titan-agent 5.4.0 → 5.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/agent/agent.js +1 -1
  2. package/dist/agent/agent.js.map +1 -1
  3. package/dist/agent/agentLoop.js +77 -12
  4. package/dist/agent/agentLoop.js.map +1 -1
  5. package/dist/agent/agentWakeup.js +8 -3
  6. package/dist/agent/agentWakeup.js.map +1 -1
  7. package/dist/agent/commandPost.js +6 -1
  8. package/dist/agent/commandPost.js.map +1 -1
  9. package/dist/agent/heartbeatScheduler.js +36 -4
  10. package/dist/agent/heartbeatScheduler.js.map +1 -1
  11. package/dist/agent/toolRunner.js +30 -0
  12. package/dist/agent/toolRunner.js.map +1 -1
  13. package/dist/config/config.js +30 -8
  14. package/dist/config/config.js.map +1 -1
  15. package/dist/config/schema.js +10 -1
  16. package/dist/config/schema.js.map +1 -1
  17. package/dist/eval/record.js +1 -1
  18. package/dist/eval/record.js.map +1 -1
  19. package/dist/gateway/server.js +26 -0
  20. package/dist/gateway/server.js.map +1 -1
  21. package/dist/mesh/transport.js +60 -8
  22. package/dist/mesh/transport.js.map +1 -1
  23. package/dist/providers/anthropic.js +3 -2
  24. package/dist/providers/anthropic.js.map +1 -1
  25. package/dist/providers/base.js.map +1 -1
  26. package/dist/providers/google.js +94 -20
  27. package/dist/providers/google.js.map +1 -1
  28. package/dist/providers/modelCapabilities.js +59 -0
  29. package/dist/providers/modelCapabilities.js.map +1 -0
  30. package/dist/providers/ollama.js +3 -2
  31. package/dist/providers/ollama.js.map +1 -1
  32. package/dist/providers/openai.js +4 -3
  33. package/dist/providers/openai.js.map +1 -1
  34. package/dist/providers/openai_compat.js +3 -2
  35. package/dist/providers/openai_compat.js.map +1 -1
  36. package/dist/providers/router.js +63 -21
  37. package/dist/providers/router.js.map +1 -1
  38. package/dist/skills/registry.js +176 -163
  39. package/dist/skills/registry.js.map +1 -1
  40. package/dist/telemetry/activityLog.js +1 -1
  41. package/dist/telemetry/activityLog.js.map +1 -1
  42. package/dist/utils/constants.js +2 -2
  43. package/dist/utils/constants.js.map +1 -1
  44. package/docs/AGENT-HIERARCHY.md +154 -0
  45. package/docs/superpowers/plans/2026-04-29-titan-production-fix.md +241 -0
  46. package/package.json +2 -2
  47. package/scripts/start-workers.sh +39 -0
  48. package/scripts/task-feeder.ts +38 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/openai_compat.ts"],"sourcesContent":["/**\n * TITAN — Generic OpenAI-Compatible Provider\n * A single provider class that works with any OpenAI-compatible API endpoint.\n * Used by: Groq, Mistral, OpenRouter, Fireworks, xAI, Together, DeepSeek,\n * Cerebras, Cohere, Perplexity, and any custom provider.\n */\nimport {\n LLMProvider,\n type ChatOptions,\n type ChatResponse,\n type ChatStreamChunk,\n type ToolCall,\n} from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport type { ProviderConfig } from '../config/schema.js';\nimport logger from '../utils/logger.js';\nimport { fetchWithRetry } from '../utils/helpers.js';\nimport { resolveApiKey } from './authResolver.js';\nimport { v4 as uuid } from 'uuid';\n\n/** Configuration for an OpenAI-compatible provider */\nexport interface OpenAICompatConfig {\n /** Internal provider name (e.g. 'groq') */\n name: string;\n /** Display name shown to users (e.g. 'Groq (Fast Inference)') */\n displayName: string;\n /** Default API base URL */\n defaultBaseUrl: string;\n /** Environment variable name for the API key */\n envKey: string;\n /** Config key name in titan.json providers section */\n configKey: string;\n /** Default model ID */\n defaultModel: string;\n /** Static model list (returned when health check fails) */\n knownModels: string[];\n /** Extra headers to send with every request */\n extraHeaders?: Record<string, string>;\n /** Whether to fetch models from /v1/models endpoint */\n supportsModelList?: boolean;\n /** Keep org/ prefix in model name (e.g. NIM API expects 'nvidia/model-name') */\n keepModelPrefix?: boolean;\n}\n\nexport class OpenAICompatProvider extends LLMProvider {\n readonly name: string;\n readonly displayName: string;\n private readonly config: OpenAICompatConfig;\n\n constructor(config: OpenAICompatConfig) {\n super();\n this.name = config.name;\n this.displayName = config.displayName;\n this.config = config;\n }\n\n private get apiKey(): string {\n const cfg = loadConfig();\n const providerCfg = (cfg.providers as Record<string, ProviderConfig>)[this.config.configKey];\n return resolveApiKey(this.config.name, providerCfg?.authProfiles || [], providerCfg?.apiKey || '', this.config.envKey, providerCfg?.rotationStrategy, providerCfg?.credentialCooldownMs);\n }\n\n private get baseUrl(): string {\n const cfg = loadConfig();\n const providerCfg = (cfg.providers as Record<string, ProviderConfig>)[this.config.configKey];\n return providerCfg?.baseUrl || this.config.defaultBaseUrl;\n }\n\n /** Sanitize messages for strict APIs (e.g., NIM) that reject empty content strings */\n private sanitizeMessages(messages: ChatOptions['messages']): ChatOptions['messages'] {\n return messages.map(m => ({\n ...m,\n content: m.content || (m.role === 'assistant' && m.toolCalls ? '' : ' '),\n }));\n }\n\n async chat(options: ChatOptions): Promise<ChatResponse> {\n const rawModel = options.model || this.config.defaultModel;\n // NIM API requires org/model format — keep prefix as-is or add it\n const model = this.config.keepModelPrefix\n ? (rawModel.includes('/') ? rawModel : `${this.name}/${rawModel}`)\n : rawModel.replace(`${this.name}/`, '');\n const apiKey = this.apiKey;\n if (!apiKey) throw new Error(`${this.displayName} API key not configured (set ${this.config.envKey} or providers.${this.config.configKey}.apiKey)`);\n\n logger.debug(this.name, `Chat request: model=${model}, messages=${options.messages.length}`);\n\n const sanitized = this.sanitizeMessages(options.messages);\n const body: Record<string, unknown> = {\n model,\n messages: sanitized.map((m) => {\n if (m.role === 'tool') {\n return { role: 'tool', content: m.content || ' ', tool_call_id: m.toolCallId };\n }\n if (m.role === 'assistant' && m.toolCalls) {\n return {\n role: 'assistant',\n content: m.content || null,\n tool_calls: m.toolCalls.map((tc) => ({\n id: tc.id,\n type: 'function',\n function: { name: tc.function.name, arguments: tc.function.arguments },\n })),\n };\n }\n return { role: m.role, content: m.content || ' ' };\n }),\n max_tokens: options.maxTokens || 8192,\n };\n\n if (options.tools && options.tools.length > 0) {\n body.tools = options.tools;\n }\n\n if (options.temperature !== undefined) {\n body.temperature = options.temperature;\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n ...(this.config.extraHeaders || {}),\n };\n\n const response = await fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n // Hunt Finding #37: attach status + Retry-After so the router can respect backoff\n const { createProviderError } = await import('./errorTaxonomy.js');\n throw createProviderError(`${this.displayName} API`, response, errorText, { provider: this.name, model });\n }\n\n const data = await response.json() as Record<string, unknown>;\n const choices = data.choices as Array<Record<string, unknown>> | undefined;\n\n if (!choices || choices.length === 0) {\n return {\n id: (data.id as string) || uuid(),\n content: '',\n usage: undefined,\n finishReason: 'stop',\n model: model.includes('/') ? model : `${this.name}/${model}`,\n };\n }\n\n const choice = choices[0];\n const message = choice.message as Record<string, unknown>;\n\n const toolCalls: ToolCall[] = [];\n if (message.tool_calls) {\n for (const tc of message.tool_calls as Array<Record<string, unknown>>) {\n const fn = tc.function as Record<string, string>;\n toolCalls.push({\n id: (tc.id as string) || uuid(),\n type: 'function',\n function: { name: fn.name, arguments: fn.arguments },\n });\n }\n }\n\n const usage = data.usage as { prompt_tokens: number; completion_tokens: number; total_tokens: number } | undefined;\n\n return {\n id: (data.id as string) || uuid(),\n content: (message.content as string) || '',\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n usage: usage\n ? {\n promptTokens: usage.prompt_tokens,\n completionTokens: usage.completion_tokens,\n totalTokens: usage.total_tokens,\n }\n : undefined,\n finishReason: toolCalls.length > 0 ? 'tool_calls' : (choice.finish_reason as 'stop' | 'length') || 'stop',\n model: model.includes('/') ? model : `${this.name}/${model}`,\n };\n }\n\n async *chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk> {\n const rawModel = options.model || this.config.defaultModel;\n const model = this.config.keepModelPrefix\n ? (rawModel.includes('/') ? rawModel : `${this.name}/${rawModel}`)\n : rawModel.replace(`${this.name}/`, '');\n const apiKey = this.apiKey;\n if (!apiKey) { yield { type: 'error', error: `${this.displayName} API key not configured` }; return; }\n\n const sanitized = this.sanitizeMessages(options.messages);\n const body: Record<string, unknown> = {\n model,\n stream: true,\n messages: sanitized.map((m) => {\n if (m.role === 'tool') return { role: 'tool', content: m.content || ' ', tool_call_id: m.toolCallId };\n if (m.role === 'assistant' && m.toolCalls) {\n return {\n role: 'assistant', content: m.content || null,\n tool_calls: m.toolCalls.map((tc) => ({ id: tc.id, type: 'function', function: { name: tc.function.name, arguments: tc.function.arguments } })),\n };\n }\n return { role: m.role, content: m.content || ' ' };\n }),\n max_tokens: options.maxTokens || 8192,\n };\n if (options.tools && options.tools.length > 0) body.tools = options.tools;\n if (options.temperature !== undefined) body.temperature = options.temperature;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n ...(this.config.extraHeaders || {}),\n };\n\n try {\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok || !response.body) {\n const errorText = await response.text();\n yield { type: 'error', error: `${this.displayName} API error (${response.status}): ${errorText}` };\n return;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n const toolCalls = new Map<number, { id: string; name: string; args: string }>();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue;\n const json = line.slice(6).trim();\n if (json === '[DONE]' || !json) continue;\n try {\n const chunk = JSON.parse(json);\n const delta = chunk.choices?.[0]?.delta;\n if (!delta) continue;\n if (delta.content) yield { type: 'text', content: delta.content };\n if (delta.tool_calls) {\n for (const tc of delta.tool_calls) {\n const idx = tc.index ?? 0;\n if (!toolCalls.has(idx)) toolCalls.set(idx, { id: tc.id || '', name: '', args: '' });\n const entry = toolCalls.get(idx)!;\n if (tc.id) entry.id = tc.id;\n if (tc.function?.name) entry.name = tc.function.name;\n if (tc.function?.arguments) entry.args += tc.function.arguments;\n }\n }\n } catch { /* skip malformed SSE lines */ }\n }\n }\n\n for (const [, tc] of toolCalls) {\n if (tc.id && tc.name) {\n yield { type: 'tool_call', toolCall: { id: tc.id, type: 'function', function: { name: tc.name, arguments: tc.args || '{}' } } };\n }\n }\n yield { type: 'done' };\n } catch (error) {\n yield { type: 'error', error: (error as Error).message };\n }\n }\n\n async listModels(): Promise<string[]> {\n if (!this.config.supportsModelList || !this.apiKey) {\n return this.config.knownModels;\n }\n try {\n const response = await fetch(`${this.baseUrl}/models`, {\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n ...(this.config.extraHeaders || {}),\n },\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) return this.config.knownModels;\n const data = await response.json() as { data?: Array<{ id: string }> };\n return (data.data || []).map((m) => m.id);\n } catch {\n return this.config.knownModels;\n }\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n if (!this.apiKey) return false;\n const response = await fetch(`${this.baseUrl}/models`, {\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n ...(this.config.extraHeaders || {}),\n },\n signal: AbortSignal.timeout(5000),\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n}\n\n// ── Provider Presets ──────────────────────────────────────────────\n\nexport const PROVIDER_PRESETS: OpenAICompatConfig[] = [\n {\n name: 'groq',\n displayName: 'Groq (Fast Inference)',\n defaultBaseUrl: 'https://api.groq.com/openai/v1',\n envKey: 'GROQ_API_KEY',\n configKey: 'groq',\n defaultModel: 'llama-3.3-70b-versatile',\n knownModels: ['llama-3.3-70b-versatile', 'llama-3.1-8b-instant', 'mixtral-8x7b-32768', 'gemma2-9b-it', 'deepseek-r1-distill-llama-70b'],\n supportsModelList: true,\n },\n {\n name: 'mistral',\n displayName: 'Mistral AI',\n defaultBaseUrl: 'https://api.mistral.ai/v1',\n envKey: 'MISTRAL_API_KEY',\n configKey: 'mistral',\n defaultModel: 'mistral-small-latest',\n knownModels: ['mistral-large-latest', 'mistral-medium-latest', 'mistral-small-latest', 'codestral-latest', 'mistral-nemo'],\n supportsModelList: true,\n },\n {\n name: 'fireworks',\n displayName: 'Fireworks AI',\n defaultBaseUrl: 'https://api.fireworks.ai/inference/v1',\n envKey: 'FIREWORKS_API_KEY',\n configKey: 'fireworks',\n defaultModel: 'accounts/fireworks/models/llama-v3p3-70b-instruct',\n knownModels: ['accounts/fireworks/models/llama-v3p3-70b-instruct', 'accounts/fireworks/models/mixtral-8x7b-instruct', 'accounts/fireworks/models/qwen3-8b'],\n supportsModelList: true,\n },\n {\n name: 'xai',\n displayName: 'xAI (Grok)',\n defaultBaseUrl: 'https://api.x.ai/v1',\n envKey: 'XAI_API_KEY',\n configKey: 'xai',\n defaultModel: 'grok-3-fast',\n knownModels: ['grok-3', 'grok-3-fast', 'grok-3-mini', 'grok-3-mini-fast'],\n supportsModelList: true,\n },\n {\n name: 'together',\n displayName: 'Together AI',\n defaultBaseUrl: 'https://api.together.xyz/v1',\n envKey: 'TOGETHER_API_KEY',\n configKey: 'together',\n defaultModel: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',\n knownModels: ['meta-llama/Llama-3.3-70B-Instruct-Turbo', 'deepseek-ai/DeepSeek-R1', 'Qwen/Qwen2.5-72B-Instruct-Turbo', 'mistralai/Mixtral-8x7B-Instruct-v0.1'],\n supportsModelList: true,\n },\n {\n name: 'deepseek',\n displayName: 'DeepSeek',\n defaultBaseUrl: 'https://api.deepseek.com/v1',\n envKey: 'DEEPSEEK_API_KEY',\n configKey: 'deepseek',\n defaultModel: 'deepseek-chat',\n knownModels: ['deepseek-chat', 'deepseek-reasoner'],\n supportsModelList: false,\n },\n {\n name: 'cerebras',\n displayName: 'Cerebras (Ultra-Fast)',\n defaultBaseUrl: 'https://api.cerebras.ai/v1',\n envKey: 'CEREBRAS_API_KEY',\n configKey: 'cerebras',\n defaultModel: 'llama-3.3-70b',\n knownModels: ['llama-3.3-70b', 'llama-3.1-8b', 'qwen-3-32b'],\n supportsModelList: true,\n },\n {\n name: 'cohere',\n displayName: 'Cohere',\n defaultBaseUrl: 'https://api.cohere.com/compatibility/v1',\n envKey: 'COHERE_API_KEY',\n configKey: 'cohere',\n defaultModel: 'command-r-plus',\n knownModels: ['command-r-plus', 'command-r', 'command-r7b'],\n supportsModelList: false,\n },\n {\n name: 'perplexity',\n displayName: 'Perplexity (Search-Augmented)',\n defaultBaseUrl: 'https://api.perplexity.ai',\n envKey: 'PERPLEXITY_API_KEY',\n configKey: 'perplexity',\n defaultModel: 'sonar',\n knownModels: ['sonar', 'sonar-pro', 'sonar-reasoning'],\n supportsModelList: false,\n },\n {\n name: 'venice',\n displayName: 'Venice AI (Privacy-First)',\n defaultBaseUrl: 'https://api.venice.ai/api/v1',\n envKey: 'VENICE_API_KEY',\n configKey: 'venice',\n defaultModel: 'llama-3.3-70b',\n knownModels: ['llama-3.3-70b', 'deepseek-r1-671b', 'qwen-2.5-vl-72b'],\n supportsModelList: true,\n },\n {\n name: 'bedrock',\n displayName: 'AWS Bedrock (via Proxy)',\n defaultBaseUrl: 'http://localhost:4000/v1',\n envKey: 'AWS_BEDROCK_API_KEY',\n configKey: 'bedrock',\n defaultModel: 'anthropic.claude-3-5-sonnet-20241022-v2:0',\n knownModels: ['anthropic.claude-3-5-sonnet-20241022-v2:0', 'amazon.titan-text-premier-v1:0', 'meta.llama3-70b-instruct-v1:0'],\n supportsModelList: false,\n },\n {\n name: 'litellm',\n displayName: 'LiteLLM (Universal Proxy)',\n defaultBaseUrl: 'http://localhost:4000/v1',\n envKey: 'LITELLM_API_KEY',\n configKey: 'litellm',\n defaultModel: 'gpt-4o',\n knownModels: ['gpt-4o', 'claude-sonnet-4-20250514', 'gemini-2.5-flash'],\n supportsModelList: true,\n },\n // NOTE: Azure OpenAI uses custom endpoints (https://{resource}.openai.azure.com/openai/deployments/{model})\n // and requires api-version query param + api-key header instead of Bearer token.\n // Users must configure baseUrl to their Azure deployment endpoint.\n {\n name: 'azure',\n displayName: 'Azure OpenAI (Enterprise)',\n defaultBaseUrl: '',\n envKey: 'AZURE_OPENAI_API_KEY',\n configKey: 'azure',\n defaultModel: 'gpt-4o',\n knownModels: ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1-preview'],\n supportsModelList: false,\n },\n {\n name: 'deepinfra',\n displayName: 'DeepInfra (Fast Inference)',\n defaultBaseUrl: 'https://api.deepinfra.com/v1/openai',\n envKey: 'DEEPINFRA_API_KEY',\n configKey: 'deepinfra',\n defaultModel: 'meta-llama/Llama-3.3-70B-Instruct',\n knownModels: ['meta-llama/Llama-3.3-70B-Instruct', 'mistralai/Mixtral-8x22B-Instruct-v0.1', 'Qwen/Qwen2.5-72B-Instruct', 'deepseek-ai/DeepSeek-R1'],\n supportsModelList: true,\n },\n {\n name: 'sambanova',\n displayName: 'SambaNova (Fast Inference)',\n defaultBaseUrl: 'https://api.sambanova.ai/v1',\n envKey: 'SAMBANOVA_API_KEY',\n configKey: 'sambanova',\n defaultModel: 'Meta-Llama-3.3-70B-Instruct',\n knownModels: ['Meta-Llama-3.3-70B-Instruct', 'DeepSeek-R1-Distill-Llama-70B', 'Qwen2.5-72B-Instruct'],\n supportsModelList: true,\n },\n {\n name: 'kimi',\n displayName: 'Kimi (Moonshot)',\n defaultBaseUrl: 'https://api.moonshot.cn/v1',\n envKey: 'MOONSHOT_API_KEY',\n configKey: 'kimi',\n defaultModel: 'kimi-k2.5',\n knownModels: ['kimi-k2.5', 'kimi-k2', 'moonshot-v1-8k', 'moonshot-v1-32k', 'moonshot-v1-128k'],\n supportsModelList: true,\n },\n {\n name: 'huggingface',\n displayName: 'Hugging Face Inference',\n defaultBaseUrl: 'https://api-inference.huggingface.co/v1',\n envKey: 'HF_API_KEY',\n configKey: 'huggingface',\n defaultModel: 'meta-llama/Llama-3.3-70B-Instruct',\n knownModels: ['meta-llama/Llama-3.3-70B-Instruct', 'mistralai/Mixtral-8x7B-Instruct-v0.1', 'Qwen/Qwen2.5-72B-Instruct', 'microsoft/Phi-3-medium-4k-instruct'],\n supportsModelList: true,\n },\n {\n name: 'ai21',\n displayName: 'AI21 Labs (Jamba)',\n defaultBaseUrl: 'https://api.ai21.com/studio/v1',\n envKey: 'AI21_API_KEY',\n configKey: 'ai21',\n defaultModel: 'jamba-1.5-large',\n knownModels: ['jamba-1.5-large', 'jamba-1.5-mini', 'jamba-instruct'],\n supportsModelList: false,\n },\n {\n name: 'cohere-v2',\n displayName: 'Cohere v2 (OpenAI-compat)',\n defaultBaseUrl: 'https://api.cohere.com/v2',\n envKey: 'COHERE_API_KEY',\n configKey: 'cohere-v2',\n defaultModel: 'command-a-03-2025',\n knownModels: ['command-a-03-2025', 'command-r-plus-08-2024', 'command-r-08-2024', 'command-r7b-12-2024'],\n supportsModelList: false,\n },\n {\n name: 'reka',\n displayName: 'Reka AI',\n defaultBaseUrl: 'https://api.reka.ai/v1',\n envKey: 'REKA_API_KEY',\n configKey: 'reka',\n defaultModel: 'reka-core',\n knownModels: ['reka-core', 'reka-flash', 'reka-edge'],\n supportsModelList: false,\n },\n {\n name: 'zhipu',\n displayName: 'Zhipu GLM',\n defaultBaseUrl: 'https://open.bigmodel.cn/api/paas/v4',\n envKey: 'ZHIPU_API_KEY',\n configKey: 'zhipu',\n defaultModel: 'glm-4-plus',\n knownModels: ['glm-4-plus', 'glm-4', 'glm-4-flash', 'glm-4-long'],\n supportsModelList: false,\n },\n {\n name: 'yi',\n displayName: '01.AI (Yi)',\n defaultBaseUrl: 'https://api.01.ai/v1',\n envKey: 'YI_API_KEY',\n configKey: 'yi',\n defaultModel: 'yi-large',\n knownModels: ['yi-large', 'yi-medium', 'yi-spark', 'yi-large-turbo'],\n supportsModelList: true,\n },\n {\n name: 'inflection',\n displayName: 'Inflection (Pi)',\n defaultBaseUrl: 'https://api.inflection.ai/v1',\n envKey: 'INFLECTION_API_KEY',\n configKey: 'inflection',\n defaultModel: 'inflection-3-pi',\n knownModels: ['inflection-3-pi', 'inflection-3-productivity'],\n supportsModelList: false,\n },\n {\n name: 'novita',\n displayName: 'Novita AI',\n defaultBaseUrl: 'https://api.novita.ai/v3/openai',\n envKey: 'NOVITA_API_KEY',\n configKey: 'novita',\n defaultModel: 'meta-llama/llama-3.3-70b-instruct',\n knownModels: ['meta-llama/llama-3.3-70b-instruct', 'deepseek/deepseek-r1', 'qwen/qwen-2.5-72b-instruct', 'mistralai/mistral-large-2411'],\n supportsModelList: true,\n },\n {\n name: 'replicate',\n displayName: 'Replicate',\n defaultBaseUrl: 'https://api.replicate.com/v1',\n envKey: 'REPLICATE_API_KEY',\n configKey: 'replicate',\n defaultModel: 'meta/meta-llama-3-70b-instruct',\n knownModels: ['meta/meta-llama-3-70b-instruct', 'mistralai/mixtral-8x7b-instruct-v0.1', 'meta/meta-llama-3.1-405b-instruct'],\n supportsModelList: false,\n },\n {\n name: 'lepton',\n displayName: 'Lepton AI',\n defaultBaseUrl: 'https://llama3-3-70b.lepton.run/api/v1',\n envKey: 'LEPTON_API_KEY',\n configKey: 'lepton',\n defaultModel: 'llama-3.3-70b',\n knownModels: ['llama-3.3-70b', 'mixtral-8x7b', 'qwen2.5-72b'],\n supportsModelList: false,\n },\n {\n name: 'anyscale',\n displayName: 'Anyscale Endpoints',\n defaultBaseUrl: 'https://api.endpoints.anyscale.com/v1',\n envKey: 'ANYSCALE_API_KEY',\n configKey: 'anyscale',\n defaultModel: 'meta-llama/Meta-Llama-3-70B-Instruct',\n knownModels: ['meta-llama/Meta-Llama-3-70B-Instruct', 'mistralai/Mixtral-8x7B-Instruct-v0.1', 'codellama/CodeLlama-70b-Instruct-hf'],\n supportsModelList: true,\n },\n {\n name: 'octo',\n displayName: 'OctoAI',\n defaultBaseUrl: 'https://text.octoai.run/v1',\n envKey: 'OCTOAI_API_KEY',\n configKey: 'octo',\n defaultModel: 'meta-llama-3.1-70b-instruct',\n knownModels: ['meta-llama-3.1-70b-instruct', 'mixtral-8x7b-instruct', 'qwen2.5-72b-instruct'],\n supportsModelList: true,\n },\n {\n name: 'nous',\n displayName: 'Nous Research (Hermes)',\n defaultBaseUrl: 'https://inference-api.nousresearch.com/v1',\n envKey: 'NOUS_API_KEY',\n configKey: 'nous',\n defaultModel: 'hermes-3-llama-3.1-70b',\n knownModels: ['hermes-3-llama-3.1-70b', 'hermes-3-llama-3.1-8b', 'hermes-2-pro-mistral-7b'],\n supportsModelList: false,\n },\n {\n name: 'openrouter',\n displayName: 'OpenRouter (Universal Gateway)',\n defaultBaseUrl: 'https://openrouter.ai/api/v1',\n envKey: 'OPENROUTER_API_KEY',\n configKey: 'openrouter',\n defaultModel: 'anthropic/claude-3.5-sonnet',\n knownModels: [\n 'anthropic/claude-3.5-sonnet',\n 'anthropic/claude-3.5-haiku',\n 'anthropic/claude-3-opus',\n 'openai/gpt-4o',\n 'openai/gpt-4o-mini',\n 'meta-llama/llama-3.3-70b-instruct',\n 'google/gemini-2.5-flash-preview',\n 'deepseek/deepseek-chat',\n 'deepseek/deepseek-r1',\n 'x-ai/grok-3-beta',\n 'nvidia/llama-3.1-nemotron-70b-instruct',\n ],\n supportsModelList: true,\n extraHeaders: {\n 'HTTP-Referer': 'https://titan.local',\n 'X-Title': 'TITAN',\n },\n },\n {\n name: 'nvidia',\n displayName: 'NVIDIA NIM',\n defaultBaseUrl: 'https://integrate.api.nvidia.com/v1',\n envKey: 'NVIDIA_API_KEY',\n configKey: 'nvidia',\n defaultModel: 'nvidia/llama-3.3-nemotron-super-49b-v1',\n knownModels: [\n 'nvidia/llama-3.3-nemotron-super-49b-v1',\n 'nvidia/llama-3.3-nemotron-super-49b-v1.5',\n 'nvidia/llama-3.1-nemotron-ultra-253b-v1',\n 'nvidia/llama-3.1-nemotron-70b-instruct',\n 'nvidia/nemotron-3-nano-30b-a3b',\n 'nvidia/nemotron-3-super-120b-a12b',\n ],\n supportsModelList: true,\n keepModelPrefix: true,\n },\n {\n name: 'minimax',\n displayName: 'MiniMax',\n defaultBaseUrl: 'https://api.minimax.chat/v1',\n envKey: 'MINIMAX_API_KEY',\n configKey: 'minimax',\n defaultModel: 'minimax-m2.7',\n knownModels: [\n 'minimax-m2.7',\n 'minimax-m2.7-highspeed',\n 'minimax-m2.5',\n 'minimax-01',\n 'minimax-text-01',\n ],\n supportsModelList: false,\n },\n];\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/providers/openai_compat.ts"],"sourcesContent":["/**\n * TITAN — Generic OpenAI-Compatible Provider\n * A single provider class that works with any OpenAI-compatible API endpoint.\n * Used by: Groq, Mistral, OpenRouter, Fireworks, xAI, Together, DeepSeek,\n * Cerebras, Cohere, Perplexity, and any custom provider.\n */\nimport {\n LLMProvider,\n type ChatOptions,\n type ChatResponse,\n type ChatStreamChunk,\n type ToolCall,\n} from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport type { ProviderConfig } from '../config/schema.js';\nimport logger from '../utils/logger.js';\nimport { fetchWithRetry } from '../utils/helpers.js';\nimport { resolveApiKey } from './authResolver.js';\nimport { v4 as uuid } from 'uuid';\nimport { clampMaxTokens } from './modelCapabilities.js';\n\n/** Configuration for an OpenAI-compatible provider */\nexport interface OpenAICompatConfig {\n /** Internal provider name (e.g. 'groq') */\n name: string;\n /** Display name shown to users (e.g. 'Groq (Fast Inference)') */\n displayName: string;\n /** Default API base URL */\n defaultBaseUrl: string;\n /** Environment variable name for the API key */\n envKey: string;\n /** Config key name in titan.json providers section */\n configKey: string;\n /** Default model ID */\n defaultModel: string;\n /** Static model list (returned when health check fails) */\n knownModels: string[];\n /** Extra headers to send with every request */\n extraHeaders?: Record<string, string>;\n /** Whether to fetch models from /v1/models endpoint */\n supportsModelList?: boolean;\n /** Keep org/ prefix in model name (e.g. NIM API expects 'nvidia/model-name') */\n keepModelPrefix?: boolean;\n}\n\nexport class OpenAICompatProvider extends LLMProvider {\n readonly name: string;\n readonly displayName: string;\n private readonly config: OpenAICompatConfig;\n\n constructor(config: OpenAICompatConfig) {\n super();\n this.name = config.name;\n this.displayName = config.displayName;\n this.config = config;\n }\n\n private get apiKey(): string {\n const cfg = loadConfig();\n const providerCfg = (cfg.providers as Record<string, unknown>)[this.config.configKey] as ProviderConfig | undefined;\n return resolveApiKey(this.config.name, providerCfg?.authProfiles || [], providerCfg?.apiKey || '', this.config.envKey, providerCfg?.rotationStrategy, providerCfg?.credentialCooldownMs);\n }\n\n private get baseUrl(): string {\n const cfg = loadConfig();\n const providerCfg = (cfg.providers as Record<string, unknown>)[this.config.configKey] as ProviderConfig | undefined;\n return providerCfg?.baseUrl || this.config.defaultBaseUrl;\n }\n\n /** Sanitize messages for strict APIs (e.g., NIM) that reject empty content strings */\n private sanitizeMessages(messages: ChatOptions['messages']): ChatOptions['messages'] {\n return messages.map(m => ({\n ...m,\n content: m.content || (m.role === 'assistant' && m.toolCalls ? '' : ' '),\n }));\n }\n\n async chat(options: ChatOptions): Promise<ChatResponse> {\n const rawModel = options.model || this.config.defaultModel;\n // NIM API requires org/model format — keep prefix as-is or add it\n const model = this.config.keepModelPrefix\n ? (rawModel.includes('/') ? rawModel : `${this.name}/${rawModel}`)\n : rawModel.replace(`${this.name}/`, '');\n const apiKey = this.apiKey;\n if (!apiKey) throw new Error(`${this.displayName} API key not configured (set ${this.config.envKey} or providers.${this.config.configKey}.apiKey)`);\n\n logger.debug(this.name, `Chat request: model=${model}, messages=${options.messages.length}`);\n\n const sanitized = this.sanitizeMessages(options.messages);\n const body: Record<string, unknown> = {\n model,\n messages: sanitized.map((m) => {\n if (m.role === 'tool') {\n return { role: 'tool', content: m.content || ' ', tool_call_id: m.toolCallId };\n }\n if (m.role === 'assistant' && m.toolCalls) {\n return {\n role: 'assistant',\n content: m.content || null,\n tool_calls: m.toolCalls.map((tc) => ({\n id: tc.id,\n type: 'function',\n function: { name: tc.function.name, arguments: tc.function.arguments },\n })),\n };\n }\n return { role: m.role, content: m.content || ' ' };\n }),\n max_tokens: clampMaxTokens(model, options.maxTokens),\n };\n\n if (options.tools && options.tools.length > 0) {\n body.tools = options.tools;\n }\n\n if (options.temperature !== undefined) {\n body.temperature = options.temperature;\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n ...(this.config.extraHeaders || {}),\n };\n\n const response = await fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n // Hunt Finding #37: attach status + Retry-After so the router can respect backoff\n const { createProviderError } = await import('./errorTaxonomy.js');\n throw createProviderError(`${this.displayName} API`, response, errorText, { provider: this.name, model });\n }\n\n const data = await response.json() as Record<string, unknown>;\n const choices = data.choices as Array<Record<string, unknown>> | undefined;\n\n if (!choices || choices.length === 0) {\n return {\n id: (data.id as string) || uuid(),\n content: '',\n usage: undefined,\n finishReason: 'stop',\n model: model.includes('/') ? model : `${this.name}/${model}`,\n };\n }\n\n const choice = choices[0];\n const message = choice.message as Record<string, unknown>;\n\n const toolCalls: ToolCall[] = [];\n if (message.tool_calls) {\n for (const tc of message.tool_calls as Array<Record<string, unknown>>) {\n const fn = tc.function as Record<string, string>;\n toolCalls.push({\n id: (tc.id as string) || uuid(),\n type: 'function',\n function: { name: fn.name, arguments: fn.arguments },\n });\n }\n }\n\n const usage = data.usage as { prompt_tokens: number; completion_tokens: number; total_tokens: number } | undefined;\n\n return {\n id: (data.id as string) || uuid(),\n content: (message.content as string) || '',\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n usage: usage\n ? {\n promptTokens: usage.prompt_tokens,\n completionTokens: usage.completion_tokens,\n totalTokens: usage.total_tokens,\n }\n : undefined,\n finishReason: toolCalls.length > 0 ? 'tool_calls' : (choice.finish_reason as 'stop' | 'length') || 'stop',\n model: model.includes('/') ? model : `${this.name}/${model}`,\n };\n }\n\n async *chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk> {\n const rawModel = options.model || this.config.defaultModel;\n const model = this.config.keepModelPrefix\n ? (rawModel.includes('/') ? rawModel : `${this.name}/${rawModel}`)\n : rawModel.replace(`${this.name}/`, '');\n const apiKey = this.apiKey;\n if (!apiKey) { yield { type: 'error', error: `${this.displayName} API key not configured` }; return; }\n\n const sanitized = this.sanitizeMessages(options.messages);\n const body: Record<string, unknown> = {\n model,\n stream: true,\n messages: sanitized.map((m) => {\n if (m.role === 'tool') return { role: 'tool', content: m.content || ' ', tool_call_id: m.toolCallId };\n if (m.role === 'assistant' && m.toolCalls) {\n return {\n role: 'assistant', content: m.content || null,\n tool_calls: m.toolCalls.map((tc) => ({ id: tc.id, type: 'function', function: { name: tc.function.name, arguments: tc.function.arguments } })),\n };\n }\n return { role: m.role, content: m.content || ' ' };\n }),\n max_tokens: clampMaxTokens(model, options.maxTokens),\n };\n if (options.tools && options.tools.length > 0) body.tools = options.tools;\n if (options.temperature !== undefined) body.temperature = options.temperature;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n ...(this.config.extraHeaders || {}),\n };\n\n try {\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok || !response.body) {\n const errorText = await response.text();\n yield { type: 'error', error: `${this.displayName} API error (${response.status}): ${errorText}` };\n return;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n const toolCalls = new Map<number, { id: string; name: string; args: string }>();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue;\n const json = line.slice(6).trim();\n if (json === '[DONE]' || !json) continue;\n try {\n const chunk = JSON.parse(json);\n const delta = chunk.choices?.[0]?.delta;\n if (!delta) continue;\n if (delta.content) yield { type: 'text', content: delta.content };\n if (delta.tool_calls) {\n for (const tc of delta.tool_calls) {\n const idx = tc.index ?? 0;\n if (!toolCalls.has(idx)) toolCalls.set(idx, { id: tc.id || '', name: '', args: '' });\n const entry = toolCalls.get(idx)!;\n if (tc.id) entry.id = tc.id;\n if (tc.function?.name) entry.name = tc.function.name;\n if (tc.function?.arguments) entry.args += tc.function.arguments;\n }\n }\n } catch { /* skip malformed SSE lines */ }\n }\n }\n\n for (const [, tc] of toolCalls) {\n if (tc.id && tc.name) {\n yield { type: 'tool_call', toolCall: { id: tc.id, type: 'function', function: { name: tc.name, arguments: tc.args || '{}' } } };\n }\n }\n yield { type: 'done' };\n } catch (error) {\n yield { type: 'error', error: (error as Error).message };\n }\n }\n\n async listModels(): Promise<string[]> {\n if (!this.config.supportsModelList || !this.apiKey) {\n return this.config.knownModels;\n }\n try {\n const response = await fetch(`${this.baseUrl}/models`, {\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n ...(this.config.extraHeaders || {}),\n },\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) return this.config.knownModels;\n const data = await response.json() as { data?: Array<{ id: string }> };\n return (data.data || []).map((m) => m.id);\n } catch {\n return this.config.knownModels;\n }\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n if (!this.apiKey) return false;\n const response = await fetch(`${this.baseUrl}/models`, {\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n ...(this.config.extraHeaders || {}),\n },\n signal: AbortSignal.timeout(5000),\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n}\n\n// ── Provider Presets ──────────────────────────────────────────────\n\nexport const PROVIDER_PRESETS: OpenAICompatConfig[] = [\n {\n name: 'groq',\n displayName: 'Groq (Fast Inference)',\n defaultBaseUrl: 'https://api.groq.com/openai/v1',\n envKey: 'GROQ_API_KEY',\n configKey: 'groq',\n defaultModel: 'llama-3.3-70b-versatile',\n knownModels: ['llama-3.3-70b-versatile', 'llama-3.1-8b-instant', 'mixtral-8x7b-32768', 'gemma2-9b-it', 'deepseek-r1-distill-llama-70b'],\n supportsModelList: true,\n },\n {\n name: 'mistral',\n displayName: 'Mistral AI',\n defaultBaseUrl: 'https://api.mistral.ai/v1',\n envKey: 'MISTRAL_API_KEY',\n configKey: 'mistral',\n defaultModel: 'mistral-small-latest',\n knownModels: ['mistral-large-latest', 'mistral-medium-latest', 'mistral-small-latest', 'codestral-latest', 'mistral-nemo'],\n supportsModelList: true,\n },\n {\n name: 'fireworks',\n displayName: 'Fireworks AI',\n defaultBaseUrl: 'https://api.fireworks.ai/inference/v1',\n envKey: 'FIREWORKS_API_KEY',\n configKey: 'fireworks',\n defaultModel: 'accounts/fireworks/models/llama-v3p3-70b-instruct',\n knownModels: ['accounts/fireworks/models/llama-v3p3-70b-instruct', 'accounts/fireworks/models/mixtral-8x7b-instruct', 'accounts/fireworks/models/qwen3-8b'],\n supportsModelList: true,\n },\n {\n name: 'xai',\n displayName: 'xAI (Grok)',\n defaultBaseUrl: 'https://api.x.ai/v1',\n envKey: 'XAI_API_KEY',\n configKey: 'xai',\n defaultModel: 'grok-3-fast',\n knownModels: ['grok-3', 'grok-3-fast', 'grok-3-mini', 'grok-3-mini-fast'],\n supportsModelList: true,\n },\n {\n name: 'together',\n displayName: 'Together AI',\n defaultBaseUrl: 'https://api.together.xyz/v1',\n envKey: 'TOGETHER_API_KEY',\n configKey: 'together',\n defaultModel: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',\n knownModels: ['meta-llama/Llama-3.3-70B-Instruct-Turbo', 'deepseek-ai/DeepSeek-R1', 'Qwen/Qwen2.5-72B-Instruct-Turbo', 'mistralai/Mixtral-8x7B-Instruct-v0.1'],\n supportsModelList: true,\n },\n {\n name: 'deepseek',\n displayName: 'DeepSeek',\n defaultBaseUrl: 'https://api.deepseek.com/v1',\n envKey: 'DEEPSEEK_API_KEY',\n configKey: 'deepseek',\n defaultModel: 'deepseek-chat',\n knownModels: ['deepseek-chat', 'deepseek-reasoner'],\n supportsModelList: false,\n },\n {\n name: 'cerebras',\n displayName: 'Cerebras (Ultra-Fast)',\n defaultBaseUrl: 'https://api.cerebras.ai/v1',\n envKey: 'CEREBRAS_API_KEY',\n configKey: 'cerebras',\n defaultModel: 'llama-3.3-70b',\n knownModels: ['llama-3.3-70b', 'llama-3.1-8b', 'qwen-3-32b'],\n supportsModelList: true,\n },\n {\n name: 'cohere',\n displayName: 'Cohere',\n defaultBaseUrl: 'https://api.cohere.com/compatibility/v1',\n envKey: 'COHERE_API_KEY',\n configKey: 'cohere',\n defaultModel: 'command-r-plus',\n knownModels: ['command-r-plus', 'command-r', 'command-r7b'],\n supportsModelList: false,\n },\n {\n name: 'perplexity',\n displayName: 'Perplexity (Search-Augmented)',\n defaultBaseUrl: 'https://api.perplexity.ai',\n envKey: 'PERPLEXITY_API_KEY',\n configKey: 'perplexity',\n defaultModel: 'sonar',\n knownModels: ['sonar', 'sonar-pro', 'sonar-reasoning'],\n supportsModelList: false,\n },\n {\n name: 'venice',\n displayName: 'Venice AI (Privacy-First)',\n defaultBaseUrl: 'https://api.venice.ai/api/v1',\n envKey: 'VENICE_API_KEY',\n configKey: 'venice',\n defaultModel: 'llama-3.3-70b',\n knownModels: ['llama-3.3-70b', 'deepseek-r1-671b', 'qwen-2.5-vl-72b'],\n supportsModelList: true,\n },\n {\n name: 'bedrock',\n displayName: 'AWS Bedrock (via Proxy)',\n defaultBaseUrl: 'http://localhost:4000/v1',\n envKey: 'AWS_BEDROCK_API_KEY',\n configKey: 'bedrock',\n defaultModel: 'anthropic.claude-3-5-sonnet-20241022-v2:0',\n knownModels: ['anthropic.claude-3-5-sonnet-20241022-v2:0', 'amazon.titan-text-premier-v1:0', 'meta.llama3-70b-instruct-v1:0'],\n supportsModelList: false,\n },\n {\n name: 'litellm',\n displayName: 'LiteLLM (Universal Proxy)',\n defaultBaseUrl: 'http://localhost:4000/v1',\n envKey: 'LITELLM_API_KEY',\n configKey: 'litellm',\n defaultModel: 'gpt-4o',\n knownModels: ['gpt-4o', 'claude-sonnet-4-20250514', 'gemini-2.5-flash'],\n supportsModelList: true,\n },\n // NOTE: Azure OpenAI uses custom endpoints (https://{resource}.openai.azure.com/openai/deployments/{model})\n // and requires api-version query param + api-key header instead of Bearer token.\n // Users must configure baseUrl to their Azure deployment endpoint.\n {\n name: 'azure',\n displayName: 'Azure OpenAI (Enterprise)',\n defaultBaseUrl: '',\n envKey: 'AZURE_OPENAI_API_KEY',\n configKey: 'azure',\n defaultModel: 'gpt-4o',\n knownModels: ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1-preview'],\n supportsModelList: false,\n },\n {\n name: 'deepinfra',\n displayName: 'DeepInfra (Fast Inference)',\n defaultBaseUrl: 'https://api.deepinfra.com/v1/openai',\n envKey: 'DEEPINFRA_API_KEY',\n configKey: 'deepinfra',\n defaultModel: 'meta-llama/Llama-3.3-70B-Instruct',\n knownModels: ['meta-llama/Llama-3.3-70B-Instruct', 'mistralai/Mixtral-8x22B-Instruct-v0.1', 'Qwen/Qwen2.5-72B-Instruct', 'deepseek-ai/DeepSeek-R1'],\n supportsModelList: true,\n },\n {\n name: 'sambanova',\n displayName: 'SambaNova (Fast Inference)',\n defaultBaseUrl: 'https://api.sambanova.ai/v1',\n envKey: 'SAMBANOVA_API_KEY',\n configKey: 'sambanova',\n defaultModel: 'Meta-Llama-3.3-70B-Instruct',\n knownModels: ['Meta-Llama-3.3-70B-Instruct', 'DeepSeek-R1-Distill-Llama-70B', 'Qwen2.5-72B-Instruct'],\n supportsModelList: true,\n },\n {\n name: 'kimi',\n displayName: 'Kimi (Moonshot)',\n defaultBaseUrl: 'https://api.moonshot.cn/v1',\n envKey: 'MOONSHOT_API_KEY',\n configKey: 'kimi',\n defaultModel: 'kimi-k2.5',\n knownModels: ['kimi-k2.5', 'kimi-k2', 'moonshot-v1-8k', 'moonshot-v1-32k', 'moonshot-v1-128k'],\n supportsModelList: true,\n },\n {\n name: 'huggingface',\n displayName: 'Hugging Face Inference',\n defaultBaseUrl: 'https://api-inference.huggingface.co/v1',\n envKey: 'HF_API_KEY',\n configKey: 'huggingface',\n defaultModel: 'meta-llama/Llama-3.3-70B-Instruct',\n knownModels: ['meta-llama/Llama-3.3-70B-Instruct', 'mistralai/Mixtral-8x7B-Instruct-v0.1', 'Qwen/Qwen2.5-72B-Instruct', 'microsoft/Phi-3-medium-4k-instruct'],\n supportsModelList: true,\n },\n {\n name: 'ai21',\n displayName: 'AI21 Labs (Jamba)',\n defaultBaseUrl: 'https://api.ai21.com/studio/v1',\n envKey: 'AI21_API_KEY',\n configKey: 'ai21',\n defaultModel: 'jamba-1.5-large',\n knownModels: ['jamba-1.5-large', 'jamba-1.5-mini', 'jamba-instruct'],\n supportsModelList: false,\n },\n {\n name: 'cohere-v2',\n displayName: 'Cohere v2 (OpenAI-compat)',\n defaultBaseUrl: 'https://api.cohere.com/v2',\n envKey: 'COHERE_API_KEY',\n configKey: 'cohere-v2',\n defaultModel: 'command-a-03-2025',\n knownModels: ['command-a-03-2025', 'command-r-plus-08-2024', 'command-r-08-2024', 'command-r7b-12-2024'],\n supportsModelList: false,\n },\n {\n name: 'reka',\n displayName: 'Reka AI',\n defaultBaseUrl: 'https://api.reka.ai/v1',\n envKey: 'REKA_API_KEY',\n configKey: 'reka',\n defaultModel: 'reka-core',\n knownModels: ['reka-core', 'reka-flash', 'reka-edge'],\n supportsModelList: false,\n },\n {\n name: 'zhipu',\n displayName: 'Zhipu GLM',\n defaultBaseUrl: 'https://open.bigmodel.cn/api/paas/v4',\n envKey: 'ZHIPU_API_KEY',\n configKey: 'zhipu',\n defaultModel: 'glm-4-plus',\n knownModels: ['glm-4-plus', 'glm-4', 'glm-4-flash', 'glm-4-long'],\n supportsModelList: false,\n },\n {\n name: 'yi',\n displayName: '01.AI (Yi)',\n defaultBaseUrl: 'https://api.01.ai/v1',\n envKey: 'YI_API_KEY',\n configKey: 'yi',\n defaultModel: 'yi-large',\n knownModels: ['yi-large', 'yi-medium', 'yi-spark', 'yi-large-turbo'],\n supportsModelList: true,\n },\n {\n name: 'inflection',\n displayName: 'Inflection (Pi)',\n defaultBaseUrl: 'https://api.inflection.ai/v1',\n envKey: 'INFLECTION_API_KEY',\n configKey: 'inflection',\n defaultModel: 'inflection-3-pi',\n knownModels: ['inflection-3-pi', 'inflection-3-productivity'],\n supportsModelList: false,\n },\n {\n name: 'novita',\n displayName: 'Novita AI',\n defaultBaseUrl: 'https://api.novita.ai/v3/openai',\n envKey: 'NOVITA_API_KEY',\n configKey: 'novita',\n defaultModel: 'meta-llama/llama-3.3-70b-instruct',\n knownModels: ['meta-llama/llama-3.3-70b-instruct', 'deepseek/deepseek-r1', 'qwen/qwen-2.5-72b-instruct', 'mistralai/mistral-large-2411'],\n supportsModelList: true,\n },\n {\n name: 'replicate',\n displayName: 'Replicate',\n defaultBaseUrl: 'https://api.replicate.com/v1',\n envKey: 'REPLICATE_API_KEY',\n configKey: 'replicate',\n defaultModel: 'meta/meta-llama-3-70b-instruct',\n knownModels: ['meta/meta-llama-3-70b-instruct', 'mistralai/mixtral-8x7b-instruct-v0.1', 'meta/meta-llama-3.1-405b-instruct'],\n supportsModelList: false,\n },\n {\n name: 'lepton',\n displayName: 'Lepton AI',\n defaultBaseUrl: 'https://llama3-3-70b.lepton.run/api/v1',\n envKey: 'LEPTON_API_KEY',\n configKey: 'lepton',\n defaultModel: 'llama-3.3-70b',\n knownModels: ['llama-3.3-70b', 'mixtral-8x7b', 'qwen2.5-72b'],\n supportsModelList: false,\n },\n {\n name: 'anyscale',\n displayName: 'Anyscale Endpoints',\n defaultBaseUrl: 'https://api.endpoints.anyscale.com/v1',\n envKey: 'ANYSCALE_API_KEY',\n configKey: 'anyscale',\n defaultModel: 'meta-llama/Meta-Llama-3-70B-Instruct',\n knownModels: ['meta-llama/Meta-Llama-3-70B-Instruct', 'mistralai/Mixtral-8x7B-Instruct-v0.1', 'codellama/CodeLlama-70b-Instruct-hf'],\n supportsModelList: true,\n },\n {\n name: 'octo',\n displayName: 'OctoAI',\n defaultBaseUrl: 'https://text.octoai.run/v1',\n envKey: 'OCTOAI_API_KEY',\n configKey: 'octo',\n defaultModel: 'meta-llama-3.1-70b-instruct',\n knownModels: ['meta-llama-3.1-70b-instruct', 'mixtral-8x7b-instruct', 'qwen2.5-72b-instruct'],\n supportsModelList: true,\n },\n {\n name: 'nous',\n displayName: 'Nous Research (Hermes)',\n defaultBaseUrl: 'https://inference-api.nousresearch.com/v1',\n envKey: 'NOUS_API_KEY',\n configKey: 'nous',\n defaultModel: 'hermes-3-llama-3.1-70b',\n knownModels: ['hermes-3-llama-3.1-70b', 'hermes-3-llama-3.1-8b', 'hermes-2-pro-mistral-7b'],\n supportsModelList: false,\n },\n {\n name: 'openrouter',\n displayName: 'OpenRouter (Universal Gateway)',\n defaultBaseUrl: 'https://openrouter.ai/api/v1',\n envKey: 'OPENROUTER_API_KEY',\n configKey: 'openrouter',\n defaultModel: 'anthropic/claude-3.5-sonnet',\n knownModels: [\n 'anthropic/claude-3.5-sonnet',\n 'anthropic/claude-3.5-haiku',\n 'anthropic/claude-3-opus',\n 'openai/gpt-4o',\n 'openai/gpt-4o-mini',\n 'meta-llama/llama-3.3-70b-instruct',\n 'google/gemini-2.5-flash-preview',\n 'deepseek/deepseek-chat',\n 'deepseek/deepseek-r1',\n 'x-ai/grok-3-beta',\n 'nvidia/llama-3.1-nemotron-70b-instruct',\n ],\n supportsModelList: true,\n extraHeaders: {\n 'HTTP-Referer': 'https://titan.local',\n 'X-Title': 'TITAN',\n },\n },\n {\n name: 'nvidia',\n displayName: 'NVIDIA NIM',\n defaultBaseUrl: 'https://integrate.api.nvidia.com/v1',\n envKey: 'NVIDIA_API_KEY',\n configKey: 'nvidia',\n defaultModel: 'nvidia/llama-3.3-nemotron-super-49b-v1',\n knownModels: [\n 'nvidia/llama-3.3-nemotron-super-49b-v1',\n 'nvidia/llama-3.3-nemotron-super-49b-v1.5',\n 'nvidia/llama-3.1-nemotron-ultra-253b-v1',\n 'nvidia/llama-3.1-nemotron-70b-instruct',\n 'nvidia/nemotron-3-nano-30b-a3b',\n 'nvidia/nemotron-3-super-120b-a12b',\n ],\n supportsModelList: true,\n keepModelPrefix: true,\n },\n {\n name: 'minimax',\n displayName: 'MiniMax',\n defaultBaseUrl: 'https://api.minimax.chat/v1',\n envKey: 'MINIMAX_API_KEY',\n configKey: 'minimax',\n defaultModel: 'minimax-m2.7',\n knownModels: [\n 'minimax-m2.7',\n 'minimax-m2.7-highspeed',\n 'minimax-m2.5',\n 'minimax-01',\n 'minimax-text-01',\n ],\n supportsModelList: false,\n },\n];\n"],"mappings":"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","names":[]}
@@ -409,36 +409,58 @@ async function tryFallbackChainStream(options, primaryModelId, originalError) {
409
409
  if (attempts >= maxRetries) break;
410
410
  if (fallbackModelId === primaryModelId) continue;
411
411
  attempts++;
412
+ let fbProviderName;
413
+ let gen;
412
414
  try {
413
415
  const { provider: fbProvider, model: fbModel } = resolveModel(fallbackModelId);
414
- const fbProviderName = fbProvider.name;
416
+ fbProviderName = fbProvider.name;
415
417
  if (!canRequest(fbProviderName, true)) {
416
418
  const cb = getCircuitBreaker(fbProviderName);
417
419
  logger.warn(COMPONENT, `Skipping stream fallback ${fallbackModelId} \u2014 circuit breaker OPEN (${cb.failureCount} failures)`);
418
420
  continue;
419
421
  }
420
422
  logger.warn(COMPONENT, `Stream model ${primaryModelId} failed (${originalError.message}), falling back to ${fallbackModelId}`);
421
- const gen = fbProvider.chatStream({ ...options, model: fbModel });
422
- recordSuccess(fbProviderName);
423
- lastFallbackEvent = {
424
- primary: primaryModelId,
425
- active: fallbackModelId,
426
- reason: originalError.message,
427
- timestamp: Date.now()
428
- };
429
- return gen;
423
+ gen = fbProvider.chatStream({ ...options, model: fbModel });
430
424
  } catch (chainErr) {
431
425
  try {
432
426
  const { provider: fbProvider } = resolveModel(fallbackModelId);
433
427
  recordFailure(fbProvider.name);
434
428
  } catch {
435
429
  }
436
- logger.warn(COMPONENT, `Fallback stream model ${fallbackModelId} also failed: ${chainErr.message}`);
430
+ logger.warn(COMPONENT, `Fallback stream model ${fallbackModelId} setup failed: ${chainErr.message}`);
437
431
  continue;
438
432
  }
433
+ lastFallbackEvent = {
434
+ primary: primaryModelId,
435
+ active: fallbackModelId,
436
+ reason: originalError.message,
437
+ timestamp: Date.now()
438
+ };
439
+ return monitorStreamForBreaker(gen, fbProviderName);
439
440
  }
440
441
  return null;
441
442
  }
443
+ async function* monitorStreamForBreaker(inner, providerName) {
444
+ let recorded = false;
445
+ try {
446
+ for await (const chunk of inner) {
447
+ if (chunk.type === "error") {
448
+ if (!recorded) {
449
+ recordFailure(providerName);
450
+ recorded = true;
451
+ }
452
+ }
453
+ yield chunk;
454
+ }
455
+ if (!recorded) recordSuccess(providerName);
456
+ } catch (innerErr) {
457
+ if (!recorded) {
458
+ recordFailure(providerName);
459
+ recorded = true;
460
+ }
461
+ throw innerErr;
462
+ }
463
+ }
442
464
  async function meshChat(peer, modelId, message) {
443
465
  const requestId = randomBytes(8).toString("hex");
444
466
  const config = loadConfig();
@@ -686,11 +708,15 @@ async function* chatStream(options) {
686
708
  }
687
709
  let lastError = null;
688
710
  const maxRetries = RETRY_CONFIG.maxRetries;
711
+ let fallbackChainAttempted = false;
712
+ let priorityFailoverAttempted = false;
689
713
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
690
714
  try {
715
+ let recordedSuccess = false;
691
716
  for await (const chunk of provider.chatStream({ ...options, model })) {
692
- if (attempt === 0 && chunk.type !== "error") {
717
+ if (!recordedSuccess && chunk.type !== "error" && attempt === 0) {
693
718
  recordSuccess(providerName);
719
+ recordedSuccess = true;
694
720
  }
695
721
  lastFallbackEvent = null;
696
722
  yield chunk;
@@ -710,11 +736,13 @@ async function* chatStream(options) {
710
736
  const retryDelayMs = Math.max(classified.cooldownMs, calculateBackoffDelay(attempt));
711
737
  logger.warn(COMPONENT, `${errorMsg} [${classified.reason}] \u2014 streaming retry in ${Math.round(retryDelayMs)}ms`);
712
738
  yield {
713
- type: "text",
714
- content: `
715
- [Retrying request (${attempt + 1}/${maxRetries}) due to ${classified.reason}...]
716
-
717
- `
739
+ type: "retry",
740
+ attempt: attempt + 1,
741
+ maxRetries,
742
+ reason: classified.reason,
743
+ provider: providerName,
744
+ model,
745
+ delayMs: Math.round(retryDelayMs)
718
746
  };
719
747
  await sleep(retryDelayMs);
720
748
  continue;
@@ -724,7 +752,8 @@ async function* chatStream(options) {
724
752
  } else {
725
753
  logger.error(COMPONENT, `${errorMsg} \u2014 streaming max retries exceeded [${classified.reason}]`);
726
754
  }
727
- if (classified.retryable || classified.shouldFallback) {
755
+ if (!fallbackChainAttempted && (classified.retryable || classified.shouldFallback)) {
756
+ fallbackChainAttempted = true;
728
757
  const chainStream = await tryFallbackChainStream(options, modelId, error);
729
758
  if (chainStream) {
730
759
  yield {
@@ -752,7 +781,8 @@ async function* chatStream(options) {
752
781
  }
753
782
  }
754
783
  }
755
- if (attempt === 0) {
784
+ if (!priorityFailoverAttempted) {
785
+ priorityFailoverAttempted = true;
756
786
  const failoverOrder = getFailoverOrder(providerName);
757
787
  let failedOver = false;
758
788
  for (const fallbackName of failoverOrder) {
@@ -777,8 +807,20 @@ async function* chatStream(options) {
777
807
  originalModel: model,
778
808
  error: errorMsg
779
809
  };
780
- yield* fallback.chatStream({ ...options, model: preferred });
781
- recordSuccess(fallbackName);
810
+ let recorded = false;
811
+ try {
812
+ for await (const chunk of fallback.chatStream({ ...options, model: preferred })) {
813
+ if (chunk.type === "error" && !recorded) {
814
+ recordFailure(fallbackName);
815
+ recorded = true;
816
+ }
817
+ yield chunk;
818
+ }
819
+ if (!recorded) recordSuccess(fallbackName);
820
+ } catch (innerErr) {
821
+ if (!recorded) recordFailure(fallbackName);
822
+ throw innerErr;
823
+ }
782
824
  failedOver = true;
783
825
  break;
784
826
  } catch (fallbackErr) {