diff --git a/apps/docs/content/docs/de/execution/costs.mdx b/apps/docs/content/docs/de/execution/costs.mdx index 385ebd6699..5c77035b5a 100644 --- a/apps/docs/content/docs/de/execution/costs.mdx +++ b/apps/docs/content/docs/de/execution/costs.mdx @@ -170,17 +170,49 @@ Verschiedene Abonnementpläne haben unterschiedliche Nutzungslimits: | **Team** | $500 (gepoolt) | 50 sync, 100 async | | **Enterprise** | Individuell | Individuell | +## Abrechnungsmodell + +Sim verwendet ein **Basisabonnement + Mehrverbrauch** Abrechnungsmodell: + +### Wie es funktioniert + +**Pro-Plan (20 $/Monat):** +- Monatliches Abonnement beinhaltet 20 $ Nutzung +- Nutzung unter 20 $ → Keine zusätzlichen Kosten +- Nutzung über 20 $ → Zahlung des Mehrverbrauchs am Monatsende +- Beispiel: 35 $ Nutzung = 20 $ (Abonnement) + 15 $ (Mehrverbrauch) + +**Team-Plan (40 $/Sitz/Monat):** +- Gemeinsame Nutzung für alle Teammitglieder +- Mehrverbrauch wird aus der Gesamtnutzung des Teams berechnet +- Organisationsinhaber erhält eine Rechnung + +**Enterprise-Pläne:** +- Fester monatlicher Preis, kein Mehrverbrauch +- Individuelle Nutzungslimits gemäß Vereinbarung + +### Schwellenwertabrechnung + +Wenn der nicht abgerechnete Mehrverbrauch 50 $ erreicht, berechnet Sim automatisch den gesamten nicht abgerechneten Betrag. + +**Beispiel:** +- Tag 10: 70 $ Mehrverbrauch → Sofortige Abrechnung von 70 $ +- Tag 15: Zusätzliche 35 $ Nutzung (insgesamt 105 $) → Bereits abgerechnet, keine Aktion +- Tag 20: Weitere 50 $ Nutzung (insgesamt 155 $, 85 $ nicht abgerechnet) → Sofortige Abrechnung von 85 $ + +Dies verteilt hohe Mehrverbrauchskosten über den Monat, anstatt eine große Rechnung am Periodenende zu stellen. + ## Best Practices für Kostenmanagement 1. **Regelmäßig überwachen**: Prüfen Sie Ihr Nutzungs-Dashboard häufig, um Überraschungen zu vermeiden 2. **Budgets festlegen**: Nutzen Sie Planlimits als Leitplanken für Ihre Ausgaben 3. **Workflows optimieren**: Überprüfen Sie kostenintensive Ausführungen und optimieren Sie Prompts oder Modellauswahl -4. **Passende Modelle verwenden**: Stimmen Sie die Modellkomplexität auf die Aufgabenanforderungen ab +4. **Geeignete Modelle verwenden**: Passen Sie die Modellkomplexität an die Aufgabenanforderungen an 5. **Ähnliche Aufgaben bündeln**: Kombinieren Sie wenn möglich mehrere Anfragen, um den Overhead zu reduzieren ## Nächste Schritte - Überprüfen Sie Ihre aktuelle Nutzung unter [Einstellungen → Abonnement](https://sim.ai/settings/subscription) - Erfahren Sie mehr über [Logging](/execution/logging), um Ausführungsdetails zu verfolgen -- Erkunden Sie die [Externe API](/execution/api) für programmatische Kostenüberwachung -- Sehen Sie sich [Workflow-Optimierungstechniken](/blocks) an, um Kosten zu reduzieren \ No newline at end of file +- Erkunden Sie die [externe API](/execution/api) für programmatische Kostenüberwachung +- Sehen Sie sich [Workflow-Optimierungstechniken](/blocks) zur Kostenreduzierung an \ No newline at end of file diff --git a/apps/docs/content/docs/de/sdks/python.mdx b/apps/docs/content/docs/de/sdks/python.mdx index 368010f430..c185733f85 100644 --- a/apps/docs/content/docs/de/sdks/python.mdx +++ b/apps/docs/content/docs/de/sdks/python.mdx @@ -387,7 +387,7 @@ Behandeln Sie verschiedene Fehlertypen, die während der Workflow-Ausführung au from simstudio import SimStudioClient, SimStudioError import os -client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) +client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) def execute_with_error_handling(): try: @@ -600,7 +600,7 @@ Führe Workflows mit Echtzeit-Streaming-Antworten aus: from simstudio import SimStudioClient import os -client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) +client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) def execute_with_streaming(): """Execute workflow with streaming enabled.""" diff --git a/apps/docs/content/docs/de/sdks/typescript.mdx b/apps/docs/content/docs/de/sdks/typescript.mdx index 55e36ce7e2..c2a4f86550 100644 --- a/apps/docs/content/docs/de/sdks/typescript.mdx +++ b/apps/docs/content/docs/de/sdks/typescript.mdx @@ -604,28 +604,114 @@ async function executeClientSideWorkflow() { }); console.log('Workflow result:', result); - + // Update UI with result - document.getElementById('result')!.textContent = + document.getElementById('result')!.textContent = JSON.stringify(result.output, null, 2); } catch (error) { console.error('Error:', error); } } +``` + +### Datei-Upload + +Dateiobjekte werden automatisch erkannt und in das base64-Format konvertiert. Fügen Sie sie in Ihre Eingabe unter dem Feldnamen ein, der dem API-Trigger-Eingabeformat Ihres Workflows entspricht. + +Das SDK konvertiert Dateiobjekte in dieses Format: + +```typescript +{ + type: 'file', + data: 'data:mime/type;base64,base64data', + name: 'filename', + mime: 'mime/type' +} +``` + +Alternativ können Sie Dateien manuell im URL-Format bereitstellen: + +```typescript +{ + type: 'url', + data: 'https://example.com/file.pdf', + name: 'file.pdf', + mime: 'application/pdf' +} +``` + + + + + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + + const client = new SimStudioClient({ + apiKey: process.env.NEXT_PUBLIC_SIM_API_KEY! + }); + + // From file input + async function handleFileUpload(event: Event) { + const input = event.target as HTMLInputElement; + const files = Array.from(input.files || []); + + // Include files under the field name from your API trigger's input format + const result = await client.executeWorkflow('workflow-id', { + input: { + documents: files, // Must match your workflow's "files" field name + instructions: 'Analyze these documents' + } + }); + + console.log('Result:', result); + } + ``` + + + + + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + import fs from 'fs'; + + const client = new SimStudioClient({ + apiKey: process.env.SIM_API_KEY! + }); + + // Read file and create File object + const fileBuffer = fs.readFileSync('./document.pdf'); + const file = new File([fileBuffer], 'document.pdf', { + type: 'application/pdf' + }); + + // Include files under the field name from your API trigger's input format + const result = await client.executeWorkflow('workflow-id', { + input: { + documents: [file], // Must match your workflow's "files" field name + query: 'Summarize this document' + } + }); + ``` + + + -// Attach to button click +// An Button-Klick anhängen document.getElementById('executeBtn')?.addEventListener('click', executeClientSideWorkflow); + ``` - Bei der Verwendung des SDK im Browser sollten Sie darauf achten, keine sensiblen API-Schlüssel offenzulegen. Erwägen Sie die Verwendung eines Backend-Proxys oder öffentlicher API-Schlüssel mit eingeschränkten Berechtigungen. + When using the SDK in the browser, be careful not to expose sensitive API keys. Consider using a backend proxy or public API keys with limited permissions. -### React Hook-Beispiel +### React Hook Example -Erstellen eines benutzerdefinierten React-Hooks für die Workflow-Ausführung: +Create a custom React hook for workflow execution: -```typescript +``` + +typescript import { useState, useCallback } from 'react'; import { SimStudioClient, WorkflowExecutionResult } from 'simstudio-ts-sdk'; @@ -671,7 +757,7 @@ export function useWorkflow(): UseWorkflowResult { }; } -// Usage in component +// Verwendung in Komponente function WorkflowComponent() { const { result, loading, error, executeWorkflow } = useWorkflow(); @@ -684,26 +770,29 @@ function WorkflowComponent() { return (
- {error &&
Error: {error.message}
} + {error &&
Fehler: {error.message}
} {result && (
-

Result:

+

Ergebnis:

{JSON.stringify(result, null, 2)}
)}
); } + ``` -### Asynchrone Workflow-Ausführung +### Async Workflow Execution -Führen Sie Workflows asynchron für lang laufende Aufgaben aus: +Execute workflows asynchronously for long-running tasks: -```typescript +``` + +typescript import { SimStudioClient, AsyncExecutionResult } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -712,47 +801,50 @@ const client = new SimStudioClient({ async function executeAsync() { try { - // Start async execution + // Starte asynchrone Ausführung const result = await client.executeWorkflow('workflow-id', { input: { data: 'large dataset' }, - async: true // Execute asynchronously + async: true // Asynchron ausführen }); - // Check if result is an async execution + // Prüfe, ob das Ergebnis eine asynchrone Ausführung ist if ('taskId' in result) { console.log('Task ID:', result.taskId); - console.log('Status endpoint:', result.links.status); + console.log('Status-Endpunkt:', result.links.status); - // Poll for completion + // Abfragen bis zur Fertigstellung let status = await client.getJobStatus(result.taskId); while (status.status === 'queued' || status.status === 'processing') { - console.log('Current status:', status.status); - await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds + console.log('Aktueller Status:', status.status); + await new Promise(resolve => setTimeout(resolve, 2000)); // Warte 2 Sekunden status = await client.getJobStatus(result.taskId); } if (status.status === 'completed') { - console.log('Workflow completed!'); - console.log('Output:', status.output); - console.log('Duration:', status.metadata.duration); + console.log('Workflow abgeschlossen!'); + console.log('Ausgabe:', status.output); + console.log('Dauer:', status.metadata.duration); } else { - console.error('Workflow failed:', status.error); + console.error('Workflow fehlgeschlagen:', status.error); } } } catch (error) { - console.error('Error:', error); + console.error('Fehler:', error); } } executeAsync(); + ``` -### Rate-Limiting und Wiederholungsversuche +### Rate Limiting and Retry -Automatische Behandlung von Rate-Limits mit exponentiellem Backoff: +Handle rate limits automatically with exponential backoff: -```typescript +``` + +typescript import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -761,7 +853,7 @@ const client = new SimStudioClient({ async function executeWithRetryHandling() { try { - // Automatically retries on rate limit + // Wiederholt automatisch bei Rate-Limit const result = await client.executeWithRetry('workflow-id', { input: { message: 'Process this' } }, { @@ -771,26 +863,29 @@ async function executeWithRetryHandling() { backoffMultiplier: 2 }); - console.log('Success:', result); + console.log('Erfolg:', result); } catch (error) { if (error instanceof SimStudioError && error.code === 'RATE_LIMIT_EXCEEDED') { - console.error('Rate limit exceeded after all retries'); + console.error('Rate-Limit nach allen Wiederholungsversuchen überschritten'); - // Check rate limit info + // Rate-Limit-Informationen prüfen const rateLimitInfo = client.getRateLimitInfo(); if (rateLimitInfo) { - console.log('Rate limit resets at:', new Date(rateLimitInfo.reset * 1000)); + console.log('Rate-Limit wird zurückgesetzt um:', new Date(rateLimitInfo.reset * 1000)); } } } } + ``` -### Nutzungsüberwachung +### Usage Monitoring -Überwachen Sie Ihre Kontonutzung und -limits: +Monitor your account usage and limits: -```typescript +``` + +typescript import { SimStudioClient } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -802,26 +897,45 @@ async function checkUsage() { const limits = await client.getUsageLimits(); console.log('=== Rate Limits ==='); - console.log('Sync requests:'); + console.log('Synchrone Anfragen:'); console.log(' Limit:', limits.rateLimit.sync.limit); - console.log(' Remaining:', limits.rateLimit.sync.remaining); - console.log(' Resets at:', limits.rateLimit.sync.resetAt); - console.log(' Is limited:', limits.rateLimit.sync.isLimited); + console.log(' Verbleibend:', limits.rateLimit.sync.remaining); + console.log(' Zurückgesetzt um:', limits.rateLimit.sync.resetAt); + console.log(' Ist limitiert:', limits.rateLimit.sync.isLimited); - console.log('\nAsync requests:'); + console.log('\nAsynchrone Anfragen:'); console.log(' Limit:', limits.rateLimit.async.limit); - console.log(' Remaining:', limits.rateLimit.async.remaining); - console.log(' Resets at:', limits.rateLimit.async.resetAt); - console.log(' Is limited:', limits.rateLimit.async.isLimited); + console.log(' Verbleibend:', limits.rateLimit.async.remaining); + console.log(' Zurückgesetzt um:', limits.rateLimit.async.resetAt); + console.log(' Ist limitiert:', limits.rateLimit.async.isLimited); - console.log('\n=== Usage ==='); - console.log('Current period cost: + console.log('\n=== Nutzung ==='); + console.log('Kosten der aktuellen Periode: $' + limits.usage.currentPeriodCost.toFixed(2)); + console.log('Limit: $' + limits.usage.limit.toFixed(2)); + console.log('Plan:', limits.usage.plan); + + const percentUsed = (limits.usage.currentPeriodCost / limits.usage.limit) * 100; + console.log('Nutzung: ' + percentUsed.toFixed(1) + '%'); + + if (percentUsed > 80) { + console.warn('⚠️ Warnung: Sie nähern sich Ihrem Nutzungslimit!'); + } + } catch (error) { + console.error('Fehler bei der Überprüfung der Nutzung:', error); + } +} + +checkUsage(); + +``` ### Streaming Workflow Execution Execute workflows with real-time streaming responses: -```typescript +``` + +typescript import { SimStudioClient } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -830,11 +944,11 @@ const client = new SimStudioClient({ async function executeWithStreaming() { try { - // Streaming für bestimmte Block-Ausgaben aktivieren + // Streaming für bestimmte Block-Outputs aktivieren const result = await client.executeWorkflow('workflow-id', { - input: { message: 'Count to five' }, + input: { message: 'Zähle bis fünf' }, stream: true, - selectedOutputs: ['agent1.content'] // Format blockName.attribute verwenden + selectedOutputs: ['agent1.content'] // Verwende blockName.attribute Format }); console.log('Workflow-Ergebnis:', result); @@ -842,23 +956,28 @@ async function executeWithStreaming() { console.error('Fehler:', error); } } + ``` The streaming response follows the Server-Sent Events (SSE) format: ``` -data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"} + +data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"Eins"} data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", zwei"} data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}} data: [DONE] + ``` **React Streaming Example:** -```typescript +``` + +typescript import { useState, useEffect } from 'react'; function StreamingWorkflow() { @@ -878,7 +997,7 @@ function StreamingWorkflow() { 'X-API-Key': process.env.SIM_API_KEY! // Nur serverseitige Umgebungsvariable }, body: JSON.stringify({ - message: 'Generate a story', + message: 'Generiere eine Geschichte', stream: true, selectedOutputs: ['agent1.content'] }) @@ -926,6 +1045,7 @@ function StreamingWorkflow() { ); } + ``` ## Getting Your API Key @@ -961,7 +1081,9 @@ function StreamingWorkflow() { The SDK is written in TypeScript and provides full type safety: -```typescript +``` + +typescript import { SimStudioClient, WorkflowExecutionResult, @@ -977,7 +1099,7 @@ const client: SimStudioClient = new SimStudioClient({ // Typsichere Workflow-Ausführung const result: WorkflowExecutionResult = await client.executeWorkflow('workflow-id', { input: { - message: 'Hello, TypeScript!' + message: 'Hallo, TypeScript!' } }); @@ -985,6 +1107,6 @@ const result: WorkflowExecutionResult = await client.executeWorkflow('workflow-i const status: WorkflowStatus = await client.getWorkflowStatus('workflow-id'); ``` -## License +## Lizenz Apache-2.0 \ No newline at end of file diff --git a/apps/docs/content/docs/de/triggers/api.mdx b/apps/docs/content/docs/de/triggers/api.mdx index 8dab4cfb38..c5990f52f8 100644 --- a/apps/docs/content/docs/de/triggers/api.mdx +++ b/apps/docs/content/docs/de/triggers/api.mdx @@ -22,9 +22,17 @@ Der API-Trigger stellt Ihren Workflow als sicheren HTTP-Endpunkt bereit. Senden /> -Fügen Sie für jeden Parameter ein Feld **Eingabeformat** hinzu. Die Ausgabeschlüssel zur Laufzeit spiegeln das Schema wider und sind auch unter `` verfügbar. +Füge ein **Eingabeformat**-Feld für jeden Parameter hinzu. Unterstützte Typen: -Manuelle Ausführungen im Editor verwenden die Spalte `value`, damit Sie testen können, ohne eine Anfrage zu senden. Während der Ausführung füllt der Resolver sowohl `` als auch `` aus. +- **string** - Textwerte +- **number** - Numerische Werte +- **boolean** - Wahr/Falsch-Werte +- **json** - JSON-Objekte +- **files** - Datei-Uploads (Zugriff über ``, ``, usw.) + +Laufzeit-Ausgabeschlüssel spiegeln das Schema wider und sind unter `` verfügbar. + +Manuelle Ausführungen im Editor verwenden die Spalte `value`, damit du testen kannst, ohne eine Anfrage zu senden. Während der Ausführung füllt der Resolver sowohl `` als auch ``. ## Anfrage-Beispiel @@ -40,22 +48,22 @@ Erfolgreiche Antworten geben das serialisierte Ausführungsergebnis vom Executor ## Streaming-Antworten -Aktivieren Sie Echtzeit-Streaming, um Workflow-Ausgaben zu erhalten, während sie zeichen-für-zeichen generiert werden. Dies ist nützlich, um KI-Antworten progressiv für Benutzer anzuzeigen. +Aktiviere Echtzeit-Streaming, um Workflow-Ausgaben während der Generierung zeichenweise zu erhalten. Dies ist nützlich, um KI-Antworten progressiv für Benutzer anzuzeigen. -### Anfrageparameter +### Anfrage-Parameter -Fügen Sie diese Parameter hinzu, um Streaming zu aktivieren: +Füge diese Parameter hinzu, um Streaming zu aktivieren: -- `stream` - Auf `true` setzen, um Server-Sent Events (SSE) Streaming zu aktivieren +- `stream` - Setze auf `true`, um Server-Sent Events (SSE) Streaming zu aktivieren - `selectedOutputs` - Array von Block-Ausgaben zum Streamen (z.B. `["agent1.content"]`) ### Block-Ausgabeformat -Verwenden Sie das `blockName.attribute` Format, um anzugeben, welche Block-Ausgaben gestreamt werden sollen: -- Format: `"blockName.attribute"` (z.B. Wenn Sie den Inhalt des Agent 1-Blocks streamen möchten, würden Sie `"agent1.content"` verwenden) +Verwende das Format `blockName.attribute`, um anzugeben, welche Block-Ausgaben gestreamt werden sollen: +- Format: `"blockName.attribute"` (z.B. wenn du den Inhalt des Agent 1-Blocks streamen möchtest, würdest du `"agent1.content"` verwenden) - Blocknamen sind nicht case-sensitive und Leerzeichen werden ignoriert -### Beispielanfrage +### Beispiel-Anfrage ```bash curl -X POST \ @@ -86,44 +94,89 @@ data: [DONE] ``` Jedes Ereignis enthält: -- **Streaming-Chunks**: `{"blockId": "...", "chunk": "text"}` - Echtzeit-Text während er generiert wird -- **Abschlussereignis**: `{"event": "done", ...}` - Ausführungsmetadaten und vollständige Ergebnisse +- **Streaming-Chunks**: `{"blockId": "...", "chunk": "text"}` - Echtzeit-Text während der Generierung +- **Finales Ereignis**: `{"event": "done", ...}` - Ausführungsmetadaten und vollständige Ergebnisse - **Terminator**: `[DONE]` - Signalisiert das Ende des Streams ### Streaming mehrerer Blöcke Wenn `selectedOutputs` mehrere Blöcke enthält, zeigt jeder Chunk an, welcher Block ihn erzeugt hat: -```bash -curl -X POST \ - https://sim.ai/api/workflows/WORKFLOW_ID/execute \ - -H 'Content-Type: application/json' \ - -H 'X-API-Key: YOUR_KEY' \ - -d '{ - "message": "Process this request", - "stream": true, - "selectedOutputs": ["agent1.content", "agent2.content"] - }' +```json +{ + "type": "block", + "blockType": "text", + "text": "Dies ist ein Textblock" +} ``` -Das Feld `blockId` in jedem Chunk ermöglicht es Ihnen, die Ausgabe zum richtigen UI-Element zu leiten: +Das Feld `blockId` in jedem Chunk ermöglicht es, die Ausgabe an das richtige UI-Element zu leiten: +```json +{ + "type": "block", + "blockType": "code", + "text": "console.log('Hallo Welt');" +} ``` -data: {"blockId":"agent1-uuid","chunk":"Processing..."} -data: {"blockId":"agent2-uuid","chunk":"Analyzing..."} +## Ausgabe-Referenz + +| Referenz | Beschreibung | +|-----------|-------------| +| `` | Feld, das im Eingabeformat definiert ist | +| `` | Gesamter strukturierter Anforderungstext | -data: {"blockId":"agent1-uuid","chunk":" complete"} +### Datei-Upload-Format + +Die API akzeptiert Dateien in zwei Formaten: + +**1. Base64-kodierte Dateien** (empfohlen für SDKs): + +```json +{ + "files": [{ + "data": "iVBORw0KGgoAAAANSUhEUgAA...", + "name": "image.png", + "mime": "image/png" + }] +} ``` -## Ausgabereferenz +- Maximale Dateigröße: 20MB pro Datei +- Dateien werden in den Cloud-Speicher hochgeladen und in UserFile-Objekte mit allen Eigenschaften umgewandelt -| Referenz | Beschreibung | -|-----------|-------------| -| `` | Im Eingabeformat definiertes Feld | -| `` | Gesamter strukturierter Anfragekörper | +**2. Direkte URL-Referenzen**: + +```json +{ + "files": [{ + "url": "https://example.com/image.png", + "name": "image.png", + "mime": "image/png" + }] +} +``` + +- Die Datei wird nicht hochgeladen, die URL wird direkt weitergegeben +- Nützlich für die Referenzierung bestehender Dateien + +### Datei-Eigenschaften + +Für Dateien können alle Eigenschaften abgerufen werden: + +| Eigenschaft | Beschreibung | Typ | +|----------|-------------|------| +| `` | Signierte Download-URL | string | +| `` | Ursprünglicher Dateiname | string | +| `` | Dateigröße in Bytes | number | +| `` | MIME-Typ | string | +| `` | Upload-Zeitstempel (ISO 8601) | string | +| `` | URL-Ablaufzeitstempel (ISO 8601) | string | + +Für URL-referenzierte Dateien sind dieselben Eigenschaften verfügbar, mit Ausnahme von `uploadedAt` und `expiresAt`, da die Datei nicht in unseren Speicher hochgeladen wird. -Wenn kein Eingabeformat definiert ist, stellt der Executor das rohe JSON nur unter `` zur Verfügung. +Wenn kein Eingabeformat definiert ist, stellt der Executor nur das rohe JSON unter `` zur Verfügung. Ein Workflow kann nur einen API-Trigger enthalten. Veröffentlichen Sie nach Änderungen eine neue Bereitstellung, damit der Endpunkt aktuell bleibt. diff --git a/apps/docs/content/docs/de/triggers/chat.mdx b/apps/docs/content/docs/de/triggers/chat.mdx index 129054a819..2349fc229f 100644 --- a/apps/docs/content/docs/de/triggers/chat.mdx +++ b/apps/docs/content/docs/de/triggers/chat.mdx @@ -24,20 +24,31 @@ Der Chat-Auslöser erstellt eine Konversationsschnittstelle für Ihren Workflow. Der Auslöser schreibt drei Felder, auf die nachfolgende Blöcke verweisen können: -| Referenz | Beschreibung | -|-----------|-------------| -| `` | Neueste Benutzernachricht | -| `` | Konversations-Thread-ID | -| `` | Optionale hochgeladene Dateien | +| Referenz | Beschreibung | Typ | +|-----------|-------------|------| +| `` | Letzte Benutzernachricht | string | +| `` | Konversations-Thread-ID | string | +| `` | Optionale hochgeladene Dateien | files array | -Dateien enthalten `name`, `mimeType` und einen signierten Download `url`. +### Dateieigenschaften + +Zugriff auf einzelne Dateieigenschaften über Array-Indizierung: + +| Eigenschaft | Beschreibung | Typ | +|----------|-------------|------| +| `` | Signierte Download-URL | string | +| `` | Ursprünglicher Dateiname | string | +| `` | Dateigröße in Bytes | number | +| `` | MIME-Typ | string | +| `` | Upload-Zeitstempel (ISO 8601) | string | +| `` | URL-Ablaufzeitstempel (ISO 8601) | string | ## Nutzungshinweise -1. Fügen Sie einen Chat-Auslöser-Block pro Workflow hinzu. +1. Fügen Sie einen Chat-Trigger-Block pro Workflow hinzu. 2. Stellen Sie den Workflow im Chat-Modus bereit. -3. Teilen Sie den Bereitstellungslink – jede Antwort verwendet die Konversations-ID wieder, sodass der Workflow den Kontext beibehalten kann. +3. Teilen Sie den Bereitstellungslink – jede Antwort verwendet dieselbe Konversations-ID, damit der Workflow den Kontext beibehalten kann. -Der Builder blockiert mehrere Chat-Auslöser-Blöcke im selben Workflow. +Der Builder blockiert mehrere Chat-Trigger-Blöcke im selben Workflow. diff --git a/apps/docs/content/docs/es/execution/costs.mdx b/apps/docs/content/docs/es/execution/costs.mdx index 78daf6600b..40468da241 100644 --- a/apps/docs/content/docs/es/execution/costs.mdx +++ b/apps/docs/content/docs/es/execution/costs.mdx @@ -170,17 +170,49 @@ Los diferentes planes de suscripción tienen diferentes límites de uso: | **Equipo** | $500 (agrupado) | 50 síncronos, 100 asíncronos | | **Empresa** | Personalizado | Personalizado | +## Modelo de facturación + +Sim utiliza un modelo de facturación de **suscripción base + excedente**: + +### Cómo funciona + +**Plan Pro (20$/mes):** +- La suscripción mensual incluye 20$ de uso +- Uso por debajo de 20$ → Sin cargos adicionales +- Uso por encima de 20$ → Paga el excedente al final del mes +- Ejemplo: 35$ de uso = 20$ (suscripción) + 15$ (excedente) + +**Plan Team (40$/usuario/mes):** +- Uso compartido entre todos los miembros del equipo +- El excedente se calcula a partir del uso total del equipo +- El propietario de la organización recibe una única factura + +**Planes Enterprise:** +- Precio mensual fijo, sin excedentes +- Límites de uso personalizados según el acuerdo + +### Facturación por umbrales + +Cuando el excedente no facturado alcanza los 50$, Sim factura automáticamente el importe total no facturado. + +**Ejemplo:** +- Día 10: 70$ de excedente → Factura inmediata de 70$ +- Día 15: 35$ adicionales de uso (105$ en total) → Ya facturado, sin acción +- Día 20: Otros 50$ de uso (155$ en total, 85$ sin facturar) → Factura inmediata de 85$ + +Esto distribuye los cargos grandes por excedente a lo largo del mes en lugar de una factura grande al final del período. + ## Mejores prácticas para la gestión de costos -1. **Monitorear regularmente**: Revisa tu panel de uso frecuentemente para evitar sorpresas -2. **Establecer presupuestos**: Utiliza los límites del plan como guías para tu gasto -3. **Optimizar flujos de trabajo**: Revisa las ejecuciones de alto costo y optimiza los prompts o la selección de modelos -4. **Usar modelos apropiados**: Ajusta la complejidad del modelo a los requisitos de la tarea -5. **Agrupar tareas similares**: Combina múltiples solicitudes cuando sea posible para reducir la sobrecarga +1. **Monitoreo regular**: Revisa tu panel de uso con frecuencia para evitar sorpresas +2. **Establece presupuestos**: Utiliza los límites del plan como guía para tu gasto +3. **Optimiza flujos de trabajo**: Revisa las ejecuciones de alto costo y optimiza los prompts o la selección de modelos +4. **Usa modelos apropiados**: Ajusta la complejidad del modelo a los requisitos de la tarea +5. **Agrupa tareas similares**: Combina múltiples solicitudes cuando sea posible para reducir la sobrecarga ## Próximos pasos - Revisa tu uso actual en [Configuración → Suscripción](https://sim.ai/settings/subscription) - Aprende sobre [Registro](/execution/logging) para seguir los detalles de ejecución -- Explora la [API externa](/execution/api) para monitoreo programático de costos +- Explora la [API externa](/execution/api) para el monitoreo programático de costos - Consulta las [técnicas de optimización de flujo de trabajo](/blocks) para reducir costos \ No newline at end of file diff --git a/apps/docs/content/docs/es/sdks/python.mdx b/apps/docs/content/docs/es/sdks/python.mdx index 2edb110394..75b4f3777a 100644 --- a/apps/docs/content/docs/es/sdks/python.mdx +++ b/apps/docs/content/docs/es/sdks/python.mdx @@ -609,7 +609,7 @@ Ejecuta flujos de trabajo con respuestas en tiempo real: from simstudio import SimStudioClient import os -client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) +client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) def execute_with_streaming(): """Execute workflow with streaming enabled.""" diff --git a/apps/docs/content/docs/es/sdks/typescript.mdx b/apps/docs/content/docs/es/sdks/typescript.mdx index fca8a9805f..ebfb734663 100644 --- a/apps/docs/content/docs/es/sdks/typescript.mdx +++ b/apps/docs/content/docs/es/sdks/typescript.mdx @@ -604,28 +604,114 @@ async function executeClientSideWorkflow() { }); console.log('Workflow result:', result); - + // Update UI with result - document.getElementById('result')!.textContent = + document.getElementById('result')!.textContent = JSON.stringify(result.output, null, 2); } catch (error) { console.error('Error:', error); } } +``` + +### Carga de archivos + +Los objetos de archivo se detectan automáticamente y se convierten a formato base64. Inclúyelos en tu entrada bajo el nombre de campo que coincida con el formato de entrada del disparador API de tu flujo de trabajo. + +El SDK convierte los objetos File a este formato: + +```typescript +{ + type: 'file', + data: 'data:mime/type;base64,base64data', + name: 'filename', + mime: 'mime/type' +} +``` + +Alternativamente, puedes proporcionar archivos manualmente usando el formato URL: + +```typescript +{ + type: 'url', + data: 'https://example.com/file.pdf', + name: 'file.pdf', + mime: 'application/pdf' +} +``` -// Attach to button click + + + + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + + const client = new SimStudioClient({ + apiKey: process.env.NEXT_PUBLIC_SIM_API_KEY! + }); + + // From file input + async function handleFileUpload(event: Event) { + const input = event.target as HTMLInputElement; + const files = Array.from(input.files || []); + + // Include files under the field name from your API trigger's input format + const result = await client.executeWorkflow('workflow-id', { + input: { + documents: files, // Must match your workflow's "files" field name + instructions: 'Analyze these documents' + } + }); + + console.log('Result:', result); + } + ``` + + + + + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + import fs from 'fs'; + + const client = new SimStudioClient({ + apiKey: process.env.SIM_API_KEY! + }); + + // Read file and create File object + const fileBuffer = fs.readFileSync('./document.pdf'); + const file = new File([fileBuffer], 'document.pdf', { + type: 'application/pdf' + }); + + // Include files under the field name from your API trigger's input format + const result = await client.executeWorkflow('workflow-id', { + input: { + documents: [file], // Must match your workflow's "files" field name + query: 'Summarize this document' + } + }); + ``` + + + + +// Adjuntar al clic del botón document.getElementById('executeBtn')?.addEventListener('click', executeClientSideWorkflow); + ``` - Cuando uses el SDK en el navegador, ten cuidado de no exponer claves API sensibles. Considera usar un proxy de backend o claves API públicas con permisos limitados. + When using the SDK in the browser, be careful not to expose sensitive API keys. Consider using a backend proxy or public API keys with limited permissions. -### Ejemplo de hook de React +### React Hook Example -Crea un hook personalizado de React para la ejecución de flujos de trabajo: +Create a custom React hook for workflow execution: -```typescript +``` + +typescript import { useState, useCallback } from 'react'; import { SimStudioClient, WorkflowExecutionResult } from 'simstudio-ts-sdk'; @@ -671,7 +757,7 @@ export function useWorkflow(): UseWorkflowResult { }; } -// Usage in component +// Uso en componente function WorkflowComponent() { const { result, loading, error, executeWorkflow } = useWorkflow(); @@ -684,26 +770,29 @@ function WorkflowComponent() { return (
{error &&
Error: {error.message}
} {result && (
-

Result:

+

Resultado:

{JSON.stringify(result, null, 2)}
)}
); } + ``` -### Ejecución asíncrona de flujos de trabajo +### Async Workflow Execution -Ejecuta flujos de trabajo de forma asíncrona para tareas de larga duración: +Execute workflows asynchronously for long-running tasks: -```typescript +``` + +typescript import { SimStudioClient, AsyncExecutionResult } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -712,32 +801,32 @@ const client = new SimStudioClient({ async function executeAsync() { try { - // Start async execution + // Iniciar ejecución asíncrona const result = await client.executeWorkflow('workflow-id', { input: { data: 'large dataset' }, - async: true // Execute asynchronously + async: true // Ejecutar de forma asíncrona }); - // Check if result is an async execution + // Comprobar si el resultado es una ejecución asíncrona if ('taskId' in result) { - console.log('Task ID:', result.taskId); - console.log('Status endpoint:', result.links.status); + console.log('ID de tarea:', result.taskId); + console.log('Endpoint de estado:', result.links.status); - // Poll for completion + // Sondear hasta completar let status = await client.getJobStatus(result.taskId); while (status.status === 'queued' || status.status === 'processing') { - console.log('Current status:', status.status); - await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds + console.log('Estado actual:', status.status); + await new Promise(resolve => setTimeout(resolve, 2000)); // Esperar 2 segundos status = await client.getJobStatus(result.taskId); } if (status.status === 'completed') { - console.log('Workflow completed!'); - console.log('Output:', status.output); - console.log('Duration:', status.metadata.duration); + console.log('¡Flujo de trabajo completado!'); + console.log('Salida:', status.output); + console.log('Duración:', status.metadata.duration); } else { - console.error('Workflow failed:', status.error); + console.error('Flujo de trabajo fallido:', status.error); } } } catch (error) { @@ -746,13 +835,16 @@ async function executeAsync() { } executeAsync(); + ``` -### Límite de tasa y reintentos +### Rate Limiting and Retry -Maneja límites de tasa automáticamente con retroceso exponencial: +Handle rate limits automatically with exponential backoff: -```typescript +``` + +typescript import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -761,7 +853,7 @@ const client = new SimStudioClient({ async function executeWithRetryHandling() { try { - // Automatically retries on rate limit + // Reintenta automáticamente en caso de límite de tasa const result = await client.executeWithRetry('workflow-id', { input: { message: 'Process this' } }, { @@ -771,26 +863,29 @@ async function executeWithRetryHandling() { backoffMultiplier: 2 }); - console.log('Success:', result); + console.log('Éxito:', result); } catch (error) { if (error instanceof SimStudioError && error.code === 'RATE_LIMIT_EXCEEDED') { - console.error('Rate limit exceeded after all retries'); + console.error('Límite de tasa excedido después de todos los reintentos'); - // Check rate limit info + // Comprobar información del límite de tasa const rateLimitInfo = client.getRateLimitInfo(); if (rateLimitInfo) { - console.log('Rate limit resets at:', new Date(rateLimitInfo.reset * 1000)); + console.log('El límite de tasa se restablece en:', new Date(rateLimitInfo.reset * 1000)); } } } } + ``` -### Monitoreo de uso +### Usage Monitoring -Monitorea el uso de tu cuenta y sus límites: +Monitor your account usage and limits: -```typescript +``` + +typescript import { SimStudioClient } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -801,27 +896,46 @@ async function checkUsage() { try { const limits = await client.getUsageLimits(); - console.log('=== Rate Limits ==='); - console.log('Sync requests:'); - console.log(' Limit:', limits.rateLimit.sync.limit); - console.log(' Remaining:', limits.rateLimit.sync.remaining); - console.log(' Resets at:', limits.rateLimit.sync.resetAt); - console.log(' Is limited:', limits.rateLimit.sync.isLimited); + console.log('=== Límites de tasa ==='); + console.log('Solicitudes síncronas:'); + console.log(' Límite:', limits.rateLimit.sync.limit); + console.log(' Restantes:', limits.rateLimit.sync.remaining); + console.log(' Se restablece en:', limits.rateLimit.sync.resetAt); + console.log(' Está limitado:', limits.rateLimit.sync.isLimited); + + console.log('\nSolicitudes asíncronas:'); + console.log(' Límite:', limits.rateLimit.async.limit); + console.log(' Restantes:', limits.rateLimit.async.remaining); + console.log(' Se restablece en:', limits.rateLimit.async.resetAt); + console.log(' Está limitado:', limits.rateLimit.async.isLimited); + + console.log('\n=== Uso ==='); + console.log('Costo del período actual: $' + limits.usage.currentPeriodCost.toFixed(2)); + console.log('Límite: $' + limits.usage.limit.toFixed(2)); + console.log('Plan:', limits.usage.plan); + + const percentUsed = (limits.usage.currentPeriodCost / limits.usage.limit) * 100; + console.log('Uso: ' + percentUsed.toFixed(1) + '%'); + + if (percentUsed > 80) { + console.warn('⚠️ Advertencia: ¡Estás acercándote a tu límite de uso!'); + } + } catch (error) { + console.error('Error al verificar el uso:', error); + } +} - console.log('\nAsync requests:'); - console.log(' Limit:', limits.rateLimit.async.limit); - console.log(' Remaining:', limits.rateLimit.async.remaining); - console.log(' Resets at:', limits.rateLimit.async.resetAt); - console.log(' Is limited:', limits.rateLimit.async.isLimited); +checkUsage(); - console.log('\n=== Usage ==='); - console.log('Current period cost: +``` ### Streaming Workflow Execution Execute workflows with real-time streaming responses: -```typescript +``` + +typescript import { SimStudioClient } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -830,11 +944,11 @@ const client = new SimStudioClient({ async function executeWithStreaming() { try { - // Habilita streaming para salidas de bloques específicos + // Habilitar streaming para salidas de bloques específicos const result = await client.executeWorkflow('workflow-id', { - input: { message: 'Count to five' }, + input: { message: 'Cuenta hasta cinco' }, stream: true, - selectedOutputs: ['agent1.content'] // Usa el formato blockName.attribute + selectedOutputs: ['agent1.content'] // Usar formato blockName.attribute }); console.log('Resultado del flujo de trabajo:', result); @@ -842,23 +956,28 @@ async function executeWithStreaming() { console.error('Error:', error); } } + ``` The streaming response follows the Server-Sent Events (SSE) format: ``` -data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"} + +data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"Uno"} data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", dos"} data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}} data: [DONE] + ``` **React Streaming Example:** -```typescript +``` + +typescript import { useState, useEffect } from 'react'; function StreamingWorkflow() { @@ -869,16 +988,16 @@ function StreamingWorkflow() { setLoading(true); setOutput(''); - // IMPORTANT: Make this API call from your backend server, not the browser - // Never expose your API key in client-side code + // IMPORTANTE: Haz esta llamada API desde tu servidor backend, no desde el navegador + // Nunca expongas tu clave API en código del lado del cliente const response = await fetch('https://sim.ai/api/workflows/WORKFLOW_ID/execute', { method: 'POST', headers: { 'Content-Type': 'application/json', - 'X-API-Key': process.env.SIM_API_KEY! // Server-side environment variable only + 'X-API-Key': process.env.SIM_API_KEY! // Variable de entorno solo del lado del servidor }, body: JSON.stringify({ - message: 'Generate a story', + message: 'Genera una historia', stream: true, selectedOutputs: ['agent1.content'] }) @@ -907,10 +1026,10 @@ function StreamingWorkflow() { if (parsed.chunk) { setOutput(prev => prev + parsed.chunk); } else if (parsed.event === 'done') { - console.log('Execution complete:', parsed.metadata); + console.log('Ejecución completa:', parsed.metadata); } } catch (e) { - // Skip invalid JSON + // Omitir JSON inválido } } } @@ -926,6 +1045,7 @@ function StreamingWorkflow() { ); } + ``` ## Getting Your API Key @@ -961,7 +1081,9 @@ function StreamingWorkflow() { The SDK is written in TypeScript and provides full type safety: -```typescript +``` + +typescript import { SimStudioClient, WorkflowExecutionResult, @@ -969,23 +1091,22 @@ import { SimStudioError } from 'simstudio-ts-sdk'; -// Type-safe client initialization +// Inicialización del cliente con seguridad de tipos const client: SimStudioClient = new SimStudioClient({ apiKey: process.env.SIM_API_KEY! }); -// Type-safe workflow execution +// Ejecución de flujo de trabajo con seguridad de tipos const result: WorkflowExecutionResult = await client.executeWorkflow('workflow-id', { input: { message: '¡Hola, TypeScript!' } }); -// Type-safe status checking +// Verificación de estado con seguridad de tipos const status: WorkflowStatus = await client.getWorkflowStatus('workflow-id'); ``` -## License - +## Licencia Apache-2.0 diff --git a/apps/docs/content/docs/es/triggers/api.mdx b/apps/docs/content/docs/es/triggers/api.mdx index 09ecda8971..97163e3c1b 100644 --- a/apps/docs/content/docs/es/triggers/api.mdx +++ b/apps/docs/content/docs/es/triggers/api.mdx @@ -22,9 +22,17 @@ El disparador de API expone tu flujo de trabajo como un punto de conexión HTTP /> -Añade un campo de **Formato de entrada** para cada parámetro. Las claves de salida en tiempo de ejecución reflejan el esquema y también están disponibles bajo ``. +Añade un campo de **Formato de entrada** para cada parámetro. Tipos admitidos: -Las ejecuciones manuales en el editor utilizan la columna `value` para que puedas realizar pruebas sin enviar una solicitud. Durante la ejecución, el resolutor completa tanto `` como ``. +- **string** - Valores de texto +- **number** - Valores numéricos +- **boolean** - Valores verdadero/falso +- **json** - Objetos JSON +- **files** - Carga de archivos (acceso mediante ``, ``, etc.) + +Las claves de salida en tiempo de ejecución reflejan el esquema y están disponibles bajo ``. + +Las ejecuciones manuales en el editor utilizan la columna `value` para que puedas realizar pruebas sin enviar una solicitud. Durante la ejecución, el resolutor completa tanto `` como ``. ## Ejemplo de solicitud @@ -40,7 +48,7 @@ Las respuestas exitosas devuelven el resultado de ejecución serializado del Eje ## Respuestas en streaming -Habilita el streaming en tiempo real para recibir la salida del flujo de trabajo a medida que se genera, carácter por carácter. Esto es útil para mostrar las respuestas de IA progresivamente a los usuarios. +Habilita el streaming en tiempo real para recibir la salida del flujo de trabajo a medida que se genera, carácter por carácter. Esto es útil para mostrar respuestas de IA progresivamente a los usuarios. ### Parámetros de solicitud @@ -51,7 +59,7 @@ Añade estos parámetros para habilitar el streaming: ### Formato de salida de bloque -Usa el formato `blockName.attribute` para especificar qué salidas de bloques transmitir: +Utiliza el formato `blockName.attribute` para especificar qué salidas de bloque transmitir: - Formato: `"blockName.attribute"` (p. ej., si quieres transmitir el contenido del bloque Agente 1, usarías `"agent1.content"`) - Los nombres de los bloques no distinguen entre mayúsculas y minúsculas y se ignoran los espacios @@ -86,34 +94,30 @@ data: [DONE] ``` Cada evento incluye: -- **Fragmentos de streaming**: `{"blockId": "...", "chunk": "text"}` - Texto en tiempo real a medida que se genera +- **Fragmentos en streaming**: `{"blockId": "...", "chunk": "text"}` - Texto en tiempo real a medida que se genera - **Evento final**: `{"event": "done", ...}` - Metadatos de ejecución y resultados completos -- **Terminador**: `[DONE]` - Señala el fin del stream +- **Terminador**: `[DONE]` - Indica el final del stream ### Streaming de múltiples bloques Cuando `selectedOutputs` incluye múltiples bloques, cada fragmento indica qué bloque lo produjo: -```bash -curl -X POST \ - https://sim.ai/api/workflows/WORKFLOW_ID/execute \ - -H 'Content-Type: application/json' \ - -H 'X-API-Key: YOUR_KEY' \ - -d '{ - "message": "Process this request", - "stream": true, - "selectedOutputs": ["agent1.content", "agent2.content"] - }' -``` - -El campo `blockId` en cada fragmento te permite dirigir la salida al elemento de UI correcto: - +```json +{ + "type": "block", + "blockType": "text", + "text": "Este es un bloque de texto" +} ``` -data: {"blockId":"agent1-uuid","chunk":"Processing..."} -data: {"blockId":"agent2-uuid","chunk":"Analyzing..."} +El campo `blockId` en cada fragmento te permite dirigir la salida al elemento de interfaz correcto: -data: {"blockId":"agent1-uuid","chunk":" complete"} +```json +{ + "type": "block", + "blockType": "image", + "imageUrl": "https://example.com/image.jpg" +} ``` ## Referencia de salida @@ -121,10 +125,56 @@ data: {"blockId":"agent1-uuid","chunk":" complete"} | Referencia | Descripción | |-----------|-------------| | `` | Campo definido en el formato de entrada | -| `` | Cuerpo de solicitud estructurado completo | +| `` | Cuerpo completo de la solicitud estructurada | + +### Formato de carga de archivos + +La API acepta archivos en dos formatos: + +**1. Archivos codificados en Base64** (recomendado para SDKs): + +```json +{ + "files": [{ + "name": "example.pdf", + "data": "JVBERi0xLjMKJcTl8uXrp/Og0MTGCjQgMCBvY..." + }] +} +``` + +- Tamaño máximo de archivo: 20MB por archivo +- Los archivos se suben al almacenamiento en la nube y se convierten en objetos UserFile con todas las propiedades + +**2. Referencias directas de URL**: + +```json +{ + "files": [{ + "url": "https://example.com/document.pdf" + }] +} +``` + +- El archivo no se sube, la URL se pasa directamente +- Útil para referenciar archivos existentes + +### Propiedades de archivos + +Para archivos, accede a todas las propiedades: + +| Propiedad | Descripción | Tipo | +|----------|-------------|------| +| `` | URL de descarga firmada | string | +| `` | Nombre original del archivo | string | +| `` | Tamaño del archivo en bytes | number | +| `` | Tipo MIME | string | +| `` | Marca de tiempo de subida (ISO 8601) | string | +| `` | Marca de tiempo de caducidad de URL (ISO 8601) | string | + +Para archivos referenciados por URL, las mismas propiedades están disponibles excepto `uploadedAt` y `expiresAt` ya que el archivo no se sube a nuestro almacenamiento. Si no se define un formato de entrada, el ejecutor expone el JSON sin procesar solo en ``. -Un flujo de trabajo puede contener solo un disparador de API. Publica una nueva implementación después de los cambios para que el endpoint se mantenga actualizado. +Un flujo de trabajo solo puede contener un disparador de API. Publica una nueva implementación después de los cambios para que el punto de conexión se mantenga actualizado. diff --git a/apps/docs/content/docs/es/triggers/chat.mdx b/apps/docs/content/docs/es/triggers/chat.mdx index bfe4da9a7f..000926af9d 100644 --- a/apps/docs/content/docs/es/triggers/chat.mdx +++ b/apps/docs/content/docs/es/triggers/chat.mdx @@ -24,20 +24,31 @@ El disparador de Chat crea una interfaz conversacional para tu flujo de trabajo. El disparador escribe tres campos que los bloques posteriores pueden referenciar: -| Referencia | Descripción | -|-----------|-------------| -| `` | Último mensaje del usuario | -| `` | ID del hilo de conversación | -| `` | Archivos subidos opcionales | +| Referencia | Descripción | Tipo | +|-----------|-------------|------| +| `` | Último mensaje del usuario | string | +| `` | ID del hilo de conversación | string | +| `` | Archivos subidos opcionales | array de archivos | -Los archivos incluyen `name`, `mimeType`, y una descarga firmada `url`. +### Propiedades de archivo + +Accede a las propiedades individuales de los archivos usando indexación de arrays: + +| Propiedad | Descripción | Tipo | +|----------|-------------|------| +| `` | URL de descarga firmada | string | +| `` | Nombre original del archivo | string | +| `` | Tamaño del archivo en bytes | number | +| `` | Tipo MIME | string | +| `` | Marca de tiempo de subida (ISO 8601) | string | +| `` | Marca de tiempo de caducidad de la URL (ISO 8601) | string | ## Notas de uso -1. Añade un bloque de Disparador de Chat por flujo de trabajo. +1. Añade un bloque de Chat Trigger por flujo de trabajo. 2. Despliega el flujo de trabajo en modo chat. 3. Comparte el enlace de despliegue—cada respuesta reutiliza el ID de conversación para que el flujo de trabajo pueda mantener el contexto. -El constructor bloquea múltiples bloques de Disparador de Chat en el mismo flujo de trabajo. +El constructor bloquea múltiples bloques de Chat Trigger en el mismo flujo de trabajo. diff --git a/apps/docs/content/docs/fr/execution/costs.mdx b/apps/docs/content/docs/fr/execution/costs.mdx index 7ab7b0099f..ddace38cee 100644 --- a/apps/docs/content/docs/fr/execution/costs.mdx +++ b/apps/docs/content/docs/fr/execution/costs.mdx @@ -170,17 +170,49 @@ Les différents forfaits d'abonnement ont des limites d'utilisation différentes | **Équipe** | 500 $ (mutualisé) | 50 sync, 100 async | | **Entreprise** | Personnalisé | Personnalisé | +## Modèle de facturation + +Sim utilise un modèle de facturation **abonnement de base + dépassement** : + +### Comment ça fonctionne + +**Forfait Pro (20 $/mois) :** +- L'abonnement mensuel inclut 20 $ d'utilisation +- Utilisation inférieure à 20 $ → Pas de frais supplémentaires +- Utilisation supérieure à 20 $ → Paiement du dépassement en fin de mois +- Exemple : 35 $ d'utilisation = 20 $ (abonnement) + 15 $ (dépassement) + +**Forfait Équipe (40 $/utilisateur/mois) :** +- Utilisation mutualisée entre tous les membres de l'équipe +- Dépassement calculé sur l'utilisation totale de l'équipe +- Le propriétaire de l'organisation reçoit une seule facture + +**Forfaits Entreprise :** +- Prix mensuel fixe, sans dépassements +- Limites d'utilisation personnalisées selon l'accord + +### Facturation par seuil + +Lorsque le dépassement non facturé atteint 50 $, Sim facture automatiquement le montant total non facturé. + +**Exemple :** +- Jour 10 : 70 $ de dépassement → Facturation immédiate de 70 $ +- Jour 15 : 35 $ d'utilisation supplémentaire (105 $ au total) → Déjà facturé, aucune action +- Jour 20 : 50 $ d'utilisation supplémentaire (155 $ au total, 85 $ non facturés) → Facturation immédiate de 85 $ + +Cela répartit les frais de dépassement importants tout au long du mois au lieu d'une seule grosse facture en fin de période. + ## Meilleures pratiques de gestion des coûts -1. **Surveillez régulièrement** : vérifiez fréquemment votre tableau de bord d'utilisation pour éviter les surprises -2. **Définissez des budgets** : utilisez les limites du plan comme garde-fous pour vos dépenses -3. **Optimisez les flux de travail** : examinez les exécutions à coût élevé et optimisez les prompts ou la sélection de modèles -4. **Utilisez des modèles appropriés** : adaptez la complexité du modèle aux exigences de la tâche -5. **Regroupez les tâches similaires** : combinez plusieurs requêtes lorsque c'est possible pour réduire les frais généraux +1. **Surveillance régulière** : Vérifiez fréquemment votre tableau de bord d'utilisation pour éviter les surprises +2. **Définir des budgets** : Utilisez les limites du forfait comme garde-fous pour vos dépenses +3. **Optimiser les flux de travail** : Examinez les exécutions à coût élevé et optimisez les prompts ou la sélection de modèles +4. **Utiliser les modèles appropriés** : Adaptez la complexité du modèle aux exigences de la tâche +5. **Regrouper les tâches similaires** : Combinez plusieurs requêtes lorsque c'est possible pour réduire les frais généraux ## Prochaines étapes -- Examinez votre utilisation actuelle dans [Paramètres → Abonnement](https://sim.ai/settings/subscription) -- Apprenez-en plus sur la [Journalisation](/execution/logging) pour suivre les détails d'exécution +- Consultez votre utilisation actuelle dans [Paramètres → Abonnement](https://sim.ai/settings/subscription) +- Découvrez la [Journalisation](/execution/logging) pour suivre les détails d'exécution - Explorez l'[API externe](/execution/api) pour la surveillance programmatique des coûts -- Découvrez les [techniques d'optimisation de flux de travail](/blocks) pour réduire les coûts \ No newline at end of file +- Consultez les [techniques d'optimisation des flux de travail](/blocks) pour réduire les coûts \ No newline at end of file diff --git a/apps/docs/content/docs/fr/sdks/python.mdx b/apps/docs/content/docs/fr/sdks/python.mdx index faf5f4b203..d3a8f11dcc 100644 --- a/apps/docs/content/docs/fr/sdks/python.mdx +++ b/apps/docs/content/docs/fr/sdks/python.mdx @@ -387,7 +387,7 @@ Gérez différents types d'erreurs qui peuvent survenir pendant l'exécution du from simstudio import SimStudioClient, SimStudioError import os -client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) +client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) def execute_with_error_handling(): try: @@ -433,7 +433,7 @@ Exécutez plusieurs workflows efficacement : from simstudio import SimStudioClient import os -client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) +client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) def execute_workflows_batch(workflow_data_pairs): """Execute multiple workflows with different input data.""" @@ -609,7 +609,7 @@ Exécutez des workflows avec des réponses en streaming en temps réel : from simstudio import SimStudioClient import os -client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) +client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) def execute_with_streaming(): """Execute workflow with streaming enabled.""" diff --git a/apps/docs/content/docs/fr/sdks/typescript.mdx b/apps/docs/content/docs/fr/sdks/typescript.mdx index ca572c346e..8c75e13f7e 100644 --- a/apps/docs/content/docs/fr/sdks/typescript.mdx +++ b/apps/docs/content/docs/fr/sdks/typescript.mdx @@ -604,28 +604,114 @@ async function executeClientSideWorkflow() { }); console.log('Workflow result:', result); - + // Update UI with result - document.getElementById('result')!.textContent = + document.getElementById('result')!.textContent = JSON.stringify(result.output, null, 2); } catch (error) { console.error('Error:', error); } } +``` + +### Téléchargement de fichier + +Les objets File sont automatiquement détectés et convertis au format base64. Incluez-les dans votre entrée sous le nom de champ correspondant au format d'entrée du déclencheur API de votre workflow. + +Le SDK convertit les objets File dans ce format : + +```typescript +{ + type: 'file', + data: 'data:mime/type;base64,base64data', + name: 'filename', + mime: 'mime/type' +} +``` + +Alternativement, vous pouvez fournir manuellement des fichiers en utilisant le format URL : + +```typescript +{ + type: 'url', + data: 'https://example.com/file.pdf', + name: 'file.pdf', + mime: 'application/pdf' +} +``` + + + + + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + + const client = new SimStudioClient({ + apiKey: process.env.NEXT_PUBLIC_SIM_API_KEY! + }); + + // From file input + async function handleFileUpload(event: Event) { + const input = event.target as HTMLInputElement; + const files = Array.from(input.files || []); + + // Include files under the field name from your API trigger's input format + const result = await client.executeWorkflow('workflow-id', { + input: { + documents: files, // Must match your workflow's "files" field name + instructions: 'Analyze these documents' + } + }); + + console.log('Result:', result); + } + ``` + + + -// Attach to button click + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + import fs from 'fs'; + + const client = new SimStudioClient({ + apiKey: process.env.SIM_API_KEY! + }); + + // Read file and create File object + const fileBuffer = fs.readFileSync('./document.pdf'); + const file = new File([fileBuffer], 'document.pdf', { + type: 'application/pdf' + }); + + // Include files under the field name from your API trigger's input format + const result = await client.executeWorkflow('workflow-id', { + input: { + documents: [file], // Must match your workflow's "files" field name + query: 'Summarize this document' + } + }); + ``` + + + + +// Attacher au clic du bouton document.getElementById('executeBtn')?.addEventListener('click', executeClientSideWorkflow); + ``` - Lors de l'utilisation du SDK dans le navigateur, veillez à ne pas exposer de clés API sensibles. Envisagez d'utiliser un proxy backend ou des clés API publiques avec des permissions limitées. + When using the SDK in the browser, be careful not to expose sensitive API keys. Consider using a backend proxy or public API keys with limited permissions. -### Exemple de hook React +### React Hook Example -Créer un hook React personnalisé pour l'exécution de workflow : +Create a custom React hook for workflow execution: -```typescript +``` + +typescript import { useState, useCallback } from 'react'; import { SimStudioClient, WorkflowExecutionResult } from 'simstudio-ts-sdk'; @@ -671,7 +757,7 @@ export function useWorkflow(): UseWorkflowResult { }; } -// Usage in component +// Utilisation dans un composant function WorkflowComponent() { const { result, loading, error, executeWorkflow } = useWorkflow(); @@ -684,26 +770,29 @@ function WorkflowComponent() { return (
- {error &&
Error: {error.message}
} + {error &&
Erreur : {error.message}
} {result && (
-

Result:

+

Résultat :

{JSON.stringify(result, null, 2)}
)}
); } + ``` -### Exécution asynchrone de workflow +### Async Workflow Execution -Exécuter des workflows de manière asynchrone pour les tâches de longue durée : +Execute workflows asynchronously for long-running tasks: -```typescript +``` + +typescript import { SimStudioClient, AsyncExecutionResult } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -712,47 +801,50 @@ const client = new SimStudioClient({ async function executeAsync() { try { - // Start async execution + // Démarrer l'exécution asynchrone const result = await client.executeWorkflow('workflow-id', { input: { data: 'large dataset' }, - async: true // Execute asynchronously + async: true // Exécuter de manière asynchrone }); - // Check if result is an async execution + // Vérifier si le résultat est une exécution asynchrone if ('taskId' in result) { - console.log('Task ID:', result.taskId); - console.log('Status endpoint:', result.links.status); + console.log('ID de tâche :', result.taskId); + console.log('Point de terminaison de statut :', result.links.status); - // Poll for completion + // Interroger pour vérifier l'achèvement let status = await client.getJobStatus(result.taskId); while (status.status === 'queued' || status.status === 'processing') { - console.log('Current status:', status.status); - await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds + console.log('Statut actuel :', status.status); + await new Promise(resolve => setTimeout(resolve, 2000)); // Attendre 2 secondes status = await client.getJobStatus(result.taskId); } if (status.status === 'completed') { - console.log('Workflow completed!'); - console.log('Output:', status.output); - console.log('Duration:', status.metadata.duration); + console.log('Workflow terminé !'); + console.log('Sortie :', status.output); + console.log('Durée :', status.metadata.duration); } else { - console.error('Workflow failed:', status.error); + console.error('Échec du workflow :', status.error); } } } catch (error) { - console.error('Error:', error); + console.error('Erreur :', error); } } executeAsync(); + ``` -### Limitation de débit et nouvelle tentative +### Rate Limiting and Retry -Gérer automatiquement les limites de débit avec backoff exponentiel : +Handle rate limits automatically with exponential backoff: -```typescript +``` + +typescript import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -761,7 +853,7 @@ const client = new SimStudioClient({ async function executeWithRetryHandling() { try { - // Automatically retries on rate limit + // Réessaie automatiquement en cas de limite de débit const result = await client.executeWithRetry('workflow-id', { input: { message: 'Process this' } }, { @@ -771,26 +863,29 @@ async function executeWithRetryHandling() { backoffMultiplier: 2 }); - console.log('Success:', result); + console.log('Succès :', result); } catch (error) { if (error instanceof SimStudioError && error.code === 'RATE_LIMIT_EXCEEDED') { - console.error('Rate limit exceeded after all retries'); + console.error('Limite de débit dépassée après toutes les tentatives'); - // Check rate limit info + // Vérifier les informations de limite de débit const rateLimitInfo = client.getRateLimitInfo(); if (rateLimitInfo) { - console.log('Rate limit resets at:', new Date(rateLimitInfo.reset * 1000)); + console.log('La limite de débit se réinitialise à :', new Date(rateLimitInfo.reset * 1000)); } } } } + ``` -### Surveillance d'utilisation +### Usage Monitoring -Surveiller l'utilisation et les limites de votre compte : +Monitor your account usage and limits: -```typescript +``` + +typescript import { SimStudioClient } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -801,27 +896,46 @@ async function checkUsage() { try { const limits = await client.getUsageLimits(); - console.log('=== Rate Limits ==='); - console.log('Sync requests:'); - console.log(' Limit:', limits.rateLimit.sync.limit); - console.log(' Remaining:', limits.rateLimit.sync.remaining); - console.log(' Resets at:', limits.rateLimit.sync.resetAt); - console.log(' Is limited:', limits.rateLimit.sync.isLimited); + console.log('=== Limites de débit ==='); + console.log('Requêtes synchrones :'); + console.log(' Limite :', limits.rateLimit.sync.limit); + console.log(' Restant :', limits.rateLimit.sync.remaining); + console.log(' Réinitialisation à :', limits.rateLimit.sync.resetAt); + console.log(' Est limité :', limits.rateLimit.sync.isLimited); + + console.log('\nRequêtes asynchrones :'); + console.log(' Limite :', limits.rateLimit.async.limit); + console.log(' Restant :', limits.rateLimit.async.remaining); + console.log(' Réinitialisation à :', limits.rateLimit.async.resetAt); + console.log(' Est limité :', limits.rateLimit.async.isLimited); + + console.log('\n=== Utilisation ==='); + console.log('Coût de la période actuelle : ' + limits.usage.currentPeriodCost.toFixed(2) + ' €'); + console.log('Limite : ' + limits.usage.limit.toFixed(2) + ' €'); + console.log('Forfait :', limits.usage.plan); + + const percentUsed = (limits.usage.currentPeriodCost / limits.usage.limit) * 100; + console.log('Utilisation : ' + percentUsed.toFixed(1) + ' %'); + + if (percentUsed > 80) { + console.warn('⚠️ Attention : vous approchez de votre limite d'utilisation !'); + } + } catch (error) { + console.error('Erreur lors de la vérification de l'utilisation :', error); + } +} - console.log('\nAsync requests:'); - console.log(' Limit:', limits.rateLimit.async.limit); - console.log(' Remaining:', limits.rateLimit.async.remaining); - console.log(' Resets at:', limits.rateLimit.async.resetAt); - console.log(' Is limited:', limits.rateLimit.async.isLimited); +checkUsage(); - console.log('\n=== Usage ==='); - console.log('Current period cost: +``` ### Streaming Workflow Execution Execute workflows with real-time streaming responses: -```typescript +``` + +typescript import { SimStudioClient } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -842,23 +956,28 @@ async function executeWithStreaming() { console.error('Erreur :', error); } } + ``` The streaming response follows the Server-Sent Events (SSE) format: ``` -data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"} + +data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"Un"} data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", deux"} data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}} data: [DONE] + ``` **React Streaming Example:** -```typescript +``` + +typescript import { useState, useEffect } from 'react'; function StreamingWorkflow() { @@ -869,16 +988,16 @@ function StreamingWorkflow() { setLoading(true); setOutput(''); - // IMPORTANT: Make this API call from your backend server, not the browser - // Never expose your API key in client-side code + // IMPORTANT : Effectuez cet appel API depuis votre serveur backend, pas depuis le navigateur + // N'exposez jamais votre clé API dans le code côté client const response = await fetch('https://sim.ai/api/workflows/WORKFLOW_ID/execute', { method: 'POST', headers: { 'Content-Type': 'application/json', - 'X-API-Key': process.env.SIM_API_KEY! // Server-side environment variable only + 'X-API-Key': process.env.SIM_API_KEY! // Variable d'environnement côté serveur uniquement }, body: JSON.stringify({ - message: 'Generate a story', + message: 'Générer une histoire', stream: true, selectedOutputs: ['agent1.content'] }) @@ -907,10 +1026,10 @@ function StreamingWorkflow() { if (parsed.chunk) { setOutput(prev => prev + parsed.chunk); } else if (parsed.event === 'done') { - console.log('Execution complete:', parsed.metadata); + console.log('Exécution terminée :', parsed.metadata); } } catch (e) { - // Skip invalid JSON + // Ignorer le JSON invalide } } } @@ -926,6 +1045,7 @@ function StreamingWorkflow() { ); } + ``` ## Getting Your API Key @@ -961,7 +1081,9 @@ function StreamingWorkflow() { The SDK is written in TypeScript and provides full type safety: -```typescript +``` + +typescript import { SimStudioClient, WorkflowExecutionResult, @@ -969,23 +1091,22 @@ import { SimStudioError } from 'simstudio-ts-sdk'; -// Type-safe client initialization +// Initialisation du client avec typage const client: SimStudioClient = new SimStudioClient({ apiKey: process.env.SIM_API_KEY! }); -// Type-safe workflow execution +// Exécution de workflow avec typage const result: WorkflowExecutionResult = await client.executeWorkflow('workflow-id', { input: { message: 'Bonjour, TypeScript !' } }); -// Type-safe status checking +// Vérification de statut avec typage const status: WorkflowStatus = await client.getWorkflowStatus('workflow-id'); ``` -## License - +## Licence Apache-2.0 diff --git a/apps/docs/content/docs/fr/triggers/api.mdx b/apps/docs/content/docs/fr/triggers/api.mdx index 978ec55610..fa95fb0fb6 100644 --- a/apps/docs/content/docs/fr/triggers/api.mdx +++ b/apps/docs/content/docs/fr/triggers/api.mdx @@ -22,9 +22,17 @@ Le déclencheur d'API expose votre flux de travail en tant que point de terminai /> -Ajoutez un champ **Format d'entrée** pour chaque paramètre. Les clés de sortie d'exécution reflètent le schéma et sont également disponibles sous ``. +Ajoutez un champ **Format d'entrée** pour chaque paramètre. Types pris en charge : -Les exécutions manuelles dans l'éditeur utilisent la colonne `value` pour que vous puissiez tester sans envoyer de requête. Pendant l'exécution, le résolveur remplit à la fois `` et ``. +- **string** - Valeurs textuelles +- **number** - Valeurs numériques +- **boolean** - Valeurs vrai/faux +- **json** - Objets JSON +- **files** - Téléchargements de fichiers (accès via ``, ``, etc.) + +Les clés de sortie d'exécution reflètent le schéma et sont disponibles sous ``. + +Les exécutions manuelles dans l'éditeur utilisent la colonne `value` pour que vous puissiez tester sans envoyer de requête. Pendant l'exécution, le résolveur remplit à la fois `` et ``. ## Exemple de requête @@ -36,23 +44,23 @@ curl -X POST \ -d '{"userId":"demo-user","maxTokens":1024}' ``` -Les réponses réussies renvoient le résultat d'exécution sérialisé de l'exécuteur. Les erreurs révèlent des problèmes de validation, d'authentification ou d'échec du workflow. +Les réponses réussies renvoient le résultat d'exécution sérialisé de l'Exécuteur. Les erreurs révèlent des problèmes de validation, d'authentification ou d'échec de workflow. ## Réponses en streaming -Activez le streaming en temps réel pour recevoir les résultats du workflow au fur et à mesure qu'ils sont générés, caractère par caractère. Cela est utile pour afficher progressivement les réponses de l'IA aux utilisateurs. +Activez le streaming en temps réel pour recevoir la sortie du workflow au fur et à mesure qu'elle est générée, caractère par caractère. Cela est utile pour afficher progressivement les réponses d'IA aux utilisateurs. ### Paramètres de requête Ajoutez ces paramètres pour activer le streaming : - `stream` - Définissez à `true` pour activer le streaming Server-Sent Events (SSE) -- `selectedOutputs` - Tableau des sorties de blocs à diffuser en streaming (par exemple, `["agent1.content"]`) +- `selectedOutputs` - Tableau des sorties de bloc à diffuser en streaming (par ex., `["agent1.content"]`) ### Format de sortie de bloc -Utilisez le format `blockName.attribute` pour spécifier quelles sorties de blocs diffuser en streaming : -- Format : `"blockName.attribute"` (par exemple, si vous souhaitez diffuser en streaming le contenu du bloc Agent 1, vous utiliseriez `"agent1.content"`) +Utilisez le format `blockName.attribute` pour spécifier quelles sorties de bloc diffuser en streaming : +- Format : `"blockName.attribute"` (par ex., si vous souhaitez diffuser le contenu du bloc Agent 1, vous utiliseriez `"agent1.content"`) - Les noms de blocs ne sont pas sensibles à la casse et les espaces sont ignorés ### Exemple de requête @@ -85,8 +93,8 @@ data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}} data: [DONE] ``` -Chaque événement comprend : -- **Fragments en streaming** : `{"blockId": "...", "chunk": "text"}` - Texte en temps réel au fur et à mesure qu'il est généré +Chaque événement inclut : +- **Fragments en streaming** : `{"blockId": "...", "chunk": "text"}` - Texte en temps réel au fur et à mesure de sa génération - **Événement final** : `{"event": "done", ...}` - Métadonnées d'exécution et résultats complets - **Terminateur** : `[DONE]` - Signale la fin du flux @@ -94,26 +102,22 @@ Chaque événement comprend : Lorsque `selectedOutputs` inclut plusieurs blocs, chaque fragment indique quel bloc l'a produit : -```bash -curl -X POST \ - https://sim.ai/api/workflows/WORKFLOW_ID/execute \ - -H 'Content-Type: application/json' \ - -H 'X-API-Key: YOUR_KEY' \ - -d '{ - "message": "Process this request", - "stream": true, - "selectedOutputs": ["agent1.content", "agent2.content"] - }' +```json +{ + "type": "block", + "blockType": "text", + "text": "Voici une réponse en streaming" +} ``` Le champ `blockId` dans chaque fragment vous permet d'acheminer la sortie vers l'élément d'interface utilisateur approprié : -``` -data: {"blockId":"agent1-uuid","chunk":"Processing..."} - -data: {"blockId":"agent2-uuid","chunk":"Analyzing..."} - -data: {"blockId":"agent1-uuid","chunk":" complete"} +```json +{ + "type": "block", + "blockType": "code", + "text": "console.log('Ceci est un bloc de code');" +} ``` ## Référence des sorties @@ -121,10 +125,57 @@ data: {"blockId":"agent1-uuid","chunk":" complete"} | Référence | Description | |-----------|-------------| | `` | Champ défini dans le format d'entrée | -| `` | Corps de requête structuré complet | +| `` | Corps complet de la requête structurée | + +### Format de téléchargement de fichiers + +L'API accepte les fichiers dans deux formats : + +**1. Fichiers encodés en Base64** (recommandé pour les SDK) : + +```json +{ + "file": { + "data": "data:application/pdf;base64,JVBERi0xLjMKJcTl8uXrp...", + "name": "document.pdf" + } +} +``` + +- Taille maximale de fichier : 20 Mo par fichier +- Les fichiers sont téléchargés vers le stockage cloud et convertis en objets UserFile avec toutes les propriétés + +**2. Références directes par URL** : + +```json +{ + "file": { + "url": "https://example.com/document.pdf", + "name": "document.pdf" + } +} +``` + +- Le fichier n'est pas téléchargé, l'URL est transmise directement +- Utile pour référencer des fichiers existants + +### Propriétés des fichiers + +Pour les fichiers, accédez à toutes les propriétés : + +| Propriété | Description | Type | +|----------|-------------|------| +| `` | URL de téléchargement signée | chaîne | +| `` | Nom de fichier original | chaîne | +| `` | Taille du fichier en octets | nombre | +| `` | Type MIME | chaîne | +| `` | Horodatage du téléchargement (ISO 8601) | chaîne | +| `` | Horodatage d'expiration de l'URL (ISO 8601) | chaîne | + +Pour les fichiers référencés par URL, les mêmes propriétés sont disponibles à l'exception de `uploadedAt` et `expiresAt` puisque le fichier n'est pas téléchargé dans notre stockage. Si aucun format d'entrée n'est défini, l'exécuteur expose uniquement le JSON brut à ``. -Un workflow ne peut contenir qu'un seul déclencheur API. Publiez un nouveau déploiement après les modifications pour que le point de terminaison reste à jour. +Un flux de travail ne peut contenir qu'un seul déclencheur d'API. Publiez un nouveau déploiement après les modifications pour que le point de terminaison reste à jour. diff --git a/apps/docs/content/docs/fr/triggers/chat.mdx b/apps/docs/content/docs/fr/triggers/chat.mdx index 56f04cb022..b7bc78122a 100644 --- a/apps/docs/content/docs/fr/triggers/chat.mdx +++ b/apps/docs/content/docs/fr/triggers/chat.mdx @@ -24,20 +24,31 @@ Le déclencheur de chat crée une interface conversationnelle pour votre flux de Le déclencheur écrit trois champs que les blocs en aval peuvent référencer : -| Référence | Description | -|-----------|-------------| -| `` | Dernier message de l'utilisateur | -| `` | ID du fil de conversation | -| `` | Fichiers téléchargés optionnels | +| Référence | Description | Type | +|-----------|-------------|------| +| `` | Dernier message de l'utilisateur | string | +| `` | ID du fil de conversation | string | +| `` | Fichiers téléchargés optionnels | tableau de fichiers | -Les fichiers incluent `name`, `mimeType`, et un `url` signé. +### Propriétés des fichiers + +Accédez aux propriétés individuelles des fichiers en utilisant l'indexation de tableau : + +| Propriété | Description | Type | +|----------|-------------|------| +| `` | URL de téléchargement signée | string | +| `` | Nom de fichier original | string | +| `` | Taille du fichier en octets | number | +| `` | Type MIME | string | +| `` | Horodatage du téléchargement (ISO 8601) | string | +| `` | Horodatage d'expiration de l'URL (ISO 8601) | string | ## Notes d'utilisation -1. Ajoutez un bloc Déclencheur de chat par flux de travail. -2. Déployez le flux de travail en mode chat. -3. Partagez le lien de déploiement — chaque réponse réutilise l'ID de conversation pour que le flux de travail puisse conserver le contexte. +1. Ajoutez un bloc Déclencheur de chat par workflow. +2. Déployez le workflow en mode chat. +3. Partagez le lien de déploiement — chaque réponse réutilise l'ID de conversation pour que le workflow puisse conserver le contexte. -Le constructeur bloque plusieurs blocs Déclencheur de chat dans le même flux de travail. +Le constructeur bloque plusieurs blocs Déclencheur de chat dans le même workflow. diff --git a/apps/docs/content/docs/ja/execution/costs.mdx b/apps/docs/content/docs/ja/execution/costs.mdx index 6f83172d2b..c991c42c8e 100644 --- a/apps/docs/content/docs/ja/execution/costs.mdx +++ b/apps/docs/content/docs/ja/execution/costs.mdx @@ -170,17 +170,49 @@ curl -X GET -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" htt | **チーム** | $500(プール) | 50同期、100非同期 | | **エンタープライズ** | カスタム | カスタム | +## 課金モデル + +Simは**基本サブスクリプション + 超過分**の課金モデルを使用しています: + +### 仕組み + +**Proプラン(月額$20):** +- 月額サブスクリプションには$20分の使用量が含まれます +- 使用量が$20未満 → 追加料金なし +- 使用量が$20を超える → 月末に超過分を支払い +- 例:$35の使用量 = $20(サブスクリプション)+ $15(超過分) + +**チームプラン(月額$40/シート):** +- チームメンバー全体でプールされた使用量 +- チーム全体の使用量から超過分を計算 +- 組織のオーナーが一括で請求を受ける + +**エンタープライズプラン:** +- 固定月額料金、超過料金なし +- 契約に基づくカスタム使用制限 + +### しきい値課金 + +未請求の超過分が$50に達すると、Simは自動的に未請求の全額を請求します。 + +**例:** +- 10日目:$70の超過分 → 即時に$70を請求 +- 15日目:追加$35の使用(合計$105)→ すでに請求済み、アクションなし +- 20日目:さらに$50の使用(合計$155、未請求$85)→ 即時に$85を請求 + +これにより、期間終了時に大きな請求が一度にくるのではなく、月を通じて大きな超過料金が分散されます。 + ## コスト管理のベストプラクティス -1. **定期的な監視**: 予期せぬ事態を避けるため、使用状況ダッシュボードを頻繁に確認する -2. **予算の設定**: プランの制限を支出のガードレールとして使用する -3. **ワークフローの最適化**: コストの高い実行を見直し、プロンプトやモデル選択を最適化する -4. **適切なモデルの使用**: タスクの要件に合わせてモデルの複雑さを選択する -5. **類似タスクのバッチ処理**: 可能な場合は複数のリクエストを組み合わせてオーバーヘッドを削減する +1. **定期的な監視**:予想外の事態を避けるため、使用量ダッシュボードを頻繁にチェック +2. **予算設定**:支出の目安としてプラン制限を活用 +3. **ワークフローの最適化**:高コストの実行を見直し、プロンプトやモデル選択を最適化 +4. **適切なモデルの使用**:タスク要件にモデルの複雑さを合わせる +5. **類似タスクのバッチ処理**:オーバーヘッドを減らすために可能な場合は複数のリクエストを組み合わせる ## 次のステップ -- [設定 → サブスクリプション](https://sim.ai/settings/subscription)で現在の使用状況を確認する +- [設定 → サブスクリプション](https://sim.ai/settings/subscription)で現在の使用状況を確認 - 実行詳細を追跡するための[ロギング](/execution/logging)について学ぶ -- プログラムによるコスト監視のための[外部API](/execution/api)を探索する -- コスト削減のための[ワークフロー最適化テクニック](/blocks)をチェックする \ No newline at end of file +- プログラムによるコスト監視のための[外部API](/execution/api)を探索 +- コスト削減のための[ワークフロー最適化テクニック](/blocks)をチェック \ No newline at end of file diff --git a/apps/docs/content/docs/ja/sdks/python.mdx b/apps/docs/content/docs/ja/sdks/python.mdx index b667a9f3d8..39fa75470d 100644 --- a/apps/docs/content/docs/ja/sdks/python.mdx +++ b/apps/docs/content/docs/ja/sdks/python.mdx @@ -433,7 +433,7 @@ with SimStudioClient(api_key=os.getenv("SIM_API_KEY")) as client: from simstudio import SimStudioClient import os -client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) +client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) def execute_workflows_batch(workflow_data_pairs): """Execute multiple workflows with different input data.""" @@ -660,7 +660,7 @@ def stream_workflow(): 'https://sim.ai/api/workflows/WORKFLOW_ID/execute', headers={ 'Content-Type': 'application/json', - 'X-API-Key': os.getenv('SIM_API_KEY') + 'X-API-Key': os.getenv('SIM_API_KEY') }, json={ 'message': 'Generate a story', diff --git a/apps/docs/content/docs/ja/sdks/typescript.mdx b/apps/docs/content/docs/ja/sdks/typescript.mdx index 785f60b29d..cdb30b3869 100644 --- a/apps/docs/content/docs/ja/sdks/typescript.mdx +++ b/apps/docs/content/docs/ja/sdks/typescript.mdx @@ -604,28 +604,114 @@ async function executeClientSideWorkflow() { }); console.log('Workflow result:', result); - + // Update UI with result - document.getElementById('result')!.textContent = + document.getElementById('result')!.textContent = JSON.stringify(result.output, null, 2); } catch (error) { console.error('Error:', error); } } +``` + +### ファイルアップロード + +ファイルオブジェクトは自動的に検出され、base64形式に変換されます。ワークフローのAPIトリガー入力形式に一致するフィールド名で入力に含めてください。 + +SDKはファイルオブジェクトを次の形式に変換します: + +```typescript +{ + type: 'file', + data: 'data:mime/type;base64,base64data', + name: 'filename', + mime: 'mime/type' +} +``` + +または、URL形式を使用して手動でファイルを提供することもできます: + +```typescript +{ + type: 'url', + data: 'https://example.com/file.pdf', + name: 'file.pdf', + mime: 'application/pdf' +} +``` + + + + + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + + const client = new SimStudioClient({ + apiKey: process.env.NEXT_PUBLIC_SIM_API_KEY! + }); + + // From file input + async function handleFileUpload(event: Event) { + const input = event.target as HTMLInputElement; + const files = Array.from(input.files || []); + + // Include files under the field name from your API trigger's input format + const result = await client.executeWorkflow('workflow-id', { + input: { + documents: files, // Must match your workflow's "files" field name + instructions: 'Analyze these documents' + } + }); + + console.log('Result:', result); + } + ``` + + + -// Attach to button click + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + import fs from 'fs'; + + const client = new SimStudioClient({ + apiKey: process.env.SIM_API_KEY! + }); + + // Read file and create File object + const fileBuffer = fs.readFileSync('./document.pdf'); + const file = new File([fileBuffer], 'document.pdf', { + type: 'application/pdf' + }); + + // Include files under the field name from your API trigger's input format + const result = await client.executeWorkflow('workflow-id', { + input: { + documents: [file], // Must match your workflow's "files" field name + query: 'Summarize this document' + } + }); + ``` + + + + +// ボタンクリックに接続 document.getElementById('executeBtn')?.addEventListener('click', executeClientSideWorkflow); + ``` - ブラウザでSDKを使用する場合、機密性の高いAPIキーを公開しないよう注意してください。バックエンドプロキシや権限が制限された公開APIキーの使用を検討してください。 + When using the SDK in the browser, be careful not to expose sensitive API keys. Consider using a backend proxy or public API keys with limited permissions. -### Reactフックの例 +### React Hook Example -ワークフロー実行用のカスタムReactフックを作成: +Create a custom React hook for workflow execution: -```typescript +``` + +typescript import { useState, useCallback } from 'react'; import { SimStudioClient, WorkflowExecutionResult } from 'simstudio-ts-sdk'; @@ -671,7 +757,7 @@ export function useWorkflow(): UseWorkflowResult { }; } -// Usage in component +// コンポーネントでの使用 function WorkflowComponent() { const { result, loading, error, executeWorkflow } = useWorkflow(); @@ -684,26 +770,29 @@ function WorkflowComponent() { return (
- {error &&
Error: {error.message}
} + {error &&
エラー: {error.message}
} {result && (
-

Result:

+

結果:

{JSON.stringify(result, null, 2)}
)}
); } + ``` -### 非同期ワークフロー実行 +### Async Workflow Execution -長時間実行タスク向けに非同期でワークフローを実行: +Execute workflows asynchronously for long-running tasks: -```typescript +``` + +typescript import { SimStudioClient, AsyncExecutionResult } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -712,47 +801,50 @@ const client = new SimStudioClient({ async function executeAsync() { try { - // Start async execution + // 非同期実行を開始 const result = await client.executeWorkflow('workflow-id', { input: { data: 'large dataset' }, - async: true // Execute asynchronously + async: true // 非同期で実行 }); - // Check if result is an async execution + // 結果が非同期実行かどうかを確認 if ('taskId' in result) { - console.log('Task ID:', result.taskId); - console.log('Status endpoint:', result.links.status); + console.log('タスクID:', result.taskId); + console.log('ステータスエンドポイント:', result.links.status); - // Poll for completion + // 完了を確認するためのポーリング let status = await client.getJobStatus(result.taskId); while (status.status === 'queued' || status.status === 'processing') { - console.log('Current status:', status.status); - await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds + console.log('現在のステータス:', status.status); + await new Promise(resolve => setTimeout(resolve, 2000)); // 2秒待機 status = await client.getJobStatus(result.taskId); } if (status.status === 'completed') { - console.log('Workflow completed!'); - console.log('Output:', status.output); - console.log('Duration:', status.metadata.duration); + console.log('ワークフロー完了!'); + console.log('出力:', status.output); + console.log('所要時間:', status.metadata.duration); } else { - console.error('Workflow failed:', status.error); + console.error('ワークフロー失敗:', status.error); } } } catch (error) { - console.error('Error:', error); + console.error('エラー:', error); } } executeAsync(); + ``` -### レート制限とリトライ +### Rate Limiting and Retry -指数バックオフによるレート制限の自動処理: +Handle rate limits automatically with exponential backoff: -```typescript +``` + +typescript import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -761,7 +853,7 @@ const client = new SimStudioClient({ async function executeWithRetryHandling() { try { - // Automatically retries on rate limit + // レート制限時に自動的にリトライ const result = await client.executeWithRetry('workflow-id', { input: { message: 'Process this' } }, { @@ -771,26 +863,29 @@ async function executeWithRetryHandling() { backoffMultiplier: 2 }); - console.log('Success:', result); + console.log('成功:', result); } catch (error) { if (error instanceof SimStudioError && error.code === 'RATE_LIMIT_EXCEEDED') { - console.error('Rate limit exceeded after all retries'); + console.error('すべてのリトライ後もレート制限を超過'); - // Check rate limit info + // レート制限情報を確認 const rateLimitInfo = client.getRateLimitInfo(); if (rateLimitInfo) { - console.log('Rate limit resets at:', new Date(rateLimitInfo.reset * 1000)); + console.log('レート制限リセット時刻:', new Date(rateLimitInfo.reset * 1000)); } } } } + ``` -### 使用状況モニタリング +### Usage Monitoring -アカウントの使用状況と制限のモニタリング: +Monitor your account usage and limits: -```typescript +``` + +typescript import { SimStudioClient } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -801,27 +896,46 @@ async function checkUsage() { try { const limits = await client.getUsageLimits(); - console.log('=== Rate Limits ==='); - console.log('Sync requests:'); - console.log(' Limit:', limits.rateLimit.sync.limit); - console.log(' Remaining:', limits.rateLimit.sync.remaining); - console.log(' Resets at:', limits.rateLimit.sync.resetAt); - console.log(' Is limited:', limits.rateLimit.sync.isLimited); + console.log('=== レート制限 ==='); + console.log('同期リクエスト:'); + console.log(' 制限:', limits.rateLimit.sync.limit); + console.log(' 残り:', limits.rateLimit.sync.remaining); + console.log(' リセット時間:', limits.rateLimit.sync.resetAt); + console.log(' 制限中:', limits.rateLimit.sync.isLimited); + + console.log('\n非同期リクエスト:'); + console.log(' 制限:', limits.rateLimit.async.limit); + console.log(' 残り:', limits.rateLimit.async.remaining); + console.log(' リセット時間:', limits.rateLimit.async.resetAt); + console.log(' 制限中:', limits.rateLimit.async.isLimited); + + console.log('\n=== 使用状況 ==='); + console.log('現在の期間のコスト: $' + limits.usage.currentPeriodCost.toFixed(2)); + console.log('制限: $' + limits.usage.limit.toFixed(2)); + console.log('プラン:', limits.usage.plan); + + const percentUsed = (limits.usage.currentPeriodCost / limits.usage.limit) * 100; + console.log('使用率: ' + percentUsed.toFixed(1) + '%'); + + if (percentUsed > 80) { + console.warn('⚠️ 警告: 使用制限に近づいています!'); + } + } catch (error) { + console.error('使用状況確認エラー:', error); + } +} - console.log('\nAsync requests:'); - console.log(' Limit:', limits.rateLimit.async.limit); - console.log(' Remaining:', limits.rateLimit.async.remaining); - console.log(' Resets at:', limits.rateLimit.async.resetAt); - console.log(' Is limited:', limits.rateLimit.async.isLimited); +checkUsage(); - console.log('\n=== Usage ==='); - console.log('Current period cost: +``` ### Streaming Workflow Execution Execute workflows with real-time streaming responses: -```typescript +``` + +typescript import { SimStudioClient } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -834,7 +948,7 @@ async function executeWithStreaming() { const result = await client.executeWorkflow('workflow-id', { input: { message: 'Count to five' }, stream: true, - selectedOutputs: ['agent1.content'] // blockName.attribute形式を使用 + selectedOutputs: ['agent1.content'] // blockName.attribute 形式を使用 }); console.log('ワークフロー結果:', result); @@ -842,11 +956,13 @@ async function executeWithStreaming() { console.error('エラー:', error); } } + ``` The streaming response follows the Server-Sent Events (SSE) format: ``` + data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"} data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", two"} @@ -854,11 +970,14 @@ data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", two"} data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}} data: [DONE] + ``` **React Streaming Example:** -```typescript +``` + +typescript import { useState, useEffect } from 'react'; function StreamingWorkflow() { @@ -869,13 +988,13 @@ function StreamingWorkflow() { setLoading(true); setOutput(''); - // IMPORTANT: Make this API call from your backend server, not the browser - // Never expose your API key in client-side code + // 重要: このAPIコールはブラウザではなくバックエンドサーバーから行ってください + // クライアントサイドのコードにAPIキーを公開しないでください const response = await fetch('https://sim.ai/api/workflows/WORKFLOW_ID/execute', { method: 'POST', headers: { 'Content-Type': 'application/json', - 'X-API-Key': process.env.SIM_API_KEY! // Server-side environment variable only + 'X-API-Key': process.env.SIM_API_KEY! // サーバーサイドの環境変数のみ }, body: JSON.stringify({ message: 'Generate a story', @@ -907,10 +1026,10 @@ function StreamingWorkflow() { if (parsed.chunk) { setOutput(prev => prev + parsed.chunk); } else if (parsed.event === 'done') { - console.log('Execution complete:', parsed.metadata); + console.log('実行完了:', parsed.metadata); } } catch (e) { - // Skip invalid JSON + // 無効なJSONをスキップ } } } @@ -920,12 +1039,13 @@ function StreamingWorkflow() { return (
{output}
); } + ``` ## Getting Your API Key @@ -961,7 +1081,9 @@ function StreamingWorkflow() { The SDK is written in TypeScript and provides full type safety: -```typescript +``` + +typescript import { SimStudioClient, WorkflowExecutionResult, @@ -969,23 +1091,22 @@ import { SimStudioError } from 'simstudio-ts-sdk'; -// Type-safe client initialization +// 型安全なクライアント初期化 const client: SimStudioClient = new SimStudioClient({ apiKey: process.env.SIM_API_KEY! }); -// Type-safe workflow execution +// 型安全なワークフロー実行 const result: WorkflowExecutionResult = await client.executeWorkflow('workflow-id', { input: { message: 'Hello, TypeScript!' } }); -// Type-safe status checking +// 型安全なステータス確認 const status: WorkflowStatus = await client.getWorkflowStatus('workflow-id'); ``` -## License - +## ライセンス Apache-2.0 diff --git a/apps/docs/content/docs/ja/triggers/api.mdx b/apps/docs/content/docs/ja/triggers/api.mdx index 931d4da25f..27fc3dab97 100644 --- a/apps/docs/content/docs/ja/triggers/api.mdx +++ b/apps/docs/content/docs/ja/triggers/api.mdx @@ -22,9 +22,17 @@ APIトリガーは、ワークフローを安全なHTTPエンドポイントと /> -各パラメータに**入力フォーマット**フィールドを追加します。実行時の出力キーはスキーマを反映し、``でも利用できます。 +各パラメータに**入力フォーマット**フィールドを追加します。サポートされている型: -エディタでの手動実行は `value` 列を使用するため、リクエストを送信せずにテストできます。実行中、リゾルバーは `` と `` の両方に値を設定します。 +- **string** - テキスト値 +- **number** - 数値 +- **boolean** - 真/偽の値 +- **json** - JSONオブジェクト +- **files** - ファイルアップロード(``、``などでアクセス) + +ランタイム出力キーはスキーマを反映し、``の下で利用できます。 + +エディタでの手動実行では、リクエストを送信せずにテストできるように`value`列を使用します。実行中、リゾルバは``と``の両方に値を設定します。 ## リクエスト例 @@ -36,23 +44,23 @@ curl -X POST \ -d '{"userId":"demo-user","maxTokens":1024}' ``` -成功したレスポンスはエグゼキュータからシリアル化された実行結果を返します。エラーは検証、認証、またはワークフローの失敗を表示します。 +成功したレスポンスはエグゼキュータからのシリアル化された実行結果を返します。エラーは検証、認証、またはワークフローの失敗を表示します。 ## ストリーミングレスポンス -リアルタイムストリーミングを有効にすると、ワークフローの出力が生成されるたびに文字単位で受信できます。これはAIの応答をユーザーに段階的に表示するのに役立ちます。 +リアルタイムストリーミングを有効にすると、生成されたワークフロー出力を文字単位でリアルタイムに受信できます。これはAIの応答をユーザーに段階的に表示するのに役立ちます。 ### リクエストパラメータ -ストリーミングを有効にするには、これらのパラメータを追加してください: +ストリーミングを有効にするには、これらのパラメータを追加します: -- `stream` - Server-Sent Events (SSE)ストリーミングを有効にするには `true` に設定します +- `stream` - Server-Sent Events(SSE)ストリーミングを有効にするには`true`に設定 - `selectedOutputs` - ストリーミングするブロック出力の配列(例:`["agent1.content"]`) ### ブロック出力フォーマット -`blockName.attribute` フォーマットを使用して、ストリーミングするブロック出力を指定します: -- フォーマット:`"blockName.attribute"`(例:Agent 1ブロックの内容をストリーミングしたい場合は、`"agent1.content"` を使用します) +`blockName.attribute`フォーマットを使用して、ストリーミングするブロック出力を指定します: +- フォーマット:`"blockName.attribute"`(例:Agent 1ブロックの内容をストリーミングしたい場合は、`"agent1.content"`を使用) - ブロック名は大文字小文字を区別せず、スペースは無視されます ### リクエスト例 @@ -71,7 +79,7 @@ curl -X POST \ ### レスポンスフォーマット -ストリーミングレスポンスはServer-Sent Events (SSE)フォーマットを使用します: +ストリーミングレスポンスはServer-Sent Events(SSE)フォーマットを使用します: ``` data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"} @@ -88,32 +96,28 @@ data: [DONE] 各イベントには以下が含まれます: - **ストリーミングチャンク**:`{"blockId": "...", "chunk": "text"}` - 生成されるリアルタイムテキスト - **最終イベント**:`{"event": "done", ...}` - 実行メタデータと完全な結果 -- **ターミネーター**:`[DONE]` - ストリーム終了を示す信号 +- **ターミネータ**:`[DONE]` - ストリーム終了を示す信号 ### 複数ブロックのストリーミング -`selectedOutputs` に複数のブロックが含まれる場合、各チャンクはどのブロックから生成されたかを示します: +`selectedOutputs`に複数のブロックが含まれる場合、各チャンクはどのブロックがそれを生成したかを示します: -```bash -curl -X POST \ - https://sim.ai/api/workflows/WORKFLOW_ID/execute \ - -H 'Content-Type: application/json' \ - -H 'X-API-Key: YOUR_KEY' \ - -d '{ - "message": "Process this request", - "stream": true, - "selectedOutputs": ["agent1.content", "agent2.content"] - }' +```json +{ + "type": "block", + "blockId": "1", + "content": "こんにちは!" +} ``` 各チャンクの `blockId` フィールドを使用して、出力を正しいUI要素にルーティングできます: -``` -data: {"blockId":"agent1-uuid","chunk":"Processing..."} - -data: {"blockId":"agent2-uuid","chunk":"Analyzing..."} - -data: {"blockId":"agent1-uuid","chunk":" complete"} +```json +{ + "type": "block", + "blockId": "chart1", + "content": { "type": "chart", "data": [...] } +} ``` ## 出力リファレンス @@ -123,8 +127,54 @@ data: {"blockId":"agent1-uuid","chunk":" complete"} | `` | 入力フォーマットで定義されたフィールド | | `` | 構造化されたリクエスト本文全体 | +### ファイルアップロードフォーマット + +APIは2つの形式でファイルを受け付けます: + +**1. Base64エンコードされたファイル**(SDKでの使用推奨): + +```json +{ + "files": [{ + "name": "example.pdf", + "data": "JVBERi0xLjMKJcTl8uXrp/Og0MTGCjQgMCBvY..." + }] +} +``` + +- 最大ファイルサイズ:ファイルあたり20MB +- ファイルはクラウドストレージにアップロードされ、すべてのプロパティを持つUserFileオブジェクトに変換されます + +**2. 直接URLリファレンス**: + +```json +{ + "files": [{ + "url": "https://example.com/myfile.pdf" + }] +} +``` + +- ファイルはアップロードされず、URLが直接渡されます +- 既存のファイルを参照する場合に便利です + +### ファイルプロパティ + +ファイルについては、すべてのプロパティにアクセスできます: + +| プロパティ | 説明 | 型 | +|----------|-------------|------| +| `` | 署名付きダウンロードURL | string | +| `` | 元のファイル名 | string | +| `` | ファイルサイズ(バイト) | number | +| `` | MIMEタイプ | string | +| `` | アップロードタイムスタンプ(ISO 8601) | string | +| `` | URL有効期限タイムスタンプ(ISO 8601) | string | + +URLで参照されるファイルの場合、ファイルが当社のストレージにアップロードされないため、`uploadedAt` と `expiresAt` を除く同じプロパティが利用可能です。 + 入力フォーマットが定義されていない場合、エグゼキューターは `` でのみ生のJSONを公開します。 -ワークフローには1つのAPIトリガーのみ含めることができます。変更後は新しいデプロイメントを公開して、エンドポイントを最新の状態に保ってください。 +ワークフローには1つのAPIトリガーしか含めることができません。変更後は新しいデプロイメントを公開して、エンドポイントを最新の状態に保ってください。 diff --git a/apps/docs/content/docs/ja/triggers/chat.mdx b/apps/docs/content/docs/ja/triggers/chat.mdx index 8c9b6a4e45..0b1140d492 100644 --- a/apps/docs/content/docs/ja/triggers/chat.mdx +++ b/apps/docs/content/docs/ja/triggers/chat.mdx @@ -24,19 +24,30 @@ import { Image } from '@/components/ui/image' このトリガーは、下流のブロックが参照できる3つのフィールドを書き込みます: -| 参照 | 説明 | -|-----------|-------------| -| `` | 最新のユーザーメッセージ | -| `` | 会話スレッドID | -| `` | オプションのアップロードファイル | +| リファレンス | 説明 | 型 | +|-----------|-------------|------| +| `` | 最新のユーザーメッセージ | string | +| `` | 会話スレッドID | string | +| `` | オプションのアップロードファイル | files配列 | -ファイルには `name`、`mimeType`、および署名付きダウンロード `url` が含まれます。 +### ファイルプロパティ + +配列インデックスを使用して個々のファイルプロパティにアクセスします: + +| プロパティ | 説明 | 型 | +|----------|-------------|------| +| `` | 署名付きダウンロードURL | string | +| `` | 元のファイル名 | string | +| `` | ファイルサイズ(バイト単位) | number | +| `` | MIMEタイプ | string | +| `` | アップロードタイムスタンプ(ISO 8601形式) | string | +| `` | URL有効期限タイムスタンプ(ISO 8601形式) | string | ## 使用上の注意 1. ワークフローごとにチャットトリガーブロックを1つ追加します。 -2. ワークフローをチャットモードでデプロイします。 -3. デプロイメントリンクを共有します—各返信は同じ会話IDを再利用するため、ワークフローはコンテキストを保持できます。 +2. チャットモードでワークフローをデプロイします。 +3. デプロイメントリンクを共有します—すべての返信は同じ会話IDを再利用するため、ワークフローはコンテキストを保持できます。 ビルダーは同じワークフロー内の複数のチャットトリガーブロックをブロックします。 diff --git a/apps/docs/content/docs/zh/execution/costs.mdx b/apps/docs/content/docs/zh/execution/costs.mdx index 4ada972604..00e2b3387f 100644 --- a/apps/docs/content/docs/zh/execution/costs.mdx +++ b/apps/docs/content/docs/zh/execution/costs.mdx @@ -170,11 +170,43 @@ curl -X GET -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" htt | **团队** | $500(池化) | 50 同步, 100 异步 | | **企业** | 自定义 | 自定义 | +## 计费模式 + +Sim 使用 **基础订阅 + 超额** 的计费模式: + +### 工作原理 + +**专业计划($20/月):** +- 月订阅包含 $20 的使用额度 +- 使用低于 $20 → 无额外费用 +- 使用超过 $20 → 月底支付超额部分 +- 示例:$35 的使用 = $20(订阅)+ $15(超额) + +**团队计划($40/人/月):** +- 团队成员共享使用额度 +- 超额费用根据团队总使用量计算 +- 组织所有者收到一张账单 + +**企业计划:** +- 固定月费,无超额费用 +- 根据协议定制使用限制 + +### 阈值计费 + +当未结算的超额费用达到 $50 时,Sim 会自动结算全部未结算金额。 + +**示例:** +- 第 10 天:$70 超额 → 立即结算 $70 +- 第 15 天:额外使用 $35(总计 $105)→ 已结算,无需操作 +- 第 20 天:再使用 $50(总计 $155,未结算 $85)→ 立即结算 $85 + +这可以将大额超额费用分散到整个月,而不是在周期末一次性结算。 + ## 成本管理最佳实践 -1. **定期监控**:经常检查您的使用仪表板,避免意外情况 -2. **设置预算**:使用计划限制作为支出控制的护栏 -3. **优化工作流程**:审查高成本的执行情况,优化提示或模型选择 +1. **定期监控**:经常检查您的使用仪表板,避免意外 +2. **设定预算**:使用计划限制作为支出控制的参考 +3. **优化工作流程**:审查高成本的执行,优化提示或模型选择 4. **使用合适的模型**:根据任务需求匹配模型复杂度 5. **批量处理相似任务**:尽可能合并多个请求以减少开销 diff --git a/apps/docs/content/docs/zh/sdks/python.mdx b/apps/docs/content/docs/zh/sdks/python.mdx index 8ca6874295..5a59d69d70 100644 --- a/apps/docs/content/docs/zh/sdks/python.mdx +++ b/apps/docs/content/docs/zh/sdks/python.mdx @@ -433,7 +433,7 @@ with SimStudioClient(api_key=os.getenv("SIM_API_KEY")) as client: from simstudio import SimStudioClient import os -client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) +client = SimStudioClient(api_key=os.getenv("SIM_API_KEY")) def execute_workflows_batch(workflow_data_pairs): """Execute multiple workflows with different input data.""" @@ -660,7 +660,7 @@ def stream_workflow(): 'https://sim.ai/api/workflows/WORKFLOW_ID/execute', headers={ 'Content-Type': 'application/json', - 'X-API-Key': os.getenv('SIM_API_KEY') + 'X-API-Key': os.getenv('SIM_API_KEY') }, json={ 'message': 'Generate a story', diff --git a/apps/docs/content/docs/zh/sdks/typescript.mdx b/apps/docs/content/docs/zh/sdks/typescript.mdx index ba56120459..20cddf57ce 100644 --- a/apps/docs/content/docs/zh/sdks/typescript.mdx +++ b/apps/docs/content/docs/zh/sdks/typescript.mdx @@ -604,28 +604,114 @@ async function executeClientSideWorkflow() { }); console.log('Workflow result:', result); - + // Update UI with result - document.getElementById('result')!.textContent = + document.getElementById('result')!.textContent = JSON.stringify(result.output, null, 2); } catch (error) { console.error('Error:', error); } } +``` + +### 文件上传 + +文件对象会被自动检测并转换为 base64 格式。请将它们包含在与工作流 API 触发器输入格式字段名称匹配的输入中。 + +SDK 会将文件对象转换为以下格式: + +```typescript +{ + type: 'file', + data: 'data:mime/type;base64,base64data', + name: 'filename', + mime: 'mime/type' +} +``` + +或者,您可以使用 URL 格式手动提供文件: + +```typescript +{ + type: 'url', + data: 'https://example.com/file.pdf', + name: 'file.pdf', + mime: 'application/pdf' +} +``` + + + + + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + + const client = new SimStudioClient({ + apiKey: process.env.NEXT_PUBLIC_SIM_API_KEY! + }); + + // From file input + async function handleFileUpload(event: Event) { + const input = event.target as HTMLInputElement; + const files = Array.from(input.files || []); + + // Include files under the field name from your API trigger's input format + const result = await client.executeWorkflow('workflow-id', { + input: { + documents: files, // Must match your workflow's "files" field name + instructions: 'Analyze these documents' + } + }); + + console.log('Result:', result); + } + ``` + + + -// Attach to button click + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + import fs from 'fs'; + + const client = new SimStudioClient({ + apiKey: process.env.SIM_API_KEY! + }); + + // Read file and create File object + const fileBuffer = fs.readFileSync('./document.pdf'); + const file = new File([fileBuffer], 'document.pdf', { + type: 'application/pdf' + }); + + // Include files under the field name from your API trigger's input format + const result = await client.executeWorkflow('workflow-id', { + input: { + documents: [file], // Must match your workflow's "files" field name + query: 'Summarize this document' + } + }); + ``` + + + + +// 绑定到按钮点击事件 document.getElementById('executeBtn')?.addEventListener('click', executeClientSideWorkflow); + ``` - 在浏览器中使用 SDK 时,请注意不要暴露敏感的 API 密钥。建议使用后端代理或具有有限权限的公共 API 密钥。 + When using the SDK in the browser, be careful not to expose sensitive API keys. Consider using a backend proxy or public API keys with limited permissions. -### React Hook 示例 +### React Hook Example -为工作流执行创建自定义 React hook: +Create a custom React hook for workflow execution: -```typescript +``` + +typescript import { useState, useCallback } from 'react'; import { SimStudioClient, WorkflowExecutionResult } from 'simstudio-ts-sdk'; @@ -657,7 +743,7 @@ export function useWorkflow(): UseWorkflowResult { }); setResult(workflowResult); } catch (err) { - setError(err instanceof Error ? err : new Error('Unknown error')); + setError(err instanceof Error ? err : new Error('未知错误')); } finally { setLoading(false); } @@ -671,39 +757,41 @@ export function useWorkflow(): UseWorkflowResult { }; } -// Usage in component +// 在组件中使用 function WorkflowComponent() { const { result, loading, error, executeWorkflow } = useWorkflow(); const handleExecute = () => { executeWorkflow('my-workflow-id', { - message: 'Hello from React!' + message: '来自 React 的问候!' }); - }; return (
- {error &&
Error: {error.message}
} + {error &&
错误: {error.message}
} {result && (
-

Result:

+

结果:

{JSON.stringify(result, null, 2)}
)}
); } + ``` -### 异步工作流执行 +### Async Workflow Execution -为长时间运行的任务异步执行工作流: +Execute workflows asynchronously for long-running tasks: -```typescript +``` + +typescript import { SimStudioClient, AsyncExecutionResult } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -712,47 +800,50 @@ const client = new SimStudioClient({ async function executeAsync() { try { - // Start async execution + // 开始异步执行 const result = await client.executeWorkflow('workflow-id', { input: { data: 'large dataset' }, - async: true // Execute asynchronously + async: true // 异步执行 }); - // Check if result is an async execution + // 检查结果是否为异步执行 if ('taskId' in result) { - console.log('Task ID:', result.taskId); - console.log('Status endpoint:', result.links.status); + console.log('任务 ID:', result.taskId); + console.log('状态端点:', result.links.status); - // Poll for completion + // 轮询完成状态 let status = await client.getJobStatus(result.taskId); while (status.status === 'queued' || status.status === 'processing') { - console.log('Current status:', status.status); - await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds + console.log('当前状态:', status.status); + await new Promise(resolve => setTimeout(resolve, 2000)); // 等待 2 秒 status = await client.getJobStatus(result.taskId); } if (status.status === 'completed') { - console.log('Workflow completed!'); - console.log('Output:', status.output); - console.log('Duration:', status.metadata.duration); + console.log('工作流已完成!'); + console.log('输出:', status.output); + console.log('持续时间:', status.metadata.duration); } else { - console.error('Workflow failed:', status.error); + console.error('工作流失败:', status.error); } } } catch (error) { - console.error('Error:', error); + console.error('错误:', error); } } executeAsync(); + ``` -### 速率限制和重试 +### Rate Limiting and Retry -通过指数退避自动处理速率限制: +Handle rate limits automatically with exponential backoff: -```typescript +``` + +typescript import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -761,7 +852,7 @@ const client = new SimStudioClient({ async function executeWithRetryHandling() { try { - // Automatically retries on rate limit + // 在速率限制时自动重试 const result = await client.executeWithRetry('workflow-id', { input: { message: 'Process this' } }, { @@ -771,26 +862,29 @@ async function executeWithRetryHandling() { backoffMultiplier: 2 }); - console.log('Success:', result); + console.log('成功:', result); } catch (error) { if (error instanceof SimStudioError && error.code === 'RATE_LIMIT_EXCEEDED') { - console.error('Rate limit exceeded after all retries'); + console.error('在所有重试后速率限制已超出'); - // Check rate limit info + // 检查速率限制信息 const rateLimitInfo = client.getRateLimitInfo(); if (rateLimitInfo) { - console.log('Rate limit resets at:', new Date(rateLimitInfo.reset * 1000)); + console.log('速率限制将在以下时间重置:', new Date(rateLimitInfo.reset * 1000)); } } } } + ``` -### 使用监控 +### Usage Monitoring -监控您的账户使用情况和限制: +Monitor your account usage and limits: -```typescript +``` + +typescript import { SimStudioClient } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -801,27 +895,46 @@ async function checkUsage() { try { const limits = await client.getUsageLimits(); - console.log('=== Rate Limits ==='); - console.log('Sync requests:'); - console.log(' Limit:', limits.rateLimit.sync.limit); - console.log(' Remaining:', limits.rateLimit.sync.remaining); - console.log(' Resets at:', limits.rateLimit.sync.resetAt); - console.log(' Is limited:', limits.rateLimit.sync.isLimited); + console.log('=== 速率限制 ==='); + console.log('同步请求:'); + console.log(' 限制:', limits.rateLimit.sync.limit); + console.log(' 剩余:', limits.rateLimit.sync.remaining); + console.log(' 重置时间:', limits.rateLimit.sync.resetAt); + console.log(' 是否受限:', limits.rateLimit.sync.isLimited); + + console.log('\n异步请求:'); + console.log(' 限制:', limits.rateLimit.async.limit); + console.log(' 剩余:', limits.rateLimit.async.remaining); + console.log(' 重置时间:', limits.rateLimit.async.resetAt); + console.log(' 是否受限:', limits.rateLimit.async.isLimited); + + console.log('\n=== 使用情况 ==='); + console.log('当前周期费用: $' + limits.usage.currentPeriodCost.toFixed(2)); + console.log('限制: $' + limits.usage.limit.toFixed(2)); + console.log('计划:', limits.usage.plan); + + const percentUsed = (limits.usage.currentPeriodCost / limits.usage.limit) * 100; + console.log('使用率: ' + percentUsed.toFixed(1) + '%'); + + if (percentUsed > 80) { + console.warn('⚠️ 警告: 您的使用量即将达到限制!'); + } + } catch (error) { + console.error('检查使用情况时出错:', error); + } +} - console.log('\nAsync requests:'); - console.log(' Limit:', limits.rateLimit.async.limit); - console.log(' Remaining:', limits.rateLimit.async.remaining); - console.log(' Resets at:', limits.rateLimit.async.resetAt); - console.log(' Is limited:', limits.rateLimit.async.isLimited); +checkUsage(); - console.log('\n=== Usage ==='); - console.log('Current period cost: +``` ### Streaming Workflow Execution Execute workflows with real-time streaming responses: -```typescript +``` + +typescript import { SimStudioClient } from 'simstudio-ts-sdk'; const client = new SimStudioClient({ @@ -842,11 +955,13 @@ async function executeWithStreaming() { console.error('错误:', error); } } + ``` The streaming response follows the Server-Sent Events (SSE) format: ``` + data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"} data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", two"} @@ -854,11 +969,14 @@ data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", two"} data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}} data: [DONE] + ``` **React Streaming Example:** -```typescript +``` + +typescript import { useState, useEffect } from 'react'; function StreamingWorkflow() { @@ -869,7 +987,7 @@ function StreamingWorkflow() { setLoading(true); setOutput(''); - // 重要提示:请从您的后端服务器发起此 API 调用,而不是从浏览器发起 + // 重要: 请从您的后端服务器发起此 API 调用,而不是在浏览器中 // 切勿在客户端代码中暴露您的 API 密钥 const response = await fetch('https://sim.ai/api/workflows/WORKFLOW_ID/execute', { method: 'POST', @@ -926,6 +1044,7 @@ function StreamingWorkflow() { ); } + ``` ## Getting Your API Key @@ -961,7 +1080,9 @@ function StreamingWorkflow() { The SDK is written in TypeScript and provides full type safety: -```typescript +``` + +typescript import { SimStudioClient, WorkflowExecutionResult, diff --git a/apps/docs/content/docs/zh/triggers/api.mdx b/apps/docs/content/docs/zh/triggers/api.mdx index e5f6ef72ef..73853acfdd 100644 --- a/apps/docs/content/docs/zh/triggers/api.mdx +++ b/apps/docs/content/docs/zh/triggers/api.mdx @@ -22,9 +22,17 @@ API 触发器将您的工作流公开为一个安全的 HTTP 端点。将 JSON /> -为每个参数添加一个 **输入格式** 字段。运行时输出键会镜像该模式,并且也可以在 `` 下使用。 +为每个参数添加一个 **输入格式** 字段。支持的类型: -在编辑器中手动运行使用 `value` 列,因此您可以在不发送请求的情况下进行测试。在执行过程中,解析器会填充 `` 和 ``。 +- **string** - 文本值 +- **number** - 数值 +- **boolean** - 真/假值 +- **json** - JSON 对象 +- **files** - 文件上传(通过 ``、`` 等访问) + +运行时输出键与架构相对应,并可通过 `` 获取。 + +编辑器中的手动运行使用 `value` 列,因此您可以在不发送请求的情况下进行测试。在执行期间,解析器会填充 `` 和 ``。 ## 请求示例 @@ -55,7 +63,7 @@ curl -X POST \ - 格式:`"blockName.attribute"`(例如,如果您想流式传输 Agent 1 块的内容,可以使用 `"agent1.content"`) - 块名称不区分大小写,空格会被忽略 -### 示例请求 +### 请求示例 ```bash curl -X POST \ @@ -92,7 +100,7 @@ data: [DONE] ### 多块流式传输 -当 `selectedOutputs` 包含多个块时,每个块会指示其来源: +当 `selectedOutputs` 包含多个块时,每个块会指示其来源块: ```bash curl -X POST \ @@ -118,11 +126,62 @@ data: {"blockId":"agent1-uuid","chunk":" complete"} ## 输出参考 -| 参考 | 描述 | +| 引用 | 描述 | |-----------|-------------| | `` | 输入格式中定义的字段 | | `` | 整个结构化请求体 | +### 文件上传格式 + +API 接受两种格式的文件: + +**1. Base64 编码文件**(推荐用于 SDK): + +```json +{ + "documents": [{ + "type": "file", + "data": "data:application/pdf;base64,JVBERi0xLjQK...", + "name": "document.pdf", + "mime": "application/pdf" + }] +} +``` + +- 最大文件大小:每个文件 20MB +- 文件上传到云存储,并转换为具有所有属性的 UserFile 对象 + +**2. 直接 URL 引用**: + +```json +{ + "documents": [{ + "type": "url", + "data": "https://example.com/document.pdf", + "name": "document.pdf", + "mime": "application/pdf" + }] +} +``` + +- 文件未上传,URL 直接传递 +- 适用于引用现有文件 + +### 文件属性 + +对于文件,可以访问所有属性: + +| 属性 | 描述 | 类型 | +|----------|-------------|------| +| `` | 签名下载 URL | string | +| `` | 原始文件名 | string | +| `` | 文件大小(字节) | number | +| `` | MIME 类型 | string | +| `` | 上传时间戳(ISO 8601) | string | +| `` | URL 过期时间戳(ISO 8601) | string | + +对于 URL 引用的文件,除了 `uploadedAt` 和 `expiresAt` 外,其他属性均可用,因为文件未上传到我们的存储中。 + 如果未定义输入格式,执行器仅在 `` 处暴露原始 JSON。 diff --git a/apps/docs/content/docs/zh/triggers/chat.mdx b/apps/docs/content/docs/zh/triggers/chat.mdx index d48b75b97d..606f782a8c 100644 --- a/apps/docs/content/docs/zh/triggers/chat.mdx +++ b/apps/docs/content/docs/zh/triggers/chat.mdx @@ -24,20 +24,31 @@ import { Image } from '@/components/ui/image' 触发器会写入三个字段,供下游模块引用: -| 引用 | 描述 | -|-----------|-------------| -| `` | 最新的用户消息 | -| `` | 对话线程 ID | -| `` | 可选的上传文件 | +| 参考 | 描述 | 类型 | +|-----------|-------------|------| +| `` | 最新用户消息 | string | +| `` | 会话线程 ID | string | +| `` | 可选上传文件 | 文件数组 | -文件包括 `name`、`mimeType`,以及一个带签名的下载链接 `url`。 +### 文件属性 + +使用数组索引访问单个文件属性: + +| 属性 | 描述 | 类型 | +|----------|-------------|------| +| `` | 签名下载 URL | string | +| `` | 原始文件名 | string | +| `` | 文件大小(字节) | number | +| `` | MIME 类型 | string | +| `` | 上传时间戳(ISO 8601) | string | +| `` | URL 过期时间戳(ISO 8601) | string | ## 使用说明 -1. 每个工作流添加一个聊天触发器模块。 -2. 以聊天模式部署工作流。 -3. 分享部署链接——每次回复都会重用对话 ID,以便工作流保持上下文。 +1. 为每个工作流添加一个聊天触发器块。 +2. 在聊天模式下部署工作流。 +3. 分享部署链接——每次回复都会重用会话 ID,以便工作流可以保持上下文。 -构建器会阻止在同一工作流中添加多个聊天触发器模块。 +构建器会阻止在同一工作流中使用多个聊天触发器块。 diff --git a/apps/docs/i18n.lock b/apps/docs/i18n.lock index 4ef71f624c..4cd0491f18 100644 --- a/apps/docs/i18n.lock +++ b/apps/docs/i18n.lock @@ -2331,73 +2331,84 @@ checksums: content/98: 6bd60468d8cc072c5fe4214481fa9f60 content/99: a81d7cd4a644a0061dad3a5973b4fe06 content/100: 981447969a71fd038049e9d9f40f4f8c - content/101: 531941216d31cb1947367c3c02127baa - content/102: bf1afa789fdfa5815faaf43574341e90 - content/103: 5f2fe55d098d4e4f438af595708b2280 - content/104: 41b8f7cf8899a0e92e255a3f845f9584 - content/105: 61ddd890032078ffd2da931b1d153b6d - content/106: 7873aa7487bc3e8a4826d65c1760a4a0 - content/107: 98182d9aabe14d5bad43a5ee76a75eab - content/108: 2bdb01e4bcb08b1d99f192acf8e2fba7 - content/109: 7079d9c00b1e1882c329b7e9b8f74552 - content/110: 0f9d65eaf6e8de43c3d5fa7e62bc838d - content/111: 58c8e9d2d0ac37efd958203b8fbc8193 - content/112: 7859d36a7a6d0122c0818b28ee29aa3e - content/113: ce185e7b041b8f95ebc11370d3e0aad9 - content/114: 701e9bf4fd4d0669da0584eac5bd96e0 - content/115: d1bab8ec5a51a9da5464eb47e2a16b50 - content/116: da658275cc81a20f9cf7e4c66c7af1e3 - content/117: 377d7c99a5df4b72166946573f7210b8 - content/118: 3afc03a5ab1dc9db2bfa092b0ac4826a - content/119: 18ddfcaf2be4a6f1d9819407dad9ce7c - content/120: 2f6263b2e95f09f7e4842453f4bf4a0a - content/121: 4603578d6b314b662f45564a34ca430d - content/122: cf4c97eb254d0bd6ea6633344621c2c2 - content/123: 7b4640989fab002039936156f857eb21 - content/124: 65ca9f08745b47b4cce8ea8247d043bf - content/125: 162b4180611ff0a53b782e4dc8109293 - content/126: 6b367a189eb53cb198e3666023def89c - content/127: dbb2125cefcf618849600c1eccae8a64 - content/128: 04eedda0da3767b06e6017c559e05414 - content/129: 661688450606eb09d8faee1468e88331 - content/130: 8ff8367c3246103b3e3e02499e34ae0b - content/131: 44678bda9166f746da1d61b694ced482 - content/132: a5e75db27c0a901f4cacf6598f450e6c - content/133: d1bab8ec5a51a9da5464eb47e2a16b50 - content/134: da658275cc81a20f9cf7e4c66c7af1e3 - content/135: 377d7c99a5df4b72166946573f7210b8 - content/136: 3afc03a5ab1dc9db2bfa092b0ac4826a - content/137: 18ddfcaf2be4a6f1d9819407dad9ce7c - content/138: 2f6263b2e95f09f7e4842453f4bf4a0a - content/139: 4603578d6b314b662f45564a34ca430d - content/140: cf4c97eb254d0bd6ea6633344621c2c2 - content/141: 7b4640989fab002039936156f857eb21 - content/142: 65ca9f08745b47b4cce8ea8247d043bf - content/143: 162b4180611ff0a53b782e4dc8109293 - content/144: 6b367a189eb53cb198e3666023def89c - content/145: dbb2125cefcf618849600c1eccae8a64 - content/146: 04eedda0da3767b06e6017c559e05414 - content/147: 661688450606eb09d8faee1468e88331 - content/148: 8ff8367c3246103b3e3e02499e34ae0b - content/149: 44678bda9166f746da1d61b694ced482 - content/150: 192a89879084dd7a74a6f44bcecae958 - content/151: 41c2bb95317d7c0421817a2b1a68cc09 - content/152: 4c95f9fa55f698f220577380dff95011 - content/153: 9ef273d776aada1b2cff3452f08ff985 - content/154: 100e12673551d4ceb5b906b1b9c65059 - content/155: ce253674cd7c49320203cda2bdd3685b - content/156: 8910afcea8c205a28256eb30de6a1f26 - content/157: 4d7ad757d2c70fdff7834146d38dddd8 - content/158: a88260a5b5e23da73e4534376adeb193 - content/159: e5e2329cdc226186fe9d44767528a4a0 - content/160: 1773624e9ac3d5132b505894ef51977e - content/161: d62c9575cc66feec7589fba95c9f7aee - content/162: 7af652c5407ae7e156ab27b21a4f26d3 - content/163: 4aa69b29cca745389dea8cd74eba4f83 - content/164: 46877074b69519165997fa0968169611 - content/165: 2e81908c18033109ac82a054b3fafd3d - content/166: ecd571818ddf3d31b08b80a25958a662 - content/167: 7dcdf2fbf3fce3f94987046506e12a9b + content/101: c4a515e993f75288ac915094c80cc1df + content/102: 23e5e8228c45d58c3b16af1dccdaf598 + content/103: cab7213a23e59504d834d347c944b685 + content/104: fcb1568f1adf19ac5a706001a84cad91 + content/105: 7b486d79adc6500458cf8d4fb0c3ada8 + content/106: 531ba61df0fffebc44fc6ebe9b9b08b0 + content/107: 4267ac9375ea48bd994758885c0e05c9 + content/108: ae7b4696ba7e9edf4b192fbab90d8e45 + content/109: 0a7f8dfd0edb971c731dad1ce322c6e6 + content/110: 652b35852355ef0a9e0d7b634639cfc9 + content/111: 7afd8cd395c8e63bb1ede3538307de54 + content/112: 3304a33dfb626c6e2267c062e8956a9d + content/113: eea7828d6d712dc31d150bd438284b8a + content/114: 72a2b6306511832781715e503f0442d8 + content/115: fe19a895e0b360386bfefc269ca596a5 + content/116: d1bab8ec5a51a9da5464eb47e2a16b50 + content/117: f4b91b5931dff5faaa26581272e51b61 + content/118: 8f2d6066da0f1958aa55c6191f0a5be1 + content/119: 2a1c4e0626d1a10a59ae80490435f1c6 + content/120: a74834b7a623c3f5cc323d3ceeb5415f + content/121: f9da331cf341b7abe9fa4f1f021bb2ce + content/122: 006b642e4072cd86730b41503906c267 + content/123: 4570f2c71f19c1a89aa15c62abea2a6b + content/124: bbb4874da742521d5e07d05e17056a3a + content/125: 35f33ebf126b4a967bccf057d990d8ea + content/126: 519f8d2ed7a62f11b58f924d05a1bdf4 + content/127: 711f65ba5fbbc9204591770be00c0b76 + content/128: d1bab8ec5a51a9da5464eb47e2a16b50 + content/129: 9a2604ebbc848ffc92920e7ca9a1f5d5 + content/130: 2d9792d07b8887ecb00b4bddaa77760d + content/131: 67c60dcbdcb96ec99abda80aed195a39 + content/132: cd7923b20a896061bd8b437607a456ab + content/133: 6497acadfafd123e6501104bc339cb0b + content/134: 8d345f55098ed7fe8a79bfcd52780f56 + content/135: 7f2808ae7cc39c74fa1ea2e023e16db8 + content/136: 88f2cd0696cc8d78dc4b04549b26c13b + content/137: d1bab8ec5a51a9da5464eb47e2a16b50 + content/138: 4760068730805bd746ad2b7abae14be7 + content/139: 363a11a70ad2991f43e5c645343d24b1 + content/140: 76193afa096b6017eb981461fbd0af36 + content/141: 0e297ada3c58c15adbac6ede74fec86b + content/142: 08c8a11473671bde84d82b265f8f70cc + content/143: d1bab8ec5a51a9da5464eb47e2a16b50 + content/144: ac1580a83d54361553916f1518ca3eff + content/145: a10c4dc3ab88bfa976836d5a2fd21168 + content/146: e7ac414081f94d0ea1f36ef434392bb2 + content/147: 5235c1c6fe2a3956c0b55c2d1827fb98 + content/148: 074894d66efb4d36737a0735278e41cb + content/149: e5aa4e76b5d89aa3c2cda5255443eccd + content/150: b41c367dfb1527280df6c09bd32e626c + content/151: a5b2b0cf64941e8e962724a5728a5071 + content/152: 08c8a11473671bde84d82b265f8f70cc + content/153: d1bab8ec5a51a9da5464eb47e2a16b50 + content/154: da658275cc81a20f9cf7e4c66c7af1e3 + content/155: d87f098de2239cceabdb02513ec754c0 + content/156: 642e60a6fc14e6cca105684b0bc778fa + content/157: 41775a7801766af4164c8d93674e6cb2 + content/158: 3afc03a5ab1dc9db2bfa092b0ac4826a + content/159: 18ddfcaf2be4a6f1d9819407dad9ce7c + content/160: 0d9a26fefe257a86593e24043e803357 + content/161: 7ec562abd07f7db290d6f2accea4cd2d + content/162: ee8b87f59db1c578b95ad0198df084b7 + content/163: 4603578d6b314b662f45564a34ca430d + content/164: cf4c97eb254d0bd6ea6633344621c2c2 + content/165: 7b4640989fab002039936156f857eb21 + content/166: 65ca9f08745b47b4cce8ea8247d043bf + content/167: 162b4180611ff0a53b782e4dc8109293 + content/168: 6b367a189eb53cb198e3666023def89c + content/169: dbb2125cefcf618849600c1eccae8a64 + content/170: 04eedda0da3767b06e6017c559e05414 + content/171: 7b909e3f9bcefa3b6fa603301dd8f898 + content/172: 905105177a561dc57b6e7d138d5de93d + content/173: 64eac7b6860c90aeb6467d5ea873d4ef + content/174: 8ff8367c3246103b3e3e02499e34ae0b + content/175: 44678bda9166f746da1d61b694ced482 + content/176: aaa4a0a394c487d60d82c6d77c0fcfef + content/177: ecd571818ddf3d31b08b80a25958a662 + content/178: 7dcdf2fbf3fce3f94987046506e12a9b 27578f1315b6f1b7418d5e0d6042722e: meta/title: 8c555594662512e95f28e20d3880f186 content/0: 9218a2e190598690d0fc5c27c30f01bb @@ -2479,16 +2490,16 @@ checksums: content/76: 33b9b1e9744318597da4b925b0995be2 content/77: 6afe3b62e6d53c3dcd07149abcab4c05 content/78: b6363faee219321c16d41a9c3f8d3bdd - content/79: 08410ce9f0ec358b3c7230a56bc66399 + content/79: 3c5b351d25fb0639559eacdad545a0ed content/80: b8b23ab79a7eb32c6f8d5f49f43c51f6 content/81: be358297e2bbb9ab4689d11d072611d1 - content/82: 09fea7c0d742a0eefa77e982e848de6c + content/82: 414b9bf7d35039c6a17f4fb03d6b7431 content/83: 7d098f0349c782f389431377ee512e92 content/84: 22b39537f6a104803389469d211154e4 content/85: d9ec74ab28b264d76f797fdae7c8f3d3 content/86: f29d6bfd74ba3fee0b90180f620b4f47 content/87: 2a59466500b62e57481fe27692a3ed0f - content/88: cbbb123fc3a12bf2ab72dc1bbe373a6e + content/88: 94965695a02aea6c753448c21fd66b18 content/89: 7873aa7487bc3e8a4826d65c1760a4a0 content/90: 98182d9aabe14d5bad43a5ee76a75eab content/91: 67bfa8ae3e22d9a949f08c79a40b8df5 @@ -2500,11 +2511,11 @@ checksums: content/97: dae96b41f0c029b464f02ac65d3c5796 content/98: 41c2bb95317d7c0421817a2b1a68cc09 content/99: 4c95f9fa55f698f220577380dff95011 - content/100: 6695bd47a05f9963134d8a71abb3d298 + content/100: e674c5e6ecaf4dae9fc93e328b8a57c4 content/101: 100e12673551d4ceb5b906b1b9c65059 content/102: ce253674cd7c49320203cda2bdd3685b content/103: 94d4346a735149c2a83f6d2a21b8ab4c - content/104: 3ee4b16b8204ef3b5b7c0322ff636fab + content/104: 869fd72c8911057ee0696f068fa22e35 content/105: 450265802cb0ba5b435b74b9cac1bf23 content/106: b735ede8764e4b2dfb25967e33ab5143 content/107: 0f881e586a03c4b916456c73fad48358 @@ -2834,10 +2845,20 @@ checksums: content/30: dbbf313837f13ddfa4a8843d71cb9cc4 content/31: cf10560ae6defb8ee5da344fc6509f6e content/32: c5dc6e5de6e45b17ee1f5eb567a18e2f - content/33: aa47ff01b631252f024eaaae0c773e42 - content/34: 1266d1c7582bb617cdef56857be34f30 - content/35: c2cef2688104adaf6641092f43d4969a - content/36: 089fc64b4589b2eaa371de7e04c4aed9 + content/33: 332dab0588fb35dabb64b674ba6120eb + content/34: 714b3f99b0a8686bbb3434deb1f682b3 + content/35: ba18ac99184b17d7e49bd1abdc814437 + content/36: bed2b629274d55c38bd637e6a28dbc4a + content/37: 71487ae6f6fb1034d1787456de442e6d + content/38: 137d9874cf5ec8d09bd447f224cc7a7c + content/39: 6b5b4c3b2f98b8fc7dd908fef2605ce8 + content/40: 3af6812662546ce647a55939241fd88e + content/41: 6a4d7f0ccb8c28303251d1ef7b3dcca7 + content/42: 5dce779f77cc2b0abf12802a833df499 + content/43: aa47ff01b631252f024eaaae0c773e42 + content/44: 1266d1c7582bb617cdef56857be34f30 + content/45: c2cef2688104adaf6641092f43d4969a + content/46: 089fc64b4589b2eaa371de7e04c4aed9 722959335ba76c9d0097860e2ad5a952: meta/title: 9842d3af9cf52b7f5ab4a6ed4f2b23d2 content/0: 112d20eb578be8c0f59a13c819bf7716 @@ -4068,11 +4089,13 @@ checksums: content/3: 78cfe3bc9c911dd9aa75f053f768707d content/4: d5c510cc37588bf8f3d9a91543544721 content/5: a09e8940e139c0b84886fa7f16f3e690 - content/6: 33f032ae58bee4c0e244491b110a22fe - content/7: ef92830705e75d566cb1c6bbc18a2c82 - content/8: 8f06e4f0147241cadfbae88fb2fc2057 - content/9: c2d4cc3ecf06ac3c07f57c83095e461b - content/10: 3d8114d48bbc82967b2e7c881f571dc0 + content/6: 4ec178f03b8b1dd035d0a2941d01b967 + content/7: c8a934e0c369887defde32b93786799b + content/8: 36205863ef80144682e36623ba455c7c + content/9: 1423b72abb907e40921f8f4ec40a22c2 + content/10: 8f06e4f0147241cadfbae88fb2fc2057 + content/11: c2d4cc3ecf06ac3c07f57c83095e461b + content/12: 3d8114d48bbc82967b2e7c881f571dc0 c1571f6a328a5083bc542ae1ffc98fac: meta/title: 41fc753f4232b5628873660d94faba90 meta/description: b108bba63132a8a2ddbff6b5264ef993 @@ -4081,30 +4104,44 @@ checksums: content/2: 3c7457d4671bdca75eb8847e77b3d09a content/3: b3c762557a1a308f3531ef1f19701807 content/4: bf29da79344f37eeadd4c176aa19b8ff - content/5: ae52879ebefa5664a6b7bf8ce5dd57ab - content/6: ce487c9bc7a730e7d9da4a87b8eaa0a6 - content/7: e73f4b831f5b77c71d7d86c83abcbf11 - content/8: 07e064793f3e0bbcb02c4dc6083b6daa - content/9: a702b191c3f94458bee880d33853e0cb - content/10: c497057cbb9dd53599071f8550f327cd - content/11: cc6e48f85d5c6bfc05f846341f2d5cc9 - content/12: 8a80a6a97da9bf375fac565f1caabb49 - content/13: 098cc8e062187eb877fe5e172a4aa467 - content/14: e452a7cb33d7cf2f7cf1804703edaa20 - content/15: 466cfd61b1d0fcd8fc93d867dfd0f3e3 - content/16: 377572316021236994f444e88949ef34 - content/17: 54852933b2cbe3deb3b1c3059dba6a15 - content/18: 9e66b045763abe053a3ba8d2c23e9aa1 - content/19: d34f0950591e3beb085e99db64d07d2f - content/20: 8677ef07618f7289b04fef3cce8bf745 - content/21: c0e6d2790e369569e7f272a5ec9ae21a - content/22: 93643a0d9d9745f131e4eabf7ead2018 - content/23: 89c7da6d2e8fbc25e303a7381e147237 - content/24: a8ec63597dc3a3564bc5f0c3a6e5f42c - content/25: 379618989b6cd427b319cfdab523297d - content/26: bc4c2e699a7514771276e90e9aee53ba - content/27: 38e14193b679ef774c3db93d399e700e - content/28: ce110ab5da3ff96f8cbf96ce3376fc51 - content/29: 83f9b3ab46b0501c8eb3989bec3f4f1b - content/30: e00be80effb71b0acb014f9aa53dfbe1 - content/31: 847a381137856ded9faa5994fbc489fb + content/5: d9ee91aa417a55e8cb1e0c5f4e4ca83b + content/6: b747c4e9aff28c3efba1c8888ba9b9f9 + content/7: d16a981c85afb9da140d46d4b8d51e06 + content/8: ff071011d7ed2f6c9b98e1bb18c0edf5 + content/9: e73f4b831f5b77c71d7d86c83abcbf11 + content/10: 07e064793f3e0bbcb02c4dc6083b6daa + content/11: a702b191c3f94458bee880d33853e0cb + content/12: c497057cbb9dd53599071f8550f327cd + content/13: cc6e48f85d5c6bfc05f846341f2d5cc9 + content/14: 8a80a6a97da9bf375fac565f1caabb49 + content/15: 098cc8e062187eb877fe5e172a4aa467 + content/16: e452a7cb33d7cf2f7cf1804703edaa20 + content/17: 466cfd61b1d0fcd8fc93d867dfd0f3e3 + content/18: 377572316021236994f444e88949ef34 + content/19: 54852933b2cbe3deb3b1c3059dba6a15 + content/20: 9e66b045763abe053a3ba8d2c23e9aa1 + content/21: d34f0950591e3beb085e99db64d07d2f + content/22: 8677ef07618f7289b04fef3cce8bf745 + content/23: c0e6d2790e369569e7f272a5ec9ae21a + content/24: 93643a0d9d9745f131e4eabf7ead2018 + content/25: 89c7da6d2e8fbc25e303a7381e147237 + content/26: a8ec63597dc3a3564bc5f0c3a6e5f42c + content/27: 379618989b6cd427b319cfdab523297d + content/28: bc4c2e699a7514771276e90e9aee53ba + content/29: 38e14193b679ef774c3db93d399e700e + content/30: ce110ab5da3ff96f8cbf96ce3376fc51 + content/31: 83f9b3ab46b0501c8eb3989bec3f4f1b + content/32: 8eafc1489817e2b31bb2dde5cf45bb17 + content/33: f7c188211a6c76460e159b65a8dae43f + content/34: 8a64c1f76a0bb16a40ba0eeaf6141dd1 + content/35: fb03882a39682b35fd8ef5574a110020 + content/36: cb234805a1738585c4725c6519b212bc + content/37: 3dee2b82795a6dab076cbcdc59a03965 + content/38: 950899e381ce7b7c73e98ad5b15562a0 + content/39: c8b1f8cd971687fc5d2b78c28c2b4050 + content/40: c8a934e0c369887defde32b93786799b + content/41: dc440445fa0173b8d47905205307b3a1 + content/42: 42cef4d960a45562b89682cc0a563fe5 + content/43: 0bbfb30bad650027ae86bb1a0baea081 + content/44: e00be80effb71b0acb014f9aa53dfbe1 + content/45: 847a381137856ded9faa5994fbc489fb