TypeScript
Официальный TypeScript/JavaScript SDK для AACFlow обеспечивает полную типобезопасность и поддерживает как Node.js, так и браузерные среды, позволяя выполнять рабочие процессы программно из ваших Node.js-приложений, веб-приложений и других JavaScript-сред.
TypeScript SDK обеспечивает полную типобезопасность, поддержку асинхронного выполнения, автоматическое ограничение скорости с экспоненциальной задержкой и отслеживание использования.
Установка
Установите SDK с помощью предпочитаемого менеджера пакетов:
npm install aacflow-ts-sdkyarn add aacflow-ts-sdkbun add aacflow-ts-sdkБыстрый старт
Вот простой пример, чтобы начать работу:
import { AACFlowClient } from 'aacflow-ts-sdk';
// Инициализируем клиент
const client = new AACFlowClient({
apiKey: 'your-api-key-here',
baseUrl: 'https://aacflow.io' // опционально, по умолчанию https://aacflow.io
});
// Выполняем рабочий процесс
try {
const result = await client.executeWorkflow('workflow-id');
console.log('Рабочий процесс выполнен успешно:', result);
} catch (error) {
console.error('Выполнение рабочего процесса не удалось:', error);
}Справочник по API
AACFlowClient
Конструктор
new AACFlowClient(config: AACFlowConfig)Конфигурация:
config.apiKey(string): Ваш API-ключ AACFlowconfig.baseUrl(string, опционально): Базовый URL для API AACFlow (по умолчаниюhttps://aacflow.io)
Методы
executeWorkflow()
Выполняет рабочий процесс с опциональными входными данными.
const result = await client.executeWorkflow('workflow-id', { message: 'Hello, world!' }, {
timeout: 30000 // 30 секунд
});Параметры:
workflowId(string): ID рабочего процесса для выполненияinput(any, опционально): Входные данные для передачи в рабочий процессoptions(ExecutionOptions, опционально):timeout(number): Таймаут в миллисекундах (по умолчанию: 30000)stream(boolean): Включить потоковые ответы (по умолчанию: false)selectedOutputs(string[]): Выходные данные блоков для потоковой передачи в форматеblockName.attribute(например,["agent1.content"])async(boolean): Выполнять асинхронно (по умолчанию: false)
Возвращает: Promise<WorkflowExecutionResult | AsyncExecutionResult>
Когда async: true, возвращает немедленно с ID задачи для опроса. В противном случае ожидает завершения.
getWorkflowStatus()
Получает статус рабочего процесса (статус развертывания и т.д.).
const status = await client.getWorkflowStatus('workflow-id');
console.log('Развернут:', status.isDeployed);Параметры:
workflowId(string): ID рабочего процесса
Возвращает: Promise<WorkflowStatus>
validateWorkflow()
Проверяет, готов ли рабочий процесс к выполнению.
const isReady = await client.validateWorkflow('workflow-id');
if (isReady) {
// Рабочий процесс развернут и готов
}Параметры:
workflowId(string): ID рабочего процесса
Возвращает: Promise<boolean>
getJobStatus()
Получает статус асинхронного выполнения задачи.
const status = await client.getJobStatus('task-id-from-async-execution');
console.log('Статус:', status.status); // 'queued', 'processing', 'completed', 'failed'
if (status.status === 'completed') {
console.log('Выходные данные:', status.output);
}Параметры:
taskId(string): ID задачи, возвращенный из асинхронного выполнения
Возвращает: Promise<JobStatus>
Поля ответа:
success(boolean): Успешен ли запросtaskId(string): ID задачиstatus(string): Один из'queued','processing','completed','failed','cancelled'metadata(object): СодержитstartedAt,completedAtиdurationoutput(any, опционально): Выходные данные рабочего процесса (при завершении)error(any, опционально): Детали ошибки (при сбое)estimatedDuration(number, опционально): Предполагаемая продолжительность в миллисекундах (при обработке/в очереди)
executeWithRetry()
Выполняет рабочий процесс с автоматической повторной попыткой при ошибках ограничения скорости с использованием экспоненциальной задержки.
const result = await client.executeWithRetry('workflow-id', { message: 'Hello' }, {
timeout: 30000
}, {
maxRetries: 3, // Максимальное количество повторных попыток
initialDelay: 1000, // Начальная задержка в мс (1 секунда)
maxDelay: 30000, // Максимальная задержка в мс (30 секунд)
backoffMultiplier: 2 // Множитель экспоненциальной задержки
});Параметры:
workflowId(string): ID рабочего процесса для выполненияinput(any, опционально): Входные данные для передачи в рабочий процессoptions(ExecutionOptions, опционально): То же, что иexecuteWorkflow()retryOptions(RetryOptions, опционально):maxRetries(number): Максимальное количество повторных попыток (по умолчанию: 3)initialDelay(number): Начальная задержка в мс (по умолчанию: 1000)maxDelay(number): Максимальная задержка в мс (по умолчанию: 30000)backoffMultiplier(number): Множитель задержки (по умолчанию: 2)
Возвращает: Promise<WorkflowExecutionResult | AsyncExecutionResult>
Логика повторных попыток использует экспоненциальную задержку (1с → 2с → 4с → 8с...) с ±25% случайным отклонением для предотвращения "стадного эффекта". Если API предоставляет заголовок retry-after, он будет использован вместо этого.
getRateLimitInfo()
Получает текущую информацию об ограничении скорости из последнего ответа API.
const rateLimitInfo = client.getRateLimitInfo();
if (rateLimitInfo) {
console.log('Лимит:', rateLimitInfo.limit);
console.log('Осталось:', rateLimitInfo.remaining);
console.log('Сброс:', new Date(rateLimitInfo.reset * 1000));
}Возвращает: RateLimitInfo | null
getUsageLimits()
Получает текущие лимиты использования и информацию о квоте для вашей учетной записи.
const limits = await client.getUsageLimits();
console.log('Осталось синхронных запросов:', limits.rateLimit.sync.remaining);
console.log('Осталось асинхронных запросов:', limits.rateLimit.async.remaining);
console.log('Текущая стоимость периода:', limits.usage.currentPeriodCost);
console.log('Тариф:', limits.usage.plan);Возвращает: Promise<UsageLimits>
Структура ответа:
{
success: boolean
rateLimit: {
sync: {
isLimited: boolean
limit: number
remaining: number
resetAt: string
}
async: {
isLimited: boolean
limit: number
remaining: number
resetAt: string
}
authType: string // 'api' или 'manual'
}
usage: {
currentPeriodCost: number
limit: number
plan: string // например, 'free', 'pro'
}
}setApiKey()
Обновляет API-ключ.
client.setApiKey('new-api-key');setBaseUrl()
Обновляет базовый URL.
client.setBaseUrl('https://my-custom-domain.com');Типы
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; // например, "/api/jobs/{taskId}"
};
}WorkflowStatus
interface WorkflowStatus {
isDeployed: boolean;
deployedAt?: string;
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;
};
}AACFlowError
class AACFlowError extends Error {
code?: string;
status?: number;
}Распространенные коды ошибок:
UNAUTHORIZED: Неверный API-ключTIMEOUT: Превышено время ожидания запросаRATE_LIMIT_EXCEEDED: Превышено ограничение скоростиUSAGE_LIMIT_EXCEEDED: Превышен лимит использованияEXECUTION_ERROR: Сбой выполнения рабочего процесса
Примеры
Базовое выполнение рабочего процесса
Настройте AACFlowClient с вашим API-ключом.
Проверьте, развернут ли рабочий процесс и готов ли к выполнению.
Запустите рабочий процесс с вашими входными данными.
Обработайте результат выполнения и обработайте любые ошибки.
import { AACFlowClient } from 'aacflow-ts-sdk';
const client = new AACFlowClient({
apiKey: process.env.AACFLOW_API_KEY!
});
async function runWorkflow() {
try {
// Проверьте, готов ли рабочий процесс
const isReady = await client.validateWorkflow('my-workflow-id');
if (!isReady) {
throw new Error('Workflow is not deployed or ready');
}
// Выполните рабочий процесс
const result = await client.executeWorkflow('my-workflow-id', {
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();Обработка ошибок
Обрабатывайте различные типы ошибок, которые могут возникнуть во время выполнения рабочего процесса:
import { AACFlowClient, AACFlowError } from 'aacflow-ts-sdk';
const client = new AACFlowClient({
apiKey: process.env.AACFLOW_API_KEY!
});
async function executeWithErrorHandling() {
try {
const result = await client.executeWorkflow('workflow-id');
return result;
} catch (error) {
if (error instanceof AACFlowError) {
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;
}
}Конфигурация окружения
Настройте клиент с использованием переменных окружения:
import { AACFlowClient } from 'aacflow-ts-sdk';
// Конфигурация для разработки
const apiKey = process.env.AACFLOW_API_KEY;
if (!apiKey) {
throw new Error('AACFLOW_API_KEY environment variable is required');
}
const client = new AACFlowClient({
apiKey,
baseUrl: process.env.SIM_BASE_URL // опционально
});import { AACFlowClient } from 'aacflow-ts-sdk';
// Конфигурация для продакшена с валидацией
const apiKey = process.env.AACFLOW_API_KEY;
if (!apiKey) {
throw new Error('AACFLOW_API_KEY environment variable is required');
}
const client = new AACFlowClient({
apiKey,
baseUrl: process.env.SIM_BASE_URL || 'https://aacflow.io'
});Интеграция с Node.js Express
Интегрируйте с сервером Express.js:
import express from 'express';
import { AACFlowClient } from 'aacflow-ts-sdk';
const app = express();
const client = new AACFlowClient({
apiKey: process.env.AACFLOW_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');
});Next.js API Route
Используйте с Next.js API routes:
// pages/api/workflow.ts или app/api/workflow/route.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { AACFlowClient } from 'aacflow-ts-sdk';
const client = new AACFlowClient({
apiKey: process.env.AACFLOW_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'
});
}
}Использование в браузере
Используйте в браузере (с правильной конфигурацией CORS):
import { AACFlowClient } from 'aacflow-ts-sdk';
// Примечание: В продакшене используйте прокси-сервер, чтобы избежать раскрытия API-ключей
const client = new AACFlowClient({
apiKey: 'your-public-api-key', // Используйте с осторожностью в браузере
baseUrl: 'https://aacflow.io'
});
async function executeClientSideWorkflow() {
try {
const result = await client.executeWorkflow('workflow-id', {
userInput: 'Hello from browser'
});
console.log('Workflow result:', result);
// Обновите UI с результатом
document.getElementById('result')!.textContent =
JSON.stringify(result.output, null, 2);
} catch (error) {
console.error('Error:', error);
}
}Загрузка файлов
Объекты File автоматически обнаруживаются и преобразуются в формат base64. Включите их в ваши входные данные под именем поля, соответствующему формату ввода API-триггера вашего рабочего процесса.
SDK преобразует объекты File в этот формат:
{
type: 'file',
data: 'data:mime/type;base64,base64data',
name: 'filename',
mime: 'mime/type'
}Альтернативно, вы можете вручную предоставить файлы, используя формат URL:
{
type: 'url',
data: 'https://example.com/file.pdf',
name: 'file.pdf',
mime: 'application/pdf'
}import { AACFlowClient } from 'aacflow-ts-sdk';
const client = new AACFlowClient({
apiKey: process.env.NEXT_PUBLIC_AACFLOW_API_KEY!
});
// Из файлового ввода
async function handleFileUpload(event: Event) {
const input = event.target as HTMLInputElement;
const files = Array.from(input.files || []);
// Включите файлы под именем поля из формата ввода API-триггера вашего рабочего процесса
const result = await client.executeWorkflow('workflow-id', {
documents: files, // Должно соответствовать имени поля "files" вашего рабочего процесса
instructions: 'Analyze these documents'
});
console.log('Result:', result);
}import { AACFlowClient } from 'aacflow-ts-sdk';
import fs from 'fs';
const client = new AACFlowClient({
apiKey: process.env.AACFLOW_API_KEY!
});
// Прочитайте файл и создайте объект File
const fileBuffer = fs.readFileSync('./document.pdf');
const file = new File([fileBuffer], 'document.pdf', {
type: 'application/pdf'
});
// Включите файлы под именем поля из формата ввода API-триггера вашего рабочего процесса
const result = await client.executeWorkflow('workflow-id', {
documents: [file], // Должно соответствовать имени поля "files" вашего рабочего процесса
query: 'Summarize this document'
});При использовании SDK в браузере будьте осторожны, чтобы не раскрыть чувствительные API-ключи. Рассмотрите возможность использования бэкенд-прокси или публичных API-ключей с ограниченными разрешениями.
Пример React Hook
Создайте пользовательский React hook для выполнения рабочих процессов:
import { useState, useCallback } from 'react';
import { AACFlowClient, WorkflowExecutionResult } from 'aacflow-ts-sdk';
const client = new AACFlowClient({
apiKey: process.env.AACFLOW_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
};
}
// Использование в компоненте
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>
);
}Асинхронное выполнение рабочих процессов
Выполняйте рабочие процессы асинхронно для длительных задач:
import { AACFlowClient, AsyncExecutionResult } from 'aacflow-ts-sdk';
const client = new AACFlowClient({
apiKey: process.env.AACFLOW_API_KEY!
});
async function executeAsync() {
try {
// Начните асинхронное выполнение
const result = await client.executeWorkflow('workflow-id', { data: 'large dataset' }, {
async: true // Выполнить асинхронно
});
// Проверьте, является ли результат асинхронным выполнением
if ('taskId' in result) {
console.log('Task ID:', result.taskId);
console.log('Status endpoint:', result.links.status);
// Опрос на завершение
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)); // Подождите 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);
} else {
console.error('Workflow failed:', status.error);
}
}
} catch (error) {
console.error('Error:', error);
}
}
executeAsync();Ограничение скорости и повторные попытки
Обрабатывайте ограничения скорости автоматически с экспоненциальной задержкой:
import { AACFlowClient, AACFlowError } from 'aacflow-ts-sdk';
const client = new AACFlowClient({
apiKey: process.env.AACFLOW_API_KEY!
});
async function executeWithRetryHandling() {
try {
// Автоматически повторяет при ограничении скорости
const result = await client.executeWithRetry('workflow-id', { message: 'Process this' }, {}, {
maxRetries: 5,
initialDelay: 1000,
maxDelay: 60000,
backoffMultiplier: 2
});
console.log('Success:', result);
} catch (error) {
if (error instanceof AACFlowError && error.code === 'RATE_LIMIT_EXCEEDED') {
console.error('Rate limit exceeded after all retries');
// Проверьте информацию об ограничении скорости
const rateLimitInfo = client.getRateLimitInfo();
if (rateLimitInfo) {
console.log('Rate limit resets at:', new Date(rateLimitInfo.reset * 1000));
}
}
}
}Мониторинг использования
Отслеживайте использование вашего аккаунта и лимиты:
import { AACFlowClient } from 'aacflow-ts-sdk';
const client = new AACFlowClient({
apiKey: process.env.AACFLOW_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: $' + 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('Usage: ' + percentUsed.toFixed(1) + '%');
if (percentUsed > 80) {
console.warn('⚠️ Warning: You are approaching your usage limit!');
}
} catch (error) {
console.error('Error checking usage:', error);
}
}
checkUsage();Потоковое выполнение рабочих процессов
Выполняйте рабочие процессы с потоковыми ответами в реальном времени:
import { AACFlowClient } from 'aacflow-ts-sdk';
const client = new AACFlowClient({
apiKey: process.env.AACFLOW_API_KEY!
});
async function executeWithStreaming() {
try {
// Включите потоковую передачу для определенных выходов блоков
const result = await client.executeWorkflow('workflow-id', { message: 'Count to five' }, {
stream: true,
selectedOutputs: ['agent1.content'] // Используйте формат blockName.attribute
});
console.log('Workflow result:', result);
} catch (error) {
console.error('Error:', error);
}
}Потоковый ответ следует формату Server-Sent Events (SSE):
data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"}
data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", two"}
data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}}
data: [DONE]Пример потоковой передачи в React:
import { useState, useEffect } from 'react';
function StreamingWorkflow() {
const [output, setOutput] = useState('');
const [loading, setLoading] = useState(false);
const executeStreaming = async () => {
setLoading(true);
setOutput('');
// ВАЖНО: Сделайте этот API-вызов с вашего бэкенд-сервера, а не из браузера
// Никогда не раскрывайте ваш API-ключ в клиентском коде
const response = await fetch('https://aacflow.io/api/workflows/WORKFLOW_ID/execute', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.AACFLOW_API_KEY! // Только серверная переменная окружения
},
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) {
// Пропустить невалидный JSON
}
}
}
}
};
return (
<div>
<button onClick={executeStreaming} disabled={loading}>
{loading ? 'Generating...' : 'Start Streaming'}
</button>
<div style={{ whiteSpace: 'pre-wrap' }}>{output}</div>
</div>
);
}Получение вашего API-ключа
Перейдите на AACFlow и войдите в свой аккаунт.
Перейдите к рабочему процессу, который вы хотите выполнить программно.
Нажмите "Deploy", чтобы развернуть ваш рабочий процесс, если он еще не развернут.
Во время процесса развертывания выберите или создайте API-ключ.
Скопируйте API-ключ для использования в вашем TypeScript/JavaScript приложении.
Требования
- Node.js 16+
- TypeScript 5.0+ (для TypeScript проектов)
Лицензия
Apache-2.0

