UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio

172 lines (171 loc) 5.7 kB
/** * Context Overflow Error Detection * * Cross-provider regex patterns to detect context window overflow errors. * Modeled on Cline + pi-mono patterns. */ /** * Provider-specific error patterns for context overflow. * * IMPORTANT: Order matters for getContextOverflowProvider - more specific * patterns should be checked first. OpenAI patterns are very specific * (e.g., "This model's maximum context length is") so they come first. */ const OVERFLOW_PATTERNS = [ { provider: "openai", patterns: [ /This model's maximum context length is/i, /tokens\. However, (?:your messages|you requested)/i, /reduce the length of the messages/i, /Please reduce the length/i, ], }, { provider: "azure", patterns: [/content_length_exceeded/i], }, { provider: "google", patterns: [ /RESOURCE_EXHAUSTED/i, /exceeds the maximum number of tokens/i, /content is too long/i, /request payload size exceeds/i, /input token limit/i, ], }, { provider: "bedrock", patterns: [ /ValidationException.*token/i, /Input is too long/i, /exceeds the model's maximum/i, ], }, { provider: "mistral", patterns: [/context length exceeded/i, /maximum number of tokens/i], }, { provider: "openrouter", patterns: [/context_length_exceeded/i], }, { provider: "anthropic", patterns: [ /prompt is too long/i, /input is too long/i, /too many tokens/i, /maximum context length/i, ], }, ]; /** * Check if an error is a context overflow error from any provider. */ export function isContextOverflowError(error) { const errorMessage = extractErrorMessage(error); if (!errorMessage) { return false; } return OVERFLOW_PATTERNS.some(({ patterns }) => patterns.some((pattern) => pattern.test(errorMessage))); } /** * Identify which provider produced the context overflow error. */ export function getContextOverflowProvider(error) { const errorMessage = extractErrorMessage(error); if (!errorMessage) { return null; } for (const { provider, patterns } of OVERFLOW_PATTERNS) { if (patterns.some((pattern) => pattern.test(errorMessage))) { return provider; } } return null; } /** * Extract actual token counts from provider overflow error messages. * * Many providers include the actual/max token counts in their error messages: * - OpenAI: "This model's maximum context length is 128000 tokens. However, your messages resulted in 145000 tokens." * - Anthropic: "prompt is too long: 180000 tokens > 200000 token limit" * - Google: "exceeds the maximum number of tokens (180000 > 100000)" */ export function parseProviderOverflowDetails(error) { const message = extractErrorMessage(error); if (!message) { return null; } // Guard against excessively long inputs that could slow regex matching if (message.length > 2000) { return null; } // OpenAI pattern: "resulted in X tokens" + "maximum context length is Y" // Use single character-class number groups to prevent ReDoS (CodeQL: js/polynomial-redos) const openaiActual = message.match(/resulted\s+in\s+(\d[\d,]{0,19})\s*tokens/i); const openaiMax = message.match(/maximum\s+context\s+length\s+is\s+(\d[\d,]{0,19})/i); if (openaiActual && openaiMax) { return { actualTokens: parseInt(openaiActual[1].replace(/,/g, ""), 10), budgetTokens: parseInt(openaiMax[1].replace(/,/g, ""), 10), }; } // Anthropic pattern: "X tokens > Y token limit" or "X tokens, limit Y" // Use single character-class number groups to prevent ReDoS (CodeQL: js/polynomial-redos) const anthropicMatch = message.match(/(\d[\d,]{0,19})\s*tokens?\s*[>:]\s*(\d[\d,]{0,19})/i); if (anthropicMatch) { return { actualTokens: parseInt(anthropicMatch[1].replace(/,/g, ""), 10), budgetTokens: parseInt(anthropicMatch[2].replace(/,/g, ""), 10), }; } // Google pattern: "X > Y" or "X exceeds Y" // Use single character-class number groups to prevent ReDoS (CodeQL: js/polynomial-redos) const googleMatch = message.match(/(\d[\d,]{0,19})\s*(?:>|exceeds)\s*(\d[\d,]{0,19})/i); if (googleMatch) { return { actualTokens: parseInt(googleMatch[1].replace(/,/g, ""), 10), budgetTokens: parseInt(googleMatch[2].replace(/,/g, ""), 10), }; } return null; } /** * Extract error message from various error formats. */ export function extractErrorMessage(error) { if (!error) { return null; } if (typeof error === "string") { return error; } if (error instanceof Error) { // Check nested error messages too const msg = error.message; const cause = error?.cause; if (cause instanceof Error) { return `${msg} ${cause.message}`; } return msg; } if (typeof error === "object") { const obj = error; if (typeof obj.message === "string") { return obj.message; } if (typeof obj.error === "string") { return obj.error; } if (typeof obj.error === "object" && obj.error !== null) { const nested = obj.error; if (typeof nested.message === "string") { return nested.message; } } } return null; }