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', {
input: { message: 'Hello, world!' },
timeout: 30000 // 30 секунд
});Параметры:
workflowId(string): ID рабочего процесса для выполненияoptions(ExecutionOptions, опционально):input(any): Входные данные для передачи в рабочий процесс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', {
input: { message: 'Hello' },
timeout: 30000
}, {
maxRetries: 3, // Максимальное количество повторных попыток
initialDelay: 1000, // Начальная задержка в мс (1 секунда)
maxDelay: 30000, // Максимальная задержка в мс (30 секунд)
backoffMultiplier: 2 // Множитель экспоненциальной задержки
});Параметры:
workflowId(string): ID рабочего процесса для выполнения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('Рабочий процесс не развернут или не готов');
}
// Выполнение рабочего процесса
const result = await client.executeWorkflow('my-workflow-id', {
input: {
message: 'Обработать эти данные',
userId: '12345'
}
});
if (result.success) {
console.log('Выходные данные:', result.output);
console.log('Длительность:', result.metadata?.duration);
} else {
console.error('Ошибка рабочего процесса:', result.error);
}
} catch (error) {
console.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('Неверный API-ключ');
break;
case 'TIMEOUT':
console.error('Превышено время выполнения рабочего процесса');
break;
case 'USAGE_LIMIT_EXCEEDED':
console.error('Превышен лимит использования');
break;
case 'INVALID_JSON':
console.error('Неверный JSON в теле запроса');
break;
default:
console.error('Ошибка рабочего процесса:', error.message);
}
} else {
console.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');
}
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');
}
const client = new AACFlowClient({
apiKey,
baseUrl: process.env.SIM_BASE_URL || 'https://aacflow.io'
});Интеграция с Express.js
Интеграция с сервером 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('Ошибка выполнения рабочего процесса:', error);
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Неизвестная ошибка'
});
}
});
app.listen(3000, () => {
console.log('Сервер запущен на порту 3000');
});API-маршрут Next.js
Использование с API-маршрутами Next.js:
// 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: 'Метод не разрешен' });
}
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);
res.status(500).json({
error: 'Не удалось выполнить рабочий процесс'
});
}
}Использование в браузере
Использование в браузере (с правильной конфигурацией 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', {
input: {
userInput: 'Hello from browser'
}
});
console.log('Результат рабочего процесса:', result);
// Обновление UI с результатом
document.getElementById('result')!.textContent =
JSON.stringify(result.output, null, 2);
} catch (error) {
console.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!
});
// Из input-элемента файла
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', {
input: {
documents: files, // Должно соответствовать имени поля "files" вашего рабочего процесса
instructions: 'Проанализируйте эти документы'
}
});
console.log('Результат:', 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', {
input: {
documents: [file], // Должно соответствовать имени поля "files" вашего рабочего процесса
query: 'Обобщите этот документ'
}
});При использовании SDK в браузере будьте осторожны, чтобы не раскрыть чувствительные API-ключи. Рассмотрите возможность использования бэкенд-прокси или публичных API-ключей с ограниченными разрешениями.
Пример React хука
Создание пользовательского React хука для выполнения рабочих процессов:
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('Неизвестная ошибка'));
} 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 ? 'Выполняется...' : 'Выполнить рабочий процесс'}
</button>
{error && <div>Ошибка: {error.message}</div>}
{result && (
<div>
<h3>Результат:</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', {
input: { data: 'большой набор данных' },
async: true // Выполнить асинхронно
});
// Проверка, является ли результат асинхронным выполнением
if ('taskId' in result) {
console.log('ID задачи:', result.taskId);
console.log('Эндпоинт статуса:', result.links.status);
// Опрос на завершение
let status = await client.getJobStatus(result.taskId);
while (status.status === 'queued' || status.status === 'processing') {
console.log('Текущий статус:', status.status);
await new Promise(resolve => setTimeout(resolve, 2000)); // Ожидание 2 секунды
status = await client.getJobStatus(result.taskId);
}
if (status.status === 'completed') {
console.log('Рабочий процесс завершен!');
console.log('Выходные данные:', status.output);
console.log('Длительность:', status.metadata.duration);
} else {
console.error('Ошибка рабочего процесса:', status.error);
}
}
} catch (error) {
console.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', {
input: { message: 'Обработать это' }
}, {
maxRetries: 5,
initialDelay: 1000,
maxDelay: 60000,
backoffMultiplier: 2
});
console.log('Успех:', result);
} catch (error) {
if (error instanceof AACFlowError && error.code === 'RATE_LIMIT_EXCEEDED') {
console.error('Превышено ограничение скорости после всех повторных попыток');
// Проверка информации об ограничении скорости
const rateLimitInfo = client.getRateLimitInfo();
if (rateLimitInfo) {
console.log('Ограничение скорости сбросится в:', 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('=== Ограничения скорости ===');
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);
}
}
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', {
input: { message: 'Посчитать до пяти' },
stream: true,
selectedOutputs: ['agent1.content'] // Используйте формат blockName.attribute
});
console.log('Результат рабочего процесса:', result);
} catch (error) {
console.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: 'Сгенерировать историю',
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('Выполнение завершено:', parsed.metadata);
}
} catch (e) {
// Пропустить неверный JSON
}
}
}
}
};
return (
<div>
<button onClick={executeStreaming} disabled={loading}>
{loading ? 'Генерация...' : 'Начать потоковую передачу'}
</button>
<div style={{ whiteSpace: 'pre-wrap' }}>{output}</div>
</div>
);
}Получение вашего API-ключа
Перейдите на AACFlow и войдите в свой аккаунт.
Перейдите к рабочему процессу, который хотите выполнить программно.
Нажмите "Развернуть", чтобы развернуть ваш рабочий процесс, если он еще не развернут.
В процессе развертывания выберите или создайте API-ключ.
Скопируйте API-ключ для использования в вашем TypeScript/JavaScript приложении.
Требования
- Node.js 16+
- TypeScript 5.0+ (для TypeScript проектов)
Лицензия
Apache-2.0

