UNPKG

@oliverpople/agency-x

Version:

🚀 **Transform feature requests into production-ready code in seconds**

124 lines (107 loc) 3.22 kB
export interface RetryConfig { maxRetries: number; baseDelay: number; maxDelay: number; backoffMultiplier: number; } export interface AgentConfig { name: string; dependencies: string[]; critical: boolean; retryConfig: RetryConfig; timeout: number; } export class AgentError extends Error { constructor( public agentName: string, message: string, public isRetryable: boolean = true, public originalError?: Error ) { super(`[${agentName}] ${message}`); this.name = 'AgentError'; } } export class OrchestrationError extends Error { constructor( message: string, public failedAgents: string[], public completedAgents: string[] ) { super(message); this.name = 'OrchestrationError'; } } export const calculateDelay = (attempt: number, config: RetryConfig): number => { const delay = config.baseDelay * Math.pow(config.backoffMultiplier, attempt - 1); return Math.min(delay, config.maxDelay); }; export const sleep = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms)); export const withRetry = async <T>( operation: () => Promise<T>, agentName: string, config: RetryConfig ): Promise<T> => { let lastError: Error | null = null; for (let attempt = 1; attempt <= config.maxRetries; attempt++) { try { return await operation(); } catch (error) { lastError = error as Error; if (error instanceof AgentError && !error.isRetryable) { throw error; } if (attempt < config.maxRetries) { const delay = calculateDelay(attempt, config); console.warn(`⚠️ [${agentName}] Attempt ${attempt} failed: ${error}. Retrying in ${delay}ms...`); await sleep(delay); } } } throw new AgentError( agentName, `Failed after ${config.maxRetries} attempts. Last error: ${lastError?.message || 'Unknown error'}`, false, lastError || new Error('Unknown error') ); }; export const withTimeout = <T>( promise: Promise<T>, timeoutMs: number, agentName: string ): Promise<T> => { return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { reject(new AgentError(agentName, `Operation timed out after ${timeoutMs}ms`, true)); }, timeoutMs); promise .then(resolve) .catch(reject) .finally(() => clearTimeout(timeoutId)); }); }; export const createAgentRunner = (config: AgentConfig) => { return async <T>(operation: () => Promise<T>): Promise<T> => { const timedOperation = () => withTimeout(operation(), config.timeout, config.name); return withRetry(timedOperation, config.name, config.retryConfig); }; }; // Default configurations export const DEFAULT_RETRY_CONFIG: RetryConfig = { maxRetries: 3, baseDelay: 1000, // 1 second maxDelay: 30000, // 30 seconds backoffMultiplier: 2, }; export const DEFAULT_AGENT_CONFIG: Omit<AgentConfig, 'name' | 'dependencies'> = { critical: false, retryConfig: DEFAULT_RETRY_CONFIG, timeout: 90000, // 90 seconds }; export const CRITICAL_RETRY_CONFIG: RetryConfig = { maxRetries: 5, baseDelay: 2000, // 2 seconds maxDelay: 60000, // 60 seconds backoffMultiplier: 2, };