TypeScript/JavaScript SDK
Le SDK officiel TypeScript/JavaScript pour Worxflow offre une sécurité de type complÚte et prend en charge les environnements Node.js et navigateur, vous permettant d'exécuter des workflows par programmation depuis vos applications Node.js, applications web et autres environnements JavaScript.
Le SDK TypeScript offre une sécurité de type complÚte, la prise en charge de l'exécution asynchrone, une limitation automatique du débit avec backoff exponentiel et le suivi d'utilisation.
Installation
Installez le SDK en utilisant votre gestionnaire de paquets préféré :
npm install simstudio-ts-sdkyarn add simstudio-ts-sdkbun add simstudio-ts-sdkDémarrage rapide
Voici un exemple simple pour commencer :
import { SimStudioClient } from 'simstudio-ts-sdk';
// Initialize the client
const client = new SimStudioClient({
apiKey: 'your-api-key-here',
baseUrl: 'https://worxflow.ai' // optional, defaults to https://worxflow.ai
});
// Execute a workflow
try {
const result = await client.executeWorkflow('workflow-id');
console.log('Workflow executed successfully:', result);
} catch (error) {
console.error('Workflow execution failed:', error);
}Référence de l'API
SimStudioClient
Constructeur
new SimStudioClient(config: SimStudioConfig)Configuration :
config.apiKey(string) : votre clé API Simconfig.baseUrl(string, optionnel) : URL de base pour l'API Worxflow (par défauthttps://worxflow.ai)
Méthodes
executeWorkflow()
Exécuter un workflow avec des données d'entrée optionnelles.
const result = await client.executeWorkflow('workflow-id', {
input: { message: 'Hello, world!' },
timeout: 30000 // 30 seconds
});ParamĂštres :
workflowId(string) : L'ID du workflow à exécuteroptions(ExecutionOptions, optionnel) :input(any) : Données d'entrée à transmettre au workflowtimeout(number) : Délai d'expiration en millisecondes (par défaut : 30000)stream(boolean) : Activer les réponses en streaming (par défaut : false)selectedOutputs(string[]) : Bloquer les sorties à diffuser au formatblockName.attribute(par exemple,["agent1.content"])async(boolean) : Exécuter de maniÚre asynchrone (par défaut : false)
Retourne : Promise<WorkflowExecutionResult | AsyncExecutionResult>
Lorsque async: true, retourne immédiatement avec un ID de tùche pour l'interrogation. Sinon, attend la fin de l'exécution.
getWorkflowStatus()
Obtenir le statut d'un workflow (statut de déploiement, etc.).
const status = await client.getWorkflowStatus('workflow-id');
console.log('Is deployed:', status.isDeployed);ParamĂštres :
workflowId(string) : L'ID du workflow
Retourne : Promise<WorkflowStatus>
validateWorkflow()
Valider qu'un workflow est prĂȘt pour l'exĂ©cution.
const isReady = await client.validateWorkflow('workflow-id');
if (isReady) {
// Workflow is deployed and ready
}ParamĂštres :
workflowId(string) : L'ID du workflow
Retourne : Promise<boolean>
getJobStatus()
Obtenir le statut d'une exécution de tùche asynchrone.
const status = await client.getJobStatus('task-id-from-async-execution');
console.log('Status:', status.status); // 'queued', 'processing', 'completed', 'failed'
if (status.status === 'completed') {
console.log('Output:', status.output);
}ParamĂštres :
taskId(string) : L'ID de tùche retourné par l'exécution asynchrone
Retourne : Promise<JobStatus>
Champs de réponse :
success(boolean) : Indique si la requĂȘte a rĂ©ussitaskId(string) : L'ID de la tĂąchestatus(string) : L'un des statuts suivants :'queued','processing','completed','failed','cancelled'metadata(object) : ContientstartedAt,completedAt, etdurationoutput(any, optionnel) : La sortie du workflow (une fois terminĂ©)error(any, optionnel) : DĂ©tails de l'erreur (en cas d'Ă©chec)estimatedDuration(number, optionnel) : DurĂ©e estimĂ©e en millisecondes (lorsqu'en traitement/en file d'attente)
executeWithRetry()
Exécute un workflow avec une nouvelle tentative automatique en cas d'erreurs de limite de débit en utilisant un backoff exponentiel.
const result = await client.executeWithRetry('workflow-id', {
input: { message: 'Hello' },
timeout: 30000
}, {
maxRetries: 3, // Maximum number of retries
initialDelay: 1000, // Initial delay in ms (1 second)
maxDelay: 30000, // Maximum delay in ms (30 seconds)
backoffMultiplier: 2 // Exponential backoff multiplier
});ParamĂštres :
workflowId(string) : L'identifiant du workflow Ă exĂ©cuteroptions(ExecutionOptions, facultatif) : Identique ĂexecuteWorkflow()retryOptions(RetryOptions, facultatif) :maxRetries(number) : Nombre maximum de tentatives (par dĂ©faut : 3)initialDelay(number) : DĂ©lai initial en ms (par dĂ©faut : 1000)maxDelay(number) : DĂ©lai maximum en ms (par dĂ©faut : 30000)backoffMultiplier(number) : Multiplicateur de backoff (par dĂ©faut : 2)
Retourne : Promise<WorkflowExecutionResult | AsyncExecutionResult>
La logique de nouvelle tentative utilise un backoff exponentiel (1s â 2s â 4s â 8s...) avec une variation alĂ©atoire de ±25 % pour Ă©viter l'effet de rafale. Si l'API fournit un en-tĂȘte retry-after, celui-ci sera utilisĂ© Ă la place.
getRateLimitInfo()
Obtient les informations actuelles sur les limites de débit à partir de la derniÚre réponse de l'API.
const rateLimitInfo = client.getRateLimitInfo();
if (rateLimitInfo) {
console.log('Limit:', rateLimitInfo.limit);
console.log('Remaining:', rateLimitInfo.remaining);
console.log('Reset:', new Date(rateLimitInfo.reset * 1000));
}Retourne : RateLimitInfo | null
getUsageLimits()
Obtient les limites d'utilisation actuelles et les informations de quota pour votre compte.
const limits = await client.getUsageLimits();
console.log('Sync requests remaining:', limits.rateLimit.sync.remaining);
console.log('Async requests remaining:', limits.rateLimit.async.remaining);
console.log('Current period cost:', limits.usage.currentPeriodCost);
console.log('Plan:', limits.usage.plan);Retourne : Promise<UsageLimits>
Structure de la réponse :
{
success: boolean
rateLimit: {
sync: {
isLimited: boolean
limit: number
remaining: number
resetAt: string
}
async: {
isLimited: boolean
limit: number
remaining: number
resetAt: string
}
authType: string // 'api' or 'manual'
}
usage: {
currentPeriodCost: number
limit: number
plan: string // e.g., 'free', 'pro'
}
}setApiKey()
Met à jour la clé API.
client.setApiKey('new-api-key');setBaseUrl()
Met Ă jour l'URL de base.
client.setBaseUrl('https://my-custom-domain.com');Types
WorkflowExecutionResult
interface WorkflowExecutionResult {
success: boolean;
output?: any;
error?: string;
logs?: any[];
metadata?: {
duration?: number;
executionId?: string;
[key: string]: any;
};
traceSpans?: any[];
totalDuration?: number;
}AsyncExecutionResult
interface AsyncExecutionResult {
success: boolean;
taskId: string;
status: 'queued';
createdAt: string;
links: {
status: string; // e.g., "/api/jobs/{taskId}"
};
}WorkflowStatus
interface WorkflowStatus {
isDeployed: boolean;
deployedAt?: string;
isPublished: boolean;
needsRedeployment: boolean;
}RateLimitInfo
interface RateLimitInfo {
limit: number;
remaining: number;
reset: number;
retryAfter?: number;
}UsageLimits
interface UsageLimits {
success: boolean;
rateLimit: {
sync: {
isLimited: boolean;
limit: number;
remaining: number;
resetAt: string;
};
async: {
isLimited: boolean;
limit: number;
remaining: number;
resetAt: string;
};
authType: string;
};
usage: {
currentPeriodCost: number;
limit: number;
plan: string;
};
}SimStudioError
class SimStudioError extends Error {
code?: string;
status?: number;
}Codes d'erreur courants :
UNAUTHORIZED: ClĂ© API invalideTIMEOUT: DĂ©lai d'attente de la requĂȘte dĂ©passĂ©RATE_LIMIT_EXCEEDED: Limite de dĂ©bit dĂ©passĂ©eUSAGE_LIMIT_EXCEEDED: Limite d'utilisation dĂ©passĂ©eEXECUTION_ERROR: Ăchec de l'exĂ©cution du workflow
Exemples
Exécution basique d'un workflow
Configurez le SimStudioClient avec votre clé API.
VĂ©rifiez si le workflow est dĂ©ployĂ© et prĂȘt pour l'exĂ©cution.
Lancez le workflow avec vos données d'entrée.
Traitez le résultat de l'exécution et gérez les éventuelles erreurs.
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function runWorkflow() {
try {
// Check if workflow is ready
const isReady = await client.validateWorkflow('my-workflow-id');
if (!isReady) {
throw new Error('Workflow is not deployed or ready');
}
// Execute the workflow
const result = await client.executeWorkflow('my-workflow-id', {
input: {
message: 'Process this data',
userId: '12345'
}
});
if (result.success) {
console.log('Output:', result.output);
console.log('Duration:', result.metadata?.duration);
} else {
console.error('Workflow failed:', result.error);
}
} catch (error) {
console.error('Error:', error);
}
}
runWorkflow();Gestion des erreurs
Gérez différents types d'erreurs qui peuvent survenir pendant l'exécution du workflow :
import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeWithErrorHandling() {
try {
const result = await client.executeWorkflow('workflow-id');
return result;
} catch (error) {
if (error instanceof SimStudioError) {
switch (error.code) {
case 'UNAUTHORIZED':
console.error('Invalid API key');
break;
case 'TIMEOUT':
console.error('Workflow execution timed out');
break;
case 'USAGE_LIMIT_EXCEEDED':
console.error('Usage limit exceeded');
break;
case 'INVALID_JSON':
console.error('Invalid JSON in request body');
break;
default:
console.error('Workflow error:', error.message);
}
} else {
console.error('Unexpected error:', error);
}
throw error;
}
}Configuration de l'environnement
Configurez le client en utilisant des variables d'environnement :
import { SimStudioClient } from 'simstudio-ts-sdk';
// Development configuration
const apiKey = process.env.SIM_API_KEY;
if (!apiKey) {
throw new Error('SIM_API_KEY environment variable is required');
}
const client = new SimStudioClient({
apiKey,
baseUrl: process.env.SIM_BASE_URL // optional
});import { SimStudioClient } from 'simstudio-ts-sdk';
// Production configuration with validation
const apiKey = process.env.SIM_API_KEY;
if (!apiKey) {
throw new Error('SIM_API_KEY environment variable is required');
}
const client = new SimStudioClient({
apiKey,
baseUrl: process.env.SIM_BASE_URL || 'https://worxflow.ai'
});Intégration avec Express de Node.js
Intégration avec un serveur Express.js :
import express from 'express';
import { SimStudioClient } from 'simstudio-ts-sdk';
const app = express();
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
app.use(express.json());
app.post('/execute-workflow', async (req, res) => {
try {
const { workflowId, input } = req.body;
const result = await client.executeWorkflow(workflowId, {
input,
timeout: 60000
});
res.json({
success: true,
data: result
});
} catch (error) {
console.error('Workflow execution error:', error);
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
});
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});Route API Next.js
Utilisation avec les routes API Next.js :
// pages/api/workflow.ts or app/api/workflow/route.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { workflowId, input } = req.body;
const result = await client.executeWorkflow(workflowId, {
input,
timeout: 30000
});
res.status(200).json(result);
} catch (error) {
console.error('Error executing workflow:', error);
res.status(500).json({
error: 'Failed to execute workflow'
});
}
}Utilisation dans le navigateur
Utilisation dans le navigateur (avec une configuration CORS appropriée) :
import { SimStudioClient } from 'simstudio-ts-sdk';
// Note: In production, use a proxy server to avoid exposing API keys
const client = new SimStudioClient({
apiKey: 'your-public-api-key', // Use with caution in browser
baseUrl: 'https://worxflow.ai'
});
async function executeClientSideWorkflow() {
try {
const result = await client.executeWorkflow('workflow-id', {
input: {
userInput: 'Hello from browser'
}
});
console.log('Workflow result:', result);
// Update UI with result
document.getElementById('result')!.textContent =
JSON.stringify(result.output, null, 2);
} catch (error) {
console.error('Error:', error);
}
}
// Attach to button click
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.
Exemple de hook React
Créer un hook React personnalisé pour l'exécution de workflow :
import { useState, useCallback } from 'react';
import { SimStudioClient, WorkflowExecutionResult } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
interface UseWorkflowResult {
result: WorkflowExecutionResult | null;
loading: boolean;
error: Error | null;
executeWorkflow: (workflowId: string, input?: any) => Promise<void>;
}
export function useWorkflow(): UseWorkflowResult {
const [result, setResult] = useState<WorkflowExecutionResult | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const executeWorkflow = useCallback(async (workflowId: string, input?: any) => {
setLoading(true);
setError(null);
setResult(null);
try {
const workflowResult = await client.executeWorkflow(workflowId, {
input,
timeout: 30000
});
setResult(workflowResult);
} catch (err) {
setError(err instanceof Error ? err : new Error('Unknown error'));
} finally {
setLoading(false);
}
}, []);
return {
result,
loading,
error,
executeWorkflow
};
}
// Usage in component
function WorkflowComponent() {
const { result, loading, error, executeWorkflow } = useWorkflow();
const handleExecute = () => {
executeWorkflow('my-workflow-id', {
message: 'Hello from React!'
});
};
return (
<div>
<button onClick={handleExecute} disabled={loading}>
{loading ? 'Executing...' : 'Execute Workflow'}
</button>
{error && <div>Error: {error.message}</div>}
{result && (
<div>
<h3>Result:</h3>
<pre>{JSON.stringify(result, null, 2)}</pre>
</div>
)}
</div>
);
}Exécution asynchrone de workflow
Exécuter des workflows de maniÚre asynchrone pour les tùches de longue durée :
import { SimStudioClient, AsyncExecutionResult } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeAsync() {
try {
// Start async execution
const result = await client.executeWorkflow('workflow-id', {
input: { data: 'large dataset' },
async: true // Execute asynchronously
});
// Check if result is an async execution
if ('taskId' in result) {
console.log('Task ID:', result.taskId);
console.log('Status endpoint:', 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
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);
} else {
console.error('Workflow failed:', status.error);
}
}
} catch (error) {
console.error('Error:', error);
}
}
executeAsync();Limitation de débit et nouvelle tentative
Gérer automatiquement les limites de débit avec backoff exponentiel :
import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeWithRetryHandling() {
try {
// Automatically retries on rate limit
const result = await client.executeWithRetry('workflow-id', {
input: { message: 'Process this' }
}, {
maxRetries: 5,
initialDelay: 1000,
maxDelay: 60000,
backoffMultiplier: 2
});
console.log('Success:', result);
} catch (error) {
if (error instanceof SimStudioError && error.code === 'RATE_LIMIT_EXCEEDED') {
console.error('Rate limit exceeded after all retries');
// Check rate limit info
const rateLimitInfo = client.getRateLimitInfo();
if (rateLimitInfo) {
console.log('Rate limit resets at:', new Date(rateLimitInfo.reset * 1000));
}
}
}
}Surveillance d'utilisation
Surveiller l'utilisation et les limites de votre compte :
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
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('\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);
console.log('\n=== Usage ===');
console.log('Current period cost:
### Streaming Workflow Execution
Execute workflows with real-time streaming responses:
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeWithStreaming() {
try {
// Activer le streaming pour des sorties de blocs spécifiques
const result = await client.executeWorkflow('workflow-id', {
input: { message: 'Compter jusqu'Ă cinq' },
stream: true,
selectedOutputs: ['agent1.content'] // Utiliser le format blockName.attribute
});
console.log('Résultat du workflow :', result);
} catch (error) {
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":", deux"}
data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}}
data: [DONE]React Streaming Example:
import { useState, useEffect } from 'react';
function StreamingWorkflow() {
const [output, setOutput] = useState('');
const [loading, setLoading] = useState(false);
const executeStreaming = async () => {
setLoading(true);
setOutput('');
// IMPORTANT: Make this API call from your backend server, not the browser
// Never expose your API key in client-side code
const response = await fetch('https://worxflow.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
},
body: JSON.stringify({
message: 'Generate a story',
stream: true,
selectedOutputs: ['agent1.content']
})
});
const reader = response.body?.getReader();
const decoder = new TextDecoder();
while (reader) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') {
setLoading(false);
break;
}
try {
const parsed = JSON.parse(data);
if (parsed.chunk) {
setOutput(prev => prev + parsed.chunk);
} else if (parsed.event === 'done') {
console.log('Execution complete:', parsed.metadata);
}
} catch (e) {
// Skip invalid JSON
}
}
}
}
};
return (
<div>
<button onClick={executeStreaming} disabled={loading}>
{loading ? 'Génération en cours...' : 'Démarrer le streaming'}
</button>
<div style={{ whiteSpace: 'pre-wrap' }}>{output}</div>
</div>
);
}Getting Your API Key
Navigate to Sim and log in to your account.
Navigate to the workflow you want to execute programmatically.
Click on "Deploy" to deploy your workflow if it hasn't been deployed yet.
During the deployment process, select or create an API key.
Copy the API key to use in your TypeScript/JavaScript application.
Keep your API key secure and never commit it to version control. Use environment variables or secure configuration management.
Requirements
- Node.js 16+
- TypeScript 5.0+ (for TypeScript projects)
TypeScript Support
The SDK is written in TypeScript and provides full type safety:
import {
SimStudioClient,
WorkflowExecutionResult,
WorkflowStatus,
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: 'Bonjour, TypeScript !'
}
});
// Type-safe status checking
const status: WorkflowStatus = await client.getWorkflowStatus('workflow-id');License
Apache-2.0