@relayplane/proxy 0.1.2 → 0.1.4
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.
- package/README.md +5 -4
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/cli.mjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/proxy.ts","../src/storage/store.ts","../node_modules/nanoid/index.js","../node_modules/nanoid/url-alphabet/index.js","../src/storage/schema.ts","../src/routing/inference.ts","../src/routing/engine.ts","../src/learning/outcomes.ts","../src/learning/savings.ts","../src/learning/patterns.ts","../src/relay.ts","../src/cli.ts"],"sourcesContent":["/**\n * RelayPlane L2/L3 Proxy Server\n *\n * An OpenAI-compatible HTTP proxy that intelligently routes requests\n * to the optimal model using @relayplane/core.\n *\n * Supports:\n * - Streaming (SSE) for both OpenAI and Anthropic\n * - Non-streaming requests\n * - Automatic format conversion (Anthropic → OpenAI format)\n * - Tool/function calling (planned)\n *\n * @packageDocumentation\n */\n\nimport * as http from 'node:http';\nimport { RelayPlane } from './relay.js';\nimport { inferTaskType, getInferenceConfidence } from './routing/inference.js';\nimport type { Provider, TaskType } from './types.js';\n\n/**\n * Provider endpoint configuration\n */\nexport interface ProviderEndpoint {\n baseUrl: string;\n apiKeyEnv: string;\n}\n\n/**\n * Default provider endpoints\n */\nexport const DEFAULT_ENDPOINTS: Record<string, ProviderEndpoint> = {\n anthropic: {\n baseUrl: 'https://api.anthropic.com/v1',\n apiKeyEnv: 'ANTHROPIC_API_KEY',\n },\n openai: {\n baseUrl: 'https://api.openai.com/v1',\n apiKeyEnv: 'OPENAI_API_KEY',\n },\n google: {\n baseUrl: 'https://generativelanguage.googleapis.com/v1beta',\n apiKeyEnv: 'GEMINI_API_KEY',\n },\n xai: {\n baseUrl: 'https://api.x.ai/v1',\n apiKeyEnv: 'XAI_API_KEY',\n },\n moonshot: {\n baseUrl: 'https://api.moonshot.cn/v1',\n apiKeyEnv: 'MOONSHOT_API_KEY',\n },\n};\n\n/**\n * Model to provider/model mapping\n */\nexport const MODEL_MAPPING: Record<string, { provider: Provider; model: string }> = {\n // Anthropic models (using correct API model IDs)\n 'claude-opus-4-5': { provider: 'anthropic', model: 'claude-opus-4-5-20250514' },\n 'claude-sonnet-4': { provider: 'anthropic', model: 'claude-sonnet-4-20250514' },\n 'claude-3-5-sonnet': { provider: 'anthropic', model: 'claude-3-5-sonnet-20241022' },\n 'claude-3-5-haiku': { provider: 'anthropic', model: 'claude-3-5-haiku-20241022' },\n haiku: { provider: 'anthropic', model: 'claude-3-5-haiku-20241022' },\n sonnet: { provider: 'anthropic', model: 'claude-3-5-sonnet-20241022' },\n opus: { provider: 'anthropic', model: 'claude-3-opus-20240229' },\n // OpenAI models\n 'gpt-4o': { provider: 'openai', model: 'gpt-4o' },\n 'gpt-4o-mini': { provider: 'openai', model: 'gpt-4o-mini' },\n 'gpt-4.1': { provider: 'openai', model: 'gpt-4.1' },\n};\n\n/**\n * Default routing based on task type\n * Uses Haiku 3.5 for cost optimization, upgrades based on learned rules\n */\nconst DEFAULT_ROUTING: Record<TaskType, { provider: Provider; model: string }> = {\n code_generation: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n code_review: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n summarization: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n analysis: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n creative_writing: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n data_extraction: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n translation: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n question_answering: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n general: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n};\n\n/**\n * Proxy server configuration\n */\nexport interface ProxyConfig {\n port?: number;\n host?: string;\n dbPath?: string;\n verbose?: boolean;\n}\n\n/**\n * Request body structure\n */\ninterface ChatRequest {\n model: string;\n messages: Array<{ role: string; content: string | unknown }>;\n stream?: boolean;\n max_tokens?: number;\n temperature?: number;\n tools?: unknown[];\n tool_choice?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * Extract text content from messages for routing analysis\n */\nfunction extractPromptText(messages: ChatRequest['messages']): string {\n return messages\n .map((msg) => {\n if (typeof msg.content === 'string') return msg.content;\n if (Array.isArray(msg.content)) {\n return msg.content\n .map((c: unknown) => {\n const part = c as { type?: string; text?: string };\n return part.type === 'text' ? (part.text ?? '') : '';\n })\n .join(' ');\n }\n return '';\n })\n .join('\\n');\n}\n\n/**\n * Forward non-streaming request to Anthropic API\n */\nasync function forwardToAnthropic(\n request: ChatRequest,\n targetModel: string,\n apiKey: string,\n betaHeaders?: string\n): Promise<Response> {\n const anthropicBody = buildAnthropicBody(request, targetModel, false);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n };\n\n // Pass through beta headers (prompt caching, extended thinking, etc.)\n if (betaHeaders) {\n headers['anthropic-beta'] = betaHeaders;\n }\n\n const response = await fetch('https://api.anthropic.com/v1/messages', {\n method: 'POST',\n headers,\n body: JSON.stringify(anthropicBody),\n });\n\n return response;\n}\n\n/**\n * Forward streaming request to Anthropic API\n */\nasync function forwardToAnthropicStream(\n request: ChatRequest,\n targetModel: string,\n apiKey: string,\n betaHeaders?: string\n): Promise<Response> {\n const anthropicBody = buildAnthropicBody(request, targetModel, true);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n };\n\n if (betaHeaders) {\n headers['anthropic-beta'] = betaHeaders;\n }\n\n const response = await fetch('https://api.anthropic.com/v1/messages', {\n method: 'POST',\n headers,\n body: JSON.stringify(anthropicBody),\n });\n\n return response;\n}\n\n/**\n * OpenAI message structure for type safety\n */\ninterface OpenAIMessage {\n role: string;\n content?: string | unknown[] | null;\n tool_calls?: Array<{\n id: string;\n type: string;\n function: { name: string; arguments: string };\n }>;\n tool_call_id?: string;\n name?: string;\n}\n\n/**\n * Convert OpenAI messages array to Anthropic format\n * Handles: user, assistant, tool_calls, tool results\n */\nfunction convertMessagesToAnthropic(messages: Array<{ role: string; content: string | unknown; [key: string]: unknown }>): unknown[] {\n const result: unknown[] = [];\n\n for (const msg of messages) {\n const m = msg as OpenAIMessage;\n\n // Skip system messages (handled separately)\n if (m.role === 'system') continue;\n\n // Tool result message → Anthropic user message with tool_result content\n if (m.role === 'tool') {\n result.push({\n role: 'user',\n content: [\n {\n type: 'tool_result',\n tool_use_id: m.tool_call_id,\n content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content),\n },\n ],\n });\n continue;\n }\n\n // Assistant message with tool_calls → Anthropic assistant with tool_use content\n if (m.role === 'assistant' && m.tool_calls && m.tool_calls.length > 0) {\n const content: unknown[] = [];\n\n // Add text content if present\n if (m.content && typeof m.content === 'string') {\n content.push({ type: 'text', text: m.content });\n }\n\n // Add tool_use blocks\n for (const tc of m.tool_calls) {\n content.push({\n type: 'tool_use',\n id: tc.id,\n name: tc.function.name,\n input: JSON.parse(tc.function.arguments || '{}'),\n });\n }\n\n result.push({ role: 'assistant', content });\n continue;\n }\n\n // Regular user/assistant message\n result.push({\n role: m.role === 'assistant' ? 'assistant' : 'user',\n content: m.content,\n });\n }\n\n return result;\n}\n\n/**\n * Build Anthropic request body from OpenAI format\n */\nfunction buildAnthropicBody(\n request: ChatRequest,\n targetModel: string,\n stream: boolean\n): Record<string, unknown> {\n // Convert OpenAI messages to Anthropic format\n const anthropicMessages = convertMessagesToAnthropic(request.messages);\n\n const systemMessage = request.messages.find((m) => m.role === 'system');\n\n const anthropicBody: Record<string, unknown> = {\n model: targetModel,\n messages: anthropicMessages,\n max_tokens: request.max_tokens ?? 4096,\n stream,\n };\n\n if (systemMessage) {\n anthropicBody['system'] = systemMessage.content;\n }\n\n if (request.temperature !== undefined) {\n anthropicBody['temperature'] = request.temperature;\n }\n\n // Convert OpenAI tools format to Anthropic tools format\n if (request.tools && Array.isArray(request.tools)) {\n anthropicBody['tools'] = convertToolsToAnthropic(request.tools);\n }\n\n // Convert tool_choice\n if (request.tool_choice) {\n anthropicBody['tool_choice'] = convertToolChoiceToAnthropic(request.tool_choice);\n }\n\n return anthropicBody;\n}\n\n/**\n * Convert OpenAI tools format to Anthropic format\n * OpenAI: { type: \"function\", function: { name, description, parameters } }\n * Anthropic: { name, description, input_schema }\n */\nfunction convertToolsToAnthropic(tools: unknown[]): unknown[] {\n return tools.map((tool: unknown) => {\n const t = tool as { type?: string; function?: { name?: string; description?: string; parameters?: unknown } };\n if (t.type === 'function' && t.function) {\n return {\n name: t.function.name,\n description: t.function.description,\n input_schema: t.function.parameters || { type: 'object', properties: {} },\n };\n }\n // Already in Anthropic format or unknown\n return tool;\n });\n}\n\n/**\n * Convert OpenAI tool_choice to Anthropic format\n */\nfunction convertToolChoiceToAnthropic(toolChoice: unknown): unknown {\n if (toolChoice === 'auto') return { type: 'auto' };\n if (toolChoice === 'none') return { type: 'none' };\n if (toolChoice === 'required') return { type: 'any' };\n \n // Specific tool: { type: \"function\", function: { name: \"xxx\" } }\n const tc = toolChoice as { type?: string; function?: { name?: string } };\n if (tc.type === 'function' && tc.function?.name) {\n return { type: 'tool', name: tc.function.name };\n }\n \n return toolChoice;\n}\n\n/**\n * Forward non-streaming request to OpenAI API\n */\nasync function forwardToOpenAI(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const openaiBody = {\n ...request,\n model: targetModel,\n stream: false,\n };\n\n const response = await fetch('https://api.openai.com/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(openaiBody),\n });\n\n return response;\n}\n\n/**\n * Forward streaming request to OpenAI API\n */\nasync function forwardToOpenAIStream(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const openaiBody = {\n ...request,\n model: targetModel,\n stream: true,\n };\n\n const response = await fetch('https://api.openai.com/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(openaiBody),\n });\n\n return response;\n}\n\n/**\n * Forward non-streaming request to xAI API (OpenAI-compatible)\n */\nasync function forwardToXAI(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const xaiBody = {\n ...request,\n model: targetModel,\n stream: false,\n };\n\n const response = await fetch('https://api.x.ai/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(xaiBody),\n });\n\n return response;\n}\n\n/**\n * Forward streaming request to xAI API (OpenAI-compatible)\n */\nasync function forwardToXAIStream(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const xaiBody = {\n ...request,\n model: targetModel,\n stream: true,\n };\n\n const response = await fetch('https://api.x.ai/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(xaiBody),\n });\n\n return response;\n}\n\n/**\n * Forward non-streaming request to Moonshot API (OpenAI-compatible)\n */\nasync function forwardToMoonshot(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const moonshotBody = {\n ...request,\n model: targetModel,\n stream: false,\n };\n\n const response = await fetch('https://api.moonshot.cn/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(moonshotBody),\n });\n\n return response;\n}\n\n/**\n * Forward streaming request to Moonshot API (OpenAI-compatible)\n */\nasync function forwardToMoonshotStream(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const moonshotBody = {\n ...request,\n model: targetModel,\n stream: true,\n };\n\n const response = await fetch('https://api.moonshot.cn/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(moonshotBody),\n });\n\n return response;\n}\n\n/**\n * Convert OpenAI messages to Gemini format\n */\nfunction convertMessagesToGemini(messages: ChatRequest['messages']): unknown[] {\n const geminiContents: unknown[] = [];\n \n for (const msg of messages) {\n // Skip system messages (handled separately via systemInstruction)\n if (msg.role === 'system') continue;\n \n const role = msg.role === 'assistant' ? 'model' : 'user';\n \n if (typeof msg.content === 'string') {\n geminiContents.push({\n role,\n parts: [{ text: msg.content }],\n });\n } else if (Array.isArray(msg.content)) {\n // Handle multimodal content\n const parts = msg.content.map((part: unknown) => {\n const p = part as { type?: string; text?: string; image_url?: { url?: string } };\n if (p.type === 'text') {\n return { text: p.text };\n }\n if (p.type === 'image_url' && p.image_url?.url) {\n // Handle base64 images\n const url = p.image_url.url;\n if (url.startsWith('data:')) {\n const match = url.match(/^data:([^;]+);base64,(.+)$/);\n if (match) {\n return {\n inline_data: {\n mime_type: match[1],\n data: match[2],\n },\n };\n }\n }\n // URL-based images not directly supported, return as text\n return { text: `[Image: ${url}]` };\n }\n return { text: '' };\n });\n geminiContents.push({ role, parts });\n }\n }\n \n return geminiContents;\n}\n\n/**\n * Forward non-streaming request to Gemini API\n */\nasync function forwardToGemini(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const systemMessage = request.messages.find((m) => m.role === 'system');\n const geminiContents = convertMessagesToGemini(request.messages);\n \n const geminiBody: Record<string, unknown> = {\n contents: geminiContents,\n generationConfig: {\n maxOutputTokens: request.max_tokens ?? 4096,\n },\n };\n \n if (request.temperature !== undefined) {\n (geminiBody['generationConfig'] as Record<string, unknown>)['temperature'] = request.temperature;\n }\n \n if (systemMessage && typeof systemMessage.content === 'string') {\n geminiBody['systemInstruction'] = {\n parts: [{ text: systemMessage.content }],\n };\n }\n\n const response = await fetch(\n `https://generativelanguage.googleapis.com/v1beta/models/${targetModel}:generateContent?key=${apiKey}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(geminiBody),\n }\n );\n\n return response;\n}\n\n/**\n * Forward streaming request to Gemini API\n */\nasync function forwardToGeminiStream(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const systemMessage = request.messages.find((m) => m.role === 'system');\n const geminiContents = convertMessagesToGemini(request.messages);\n \n const geminiBody: Record<string, unknown> = {\n contents: geminiContents,\n generationConfig: {\n maxOutputTokens: request.max_tokens ?? 4096,\n },\n };\n \n if (request.temperature !== undefined) {\n (geminiBody['generationConfig'] as Record<string, unknown>)['temperature'] = request.temperature;\n }\n \n if (systemMessage && typeof systemMessage.content === 'string') {\n geminiBody['systemInstruction'] = {\n parts: [{ text: systemMessage.content }],\n };\n }\n\n const response = await fetch(\n `https://generativelanguage.googleapis.com/v1beta/models/${targetModel}:streamGenerateContent?alt=sse&key=${apiKey}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(geminiBody),\n }\n );\n\n return response;\n}\n\n/**\n * Gemini API response structure\n */\ninterface GeminiResponse {\n candidates?: Array<{\n content?: { parts?: Array<{ text?: string }> };\n finishReason?: string;\n }>;\n usageMetadata?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n };\n}\n\n/**\n * Convert Gemini response to OpenAI format\n */\nfunction convertGeminiResponse(geminiData: GeminiResponse, model: string): Record<string, unknown> {\n const candidate = geminiData.candidates?.[0];\n const text = candidate?.content?.parts?.map((p) => p.text ?? '').join('') ?? '';\n \n let finishReason = 'stop';\n if (candidate?.finishReason === 'MAX_TOKENS') {\n finishReason = 'length';\n } else if (candidate?.finishReason === 'SAFETY') {\n finishReason = 'content_filter';\n }\n\n return {\n id: `chatcmpl-${Date.now()}`,\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n message: {\n role: 'assistant',\n content: text,\n },\n finish_reason: finishReason,\n },\n ],\n usage: {\n prompt_tokens: geminiData.usageMetadata?.promptTokenCount ?? 0,\n completion_tokens: geminiData.usageMetadata?.candidatesTokenCount ?? 0,\n total_tokens:\n (geminiData.usageMetadata?.promptTokenCount ?? 0) +\n (geminiData.usageMetadata?.candidatesTokenCount ?? 0),\n },\n };\n}\n\n/**\n * Convert Gemini streaming event to OpenAI format\n */\nfunction convertGeminiStreamEvent(\n eventData: GeminiResponse,\n messageId: string,\n model: string,\n isFirst: boolean\n): string | null {\n const candidate = eventData.candidates?.[0];\n const text = candidate?.content?.parts?.map((p) => p.text ?? '').join('') ?? '';\n \n const choice: Record<string, unknown> = {\n index: 0,\n delta: {},\n finish_reason: null,\n };\n \n if (isFirst) {\n choice['delta'] = { role: 'assistant', content: text };\n } else if (text) {\n choice['delta'] = { content: text };\n }\n \n // Check for finish\n if (candidate?.finishReason) {\n let finishReason = 'stop';\n if (candidate.finishReason === 'MAX_TOKENS') {\n finishReason = 'length';\n } else if (candidate.finishReason === 'SAFETY') {\n finishReason = 'content_filter';\n }\n choice['finish_reason'] = finishReason;\n }\n \n const chunk = {\n id: messageId,\n object: 'chat.completion.chunk',\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [choice],\n };\n \n return `data: ${JSON.stringify(chunk)}\\n\\n`;\n}\n\n/**\n * Parse Gemini SSE stream and convert to OpenAI format\n */\nasync function* convertGeminiStream(\n response: Response,\n model: string\n): AsyncGenerator<string, void, unknown> {\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n const messageId = `chatcmpl-${Date.now()}`;\n let isFirst = true;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Process complete SSE events (Gemini uses \"data: \" prefix)\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const jsonStr = line.slice(6);\n if (jsonStr.trim() === '[DONE]') {\n yield 'data: [DONE]\\n\\n';\n continue;\n }\n try {\n const parsed = JSON.parse(jsonStr) as GeminiResponse;\n const converted = convertGeminiStreamEvent(parsed, messageId, model, isFirst);\n if (converted) {\n yield converted;\n isFirst = false;\n }\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n \n // Send [DONE] at the end\n yield 'data: [DONE]\\n\\n';\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Anthropic API response structure\n */\ninterface AnthropicResponse {\n id?: string;\n model?: string;\n content?: Array<{ type: string; text?: string; id?: string; name?: string; input?: unknown }>;\n usage?: { input_tokens?: number; output_tokens?: number };\n stop_reason?: string;\n}\n\n/**\n * Convert Anthropic response to OpenAI format\n * Handles both text and tool_use content blocks\n */\nfunction convertAnthropicResponse(anthropicData: AnthropicResponse): Record<string, unknown> {\n const textBlocks = anthropicData.content?.filter((c) => c.type === 'text') ?? [];\n const toolBlocks = anthropicData.content?.filter((c) => c.type === 'tool_use') ?? [];\n\n const textContent = textBlocks.map((c) => c.text ?? '').join('');\n\n // Build message object\n const message: Record<string, unknown> = {\n role: 'assistant',\n content: textContent || null,\n };\n\n // Convert tool_use blocks to OpenAI tool_calls format\n if (toolBlocks.length > 0) {\n message['tool_calls'] = toolBlocks.map((block) => ({\n id: block.id || `call_${Date.now()}`,\n type: 'function',\n function: {\n name: block.name,\n arguments: typeof block.input === 'string' ? block.input : JSON.stringify(block.input ?? {}),\n },\n }));\n }\n\n // Determine finish_reason\n let finishReason = 'stop';\n if (anthropicData.stop_reason === 'tool_use') {\n finishReason = 'tool_calls';\n } else if (anthropicData.stop_reason === 'end_turn') {\n finishReason = 'stop';\n } else if (anthropicData.stop_reason) {\n finishReason = anthropicData.stop_reason;\n }\n\n return {\n id: anthropicData.id || `chatcmpl-${Date.now()}`,\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: anthropicData.model,\n choices: [\n {\n index: 0,\n message,\n finish_reason: finishReason,\n },\n ],\n usage: {\n prompt_tokens: anthropicData.usage?.input_tokens ?? 0,\n completion_tokens: anthropicData.usage?.output_tokens ?? 0,\n total_tokens: (anthropicData.usage?.input_tokens ?? 0) + (anthropicData.usage?.output_tokens ?? 0),\n },\n };\n}\n\n/**\n * Streaming state for tracking tool calls across events\n */\ninterface StreamingToolState {\n currentToolIndex: number;\n tools: Map<number, { id: string; name: string; arguments: string }>;\n}\n\n/**\n * Convert Anthropic streaming event to OpenAI streaming chunk format\n * Handles both text content and tool_use streaming\n */\nfunction convertAnthropicStreamEvent(\n eventType: string,\n eventData: Record<string, unknown>,\n messageId: string,\n model: string,\n toolState: StreamingToolState\n): string | null {\n const choice = { index: 0, delta: {} as Record<string, unknown>, finish_reason: null as string | null };\n const baseChunk = {\n id: messageId,\n object: 'chat.completion.chunk',\n created: Math.floor(Date.now() / 1000),\n model: model,\n choices: [choice],\n };\n\n switch (eventType) {\n case 'message_start': {\n // First chunk: include role\n const msg = eventData['message'] as Record<string, unknown> | undefined;\n baseChunk.id = (msg?.['id'] as string) || messageId;\n choice.delta = { role: 'assistant', content: '' };\n return `data: ${JSON.stringify(baseChunk)}\\n\\n`;\n }\n\n case 'content_block_start': {\n // New content block starting - could be text or tool_use\n const contentBlock = eventData['content_block'] as Record<string, unknown> | undefined;\n const blockIndex = eventData['index'] as number | undefined;\n \n if (contentBlock?.['type'] === 'tool_use') {\n // Tool use starting - send first chunk with tool info\n const toolId = contentBlock['id'] as string;\n const toolName = contentBlock['name'] as string;\n \n toolState.tools.set(blockIndex ?? toolState.currentToolIndex, {\n id: toolId,\n name: toolName,\n arguments: '',\n });\n toolState.currentToolIndex = blockIndex ?? toolState.currentToolIndex;\n \n choice.delta = {\n tool_calls: [{\n index: blockIndex ?? 0,\n id: toolId,\n type: 'function',\n function: { name: toolName, arguments: '' },\n }],\n };\n return `data: ${JSON.stringify(baseChunk)}\\n\\n`;\n }\n return null;\n }\n\n case 'content_block_delta': {\n // Content chunk - text or tool arguments\n const delta = eventData['delta'] as Record<string, unknown> | undefined;\n const blockIndex = eventData['index'] as number | undefined;\n \n if (delta?.['type'] === 'text_delta') {\n choice.delta = { content: delta['text'] as string };\n return `data: ${JSON.stringify(baseChunk)}\\n\\n`;\n }\n \n if (delta?.['type'] === 'input_json_delta') {\n // Tool arguments streaming\n const partialJson = delta['partial_json'] as string || '';\n const tool = toolState.tools.get(blockIndex ?? toolState.currentToolIndex);\n if (tool) {\n tool.arguments += partialJson;\n }\n \n choice.delta = {\n tool_calls: [{\n index: blockIndex ?? 0,\n function: { arguments: partialJson },\n }],\n };\n return `data: ${JSON.stringify(baseChunk)}\\n\\n`;\n }\n return null;\n }\n\n case 'message_delta': {\n // Final chunk with stop reason\n const delta = eventData['delta'] as Record<string, unknown> | undefined;\n const stopReason = delta?.['stop_reason'] as string | undefined;\n \n if (stopReason === 'tool_use') {\n choice.finish_reason = 'tool_calls';\n } else if (stopReason === 'end_turn') {\n choice.finish_reason = 'stop';\n } else {\n choice.finish_reason = stopReason || 'stop';\n }\n choice.delta = {};\n return `data: ${JSON.stringify(baseChunk)}\\n\\n`;\n }\n\n case 'message_stop': {\n // Stream complete\n return 'data: [DONE]\\n\\n';\n }\n\n default:\n return null;\n }\n}\n\n/**\n * Parse SSE stream from Anthropic and convert to OpenAI format\n */\nasync function* convertAnthropicStream(\n response: Response,\n model: string\n): AsyncGenerator<string, void, unknown> {\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n let messageId = `chatcmpl-${Date.now()}`;\n \n // Tool state for tracking streaming tool calls\n const toolState: StreamingToolState = {\n currentToolIndex: 0,\n tools: new Map(),\n };\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Process complete SSE events\n const lines = buffer.split('\\n');\n buffer = lines.pop() || ''; // Keep incomplete line in buffer\n\n let eventType = '';\n let eventData = '';\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n eventType = line.slice(7).trim();\n } else if (line.startsWith('data: ')) {\n eventData = line.slice(6);\n } else if (line === '' && eventType && eventData) {\n // Complete event, process it\n try {\n const parsed = JSON.parse(eventData) as Record<string, unknown>;\n const converted = convertAnthropicStreamEvent(eventType, parsed, messageId, model, toolState);\n if (converted) {\n yield converted;\n }\n } catch {\n // Skip malformed JSON\n }\n eventType = '';\n eventData = '';\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Pipe OpenAI streaming response directly (already in correct format)\n */\nasync function* pipeOpenAIStream(\n response: Response\n): AsyncGenerator<string, void, unknown> {\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n yield decoder.decode(value, { stream: true });\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Parse preferred model string (format: \"provider:model\")\n */\nfunction parsePreferredModel(\n preferredModel: string\n): { provider: Provider; model: string } | null {\n const [provider, model] = preferredModel.split(':');\n if (!provider || !model) return null;\n\n // Validate provider\n const validProviders: Provider[] = ['openai', 'anthropic', 'google', 'xai', 'moonshot', 'local'];\n if (!validProviders.includes(provider as Provider)) return null;\n\n return { provider: provider as Provider, model };\n}\n\n/**\n * Resolve explicit model name to provider and model\n * Handles direct model names like \"claude-3-5-sonnet-latest\" or \"gpt-4o\"\n */\nfunction resolveExplicitModel(\n modelName: string\n): { provider: Provider; model: string } | null {\n // Check MODEL_MAPPING first (aliases)\n if (MODEL_MAPPING[modelName]) {\n return MODEL_MAPPING[modelName];\n }\n\n // Anthropic models (claude-*)\n if (modelName.startsWith('claude-')) {\n return { provider: 'anthropic', model: modelName };\n }\n\n // OpenAI models (gpt-*, o1-*, chatgpt-*, text-*, dall-e-*, whisper-*, tts-*)\n if (\n modelName.startsWith('gpt-') ||\n modelName.startsWith('o1-') ||\n modelName.startsWith('o3-') ||\n modelName.startsWith('chatgpt-') ||\n modelName.startsWith('text-') ||\n modelName.startsWith('dall-e') ||\n modelName.startsWith('whisper') ||\n modelName.startsWith('tts-')\n ) {\n return { provider: 'openai', model: modelName };\n }\n\n // Google models (gemini-*, palm-*)\n if (modelName.startsWith('gemini-') || modelName.startsWith('palm-')) {\n return { provider: 'google', model: modelName };\n }\n\n // xAI models (grok-*)\n if (modelName.startsWith('grok-')) {\n return { provider: 'xai', model: modelName };\n }\n\n // Moonshot models (moonshot-*)\n if (modelName.startsWith('moonshot-')) {\n return { provider: 'moonshot', model: modelName };\n }\n\n // Provider-prefixed format: \"anthropic/claude-3-5-sonnet-latest\"\n if (modelName.includes('/')) {\n const [provider, model] = modelName.split('/');\n const validProviders: Provider[] = ['openai', 'anthropic', 'google', 'xai', 'moonshot', 'local'];\n if (provider && model && validProviders.includes(provider as Provider)) {\n return { provider: provider as Provider, model };\n }\n }\n\n return null;\n}\n\n/**\n * Start the RelayPlane proxy server\n */\nexport async function startProxy(config: ProxyConfig = {}): Promise<http.Server> {\n const port = config.port ?? 3001;\n const host = config.host ?? '127.0.0.1';\n const verbose = config.verbose ?? false;\n\n // Initialize RelayPlane\n const relay = new RelayPlane({ dbPath: config.dbPath });\n\n const log = (msg: string) => {\n if (verbose) console.log(`[relayplane] ${msg}`);\n };\n\n const server = http.createServer(async (req, res) => {\n // CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Only handle POST to /v1/chat/completions\n if (req.method !== 'POST' || !req.url?.includes('/chat/completions')) {\n // Return model list for /v1/models\n if (req.method === 'GET' && req.url?.includes('/models')) {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n object: 'list',\n data: [\n { id: 'relayplane:auto', object: 'model', owned_by: 'relayplane' },\n { id: 'relayplane:cost', object: 'model', owned_by: 'relayplane' },\n { id: 'relayplane:quality', object: 'model', owned_by: 'relayplane' },\n ],\n })\n );\n return;\n }\n\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n return;\n }\n\n // Parse request body\n let body = '';\n for await (const chunk of req) {\n body += chunk;\n }\n\n let request: ChatRequest;\n try {\n request = JSON.parse(body);\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid JSON' }));\n return;\n }\n\n const isStreaming = request.stream === true;\n\n // Extract routing mode from model name\n const requestedModel = request.model;\n let routingMode: 'auto' | 'cost' | 'quality' | 'passthrough' = 'auto';\n let targetModel: string = '';\n let targetProvider: Provider = 'anthropic';\n\n // Check if this is a RelayPlane routing model or explicit pass-through\n if (requestedModel.startsWith('relayplane:')) {\n // RelayPlane smart routing\n if (requestedModel.includes(':cost')) {\n routingMode = 'cost';\n } else if (requestedModel.includes(':quality')) {\n routingMode = 'quality';\n }\n } else {\n // Explicit model pass-through (L3 mode)\n routingMode = 'passthrough';\n const resolved = resolveExplicitModel(requestedModel);\n if (resolved) {\n targetProvider = resolved.provider;\n targetModel = resolved.model;\n log(`Pass-through mode: ${requestedModel} → ${targetProvider}/${targetModel}`);\n } else {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: `Unknown model: ${requestedModel}` }));\n return;\n }\n }\n\n log(`Received request for model: ${requestedModel} (mode: ${routingMode}, stream: ${isStreaming})`);\n\n // Infer task type from prompt (for logging/learning, even in passthrough)\n const promptText = extractPromptText(request.messages);\n const taskType = inferTaskType(promptText);\n const confidence = getInferenceConfidence(promptText, taskType);\n\n log(`Inferred task: ${taskType} (confidence: ${confidence.toFixed(2)})`);\n\n // Smart routing only for RelayPlane models\n if (routingMode !== 'passthrough') {\n // Check if there's a learned rule for this task type\n const rule = relay.routing.get(taskType);\n\n if (rule && rule.preferredModel) {\n const parsed = parsePreferredModel(rule.preferredModel);\n if (parsed) {\n targetProvider = parsed.provider;\n targetModel = parsed.model;\n log(`Using learned rule: ${rule.preferredModel}`);\n } else {\n // Fallback to defaults\n const defaultRoute = DEFAULT_ROUTING[taskType];\n targetProvider = defaultRoute.provider;\n targetModel = defaultRoute.model;\n }\n } else {\n // Use default routing\n const defaultRoute = DEFAULT_ROUTING[taskType];\n targetProvider = defaultRoute.provider;\n targetModel = defaultRoute.model;\n }\n\n // Override based on routing mode\n if (routingMode === 'cost') {\n // Prefer cheapest: Haiku for simple tasks\n const simpleTasks: TaskType[] = ['summarization', 'data_extraction', 'translation', 'question_answering'];\n if (simpleTasks.includes(taskType)) {\n targetModel = 'claude-3-5-haiku-latest';\n targetProvider = 'anthropic';\n }\n } else if (routingMode === 'quality') {\n // Quality mode: Always use the best available model\n const qualityModel = process.env['RELAYPLANE_QUALITY_MODEL'] || 'claude-3-5-sonnet-latest';\n targetModel = qualityModel;\n targetProvider = 'anthropic';\n }\n }\n\n log(`Routing to: ${targetProvider}/${targetModel}`);\n\n // Get API key for target provider\n const apiKeyEnv = DEFAULT_ENDPOINTS[targetProvider]?.apiKeyEnv ?? `${targetProvider.toUpperCase()}_API_KEY`;\n const apiKey = process.env[apiKeyEnv];\n\n if (!apiKey) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: `Missing ${apiKeyEnv} environment variable` }));\n return;\n }\n\n const startTime = Date.now();\n\n // Extract Anthropic beta headers from request (for prompt caching, extended thinking, etc.)\n const betaHeaders = req.headers['anthropic-beta'] as string | undefined;\n\n // Handle streaming vs non-streaming\n if (isStreaming) {\n await handleStreamingRequest(\n res,\n request,\n targetProvider,\n targetModel,\n apiKey,\n relay,\n promptText,\n taskType,\n confidence,\n routingMode,\n startTime,\n log,\n betaHeaders\n );\n } else {\n await handleNonStreamingRequest(\n res,\n request,\n targetProvider,\n targetModel,\n apiKey,\n relay,\n promptText,\n taskType,\n confidence,\n routingMode,\n startTime,\n log,\n betaHeaders\n );\n }\n });\n\n return new Promise((resolve, reject) => {\n server.on('error', reject);\n server.listen(port, host, () => {\n console.log(`RelayPlane proxy listening on http://${host}:${port}`);\n console.log(` Models: relayplane:auto, relayplane:cost, relayplane:quality`);\n console.log(` Endpoint: POST /v1/chat/completions`);\n console.log(` Streaming: ✅ Enabled`);\n resolve(server);\n });\n });\n}\n\n/**\n * Handle streaming request\n */\nasync function handleStreamingRequest(\n res: http.ServerResponse,\n request: ChatRequest,\n targetProvider: Provider,\n targetModel: string,\n apiKey: string,\n relay: RelayPlane,\n promptText: string,\n taskType: TaskType,\n confidence: number,\n routingMode: string,\n startTime: number,\n log: (msg: string) => void,\n betaHeaders?: string\n): Promise<void> {\n let providerResponse: Response;\n\n try {\n switch (targetProvider) {\n case 'anthropic':\n providerResponse = await forwardToAnthropicStream(request, targetModel, apiKey, betaHeaders);\n break;\n case 'google':\n providerResponse = await forwardToGeminiStream(request, targetModel, apiKey);\n break;\n case 'xai':\n providerResponse = await forwardToXAIStream(request, targetModel, apiKey);\n break;\n case 'moonshot':\n providerResponse = await forwardToMoonshotStream(request, targetModel, apiKey);\n break;\n default:\n providerResponse = await forwardToOpenAIStream(request, targetModel, apiKey);\n }\n\n if (!providerResponse.ok) {\n const errorData = await providerResponse.json();\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(errorData));\n return;\n }\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: `Provider error: ${errorMsg}` }));\n return;\n }\n\n // Set SSE headers\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n });\n\n try {\n // Stream the response based on provider format\n switch (targetProvider) {\n case 'anthropic':\n // Convert Anthropic stream to OpenAI format\n for await (const chunk of convertAnthropicStream(providerResponse, targetModel)) {\n res.write(chunk);\n }\n break;\n case 'google':\n // Convert Gemini stream to OpenAI format\n for await (const chunk of convertGeminiStream(providerResponse, targetModel)) {\n res.write(chunk);\n }\n break;\n default:\n // xAI, Moonshot, OpenAI all use OpenAI-compatible streaming format\n for await (const chunk of pipeOpenAIStream(providerResponse)) {\n res.write(chunk);\n }\n }\n } catch (err) {\n log(`Streaming error: ${err}`);\n }\n\n const durationMs = Date.now() - startTime;\n\n // Record the run (non-blocking)\n relay\n .run({\n prompt: promptText.slice(0, 500),\n taskType,\n model: `${targetProvider}:${targetModel}`,\n })\n .then((runResult) => {\n log(`Completed streaming in ${durationMs}ms, runId: ${runResult.runId}`);\n })\n .catch((err) => {\n log(`Failed to record run: ${err}`);\n });\n\n res.end();\n}\n\n/**\n * Handle non-streaming request\n */\nasync function handleNonStreamingRequest(\n res: http.ServerResponse,\n request: ChatRequest,\n targetProvider: Provider,\n targetModel: string,\n apiKey: string,\n relay: RelayPlane,\n promptText: string,\n taskType: TaskType,\n confidence: number,\n routingMode: string,\n startTime: number,\n log: (msg: string) => void,\n betaHeaders?: string\n): Promise<void> {\n let providerResponse: Response;\n let responseData: Record<string, unknown>;\n\n try {\n switch (targetProvider) {\n case 'anthropic': {\n providerResponse = await forwardToAnthropic(request, targetModel, apiKey, betaHeaders);\n const rawData = (await providerResponse.json()) as AnthropicResponse;\n\n if (!providerResponse.ok) {\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(rawData));\n return;\n }\n\n // Convert to OpenAI format\n responseData = convertAnthropicResponse(rawData);\n break;\n }\n case 'google': {\n providerResponse = await forwardToGemini(request, targetModel, apiKey);\n const rawData = (await providerResponse.json()) as GeminiResponse;\n\n if (!providerResponse.ok) {\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(rawData));\n return;\n }\n\n // Convert to OpenAI format\n responseData = convertGeminiResponse(rawData, targetModel);\n break;\n }\n case 'xai': {\n providerResponse = await forwardToXAI(request, targetModel, apiKey);\n responseData = (await providerResponse.json()) as Record<string, unknown>;\n\n if (!providerResponse.ok) {\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(responseData));\n return;\n }\n break;\n }\n case 'moonshot': {\n providerResponse = await forwardToMoonshot(request, targetModel, apiKey);\n responseData = (await providerResponse.json()) as Record<string, unknown>;\n\n if (!providerResponse.ok) {\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(responseData));\n return;\n }\n break;\n }\n default: {\n providerResponse = await forwardToOpenAI(request, targetModel, apiKey);\n responseData = (await providerResponse.json()) as Record<string, unknown>;\n\n if (!providerResponse.ok) {\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(responseData));\n return;\n }\n }\n }\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: `Provider error: ${errorMsg}` }));\n return;\n }\n\n const durationMs = Date.now() - startTime;\n\n // Record the run in RelayPlane\n try {\n const runResult = await relay.run({\n prompt: promptText.slice(0, 500),\n taskType,\n model: `${targetProvider}:${targetModel}`,\n });\n\n // Add routing metadata to response\n responseData['_relayplane'] = {\n runId: runResult.runId,\n routedTo: `${targetProvider}/${targetModel}`,\n taskType,\n confidence,\n durationMs,\n mode: routingMode,\n };\n\n log(`Completed in ${durationMs}ms, runId: ${runResult.runId}`);\n } catch (err) {\n log(`Failed to record run: ${err}`);\n }\n\n // Send response\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(responseData));\n}\n\n/**\n * CLI entry point\n */\nexport async function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n let port = 3001;\n let verbose = false;\n\n for (let i = 0; i < args.length; i++) {\n if (args[i] === '--port' && args[i + 1]) {\n port = parseInt(args[i + 1] ?? '3001', 10);\n i++;\n } else if (args[i] === '-v' || args[i] === '--verbose') {\n verbose = true;\n }\n }\n\n try {\n await startProxy({ port, verbose });\n } catch (err) {\n console.error('Failed to start proxy:', err);\n process.exit(1);\n }\n}\n\n// Note: Use cli.ts for direct execution\n// This module is imported by cli.ts\n","/**\n * SQLite Storage Implementation\n *\n * Provides persistent storage for runs, outcomes, routing rules, and suggestions.\n *\n * @packageDocumentation\n */\n\nimport Database from 'better-sqlite3';\nimport { nanoid } from 'nanoid';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\nimport { SCHEMA_SQL, generateSeedSQL } from './schema.js';\nimport type {\n RunRecord,\n OutcomeRecord,\n RuleRecord,\n SuggestionRecord,\n TaskType,\n RuleSource,\n OutcomeQuality,\n} from '../types.js';\n\n/**\n * Default database path.\n */\nexport function getDefaultDbPath(): string {\n return path.join(os.homedir(), '.relayplane', 'data.db');\n}\n\n/**\n * SQLite storage class for RelayPlane data.\n */\nexport class Store {\n private db: Database.Database;\n private readonly dbPath: string;\n\n /**\n * Creates a new Store instance.\n *\n * @param dbPath - Path to the SQLite database file. Defaults to ~/.relayplane/data.db\n */\n constructor(dbPath?: string) {\n this.dbPath = dbPath ?? getDefaultDbPath();\n\n // Ensure directory exists\n const dir = path.dirname(this.dbPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Open database\n this.db = new Database(this.dbPath);\n\n // Enable WAL mode for better concurrent access\n this.db.pragma('journal_mode = WAL');\n\n // Enable foreign keys\n this.db.pragma('foreign_keys = ON');\n\n // Initialize schema\n this.initializeSchema();\n }\n\n /**\n * Initializes the database schema.\n */\n private initializeSchema(): void {\n this.db.exec(SCHEMA_SQL);\n this.db.exec(generateSeedSQL());\n }\n\n /**\n * Closes the database connection.\n */\n close(): void {\n this.db.close();\n }\n\n /**\n * Gets the database path.\n */\n getDbPath(): string {\n return this.dbPath;\n }\n\n // ============================================================================\n // Runs\n // ============================================================================\n\n /**\n * Records a new run.\n */\n recordRun(run: Omit<RunRecord, 'id' | 'createdAt'>): string {\n const id = nanoid();\n const stmt = this.db.prepare(`\n INSERT INTO runs (id, prompt, system_prompt, task_type, model, success, output, error, duration_ms, tokens_in, tokens_out, cost_usd, metadata, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))\n `);\n\n stmt.run(\n id,\n run.prompt,\n run.systemPrompt,\n run.taskType,\n run.model,\n run.success ? 1 : 0,\n run.output,\n run.error,\n run.durationMs,\n run.tokensIn,\n run.tokensOut,\n run.costUsd,\n run.metadata\n );\n\n return id;\n }\n\n /**\n * Gets a run by ID.\n */\n getRun(id: string): RunRecord | null {\n const stmt = this.db.prepare(`\n SELECT id, prompt, system_prompt as systemPrompt, task_type as taskType, model, success, output, error, duration_ms as durationMs, tokens_in as tokensIn, tokens_out as tokensOut, cost_usd as costUsd, metadata, created_at as createdAt\n FROM runs\n WHERE id = ?\n `);\n\n const row = stmt.get(id) as RunRecord | undefined;\n if (!row) return null;\n\n return {\n ...row,\n success: Boolean(row.success),\n };\n }\n\n /**\n * Gets runs with optional filters.\n */\n getRuns(options?: {\n taskType?: TaskType;\n model?: string;\n limit?: number;\n offset?: number;\n from?: string;\n to?: string;\n }): RunRecord[] {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options?.taskType) {\n conditions.push('task_type = ?');\n params.push(options.taskType);\n }\n\n if (options?.model) {\n conditions.push('model = ?');\n params.push(options.model);\n }\n\n if (options?.from) {\n conditions.push('created_at >= ?');\n params.push(options.from);\n }\n\n if (options?.to) {\n conditions.push('created_at <= ?');\n params.push(options.to);\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const limit = options?.limit ?? 100;\n const offset = options?.offset ?? 0;\n\n const stmt = this.db.prepare(`\n SELECT id, prompt, system_prompt as systemPrompt, task_type as taskType, model, success, output, error, duration_ms as durationMs, tokens_in as tokensIn, tokens_out as tokensOut, cost_usd as costUsd, metadata, created_at as createdAt\n FROM runs\n ${whereClause}\n ORDER BY created_at DESC\n LIMIT ? OFFSET ?\n `);\n\n params.push(limit, offset);\n\n const rows = stmt.all(...params) as RunRecord[];\n return rows.map((row) => ({\n ...row,\n success: Boolean(row.success),\n }));\n }\n\n /**\n * Counts runs with optional filters.\n */\n countRuns(options?: {\n taskType?: TaskType;\n model?: string;\n from?: string;\n to?: string;\n }): number {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options?.taskType) {\n conditions.push('task_type = ?');\n params.push(options.taskType);\n }\n\n if (options?.model) {\n conditions.push('model = ?');\n params.push(options.model);\n }\n\n if (options?.from) {\n conditions.push('created_at >= ?');\n params.push(options.from);\n }\n\n if (options?.to) {\n conditions.push('created_at <= ?');\n params.push(options.to);\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n\n const stmt = this.db.prepare(`\n SELECT COUNT(*) as count\n FROM runs\n ${whereClause}\n `);\n\n const row = stmt.get(...params) as { count: number };\n return row.count;\n }\n\n // ============================================================================\n // Outcomes\n // ============================================================================\n\n /**\n * Records an outcome for a run.\n */\n recordOutcome(outcome: Omit<OutcomeRecord, 'id' | 'createdAt'>): string {\n const id = nanoid();\n const stmt = this.db.prepare(`\n INSERT INTO outcomes (id, run_id, success, quality, latency_satisfactory, cost_satisfactory, feedback, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))\n ON CONFLICT(run_id) DO UPDATE SET\n success = excluded.success,\n quality = excluded.quality,\n latency_satisfactory = excluded.latency_satisfactory,\n cost_satisfactory = excluded.cost_satisfactory,\n feedback = excluded.feedback,\n created_at = datetime('now')\n `);\n\n stmt.run(\n id,\n outcome.runId,\n outcome.success ? 1 : 0,\n outcome.quality,\n outcome.latencySatisfactory != null ? (outcome.latencySatisfactory ? 1 : 0) : null,\n outcome.costSatisfactory != null ? (outcome.costSatisfactory ? 1 : 0) : null,\n outcome.feedback\n );\n\n return id;\n }\n\n /**\n * Gets an outcome for a run.\n */\n getOutcome(runId: string): OutcomeRecord | null {\n const stmt = this.db.prepare(`\n SELECT id, run_id as runId, success, quality, latency_satisfactory as latencySatisfactory, cost_satisfactory as costSatisfactory, feedback, created_at as createdAt\n FROM outcomes\n WHERE run_id = ?\n `);\n\n const row = stmt.get(runId) as OutcomeRecord | undefined;\n if (!row) return null;\n\n return {\n ...row,\n success: Boolean(row.success),\n latencySatisfactory: row.latencySatisfactory != null ? Boolean(row.latencySatisfactory) : null,\n costSatisfactory: row.costSatisfactory != null ? Boolean(row.costSatisfactory) : null,\n };\n }\n\n /**\n * Gets outcomes with optional filters.\n */\n getOutcomes(options?: {\n taskType?: TaskType;\n model?: string;\n limit?: number;\n from?: string;\n to?: string;\n }): Array<OutcomeRecord & { taskType: TaskType; model: string }> {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options?.taskType) {\n conditions.push('r.task_type = ?');\n params.push(options.taskType);\n }\n\n if (options?.model) {\n conditions.push('r.model = ?');\n params.push(options.model);\n }\n\n if (options?.from) {\n conditions.push('o.created_at >= ?');\n params.push(options.from);\n }\n\n if (options?.to) {\n conditions.push('o.created_at <= ?');\n params.push(options.to);\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const limit = options?.limit ?? 100;\n\n const stmt = this.db.prepare(`\n SELECT o.id, o.run_id as runId, o.success, o.quality, o.latency_satisfactory as latencySatisfactory, o.cost_satisfactory as costSatisfactory, o.feedback, o.created_at as createdAt, r.task_type as taskType, r.model\n FROM outcomes o\n JOIN runs r ON o.run_id = r.id\n ${whereClause}\n ORDER BY o.created_at DESC\n LIMIT ?\n `);\n\n params.push(limit);\n\n const rows = stmt.all(...params) as Array<OutcomeRecord & { taskType: TaskType; model: string }>;\n return rows.map((row) => ({\n ...row,\n success: Boolean(row.success),\n latencySatisfactory: row.latencySatisfactory != null ? Boolean(row.latencySatisfactory) : null,\n costSatisfactory: row.costSatisfactory != null ? Boolean(row.costSatisfactory) : null,\n }));\n }\n\n // ============================================================================\n // Routing Rules\n // ============================================================================\n\n /**\n * Gets a routing rule for a task type.\n */\n getRule(taskType: TaskType): RuleRecord | null {\n const stmt = this.db.prepare(`\n SELECT id, task_type as taskType, preferred_model as preferredModel, source, confidence, sample_count as sampleCount, created_at as createdAt, updated_at as updatedAt\n FROM routing_rules\n WHERE task_type = ?\n `);\n\n return (stmt.get(taskType) as RuleRecord | undefined) ?? null;\n }\n\n /**\n * Sets a routing rule for a task type.\n */\n setRule(taskType: TaskType, preferredModel: string, source: RuleSource, confidence?: number, sampleCount?: number): string {\n const existingRule = this.getRule(taskType);\n const id = existingRule?.id ?? nanoid();\n\n const stmt = this.db.prepare(`\n INSERT INTO routing_rules (id, task_type, preferred_model, source, confidence, sample_count, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))\n ON CONFLICT(task_type) DO UPDATE SET\n preferred_model = excluded.preferred_model,\n source = excluded.source,\n confidence = excluded.confidence,\n sample_count = excluded.sample_count,\n updated_at = datetime('now')\n `);\n\n stmt.run(id, taskType, preferredModel, source, confidence ?? null, sampleCount ?? null);\n\n return id;\n }\n\n /**\n * Lists all routing rules.\n */\n listRules(): RuleRecord[] {\n const stmt = this.db.prepare(`\n SELECT id, task_type as taskType, preferred_model as preferredModel, source, confidence, sample_count as sampleCount, created_at as createdAt, updated_at as updatedAt\n FROM routing_rules\n ORDER BY task_type\n `);\n\n return stmt.all() as RuleRecord[];\n }\n\n /**\n * Deletes a routing rule and resets to default.\n */\n deleteRule(taskType: TaskType): boolean {\n // Find the default rule for this task type\n const defaultRule = DEFAULT_ROUTING_RULES.find((r) => r.taskType === taskType);\n if (!defaultRule) return false;\n\n // Reset to default\n this.setRule(taskType, defaultRule.preferredModel, 'default');\n return true;\n }\n\n // ============================================================================\n // Suggestions\n // ============================================================================\n\n /**\n * Records a suggestion.\n */\n recordSuggestion(suggestion: Omit<SuggestionRecord, 'id' | 'createdAt' | 'acceptedAt'>): string {\n const id = nanoid();\n const stmt = this.db.prepare(`\n INSERT INTO suggestions (id, task_type, current_model, suggested_model, reason, confidence, expected_improvement, sample_count, accepted, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))\n `);\n\n stmt.run(\n id,\n suggestion.taskType,\n suggestion.currentModel,\n suggestion.suggestedModel,\n suggestion.reason,\n suggestion.confidence,\n suggestion.expectedImprovement,\n suggestion.sampleCount,\n suggestion.accepted ?? null\n );\n\n return id;\n }\n\n /**\n * Gets a suggestion by ID.\n */\n getSuggestion(id: string): SuggestionRecord | null {\n const stmt = this.db.prepare(`\n SELECT id, task_type as taskType, current_model as currentModel, suggested_model as suggestedModel, reason, confidence, expected_improvement as expectedImprovement, sample_count as sampleCount, accepted, created_at as createdAt, accepted_at as acceptedAt\n FROM suggestions\n WHERE id = ?\n `);\n\n const row = stmt.get(id) as SuggestionRecord | undefined;\n if (!row) return null;\n\n return {\n ...row,\n accepted: row.accepted != null ? Boolean(row.accepted) : null,\n };\n }\n\n /**\n * Gets pending (unaccepted) suggestions.\n */\n getPendingSuggestions(): SuggestionRecord[] {\n const stmt = this.db.prepare(`\n SELECT id, task_type as taskType, current_model as currentModel, suggested_model as suggestedModel, reason, confidence, expected_improvement as expectedImprovement, sample_count as sampleCount, accepted, created_at as createdAt, accepted_at as acceptedAt\n FROM suggestions\n WHERE accepted IS NULL\n ORDER BY confidence DESC\n `);\n\n const rows = stmt.all() as SuggestionRecord[];\n return rows.map((row) => ({\n ...row,\n accepted: row.accepted != null ? Boolean(row.accepted) : null,\n }));\n }\n\n /**\n * Accepts a suggestion.\n */\n acceptSuggestion(id: string): boolean {\n const suggestion = this.getSuggestion(id);\n if (!suggestion) return false;\n\n // Update the suggestion\n const updateStmt = this.db.prepare(`\n UPDATE suggestions\n SET accepted = 1, accepted_at = datetime('now')\n WHERE id = ?\n `);\n updateStmt.run(id);\n\n // Update the routing rule\n this.setRule(\n suggestion.taskType,\n suggestion.suggestedModel,\n 'learned',\n suggestion.confidence,\n suggestion.sampleCount\n );\n\n return true;\n }\n\n /**\n * Rejects a suggestion.\n */\n rejectSuggestion(id: string): boolean {\n const stmt = this.db.prepare(`\n UPDATE suggestions\n SET accepted = 0, accepted_at = datetime('now')\n WHERE id = ?\n `);\n\n const result = stmt.run(id);\n return result.changes > 0;\n }\n\n // ============================================================================\n // Statistics\n // ============================================================================\n\n /**\n * Gets aggregated statistics.\n */\n getStats(options?: { from?: string; to?: string }): {\n totalRuns: number;\n successfulRuns: number;\n avgDurationMs: number;\n byTaskType: Record<string, { runs: number; successRate: number; avgDurationMs: number }>;\n byModel: Record<string, { runs: number; successRate: number; avgDurationMs: number }>;\n } {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options?.from) {\n conditions.push('created_at >= ?');\n params.push(options.from);\n }\n\n if (options?.to) {\n conditions.push('created_at <= ?');\n params.push(options.to);\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n\n // Overall stats\n const overallStmt = this.db.prepare(`\n SELECT \n COUNT(*) as totalRuns,\n SUM(success) as successfulRuns,\n AVG(duration_ms) as avgDurationMs\n FROM runs\n ${whereClause}\n `);\n\n const overall = overallStmt.get(...params) as {\n totalRuns: number;\n successfulRuns: number;\n avgDurationMs: number;\n };\n\n // Stats by task type\n const byTaskTypeStmt = this.db.prepare(`\n SELECT \n task_type as taskType,\n COUNT(*) as runs,\n AVG(success) as successRate,\n AVG(duration_ms) as avgDurationMs\n FROM runs\n ${whereClause}\n GROUP BY task_type\n `);\n\n const byTaskTypeRows = byTaskTypeStmt.all(...params) as Array<{\n taskType: string;\n runs: number;\n successRate: number;\n avgDurationMs: number;\n }>;\n\n const byTaskType: Record<string, { runs: number; successRate: number; avgDurationMs: number }> = {};\n for (const row of byTaskTypeRows) {\n byTaskType[row.taskType] = {\n runs: row.runs,\n successRate: row.successRate,\n avgDurationMs: row.avgDurationMs,\n };\n }\n\n // Stats by model\n const byModelStmt = this.db.prepare(`\n SELECT \n model,\n COUNT(*) as runs,\n AVG(success) as successRate,\n AVG(duration_ms) as avgDurationMs\n FROM runs\n ${whereClause}\n GROUP BY model\n `);\n\n const byModelRows = byModelStmt.all(...params) as Array<{\n model: string;\n runs: number;\n successRate: number;\n avgDurationMs: number;\n }>;\n\n const byModel: Record<string, { runs: number; successRate: number; avgDurationMs: number }> = {};\n for (const row of byModelRows) {\n byModel[row.model] = {\n runs: row.runs,\n successRate: row.successRate,\n avgDurationMs: row.avgDurationMs,\n };\n }\n\n return {\n totalRuns: overall.totalRuns,\n successfulRuns: overall.successfulRuns ?? 0,\n avgDurationMs: overall.avgDurationMs ?? 0,\n byTaskType,\n byModel,\n };\n }\n\n /**\n * Gets statistics for learning (outcomes joined with runs).\n */\n getLearningStats(taskType: TaskType): Array<{\n model: string;\n runs: number;\n successRate: number;\n avgDurationMs: number;\n outcomeSuccessRate: number;\n }> {\n const stmt = this.db.prepare(`\n SELECT \n r.model,\n COUNT(*) as runs,\n AVG(r.success) as successRate,\n AVG(r.duration_ms) as avgDurationMs,\n AVG(CASE WHEN o.success IS NOT NULL THEN o.success ELSE r.success END) as outcomeSuccessRate\n FROM runs r\n LEFT JOIN outcomes o ON r.id = o.run_id\n WHERE r.task_type = ?\n GROUP BY r.model\n HAVING runs >= 5\n `);\n\n return stmt.all(taskType) as Array<{\n model: string;\n runs: number;\n successRate: number;\n avgDurationMs: number;\n outcomeSuccessRate: number;\n }>;\n }\n}\n\n// Import for seed data\nimport { DEFAULT_ROUTING_RULES } from './schema.js';\n","import crypto from 'crypto'\nimport { urlAlphabet } from './url-alphabet/index.js'\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool, poolOffset\nlet fillPool = bytes => {\n if (!pool || pool.length < bytes) {\n pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n crypto.randomFillSync(pool)\n poolOffset = 0\n } else if (poolOffset + bytes > pool.length) {\n crypto.randomFillSync(pool)\n poolOffset = 0\n }\n poolOffset += bytes\n}\nlet random = bytes => {\n fillPool((bytes |= 0))\n return pool.subarray(poolOffset - bytes, poolOffset)\n}\nlet customRandom = (alphabet, defaultSize, getRandom) => {\n let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1\n let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)\n return (size = defaultSize) => {\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let i = step\n while (i--) {\n id += alphabet[bytes[i] & mask] || ''\n if (id.length === size) return id\n }\n }\n }\n}\nlet customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size, random)\nlet nanoid = (size = 21) => {\n fillPool((size |= 0))\n let id = ''\n for (let i = poolOffset - size; i < poolOffset; i++) {\n id += urlAlphabet[pool[i] & 63]\n }\n return id\n}\nexport { nanoid, customAlphabet, customRandom, urlAlphabet, random }\n","let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\nexport { urlAlphabet }\n","/**\n * SQLite Schema Definition\n *\n * Defines the database schema for RelayPlane storage.\n *\n * @packageDocumentation\n */\n\n/**\n * SQL statements for creating the database schema.\n */\nexport const SCHEMA_SQL = `\n-- Runs table: stores all LLM invocations\nCREATE TABLE IF NOT EXISTS runs (\n id TEXT PRIMARY KEY,\n prompt TEXT NOT NULL,\n system_prompt TEXT,\n task_type TEXT NOT NULL,\n model TEXT NOT NULL,\n success INTEGER NOT NULL,\n output TEXT,\n error TEXT,\n duration_ms INTEGER NOT NULL,\n tokens_in INTEGER,\n tokens_out INTEGER,\n cost_usd REAL,\n metadata TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Index for task type queries\nCREATE INDEX IF NOT EXISTS idx_runs_task_type ON runs(task_type);\n\n-- Index for model queries\nCREATE INDEX IF NOT EXISTS idx_runs_model ON runs(model);\n\n-- Index for time-based queries\nCREATE INDEX IF NOT EXISTS idx_runs_created_at ON runs(created_at);\n\n-- Outcomes table: stores user feedback on runs\nCREATE TABLE IF NOT EXISTS outcomes (\n id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,\n success INTEGER NOT NULL,\n quality TEXT,\n latency_satisfactory INTEGER,\n cost_satisfactory INTEGER,\n feedback TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n UNIQUE(run_id)\n);\n\n-- Index for run lookups\nCREATE INDEX IF NOT EXISTS idx_outcomes_run_id ON outcomes(run_id);\n\n-- Routing rules table: stores routing preferences\nCREATE TABLE IF NOT EXISTS routing_rules (\n id TEXT PRIMARY KEY,\n task_type TEXT NOT NULL UNIQUE,\n preferred_model TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'default',\n confidence REAL,\n sample_count INTEGER,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Index for task type lookups\nCREATE INDEX IF NOT EXISTS idx_routing_rules_task_type ON routing_rules(task_type);\n\n-- Suggestions table: stores routing improvement suggestions\nCREATE TABLE IF NOT EXISTS suggestions (\n id TEXT PRIMARY KEY,\n task_type TEXT NOT NULL,\n current_model TEXT NOT NULL,\n suggested_model TEXT NOT NULL,\n reason TEXT NOT NULL,\n confidence REAL NOT NULL,\n expected_improvement TEXT NOT NULL,\n sample_count INTEGER NOT NULL,\n accepted INTEGER,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n accepted_at TEXT\n);\n\n-- Index for task type lookups\nCREATE INDEX IF NOT EXISTS idx_suggestions_task_type ON suggestions(task_type);\n\n-- Index for pending suggestions\nCREATE INDEX IF NOT EXISTS idx_suggestions_accepted ON suggestions(accepted);\n\n-- Schema version table for migrations\nCREATE TABLE IF NOT EXISTS schema_version (\n version INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Insert initial schema version\nINSERT OR IGNORE INTO schema_version (version) VALUES (1);\n`;\n\n/**\n * Default routing rules to seed the database.\n * Using -latest suffix for automatic model updates.\n */\nexport const DEFAULT_ROUTING_RULES = [\n { taskType: 'code_generation', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'code_review', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'summarization', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'analysis', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'creative_writing', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'data_extraction', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'translation', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'question_answering', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'general', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n] as const;\n\n/**\n * SQL for seeding default routing rules.\n */\nexport function generateSeedSQL(): string {\n const values = DEFAULT_ROUTING_RULES.map((rule, index) => {\n const id = `default-${rule.taskType}`;\n return `('${id}', '${rule.taskType}', '${rule.preferredModel}', 'default', NULL, NULL, datetime('now'), datetime('now'))`;\n }).join(',\\n ');\n\n return `\nINSERT OR IGNORE INTO routing_rules (id, task_type, preferred_model, source, confidence, sample_count, created_at, updated_at)\nVALUES\n ${values};\n`;\n}\n","/**\n * Task Type Inference\n *\n * Infers the task type from a prompt using pattern matching.\n * Designed for <5ms execution with no network calls.\n *\n * @packageDocumentation\n */\n\nimport type { TaskType } from '../types.js';\n\n/**\n * Pattern definition for task inference.\n */\ninterface InferencePattern {\n /**\n * Regular expression to match against the prompt.\n */\n pattern: RegExp;\n\n /**\n * Weight for this pattern (higher = more confident).\n */\n weight: number;\n}\n\n/**\n * Patterns for each task type.\n * Order matters - earlier patterns in the array have higher priority when weights are equal.\n */\nconst TASK_PATTERNS: Record<TaskType, InferencePattern[]> = {\n code_generation: [\n { pattern: /\\b(write|create|generate|implement|build|code|develop|make)\\b.{0,50}\\b(function|class|code|script|program|method|module|api|endpoint|component)\\b/i, weight: 10 },\n { pattern: /\\b(write|create|generate)\\b.{0,30}\\b(python|javascript|typescript|java|go|rust|c\\+\\+|ruby|php|swift)\\b/i, weight: 10 },\n { pattern: /\\bcreate a.{0,30}(that|which|to)\\b/i, weight: 5 },\n { pattern: /\\bimplement\\b.{0,50}\\b(algorithm|logic|feature)\\b/i, weight: 8 },\n { pattern: /\\bcode\\s+for\\b/i, weight: 7 },\n { pattern: /\\bwrite me\\b.{0,30}\\b(code|script|function)\\b/i, weight: 9 },\n { pattern: /```[\\w]*\\n/i, weight: 3 }, // Code blocks suggest code context\n ],\n\n code_review: [\n { pattern: /\\b(review|analyze|check|audit|inspect|evaluate|assess|critique)\\b.{0,30}\\b(code|function|class|script|implementation|pull request|pr|diff)\\b/i, weight: 10 },\n { pattern: /\\b(what'?s? wrong|find\\s+(bugs?|issues?|problems?|errors?))\\b.{0,30}\\b(code|function|this)\\b/i, weight: 9 },\n { pattern: /\\b(improve|optimize|refactor)\\b.{0,30}\\b(code|function|this)\\b/i, weight: 7 },\n { pattern: /\\blook\\s+(at|over)\\s+(this|my)\\s+code\\b/i, weight: 8 },\n { pattern: /\\bcode\\s+review\\b/i, weight: 10 },\n { pattern: /\\bcan you (check|review)\\b/i, weight: 5 },\n ],\n\n summarization: [\n { pattern: /\\b(summarize|summarise|summary|tldr|tl;dr|recap|condense|brief|overview)\\b/i, weight: 10 },\n { pattern: /\\b(give|provide|write)\\s+(me\\s+)?(a\\s+)?(brief|short|quick|concise)\\s+(summary|overview)\\b/i, weight: 9 },\n { pattern: /\\bshorten\\s+(this|the)\\b/i, weight: 6 },\n { pattern: /\\bin\\s+(brief|short|a nutshell)\\b/i, weight: 7 },\n { pattern: /\\bkey\\s+(points?|takeaways?)\\b/i, weight: 8 },\n { pattern: /\\bmain\\s+(ideas?|points?)\\b/i, weight: 7 },\n ],\n\n analysis: [\n { pattern: /\\b(analyze|analyse|analysis|examine|investigate|assess|evaluate|study)\\b/i, weight: 8 },\n { pattern: /\\b(compare|contrast|differentiate|distinguish)\\b.{0,30}\\b(between|and)\\b/i, weight: 9 },\n { pattern: /\\b(pros?\\s+and\\s+cons?|advantages?\\s+and\\s+disadvantages?|strengths?\\s+and\\s+weaknesses?)\\b/i, weight: 9 },\n { pattern: /\\b(what\\s+are|explain)\\s+(the\\s+)?(implications?|consequences?|effects?|impacts?)\\b/i, weight: 8 },\n { pattern: /\\bbreak\\s*down\\b/i, weight: 6 },\n { pattern: /\\bdeep\\s*dive\\b/i, weight: 7 },\n { pattern: /\\bcritical(ly)?\\s+(analysis|evaluation|assessment)\\b/i, weight: 9 },\n ],\n\n creative_writing: [\n { pattern: /\\b(write|create|compose|craft|author)\\b.{0,30}\\b(story|poem|essay|article|blog|post|narrative|fiction|novel|song|lyrics)\\b/i, weight: 10 },\n { pattern: /\\b(creative|imaginative|fictional)\\s+(writing|story|piece)\\b/i, weight: 10 },\n { pattern: /\\bonce upon a time\\b/i, weight: 8 },\n { pattern: /\\b(write|tell)\\s+(me\\s+)?(a\\s+)?(short\\s+)?story\\b/i, weight: 9 },\n { pattern: /\\b(brainstorm|ideate)\\b.{0,30}\\b(ideas?|concepts?|themes?)\\b/i, weight: 7 },\n { pattern: /\\bwrite\\s+(in|like)\\s+(the\\s+)?style\\s+of\\b/i, weight: 8 },\n { pattern: /\\b(catchy|creative|engaging)\\s+(title|headline|tagline|slogan)\\b/i, weight: 7 },\n ],\n\n data_extraction: [\n { pattern: /\\b(extract|parse|pull|get|retrieve|find|identify)\\b.{0,30}\\b(data|information|details?|values?|fields?|entities?|names?|numbers?|dates?|emails?|phones?|addresses?)\\b/i, weight: 10 },\n { pattern: /\\b(convert|transform)\\b.{0,30}\\b(to|into)\\s+(json|csv|xml|yaml|table|structured)\\b/i, weight: 9 },\n { pattern: /\\bstructured\\s+(data|output|format)\\b/i, weight: 8 },\n { pattern: /\\bnamed\\s+entity\\s+(recognition|extraction)\\b/i, weight: 10 },\n { pattern: /\\b(scrape|crawl)\\b/i, weight: 6 },\n { pattern: /\\bjson\\s+(output|format|schema)\\b/i, weight: 7 },\n ],\n\n translation: [\n { pattern: /\\b(translate|translation|translator)\\b/i, weight: 10 },\n { pattern: /\\b(convert|change)\\b.{0,20}\\b(to|into)\\s+(english|spanish|french|german|chinese|japanese|korean|portuguese|italian|russian|arabic|hindi|dutch)\\b/i, weight: 9 },\n { pattern: /\\b(in|to)\\s+(english|spanish|french|german|chinese|japanese|korean|portuguese|italian|russian|arabic|hindi|dutch)\\b/i, weight: 6 },\n { pattern: /\\bfrom\\s+(english|spanish|french|german|chinese|japanese|korean|portuguese|italian|russian|arabic|hindi|dutch)\\s+to\\b/i, weight: 10 },\n { pattern: /\\blocalize|localization\\b/i, weight: 7 },\n ],\n\n question_answering: [\n { pattern: /^(what|who|where|when|why|how|which|is|are|does|do|can|could|would|should|will|did)\\s/i, weight: 7 },\n { pattern: /\\?$/i, weight: 5 },\n { pattern: /\\b(explain|describe|define|what\\s+is|what\\s+are|tell\\s+me\\s+about)\\b/i, weight: 8 },\n { pattern: /\\b(answer|respond|reply)\\b.{0,20}\\b(question|query)\\b/i, weight: 9 },\n { pattern: /\\bfaq\\b/i, weight: 8 },\n { pattern: /\\bi\\s+(want|need)\\s+to\\s+know\\b/i, weight: 6 },\n { pattern: /\\bcan\\s+you\\s+(tell|explain|help)\\b/i, weight: 5 },\n ],\n\n general: [\n // Catch-all patterns with low weights\n { pattern: /./i, weight: 1 },\n ],\n};\n\n/**\n * Infers the task type from a prompt.\n *\n * @param prompt - The user's prompt\n * @returns The inferred task type\n */\nexport function inferTaskType(prompt: string): TaskType {\n // Normalize the prompt\n const normalizedPrompt = prompt.trim().toLowerCase();\n\n // Score each task type\n const scores: Record<TaskType, number> = {\n code_generation: 0,\n code_review: 0,\n summarization: 0,\n analysis: 0,\n creative_writing: 0,\n data_extraction: 0,\n translation: 0,\n question_answering: 0,\n general: 0,\n };\n\n // Calculate scores\n for (const [taskType, patterns] of Object.entries(TASK_PATTERNS)) {\n for (const { pattern, weight } of patterns) {\n if (pattern.test(prompt)) {\n scores[taskType as TaskType] += weight;\n }\n }\n }\n\n // Find the highest scoring task type\n let maxScore = 0;\n let inferredType: TaskType = 'general';\n\n for (const [taskType, score] of Object.entries(scores)) {\n if (score > maxScore) {\n maxScore = score;\n inferredType = taskType as TaskType;\n }\n }\n\n // If the max score is very low, default to general\n if (maxScore <= 1) {\n return 'general';\n }\n\n return inferredType;\n}\n\n/**\n * Gets the confidence score for an inferred task type.\n *\n * @param prompt - The user's prompt\n * @param taskType - The task type to check confidence for\n * @returns Confidence score between 0 and 1\n */\nexport function getInferenceConfidence(prompt: string, taskType: TaskType): number {\n const patterns = TASK_PATTERNS[taskType];\n if (!patterns) return 0;\n\n let totalWeight = 0;\n let maxPossibleWeight = 0;\n\n for (const { pattern, weight } of patterns) {\n maxPossibleWeight += weight;\n if (pattern.test(prompt)) {\n totalWeight += weight;\n }\n }\n\n if (maxPossibleWeight === 0) return 0;\n\n // Normalize to 0-1 range, cap at 0.95 to show uncertainty\n return Math.min(totalWeight / maxPossibleWeight, 0.95);\n}\n\n/**\n * Gets all matching task types with their scores.\n *\n * @param prompt - The user's prompt\n * @returns Array of task types with scores, sorted by score descending\n */\nexport function getAllMatches(prompt: string): Array<{ taskType: TaskType; score: number; confidence: number }> {\n const scores: Record<TaskType, number> = {\n code_generation: 0,\n code_review: 0,\n summarization: 0,\n analysis: 0,\n creative_writing: 0,\n data_extraction: 0,\n translation: 0,\n question_answering: 0,\n general: 0,\n };\n\n // Calculate scores\n for (const [taskType, patterns] of Object.entries(TASK_PATTERNS)) {\n for (const { pattern, weight } of patterns) {\n if (pattern.test(prompt)) {\n scores[taskType as TaskType] += weight;\n }\n }\n }\n\n // Convert to array and sort\n const results = Object.entries(scores)\n .map(([taskType, score]) => ({\n taskType: taskType as TaskType,\n score,\n confidence: getInferenceConfidence(prompt, taskType as TaskType),\n }))\n .filter((r) => r.score > 0)\n .sort((a, b) => b.score - a.score);\n\n return results;\n}\n","/**\n * Routing Engine\n *\n * Manages routing rules and model selection for tasks.\n *\n * @packageDocumentation\n */\n\nimport type { Store } from '../storage/store.js';\nimport type { TaskType, RoutingRule, RuleSource } from '../types.js';\nimport { inferTaskType, getInferenceConfidence } from './inference.js';\n\n/**\n * Routing engine for managing model selection.\n */\nexport class RoutingEngine {\n private store: Store;\n\n /**\n * Creates a new RoutingEngine.\n *\n * @param store - The storage instance to use\n */\n constructor(store: Store) {\n this.store = store;\n }\n\n /**\n * Infers the task type from a prompt.\n *\n * @param prompt - The prompt to analyze\n * @returns The inferred task type\n */\n inferTaskType(prompt: string): TaskType {\n return inferTaskType(prompt);\n }\n\n /**\n * Gets the inference confidence for a task type.\n *\n * @param prompt - The prompt to analyze\n * @param taskType - The task type to check\n * @returns Confidence score (0-1)\n */\n getInferenceConfidence(prompt: string, taskType: TaskType): number {\n return getInferenceConfidence(prompt, taskType);\n }\n\n /**\n * Gets the routing rule for a task type.\n *\n * @param taskType - The task type to get the rule for\n * @returns The routing rule, or null if not found\n */\n get(taskType: TaskType): RoutingRule | null {\n const record = this.store.getRule(taskType);\n if (!record) return null;\n\n return {\n id: record.id,\n taskType: record.taskType,\n preferredModel: record.preferredModel,\n source: record.source,\n confidence: record.confidence ?? undefined,\n sampleCount: record.sampleCount ?? undefined,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n };\n }\n\n /**\n * Sets a routing rule for a task type.\n *\n * @param taskType - The task type to set the rule for\n * @param preferredModel - The preferred model (format: \"provider:model\")\n * @param source - How the rule was created\n * @param options - Optional confidence and sample count\n * @returns The rule ID\n */\n set(\n taskType: TaskType,\n preferredModel: string,\n source: RuleSource = 'user',\n options?: { confidence?: number; sampleCount?: number }\n ): string {\n return this.store.setRule(\n taskType,\n preferredModel,\n source,\n options?.confidence,\n options?.sampleCount\n );\n }\n\n /**\n * Lists all routing rules.\n *\n * @returns Array of all routing rules\n */\n list(): RoutingRule[] {\n const records = this.store.listRules();\n return records.map((record) => ({\n id: record.id,\n taskType: record.taskType,\n preferredModel: record.preferredModel,\n source: record.source,\n confidence: record.confidence ?? undefined,\n sampleCount: record.sampleCount ?? undefined,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n }));\n }\n\n /**\n * Deletes a routing rule and resets to default.\n *\n * @param taskType - The task type to reset\n * @returns True if the rule was reset\n */\n delete(taskType: TaskType): boolean {\n return this.store.deleteRule(taskType);\n }\n\n /**\n * Gets the preferred model for a task type.\n *\n * @param taskType - The task type\n * @returns The preferred model string, or a default\n */\n getPreferredModel(taskType: TaskType): string {\n const rule = this.get(taskType);\n return rule?.preferredModel ?? 'local:llama3.2';\n }\n\n /**\n * Parses a model string into provider and model name.\n *\n * @param modelString - The model string (format: \"provider:model\")\n * @returns Object with provider and model\n */\n parseModel(modelString: string): { provider: string; model: string } {\n const parts = modelString.split(':');\n if (parts.length < 2) {\n return { provider: 'local', model: modelString };\n }\n return { provider: parts[0]!, model: parts.slice(1).join(':') };\n }\n\n /**\n * Resolves the model to use for a prompt.\n *\n * @param prompt - The prompt to analyze\n * @param overrideTaskType - Optional task type override\n * @param overrideModel - Optional model override\n * @returns Object with resolved taskType, model, provider, and confidence\n */\n resolve(\n prompt: string,\n overrideTaskType?: TaskType,\n overrideModel?: string\n ): {\n taskType: TaskType;\n model: string;\n provider: string;\n modelName: string;\n confidence: number;\n } {\n // Determine task type\n const taskType = overrideTaskType ?? this.inferTaskType(prompt);\n const confidence = this.getInferenceConfidence(prompt, taskType);\n\n // Determine model\n let model: string;\n if (overrideModel) {\n model = overrideModel;\n } else {\n model = this.getPreferredModel(taskType);\n }\n\n const { provider, model: modelName } = this.parseModel(model);\n\n return {\n taskType,\n model,\n provider,\n modelName,\n confidence,\n };\n }\n}\n","/**\n * Outcome Recording\n *\n * Handles recording and processing of run outcomes.\n *\n * @packageDocumentation\n */\n\nimport type { Store } from '../storage/store.js';\nimport type { OutcomeInput, Outcome, OutcomeRecord } from '../types.js';\n\n/**\n * Outcome recorder for processing user feedback.\n */\nexport class OutcomeRecorder {\n private store: Store;\n\n /**\n * Creates a new OutcomeRecorder.\n *\n * @param store - The storage instance to use\n */\n constructor(store: Store) {\n this.store = store;\n }\n\n /**\n * Records an outcome for a run.\n *\n * @param input - The outcome input\n * @returns The recorded outcome\n * @throws If the run ID is not found\n */\n record(input: OutcomeInput): Outcome {\n // Verify the run exists\n const run = this.store.getRun(input.runId);\n if (!run) {\n throw new Error(`Run not found: ${input.runId}`);\n }\n\n // Record the outcome\n const id = this.store.recordOutcome({\n runId: input.runId,\n success: input.success,\n quality: input.quality ?? null,\n latencySatisfactory: input.latencySatisfactory ?? null,\n costSatisfactory: input.costSatisfactory ?? null,\n feedback: input.feedback ?? null,\n });\n\n // Get the recorded outcome\n const outcome = this.store.getOutcome(input.runId);\n if (!outcome) {\n throw new Error('Failed to record outcome');\n }\n\n return {\n id: outcome.id,\n runId: outcome.runId,\n success: outcome.success,\n quality: outcome.quality ?? undefined,\n latencySatisfactory: outcome.latencySatisfactory ?? undefined,\n costSatisfactory: outcome.costSatisfactory ?? undefined,\n feedback: outcome.feedback ?? undefined,\n recordedAt: outcome.createdAt,\n };\n }\n\n /**\n * Gets an outcome for a run.\n *\n * @param runId - The run ID\n * @returns The outcome, or null if not found\n */\n get(runId: string): Outcome | null {\n const outcome = this.store.getOutcome(runId);\n if (!outcome) return null;\n\n return {\n id: outcome.id,\n runId: outcome.runId,\n success: outcome.success,\n quality: outcome.quality ?? undefined,\n latencySatisfactory: outcome.latencySatisfactory ?? undefined,\n costSatisfactory: outcome.costSatisfactory ?? undefined,\n feedback: outcome.feedback ?? undefined,\n recordedAt: outcome.createdAt,\n };\n }\n\n /**\n * Gets outcome statistics for a task type.\n *\n * @param taskType - The task type to get stats for\n * @returns Outcome statistics\n */\n getTaskStats(taskType: string): {\n totalOutcomes: number;\n successRate: number;\n qualityDistribution: Record<string, number>;\n latencySatisfactionRate: number;\n costSatisfactionRate: number;\n } {\n const outcomes = this.store.getOutcomes({ taskType: taskType as any, limit: 1000 });\n\n if (outcomes.length === 0) {\n return {\n totalOutcomes: 0,\n successRate: 0,\n qualityDistribution: {},\n latencySatisfactionRate: 0,\n costSatisfactionRate: 0,\n };\n }\n\n // Calculate statistics\n let successCount = 0;\n let latencySatisfiedCount = 0;\n let latencyRatedCount = 0;\n let costSatisfiedCount = 0;\n let costRatedCount = 0;\n const qualityDistribution: Record<string, number> = {};\n\n for (const outcome of outcomes) {\n if (outcome.success) successCount++;\n\n if (outcome.quality) {\n qualityDistribution[outcome.quality] = (qualityDistribution[outcome.quality] ?? 0) + 1;\n }\n\n if (outcome.latencySatisfactory != null) {\n latencyRatedCount++;\n if (outcome.latencySatisfactory) latencySatisfiedCount++;\n }\n\n if (outcome.costSatisfactory != null) {\n costRatedCount++;\n if (outcome.costSatisfactory) costSatisfiedCount++;\n }\n }\n\n return {\n totalOutcomes: outcomes.length,\n successRate: successCount / outcomes.length,\n qualityDistribution,\n latencySatisfactionRate: latencyRatedCount > 0 ? latencySatisfiedCount / latencyRatedCount : 0,\n costSatisfactionRate: costRatedCount > 0 ? costSatisfiedCount / costRatedCount : 0,\n };\n }\n}\n","/**\n * Savings Calculator\n *\n * Calculates cost savings from intelligent model routing vs a baseline (all-Opus).\n *\n * @packageDocumentation\n */\n\nimport type { Store } from '../storage/store.js';\n\n/**\n * Model pricing in USD per 1M tokens.\n */\nexport const MODEL_PRICING: Record<string, { input: number; output: number }> = {\n // Anthropic models\n 'claude-3-5-haiku-latest': { input: 0.25, output: 1.25 },\n 'claude-3-5-haiku-20241022': { input: 0.25, output: 1.25 },\n 'claude-3-5-sonnet-latest': { input: 3, output: 15 },\n 'claude-3-5-sonnet-20241022': { input: 3, output: 15 },\n 'claude-sonnet-4-20250514': { input: 3, output: 15 },\n 'claude-3-opus-latest': { input: 15, output: 75 },\n 'claude-3-opus-20240229': { input: 15, output: 75 },\n 'claude-opus-4-5-20250514': { input: 15, output: 75 },\n // OpenAI models\n 'gpt-4o': { input: 2.5, output: 10 },\n 'gpt-4o-mini': { input: 0.15, output: 0.6 },\n 'gpt-4.1': { input: 2, output: 8 },\n 'gpt-4-turbo': { input: 10, output: 30 },\n // Google models\n 'gemini-1.5-flash': { input: 0.075, output: 0.3 },\n 'gemini-1.5-pro': { input: 1.25, output: 5 },\n 'gemini-2.0-flash': { input: 0.1, output: 0.4 },\n // xAI models\n 'grok-2': { input: 2, output: 10 },\n 'grok-2-latest': { input: 2, output: 10 },\n // Moonshot models\n 'moonshot-v1-8k': { input: 0.1, output: 0.1 },\n 'moonshot-v1-32k': { input: 0.2, output: 0.2 },\n};\n\n/**\n * Baseline model for savings comparison (most expensive).\n */\nexport const BASELINE_MODEL = 'claude-3-opus-latest';\n\n/**\n * Model cost breakdown.\n */\nexport interface ModelCostBreakdown {\n runs: number;\n tokensIn: number;\n tokensOut: number;\n cost: number;\n successRate: number;\n avgLatencyMs: number;\n}\n\n/**\n * Savings report structure.\n */\nexport interface SavingsReport {\n /** Number of days included in the report */\n periodDays: number;\n /** Date range */\n period: {\n from: string;\n to: string;\n };\n /** Total number of runs */\n totalRuns: number;\n /** Total tokens used */\n totalTokensIn: number;\n totalTokensOut: number;\n /** Actual cost incurred */\n actualCost: number;\n /** Cost if all calls went to baseline model (Opus) */\n baselineCost: number;\n /** Total savings */\n savings: number;\n /** Savings as percentage */\n savingsPercent: number;\n /** Cost breakdown by model */\n byModel: Record<string, ModelCostBreakdown>;\n /** Cost breakdown by task type */\n byTaskType: Record<string, { runs: number; cost: number; avgCostPerRun: number }>;\n}\n\n/**\n * Calculate cost for a specific model and token counts.\n */\nexport function calculateCost(\n model: string,\n tokensIn: number,\n tokensOut: number\n): number {\n // Extract model name from provider:model format\n const modelName = model.includes(':') ? model.split(':')[1] : model;\n \n // Find pricing, with fallback to default\n const pricing = MODEL_PRICING[modelName as keyof typeof MODEL_PRICING] ??\n MODEL_PRICING[model as keyof typeof MODEL_PRICING] ??\n { input: 1, output: 3 }; // Default fallback pricing\n\n const inputCost = (tokensIn / 1_000_000) * pricing.input;\n const outputCost = (tokensOut / 1_000_000) * pricing.output;\n\n return inputCost + outputCost;\n}\n\n/**\n * Get pricing for a model.\n */\nexport function getModelPricing(model: string): { input: number; output: number } | null {\n const modelName = model.includes(':') ? model.split(':')[1] : model;\n return MODEL_PRICING[modelName as keyof typeof MODEL_PRICING] ??\n MODEL_PRICING[model as keyof typeof MODEL_PRICING] ??\n null;\n}\n\n/**\n * Calculate savings report from stored runs.\n */\nexport function calculateSavings(store: Store, days: number = 30): SavingsReport {\n // Calculate date range\n const to = new Date();\n const from = new Date();\n from.setDate(from.getDate() - days);\n\n const fromStr = from.toISOString();\n const toStr = to.toISOString();\n\n // Get all runs in the period\n const runs = store.getRuns({\n from: fromStr,\n to: toStr,\n limit: 100000, // Get all runs\n });\n\n // Initialize aggregation\n const byModel: Record<string, ModelCostBreakdown> = {};\n const byTaskType: Record<string, { runs: number; cost: number; totalCost: number }> = {};\n \n let totalTokensIn = 0;\n let totalTokensOut = 0;\n let actualCost = 0;\n let baselineCost = 0;\n\n const baselinePricing = MODEL_PRICING[BASELINE_MODEL] ?? { input: 15, output: 75 };\n\n for (const run of runs) {\n const tokensIn = run.tokensIn ?? 0;\n const tokensOut = run.tokensOut ?? 0;\n const modelName = run.model.includes(':') ? run.model.split(':')[1] ?? run.model : run.model;\n\n // Calculate actual cost for this run\n const runCost = calculateCost(run.model, tokensIn, tokensOut);\n actualCost += runCost;\n\n // Calculate baseline cost (if this run used Opus)\n const baselineRunCost = (tokensIn / 1_000_000) * (baselinePricing?.input ?? 15) +\n (tokensOut / 1_000_000) * (baselinePricing?.output ?? 75);\n baselineCost += baselineRunCost;\n\n // Aggregate totals\n totalTokensIn += tokensIn;\n totalTokensOut += tokensOut;\n\n // Aggregate by model\n if (!byModel[modelName]) {\n byModel[modelName] = {\n runs: 0,\n tokensIn: 0,\n tokensOut: 0,\n cost: 0,\n successRate: 0,\n avgLatencyMs: 0,\n };\n }\n const modelStats = byModel[modelName]!;\n modelStats.runs++;\n modelStats.tokensIn += tokensIn;\n modelStats.tokensOut += tokensOut;\n modelStats.cost += runCost;\n modelStats.avgLatencyMs += run.durationMs;\n if (run.success) {\n modelStats.successRate++;\n }\n\n // Aggregate by task type\n if (!byTaskType[run.taskType]) {\n byTaskType[run.taskType] = { runs: 0, cost: 0, totalCost: 0 };\n }\n const taskStats = byTaskType[run.taskType]!;\n taskStats.runs++;\n taskStats.totalCost += runCost;\n }\n\n // Finalize model stats (calculate averages)\n for (const model of Object.keys(byModel)) {\n const stats = byModel[model]!;\n stats.successRate = stats.runs > 0 ? stats.successRate / stats.runs : 0;\n stats.avgLatencyMs = stats.runs > 0 ? stats.avgLatencyMs / stats.runs : 0;\n }\n\n // Finalize task type stats\n const byTaskTypeFinal: Record<string, { runs: number; cost: number; avgCostPerRun: number }> = {};\n for (const [taskType, stats] of Object.entries(byTaskType)) {\n byTaskTypeFinal[taskType] = {\n runs: stats.runs,\n cost: stats.totalCost,\n avgCostPerRun: stats.runs > 0 ? stats.totalCost / stats.runs : 0,\n };\n }\n\n // Calculate savings\n const savings = baselineCost - actualCost;\n const savingsPercent = baselineCost > 0 ? (savings / baselineCost) * 100 : 0;\n\n return {\n periodDays: days,\n period: {\n from: fromStr,\n to: toStr,\n },\n totalRuns: runs.length,\n totalTokensIn,\n totalTokensOut,\n actualCost,\n baselineCost,\n savings: Math.max(0, savings), // Don't report negative savings\n savingsPercent: Math.max(0, savingsPercent),\n byModel,\n byTaskType: byTaskTypeFinal,\n };\n}\n\n/**\n * Format currency for display.\n */\nexport function formatCurrency(amount: number): string {\n if (amount < 0.01) {\n return `$${amount.toFixed(4)}`;\n }\n return `$${amount.toFixed(2)}`;\n}\n\n/**\n * Format token count for display.\n */\nexport function formatTokens(count: number): string {\n if (count >= 1_000_000) {\n return `${(count / 1_000_000).toFixed(1)}M`;\n }\n if (count >= 1_000) {\n return `${(count / 1_000).toFixed(1)}K`;\n }\n return String(count);\n}\n","/**\n * Pattern Detection\n *\n * Analyzes run history to detect patterns and generate suggestions.\n *\n * @packageDocumentation\n */\n\nimport type { Store } from '../storage/store.js';\nimport type { TaskType, Suggestion } from '../types.js';\nimport { nanoid } from 'nanoid';\nimport { calculateCost, MODEL_PRICING } from './savings.js';\n\n/**\n * Minimum number of runs required to generate a suggestion.\n */\nconst MIN_RUNS_FOR_SUGGESTION = 10;\n\n/**\n * Minimum confidence threshold for suggestions.\n */\nconst MIN_CONFIDENCE_THRESHOLD = 0.6;\n\n/**\n * Minimum improvement threshold to suggest a change (e.g., 10% better).\n */\nconst MIN_IMPROVEMENT_THRESHOLD = 0.1;\n\n/**\n * Minimum cost savings threshold to suggest a cheaper model (20% cost reduction).\n */\nconst MIN_COST_IMPROVEMENT_THRESHOLD = 0.2;\n\n/**\n * Pattern detection engine for learning from outcomes.\n */\nexport class PatternDetector {\n private store: Store;\n\n /**\n * Creates a new PatternDetector.\n *\n * @param store - The storage instance to use\n */\n constructor(store: Store) {\n this.store = store;\n }\n\n /**\n * Analyzes a task type and generates suggestions if appropriate.\n *\n * @param taskType - The task type to analyze\n * @returns Array of suggestions\n */\n analyzeTaskType(taskType: TaskType): Suggestion[] {\n const stats = this.store.getLearningStats(taskType);\n\n if (stats.length < 2) {\n // Need at least 2 models to compare\n return [];\n }\n\n // Get the current routing rule\n const currentRule = this.store.getRule(taskType);\n if (!currentRule) return [];\n\n const currentModel = currentRule.preferredModel;\n\n // Find the current model's stats\n const currentStats = stats.find((s) => s.model === currentModel);\n if (!currentStats) return [];\n\n // Get pricing for current model\n const currentModelName = currentModel.includes(':') ? currentModel.split(':')[1] : currentModel;\n const currentPricing = MODEL_PRICING[currentModelName as keyof typeof MODEL_PRICING];\n\n // Find better performing models\n const suggestions: Suggestion[] = [];\n\n for (const modelStats of stats) {\n if (modelStats.model === currentModel) continue;\n if (modelStats.runs < MIN_RUNS_FOR_SUGGESTION) continue;\n\n // Calculate improvement potential\n const successImprovement = modelStats.outcomeSuccessRate - currentStats.outcomeSuccessRate;\n const latencyImprovement = (currentStats.avgDurationMs - modelStats.avgDurationMs) / currentStats.avgDurationMs;\n\n // Calculate cost improvement\n const suggestedModelName = modelStats.model.includes(':') \n ? modelStats.model.split(':')[1] \n : modelStats.model;\n const suggestedPricing = MODEL_PRICING[suggestedModelName as keyof typeof MODEL_PRICING];\n \n let costImprovement = 0;\n if (currentPricing && suggestedPricing) {\n // Use average of input/output pricing for comparison\n const currentAvgCost = (currentPricing.input + currentPricing.output) / 2;\n const suggestedAvgCost = (suggestedPricing.input + suggestedPricing.output) / 2;\n costImprovement = (currentAvgCost - suggestedAvgCost) / currentAvgCost;\n }\n\n // Check if this model is significantly better\n // Better = higher success OR faster OR cheaper (with acceptable success rate)\n const isSignificantlyBetter =\n successImprovement > MIN_IMPROVEMENT_THRESHOLD ||\n (successImprovement >= 0 && latencyImprovement > MIN_IMPROVEMENT_THRESHOLD) ||\n (successImprovement >= -0.05 && costImprovement > MIN_COST_IMPROVEMENT_THRESHOLD); // Allow 5% worse success for 20%+ cost savings\n\n if (!isSignificantlyBetter) continue;\n\n // Calculate confidence based on sample size and improvement magnitude\n const sampleConfidence = Math.min(modelStats.runs / 50, 1); // Max confidence at 50 runs\n const improvementConfidence = Math.min(\n Math.abs(successImprovement) / 0.3 + \n Math.abs(latencyImprovement) / 0.5 +\n Math.abs(costImprovement) / 0.5,\n 1\n );\n const confidence = (sampleConfidence + improvementConfidence) / 2;\n\n if (confidence < MIN_CONFIDENCE_THRESHOLD) continue;\n\n // Generate reason\n const reasons: string[] = [];\n if (successImprovement > 0) {\n reasons.push(`${(successImprovement * 100).toFixed(0)}% higher success rate`);\n }\n if (latencyImprovement > 0) {\n reasons.push(`${(latencyImprovement * 100).toFixed(0)}% faster`);\n }\n if (costImprovement > 0) {\n reasons.push(`${(costImprovement * 100).toFixed(0)}% cheaper`);\n }\n\n const suggestion: Suggestion = {\n id: nanoid(),\n taskType,\n currentModel,\n suggestedModel: modelStats.model,\n reason: reasons.join(', '),\n confidence,\n expectedImprovement: {\n successRate: successImprovement > 0 ? successImprovement : undefined,\n latency: latencyImprovement > 0 ? latencyImprovement : undefined,\n cost: costImprovement > 0 ? costImprovement : undefined,\n },\n sampleCount: modelStats.runs,\n createdAt: new Date().toISOString(),\n };\n\n suggestions.push(suggestion);\n }\n\n // Sort by confidence descending\n suggestions.sort((a, b) => b.confidence - a.confidence);\n\n return suggestions;\n }\n\n /**\n * Analyzes all task types and generates suggestions.\n *\n * @returns Array of all suggestions across task types\n */\n analyzeAll(): Suggestion[] {\n const taskTypes: TaskType[] = [\n 'code_generation',\n 'code_review',\n 'summarization',\n 'analysis',\n 'creative_writing',\n 'data_extraction',\n 'translation',\n 'question_answering',\n 'general',\n ];\n\n const allSuggestions: Suggestion[] = [];\n\n for (const taskType of taskTypes) {\n const suggestions = this.analyzeTaskType(taskType);\n allSuggestions.push(...suggestions);\n }\n\n // Sort by confidence descending\n allSuggestions.sort((a, b) => b.confidence - a.confidence);\n\n return allSuggestions;\n }\n\n /**\n * Stores suggestions in the database.\n *\n * @param suggestions - The suggestions to store\n * @returns Array of suggestion IDs\n */\n storeSuggestions(suggestions: Suggestion[]): string[] {\n const ids: string[] = [];\n\n for (const suggestion of suggestions) {\n const id = this.store.recordSuggestion({\n taskType: suggestion.taskType,\n currentModel: suggestion.currentModel,\n suggestedModel: suggestion.suggestedModel,\n reason: suggestion.reason,\n confidence: suggestion.confidence,\n expectedImprovement: JSON.stringify(suggestion.expectedImprovement),\n sampleCount: suggestion.sampleCount,\n accepted: null,\n });\n ids.push(id);\n }\n\n return ids;\n }\n\n /**\n * Generates and stores new suggestions, returning only new ones.\n *\n * @returns Array of new suggestions\n */\n generateSuggestions(): Suggestion[] {\n const suggestions = this.analyzeAll();\n\n // Filter out suggestions that already exist (same task type + suggested model)\n const pending = this.store.getPendingSuggestions();\n const existingKeys = new Set(\n pending.map((s) => `${s.taskType}:${s.suggestedModel}`)\n );\n\n const newSuggestions = suggestions.filter(\n (s) => !existingKeys.has(`${s.taskType}:${s.suggestedModel}`)\n );\n\n // Store new suggestions\n this.storeSuggestions(newSuggestions);\n\n return newSuggestions;\n }\n}\n","/**\n * RelayPlane Main Class\n *\n * The main entry point for the agent optimization layer.\n *\n * @packageDocumentation\n */\n\nimport { Store, getDefaultDbPath } from './storage/index.js';\nimport { RoutingEngine } from './routing/index.js';\nimport { OutcomeRecorder } from './learning/outcomes.js';\nimport { PatternDetector } from './learning/patterns.js';\nimport { calculateCost, calculateSavings, type SavingsReport } from './learning/savings.js';\nimport type {\n RelayPlaneConfig,\n RunInput,\n RunResult,\n OutcomeInput,\n Outcome,\n Stats,\n Suggestion,\n TaskType,\n Provider,\n ProviderConfig,\n} from './types.js';\n\n// Type-only import for adapters to avoid runtime dependency if not used\ntype ModelAdapter = {\n execute(args: {\n model: string;\n input: any;\n apiKey: string;\n baseUrl?: string;\n }): Promise<{\n success: boolean;\n output?: any;\n error?: { message: string };\n durationMs: number;\n tokensIn?: number;\n tokensOut?: number;\n }>;\n};\n\n/**\n * RelayPlane - Agent Optimization Layer\n *\n * Provides intelligent routing, outcome tracking, and learning for AI model selection.\n *\n * @example Basic usage\n * ```typescript\n * import { RelayPlane } from '@relayplane/core';\n *\n * const relay = new RelayPlane();\n *\n * // Run a task - automatically infers type and routes to best model\n * const result = await relay.run({\n * prompt: 'Review this code for bugs...',\n * });\n *\n * // Record the outcome for learning\n * await relay.recordOutcome(result.runId, { success: true, quality: 'good' });\n *\n * // Get suggestions for routing improvements\n * const suggestions = await relay.getSuggestions();\n * ```\n */\nexport class RelayPlane {\n private store: Store;\n private _routing: RoutingEngine;\n private outcomeRecorder: OutcomeRecorder;\n private patternDetector: PatternDetector;\n private config: RelayPlaneConfig;\n private adapterRegistry: any | null = null;\n\n /**\n * Creates a new RelayPlane instance.\n *\n * @param config - Configuration options\n */\n constructor(config: RelayPlaneConfig = {}) {\n this.config = {\n dbPath: config.dbPath ?? getDefaultDbPath(),\n defaultProvider: config.defaultProvider ?? 'local',\n defaultModel: config.defaultModel ?? 'llama3.2',\n providers: config.providers ?? {},\n };\n\n // Initialize storage\n this.store = new Store(this.config.dbPath);\n\n // Initialize components\n this._routing = new RoutingEngine(this.store);\n this.outcomeRecorder = new OutcomeRecorder(this.store);\n this.patternDetector = new PatternDetector(this.store);\n }\n\n /**\n * Gets the routing engine for direct access.\n */\n get routing(): RoutingEngine {\n return this._routing;\n }\n\n /**\n * Runs a prompt through the appropriate model.\n *\n * @param input - The run input\n * @returns The run result\n */\n async run(input: RunInput): Promise<RunResult> {\n const startTime = Date.now();\n\n // Resolve routing\n const resolved = this._routing.resolve(input.prompt, input.taskType, input.model);\n\n // Get the adapter\n const adapter = await this.getAdapter(resolved.provider as Provider);\n if (!adapter) {\n // No adapter available - record and return error\n const runId = this.store.recordRun({\n prompt: input.prompt,\n systemPrompt: input.systemPrompt ?? null,\n taskType: resolved.taskType,\n model: resolved.model,\n success: false,\n output: null,\n error: `No adapter configured for provider: ${resolved.provider}`,\n durationMs: Date.now() - startTime,\n tokensIn: null,\n tokensOut: null,\n costUsd: null,\n metadata: input.metadata ? JSON.stringify(input.metadata) : null,\n });\n\n return {\n runId,\n success: false,\n error: `No adapter configured for provider: ${resolved.provider}`,\n taskType: resolved.taskType,\n model: resolved.model,\n durationMs: Date.now() - startTime,\n timestamp: new Date().toISOString(),\n };\n }\n\n // Get API key for the provider\n const providerConfig = this.config.providers?.[resolved.provider as Provider];\n const apiKey = providerConfig?.apiKey ?? this.getEnvApiKey(resolved.provider as Provider);\n\n // Build the full prompt\n const fullInput = input.systemPrompt\n ? `${input.systemPrompt}\\n\\n${input.prompt}`\n : input.prompt;\n\n // Execute the adapter\n const result = await adapter.execute({\n model: resolved.modelName,\n input: fullInput,\n apiKey: apiKey ?? '',\n baseUrl: providerConfig?.baseUrl,\n });\n\n const durationMs = Date.now() - startTime;\n\n // Calculate cost based on tokens\n const tokensIn = result.tokensIn ?? 0;\n const tokensOut = result.tokensOut ?? 0;\n const costUsd = calculateCost(resolved.model, tokensIn, tokensOut);\n\n // Record the run\n const runId = this.store.recordRun({\n prompt: input.prompt,\n systemPrompt: input.systemPrompt ?? null,\n taskType: resolved.taskType,\n model: resolved.model,\n success: result.success,\n output: result.output ?? null,\n error: result.error?.message ?? null,\n durationMs,\n tokensIn: result.tokensIn ?? null,\n tokensOut: result.tokensOut ?? null,\n costUsd: costUsd > 0 ? costUsd : null,\n metadata: input.metadata ? JSON.stringify(input.metadata) : null,\n });\n\n return {\n runId,\n success: result.success,\n output: result.output,\n error: result.error?.message,\n taskType: resolved.taskType,\n model: resolved.model,\n durationMs,\n tokensIn: result.tokensIn,\n tokensOut: result.tokensOut,\n timestamp: new Date().toISOString(),\n };\n }\n\n /**\n * Gets an adapter for a provider.\n * Note: In the standalone proxy package, adapters are not used.\n * The proxy handles provider calls directly via HTTP.\n */\n private async getAdapter(_provider: Provider): Promise<ModelAdapter | null> {\n // Adapters not available in standalone proxy package\n // The proxy handles all provider calls directly\n return null;\n }\n\n /**\n * Gets an API key from environment variables.\n */\n private getEnvApiKey(provider: Provider): string | undefined {\n const envVars: Record<Provider, string> = {\n openai: 'OPENAI_API_KEY',\n anthropic: 'ANTHROPIC_API_KEY',\n google: 'GOOGLE_API_KEY',\n xai: 'XAI_API_KEY',\n moonshot: 'MOONSHOT_API_KEY',\n local: '',\n };\n\n const envVar = envVars[provider];\n return envVar ? process.env[envVar] : undefined;\n }\n\n /**\n * Records an outcome for a run.\n *\n * @param runId - The run ID\n * @param outcome - The outcome details\n * @returns The recorded outcome\n */\n recordOutcome(runId: string, outcome: Omit<OutcomeInput, 'runId'>): Outcome {\n return this.outcomeRecorder.record({\n runId,\n ...outcome,\n });\n }\n\n /**\n * Gets an outcome for a run.\n *\n * @param runId - The run ID\n * @returns The outcome, or null if not found\n */\n getOutcome(runId: string): Outcome | null {\n return this.outcomeRecorder.get(runId);\n }\n\n /**\n * Gets statistics for runs.\n *\n * @param options - Optional filters\n * @returns Statistics object\n */\n stats(options?: { from?: string; to?: string }): Stats {\n const raw = this.store.getStats(options);\n\n // Build stats by task type\n const byTaskType: Stats['byTaskType'] = {} as Stats['byTaskType'];\n const taskTypes: TaskType[] = [\n 'code_generation',\n 'code_review',\n 'summarization',\n 'analysis',\n 'creative_writing',\n 'data_extraction',\n 'translation',\n 'question_answering',\n 'general',\n ];\n\n for (const taskType of taskTypes) {\n const taskStats = raw.byTaskType[taskType];\n byTaskType[taskType] = {\n taskType,\n totalRuns: taskStats?.runs ?? 0,\n successfulRuns: Math.round((taskStats?.runs ?? 0) * (taskStats?.successRate ?? 0)),\n successRate: taskStats?.successRate ?? 0,\n avgDurationMs: taskStats?.avgDurationMs ?? 0,\n byModel: {},\n };\n }\n\n // Add model breakdown\n for (const [model, modelStats] of Object.entries(raw.byModel)) {\n // Find which task type this model belongs to (simplified - assumes model is used for one task type)\n // In a real implementation, we'd query runs grouped by task type AND model\n for (const taskType of taskTypes) {\n if (!byTaskType[taskType].byModel[model]) {\n byTaskType[taskType].byModel[model] = {\n runs: 0,\n successRate: 0,\n avgDurationMs: 0,\n };\n }\n }\n }\n\n return {\n totalRuns: raw.totalRuns,\n overallSuccessRate: raw.totalRuns > 0 ? raw.successfulRuns / raw.totalRuns : 0,\n byTaskType,\n period: {\n from: options?.from ?? '',\n to: options?.to ?? new Date().toISOString(),\n },\n };\n }\n\n /**\n * Gets a savings report.\n *\n * @param days - Number of days to include (default: 30)\n * @returns Savings report\n */\n savingsReport(days: number = 30): SavingsReport {\n return calculateSavings(this.store, days);\n }\n\n /**\n * Gets routing improvement suggestions.\n *\n * @returns Array of suggestions\n */\n getSuggestions(): Suggestion[] {\n // Get pending suggestions from the database\n const pending = this.store.getPendingSuggestions();\n\n return pending.map((record) => ({\n id: record.id,\n taskType: record.taskType,\n currentModel: record.currentModel,\n suggestedModel: record.suggestedModel,\n reason: record.reason,\n confidence: record.confidence,\n expectedImprovement: JSON.parse(record.expectedImprovement),\n sampleCount: record.sampleCount,\n createdAt: record.createdAt,\n accepted: record.accepted ?? undefined,\n acceptedAt: record.acceptedAt ?? undefined,\n }));\n }\n\n /**\n * Generates new suggestions based on current data.\n *\n * @returns Array of newly generated suggestions\n */\n generateSuggestions(): Suggestion[] {\n return this.patternDetector.generateSuggestions();\n }\n\n /**\n * Accepts a suggestion and updates routing.\n *\n * @param suggestionId - The suggestion ID to accept\n * @returns True if successful\n */\n acceptSuggestion(suggestionId: string): boolean {\n return this.store.acceptSuggestion(suggestionId);\n }\n\n /**\n * Rejects a suggestion.\n *\n * @param suggestionId - The suggestion ID to reject\n * @returns True if successful\n */\n rejectSuggestion(suggestionId: string): boolean {\n return this.store.rejectSuggestion(suggestionId);\n }\n\n /**\n * Closes the RelayPlane instance and releases resources.\n */\n close(): void {\n this.store.close();\n }\n}\n","#!/usr/bin/env node\n/**\n * RelayPlane Proxy CLI\n * \n * Intelligent AI model routing proxy server.\n * \n * Usage:\n * npx @relayplane/proxy [options]\n * relayplane-proxy [options]\n * \n * Options:\n * --port <number> Port to listen on (default: 3001)\n * --host <string> Host to bind to (default: 127.0.0.1)\n * -v, --verbose Enable verbose logging\n * -h, --help Show this help message\n * \n * Environment Variables:\n * ANTHROPIC_API_KEY Anthropic API key\n * OPENAI_API_KEY OpenAI API key\n * GEMINI_API_KEY Google Gemini API key\n * XAI_API_KEY xAI/Grok API key\n * MOONSHOT_API_KEY Moonshot API key\n * \n * @packageDocumentation\n */\n\nimport { startProxy } from './proxy.js';\n\nfunction printHelp(): void {\n console.log(`\nRelayPlane Proxy - Intelligent AI Model Routing\n\nUsage:\n npx @relayplane/proxy [options]\n relayplane-proxy [options]\n\nOptions:\n --port <number> Port to listen on (default: 3001)\n --host <string> Host to bind to (default: 127.0.0.1)\n -v, --verbose Enable verbose logging\n -h, --help Show this help message\n\nEnvironment Variables:\n ANTHROPIC_API_KEY Anthropic API key\n OPENAI_API_KEY OpenAI API key\n GEMINI_API_KEY Google Gemini API key (optional)\n XAI_API_KEY xAI/Grok API key (optional)\n MOONSHOT_API_KEY Moonshot API key (optional)\n\nExample:\n # Start proxy on default port\n npx @relayplane/proxy\n\n # Start on custom port with verbose logging\n npx @relayplane/proxy --port 8080 -v\n\n # Then point your SDKs to the proxy\n export ANTHROPIC_BASE_URL=http://localhost:3001\n export OPENAI_BASE_URL=http://localhost:3001\n\nLearn more: https://relayplane.com/integrations/openclaw\n`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n // Check for help\n if (args.includes('-h') || args.includes('--help')) {\n printHelp();\n process.exit(0);\n }\n\n // Parse arguments\n let port = 3001;\n let host = '127.0.0.1';\n let verbose = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n \n if (arg === '--port' && args[i + 1]) {\n port = parseInt(args[i + 1]!, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error('Error: Invalid port number');\n process.exit(1);\n }\n i++;\n } else if (arg === '--host' && args[i + 1]) {\n host = args[i + 1]!;\n i++;\n } else if (arg === '-v' || arg === '--verbose') {\n verbose = true;\n }\n }\n\n // Check for at least one API key\n const hasAnthropicKey = !!process.env['ANTHROPIC_API_KEY'];\n const hasOpenAIKey = !!process.env['OPENAI_API_KEY'];\n const hasGeminiKey = !!process.env['GEMINI_API_KEY'];\n const hasXAIKey = !!process.env['XAI_API_KEY'];\n const hasMoonshotKey = !!process.env['MOONSHOT_API_KEY'];\n\n if (!hasAnthropicKey && !hasOpenAIKey && !hasGeminiKey && !hasXAIKey && !hasMoonshotKey) {\n console.error('Error: No API keys found. Set at least one of:');\n console.error(' ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, XAI_API_KEY, MOONSHOT_API_KEY');\n process.exit(1);\n }\n\n // Print startup info\n console.log('');\n console.log(' ╭─────────────────────────────────────────╮');\n console.log(' │ RelayPlane Proxy v0.1.0 │');\n console.log(' │ Intelligent AI Model Routing │');\n console.log(' ╰─────────────────────────────────────────╯');\n console.log('');\n console.log(' Providers:');\n if (hasAnthropicKey) console.log(' ✓ Anthropic');\n if (hasOpenAIKey) console.log(' ✓ OpenAI');\n if (hasGeminiKey) console.log(' ✓ Google Gemini');\n if (hasXAIKey) console.log(' ✓ xAI (Grok)');\n if (hasMoonshotKey) console.log(' ✓ Moonshot');\n console.log('');\n\n try {\n await startProxy({ port, host, verbose });\n \n console.log('');\n console.log(' To use, set these environment variables:');\n console.log(` export ANTHROPIC_BASE_URL=http://${host}:${port}`);\n console.log(` export OPENAI_BASE_URL=http://${host}:${port}`);\n console.log('');\n console.log(' Then run your agent (OpenClaw, Cursor, Aider, etc.)');\n console.log('');\n } catch (err) {\n console.error('Failed to start proxy:', err);\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,WAAsB;;;ACPtB,4BAAqB;;;ACRrB,oBAAmB;;;ACAnB,IAAI,cACF;;;ADCF,IAAM,uBAAuB;AAC7B,IAAI;AAAJ,IAAU;AACV,IAAI,WAAW,WAAS;AACtB,MAAI,CAAC,QAAQ,KAAK,SAAS,OAAO;AAChC,WAAO,OAAO,YAAY,QAAQ,oBAAoB;AACtD,kBAAAA,QAAO,eAAe,IAAI;AAC1B,iBAAa;AAAA,EACf,WAAW,aAAa,QAAQ,KAAK,QAAQ;AAC3C,kBAAAA,QAAO,eAAe,IAAI;AAC1B,iBAAa;AAAA,EACf;AACA,gBAAc;AAChB;AAsBA,IAAI,SAAS,CAAC,OAAO,OAAO;AAC1B,WAAU,QAAQ,CAAE;AACpB,MAAI,KAAK;AACT,WAAS,IAAI,aAAa,MAAM,IAAI,YAAY,KAAK;AACnD,UAAM,YAAY,KAAK,CAAC,IAAI,EAAE;AAAA,EAChC;AACA,SAAO;AACT;;;ADjCA,SAAoB;AACpB,WAAsB;AACtB,SAAoB;;;AGDb,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8FnB,IAAM,wBAAwB;AAAA,EACnC,EAAE,UAAU,mBAAmB,gBAAgB,oCAAoC;AAAA,EACnF,EAAE,UAAU,eAAe,gBAAgB,oCAAoC;AAAA,EAC/E,EAAE,UAAU,iBAAiB,gBAAgB,oCAAoC;AAAA,EACjF,EAAE,UAAU,YAAY,gBAAgB,oCAAoC;AAAA,EAC5E,EAAE,UAAU,oBAAoB,gBAAgB,oCAAoC;AAAA,EACpF,EAAE,UAAU,mBAAmB,gBAAgB,oCAAoC;AAAA,EACnF,EAAE,UAAU,eAAe,gBAAgB,oCAAoC;AAAA,EAC/E,EAAE,UAAU,sBAAsB,gBAAgB,oCAAoC;AAAA,EACtF,EAAE,UAAU,WAAW,gBAAgB,oCAAoC;AAC7E;AAKO,SAAS,kBAA0B;AACxC,QAAM,SAAS,sBAAsB,IAAI,CAAC,MAAM,UAAU;AACxD,UAAM,KAAK,WAAW,KAAK,QAAQ;AACnC,WAAO,KAAK,EAAE,OAAO,KAAK,QAAQ,OAAO,KAAK,cAAc;AAAA,EAC9D,CAAC,EAAE,KAAK,OAAO;AAEf,SAAO;AAAA;AAAA;AAAA,IAGL,MAAM;AAAA;AAEV;;;AHvGO,SAAS,mBAA2B;AACzC,SAAY,UAAQ,WAAQ,GAAG,eAAe,SAAS;AACzD;AAKO,IAAM,QAAN,MAAY;AAAA,EACT;AAAA,EACS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjB,YAAY,QAAiB;AAC3B,SAAK,SAAS,UAAU,iBAAiB;AAGzC,UAAM,MAAW,aAAQ,KAAK,MAAM;AACpC,QAAI,CAAI,cAAW,GAAG,GAAG;AACvB,MAAG,aAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,IACvC;AAGA,SAAK,KAAK,IAAI,sBAAAC,QAAS,KAAK,MAAM;AAGlC,SAAK,GAAG,OAAO,oBAAoB;AAGnC,SAAK,GAAG,OAAO,mBAAmB;AAGlC,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAyB;AAC/B,SAAK,GAAG,KAAK,UAAU;AACvB,SAAK,GAAG,KAAK,gBAAgB,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,GAAG,MAAM;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAU,KAAkD;AAC1D,UAAM,KAAK,OAAO;AAClB,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA,KAG5B;AAED,SAAK;AAAA,MACH;AAAA,MACA,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI,UAAU,IAAI;AAAA,MAClB,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAA8B;AACnC,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA,KAI5B;AAED,UAAM,MAAM,KAAK,IAAI,EAAE;AACvB,QAAI,CAAC,IAAK,QAAO;AAEjB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS,QAAQ,IAAI,OAAO;AAAA,IAC9B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,SAOQ;AACd,UAAM,aAAuB,CAAC;AAC9B,UAAM,SAAoB,CAAC;AAE3B,QAAI,SAAS,UAAU;AACrB,iBAAW,KAAK,eAAe;AAC/B,aAAO,KAAK,QAAQ,QAAQ;AAAA,IAC9B;AAEA,QAAI,SAAS,OAAO;AAClB,iBAAW,KAAK,WAAW;AAC3B,aAAO,KAAK,QAAQ,KAAK;AAAA,IAC3B;AAEA,QAAI,SAAS,MAAM;AACjB,iBAAW,KAAK,iBAAiB;AACjC,aAAO,KAAK,QAAQ,IAAI;AAAA,IAC1B;AAEA,QAAI,SAAS,IAAI;AACf,iBAAW,KAAK,iBAAiB;AACjC,aAAO,KAAK,QAAQ,EAAE;AAAA,IACxB;AAEA,UAAM,cAAc,WAAW,SAAS,IAAI,SAAS,WAAW,KAAK,OAAO,CAAC,KAAK;AAClF,UAAM,QAAQ,SAAS,SAAS;AAChC,UAAM,SAAS,SAAS,UAAU;AAElC,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA,QAGzB,WAAW;AAAA;AAAA;AAAA,KAGd;AAED,WAAO,KAAK,OAAO,MAAM;AAEzB,UAAM,OAAO,KAAK,IAAI,GAAG,MAAM;AAC/B,WAAO,KAAK,IAAI,CAAC,SAAS;AAAA,MACxB,GAAG;AAAA,MACH,SAAS,QAAQ,IAAI,OAAO;AAAA,IAC9B,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,SAKC;AACT,UAAM,aAAuB,CAAC;AAC9B,UAAM,SAAoB,CAAC;AAE3B,QAAI,SAAS,UAAU;AACrB,iBAAW,KAAK,eAAe;AAC/B,aAAO,KAAK,QAAQ,QAAQ;AAAA,IAC9B;AAEA,QAAI,SAAS,OAAO;AAClB,iBAAW,KAAK,WAAW;AAC3B,aAAO,KAAK,QAAQ,KAAK;AAAA,IAC3B;AAEA,QAAI,SAAS,MAAM;AACjB,iBAAW,KAAK,iBAAiB;AACjC,aAAO,KAAK,QAAQ,IAAI;AAAA,IAC1B;AAEA,QAAI,SAAS,IAAI;AACf,iBAAW,KAAK,iBAAiB;AACjC,aAAO,KAAK,QAAQ,EAAE;AAAA,IACxB;AAEA,UAAM,cAAc,WAAW,SAAS,IAAI,SAAS,WAAW,KAAK,OAAO,CAAC,KAAK;AAElF,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA,QAGzB,WAAW;AAAA,KACd;AAED,UAAM,MAAM,KAAK,IAAI,GAAG,MAAM;AAC9B,WAAO,IAAI;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cAAc,SAA0D;AACtE,UAAM,KAAK,OAAO;AAClB,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAU5B;AAED,SAAK;AAAA,MACH;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ,UAAU,IAAI;AAAA,MACtB,QAAQ;AAAA,MACR,QAAQ,uBAAuB,OAAQ,QAAQ,sBAAsB,IAAI,IAAK;AAAA,MAC9E,QAAQ,oBAAoB,OAAQ,QAAQ,mBAAmB,IAAI,IAAK;AAAA,MACxE,QAAQ;AAAA,IACV;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,OAAqC;AAC9C,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA,KAI5B;AAED,UAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,QAAI,CAAC,IAAK,QAAO;AAEjB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS,QAAQ,IAAI,OAAO;AAAA,MAC5B,qBAAqB,IAAI,uBAAuB,OAAO,QAAQ,IAAI,mBAAmB,IAAI;AAAA,MAC1F,kBAAkB,IAAI,oBAAoB,OAAO,QAAQ,IAAI,gBAAgB,IAAI;AAAA,IACnF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,SAMqD;AAC/D,UAAM,aAAuB,CAAC;AAC9B,UAAM,SAAoB,CAAC;AAE3B,QAAI,SAAS,UAAU;AACrB,iBAAW,KAAK,iBAAiB;AACjC,aAAO,KAAK,QAAQ,QAAQ;AAAA,IAC9B;AAEA,QAAI,SAAS,OAAO;AAClB,iBAAW,KAAK,aAAa;AAC7B,aAAO,KAAK,QAAQ,KAAK;AAAA,IAC3B;AAEA,QAAI,SAAS,MAAM;AACjB,iBAAW,KAAK,mBAAmB;AACnC,aAAO,KAAK,QAAQ,IAAI;AAAA,IAC1B;AAEA,QAAI,SAAS,IAAI;AACf,iBAAW,KAAK,mBAAmB;AACnC,aAAO,KAAK,QAAQ,EAAE;AAAA,IACxB;AAEA,UAAM,cAAc,WAAW,SAAS,IAAI,SAAS,WAAW,KAAK,OAAO,CAAC,KAAK;AAClF,UAAM,QAAQ,SAAS,SAAS;AAEhC,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA,QAIzB,WAAW;AAAA;AAAA;AAAA,KAGd;AAED,WAAO,KAAK,KAAK;AAEjB,UAAM,OAAO,KAAK,IAAI,GAAG,MAAM;AAC/B,WAAO,KAAK,IAAI,CAAC,SAAS;AAAA,MACxB,GAAG;AAAA,MACH,SAAS,QAAQ,IAAI,OAAO;AAAA,MAC5B,qBAAqB,IAAI,uBAAuB,OAAO,QAAQ,IAAI,mBAAmB,IAAI;AAAA,MAC1F,kBAAkB,IAAI,oBAAoB,OAAO,QAAQ,IAAI,gBAAgB,IAAI;AAAA,IACnF,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,QAAQ,UAAuC;AAC7C,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA,KAI5B;AAED,WAAQ,KAAK,IAAI,QAAQ,KAAgC;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,UAAoB,gBAAwB,QAAoB,YAAqB,aAA8B;AACzH,UAAM,eAAe,KAAK,QAAQ,QAAQ;AAC1C,UAAM,KAAK,cAAc,MAAM,OAAO;AAEtC,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAS5B;AAED,SAAK,IAAI,IAAI,UAAU,gBAAgB,QAAQ,cAAc,MAAM,eAAe,IAAI;AAEtF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,YAA0B;AACxB,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA,KAI5B;AAED,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,UAA6B;AAEtC,UAAM,cAAc,sBAAsB,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ;AAC7E,QAAI,CAAC,YAAa,QAAO;AAGzB,SAAK,QAAQ,UAAU,YAAY,gBAAgB,SAAS;AAC5D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,iBAAiB,YAA+E;AAC9F,UAAM,KAAK,OAAO;AAClB,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA,KAG5B;AAED,SAAK;AAAA,MACH;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW,YAAY;AAAA,IACzB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,IAAqC;AACjD,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA,KAI5B;AAED,UAAM,MAAM,KAAK,IAAI,EAAE;AACvB,QAAI,CAAC,IAAK,QAAO;AAEjB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,UAAU,IAAI,YAAY,OAAO,QAAQ,IAAI,QAAQ,IAAI;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,wBAA4C;AAC1C,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,KAK5B;AAED,UAAM,OAAO,KAAK,IAAI;AACtB,WAAO,KAAK,IAAI,CAAC,SAAS;AAAA,MACxB,GAAG;AAAA,MACH,UAAU,IAAI,YAAY,OAAO,QAAQ,IAAI,QAAQ,IAAI;AAAA,IAC3D,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,IAAqB;AACpC,UAAM,aAAa,KAAK,cAAc,EAAE;AACxC,QAAI,CAAC,WAAY,QAAO;AAGxB,UAAM,aAAa,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA,KAIlC;AACD,eAAW,IAAI,EAAE;AAGjB,SAAK;AAAA,MACH,WAAW;AAAA,MACX,WAAW;AAAA,MACX;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,IAAqB;AACpC,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA,KAI5B;AAED,UAAM,SAAS,KAAK,IAAI,EAAE;AAC1B,WAAO,OAAO,UAAU;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SAAS,SAMP;AACA,UAAM,aAAuB,CAAC;AAC9B,UAAM,SAAoB,CAAC;AAE3B,QAAI,SAAS,MAAM;AACjB,iBAAW,KAAK,iBAAiB;AACjC,aAAO,KAAK,QAAQ,IAAI;AAAA,IAC1B;AAEA,QAAI,SAAS,IAAI;AACf,iBAAW,KAAK,iBAAiB;AACjC,aAAO,KAAK,QAAQ,EAAE;AAAA,IACxB;AAEA,UAAM,cAAc,WAAW,SAAS,IAAI,SAAS,WAAW,KAAK,OAAO,CAAC,KAAK;AAGlF,UAAM,cAAc,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMhC,WAAW;AAAA,KACd;AAED,UAAM,UAAU,YAAY,IAAI,GAAG,MAAM;AAOzC,UAAM,iBAAiB,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOnC,WAAW;AAAA;AAAA,KAEd;AAED,UAAM,iBAAiB,eAAe,IAAI,GAAG,MAAM;AAOnD,UAAM,aAA2F,CAAC;AAClG,eAAW,OAAO,gBAAgB;AAChC,iBAAW,IAAI,QAAQ,IAAI;AAAA,QACzB,MAAM,IAAI;AAAA,QACV,aAAa,IAAI;AAAA,QACjB,eAAe,IAAI;AAAA,MACrB;AAAA,IACF;AAGA,UAAM,cAAc,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOhC,WAAW;AAAA;AAAA,KAEd;AAED,UAAM,cAAc,YAAY,IAAI,GAAG,MAAM;AAO7C,UAAM,UAAwF,CAAC;AAC/F,eAAW,OAAO,aAAa;AAC7B,cAAQ,IAAI,KAAK,IAAI;AAAA,QACnB,MAAM,IAAI;AAAA,QACV,aAAa,IAAI;AAAA,QACjB,eAAe,IAAI;AAAA,MACrB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,WAAW,QAAQ;AAAA,MACnB,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,eAAe,QAAQ,iBAAiB;AAAA,MACxC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,UAMd;AACD,UAAM,OAAO,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAY5B;AAED,WAAO,KAAK,IAAI,QAAQ;AAAA,EAO1B;AACF;;;AI3nBA,IAAM,gBAAsD;AAAA,EAC1D,iBAAiB;AAAA,IACf,EAAE,SAAS,sJAAsJ,QAAQ,GAAG;AAAA,IAC5K,EAAE,SAAS,2GAA2G,QAAQ,GAAG;AAAA,IACjI,EAAE,SAAS,uCAAuC,QAAQ,EAAE;AAAA,IAC5D,EAAE,SAAS,sDAAsD,QAAQ,EAAE;AAAA,IAC3E,EAAE,SAAS,mBAAmB,QAAQ,EAAE;AAAA,IACxC,EAAE,SAAS,kDAAkD,QAAQ,EAAE;AAAA,IACvE,EAAE,SAAS,eAAe,QAAQ,EAAE;AAAA;AAAA,EACtC;AAAA,EAEA,aAAa;AAAA,IACX,EAAE,SAAS,iJAAiJ,QAAQ,GAAG;AAAA,IACvK,EAAE,SAAS,iGAAiG,QAAQ,EAAE;AAAA,IACtH,EAAE,SAAS,mEAAmE,QAAQ,EAAE;AAAA,IACxF,EAAE,SAAS,4CAA4C,QAAQ,EAAE;AAAA,IACjE,EAAE,SAAS,sBAAsB,QAAQ,GAAG;AAAA,IAC5C,EAAE,SAAS,+BAA+B,QAAQ,EAAE;AAAA,EACtD;AAAA,EAEA,eAAe;AAAA,IACb,EAAE,SAAS,+EAA+E,QAAQ,GAAG;AAAA,IACrG,EAAE,SAAS,+FAA+F,QAAQ,EAAE;AAAA,IACpH,EAAE,SAAS,6BAA6B,QAAQ,EAAE;AAAA,IAClD,EAAE,SAAS,sCAAsC,QAAQ,EAAE;AAAA,IAC3D,EAAE,SAAS,mCAAmC,QAAQ,EAAE;AAAA,IACxD,EAAE,SAAS,gCAAgC,QAAQ,EAAE;AAAA,EACvD;AAAA,EAEA,UAAU;AAAA,IACR,EAAE,SAAS,6EAA6E,QAAQ,EAAE;AAAA,IAClG,EAAE,SAAS,6EAA6E,QAAQ,EAAE;AAAA,IAClG,EAAE,SAAS,gGAAgG,QAAQ,EAAE;AAAA,IACrH,EAAE,SAAS,wFAAwF,QAAQ,EAAE;AAAA,IAC7G,EAAE,SAAS,qBAAqB,QAAQ,EAAE;AAAA,IAC1C,EAAE,SAAS,oBAAoB,QAAQ,EAAE;AAAA,IACzC,EAAE,SAAS,yDAAyD,QAAQ,EAAE;AAAA,EAChF;AAAA,EAEA,kBAAkB;AAAA,IAChB,EAAE,SAAS,+HAA+H,QAAQ,GAAG;AAAA,IACrJ,EAAE,SAAS,iEAAiE,QAAQ,GAAG;AAAA,IACvF,EAAE,SAAS,yBAAyB,QAAQ,EAAE;AAAA,IAC9C,EAAE,SAAS,uDAAuD,QAAQ,EAAE;AAAA,IAC5E,EAAE,SAAS,iEAAiE,QAAQ,EAAE;AAAA,IACtF,EAAE,SAAS,gDAAgD,QAAQ,EAAE;AAAA,IACrE,EAAE,SAAS,qEAAqE,QAAQ,EAAE;AAAA,EAC5F;AAAA,EAEA,iBAAiB;AAAA,IACf,EAAE,SAAS,0KAA0K,QAAQ,GAAG;AAAA,IAChM,EAAE,SAAS,uFAAuF,QAAQ,EAAE;AAAA,IAC5G,EAAE,SAAS,0CAA0C,QAAQ,EAAE;AAAA,IAC/D,EAAE,SAAS,kDAAkD,QAAQ,GAAG;AAAA,IACxE,EAAE,SAAS,uBAAuB,QAAQ,EAAE;AAAA,IAC5C,EAAE,SAAS,sCAAsC,QAAQ,EAAE;AAAA,EAC7D;AAAA,EAEA,aAAa;AAAA,IACX,EAAE,SAAS,2CAA2C,QAAQ,GAAG;AAAA,IACjE,EAAE,SAAS,qJAAqJ,QAAQ,EAAE;AAAA,IAC1K,EAAE,SAAS,wHAAwH,QAAQ,EAAE;AAAA,IAC7I,EAAE,SAAS,0HAA0H,QAAQ,GAAG;AAAA,IAChJ,EAAE,SAAS,8BAA8B,QAAQ,EAAE;AAAA,EACrD;AAAA,EAEA,oBAAoB;AAAA,IAClB,EAAE,SAAS,0FAA0F,QAAQ,EAAE;AAAA,IAC/G,EAAE,SAAS,QAAQ,QAAQ,EAAE;AAAA,IAC7B,EAAE,SAAS,yEAAyE,QAAQ,EAAE;AAAA,IAC9F,EAAE,SAAS,0DAA0D,QAAQ,EAAE;AAAA,IAC/E,EAAE,SAAS,YAAY,QAAQ,EAAE;AAAA,IACjC,EAAE,SAAS,oCAAoC,QAAQ,EAAE;AAAA,IACzD,EAAE,SAAS,wCAAwC,QAAQ,EAAE;AAAA,EAC/D;AAAA,EAEA,SAAS;AAAA;AAAA,IAEP,EAAE,SAAS,MAAM,QAAQ,EAAE;AAAA,EAC7B;AACF;AAQO,SAAS,cAAc,QAA0B;AAEtD,QAAM,mBAAmB,OAAO,KAAK,EAAE,YAAY;AAGnD,QAAM,SAAmC;AAAA,IACvC,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,UAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,SAAS;AAAA,EACX;AAGA,aAAW,CAAC,UAAU,QAAQ,KAAK,OAAO,QAAQ,aAAa,GAAG;AAChE,eAAW,EAAE,SAAS,OAAO,KAAK,UAAU;AAC1C,UAAI,QAAQ,KAAK,MAAM,GAAG;AACxB,eAAO,QAAoB,KAAK;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,WAAW;AACf,MAAI,eAAyB;AAE7B,aAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACtD,QAAI,QAAQ,UAAU;AACpB,iBAAW;AACX,qBAAe;AAAA,IACjB;AAAA,EACF;AAGA,MAAI,YAAY,GAAG;AACjB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AASO,SAAS,uBAAuB,QAAgB,UAA4B;AACjF,QAAM,WAAW,cAAc,QAAQ;AACvC,MAAI,CAAC,SAAU,QAAO;AAEtB,MAAI,cAAc;AAClB,MAAI,oBAAoB;AAExB,aAAW,EAAE,SAAS,OAAO,KAAK,UAAU;AAC1C,yBAAqB;AACrB,QAAI,QAAQ,KAAK,MAAM,GAAG;AACxB,qBAAe;AAAA,IACjB;AAAA,EACF;AAEA,MAAI,sBAAsB,EAAG,QAAO;AAGpC,SAAO,KAAK,IAAI,cAAc,mBAAmB,IAAI;AACvD;;;AC7KO,IAAM,gBAAN,MAAoB;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOR,YAAY,OAAc;AACxB,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAc,QAA0B;AACtC,WAAO,cAAc,MAAM;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,uBAAuB,QAAgB,UAA4B;AACjE,WAAO,uBAAuB,QAAQ,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,UAAwC;AAC1C,UAAM,SAAS,KAAK,MAAM,QAAQ,QAAQ;AAC1C,QAAI,CAAC,OAAQ,QAAO;AAEpB,WAAO;AAAA,MACL,IAAI,OAAO;AAAA,MACX,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,QAAQ,OAAO;AAAA,MACf,YAAY,OAAO,cAAc;AAAA,MACjC,aAAa,OAAO,eAAe;AAAA,MACnC,WAAW,OAAO;AAAA,MAClB,WAAW,OAAO;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,IACE,UACA,gBACA,SAAqB,QACrB,SACQ;AACR,WAAO,KAAK,MAAM;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAsB;AACpB,UAAM,UAAU,KAAK,MAAM,UAAU;AACrC,WAAO,QAAQ,IAAI,CAAC,YAAY;AAAA,MAC9B,IAAI,OAAO;AAAA,MACX,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,QAAQ,OAAO;AAAA,MACf,YAAY,OAAO,cAAc;AAAA,MACjC,aAAa,OAAO,eAAe;AAAA,MACnC,WAAW,OAAO;AAAA,MAClB,WAAW,OAAO;AAAA,IACpB,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,UAA6B;AAClC,WAAO,KAAK,MAAM,WAAW,QAAQ;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,kBAAkB,UAA4B;AAC5C,UAAM,OAAO,KAAK,IAAI,QAAQ;AAC9B,WAAO,MAAM,kBAAkB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,aAA0D;AACnE,UAAM,QAAQ,YAAY,MAAM,GAAG;AACnC,QAAI,MAAM,SAAS,GAAG;AACpB,aAAO,EAAE,UAAU,SAAS,OAAO,YAAY;AAAA,IACjD;AACA,WAAO,EAAE,UAAU,MAAM,CAAC,GAAI,OAAO,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QACE,QACA,kBACA,eAOA;AAEA,UAAM,WAAW,oBAAoB,KAAK,cAAc,MAAM;AAC9D,UAAM,aAAa,KAAK,uBAAuB,QAAQ,QAAQ;AAG/D,QAAI;AACJ,QAAI,eAAe;AACjB,cAAQ;AAAA,IACV,OAAO;AACL,cAAQ,KAAK,kBAAkB,QAAQ;AAAA,IACzC;AAEA,UAAM,EAAE,UAAU,OAAO,UAAU,IAAI,KAAK,WAAW,KAAK;AAE5D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AC/KO,IAAM,kBAAN,MAAsB;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOR,YAAY,OAAc;AACxB,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,OAA8B;AAEnC,UAAM,MAAM,KAAK,MAAM,OAAO,MAAM,KAAK;AACzC,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,MAAM,kBAAkB,MAAM,KAAK,EAAE;AAAA,IACjD;AAGA,UAAM,KAAK,KAAK,MAAM,cAAc;AAAA,MAClC,OAAO,MAAM;AAAA,MACb,SAAS,MAAM;AAAA,MACf,SAAS,MAAM,WAAW;AAAA,MAC1B,qBAAqB,MAAM,uBAAuB;AAAA,MAClD,kBAAkB,MAAM,oBAAoB;AAAA,MAC5C,UAAU,MAAM,YAAY;AAAA,IAC9B,CAAC;AAGD,UAAM,UAAU,KAAK,MAAM,WAAW,MAAM,KAAK;AACjD,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,WAAO;AAAA,MACL,IAAI,QAAQ;AAAA,MACZ,OAAO,QAAQ;AAAA,MACf,SAAS,QAAQ;AAAA,MACjB,SAAS,QAAQ,WAAW;AAAA,MAC5B,qBAAqB,QAAQ,uBAAuB;AAAA,MACpD,kBAAkB,QAAQ,oBAAoB;AAAA,MAC9C,UAAU,QAAQ,YAAY;AAAA,MAC9B,YAAY,QAAQ;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,OAA+B;AACjC,UAAM,UAAU,KAAK,MAAM,WAAW,KAAK;AAC3C,QAAI,CAAC,QAAS,QAAO;AAErB,WAAO;AAAA,MACL,IAAI,QAAQ;AAAA,MACZ,OAAO,QAAQ;AAAA,MACf,SAAS,QAAQ;AAAA,MACjB,SAAS,QAAQ,WAAW;AAAA,MAC5B,qBAAqB,QAAQ,uBAAuB;AAAA,MACpD,kBAAkB,QAAQ,oBAAoB;AAAA,MAC9C,UAAU,QAAQ,YAAY;AAAA,MAC9B,YAAY,QAAQ;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,UAMX;AACA,UAAM,WAAW,KAAK,MAAM,YAAY,EAAE,UAA2B,OAAO,IAAK,CAAC;AAElF,QAAI,SAAS,WAAW,GAAG;AACzB,aAAO;AAAA,QACL,eAAe;AAAA,QACf,aAAa;AAAA,QACb,qBAAqB,CAAC;AAAA,QACtB,yBAAyB;AAAA,QACzB,sBAAsB;AAAA,MACxB;AAAA,IACF;AAGA,QAAI,eAAe;AACnB,QAAI,wBAAwB;AAC5B,QAAI,oBAAoB;AACxB,QAAI,qBAAqB;AACzB,QAAI,iBAAiB;AACrB,UAAM,sBAA8C,CAAC;AAErD,eAAW,WAAW,UAAU;AAC9B,UAAI,QAAQ,QAAS;AAErB,UAAI,QAAQ,SAAS;AACnB,4BAAoB,QAAQ,OAAO,KAAK,oBAAoB,QAAQ,OAAO,KAAK,KAAK;AAAA,MACvF;AAEA,UAAI,QAAQ,uBAAuB,MAAM;AACvC;AACA,YAAI,QAAQ,oBAAqB;AAAA,MACnC;AAEA,UAAI,QAAQ,oBAAoB,MAAM;AACpC;AACA,YAAI,QAAQ,iBAAkB;AAAA,MAChC;AAAA,IACF;AAEA,WAAO;AAAA,MACL,eAAe,SAAS;AAAA,MACxB,aAAa,eAAe,SAAS;AAAA,MACrC;AAAA,MACA,yBAAyB,oBAAoB,IAAI,wBAAwB,oBAAoB;AAAA,MAC7F,sBAAsB,iBAAiB,IAAI,qBAAqB,iBAAiB;AAAA,IACnF;AAAA,EACF;AACF;;;ACxIO,IAAM,gBAAmE;AAAA;AAAA,EAE9E,2BAA2B,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA,EACvD,6BAA6B,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA,EACzD,4BAA4B,EAAE,OAAO,GAAG,QAAQ,GAAG;AAAA,EACnD,8BAA8B,EAAE,OAAO,GAAG,QAAQ,GAAG;AAAA,EACrD,4BAA4B,EAAE,OAAO,GAAG,QAAQ,GAAG;AAAA,EACnD,wBAAwB,EAAE,OAAO,IAAI,QAAQ,GAAG;AAAA,EAChD,0BAA0B,EAAE,OAAO,IAAI,QAAQ,GAAG;AAAA,EAClD,4BAA4B,EAAE,OAAO,IAAI,QAAQ,GAAG;AAAA;AAAA,EAEpD,UAAU,EAAE,OAAO,KAAK,QAAQ,GAAG;AAAA,EACnC,eAAe,EAAE,OAAO,MAAM,QAAQ,IAAI;AAAA,EAC1C,WAAW,EAAE,OAAO,GAAG,QAAQ,EAAE;AAAA,EACjC,eAAe,EAAE,OAAO,IAAI,QAAQ,GAAG;AAAA;AAAA,EAEvC,oBAAoB,EAAE,OAAO,OAAO,QAAQ,IAAI;AAAA,EAChD,kBAAkB,EAAE,OAAO,MAAM,QAAQ,EAAE;AAAA,EAC3C,oBAAoB,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA;AAAA,EAE9C,UAAU,EAAE,OAAO,GAAG,QAAQ,GAAG;AAAA,EACjC,iBAAiB,EAAE,OAAO,GAAG,QAAQ,GAAG;AAAA;AAAA,EAExC,kBAAkB,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,EAC5C,mBAAmB,EAAE,OAAO,KAAK,QAAQ,IAAI;AAC/C;AAKO,IAAM,iBAAiB;AA+CvB,SAAS,cACd,OACA,UACA,WACQ;AAER,QAAM,YAAY,MAAM,SAAS,GAAG,IAAI,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI;AAG9D,QAAM,UAAU,cAAc,SAAuC,KACnE,cAAc,KAAmC,KACjD,EAAE,OAAO,GAAG,QAAQ,EAAE;AAExB,QAAM,YAAa,WAAW,MAAa,QAAQ;AACnD,QAAM,aAAc,YAAY,MAAa,QAAQ;AAErD,SAAO,YAAY;AACrB;AAeO,SAAS,iBAAiB,OAAc,OAAe,IAAmB;AAE/E,QAAM,KAAK,oBAAI,KAAK;AACpB,QAAM,OAAO,oBAAI,KAAK;AACtB,OAAK,QAAQ,KAAK,QAAQ,IAAI,IAAI;AAElC,QAAM,UAAU,KAAK,YAAY;AACjC,QAAM,QAAQ,GAAG,YAAY;AAG7B,QAAM,OAAO,MAAM,QAAQ;AAAA,IACzB,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA;AAAA,EACT,CAAC;AAGD,QAAM,UAA8C,CAAC;AACrD,QAAM,aAAgF,CAAC;AAEvF,MAAI,gBAAgB;AACpB,MAAI,iBAAiB;AACrB,MAAI,aAAa;AACjB,MAAI,eAAe;AAEnB,QAAM,kBAAkB,cAAc,cAAc,KAAK,EAAE,OAAO,IAAI,QAAQ,GAAG;AAEjF,aAAW,OAAO,MAAM;AACtB,UAAM,WAAW,IAAI,YAAY;AACjC,UAAM,YAAY,IAAI,aAAa;AACnC,UAAM,YAAY,IAAI,MAAM,SAAS,GAAG,IAAI,IAAI,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,QAAQ,IAAI;AAGvF,UAAM,UAAU,cAAc,IAAI,OAAO,UAAU,SAAS;AAC5D,kBAAc;AAGd,UAAM,kBAAmB,WAAW,OAAc,iBAAiB,SAAS,MACzE,YAAY,OAAc,iBAAiB,UAAU;AACxD,oBAAgB;AAGhB,qBAAiB;AACjB,sBAAkB;AAGlB,QAAI,CAAC,QAAQ,SAAS,GAAG;AACvB,cAAQ,SAAS,IAAI;AAAA,QACnB,MAAM;AAAA,QACN,UAAU;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,aAAa;AAAA,QACb,cAAc;AAAA,MAChB;AAAA,IACF;AACA,UAAM,aAAa,QAAQ,SAAS;AACpC,eAAW;AACX,eAAW,YAAY;AACvB,eAAW,aAAa;AACxB,eAAW,QAAQ;AACnB,eAAW,gBAAgB,IAAI;AAC/B,QAAI,IAAI,SAAS;AACf,iBAAW;AAAA,IACb;AAGA,QAAI,CAAC,WAAW,IAAI,QAAQ,GAAG;AAC7B,iBAAW,IAAI,QAAQ,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,EAAE;AAAA,IAC9D;AACA,UAAM,YAAY,WAAW,IAAI,QAAQ;AACzC,cAAU;AACV,cAAU,aAAa;AAAA,EACzB;AAGA,aAAW,SAAS,OAAO,KAAK,OAAO,GAAG;AACxC,UAAM,QAAQ,QAAQ,KAAK;AAC3B,UAAM,cAAc,MAAM,OAAO,IAAI,MAAM,cAAc,MAAM,OAAO;AACtE,UAAM,eAAe,MAAM,OAAO,IAAI,MAAM,eAAe,MAAM,OAAO;AAAA,EAC1E;AAGA,QAAM,kBAAyF,CAAC;AAChG,aAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC1D,oBAAgB,QAAQ,IAAI;AAAA,MAC1B,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,MACZ,eAAe,MAAM,OAAO,IAAI,MAAM,YAAY,MAAM,OAAO;AAAA,IACjE;AAAA,EACF;AAGA,QAAM,UAAU,eAAe;AAC/B,QAAM,iBAAiB,eAAe,IAAK,UAAU,eAAgB,MAAM;AAE3E,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,IAAI;AAAA,IACN;AAAA,IACA,WAAW,KAAK;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,KAAK,IAAI,GAAG,OAAO;AAAA;AAAA,IAC5B,gBAAgB,KAAK,IAAI,GAAG,cAAc;AAAA,IAC1C;AAAA,IACA,YAAY;AAAA,EACd;AACF;;;AC1NA,IAAM,0BAA0B;AAKhC,IAAM,2BAA2B;AAKjC,IAAM,4BAA4B;AAKlC,IAAM,iCAAiC;AAKhC,IAAM,kBAAN,MAAsB;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOR,YAAY,OAAc;AACxB,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,UAAkC;AAChD,UAAM,QAAQ,KAAK,MAAM,iBAAiB,QAAQ;AAElD,QAAI,MAAM,SAAS,GAAG;AAEpB,aAAO,CAAC;AAAA,IACV;AAGA,UAAM,cAAc,KAAK,MAAM,QAAQ,QAAQ;AAC/C,QAAI,CAAC,YAAa,QAAO,CAAC;AAE1B,UAAM,eAAe,YAAY;AAGjC,UAAM,eAAe,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,YAAY;AAC/D,QAAI,CAAC,aAAc,QAAO,CAAC;AAG3B,UAAM,mBAAmB,aAAa,SAAS,GAAG,IAAI,aAAa,MAAM,GAAG,EAAE,CAAC,IAAI;AACnF,UAAM,iBAAiB,cAAc,gBAA8C;AAGnF,UAAM,cAA4B,CAAC;AAEnC,eAAW,cAAc,OAAO;AAC9B,UAAI,WAAW,UAAU,aAAc;AACvC,UAAI,WAAW,OAAO,wBAAyB;AAG/C,YAAM,qBAAqB,WAAW,qBAAqB,aAAa;AACxE,YAAM,sBAAsB,aAAa,gBAAgB,WAAW,iBAAiB,aAAa;AAGlG,YAAM,qBAAqB,WAAW,MAAM,SAAS,GAAG,IACpD,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC,IAC7B,WAAW;AACf,YAAM,mBAAmB,cAAc,kBAAgD;AAEvF,UAAI,kBAAkB;AACtB,UAAI,kBAAkB,kBAAkB;AAEtC,cAAM,kBAAkB,eAAe,QAAQ,eAAe,UAAU;AACxE,cAAM,oBAAoB,iBAAiB,QAAQ,iBAAiB,UAAU;AAC9E,2BAAmB,iBAAiB,oBAAoB;AAAA,MAC1D;AAIA,YAAM,wBACJ,qBAAqB,6BACpB,sBAAsB,KAAK,qBAAqB,6BAChD,sBAAsB,SAAS,kBAAkB;AAEpD,UAAI,CAAC,sBAAuB;AAG5B,YAAM,mBAAmB,KAAK,IAAI,WAAW,OAAO,IAAI,CAAC;AACzD,YAAM,wBAAwB,KAAK;AAAA,QACjC,KAAK,IAAI,kBAAkB,IAAI,MAC/B,KAAK,IAAI,kBAAkB,IAAI,MAC/B,KAAK,IAAI,eAAe,IAAI;AAAA,QAC5B;AAAA,MACF;AACA,YAAM,cAAc,mBAAmB,yBAAyB;AAEhE,UAAI,aAAa,yBAA0B;AAG3C,YAAM,UAAoB,CAAC;AAC3B,UAAI,qBAAqB,GAAG;AAC1B,gBAAQ,KAAK,IAAI,qBAAqB,KAAK,QAAQ,CAAC,CAAC,uBAAuB;AAAA,MAC9E;AACA,UAAI,qBAAqB,GAAG;AAC1B,gBAAQ,KAAK,IAAI,qBAAqB,KAAK,QAAQ,CAAC,CAAC,UAAU;AAAA,MACjE;AACA,UAAI,kBAAkB,GAAG;AACvB,gBAAQ,KAAK,IAAI,kBAAkB,KAAK,QAAQ,CAAC,CAAC,WAAW;AAAA,MAC/D;AAEA,YAAM,aAAyB;AAAA,QAC7B,IAAI,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA,gBAAgB,WAAW;AAAA,QAC3B,QAAQ,QAAQ,KAAK,IAAI;AAAA,QACzB;AAAA,QACA,qBAAqB;AAAA,UACnB,aAAa,qBAAqB,IAAI,qBAAqB;AAAA,UAC3D,SAAS,qBAAqB,IAAI,qBAAqB;AAAA,UACvD,MAAM,kBAAkB,IAAI,kBAAkB;AAAA,QAChD;AAAA,QACA,aAAa,WAAW;AAAA,QACxB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAEA,kBAAY,KAAK,UAAU;AAAA,IAC7B;AAGA,gBAAY,KAAK,CAAC,GAAG,MAAM,EAAE,aAAa,EAAE,UAAU;AAEtD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAA2B;AACzB,UAAM,YAAwB;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,iBAA+B,CAAC;AAEtC,eAAW,YAAY,WAAW;AAChC,YAAM,cAAc,KAAK,gBAAgB,QAAQ;AACjD,qBAAe,KAAK,GAAG,WAAW;AAAA,IACpC;AAGA,mBAAe,KAAK,CAAC,GAAG,MAAM,EAAE,aAAa,EAAE,UAAU;AAEzD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,aAAqC;AACpD,UAAM,MAAgB,CAAC;AAEvB,eAAW,cAAc,aAAa;AACpC,YAAM,KAAK,KAAK,MAAM,iBAAiB;AAAA,QACrC,UAAU,WAAW;AAAA,QACrB,cAAc,WAAW;AAAA,QACzB,gBAAgB,WAAW;AAAA,QAC3B,QAAQ,WAAW;AAAA,QACnB,YAAY,WAAW;AAAA,QACvB,qBAAqB,KAAK,UAAU,WAAW,mBAAmB;AAAA,QAClE,aAAa,WAAW;AAAA,QACxB,UAAU;AAAA,MACZ,CAAC;AACD,UAAI,KAAK,EAAE;AAAA,IACb;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,sBAAoC;AAClC,UAAM,cAAc,KAAK,WAAW;AAGpC,UAAM,UAAU,KAAK,MAAM,sBAAsB;AACjD,UAAM,eAAe,IAAI;AAAA,MACvB,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE,QAAQ,IAAI,EAAE,cAAc,EAAE;AAAA,IACxD;AAEA,UAAM,iBAAiB,YAAY;AAAA,MACjC,CAAC,MAAM,CAAC,aAAa,IAAI,GAAG,EAAE,QAAQ,IAAI,EAAE,cAAc,EAAE;AAAA,IAC9D;AAGA,SAAK,iBAAiB,cAAc;AAEpC,WAAO;AAAA,EACT;AACF;;;AC7KO,IAAM,aAAN,MAAiB;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtC,YAAY,SAA2B,CAAC,GAAG;AACzC,SAAK,SAAS;AAAA,MACZ,QAAQ,OAAO,UAAU,iBAAiB;AAAA,MAC1C,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,cAAc,OAAO,gBAAgB;AAAA,MACrC,WAAW,OAAO,aAAa,CAAC;AAAA,IAClC;AAGA,SAAK,QAAQ,IAAI,MAAM,KAAK,OAAO,MAAM;AAGzC,SAAK,WAAW,IAAI,cAAc,KAAK,KAAK;AAC5C,SAAK,kBAAkB,IAAI,gBAAgB,KAAK,KAAK;AACrD,SAAK,kBAAkB,IAAI,gBAAgB,KAAK,KAAK;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAI,OAAqC;AAC7C,UAAM,YAAY,KAAK,IAAI;AAG3B,UAAM,WAAW,KAAK,SAAS,QAAQ,MAAM,QAAQ,MAAM,UAAU,MAAM,KAAK;AAGhF,UAAM,UAAU,MAAM,KAAK,WAAW,SAAS,QAAoB;AACnE,QAAI,CAAC,SAAS;AAEZ,YAAMC,SAAQ,KAAK,MAAM,UAAU;AAAA,QACjC,QAAQ,MAAM;AAAA,QACd,cAAc,MAAM,gBAAgB;AAAA,QACpC,UAAU,SAAS;AAAA,QACnB,OAAO,SAAS;AAAA,QAChB,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,OAAO,uCAAuC,SAAS,QAAQ;AAAA,QAC/D,YAAY,KAAK,IAAI,IAAI;AAAA,QACzB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,SAAS;AAAA,QACT,UAAU,MAAM,WAAW,KAAK,UAAU,MAAM,QAAQ,IAAI;AAAA,MAC9D,CAAC;AAED,aAAO;AAAA,QACL,OAAAA;AAAA,QACA,SAAS;AAAA,QACT,OAAO,uCAAuC,SAAS,QAAQ;AAAA,QAC/D,UAAU,SAAS;AAAA,QACnB,OAAO,SAAS;AAAA,QAChB,YAAY,KAAK,IAAI,IAAI;AAAA,QACzB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAAA,IACF;AAGA,UAAM,iBAAiB,KAAK,OAAO,YAAY,SAAS,QAAoB;AAC5E,UAAM,SAAS,gBAAgB,UAAU,KAAK,aAAa,SAAS,QAAoB;AAGxF,UAAM,YAAY,MAAM,eACpB,GAAG,MAAM,YAAY;AAAA;AAAA,EAAO,MAAM,MAAM,KACxC,MAAM;AAGV,UAAM,SAAS,MAAM,QAAQ,QAAQ;AAAA,MACnC,OAAO,SAAS;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ,UAAU;AAAA,MAClB,SAAS,gBAAgB;AAAA,IAC3B,CAAC;AAED,UAAM,aAAa,KAAK,IAAI,IAAI;AAGhC,UAAM,WAAW,OAAO,YAAY;AACpC,UAAM,YAAY,OAAO,aAAa;AACtC,UAAM,UAAU,cAAc,SAAS,OAAO,UAAU,SAAS;AAGjE,UAAM,QAAQ,KAAK,MAAM,UAAU;AAAA,MACjC,QAAQ,MAAM;AAAA,MACd,cAAc,MAAM,gBAAgB;AAAA,MACpC,UAAU,SAAS;AAAA,MACnB,OAAO,SAAS;AAAA,MAChB,SAAS,OAAO;AAAA,MAChB,QAAQ,OAAO,UAAU;AAAA,MACzB,OAAO,OAAO,OAAO,WAAW;AAAA,MAChC;AAAA,MACA,UAAU,OAAO,YAAY;AAAA,MAC7B,WAAW,OAAO,aAAa;AAAA,MAC/B,SAAS,UAAU,IAAI,UAAU;AAAA,MACjC,UAAU,MAAM,WAAW,KAAK,UAAU,MAAM,QAAQ,IAAI;AAAA,IAC9D,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA,SAAS,OAAO;AAAA,MAChB,QAAQ,OAAO;AAAA,MACf,OAAO,OAAO,OAAO;AAAA,MACrB,UAAU,SAAS;AAAA,MACnB,OAAO,SAAS;AAAA,MAChB;AAAA,MACA,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,MAClB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,WAAW,WAAmD;AAG1E,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,UAAwC;AAC3D,UAAM,UAAoC;AAAA,MACxC,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,UAAU;AAAA,MACV,OAAO;AAAA,IACT;AAEA,UAAM,SAAS,QAAQ,QAAQ;AAC/B,WAAO,SAAS,QAAQ,IAAI,MAAM,IAAI;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cAAc,OAAe,SAA+C;AAC1E,WAAO,KAAK,gBAAgB,OAAO;AAAA,MACjC;AAAA,MACA,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,OAA+B;AACxC,WAAO,KAAK,gBAAgB,IAAI,KAAK;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAAiD;AACrD,UAAM,MAAM,KAAK,MAAM,SAAS,OAAO;AAGvC,UAAM,aAAkC,CAAC;AACzC,UAAM,YAAwB;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,eAAW,YAAY,WAAW;AAChC,YAAM,YAAY,IAAI,WAAW,QAAQ;AACzC,iBAAW,QAAQ,IAAI;AAAA,QACrB;AAAA,QACA,WAAW,WAAW,QAAQ;AAAA,QAC9B,gBAAgB,KAAK,OAAO,WAAW,QAAQ,MAAM,WAAW,eAAe,EAAE;AAAA,QACjF,aAAa,WAAW,eAAe;AAAA,QACvC,eAAe,WAAW,iBAAiB;AAAA,QAC3C,SAAS,CAAC;AAAA,MACZ;AAAA,IACF;AAGA,eAAW,CAAC,OAAO,UAAU,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AAG7D,iBAAW,YAAY,WAAW;AAChC,YAAI,CAAC,WAAW,QAAQ,EAAE,QAAQ,KAAK,GAAG;AACxC,qBAAW,QAAQ,EAAE,QAAQ,KAAK,IAAI;AAAA,YACpC,MAAM;AAAA,YACN,aAAa;AAAA,YACb,eAAe;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,WAAW,IAAI;AAAA,MACf,oBAAoB,IAAI,YAAY,IAAI,IAAI,iBAAiB,IAAI,YAAY;AAAA,MAC7E;AAAA,MACA,QAAQ;AAAA,QACN,MAAM,SAAS,QAAQ;AAAA,QACvB,IAAI,SAAS,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAc,OAAe,IAAmB;AAC9C,WAAO,iBAAiB,KAAK,OAAO,IAAI;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAA+B;AAE7B,UAAM,UAAU,KAAK,MAAM,sBAAsB;AAEjD,WAAO,QAAQ,IAAI,CAAC,YAAY;AAAA,MAC9B,IAAI,OAAO;AAAA,MACX,UAAU,OAAO;AAAA,MACjB,cAAc,OAAO;AAAA,MACrB,gBAAgB,OAAO;AAAA,MACvB,QAAQ,OAAO;AAAA,MACf,YAAY,OAAO;AAAA,MACnB,qBAAqB,KAAK,MAAM,OAAO,mBAAmB;AAAA,MAC1D,aAAa,OAAO;AAAA,MACpB,WAAW,OAAO;AAAA,MAClB,UAAU,OAAO,YAAY;AAAA,MAC7B,YAAY,OAAO,cAAc;AAAA,IACnC,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,sBAAoC;AAClC,WAAO,KAAK,gBAAgB,oBAAoB;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,cAA+B;AAC9C,WAAO,KAAK,MAAM,iBAAiB,YAAY;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,cAA+B;AAC9C,WAAO,KAAK,MAAM,iBAAiB,YAAY;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,MAAM,MAAM;AAAA,EACnB;AACF;;;AV9VO,IAAM,oBAAsD;AAAA,EACjE,WAAW;AAAA,IACT,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,KAAK;AAAA,IACH,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AACF;AAKO,IAAM,gBAAuE;AAAA;AAAA,EAElF,mBAAmB,EAAE,UAAU,aAAa,OAAO,2BAA2B;AAAA,EAC9E,mBAAmB,EAAE,UAAU,aAAa,OAAO,2BAA2B;AAAA,EAC9E,qBAAqB,EAAE,UAAU,aAAa,OAAO,6BAA6B;AAAA,EAClF,oBAAoB,EAAE,UAAU,aAAa,OAAO,4BAA4B;AAAA,EAChF,OAAO,EAAE,UAAU,aAAa,OAAO,4BAA4B;AAAA,EACnE,QAAQ,EAAE,UAAU,aAAa,OAAO,6BAA6B;AAAA,EACrE,MAAM,EAAE,UAAU,aAAa,OAAO,yBAAyB;AAAA;AAAA,EAE/D,UAAU,EAAE,UAAU,UAAU,OAAO,SAAS;AAAA,EAChD,eAAe,EAAE,UAAU,UAAU,OAAO,cAAc;AAAA,EAC1D,WAAW,EAAE,UAAU,UAAU,OAAO,UAAU;AACpD;AAMA,IAAM,kBAA2E;AAAA,EAC/E,iBAAiB,EAAE,UAAU,aAAa,OAAO,0BAA0B;AAAA,EAC3E,aAAa,EAAE,UAAU,aAAa,OAAO,0BAA0B;AAAA,EACvE,eAAe,EAAE,UAAU,aAAa,OAAO,0BAA0B;AAAA,EACzE,UAAU,EAAE,UAAU,aAAa,OAAO,0BAA0B;AAAA,EACpE,kBAAkB,EAAE,UAAU,aAAa,OAAO,0BAA0B;AAAA,EAC5E,iBAAiB,EAAE,UAAU,aAAa,OAAO,0BAA0B;AAAA,EAC3E,aAAa,EAAE,UAAU,aAAa,OAAO,0BAA0B;AAAA,EACvE,oBAAoB,EAAE,UAAU,aAAa,OAAO,0BAA0B;AAAA,EAC9E,SAAS,EAAE,UAAU,aAAa,OAAO,0BAA0B;AACrE;AA6BA,SAAS,kBAAkB,UAA2C;AACpE,SAAO,SACJ,IAAI,CAAC,QAAQ;AACZ,QAAI,OAAO,IAAI,YAAY,SAAU,QAAO,IAAI;AAChD,QAAI,MAAM,QAAQ,IAAI,OAAO,GAAG;AAC9B,aAAO,IAAI,QACR,IAAI,CAAC,MAAe;AACnB,cAAM,OAAO;AACb,eAAO,KAAK,SAAS,SAAU,KAAK,QAAQ,KAAM;AAAA,MACpD,CAAC,EACA,KAAK,GAAG;AAAA,IACb;AACA,WAAO;AAAA,EACT,CAAC,EACA,KAAK,IAAI;AACd;AAKA,eAAe,mBACb,SACA,aACA,QACA,aACmB;AACnB,QAAM,gBAAgB,mBAAmB,SAAS,aAAa,KAAK;AAEpE,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,qBAAqB;AAAA,EACvB;AAGA,MAAI,aAAa;AACf,YAAQ,gBAAgB,IAAI;AAAA,EAC9B;AAEA,QAAM,WAAW,MAAM,MAAM,yCAAyC;AAAA,IACpE,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,KAAK,UAAU,aAAa;AAAA,EACpC,CAAC;AAED,SAAO;AACT;AAKA,eAAe,yBACb,SACA,aACA,QACA,aACmB;AACnB,QAAM,gBAAgB,mBAAmB,SAAS,aAAa,IAAI;AAEnE,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,qBAAqB;AAAA,EACvB;AAEA,MAAI,aAAa;AACf,YAAQ,gBAAgB,IAAI;AAAA,EAC9B;AAEA,QAAM,WAAW,MAAM,MAAM,yCAAyC;AAAA,IACpE,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,KAAK,UAAU,aAAa;AAAA,EACpC,CAAC;AAED,SAAO;AACT;AAqBA,SAAS,2BAA2B,UAAiG;AACnI,QAAM,SAAoB,CAAC;AAE3B,aAAW,OAAO,UAAU;AAC1B,UAAM,IAAI;AAGV,QAAI,EAAE,SAAS,SAAU;AAGzB,QAAI,EAAE,SAAS,QAAQ;AACrB,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,aAAa,EAAE;AAAA,YACf,SAAS,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU,KAAK,UAAU,EAAE,OAAO;AAAA,UAC/E;AAAA,QACF;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAGA,QAAI,EAAE,SAAS,eAAe,EAAE,cAAc,EAAE,WAAW,SAAS,GAAG;AACrE,YAAM,UAAqB,CAAC;AAG5B,UAAI,EAAE,WAAW,OAAO,EAAE,YAAY,UAAU;AAC9C,gBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,EAAE,QAAQ,CAAC;AAAA,MAChD;AAGA,iBAAW,MAAM,EAAE,YAAY;AAC7B,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,IAAI,GAAG;AAAA,UACP,MAAM,GAAG,SAAS;AAAA,UAClB,OAAO,KAAK,MAAM,GAAG,SAAS,aAAa,IAAI;AAAA,QACjD,CAAC;AAAA,MACH;AAEA,aAAO,KAAK,EAAE,MAAM,aAAa,QAAQ,CAAC;AAC1C;AAAA,IACF;AAGA,WAAO,KAAK;AAAA,MACV,MAAM,EAAE,SAAS,cAAc,cAAc;AAAA,MAC7C,SAAS,EAAE;AAAA,IACb,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAKA,SAAS,mBACP,SACA,aACA,QACyB;AAEzB,QAAM,oBAAoB,2BAA2B,QAAQ,QAAQ;AAErE,QAAM,gBAAgB,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AAEtE,QAAM,gBAAyC;AAAA,IAC7C,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,QAAQ,cAAc;AAAA,IAClC;AAAA,EACF;AAEA,MAAI,eAAe;AACjB,kBAAc,QAAQ,IAAI,cAAc;AAAA,EAC1C;AAEA,MAAI,QAAQ,gBAAgB,QAAW;AACrC,kBAAc,aAAa,IAAI,QAAQ;AAAA,EACzC;AAGA,MAAI,QAAQ,SAAS,MAAM,QAAQ,QAAQ,KAAK,GAAG;AACjD,kBAAc,OAAO,IAAI,wBAAwB,QAAQ,KAAK;AAAA,EAChE;AAGA,MAAI,QAAQ,aAAa;AACvB,kBAAc,aAAa,IAAI,6BAA6B,QAAQ,WAAW;AAAA,EACjF;AAEA,SAAO;AACT;AAOA,SAAS,wBAAwB,OAA6B;AAC5D,SAAO,MAAM,IAAI,CAAC,SAAkB;AAClC,UAAM,IAAI;AACV,QAAI,EAAE,SAAS,cAAc,EAAE,UAAU;AACvC,aAAO;AAAA,QACL,MAAM,EAAE,SAAS;AAAA,QACjB,aAAa,EAAE,SAAS;AAAA,QACxB,cAAc,EAAE,SAAS,cAAc,EAAE,MAAM,UAAU,YAAY,CAAC,EAAE;AAAA,MAC1E;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AACH;AAKA,SAAS,6BAA6B,YAA8B;AAClE,MAAI,eAAe,OAAQ,QAAO,EAAE,MAAM,OAAO;AACjD,MAAI,eAAe,OAAQ,QAAO,EAAE,MAAM,OAAO;AACjD,MAAI,eAAe,WAAY,QAAO,EAAE,MAAM,MAAM;AAGpD,QAAM,KAAK;AACX,MAAI,GAAG,SAAS,cAAc,GAAG,UAAU,MAAM;AAC/C,WAAO,EAAE,MAAM,QAAQ,MAAM,GAAG,SAAS,KAAK;AAAA,EAChD;AAEA,SAAO;AACT;AAKA,eAAe,gBACb,SACA,aACA,QACmB;AACnB,QAAM,aAAa;AAAA,IACjB,GAAG;AAAA,IACH,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAEA,QAAM,WAAW,MAAM,MAAM,8CAA8C;AAAA,IACzE,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,MAAM;AAAA,IACjC;AAAA,IACA,MAAM,KAAK,UAAU,UAAU;AAAA,EACjC,CAAC;AAED,SAAO;AACT;AAKA,eAAe,sBACb,SACA,aACA,QACmB;AACnB,QAAM,aAAa;AAAA,IACjB,GAAG;AAAA,IACH,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAEA,QAAM,WAAW,MAAM,MAAM,8CAA8C;AAAA,IACzE,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,MAAM;AAAA,IACjC;AAAA,IACA,MAAM,KAAK,UAAU,UAAU;AAAA,EACjC,CAAC;AAED,SAAO;AACT;AAKA,eAAe,aACb,SACA,aACA,QACmB;AACnB,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAEA,QAAM,WAAW,MAAM,MAAM,wCAAwC;AAAA,IACnE,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,MAAM;AAAA,IACjC;AAAA,IACA,MAAM,KAAK,UAAU,OAAO;AAAA,EAC9B,CAAC;AAED,SAAO;AACT;AAKA,eAAe,mBACb,SACA,aACA,QACmB;AACnB,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAEA,QAAM,WAAW,MAAM,MAAM,wCAAwC;AAAA,IACnE,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,MAAM;AAAA,IACjC;AAAA,IACA,MAAM,KAAK,UAAU,OAAO;AAAA,EAC9B,CAAC;AAED,SAAO;AACT;AAKA,eAAe,kBACb,SACA,aACA,QACmB;AACnB,QAAM,eAAe;AAAA,IACnB,GAAG;AAAA,IACH,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAEA,QAAM,WAAW,MAAM,MAAM,+CAA+C;AAAA,IAC1E,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,MAAM;AAAA,IACjC;AAAA,IACA,MAAM,KAAK,UAAU,YAAY;AAAA,EACnC,CAAC;AAED,SAAO;AACT;AAKA,eAAe,wBACb,SACA,aACA,QACmB;AACnB,QAAM,eAAe;AAAA,IACnB,GAAG;AAAA,IACH,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAEA,QAAM,WAAW,MAAM,MAAM,+CAA+C;AAAA,IAC1E,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,MAAM;AAAA,IACjC;AAAA,IACA,MAAM,KAAK,UAAU,YAAY;AAAA,EACnC,CAAC;AAED,SAAO;AACT;AAKA,SAAS,wBAAwB,UAA8C;AAC7E,QAAM,iBAA4B,CAAC;AAEnC,aAAW,OAAO,UAAU;AAE1B,QAAI,IAAI,SAAS,SAAU;AAE3B,UAAM,OAAO,IAAI,SAAS,cAAc,UAAU;AAElD,QAAI,OAAO,IAAI,YAAY,UAAU;AACnC,qBAAe,KAAK;AAAA,QAClB;AAAA,QACA,OAAO,CAAC,EAAE,MAAM,IAAI,QAAQ,CAAC;AAAA,MAC/B,CAAC;AAAA,IACH,WAAW,MAAM,QAAQ,IAAI,OAAO,GAAG;AAErC,YAAM,QAAQ,IAAI,QAAQ,IAAI,CAAC,SAAkB;AAC/C,cAAM,IAAI;AACV,YAAI,EAAE,SAAS,QAAQ;AACrB,iBAAO,EAAE,MAAM,EAAE,KAAK;AAAA,QACxB;AACA,YAAI,EAAE,SAAS,eAAe,EAAE,WAAW,KAAK;AAE9C,gBAAM,MAAM,EAAE,UAAU;AACxB,cAAI,IAAI,WAAW,OAAO,GAAG;AAC3B,kBAAM,QAAQ,IAAI,MAAM,4BAA4B;AACpD,gBAAI,OAAO;AACT,qBAAO;AAAA,gBACL,aAAa;AAAA,kBACX,WAAW,MAAM,CAAC;AAAA,kBAClB,MAAM,MAAM,CAAC;AAAA,gBACf;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA,iBAAO,EAAE,MAAM,WAAW,GAAG,IAAI;AAAA,QACnC;AACA,eAAO,EAAE,MAAM,GAAG;AAAA,MACpB,CAAC;AACD,qBAAe,KAAK,EAAE,MAAM,MAAM,CAAC;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAe,gBACb,SACA,aACA,QACmB;AACnB,QAAM,gBAAgB,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AACtE,QAAM,iBAAiB,wBAAwB,QAAQ,QAAQ;AAE/D,QAAM,aAAsC;AAAA,IAC1C,UAAU;AAAA,IACV,kBAAkB;AAAA,MAChB,iBAAiB,QAAQ,cAAc;AAAA,IACzC;AAAA,EACF;AAEA,MAAI,QAAQ,gBAAgB,QAAW;AACrC,IAAC,WAAW,kBAAkB,EAA8B,aAAa,IAAI,QAAQ;AAAA,EACvF;AAEA,MAAI,iBAAiB,OAAO,cAAc,YAAY,UAAU;AAC9D,eAAW,mBAAmB,IAAI;AAAA,MAChC,OAAO,CAAC,EAAE,MAAM,cAAc,QAAQ,CAAC;AAAA,IACzC;AAAA,EACF;AAEA,QAAM,WAAW,MAAM;AAAA,IACrB,2DAA2D,WAAW,wBAAwB,MAAM;AAAA,IACpG;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,UAAU;AAAA,IACjC;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAe,sBACb,SACA,aACA,QACmB;AACnB,QAAM,gBAAgB,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AACtE,QAAM,iBAAiB,wBAAwB,QAAQ,QAAQ;AAE/D,QAAM,aAAsC;AAAA,IAC1C,UAAU;AAAA,IACV,kBAAkB;AAAA,MAChB,iBAAiB,QAAQ,cAAc;AAAA,IACzC;AAAA,EACF;AAEA,MAAI,QAAQ,gBAAgB,QAAW;AACrC,IAAC,WAAW,kBAAkB,EAA8B,aAAa,IAAI,QAAQ;AAAA,EACvF;AAEA,MAAI,iBAAiB,OAAO,cAAc,YAAY,UAAU;AAC9D,eAAW,mBAAmB,IAAI;AAAA,MAChC,OAAO,CAAC,EAAE,MAAM,cAAc,QAAQ,CAAC;AAAA,IACzC;AAAA,EACF;AAEA,QAAM,WAAW,MAAM;AAAA,IACrB,2DAA2D,WAAW,sCAAsC,MAAM;AAAA,IAClH;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,UAAU;AAAA,IACjC;AAAA,EACF;AAEA,SAAO;AACT;AAmBA,SAAS,sBAAsB,YAA4B,OAAwC;AACjG,QAAM,YAAY,WAAW,aAAa,CAAC;AAC3C,QAAM,OAAO,WAAW,SAAS,OAAO,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK;AAE7E,MAAI,eAAe;AACnB,MAAI,WAAW,iBAAiB,cAAc;AAC5C,mBAAe;AAAA,EACjB,WAAW,WAAW,iBAAiB,UAAU;AAC/C,mBAAe;AAAA,EACjB;AAEA,SAAO;AAAA,IACL,IAAI,YAAY,KAAK,IAAI,CAAC;AAAA,IAC1B,QAAQ;AAAA,IACR,SAAS,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA,IACrC;AAAA,IACA,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,SAAS;AAAA,UACP,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,QACA,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,IACA,OAAO;AAAA,MACL,eAAe,WAAW,eAAe,oBAAoB;AAAA,MAC7D,mBAAmB,WAAW,eAAe,wBAAwB;AAAA,MACrE,eACG,WAAW,eAAe,oBAAoB,MAC9C,WAAW,eAAe,wBAAwB;AAAA,IACvD;AAAA,EACF;AACF;AAKA,SAAS,yBACP,WACA,WACA,OACA,SACe;AACf,QAAM,YAAY,UAAU,aAAa,CAAC;AAC1C,QAAM,OAAO,WAAW,SAAS,OAAO,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK;AAE7E,QAAM,SAAkC;AAAA,IACtC,OAAO;AAAA,IACP,OAAO,CAAC;AAAA,IACR,eAAe;AAAA,EACjB;AAEA,MAAI,SAAS;AACX,WAAO,OAAO,IAAI,EAAE,MAAM,aAAa,SAAS,KAAK;AAAA,EACvD,WAAW,MAAM;AACf,WAAO,OAAO,IAAI,EAAE,SAAS,KAAK;AAAA,EACpC;AAGA,MAAI,WAAW,cAAc;AAC3B,QAAI,eAAe;AACnB,QAAI,UAAU,iBAAiB,cAAc;AAC3C,qBAAe;AAAA,IACjB,WAAW,UAAU,iBAAiB,UAAU;AAC9C,qBAAe;AAAA,IACjB;AACA,WAAO,eAAe,IAAI;AAAA,EAC5B;AAEA,QAAM,QAAQ;AAAA,IACZ,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,SAAS,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA,IACrC;AAAA,IACA,SAAS,CAAC,MAAM;AAAA,EAClB;AAEA,SAAO,SAAS,KAAK,UAAU,KAAK,CAAC;AAAA;AAAA;AACvC;AAKA,gBAAgB,oBACd,UACA,OACuC;AACvC,QAAM,SAAS,SAAS,MAAM,UAAU;AACxC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACpC;AAEA,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AACb,QAAM,YAAY,YAAY,KAAK,IAAI,CAAC;AACxC,MAAI,UAAU;AAEd,MAAI;AACF,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AAEV,gBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAGhD,YAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,eAAS,MAAM,IAAI,KAAK;AAExB,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,WAAW,QAAQ,GAAG;AAC7B,gBAAM,UAAU,KAAK,MAAM,CAAC;AAC5B,cAAI,QAAQ,KAAK,MAAM,UAAU;AAC/B,kBAAM;AACN;AAAA,UACF;AACA,cAAI;AACF,kBAAM,SAAS,KAAK,MAAM,OAAO;AACjC,kBAAM,YAAY,yBAAyB,QAAQ,WAAW,OAAO,OAAO;AAC5E,gBAAI,WAAW;AACb,oBAAM;AACN,wBAAU;AAAA,YACZ;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM;AAAA,EACR,UAAE;AACA,WAAO,YAAY;AAAA,EACrB;AACF;AAiBA,SAAS,yBAAyB,eAA2D;AAC3F,QAAM,aAAa,cAAc,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,KAAK,CAAC;AAC/E,QAAM,aAAa,cAAc,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,KAAK,CAAC;AAEnF,QAAM,cAAc,WAAW,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE;AAG/D,QAAM,UAAmC;AAAA,IACvC,MAAM;AAAA,IACN,SAAS,eAAe;AAAA,EAC1B;AAGA,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,YAAY,IAAI,WAAW,IAAI,CAAC,WAAW;AAAA,MACjD,IAAI,MAAM,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,MAClC,MAAM;AAAA,MACN,UAAU;AAAA,QACR,MAAM,MAAM;AAAA,QACZ,WAAW,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ,KAAK,UAAU,MAAM,SAAS,CAAC,CAAC;AAAA,MAC7F;AAAA,IACF,EAAE;AAAA,EACJ;AAGA,MAAI,eAAe;AACnB,MAAI,cAAc,gBAAgB,YAAY;AAC5C,mBAAe;AAAA,EACjB,WAAW,cAAc,gBAAgB,YAAY;AACnD,mBAAe;AAAA,EACjB,WAAW,cAAc,aAAa;AACpC,mBAAe,cAAc;AAAA,EAC/B;AAEA,SAAO;AAAA,IACL,IAAI,cAAc,MAAM,YAAY,KAAK,IAAI,CAAC;AAAA,IAC9C,QAAQ;AAAA,IACR,SAAS,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA,IACrC,OAAO,cAAc;AAAA,IACrB,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP;AAAA,QACA,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,IACA,OAAO;AAAA,MACL,eAAe,cAAc,OAAO,gBAAgB;AAAA,MACpD,mBAAmB,cAAc,OAAO,iBAAiB;AAAA,MACzD,eAAe,cAAc,OAAO,gBAAgB,MAAM,cAAc,OAAO,iBAAiB;AAAA,IAClG;AAAA,EACF;AACF;AAcA,SAAS,4BACP,WACA,WACA,WACA,OACA,WACe;AACf,QAAM,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,GAA8B,eAAe,KAAsB;AACtG,QAAM,YAAY;AAAA,IAChB,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,SAAS,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA,IACrC;AAAA,IACA,SAAS,CAAC,MAAM;AAAA,EAClB;AAEA,UAAQ,WAAW;AAAA,IACjB,KAAK,iBAAiB;AAEpB,YAAM,MAAM,UAAU,SAAS;AAC/B,gBAAU,KAAM,MAAM,IAAI,KAAgB;AAC1C,aAAO,QAAQ,EAAE,MAAM,aAAa,SAAS,GAAG;AAChD,aAAO,SAAS,KAAK,UAAU,SAAS,CAAC;AAAA;AAAA;AAAA,IAC3C;AAAA,IAEA,KAAK,uBAAuB;AAE1B,YAAM,eAAe,UAAU,eAAe;AAC9C,YAAM,aAAa,UAAU,OAAO;AAEpC,UAAI,eAAe,MAAM,MAAM,YAAY;AAEzC,cAAM,SAAS,aAAa,IAAI;AAChC,cAAM,WAAW,aAAa,MAAM;AAEpC,kBAAU,MAAM,IAAI,cAAc,UAAU,kBAAkB;AAAA,UAC5D,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,WAAW;AAAA,QACb,CAAC;AACD,kBAAU,mBAAmB,cAAc,UAAU;AAErD,eAAO,QAAQ;AAAA,UACb,YAAY,CAAC;AAAA,YACX,OAAO,cAAc;AAAA,YACrB,IAAI;AAAA,YACJ,MAAM;AAAA,YACN,UAAU,EAAE,MAAM,UAAU,WAAW,GAAG;AAAA,UAC5C,CAAC;AAAA,QACH;AACA,eAAO,SAAS,KAAK,UAAU,SAAS,CAAC;AAAA;AAAA;AAAA,MAC3C;AACA,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,uBAAuB;AAE1B,YAAM,QAAQ,UAAU,OAAO;AAC/B,YAAM,aAAa,UAAU,OAAO;AAEpC,UAAI,QAAQ,MAAM,MAAM,cAAc;AACpC,eAAO,QAAQ,EAAE,SAAS,MAAM,MAAM,EAAY;AAClD,eAAO,SAAS,KAAK,UAAU,SAAS,CAAC;AAAA;AAAA;AAAA,MAC3C;AAEA,UAAI,QAAQ,MAAM,MAAM,oBAAoB;AAE1C,cAAM,cAAc,MAAM,cAAc,KAAe;AACvD,cAAM,OAAO,UAAU,MAAM,IAAI,cAAc,UAAU,gBAAgB;AACzE,YAAI,MAAM;AACR,eAAK,aAAa;AAAA,QACpB;AAEA,eAAO,QAAQ;AAAA,UACb,YAAY,CAAC;AAAA,YACX,OAAO,cAAc;AAAA,YACrB,UAAU,EAAE,WAAW,YAAY;AAAA,UACrC,CAAC;AAAA,QACH;AACA,eAAO,SAAS,KAAK,UAAU,SAAS,CAAC;AAAA;AAAA;AAAA,MAC3C;AACA,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,iBAAiB;AAEpB,YAAM,QAAQ,UAAU,OAAO;AAC/B,YAAM,aAAa,QAAQ,aAAa;AAExC,UAAI,eAAe,YAAY;AAC7B,eAAO,gBAAgB;AAAA,MACzB,WAAW,eAAe,YAAY;AACpC,eAAO,gBAAgB;AAAA,MACzB,OAAO;AACL,eAAO,gBAAgB,cAAc;AAAA,MACvC;AACA,aAAO,QAAQ,CAAC;AAChB,aAAO,SAAS,KAAK,UAAU,SAAS,CAAC;AAAA;AAAA;AAAA,IAC3C;AAAA,IAEA,KAAK,gBAAgB;AAEnB,aAAO;AAAA,IACT;AAAA,IAEA;AACE,aAAO;AAAA,EACX;AACF;AAKA,gBAAgB,uBACd,UACA,OACuC;AACvC,QAAM,SAAS,SAAS,MAAM,UAAU;AACxC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACpC;AAEA,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AACb,MAAI,YAAY,YAAY,KAAK,IAAI,CAAC;AAGtC,QAAM,YAAgC;AAAA,IACpC,kBAAkB;AAAA,IAClB,OAAO,oBAAI,IAAI;AAAA,EACjB;AAEA,MAAI;AACF,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AAEV,gBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAGhD,YAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,eAAS,MAAM,IAAI,KAAK;AAExB,UAAI,YAAY;AAChB,UAAI,YAAY;AAEhB,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,sBAAY,KAAK,MAAM,CAAC,EAAE,KAAK;AAAA,QACjC,WAAW,KAAK,WAAW,QAAQ,GAAG;AACpC,sBAAY,KAAK,MAAM,CAAC;AAAA,QAC1B,WAAW,SAAS,MAAM,aAAa,WAAW;AAEhD,cAAI;AACF,kBAAM,SAAS,KAAK,MAAM,SAAS;AACnC,kBAAM,YAAY,4BAA4B,WAAW,QAAQ,WAAW,OAAO,SAAS;AAC5F,gBAAI,WAAW;AACb,oBAAM;AAAA,YACR;AAAA,UACF,QAAQ;AAAA,UAER;AACA,sBAAY;AACZ,sBAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF,UAAE;AACA,WAAO,YAAY;AAAA,EACrB;AACF;AAKA,gBAAgB,iBACd,UACuC;AACvC,QAAM,SAAS,SAAS,MAAM,UAAU;AACxC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACpC;AAEA,QAAM,UAAU,IAAI,YAAY;AAEhC,MAAI;AACF,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,YAAM,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAAA,IAC9C;AAAA,EACF,UAAE;AACA,WAAO,YAAY;AAAA,EACrB;AACF;AAKA,SAAS,oBACP,gBAC8C;AAC9C,QAAM,CAAC,UAAU,KAAK,IAAI,eAAe,MAAM,GAAG;AAClD,MAAI,CAAC,YAAY,CAAC,MAAO,QAAO;AAGhC,QAAM,iBAA6B,CAAC,UAAU,aAAa,UAAU,OAAO,YAAY,OAAO;AAC/F,MAAI,CAAC,eAAe,SAAS,QAAoB,EAAG,QAAO;AAE3D,SAAO,EAAE,UAAgC,MAAM;AACjD;AAMA,SAAS,qBACP,WAC8C;AAE9C,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO,cAAc,SAAS;AAAA,EAChC;AAGA,MAAI,UAAU,WAAW,SAAS,GAAG;AACnC,WAAO,EAAE,UAAU,aAAa,OAAO,UAAU;AAAA,EACnD;AAGA,MACE,UAAU,WAAW,MAAM,KAC3B,UAAU,WAAW,KAAK,KAC1B,UAAU,WAAW,KAAK,KAC1B,UAAU,WAAW,UAAU,KAC/B,UAAU,WAAW,OAAO,KAC5B,UAAU,WAAW,QAAQ,KAC7B,UAAU,WAAW,SAAS,KAC9B,UAAU,WAAW,MAAM,GAC3B;AACA,WAAO,EAAE,UAAU,UAAU,OAAO,UAAU;AAAA,EAChD;AAGA,MAAI,UAAU,WAAW,SAAS,KAAK,UAAU,WAAW,OAAO,GAAG;AACpE,WAAO,EAAE,UAAU,UAAU,OAAO,UAAU;AAAA,EAChD;AAGA,MAAI,UAAU,WAAW,OAAO,GAAG;AACjC,WAAO,EAAE,UAAU,OAAO,OAAO,UAAU;AAAA,EAC7C;AAGA,MAAI,UAAU,WAAW,WAAW,GAAG;AACrC,WAAO,EAAE,UAAU,YAAY,OAAO,UAAU;AAAA,EAClD;AAGA,MAAI,UAAU,SAAS,GAAG,GAAG;AAC3B,UAAM,CAAC,UAAU,KAAK,IAAI,UAAU,MAAM,GAAG;AAC7C,UAAM,iBAA6B,CAAC,UAAU,aAAa,UAAU,OAAO,YAAY,OAAO;AAC/F,QAAI,YAAY,SAAS,eAAe,SAAS,QAAoB,GAAG;AACtE,aAAO,EAAE,UAAgC,MAAM;AAAA,IACjD;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAsB,WAAW,SAAsB,CAAC,GAAyB;AAC/E,QAAM,OAAO,OAAO,QAAQ;AAC5B,QAAM,OAAO,OAAO,QAAQ;AAC5B,QAAM,UAAU,OAAO,WAAW;AAGlC,QAAM,QAAQ,IAAI,WAAW,EAAE,QAAQ,OAAO,OAAO,CAAC;AAEtD,QAAM,MAAM,CAAC,QAAgB;AAC3B,QAAI,QAAS,SAAQ,IAAI,gBAAgB,GAAG,EAAE;AAAA,EAChD;AAEA,QAAM,SAAc,kBAAa,OAAO,KAAK,QAAQ;AAEnD,QAAI,UAAU,+BAA+B,GAAG;AAChD,QAAI,UAAU,gCAAgC,eAAe;AAC7D,QAAI,UAAU,gCAAgC,6BAA6B;AAE3E,QAAI,IAAI,WAAW,WAAW;AAC5B,UAAI,UAAU,GAAG;AACjB,UAAI,IAAI;AACR;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,UAAU,CAAC,IAAI,KAAK,SAAS,mBAAmB,GAAG;AAEpE,UAAI,IAAI,WAAW,SAAS,IAAI,KAAK,SAAS,SAAS,GAAG;AACxD,YAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,YAAI;AAAA,UACF,KAAK,UAAU;AAAA,YACb,QAAQ;AAAA,YACR,MAAM;AAAA,cACJ,EAAE,IAAI,mBAAmB,QAAQ,SAAS,UAAU,aAAa;AAAA,cACjE,EAAE,IAAI,mBAAmB,QAAQ,SAAS,UAAU,aAAa;AAAA,cACjE,EAAE,IAAI,sBAAsB,QAAQ,SAAS,UAAU,aAAa;AAAA,YACtE;AAAA,UACF,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAEA,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI,IAAI,KAAK,UAAU,EAAE,OAAO,YAAY,CAAC,CAAC;AAC9C;AAAA,IACF;AAGA,QAAI,OAAO;AACX,qBAAiB,SAAS,KAAK;AAC7B,cAAQ;AAAA,IACV;AAEA,QAAI;AACJ,QAAI;AACF,gBAAU,KAAK,MAAM,IAAI;AAAA,IAC3B,QAAQ;AACN,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI,IAAI,KAAK,UAAU,EAAE,OAAO,eAAe,CAAC,CAAC;AACjD;AAAA,IACF;AAEA,UAAM,cAAc,QAAQ,WAAW;AAGvC,UAAM,iBAAiB,QAAQ;AAC/B,QAAI,cAA2D;AAC/D,QAAI,cAAsB;AAC1B,QAAI,iBAA2B;AAG/B,QAAI,eAAe,WAAW,aAAa,GAAG;AAE5C,UAAI,eAAe,SAAS,OAAO,GAAG;AACpC,sBAAc;AAAA,MAChB,WAAW,eAAe,SAAS,UAAU,GAAG;AAC9C,sBAAc;AAAA,MAChB;AAAA,IACF,OAAO;AAEL,oBAAc;AACd,YAAM,WAAW,qBAAqB,cAAc;AACpD,UAAI,UAAU;AACZ,yBAAiB,SAAS;AAC1B,sBAAc,SAAS;AACvB,YAAI,sBAAsB,cAAc,WAAM,cAAc,IAAI,WAAW,EAAE;AAAA,MAC/E,OAAO;AACL,YAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,YAAI,IAAI,KAAK,UAAU,EAAE,OAAO,kBAAkB,cAAc,GAAG,CAAC,CAAC;AACrE;AAAA,MACF;AAAA,IACF;AAEA,QAAI,+BAA+B,cAAc,WAAW,WAAW,aAAa,WAAW,GAAG;AAGlG,UAAM,aAAa,kBAAkB,QAAQ,QAAQ;AACrD,UAAM,WAAW,cAAc,UAAU;AACzC,UAAM,aAAa,uBAAuB,YAAY,QAAQ;AAE9D,QAAI,kBAAkB,QAAQ,iBAAiB,WAAW,QAAQ,CAAC,CAAC,GAAG;AAGvE,QAAI,gBAAgB,eAAe;AAEjC,YAAM,OAAO,MAAM,QAAQ,IAAI,QAAQ;AAEvC,UAAI,QAAQ,KAAK,gBAAgB;AAC/B,cAAM,SAAS,oBAAoB,KAAK,cAAc;AACtD,YAAI,QAAQ;AACV,2BAAiB,OAAO;AACxB,wBAAc,OAAO;AACrB,cAAI,uBAAuB,KAAK,cAAc,EAAE;AAAA,QAClD,OAAO;AAEL,gBAAM,eAAe,gBAAgB,QAAQ;AAC7C,2BAAiB,aAAa;AAC9B,wBAAc,aAAa;AAAA,QAC7B;AAAA,MACF,OAAO;AAEL,cAAM,eAAe,gBAAgB,QAAQ;AAC7C,yBAAiB,aAAa;AAC9B,sBAAc,aAAa;AAAA,MAC7B;AAGA,UAAI,gBAAgB,QAAQ;AAE1B,cAAM,cAA0B,CAAC,iBAAiB,mBAAmB,eAAe,oBAAoB;AACxG,YAAI,YAAY,SAAS,QAAQ,GAAG;AAClC,wBAAc;AACd,2BAAiB;AAAA,QACnB;AAAA,MACF,WAAW,gBAAgB,WAAW;AAEpC,cAAM,eAAe,QAAQ,IAAI,0BAA0B,KAAK;AAChE,sBAAc;AACd,yBAAiB;AAAA,MACnB;AAAA,IACF;AAEA,QAAI,eAAe,cAAc,IAAI,WAAW,EAAE;AAGlD,UAAM,YAAY,kBAAkB,cAAc,GAAG,aAAa,GAAG,eAAe,YAAY,CAAC;AACjG,UAAM,SAAS,QAAQ,IAAI,SAAS;AAEpC,QAAI,CAAC,QAAQ;AACX,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI,IAAI,KAAK,UAAU,EAAE,OAAO,WAAW,SAAS,wBAAwB,CAAC,CAAC;AAC9E;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,IAAI;AAG3B,UAAM,cAAc,IAAI,QAAQ,gBAAgB;AAGhD,QAAI,aAAa;AACf,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,WAAO,GAAG,SAAS,MAAM;AACzB,WAAO,OAAO,MAAM,MAAM,MAAM;AAC9B,cAAQ,IAAI,wCAAwC,IAAI,IAAI,IAAI,EAAE;AAClE,cAAQ,IAAI,gEAAgE;AAC5E,cAAQ,IAAI,uCAAuC;AACnD,cAAQ,IAAI,6BAAwB;AACpC,cAAQ,MAAM;AAAA,IAChB,CAAC;AAAA,EACH,CAAC;AACH;AAKA,eAAe,uBACb,KACA,SACA,gBACA,aACA,QACA,OACA,YACA,UACA,YACA,aACA,WACA,KACA,aACe;AACf,MAAI;AAEJ,MAAI;AACF,YAAQ,gBAAgB;AAAA,MACtB,KAAK;AACH,2BAAmB,MAAM,yBAAyB,SAAS,aAAa,QAAQ,WAAW;AAC3F;AAAA,MACF,KAAK;AACH,2BAAmB,MAAM,sBAAsB,SAAS,aAAa,MAAM;AAC3E;AAAA,MACF,KAAK;AACH,2BAAmB,MAAM,mBAAmB,SAAS,aAAa,MAAM;AACxE;AAAA,MACF,KAAK;AACH,2BAAmB,MAAM,wBAAwB,SAAS,aAAa,MAAM;AAC7E;AAAA,MACF;AACE,2BAAmB,MAAM,sBAAsB,SAAS,aAAa,MAAM;AAAA,IAC/E;AAEA,QAAI,CAAC,iBAAiB,IAAI;AACxB,YAAM,YAAY,MAAM,iBAAiB,KAAK;AAC9C,UAAI,UAAU,iBAAiB,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC7E,UAAI,IAAI,KAAK,UAAU,SAAS,CAAC;AACjC;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,WAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAChE,QAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,mBAAmB,QAAQ,GAAG,CAAC,CAAC;AAChE;AAAA,EACF;AAGA,MAAI,UAAU,KAAK;AAAA,IACjB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB,CAAC;AAED,MAAI;AAEF,YAAQ,gBAAgB;AAAA,MACtB,KAAK;AAEH,yBAAiB,SAAS,uBAAuB,kBAAkB,WAAW,GAAG;AAC/E,cAAI,MAAM,KAAK;AAAA,QACjB;AACA;AAAA,MACF,KAAK;AAEH,yBAAiB,SAAS,oBAAoB,kBAAkB,WAAW,GAAG;AAC5E,cAAI,MAAM,KAAK;AAAA,QACjB;AACA;AAAA,MACF;AAEE,yBAAiB,SAAS,iBAAiB,gBAAgB,GAAG;AAC5D,cAAI,MAAM,KAAK;AAAA,QACjB;AAAA,IACJ;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,oBAAoB,GAAG,EAAE;AAAA,EAC/B;AAEA,QAAM,aAAa,KAAK,IAAI,IAAI;AAGhC,QACG,IAAI;AAAA,IACH,QAAQ,WAAW,MAAM,GAAG,GAAG;AAAA,IAC/B;AAAA,IACA,OAAO,GAAG,cAAc,IAAI,WAAW;AAAA,EACzC,CAAC,EACA,KAAK,CAAC,cAAc;AACnB,QAAI,0BAA0B,UAAU,cAAc,UAAU,KAAK,EAAE;AAAA,EACzE,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,QAAI,yBAAyB,GAAG,EAAE;AAAA,EACpC,CAAC;AAEH,MAAI,IAAI;AACV;AAKA,eAAe,0BACb,KACA,SACA,gBACA,aACA,QACA,OACA,YACA,UACA,YACA,aACA,WACA,KACA,aACe;AACf,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,YAAQ,gBAAgB;AAAA,MACtB,KAAK,aAAa;AAChB,2BAAmB,MAAM,mBAAmB,SAAS,aAAa,QAAQ,WAAW;AACrF,cAAM,UAAW,MAAM,iBAAiB,KAAK;AAE7C,YAAI,CAAC,iBAAiB,IAAI;AACxB,cAAI,UAAU,iBAAiB,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC7E,cAAI,IAAI,KAAK,UAAU,OAAO,CAAC;AAC/B;AAAA,QACF;AAGA,uBAAe,yBAAyB,OAAO;AAC/C;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AACb,2BAAmB,MAAM,gBAAgB,SAAS,aAAa,MAAM;AACrE,cAAM,UAAW,MAAM,iBAAiB,KAAK;AAE7C,YAAI,CAAC,iBAAiB,IAAI;AACxB,cAAI,UAAU,iBAAiB,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC7E,cAAI,IAAI,KAAK,UAAU,OAAO,CAAC;AAC/B;AAAA,QACF;AAGA,uBAAe,sBAAsB,SAAS,WAAW;AACzD;AAAA,MACF;AAAA,MACA,KAAK,OAAO;AACV,2BAAmB,MAAM,aAAa,SAAS,aAAa,MAAM;AAClE,uBAAgB,MAAM,iBAAiB,KAAK;AAE5C,YAAI,CAAC,iBAAiB,IAAI;AACxB,cAAI,UAAU,iBAAiB,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC7E,cAAI,IAAI,KAAK,UAAU,YAAY,CAAC;AACpC;AAAA,QACF;AACA;AAAA,MACF;AAAA,MACA,KAAK,YAAY;AACf,2BAAmB,MAAM,kBAAkB,SAAS,aAAa,MAAM;AACvE,uBAAgB,MAAM,iBAAiB,KAAK;AAE5C,YAAI,CAAC,iBAAiB,IAAI;AACxB,cAAI,UAAU,iBAAiB,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC7E,cAAI,IAAI,KAAK,UAAU,YAAY,CAAC;AACpC;AAAA,QACF;AACA;AAAA,MACF;AAAA,MACA,SAAS;AACP,2BAAmB,MAAM,gBAAgB,SAAS,aAAa,MAAM;AACrE,uBAAgB,MAAM,iBAAiB,KAAK;AAE5C,YAAI,CAAC,iBAAiB,IAAI;AACxB,cAAI,UAAU,iBAAiB,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC7E,cAAI,IAAI,KAAK,UAAU,YAAY,CAAC;AACpC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,WAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAChE,QAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,mBAAmB,QAAQ,GAAG,CAAC,CAAC;AAChE;AAAA,EACF;AAEA,QAAM,aAAa,KAAK,IAAI,IAAI;AAGhC,MAAI;AACF,UAAM,YAAY,MAAM,MAAM,IAAI;AAAA,MAChC,QAAQ,WAAW,MAAM,GAAG,GAAG;AAAA,MAC/B;AAAA,MACA,OAAO,GAAG,cAAc,IAAI,WAAW;AAAA,IACzC,CAAC;AAGD,iBAAa,aAAa,IAAI;AAAA,MAC5B,OAAO,UAAU;AAAA,MACjB,UAAU,GAAG,cAAc,IAAI,WAAW;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IACR;AAEA,QAAI,gBAAgB,UAAU,cAAc,UAAU,KAAK,EAAE;AAAA,EAC/D,SAAS,KAAK;AACZ,QAAI,yBAAyB,GAAG,EAAE;AAAA,EACpC;AAGA,MAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,MAAI,IAAI,KAAK,UAAU,YAAY,CAAC;AACtC;;;AW1gDA,SAAS,YAAkB;AACzB,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAgCb;AACD;AAEA,eAAe,OAAsB;AACnC,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAGjC,MAAI,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,QAAQ,GAAG;AAClD,cAAU;AACV,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,UAAU;AAEd,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAElB,QAAI,QAAQ,YAAY,KAAK,IAAI,CAAC,GAAG;AACnC,aAAO,SAAS,KAAK,IAAI,CAAC,GAAI,EAAE;AAChC,UAAI,MAAM,IAAI,KAAK,OAAO,KAAK,OAAO,OAAO;AAC3C,gBAAQ,MAAM,4BAA4B;AAC1C,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF,WAAW,QAAQ,YAAY,KAAK,IAAI,CAAC,GAAG;AAC1C,aAAO,KAAK,IAAI,CAAC;AACjB;AAAA,IACF,WAAW,QAAQ,QAAQ,QAAQ,aAAa;AAC9C,gBAAU;AAAA,IACZ;AAAA,EACF;AAGA,QAAM,kBAAkB,CAAC,CAAC,QAAQ,IAAI,mBAAmB;AACzD,QAAM,eAAe,CAAC,CAAC,QAAQ,IAAI,gBAAgB;AACnD,QAAM,eAAe,CAAC,CAAC,QAAQ,IAAI,gBAAgB;AACnD,QAAM,YAAY,CAAC,CAAC,QAAQ,IAAI,aAAa;AAC7C,QAAM,iBAAiB,CAAC,CAAC,QAAQ,IAAI,kBAAkB;AAEvD,MAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,aAAa,CAAC,gBAAgB;AACvF,YAAQ,MAAM,gDAAgD;AAC9D,YAAQ,MAAM,oFAAoF;AAClG,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,sQAA+C;AAC3D,UAAQ,IAAI,yDAA+C;AAC3D,UAAQ,IAAI,yDAA+C;AAC3D,UAAQ,IAAI,sQAA+C;AAC3D,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,cAAc;AAC1B,MAAI,gBAAiB,SAAQ,IAAI,sBAAiB;AAClD,MAAI,aAAc,SAAQ,IAAI,mBAAc;AAC5C,MAAI,aAAc,SAAQ,IAAI,0BAAqB;AACnD,MAAI,UAAW,SAAQ,IAAI,uBAAkB;AAC7C,MAAI,eAAgB,SAAQ,IAAI,qBAAgB;AAChD,UAAQ,IAAI,EAAE;AAEd,MAAI;AACF,UAAM,WAAW,EAAE,MAAM,MAAM,QAAQ,CAAC;AAExC,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,4CAA4C;AACxD,YAAQ,IAAI,wCAAwC,IAAI,IAAI,IAAI,EAAE;AAClE,YAAQ,IAAI,qCAAqC,IAAI,IAAI,IAAI,EAAE;AAC/D,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,uDAAuD;AACnE,YAAQ,IAAI,EAAE;AAAA,EAChB,SAAS,KAAK;AACZ,YAAQ,MAAM,0BAA0B,GAAG;AAC3C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,KAAK;","names":["crypto","Database","runId"]}
|
|
1
|
+
{"version":3,"sources":["../src/proxy.ts","../src/storage/store.ts","../node_modules/nanoid/index.js","../node_modules/nanoid/url-alphabet/index.js","../src/storage/schema.ts","../src/routing/inference.ts","../src/routing/engine.ts","../src/learning/outcomes.ts","../src/learning/savings.ts","../src/learning/patterns.ts","../src/relay.ts","../src/cli.ts"],"sourcesContent":["/**\n * RelayPlane L2/L3 Proxy Server\n *\n * An OpenAI-compatible HTTP proxy that intelligently routes requests\n * to the optimal model using @relayplane/core.\n *\n * Supports:\n * - Streaming (SSE) for both OpenAI and Anthropic\n * - Non-streaming requests\n * - Automatic format conversion (Anthropic → OpenAI format)\n * - Tool/function calling (planned)\n *\n * @packageDocumentation\n */\n\nimport * as http from 'node:http';\nimport { RelayPlane } from './relay.js';\nimport { inferTaskType, getInferenceConfidence } from './routing/inference.js';\nimport type { Provider, TaskType } from './types.js';\n\n/**\n * Provider endpoint configuration\n */\nexport interface ProviderEndpoint {\n baseUrl: string;\n apiKeyEnv: string;\n}\n\n/**\n * Default provider endpoints\n */\nexport const DEFAULT_ENDPOINTS: Record<string, ProviderEndpoint> = {\n anthropic: {\n baseUrl: 'https://api.anthropic.com/v1',\n apiKeyEnv: 'ANTHROPIC_API_KEY',\n },\n openai: {\n baseUrl: 'https://api.openai.com/v1',\n apiKeyEnv: 'OPENAI_API_KEY',\n },\n google: {\n baseUrl: 'https://generativelanguage.googleapis.com/v1beta',\n apiKeyEnv: 'GEMINI_API_KEY',\n },\n xai: {\n baseUrl: 'https://api.x.ai/v1',\n apiKeyEnv: 'XAI_API_KEY',\n },\n moonshot: {\n baseUrl: 'https://api.moonshot.cn/v1',\n apiKeyEnv: 'MOONSHOT_API_KEY',\n },\n};\n\n/**\n * Model to provider/model mapping\n */\nexport const MODEL_MAPPING: Record<string, { provider: Provider; model: string }> = {\n // Anthropic models (using correct API model IDs)\n 'claude-opus-4-5': { provider: 'anthropic', model: 'claude-opus-4-5-20250514' },\n 'claude-sonnet-4': { provider: 'anthropic', model: 'claude-sonnet-4-20250514' },\n 'claude-3-5-sonnet': { provider: 'anthropic', model: 'claude-3-5-sonnet-20241022' },\n 'claude-3-5-haiku': { provider: 'anthropic', model: 'claude-3-5-haiku-20241022' },\n haiku: { provider: 'anthropic', model: 'claude-3-5-haiku-20241022' },\n sonnet: { provider: 'anthropic', model: 'claude-3-5-sonnet-20241022' },\n opus: { provider: 'anthropic', model: 'claude-3-opus-20240229' },\n // OpenAI models\n 'gpt-4o': { provider: 'openai', model: 'gpt-4o' },\n 'gpt-4o-mini': { provider: 'openai', model: 'gpt-4o-mini' },\n 'gpt-4.1': { provider: 'openai', model: 'gpt-4.1' },\n};\n\n/**\n * Default routing based on task type\n * Uses Haiku 3.5 for cost optimization, upgrades based on learned rules\n */\nconst DEFAULT_ROUTING: Record<TaskType, { provider: Provider; model: string }> = {\n code_generation: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n code_review: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n summarization: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n analysis: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n creative_writing: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n data_extraction: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n translation: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n question_answering: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n general: { provider: 'anthropic', model: 'claude-3-5-haiku-latest' },\n};\n\n/**\n * Proxy server configuration\n */\nexport interface ProxyConfig {\n port?: number;\n host?: string;\n dbPath?: string;\n verbose?: boolean;\n}\n\n/**\n * Request body structure\n */\ninterface ChatRequest {\n model: string;\n messages: Array<{ role: string; content: string | unknown }>;\n stream?: boolean;\n max_tokens?: number;\n temperature?: number;\n tools?: unknown[];\n tool_choice?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * Extract text content from messages for routing analysis\n */\nfunction extractPromptText(messages: ChatRequest['messages']): string {\n return messages\n .map((msg) => {\n if (typeof msg.content === 'string') return msg.content;\n if (Array.isArray(msg.content)) {\n return msg.content\n .map((c: unknown) => {\n const part = c as { type?: string; text?: string };\n return part.type === 'text' ? (part.text ?? '') : '';\n })\n .join(' ');\n }\n return '';\n })\n .join('\\n');\n}\n\n/**\n * Forward non-streaming request to Anthropic API\n */\nasync function forwardToAnthropic(\n request: ChatRequest,\n targetModel: string,\n apiKey: string,\n betaHeaders?: string\n): Promise<Response> {\n const anthropicBody = buildAnthropicBody(request, targetModel, false);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n };\n\n // Pass through beta headers (prompt caching, extended thinking, etc.)\n if (betaHeaders) {\n headers['anthropic-beta'] = betaHeaders;\n }\n\n const response = await fetch('https://api.anthropic.com/v1/messages', {\n method: 'POST',\n headers,\n body: JSON.stringify(anthropicBody),\n });\n\n return response;\n}\n\n/**\n * Forward streaming request to Anthropic API\n */\nasync function forwardToAnthropicStream(\n request: ChatRequest,\n targetModel: string,\n apiKey: string,\n betaHeaders?: string\n): Promise<Response> {\n const anthropicBody = buildAnthropicBody(request, targetModel, true);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n };\n\n if (betaHeaders) {\n headers['anthropic-beta'] = betaHeaders;\n }\n\n const response = await fetch('https://api.anthropic.com/v1/messages', {\n method: 'POST',\n headers,\n body: JSON.stringify(anthropicBody),\n });\n\n return response;\n}\n\n/**\n * OpenAI message structure for type safety\n */\ninterface OpenAIMessage {\n role: string;\n content?: string | unknown[] | null;\n tool_calls?: Array<{\n id: string;\n type: string;\n function: { name: string; arguments: string };\n }>;\n tool_call_id?: string;\n name?: string;\n}\n\n/**\n * Convert OpenAI messages array to Anthropic format\n * Handles: user, assistant, tool_calls, tool results\n */\nfunction convertMessagesToAnthropic(messages: Array<{ role: string; content: string | unknown; [key: string]: unknown }>): unknown[] {\n const result: unknown[] = [];\n\n for (const msg of messages) {\n const m = msg as OpenAIMessage;\n\n // Skip system messages (handled separately)\n if (m.role === 'system') continue;\n\n // Tool result message → Anthropic user message with tool_result content\n if (m.role === 'tool') {\n result.push({\n role: 'user',\n content: [\n {\n type: 'tool_result',\n tool_use_id: m.tool_call_id,\n content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content),\n },\n ],\n });\n continue;\n }\n\n // Assistant message with tool_calls → Anthropic assistant with tool_use content\n if (m.role === 'assistant' && m.tool_calls && m.tool_calls.length > 0) {\n const content: unknown[] = [];\n\n // Add text content if present\n if (m.content && typeof m.content === 'string') {\n content.push({ type: 'text', text: m.content });\n }\n\n // Add tool_use blocks\n for (const tc of m.tool_calls) {\n content.push({\n type: 'tool_use',\n id: tc.id,\n name: tc.function.name,\n input: JSON.parse(tc.function.arguments || '{}'),\n });\n }\n\n result.push({ role: 'assistant', content });\n continue;\n }\n\n // Regular user/assistant message\n result.push({\n role: m.role === 'assistant' ? 'assistant' : 'user',\n content: m.content,\n });\n }\n\n return result;\n}\n\n/**\n * Build Anthropic request body from OpenAI format\n */\nfunction buildAnthropicBody(\n request: ChatRequest,\n targetModel: string,\n stream: boolean\n): Record<string, unknown> {\n // Convert OpenAI messages to Anthropic format\n const anthropicMessages = convertMessagesToAnthropic(request.messages);\n\n const systemMessage = request.messages.find((m) => m.role === 'system');\n\n const anthropicBody: Record<string, unknown> = {\n model: targetModel,\n messages: anthropicMessages,\n max_tokens: request.max_tokens ?? 4096,\n stream,\n };\n\n if (systemMessage) {\n anthropicBody['system'] = systemMessage.content;\n }\n\n if (request.temperature !== undefined) {\n anthropicBody['temperature'] = request.temperature;\n }\n\n // Convert OpenAI tools format to Anthropic tools format\n if (request.tools && Array.isArray(request.tools)) {\n anthropicBody['tools'] = convertToolsToAnthropic(request.tools);\n }\n\n // Convert tool_choice\n if (request.tool_choice) {\n anthropicBody['tool_choice'] = convertToolChoiceToAnthropic(request.tool_choice);\n }\n\n return anthropicBody;\n}\n\n/**\n * Convert OpenAI tools format to Anthropic format\n * OpenAI: { type: \"function\", function: { name, description, parameters } }\n * Anthropic: { name, description, input_schema }\n */\nfunction convertToolsToAnthropic(tools: unknown[]): unknown[] {\n return tools.map((tool: unknown) => {\n const t = tool as { type?: string; function?: { name?: string; description?: string; parameters?: unknown } };\n if (t.type === 'function' && t.function) {\n return {\n name: t.function.name,\n description: t.function.description,\n input_schema: t.function.parameters || { type: 'object', properties: {} },\n };\n }\n // Already in Anthropic format or unknown\n return tool;\n });\n}\n\n/**\n * Convert OpenAI tool_choice to Anthropic format\n */\nfunction convertToolChoiceToAnthropic(toolChoice: unknown): unknown {\n if (toolChoice === 'auto') return { type: 'auto' };\n if (toolChoice === 'none') return { type: 'none' };\n if (toolChoice === 'required') return { type: 'any' };\n \n // Specific tool: { type: \"function\", function: { name: \"xxx\" } }\n const tc = toolChoice as { type?: string; function?: { name?: string } };\n if (tc.type === 'function' && tc.function?.name) {\n return { type: 'tool', name: tc.function.name };\n }\n \n return toolChoice;\n}\n\n/**\n * Forward non-streaming request to OpenAI API\n */\nasync function forwardToOpenAI(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const openaiBody = {\n ...request,\n model: targetModel,\n stream: false,\n };\n\n const response = await fetch('https://api.openai.com/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(openaiBody),\n });\n\n return response;\n}\n\n/**\n * Forward streaming request to OpenAI API\n */\nasync function forwardToOpenAIStream(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const openaiBody = {\n ...request,\n model: targetModel,\n stream: true,\n };\n\n const response = await fetch('https://api.openai.com/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(openaiBody),\n });\n\n return response;\n}\n\n/**\n * Forward non-streaming request to xAI API (OpenAI-compatible)\n */\nasync function forwardToXAI(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const xaiBody = {\n ...request,\n model: targetModel,\n stream: false,\n };\n\n const response = await fetch('https://api.x.ai/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(xaiBody),\n });\n\n return response;\n}\n\n/**\n * Forward streaming request to xAI API (OpenAI-compatible)\n */\nasync function forwardToXAIStream(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const xaiBody = {\n ...request,\n model: targetModel,\n stream: true,\n };\n\n const response = await fetch('https://api.x.ai/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(xaiBody),\n });\n\n return response;\n}\n\n/**\n * Forward non-streaming request to Moonshot API (OpenAI-compatible)\n */\nasync function forwardToMoonshot(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const moonshotBody = {\n ...request,\n model: targetModel,\n stream: false,\n };\n\n const response = await fetch('https://api.moonshot.cn/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(moonshotBody),\n });\n\n return response;\n}\n\n/**\n * Forward streaming request to Moonshot API (OpenAI-compatible)\n */\nasync function forwardToMoonshotStream(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const moonshotBody = {\n ...request,\n model: targetModel,\n stream: true,\n };\n\n const response = await fetch('https://api.moonshot.cn/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(moonshotBody),\n });\n\n return response;\n}\n\n/**\n * Convert OpenAI messages to Gemini format\n */\nfunction convertMessagesToGemini(messages: ChatRequest['messages']): unknown[] {\n const geminiContents: unknown[] = [];\n \n for (const msg of messages) {\n // Skip system messages (handled separately via systemInstruction)\n if (msg.role === 'system') continue;\n \n const role = msg.role === 'assistant' ? 'model' : 'user';\n \n if (typeof msg.content === 'string') {\n geminiContents.push({\n role,\n parts: [{ text: msg.content }],\n });\n } else if (Array.isArray(msg.content)) {\n // Handle multimodal content\n const parts = msg.content.map((part: unknown) => {\n const p = part as { type?: string; text?: string; image_url?: { url?: string } };\n if (p.type === 'text') {\n return { text: p.text };\n }\n if (p.type === 'image_url' && p.image_url?.url) {\n // Handle base64 images\n const url = p.image_url.url;\n if (url.startsWith('data:')) {\n const match = url.match(/^data:([^;]+);base64,(.+)$/);\n if (match) {\n return {\n inline_data: {\n mime_type: match[1],\n data: match[2],\n },\n };\n }\n }\n // URL-based images not directly supported, return as text\n return { text: `[Image: ${url}]` };\n }\n return { text: '' };\n });\n geminiContents.push({ role, parts });\n }\n }\n \n return geminiContents;\n}\n\n/**\n * Forward non-streaming request to Gemini API\n */\nasync function forwardToGemini(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const systemMessage = request.messages.find((m) => m.role === 'system');\n const geminiContents = convertMessagesToGemini(request.messages);\n \n const geminiBody: Record<string, unknown> = {\n contents: geminiContents,\n generationConfig: {\n maxOutputTokens: request.max_tokens ?? 4096,\n },\n };\n \n if (request.temperature !== undefined) {\n (geminiBody['generationConfig'] as Record<string, unknown>)['temperature'] = request.temperature;\n }\n \n if (systemMessage && typeof systemMessage.content === 'string') {\n geminiBody['systemInstruction'] = {\n parts: [{ text: systemMessage.content }],\n };\n }\n\n const response = await fetch(\n `https://generativelanguage.googleapis.com/v1beta/models/${targetModel}:generateContent?key=${apiKey}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(geminiBody),\n }\n );\n\n return response;\n}\n\n/**\n * Forward streaming request to Gemini API\n */\nasync function forwardToGeminiStream(\n request: ChatRequest,\n targetModel: string,\n apiKey: string\n): Promise<Response> {\n const systemMessage = request.messages.find((m) => m.role === 'system');\n const geminiContents = convertMessagesToGemini(request.messages);\n \n const geminiBody: Record<string, unknown> = {\n contents: geminiContents,\n generationConfig: {\n maxOutputTokens: request.max_tokens ?? 4096,\n },\n };\n \n if (request.temperature !== undefined) {\n (geminiBody['generationConfig'] as Record<string, unknown>)['temperature'] = request.temperature;\n }\n \n if (systemMessage && typeof systemMessage.content === 'string') {\n geminiBody['systemInstruction'] = {\n parts: [{ text: systemMessage.content }],\n };\n }\n\n const response = await fetch(\n `https://generativelanguage.googleapis.com/v1beta/models/${targetModel}:streamGenerateContent?alt=sse&key=${apiKey}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(geminiBody),\n }\n );\n\n return response;\n}\n\n/**\n * Gemini API response structure\n */\ninterface GeminiResponse {\n candidates?: Array<{\n content?: { parts?: Array<{ text?: string }> };\n finishReason?: string;\n }>;\n usageMetadata?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n };\n}\n\n/**\n * Convert Gemini response to OpenAI format\n */\nfunction convertGeminiResponse(geminiData: GeminiResponse, model: string): Record<string, unknown> {\n const candidate = geminiData.candidates?.[0];\n const text = candidate?.content?.parts?.map((p) => p.text ?? '').join('') ?? '';\n \n let finishReason = 'stop';\n if (candidate?.finishReason === 'MAX_TOKENS') {\n finishReason = 'length';\n } else if (candidate?.finishReason === 'SAFETY') {\n finishReason = 'content_filter';\n }\n\n return {\n id: `chatcmpl-${Date.now()}`,\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n message: {\n role: 'assistant',\n content: text,\n },\n finish_reason: finishReason,\n },\n ],\n usage: {\n prompt_tokens: geminiData.usageMetadata?.promptTokenCount ?? 0,\n completion_tokens: geminiData.usageMetadata?.candidatesTokenCount ?? 0,\n total_tokens:\n (geminiData.usageMetadata?.promptTokenCount ?? 0) +\n (geminiData.usageMetadata?.candidatesTokenCount ?? 0),\n },\n };\n}\n\n/**\n * Convert Gemini streaming event to OpenAI format\n */\nfunction convertGeminiStreamEvent(\n eventData: GeminiResponse,\n messageId: string,\n model: string,\n isFirst: boolean\n): string | null {\n const candidate = eventData.candidates?.[0];\n const text = candidate?.content?.parts?.map((p) => p.text ?? '').join('') ?? '';\n \n const choice: Record<string, unknown> = {\n index: 0,\n delta: {},\n finish_reason: null,\n };\n \n if (isFirst) {\n choice['delta'] = { role: 'assistant', content: text };\n } else if (text) {\n choice['delta'] = { content: text };\n }\n \n // Check for finish\n if (candidate?.finishReason) {\n let finishReason = 'stop';\n if (candidate.finishReason === 'MAX_TOKENS') {\n finishReason = 'length';\n } else if (candidate.finishReason === 'SAFETY') {\n finishReason = 'content_filter';\n }\n choice['finish_reason'] = finishReason;\n }\n \n const chunk = {\n id: messageId,\n object: 'chat.completion.chunk',\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [choice],\n };\n \n return `data: ${JSON.stringify(chunk)}\\n\\n`;\n}\n\n/**\n * Parse Gemini SSE stream and convert to OpenAI format\n */\nasync function* convertGeminiStream(\n response: Response,\n model: string\n): AsyncGenerator<string, void, unknown> {\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n const messageId = `chatcmpl-${Date.now()}`;\n let isFirst = true;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Process complete SSE events (Gemini uses \"data: \" prefix)\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const jsonStr = line.slice(6);\n if (jsonStr.trim() === '[DONE]') {\n yield 'data: [DONE]\\n\\n';\n continue;\n }\n try {\n const parsed = JSON.parse(jsonStr) as GeminiResponse;\n const converted = convertGeminiStreamEvent(parsed, messageId, model, isFirst);\n if (converted) {\n yield converted;\n isFirst = false;\n }\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n \n // Send [DONE] at the end\n yield 'data: [DONE]\\n\\n';\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Anthropic API response structure\n */\ninterface AnthropicResponse {\n id?: string;\n model?: string;\n content?: Array<{ type: string; text?: string; id?: string; name?: string; input?: unknown }>;\n usage?: { input_tokens?: number; output_tokens?: number };\n stop_reason?: string;\n}\n\n/**\n * Convert Anthropic response to OpenAI format\n * Handles both text and tool_use content blocks\n */\nfunction convertAnthropicResponse(anthropicData: AnthropicResponse): Record<string, unknown> {\n const textBlocks = anthropicData.content?.filter((c) => c.type === 'text') ?? [];\n const toolBlocks = anthropicData.content?.filter((c) => c.type === 'tool_use') ?? [];\n\n const textContent = textBlocks.map((c) => c.text ?? '').join('');\n\n // Build message object\n const message: Record<string, unknown> = {\n role: 'assistant',\n content: textContent || null,\n };\n\n // Convert tool_use blocks to OpenAI tool_calls format\n if (toolBlocks.length > 0) {\n message['tool_calls'] = toolBlocks.map((block) => ({\n id: block.id || `call_${Date.now()}`,\n type: 'function',\n function: {\n name: block.name,\n arguments: typeof block.input === 'string' ? block.input : JSON.stringify(block.input ?? {}),\n },\n }));\n }\n\n // Determine finish_reason\n let finishReason = 'stop';\n if (anthropicData.stop_reason === 'tool_use') {\n finishReason = 'tool_calls';\n } else if (anthropicData.stop_reason === 'end_turn') {\n finishReason = 'stop';\n } else if (anthropicData.stop_reason) {\n finishReason = anthropicData.stop_reason;\n }\n\n return {\n id: anthropicData.id || `chatcmpl-${Date.now()}`,\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: anthropicData.model,\n choices: [\n {\n index: 0,\n message,\n finish_reason: finishReason,\n },\n ],\n usage: {\n prompt_tokens: anthropicData.usage?.input_tokens ?? 0,\n completion_tokens: anthropicData.usage?.output_tokens ?? 0,\n total_tokens: (anthropicData.usage?.input_tokens ?? 0) + (anthropicData.usage?.output_tokens ?? 0),\n },\n };\n}\n\n/**\n * Streaming state for tracking tool calls across events\n */\ninterface StreamingToolState {\n currentToolIndex: number;\n tools: Map<number, { id: string; name: string; arguments: string }>;\n}\n\n/**\n * Convert Anthropic streaming event to OpenAI streaming chunk format\n * Handles both text content and tool_use streaming\n */\nfunction convertAnthropicStreamEvent(\n eventType: string,\n eventData: Record<string, unknown>,\n messageId: string,\n model: string,\n toolState: StreamingToolState\n): string | null {\n const choice = { index: 0, delta: {} as Record<string, unknown>, finish_reason: null as string | null };\n const baseChunk = {\n id: messageId,\n object: 'chat.completion.chunk',\n created: Math.floor(Date.now() / 1000),\n model: model,\n choices: [choice],\n };\n\n switch (eventType) {\n case 'message_start': {\n // First chunk: include role\n const msg = eventData['message'] as Record<string, unknown> | undefined;\n baseChunk.id = (msg?.['id'] as string) || messageId;\n choice.delta = { role: 'assistant', content: '' };\n return `data: ${JSON.stringify(baseChunk)}\\n\\n`;\n }\n\n case 'content_block_start': {\n // New content block starting - could be text or tool_use\n const contentBlock = eventData['content_block'] as Record<string, unknown> | undefined;\n const blockIndex = eventData['index'] as number | undefined;\n \n if (contentBlock?.['type'] === 'tool_use') {\n // Tool use starting - send first chunk with tool info\n const toolId = contentBlock['id'] as string;\n const toolName = contentBlock['name'] as string;\n \n toolState.tools.set(blockIndex ?? toolState.currentToolIndex, {\n id: toolId,\n name: toolName,\n arguments: '',\n });\n toolState.currentToolIndex = blockIndex ?? toolState.currentToolIndex;\n \n choice.delta = {\n tool_calls: [{\n index: blockIndex ?? 0,\n id: toolId,\n type: 'function',\n function: { name: toolName, arguments: '' },\n }],\n };\n return `data: ${JSON.stringify(baseChunk)}\\n\\n`;\n }\n return null;\n }\n\n case 'content_block_delta': {\n // Content chunk - text or tool arguments\n const delta = eventData['delta'] as Record<string, unknown> | undefined;\n const blockIndex = eventData['index'] as number | undefined;\n \n if (delta?.['type'] === 'text_delta') {\n choice.delta = { content: delta['text'] as string };\n return `data: ${JSON.stringify(baseChunk)}\\n\\n`;\n }\n \n if (delta?.['type'] === 'input_json_delta') {\n // Tool arguments streaming\n const partialJson = delta['partial_json'] as string || '';\n const tool = toolState.tools.get(blockIndex ?? toolState.currentToolIndex);\n if (tool) {\n tool.arguments += partialJson;\n }\n \n choice.delta = {\n tool_calls: [{\n index: blockIndex ?? 0,\n function: { arguments: partialJson },\n }],\n };\n return `data: ${JSON.stringify(baseChunk)}\\n\\n`;\n }\n return null;\n }\n\n case 'message_delta': {\n // Final chunk with stop reason\n const delta = eventData['delta'] as Record<string, unknown> | undefined;\n const stopReason = delta?.['stop_reason'] as string | undefined;\n \n if (stopReason === 'tool_use') {\n choice.finish_reason = 'tool_calls';\n } else if (stopReason === 'end_turn') {\n choice.finish_reason = 'stop';\n } else {\n choice.finish_reason = stopReason || 'stop';\n }\n choice.delta = {};\n return `data: ${JSON.stringify(baseChunk)}\\n\\n`;\n }\n\n case 'message_stop': {\n // Stream complete\n return 'data: [DONE]\\n\\n';\n }\n\n default:\n return null;\n }\n}\n\n/**\n * Parse SSE stream from Anthropic and convert to OpenAI format\n */\nasync function* convertAnthropicStream(\n response: Response,\n model: string\n): AsyncGenerator<string, void, unknown> {\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n let messageId = `chatcmpl-${Date.now()}`;\n \n // Tool state for tracking streaming tool calls\n const toolState: StreamingToolState = {\n currentToolIndex: 0,\n tools: new Map(),\n };\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Process complete SSE events\n const lines = buffer.split('\\n');\n buffer = lines.pop() || ''; // Keep incomplete line in buffer\n\n let eventType = '';\n let eventData = '';\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n eventType = line.slice(7).trim();\n } else if (line.startsWith('data: ')) {\n eventData = line.slice(6);\n } else if (line === '' && eventType && eventData) {\n // Complete event, process it\n try {\n const parsed = JSON.parse(eventData) as Record<string, unknown>;\n const converted = convertAnthropicStreamEvent(eventType, parsed, messageId, model, toolState);\n if (converted) {\n yield converted;\n }\n } catch {\n // Skip malformed JSON\n }\n eventType = '';\n eventData = '';\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Pipe OpenAI streaming response directly (already in correct format)\n */\nasync function* pipeOpenAIStream(\n response: Response\n): AsyncGenerator<string, void, unknown> {\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n yield decoder.decode(value, { stream: true });\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Parse preferred model string (format: \"provider:model\")\n */\nfunction parsePreferredModel(\n preferredModel: string\n): { provider: Provider; model: string } | null {\n const [provider, model] = preferredModel.split(':');\n if (!provider || !model) return null;\n\n // Validate provider\n const validProviders: Provider[] = ['openai', 'anthropic', 'google', 'xai', 'moonshot', 'local'];\n if (!validProviders.includes(provider as Provider)) return null;\n\n return { provider: provider as Provider, model };\n}\n\n/**\n * Resolve explicit model name to provider and model\n * Handles direct model names like \"claude-3-5-sonnet-latest\" or \"gpt-4o\"\n */\nfunction resolveExplicitModel(\n modelName: string\n): { provider: Provider; model: string } | null {\n // Check MODEL_MAPPING first (aliases)\n if (MODEL_MAPPING[modelName]) {\n return MODEL_MAPPING[modelName];\n }\n\n // Anthropic models (claude-*)\n if (modelName.startsWith('claude-')) {\n return { provider: 'anthropic', model: modelName };\n }\n\n // OpenAI models (gpt-*, o1-*, chatgpt-*, text-*, dall-e-*, whisper-*, tts-*)\n if (\n modelName.startsWith('gpt-') ||\n modelName.startsWith('o1-') ||\n modelName.startsWith('o3-') ||\n modelName.startsWith('chatgpt-') ||\n modelName.startsWith('text-') ||\n modelName.startsWith('dall-e') ||\n modelName.startsWith('whisper') ||\n modelName.startsWith('tts-')\n ) {\n return { provider: 'openai', model: modelName };\n }\n\n // Google models (gemini-*, palm-*)\n if (modelName.startsWith('gemini-') || modelName.startsWith('palm-')) {\n return { provider: 'google', model: modelName };\n }\n\n // xAI models (grok-*)\n if (modelName.startsWith('grok-')) {\n return { provider: 'xai', model: modelName };\n }\n\n // Moonshot models (moonshot-*)\n if (modelName.startsWith('moonshot-')) {\n return { provider: 'moonshot', model: modelName };\n }\n\n // Provider-prefixed format: \"anthropic/claude-3-5-sonnet-latest\"\n if (modelName.includes('/')) {\n const [provider, model] = modelName.split('/');\n const validProviders: Provider[] = ['openai', 'anthropic', 'google', 'xai', 'moonshot', 'local'];\n if (provider && model && validProviders.includes(provider as Provider)) {\n return { provider: provider as Provider, model };\n }\n }\n\n return null;\n}\n\n/**\n * Start the RelayPlane proxy server\n */\nexport async function startProxy(config: ProxyConfig = {}): Promise<http.Server> {\n const port = config.port ?? 3001;\n const host = config.host ?? '127.0.0.1';\n const verbose = config.verbose ?? false;\n\n // Initialize RelayPlane\n const relay = new RelayPlane({ dbPath: config.dbPath });\n\n const log = (msg: string) => {\n if (verbose) console.log(`[relayplane] ${msg}`);\n };\n\n const server = http.createServer(async (req, res) => {\n // CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Only handle POST to /v1/chat/completions\n if (req.method !== 'POST' || !req.url?.includes('/chat/completions')) {\n // Return model list for /v1/models\n if (req.method === 'GET' && req.url?.includes('/models')) {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n object: 'list',\n data: [\n { id: 'relayplane:auto', object: 'model', owned_by: 'relayplane' },\n { id: 'relayplane:cost', object: 'model', owned_by: 'relayplane' },\n { id: 'relayplane:quality', object: 'model', owned_by: 'relayplane' },\n ],\n })\n );\n return;\n }\n\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n return;\n }\n\n // Parse request body\n let body = '';\n for await (const chunk of req) {\n body += chunk;\n }\n\n let request: ChatRequest;\n try {\n request = JSON.parse(body);\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid JSON' }));\n return;\n }\n\n const isStreaming = request.stream === true;\n\n // Extract routing mode from model name\n const requestedModel = request.model;\n let routingMode: 'auto' | 'cost' | 'quality' | 'passthrough' = 'auto';\n let targetModel: string = '';\n let targetProvider: Provider = 'anthropic';\n\n // Check if this is a RelayPlane routing model or explicit pass-through\n if (requestedModel.startsWith('relayplane:')) {\n // RelayPlane smart routing\n if (requestedModel.includes(':cost')) {\n routingMode = 'cost';\n } else if (requestedModel.includes(':quality')) {\n routingMode = 'quality';\n }\n } else {\n // Explicit model pass-through (L3 mode)\n routingMode = 'passthrough';\n const resolved = resolveExplicitModel(requestedModel);\n if (resolved) {\n targetProvider = resolved.provider;\n targetModel = resolved.model;\n log(`Pass-through mode: ${requestedModel} → ${targetProvider}/${targetModel}`);\n } else {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: `Unknown model: ${requestedModel}` }));\n return;\n }\n }\n\n log(`Received request for model: ${requestedModel} (mode: ${routingMode}, stream: ${isStreaming})`);\n\n // Infer task type from prompt (for logging/learning, even in passthrough)\n const promptText = extractPromptText(request.messages);\n const taskType = inferTaskType(promptText);\n const confidence = getInferenceConfidence(promptText, taskType);\n\n log(`Inferred task: ${taskType} (confidence: ${confidence.toFixed(2)})`);\n\n // Smart routing only for RelayPlane models\n if (routingMode !== 'passthrough') {\n // Check if there's a learned rule for this task type\n const rule = relay.routing.get(taskType);\n\n if (rule && rule.preferredModel) {\n const parsed = parsePreferredModel(rule.preferredModel);\n if (parsed) {\n targetProvider = parsed.provider;\n targetModel = parsed.model;\n log(`Using learned rule: ${rule.preferredModel}`);\n } else {\n // Fallback to defaults\n const defaultRoute = DEFAULT_ROUTING[taskType];\n targetProvider = defaultRoute.provider;\n targetModel = defaultRoute.model;\n }\n } else {\n // Use default routing\n const defaultRoute = DEFAULT_ROUTING[taskType];\n targetProvider = defaultRoute.provider;\n targetModel = defaultRoute.model;\n }\n\n // Override based on routing mode\n if (routingMode === 'cost') {\n // Prefer cheapest: Haiku for simple tasks\n const simpleTasks: TaskType[] = ['summarization', 'data_extraction', 'translation', 'question_answering'];\n if (simpleTasks.includes(taskType)) {\n targetModel = 'claude-3-5-haiku-latest';\n targetProvider = 'anthropic';\n }\n } else if (routingMode === 'quality') {\n // Quality mode: Always use the best available model\n const qualityModel = process.env['RELAYPLANE_QUALITY_MODEL'] || 'claude-sonnet-4-20250514';\n targetModel = qualityModel;\n targetProvider = 'anthropic';\n }\n }\n\n log(`Routing to: ${targetProvider}/${targetModel}`);\n\n // Get API key for target provider\n const apiKeyEnv = DEFAULT_ENDPOINTS[targetProvider]?.apiKeyEnv ?? `${targetProvider.toUpperCase()}_API_KEY`;\n const apiKey = process.env[apiKeyEnv];\n\n if (!apiKey) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: `Missing ${apiKeyEnv} environment variable` }));\n return;\n }\n\n const startTime = Date.now();\n\n // Extract Anthropic beta headers from request (for prompt caching, extended thinking, etc.)\n const betaHeaders = req.headers['anthropic-beta'] as string | undefined;\n\n // Handle streaming vs non-streaming\n if (isStreaming) {\n await handleStreamingRequest(\n res,\n request,\n targetProvider,\n targetModel,\n apiKey,\n relay,\n promptText,\n taskType,\n confidence,\n routingMode,\n startTime,\n log,\n betaHeaders\n );\n } else {\n await handleNonStreamingRequest(\n res,\n request,\n targetProvider,\n targetModel,\n apiKey,\n relay,\n promptText,\n taskType,\n confidence,\n routingMode,\n startTime,\n log,\n betaHeaders\n );\n }\n });\n\n return new Promise((resolve, reject) => {\n server.on('error', reject);\n server.listen(port, host, () => {\n console.log(`RelayPlane proxy listening on http://${host}:${port}`);\n console.log(` Models: relayplane:auto, relayplane:cost, relayplane:quality`);\n console.log(` Endpoint: POST /v1/chat/completions`);\n console.log(` Streaming: ✅ Enabled`);\n resolve(server);\n });\n });\n}\n\n/**\n * Handle streaming request\n */\nasync function handleStreamingRequest(\n res: http.ServerResponse,\n request: ChatRequest,\n targetProvider: Provider,\n targetModel: string,\n apiKey: string,\n relay: RelayPlane,\n promptText: string,\n taskType: TaskType,\n confidence: number,\n routingMode: string,\n startTime: number,\n log: (msg: string) => void,\n betaHeaders?: string\n): Promise<void> {\n let providerResponse: Response;\n\n try {\n switch (targetProvider) {\n case 'anthropic':\n providerResponse = await forwardToAnthropicStream(request, targetModel, apiKey, betaHeaders);\n break;\n case 'google':\n providerResponse = await forwardToGeminiStream(request, targetModel, apiKey);\n break;\n case 'xai':\n providerResponse = await forwardToXAIStream(request, targetModel, apiKey);\n break;\n case 'moonshot':\n providerResponse = await forwardToMoonshotStream(request, targetModel, apiKey);\n break;\n default:\n providerResponse = await forwardToOpenAIStream(request, targetModel, apiKey);\n }\n\n if (!providerResponse.ok) {\n const errorData = await providerResponse.json();\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(errorData));\n return;\n }\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: `Provider error: ${errorMsg}` }));\n return;\n }\n\n // Set SSE headers\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n });\n\n try {\n // Stream the response based on provider format\n switch (targetProvider) {\n case 'anthropic':\n // Convert Anthropic stream to OpenAI format\n for await (const chunk of convertAnthropicStream(providerResponse, targetModel)) {\n res.write(chunk);\n }\n break;\n case 'google':\n // Convert Gemini stream to OpenAI format\n for await (const chunk of convertGeminiStream(providerResponse, targetModel)) {\n res.write(chunk);\n }\n break;\n default:\n // xAI, Moonshot, OpenAI all use OpenAI-compatible streaming format\n for await (const chunk of pipeOpenAIStream(providerResponse)) {\n res.write(chunk);\n }\n }\n } catch (err) {\n log(`Streaming error: ${err}`);\n }\n\n const durationMs = Date.now() - startTime;\n\n // Record the run (non-blocking)\n relay\n .run({\n prompt: promptText.slice(0, 500),\n taskType,\n model: `${targetProvider}:${targetModel}`,\n })\n .then((runResult) => {\n log(`Completed streaming in ${durationMs}ms, runId: ${runResult.runId}`);\n })\n .catch((err) => {\n log(`Failed to record run: ${err}`);\n });\n\n res.end();\n}\n\n/**\n * Handle non-streaming request\n */\nasync function handleNonStreamingRequest(\n res: http.ServerResponse,\n request: ChatRequest,\n targetProvider: Provider,\n targetModel: string,\n apiKey: string,\n relay: RelayPlane,\n promptText: string,\n taskType: TaskType,\n confidence: number,\n routingMode: string,\n startTime: number,\n log: (msg: string) => void,\n betaHeaders?: string\n): Promise<void> {\n let providerResponse: Response;\n let responseData: Record<string, unknown>;\n\n try {\n switch (targetProvider) {\n case 'anthropic': {\n providerResponse = await forwardToAnthropic(request, targetModel, apiKey, betaHeaders);\n const rawData = (await providerResponse.json()) as AnthropicResponse;\n\n if (!providerResponse.ok) {\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(rawData));\n return;\n }\n\n // Convert to OpenAI format\n responseData = convertAnthropicResponse(rawData);\n break;\n }\n case 'google': {\n providerResponse = await forwardToGemini(request, targetModel, apiKey);\n const rawData = (await providerResponse.json()) as GeminiResponse;\n\n if (!providerResponse.ok) {\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(rawData));\n return;\n }\n\n // Convert to OpenAI format\n responseData = convertGeminiResponse(rawData, targetModel);\n break;\n }\n case 'xai': {\n providerResponse = await forwardToXAI(request, targetModel, apiKey);\n responseData = (await providerResponse.json()) as Record<string, unknown>;\n\n if (!providerResponse.ok) {\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(responseData));\n return;\n }\n break;\n }\n case 'moonshot': {\n providerResponse = await forwardToMoonshot(request, targetModel, apiKey);\n responseData = (await providerResponse.json()) as Record<string, unknown>;\n\n if (!providerResponse.ok) {\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(responseData));\n return;\n }\n break;\n }\n default: {\n providerResponse = await forwardToOpenAI(request, targetModel, apiKey);\n responseData = (await providerResponse.json()) as Record<string, unknown>;\n\n if (!providerResponse.ok) {\n res.writeHead(providerResponse.status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(responseData));\n return;\n }\n }\n }\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: `Provider error: ${errorMsg}` }));\n return;\n }\n\n const durationMs = Date.now() - startTime;\n\n // Record the run in RelayPlane\n try {\n const runResult = await relay.run({\n prompt: promptText.slice(0, 500),\n taskType,\n model: `${targetProvider}:${targetModel}`,\n });\n\n // Add routing metadata to response\n responseData['_relayplane'] = {\n runId: runResult.runId,\n routedTo: `${targetProvider}/${targetModel}`,\n taskType,\n confidence,\n durationMs,\n mode: routingMode,\n };\n\n log(`Completed in ${durationMs}ms, runId: ${runResult.runId}`);\n } catch (err) {\n log(`Failed to record run: ${err}`);\n }\n\n // Send response\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(responseData));\n}\n\n/**\n * CLI entry point\n */\nexport async function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n let port = 3001;\n let verbose = false;\n\n for (let i = 0; i < args.length; i++) {\n if (args[i] === '--port' && args[i + 1]) {\n port = parseInt(args[i + 1] ?? '3001', 10);\n i++;\n } else if (args[i] === '-v' || args[i] === '--verbose') {\n verbose = true;\n }\n }\n\n try {\n await startProxy({ port, verbose });\n } catch (err) {\n console.error('Failed to start proxy:', err);\n process.exit(1);\n }\n}\n\n// Note: Use cli.ts for direct execution\n// This module is imported by cli.ts\n","/**\n * SQLite Storage Implementation\n *\n * Provides persistent storage for runs, outcomes, routing rules, and suggestions.\n *\n * @packageDocumentation\n */\n\nimport Database from 'better-sqlite3';\nimport { nanoid } from 'nanoid';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\nimport { SCHEMA_SQL, generateSeedSQL } from './schema.js';\nimport type {\n RunRecord,\n OutcomeRecord,\n RuleRecord,\n SuggestionRecord,\n TaskType,\n RuleSource,\n OutcomeQuality,\n} from '../types.js';\n\n/**\n * Default database path.\n */\nexport function getDefaultDbPath(): string {\n return path.join(os.homedir(), '.relayplane', 'data.db');\n}\n\n/**\n * SQLite storage class for RelayPlane data.\n */\nexport class Store {\n private db: Database.Database;\n private readonly dbPath: string;\n\n /**\n * Creates a new Store instance.\n *\n * @param dbPath - Path to the SQLite database file. Defaults to ~/.relayplane/data.db\n */\n constructor(dbPath?: string) {\n this.dbPath = dbPath ?? getDefaultDbPath();\n\n // Ensure directory exists\n const dir = path.dirname(this.dbPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Open database\n this.db = new Database(this.dbPath);\n\n // Enable WAL mode for better concurrent access\n this.db.pragma('journal_mode = WAL');\n\n // Enable foreign keys\n this.db.pragma('foreign_keys = ON');\n\n // Initialize schema\n this.initializeSchema();\n }\n\n /**\n * Initializes the database schema.\n */\n private initializeSchema(): void {\n this.db.exec(SCHEMA_SQL);\n this.db.exec(generateSeedSQL());\n }\n\n /**\n * Closes the database connection.\n */\n close(): void {\n this.db.close();\n }\n\n /**\n * Gets the database path.\n */\n getDbPath(): string {\n return this.dbPath;\n }\n\n // ============================================================================\n // Runs\n // ============================================================================\n\n /**\n * Records a new run.\n */\n recordRun(run: Omit<RunRecord, 'id' | 'createdAt'>): string {\n const id = nanoid();\n const stmt = this.db.prepare(`\n INSERT INTO runs (id, prompt, system_prompt, task_type, model, success, output, error, duration_ms, tokens_in, tokens_out, cost_usd, metadata, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))\n `);\n\n stmt.run(\n id,\n run.prompt,\n run.systemPrompt,\n run.taskType,\n run.model,\n run.success ? 1 : 0,\n run.output,\n run.error,\n run.durationMs,\n run.tokensIn,\n run.tokensOut,\n run.costUsd,\n run.metadata\n );\n\n return id;\n }\n\n /**\n * Gets a run by ID.\n */\n getRun(id: string): RunRecord | null {\n const stmt = this.db.prepare(`\n SELECT id, prompt, system_prompt as systemPrompt, task_type as taskType, model, success, output, error, duration_ms as durationMs, tokens_in as tokensIn, tokens_out as tokensOut, cost_usd as costUsd, metadata, created_at as createdAt\n FROM runs\n WHERE id = ?\n `);\n\n const row = stmt.get(id) as RunRecord | undefined;\n if (!row) return null;\n\n return {\n ...row,\n success: Boolean(row.success),\n };\n }\n\n /**\n * Gets runs with optional filters.\n */\n getRuns(options?: {\n taskType?: TaskType;\n model?: string;\n limit?: number;\n offset?: number;\n from?: string;\n to?: string;\n }): RunRecord[] {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options?.taskType) {\n conditions.push('task_type = ?');\n params.push(options.taskType);\n }\n\n if (options?.model) {\n conditions.push('model = ?');\n params.push(options.model);\n }\n\n if (options?.from) {\n conditions.push('created_at >= ?');\n params.push(options.from);\n }\n\n if (options?.to) {\n conditions.push('created_at <= ?');\n params.push(options.to);\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const limit = options?.limit ?? 100;\n const offset = options?.offset ?? 0;\n\n const stmt = this.db.prepare(`\n SELECT id, prompt, system_prompt as systemPrompt, task_type as taskType, model, success, output, error, duration_ms as durationMs, tokens_in as tokensIn, tokens_out as tokensOut, cost_usd as costUsd, metadata, created_at as createdAt\n FROM runs\n ${whereClause}\n ORDER BY created_at DESC\n LIMIT ? OFFSET ?\n `);\n\n params.push(limit, offset);\n\n const rows = stmt.all(...params) as RunRecord[];\n return rows.map((row) => ({\n ...row,\n success: Boolean(row.success),\n }));\n }\n\n /**\n * Counts runs with optional filters.\n */\n countRuns(options?: {\n taskType?: TaskType;\n model?: string;\n from?: string;\n to?: string;\n }): number {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options?.taskType) {\n conditions.push('task_type = ?');\n params.push(options.taskType);\n }\n\n if (options?.model) {\n conditions.push('model = ?');\n params.push(options.model);\n }\n\n if (options?.from) {\n conditions.push('created_at >= ?');\n params.push(options.from);\n }\n\n if (options?.to) {\n conditions.push('created_at <= ?');\n params.push(options.to);\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n\n const stmt = this.db.prepare(`\n SELECT COUNT(*) as count\n FROM runs\n ${whereClause}\n `);\n\n const row = stmt.get(...params) as { count: number };\n return row.count;\n }\n\n // ============================================================================\n // Outcomes\n // ============================================================================\n\n /**\n * Records an outcome for a run.\n */\n recordOutcome(outcome: Omit<OutcomeRecord, 'id' | 'createdAt'>): string {\n const id = nanoid();\n const stmt = this.db.prepare(`\n INSERT INTO outcomes (id, run_id, success, quality, latency_satisfactory, cost_satisfactory, feedback, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))\n ON CONFLICT(run_id) DO UPDATE SET\n success = excluded.success,\n quality = excluded.quality,\n latency_satisfactory = excluded.latency_satisfactory,\n cost_satisfactory = excluded.cost_satisfactory,\n feedback = excluded.feedback,\n created_at = datetime('now')\n `);\n\n stmt.run(\n id,\n outcome.runId,\n outcome.success ? 1 : 0,\n outcome.quality,\n outcome.latencySatisfactory != null ? (outcome.latencySatisfactory ? 1 : 0) : null,\n outcome.costSatisfactory != null ? (outcome.costSatisfactory ? 1 : 0) : null,\n outcome.feedback\n );\n\n return id;\n }\n\n /**\n * Gets an outcome for a run.\n */\n getOutcome(runId: string): OutcomeRecord | null {\n const stmt = this.db.prepare(`\n SELECT id, run_id as runId, success, quality, latency_satisfactory as latencySatisfactory, cost_satisfactory as costSatisfactory, feedback, created_at as createdAt\n FROM outcomes\n WHERE run_id = ?\n `);\n\n const row = stmt.get(runId) as OutcomeRecord | undefined;\n if (!row) return null;\n\n return {\n ...row,\n success: Boolean(row.success),\n latencySatisfactory: row.latencySatisfactory != null ? Boolean(row.latencySatisfactory) : null,\n costSatisfactory: row.costSatisfactory != null ? Boolean(row.costSatisfactory) : null,\n };\n }\n\n /**\n * Gets outcomes with optional filters.\n */\n getOutcomes(options?: {\n taskType?: TaskType;\n model?: string;\n limit?: number;\n from?: string;\n to?: string;\n }): Array<OutcomeRecord & { taskType: TaskType; model: string }> {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options?.taskType) {\n conditions.push('r.task_type = ?');\n params.push(options.taskType);\n }\n\n if (options?.model) {\n conditions.push('r.model = ?');\n params.push(options.model);\n }\n\n if (options?.from) {\n conditions.push('o.created_at >= ?');\n params.push(options.from);\n }\n\n if (options?.to) {\n conditions.push('o.created_at <= ?');\n params.push(options.to);\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const limit = options?.limit ?? 100;\n\n const stmt = this.db.prepare(`\n SELECT o.id, o.run_id as runId, o.success, o.quality, o.latency_satisfactory as latencySatisfactory, o.cost_satisfactory as costSatisfactory, o.feedback, o.created_at as createdAt, r.task_type as taskType, r.model\n FROM outcomes o\n JOIN runs r ON o.run_id = r.id\n ${whereClause}\n ORDER BY o.created_at DESC\n LIMIT ?\n `);\n\n params.push(limit);\n\n const rows = stmt.all(...params) as Array<OutcomeRecord & { taskType: TaskType; model: string }>;\n return rows.map((row) => ({\n ...row,\n success: Boolean(row.success),\n latencySatisfactory: row.latencySatisfactory != null ? Boolean(row.latencySatisfactory) : null,\n costSatisfactory: row.costSatisfactory != null ? Boolean(row.costSatisfactory) : null,\n }));\n }\n\n // ============================================================================\n // Routing Rules\n // ============================================================================\n\n /**\n * Gets a routing rule for a task type.\n */\n getRule(taskType: TaskType): RuleRecord | null {\n const stmt = this.db.prepare(`\n SELECT id, task_type as taskType, preferred_model as preferredModel, source, confidence, sample_count as sampleCount, created_at as createdAt, updated_at as updatedAt\n FROM routing_rules\n WHERE task_type = ?\n `);\n\n return (stmt.get(taskType) as RuleRecord | undefined) ?? null;\n }\n\n /**\n * Sets a routing rule for a task type.\n */\n setRule(taskType: TaskType, preferredModel: string, source: RuleSource, confidence?: number, sampleCount?: number): string {\n const existingRule = this.getRule(taskType);\n const id = existingRule?.id ?? nanoid();\n\n const stmt = this.db.prepare(`\n INSERT INTO routing_rules (id, task_type, preferred_model, source, confidence, sample_count, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))\n ON CONFLICT(task_type) DO UPDATE SET\n preferred_model = excluded.preferred_model,\n source = excluded.source,\n confidence = excluded.confidence,\n sample_count = excluded.sample_count,\n updated_at = datetime('now')\n `);\n\n stmt.run(id, taskType, preferredModel, source, confidence ?? null, sampleCount ?? null);\n\n return id;\n }\n\n /**\n * Lists all routing rules.\n */\n listRules(): RuleRecord[] {\n const stmt = this.db.prepare(`\n SELECT id, task_type as taskType, preferred_model as preferredModel, source, confidence, sample_count as sampleCount, created_at as createdAt, updated_at as updatedAt\n FROM routing_rules\n ORDER BY task_type\n `);\n\n return stmt.all() as RuleRecord[];\n }\n\n /**\n * Deletes a routing rule and resets to default.\n */\n deleteRule(taskType: TaskType): boolean {\n // Find the default rule for this task type\n const defaultRule = DEFAULT_ROUTING_RULES.find((r) => r.taskType === taskType);\n if (!defaultRule) return false;\n\n // Reset to default\n this.setRule(taskType, defaultRule.preferredModel, 'default');\n return true;\n }\n\n // ============================================================================\n // Suggestions\n // ============================================================================\n\n /**\n * Records a suggestion.\n */\n recordSuggestion(suggestion: Omit<SuggestionRecord, 'id' | 'createdAt' | 'acceptedAt'>): string {\n const id = nanoid();\n const stmt = this.db.prepare(`\n INSERT INTO suggestions (id, task_type, current_model, suggested_model, reason, confidence, expected_improvement, sample_count, accepted, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))\n `);\n\n stmt.run(\n id,\n suggestion.taskType,\n suggestion.currentModel,\n suggestion.suggestedModel,\n suggestion.reason,\n suggestion.confidence,\n suggestion.expectedImprovement,\n suggestion.sampleCount,\n suggestion.accepted ?? null\n );\n\n return id;\n }\n\n /**\n * Gets a suggestion by ID.\n */\n getSuggestion(id: string): SuggestionRecord | null {\n const stmt = this.db.prepare(`\n SELECT id, task_type as taskType, current_model as currentModel, suggested_model as suggestedModel, reason, confidence, expected_improvement as expectedImprovement, sample_count as sampleCount, accepted, created_at as createdAt, accepted_at as acceptedAt\n FROM suggestions\n WHERE id = ?\n `);\n\n const row = stmt.get(id) as SuggestionRecord | undefined;\n if (!row) return null;\n\n return {\n ...row,\n accepted: row.accepted != null ? Boolean(row.accepted) : null,\n };\n }\n\n /**\n * Gets pending (unaccepted) suggestions.\n */\n getPendingSuggestions(): SuggestionRecord[] {\n const stmt = this.db.prepare(`\n SELECT id, task_type as taskType, current_model as currentModel, suggested_model as suggestedModel, reason, confidence, expected_improvement as expectedImprovement, sample_count as sampleCount, accepted, created_at as createdAt, accepted_at as acceptedAt\n FROM suggestions\n WHERE accepted IS NULL\n ORDER BY confidence DESC\n `);\n\n const rows = stmt.all() as SuggestionRecord[];\n return rows.map((row) => ({\n ...row,\n accepted: row.accepted != null ? Boolean(row.accepted) : null,\n }));\n }\n\n /**\n * Accepts a suggestion.\n */\n acceptSuggestion(id: string): boolean {\n const suggestion = this.getSuggestion(id);\n if (!suggestion) return false;\n\n // Update the suggestion\n const updateStmt = this.db.prepare(`\n UPDATE suggestions\n SET accepted = 1, accepted_at = datetime('now')\n WHERE id = ?\n `);\n updateStmt.run(id);\n\n // Update the routing rule\n this.setRule(\n suggestion.taskType,\n suggestion.suggestedModel,\n 'learned',\n suggestion.confidence,\n suggestion.sampleCount\n );\n\n return true;\n }\n\n /**\n * Rejects a suggestion.\n */\n rejectSuggestion(id: string): boolean {\n const stmt = this.db.prepare(`\n UPDATE suggestions\n SET accepted = 0, accepted_at = datetime('now')\n WHERE id = ?\n `);\n\n const result = stmt.run(id);\n return result.changes > 0;\n }\n\n // ============================================================================\n // Statistics\n // ============================================================================\n\n /**\n * Gets aggregated statistics.\n */\n getStats(options?: { from?: string; to?: string }): {\n totalRuns: number;\n successfulRuns: number;\n avgDurationMs: number;\n byTaskType: Record<string, { runs: number; successRate: number; avgDurationMs: number }>;\n byModel: Record<string, { runs: number; successRate: number; avgDurationMs: number }>;\n } {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options?.from) {\n conditions.push('created_at >= ?');\n params.push(options.from);\n }\n\n if (options?.to) {\n conditions.push('created_at <= ?');\n params.push(options.to);\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n\n // Overall stats\n const overallStmt = this.db.prepare(`\n SELECT \n COUNT(*) as totalRuns,\n SUM(success) as successfulRuns,\n AVG(duration_ms) as avgDurationMs\n FROM runs\n ${whereClause}\n `);\n\n const overall = overallStmt.get(...params) as {\n totalRuns: number;\n successfulRuns: number;\n avgDurationMs: number;\n };\n\n // Stats by task type\n const byTaskTypeStmt = this.db.prepare(`\n SELECT \n task_type as taskType,\n COUNT(*) as runs,\n AVG(success) as successRate,\n AVG(duration_ms) as avgDurationMs\n FROM runs\n ${whereClause}\n GROUP BY task_type\n `);\n\n const byTaskTypeRows = byTaskTypeStmt.all(...params) as Array<{\n taskType: string;\n runs: number;\n successRate: number;\n avgDurationMs: number;\n }>;\n\n const byTaskType: Record<string, { runs: number; successRate: number; avgDurationMs: number }> = {};\n for (const row of byTaskTypeRows) {\n byTaskType[row.taskType] = {\n runs: row.runs,\n successRate: row.successRate,\n avgDurationMs: row.avgDurationMs,\n };\n }\n\n // Stats by model\n const byModelStmt = this.db.prepare(`\n SELECT \n model,\n COUNT(*) as runs,\n AVG(success) as successRate,\n AVG(duration_ms) as avgDurationMs\n FROM runs\n ${whereClause}\n GROUP BY model\n `);\n\n const byModelRows = byModelStmt.all(...params) as Array<{\n model: string;\n runs: number;\n successRate: number;\n avgDurationMs: number;\n }>;\n\n const byModel: Record<string, { runs: number; successRate: number; avgDurationMs: number }> = {};\n for (const row of byModelRows) {\n byModel[row.model] = {\n runs: row.runs,\n successRate: row.successRate,\n avgDurationMs: row.avgDurationMs,\n };\n }\n\n return {\n totalRuns: overall.totalRuns,\n successfulRuns: overall.successfulRuns ?? 0,\n avgDurationMs: overall.avgDurationMs ?? 0,\n byTaskType,\n byModel,\n };\n }\n\n /**\n * Gets statistics for learning (outcomes joined with runs).\n */\n getLearningStats(taskType: TaskType): Array<{\n model: string;\n runs: number;\n successRate: number;\n avgDurationMs: number;\n outcomeSuccessRate: number;\n }> {\n const stmt = this.db.prepare(`\n SELECT \n r.model,\n COUNT(*) as runs,\n AVG(r.success) as successRate,\n AVG(r.duration_ms) as avgDurationMs,\n AVG(CASE WHEN o.success IS NOT NULL THEN o.success ELSE r.success END) as outcomeSuccessRate\n FROM runs r\n LEFT JOIN outcomes o ON r.id = o.run_id\n WHERE r.task_type = ?\n GROUP BY r.model\n HAVING runs >= 5\n `);\n\n return stmt.all(taskType) as Array<{\n model: string;\n runs: number;\n successRate: number;\n avgDurationMs: number;\n outcomeSuccessRate: number;\n }>;\n }\n}\n\n// Import for seed data\nimport { DEFAULT_ROUTING_RULES } from './schema.js';\n","import crypto from 'crypto'\nimport { urlAlphabet } from './url-alphabet/index.js'\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool, poolOffset\nlet fillPool = bytes => {\n if (!pool || pool.length < bytes) {\n pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n crypto.randomFillSync(pool)\n poolOffset = 0\n } else if (poolOffset + bytes > pool.length) {\n crypto.randomFillSync(pool)\n poolOffset = 0\n }\n poolOffset += bytes\n}\nlet random = bytes => {\n fillPool((bytes |= 0))\n return pool.subarray(poolOffset - bytes, poolOffset)\n}\nlet customRandom = (alphabet, defaultSize, getRandom) => {\n let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1\n let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)\n return (size = defaultSize) => {\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let i = step\n while (i--) {\n id += alphabet[bytes[i] & mask] || ''\n if (id.length === size) return id\n }\n }\n }\n}\nlet customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size, random)\nlet nanoid = (size = 21) => {\n fillPool((size |= 0))\n let id = ''\n for (let i = poolOffset - size; i < poolOffset; i++) {\n id += urlAlphabet[pool[i] & 63]\n }\n return id\n}\nexport { nanoid, customAlphabet, customRandom, urlAlphabet, random }\n","let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\nexport { urlAlphabet }\n","/**\n * SQLite Schema Definition\n *\n * Defines the database schema for RelayPlane storage.\n *\n * @packageDocumentation\n */\n\n/**\n * SQL statements for creating the database schema.\n */\nexport const SCHEMA_SQL = `\n-- Runs table: stores all LLM invocations\nCREATE TABLE IF NOT EXISTS runs (\n id TEXT PRIMARY KEY,\n prompt TEXT NOT NULL,\n system_prompt TEXT,\n task_type TEXT NOT NULL,\n model TEXT NOT NULL,\n success INTEGER NOT NULL,\n output TEXT,\n error TEXT,\n duration_ms INTEGER NOT NULL,\n tokens_in INTEGER,\n tokens_out INTEGER,\n cost_usd REAL,\n metadata TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Index for task type queries\nCREATE INDEX IF NOT EXISTS idx_runs_task_type ON runs(task_type);\n\n-- Index for model queries\nCREATE INDEX IF NOT EXISTS idx_runs_model ON runs(model);\n\n-- Index for time-based queries\nCREATE INDEX IF NOT EXISTS idx_runs_created_at ON runs(created_at);\n\n-- Outcomes table: stores user feedback on runs\nCREATE TABLE IF NOT EXISTS outcomes (\n id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,\n success INTEGER NOT NULL,\n quality TEXT,\n latency_satisfactory INTEGER,\n cost_satisfactory INTEGER,\n feedback TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n UNIQUE(run_id)\n);\n\n-- Index for run lookups\nCREATE INDEX IF NOT EXISTS idx_outcomes_run_id ON outcomes(run_id);\n\n-- Routing rules table: stores routing preferences\nCREATE TABLE IF NOT EXISTS routing_rules (\n id TEXT PRIMARY KEY,\n task_type TEXT NOT NULL UNIQUE,\n preferred_model TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'default',\n confidence REAL,\n sample_count INTEGER,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Index for task type lookups\nCREATE INDEX IF NOT EXISTS idx_routing_rules_task_type ON routing_rules(task_type);\n\n-- Suggestions table: stores routing improvement suggestions\nCREATE TABLE IF NOT EXISTS suggestions (\n id TEXT PRIMARY KEY,\n task_type TEXT NOT NULL,\n current_model TEXT NOT NULL,\n suggested_model TEXT NOT NULL,\n reason TEXT NOT NULL,\n confidence REAL NOT NULL,\n expected_improvement TEXT NOT NULL,\n sample_count INTEGER NOT NULL,\n accepted INTEGER,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n accepted_at TEXT\n);\n\n-- Index for task type lookups\nCREATE INDEX IF NOT EXISTS idx_suggestions_task_type ON suggestions(task_type);\n\n-- Index for pending suggestions\nCREATE INDEX IF NOT EXISTS idx_suggestions_accepted ON suggestions(accepted);\n\n-- Schema version table for migrations\nCREATE TABLE IF NOT EXISTS schema_version (\n version INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Insert initial schema version\nINSERT OR IGNORE INTO schema_version (version) VALUES (1);\n`;\n\n/**\n * Default routing rules to seed the database.\n * Using -latest suffix for automatic model updates.\n */\nexport const DEFAULT_ROUTING_RULES = [\n { taskType: 'code_generation', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'code_review', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'summarization', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'analysis', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'creative_writing', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'data_extraction', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'translation', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'question_answering', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n { taskType: 'general', preferredModel: 'anthropic:claude-3-5-haiku-latest' },\n] as const;\n\n/**\n * SQL for seeding default routing rules.\n */\nexport function generateSeedSQL(): string {\n const values = DEFAULT_ROUTING_RULES.map((rule, index) => {\n const id = `default-${rule.taskType}`;\n return `('${id}', '${rule.taskType}', '${rule.preferredModel}', 'default', NULL, NULL, datetime('now'), datetime('now'))`;\n }).join(',\\n ');\n\n return `\nINSERT OR IGNORE INTO routing_rules (id, task_type, preferred_model, source, confidence, sample_count, created_at, updated_at)\nVALUES\n ${values};\n`;\n}\n","/**\n * Task Type Inference\n *\n * Infers the task type from a prompt using pattern matching.\n * Designed for <5ms execution with no network calls.\n *\n * @packageDocumentation\n */\n\nimport type { TaskType } from '../types.js';\n\n/**\n * Pattern definition for task inference.\n */\ninterface InferencePattern {\n /**\n * Regular expression to match against the prompt.\n */\n pattern: RegExp;\n\n /**\n * Weight for this pattern (higher = more confident).\n */\n weight: number;\n}\n\n/**\n * Patterns for each task type.\n * Order matters - earlier patterns in the array have higher priority when weights are equal.\n */\nconst TASK_PATTERNS: Record<TaskType, InferencePattern[]> = {\n code_generation: [\n { pattern: /\\b(write|create|generate|implement|build|code|develop|make)\\b.{0,50}\\b(function|class|code|script|program|method|module|api|endpoint|component)\\b/i, weight: 10 },\n { pattern: /\\b(write|create|generate)\\b.{0,30}\\b(python|javascript|typescript|java|go|rust|c\\+\\+|ruby|php|swift)\\b/i, weight: 10 },\n { pattern: /\\bcreate a.{0,30}(that|which|to)\\b/i, weight: 5 },\n { pattern: /\\bimplement\\b.{0,50}\\b(algorithm|logic|feature)\\b/i, weight: 8 },\n { pattern: /\\bcode\\s+for\\b/i, weight: 7 },\n { pattern: /\\bwrite me\\b.{0,30}\\b(code|script|function)\\b/i, weight: 9 },\n { pattern: /```[\\w]*\\n/i, weight: 3 }, // Code blocks suggest code context\n ],\n\n code_review: [\n { pattern: /\\b(review|analyze|check|audit|inspect|evaluate|assess|critique)\\b.{0,30}\\b(code|function|class|script|implementation|pull request|pr|diff)\\b/i, weight: 10 },\n { pattern: /\\b(what'?s? wrong|find\\s+(bugs?|issues?|problems?|errors?))\\b.{0,30}\\b(code|function|this)\\b/i, weight: 9 },\n { pattern: /\\b(improve|optimize|refactor)\\b.{0,30}\\b(code|function|this)\\b/i, weight: 7 },\n { pattern: /\\blook\\s+(at|over)\\s+(this|my)\\s+code\\b/i, weight: 8 },\n { pattern: /\\bcode\\s+review\\b/i, weight: 10 },\n { pattern: /\\bcan you (check|review)\\b/i, weight: 5 },\n ],\n\n summarization: [\n { pattern: /\\b(summarize|summarise|summary|tldr|tl;dr|recap|condense|brief|overview)\\b/i, weight: 10 },\n { pattern: /\\b(give|provide|write)\\s+(me\\s+)?(a\\s+)?(brief|short|quick|concise)\\s+(summary|overview)\\b/i, weight: 9 },\n { pattern: /\\bshorten\\s+(this|the)\\b/i, weight: 6 },\n { pattern: /\\bin\\s+(brief|short|a nutshell)\\b/i, weight: 7 },\n { pattern: /\\bkey\\s+(points?|takeaways?)\\b/i, weight: 8 },\n { pattern: /\\bmain\\s+(ideas?|points?)\\b/i, weight: 7 },\n ],\n\n analysis: [\n { pattern: /\\b(analyze|analyse|analysis|examine|investigate|assess|evaluate|study)\\b/i, weight: 8 },\n { pattern: /\\b(compare|contrast|differentiate|distinguish)\\b.{0,30}\\b(between|and)\\b/i, weight: 9 },\n { pattern: /\\b(pros?\\s+and\\s+cons?|advantages?\\s+and\\s+disadvantages?|strengths?\\s+and\\s+weaknesses?)\\b/i, weight: 9 },\n { pattern: /\\b(what\\s+are|explain)\\s+(the\\s+)?(implications?|consequences?|effects?|impacts?)\\b/i, weight: 8 },\n { pattern: /\\bbreak\\s*down\\b/i, weight: 6 },\n { pattern: /\\bdeep\\s*dive\\b/i, weight: 7 },\n { pattern: /\\bcritical(ly)?\\s+(analysis|evaluation|assessment)\\b/i, weight: 9 },\n ],\n\n creative_writing: [\n { pattern: /\\b(write|create|compose|craft|author)\\b.{0,30}\\b(story|poem|essay|article|blog|post|narrative|fiction|novel|song|lyrics)\\b/i, weight: 10 },\n { pattern: /\\b(creative|imaginative|fictional)\\s+(writing|story|piece)\\b/i, weight: 10 },\n { pattern: /\\bonce upon a time\\b/i, weight: 8 },\n { pattern: /\\b(write|tell)\\s+(me\\s+)?(a\\s+)?(short\\s+)?story\\b/i, weight: 9 },\n { pattern: /\\b(brainstorm|ideate)\\b.{0,30}\\b(ideas?|concepts?|themes?)\\b/i, weight: 7 },\n { pattern: /\\bwrite\\s+(in|like)\\s+(the\\s+)?style\\s+of\\b/i, weight: 8 },\n { pattern: /\\b(catchy|creative|engaging)\\s+(title|headline|tagline|slogan)\\b/i, weight: 7 },\n ],\n\n data_extraction: [\n { pattern: /\\b(extract|parse|pull|get|retrieve|find|identify)\\b.{0,30}\\b(data|information|details?|values?|fields?|entities?|names?|numbers?|dates?|emails?|phones?|addresses?)\\b/i, weight: 10 },\n { pattern: /\\b(convert|transform)\\b.{0,30}\\b(to|into)\\s+(json|csv|xml|yaml|table|structured)\\b/i, weight: 9 },\n { pattern: /\\bstructured\\s+(data|output|format)\\b/i, weight: 8 },\n { pattern: /\\bnamed\\s+entity\\s+(recognition|extraction)\\b/i, weight: 10 },\n { pattern: /\\b(scrape|crawl)\\b/i, weight: 6 },\n { pattern: /\\bjson\\s+(output|format|schema)\\b/i, weight: 7 },\n ],\n\n translation: [\n { pattern: /\\b(translate|translation|translator)\\b/i, weight: 10 },\n { pattern: /\\b(convert|change)\\b.{0,20}\\b(to|into)\\s+(english|spanish|french|german|chinese|japanese|korean|portuguese|italian|russian|arabic|hindi|dutch)\\b/i, weight: 9 },\n { pattern: /\\b(in|to)\\s+(english|spanish|french|german|chinese|japanese|korean|portuguese|italian|russian|arabic|hindi|dutch)\\b/i, weight: 6 },\n { pattern: /\\bfrom\\s+(english|spanish|french|german|chinese|japanese|korean|portuguese|italian|russian|arabic|hindi|dutch)\\s+to\\b/i, weight: 10 },\n { pattern: /\\blocalize|localization\\b/i, weight: 7 },\n ],\n\n question_answering: [\n { pattern: /^(what|who|where|when|why|how|which|is|are|does|do|can|could|would|should|will|did)\\s/i, weight: 7 },\n { pattern: /\\?$/i, weight: 5 },\n { pattern: /\\b(explain|describe|define|what\\s+is|what\\s+are|tell\\s+me\\s+about)\\b/i, weight: 8 },\n { pattern: /\\b(answer|respond|reply)\\b.{0,20}\\b(question|query)\\b/i, weight: 9 },\n { pattern: /\\bfaq\\b/i, weight: 8 },\n { pattern: /\\bi\\s+(want|need)\\s+to\\s+know\\b/i, weight: 6 },\n { pattern: /\\bcan\\s+you\\s+(tell|explain|help)\\b/i, weight: 5 },\n ],\n\n general: [\n // Catch-all patterns with low weights\n { pattern: /./i, weight: 1 },\n ],\n};\n\n/**\n * Infers the task type from a prompt.\n *\n * @param prompt - The user's prompt\n * @returns The inferred task type\n */\nexport function inferTaskType(prompt: string): TaskType {\n // Normalize the prompt\n const normalizedPrompt = prompt.trim().toLowerCase();\n\n // Score each task type\n const scores: Record<TaskType, number> = {\n code_generation: 0,\n code_review: 0,\n summarization: 0,\n analysis: 0,\n creative_writing: 0,\n data_extraction: 0,\n translation: 0,\n question_answering: 0,\n general: 0,\n };\n\n // Calculate scores\n for (const [taskType, patterns] of Object.entries(TASK_PATTERNS)) {\n for (const { pattern, weight } of patterns) {\n if (pattern.test(prompt)) {\n scores[taskType as TaskType] += weight;\n }\n }\n }\n\n // Find the highest scoring task type\n let maxScore = 0;\n let inferredType: TaskType = 'general';\n\n for (const [taskType, score] of Object.entries(scores)) {\n if (score > maxScore) {\n maxScore = score;\n inferredType = taskType as TaskType;\n }\n }\n\n // If the max score is very low, default to general\n if (maxScore <= 1) {\n return 'general';\n }\n\n return inferredType;\n}\n\n/**\n * Gets the confidence score for an inferred task type.\n *\n * @param prompt - The user's prompt\n * @param taskType - The task type to check confidence for\n * @returns Confidence score between 0 and 1\n */\nexport function getInferenceConfidence(prompt: string, taskType: TaskType): number {\n const patterns = TASK_PATTERNS[taskType];\n if (!patterns) return 0;\n\n let totalWeight = 0;\n let maxPossibleWeight = 0;\n\n for (const { pattern, weight } of patterns) {\n maxPossibleWeight += weight;\n if (pattern.test(prompt)) {\n totalWeight += weight;\n }\n }\n\n if (maxPossibleWeight === 0) return 0;\n\n // Normalize to 0-1 range, cap at 0.95 to show uncertainty\n return Math.min(totalWeight / maxPossibleWeight, 0.95);\n}\n\n/**\n * Gets all matching task types with their scores.\n *\n * @param prompt - The user's prompt\n * @returns Array of task types with scores, sorted by score descending\n */\nexport function getAllMatches(prompt: string): Array<{ taskType: TaskType; score: number; confidence: number }> {\n const scores: Record<TaskType, number> = {\n code_generation: 0,\n code_review: 0,\n summarization: 0,\n analysis: 0,\n creative_writing: 0,\n data_extraction: 0,\n translation: 0,\n question_answering: 0,\n general: 0,\n };\n\n // Calculate scores\n for (const [taskType, patterns] of Object.entries(TASK_PATTERNS)) {\n for (const { pattern, weight } of patterns) {\n if (pattern.test(prompt)) {\n scores[taskType as TaskType] += weight;\n }\n }\n }\n\n // Convert to array and sort\n const results = Object.entries(scores)\n .map(([taskType, score]) => ({\n taskType: taskType as TaskType,\n score,\n confidence: getInferenceConfidence(prompt, taskType as TaskType),\n }))\n .filter((r) => r.score > 0)\n .sort((a, b) => b.score - a.score);\n\n return results;\n}\n","/**\n * Routing Engine\n *\n * Manages routing rules and model selection for tasks.\n *\n * @packageDocumentation\n */\n\nimport type { Store } from '../storage/store.js';\nimport type { TaskType, RoutingRule, RuleSource } from '../types.js';\nimport { inferTaskType, getInferenceConfidence } from './inference.js';\n\n/**\n * Routing engine for managing model selection.\n */\nexport class RoutingEngine {\n private store: Store;\n\n /**\n * Creates a new RoutingEngine.\n *\n * @param store - The storage instance to use\n */\n constructor(store: Store) {\n this.store = store;\n }\n\n /**\n * Infers the task type from a prompt.\n *\n * @param prompt - The prompt to analyze\n * @returns The inferred task type\n */\n inferTaskType(prompt: string): TaskType {\n return inferTaskType(prompt);\n }\n\n /**\n * Gets the inference confidence for a task type.\n *\n * @param prompt - The prompt to analyze\n * @param taskType - The task type to check\n * @returns Confidence score (0-1)\n */\n getInferenceConfidence(prompt: string, taskType: TaskType): number {\n return getInferenceConfidence(prompt, taskType);\n }\n\n /**\n * Gets the routing rule for a task type.\n *\n * @param taskType - The task type to get the rule for\n * @returns The routing rule, or null if not found\n */\n get(taskType: TaskType): RoutingRule | null {\n const record = this.store.getRule(taskType);\n if (!record) return null;\n\n return {\n id: record.id,\n taskType: record.taskType,\n preferredModel: record.preferredModel,\n source: record.source,\n confidence: record.confidence ?? undefined,\n sampleCount: record.sampleCount ?? undefined,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n };\n }\n\n /**\n * Sets a routing rule for a task type.\n *\n * @param taskType - The task type to set the rule for\n * @param preferredModel - The preferred model (format: \"provider:model\")\n * @param source - How the rule was created\n * @param options - Optional confidence and sample count\n * @returns The rule ID\n */\n set(\n taskType: TaskType,\n preferredModel: string,\n source: RuleSource = 'user',\n options?: { confidence?: number; sampleCount?: number }\n ): string {\n return this.store.setRule(\n taskType,\n preferredModel,\n source,\n options?.confidence,\n options?.sampleCount\n );\n }\n\n /**\n * Lists all routing rules.\n *\n * @returns Array of all routing rules\n */\n list(): RoutingRule[] {\n const records = this.store.listRules();\n return records.map((record) => ({\n id: record.id,\n taskType: record.taskType,\n preferredModel: record.preferredModel,\n source: record.source,\n confidence: record.confidence ?? undefined,\n sampleCount: record.sampleCount ?? undefined,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n }));\n }\n\n /**\n * Deletes a routing rule and resets to default.\n *\n * @param taskType - The task type to reset\n * @returns True if the rule was reset\n */\n delete(taskType: TaskType): boolean {\n return this.store.deleteRule(taskType);\n }\n\n /**\n * Gets the preferred model for a task type.\n *\n * @param taskType - The task type\n * @returns The preferred model string, or a default\n */\n getPreferredModel(taskType: TaskType): string {\n const rule = this.get(taskType);\n return rule?.preferredModel ?? 'local:llama3.2';\n }\n\n /**\n * Parses a model string into provider and model name.\n *\n * @param modelString - The model string (format: \"provider:model\")\n * @returns Object with provider and model\n */\n parseModel(modelString: string): { provider: string; model: string } {\n const parts = modelString.split(':');\n if (parts.length < 2) {\n return { provider: 'local', model: modelString };\n }\n return { provider: parts[0]!, model: parts.slice(1).join(':') };\n }\n\n /**\n * Resolves the model to use for a prompt.\n *\n * @param prompt - The prompt to analyze\n * @param overrideTaskType - Optional task type override\n * @param overrideModel - Optional model override\n * @returns Object with resolved taskType, model, provider, and confidence\n */\n resolve(\n prompt: string,\n overrideTaskType?: TaskType,\n overrideModel?: string\n ): {\n taskType: TaskType;\n model: string;\n provider: string;\n modelName: string;\n confidence: number;\n } {\n // Determine task type\n const taskType = overrideTaskType ?? this.inferTaskType(prompt);\n const confidence = this.getInferenceConfidence(prompt, taskType);\n\n // Determine model\n let model: string;\n if (overrideModel) {\n model = overrideModel;\n } else {\n model = this.getPreferredModel(taskType);\n }\n\n const { provider, model: modelName } = this.parseModel(model);\n\n return {\n taskType,\n model,\n provider,\n modelName,\n confidence,\n };\n }\n}\n","/**\n * Outcome Recording\n *\n * Handles recording and processing of run outcomes.\n *\n * @packageDocumentation\n */\n\nimport type { Store } from '../storage/store.js';\nimport type { OutcomeInput, Outcome, OutcomeRecord } from '../types.js';\n\n/**\n * Outcome recorder for processing user feedback.\n */\nexport class OutcomeRecorder {\n private store: Store;\n\n /**\n * Creates a new OutcomeRecorder.\n *\n * @param store - The storage instance to use\n */\n constructor(store: Store) {\n this.store = store;\n }\n\n /**\n * Records an outcome for a run.\n *\n * @param input - The outcome input\n * @returns The recorded outcome\n * @throws If the run ID is not found\n */\n record(input: OutcomeInput): Outcome {\n // Verify the run exists\n const run = this.store.getRun(input.runId);\n if (!run) {\n throw new Error(`Run not found: ${input.runId}`);\n }\n\n // Record the outcome\n const id = this.store.recordOutcome({\n runId: input.runId,\n success: input.success,\n quality: input.quality ?? null,\n latencySatisfactory: input.latencySatisfactory ?? null,\n costSatisfactory: input.costSatisfactory ?? null,\n feedback: input.feedback ?? null,\n });\n\n // Get the recorded outcome\n const outcome = this.store.getOutcome(input.runId);\n if (!outcome) {\n throw new Error('Failed to record outcome');\n }\n\n return {\n id: outcome.id,\n runId: outcome.runId,\n success: outcome.success,\n quality: outcome.quality ?? undefined,\n latencySatisfactory: outcome.latencySatisfactory ?? undefined,\n costSatisfactory: outcome.costSatisfactory ?? undefined,\n feedback: outcome.feedback ?? undefined,\n recordedAt: outcome.createdAt,\n };\n }\n\n /**\n * Gets an outcome for a run.\n *\n * @param runId - The run ID\n * @returns The outcome, or null if not found\n */\n get(runId: string): Outcome | null {\n const outcome = this.store.getOutcome(runId);\n if (!outcome) return null;\n\n return {\n id: outcome.id,\n runId: outcome.runId,\n success: outcome.success,\n quality: outcome.quality ?? undefined,\n latencySatisfactory: outcome.latencySatisfactory ?? undefined,\n costSatisfactory: outcome.costSatisfactory ?? undefined,\n feedback: outcome.feedback ?? undefined,\n recordedAt: outcome.createdAt,\n };\n }\n\n /**\n * Gets outcome statistics for a task type.\n *\n * @param taskType - The task type to get stats for\n * @returns Outcome statistics\n */\n getTaskStats(taskType: string): {\n totalOutcomes: number;\n successRate: number;\n qualityDistribution: Record<string, number>;\n latencySatisfactionRate: number;\n costSatisfactionRate: number;\n } {\n const outcomes = this.store.getOutcomes({ taskType: taskType as any, limit: 1000 });\n\n if (outcomes.length === 0) {\n return {\n totalOutcomes: 0,\n successRate: 0,\n qualityDistribution: {},\n latencySatisfactionRate: 0,\n costSatisfactionRate: 0,\n };\n }\n\n // Calculate statistics\n let successCount = 0;\n let latencySatisfiedCount = 0;\n let latencyRatedCount = 0;\n let costSatisfiedCount = 0;\n let costRatedCount = 0;\n const qualityDistribution: Record<string, number> = {};\n\n for (const outcome of outcomes) {\n if (outcome.success) successCount++;\n\n if (outcome.quality) {\n qualityDistribution[outcome.quality] = (qualityDistribution[outcome.quality] ?? 0) + 1;\n }\n\n if (outcome.latencySatisfactory != null) {\n latencyRatedCount++;\n if (outcome.latencySatisfactory) latencySatisfiedCount++;\n }\n\n if (outcome.costSatisfactory != null) {\n costRatedCount++;\n if (outcome.costSatisfactory) costSatisfiedCount++;\n }\n }\n\n return {\n totalOutcomes: outcomes.length,\n successRate: successCount / outcomes.length,\n qualityDistribution,\n latencySatisfactionRate: latencyRatedCount > 0 ? latencySatisfiedCount / latencyRatedCount : 0,\n costSatisfactionRate: costRatedCount > 0 ? costSatisfiedCount / costRatedCount : 0,\n };\n }\n}\n","/**\n * Savings Calculator\n *\n * Calculates cost savings from intelligent model routing vs a baseline (all-Opus).\n *\n * @packageDocumentation\n */\n\nimport type { Store } from '../storage/store.js';\n\n/**\n * Model pricing in USD per 1M tokens.\n */\nexport const MODEL_PRICING: Record<string, { input: number; output: number }> = {\n // Anthropic models\n 'claude-3-5-haiku-latest': { input: 0.25, output: 1.25 },\n 'claude-3-5-haiku-20241022': { input: 0.25, output: 1.25 },\n 'claude-3-5-sonnet-latest': { input: 3, output: 15 },\n 'claude-3-5-sonnet-20241022': { input: 3, output: 15 },\n 'claude-sonnet-4-20250514': { input: 3, output: 15 },\n 'claude-3-opus-latest': { input: 15, output: 75 },\n 'claude-3-opus-20240229': { input: 15, output: 75 },\n 'claude-opus-4-5-20250514': { input: 15, output: 75 },\n // OpenAI models\n 'gpt-4o': { input: 2.5, output: 10 },\n 'gpt-4o-mini': { input: 0.15, output: 0.6 },\n 'gpt-4.1': { input: 2, output: 8 },\n 'gpt-4-turbo': { input: 10, output: 30 },\n // Google models\n 'gemini-1.5-flash': { input: 0.075, output: 0.3 },\n 'gemini-1.5-pro': { input: 1.25, output: 5 },\n 'gemini-2.0-flash': { input: 0.1, output: 0.4 },\n // xAI models\n 'grok-2': { input: 2, output: 10 },\n 'grok-2-latest': { input: 2, output: 10 },\n // Moonshot models\n 'moonshot-v1-8k': { input: 0.1, output: 0.1 },\n 'moonshot-v1-32k': { input: 0.2, output: 0.2 },\n};\n\n/**\n * Baseline model for savings comparison (most expensive).\n */\nexport const BASELINE_MODEL = 'claude-3-opus-latest';\n\n/**\n * Model cost breakdown.\n */\nexport interface ModelCostBreakdown {\n runs: number;\n tokensIn: number;\n tokensOut: number;\n cost: number;\n successRate: number;\n avgLatencyMs: number;\n}\n\n/**\n * Savings report structure.\n */\nexport interface SavingsReport {\n /** Number of days included in the report */\n periodDays: number;\n /** Date range */\n period: {\n from: string;\n to: string;\n };\n /** Total number of runs */\n totalRuns: number;\n /** Total tokens used */\n totalTokensIn: number;\n totalTokensOut: number;\n /** Actual cost incurred */\n actualCost: number;\n /** Cost if all calls went to baseline model (Opus) */\n baselineCost: number;\n /** Total savings */\n savings: number;\n /** Savings as percentage */\n savingsPercent: number;\n /** Cost breakdown by model */\n byModel: Record<string, ModelCostBreakdown>;\n /** Cost breakdown by task type */\n byTaskType: Record<string, { runs: number; cost: number; avgCostPerRun: number }>;\n}\n\n/**\n * Calculate cost for a specific model and token counts.\n */\nexport function calculateCost(\n model: string,\n tokensIn: number,\n tokensOut: number\n): number {\n // Extract model name from provider:model format\n const modelName = model.includes(':') ? model.split(':')[1] : model;\n \n // Find pricing, with fallback to default\n const pricing = MODEL_PRICING[modelName as keyof typeof MODEL_PRICING] ??\n MODEL_PRICING[model as keyof typeof MODEL_PRICING] ??\n { input: 1, output: 3 }; // Default fallback pricing\n\n const inputCost = (tokensIn / 1_000_000) * pricing.input;\n const outputCost = (tokensOut / 1_000_000) * pricing.output;\n\n return inputCost + outputCost;\n}\n\n/**\n * Get pricing for a model.\n */\nexport function getModelPricing(model: string): { input: number; output: number } | null {\n const modelName = model.includes(':') ? model.split(':')[1] : model;\n return MODEL_PRICING[modelName as keyof typeof MODEL_PRICING] ??\n MODEL_PRICING[model as keyof typeof MODEL_PRICING] ??\n null;\n}\n\n/**\n * Calculate savings report from stored runs.\n */\nexport function calculateSavings(store: Store, days: number = 30): SavingsReport {\n // Calculate date range\n const to = new Date();\n const from = new Date();\n from.setDate(from.getDate() - days);\n\n const fromStr = from.toISOString();\n const toStr = to.toISOString();\n\n // Get all runs in the period\n const runs = store.getRuns({\n from: fromStr,\n to: toStr,\n limit: 100000, // Get all runs\n });\n\n // Initialize aggregation\n const byModel: Record<string, ModelCostBreakdown> = {};\n const byTaskType: Record<string, { runs: number; cost: number; totalCost: number }> = {};\n \n let totalTokensIn = 0;\n let totalTokensOut = 0;\n let actualCost = 0;\n let baselineCost = 0;\n\n const baselinePricing = MODEL_PRICING[BASELINE_MODEL] ?? { input: 15, output: 75 };\n\n for (const run of runs) {\n const tokensIn = run.tokensIn ?? 0;\n const tokensOut = run.tokensOut ?? 0;\n const modelName = run.model.includes(':') ? run.model.split(':')[1] ?? run.model : run.model;\n\n // Calculate actual cost for this run\n const runCost = calculateCost(run.model, tokensIn, tokensOut);\n actualCost += runCost;\n\n // Calculate baseline cost (if this run used Opus)\n const baselineRunCost = (tokensIn / 1_000_000) * (baselinePricing?.input ?? 15) +\n (tokensOut / 1_000_000) * (baselinePricing?.output ?? 75);\n baselineCost += baselineRunCost;\n\n // Aggregate totals\n totalTokensIn += tokensIn;\n totalTokensOut += tokensOut;\n\n // Aggregate by model\n if (!byModel[modelName]) {\n byModel[modelName] = {\n runs: 0,\n tokensIn: 0,\n tokensOut: 0,\n cost: 0,\n successRate: 0,\n avgLatencyMs: 0,\n };\n }\n const modelStats = byModel[modelName]!;\n modelStats.runs++;\n modelStats.tokensIn += tokensIn;\n modelStats.tokensOut += tokensOut;\n modelStats.cost += runCost;\n modelStats.avgLatencyMs += run.durationMs;\n if (run.success) {\n modelStats.successRate++;\n }\n\n // Aggregate by task type\n if (!byTaskType[run.taskType]) {\n byTaskType[run.taskType] = { runs: 0, cost: 0, totalCost: 0 };\n }\n const taskStats = byTaskType[run.taskType]!;\n taskStats.runs++;\n taskStats.totalCost += runCost;\n }\n\n // Finalize model stats (calculate averages)\n for (const model of Object.keys(byModel)) {\n const stats = byModel[model]!;\n stats.successRate = stats.runs > 0 ? stats.successRate / stats.runs : 0;\n stats.avgLatencyMs = stats.runs > 0 ? stats.avgLatencyMs / stats.runs : 0;\n }\n\n // Finalize task type stats\n const byTaskTypeFinal: Record<string, { runs: number; cost: number; avgCostPerRun: number }> = {};\n for (const [taskType, stats] of Object.entries(byTaskType)) {\n byTaskTypeFinal[taskType] = {\n runs: stats.runs,\n cost: stats.totalCost,\n avgCostPerRun: stats.runs > 0 ? stats.totalCost / stats.runs : 0,\n };\n }\n\n // Calculate savings\n const savings = baselineCost - actualCost;\n const savingsPercent = baselineCost > 0 ? (savings / baselineCost) * 100 : 0;\n\n return {\n periodDays: days,\n period: {\n from: fromStr,\n to: toStr,\n },\n totalRuns: runs.length,\n totalTokensIn,\n totalTokensOut,\n actualCost,\n baselineCost,\n savings: Math.max(0, savings), // Don't report negative savings\n savingsPercent: Math.max(0, savingsPercent),\n byModel,\n byTaskType: byTaskTypeFinal,\n };\n}\n\n/**\n * Format currency for display.\n */\nexport function formatCurrency(amount: number): string {\n if (amount < 0.01) {\n return `$${amount.toFixed(4)}`;\n }\n return `$${amount.toFixed(2)}`;\n}\n\n/**\n * Format token count for display.\n */\nexport function formatTokens(count: number): string {\n if (count >= 1_000_000) {\n return `${(count / 1_000_000).toFixed(1)}M`;\n }\n if (count >= 1_000) {\n return `${(count / 1_000).toFixed(1)}K`;\n }\n return String(count);\n}\n","/**\n * Pattern Detection\n *\n * Analyzes run history to detect patterns and generate suggestions.\n *\n * @packageDocumentation\n */\n\nimport type { Store } from '../storage/store.js';\nimport type { TaskType, Suggestion } from '../types.js';\nimport { nanoid } from 'nanoid';\nimport { calculateCost, MODEL_PRICING } from './savings.js';\n\n/**\n * Minimum number of runs required to generate a suggestion.\n */\nconst MIN_RUNS_FOR_SUGGESTION = 10;\n\n/**\n * Minimum confidence threshold for suggestions.\n */\nconst MIN_CONFIDENCE_THRESHOLD = 0.6;\n\n/**\n * Minimum improvement threshold to suggest a change (e.g., 10% better).\n */\nconst MIN_IMPROVEMENT_THRESHOLD = 0.1;\n\n/**\n * Minimum cost savings threshold to suggest a cheaper model (20% cost reduction).\n */\nconst MIN_COST_IMPROVEMENT_THRESHOLD = 0.2;\n\n/**\n * Pattern detection engine for learning from outcomes.\n */\nexport class PatternDetector {\n private store: Store;\n\n /**\n * Creates a new PatternDetector.\n *\n * @param store - The storage instance to use\n */\n constructor(store: Store) {\n this.store = store;\n }\n\n /**\n * Analyzes a task type and generates suggestions if appropriate.\n *\n * @param taskType - The task type to analyze\n * @returns Array of suggestions\n */\n analyzeTaskType(taskType: TaskType): Suggestion[] {\n const stats = this.store.getLearningStats(taskType);\n\n if (stats.length < 2) {\n // Need at least 2 models to compare\n return [];\n }\n\n // Get the current routing rule\n const currentRule = this.store.getRule(taskType);\n if (!currentRule) return [];\n\n const currentModel = currentRule.preferredModel;\n\n // Find the current model's stats\n const currentStats = stats.find((s) => s.model === currentModel);\n if (!currentStats) return [];\n\n // Get pricing for current model\n const currentModelName = currentModel.includes(':') ? currentModel.split(':')[1] : currentModel;\n const currentPricing = MODEL_PRICING[currentModelName as keyof typeof MODEL_PRICING];\n\n // Find better performing models\n const suggestions: Suggestion[] = [];\n\n for (const modelStats of stats) {\n if (modelStats.model === currentModel) continue;\n if (modelStats.runs < MIN_RUNS_FOR_SUGGESTION) continue;\n\n // Calculate improvement potential\n const successImprovement = modelStats.outcomeSuccessRate - currentStats.outcomeSuccessRate;\n const latencyImprovement = (currentStats.avgDurationMs - modelStats.avgDurationMs) / currentStats.avgDurationMs;\n\n // Calculate cost improvement\n const suggestedModelName = modelStats.model.includes(':') \n ? modelStats.model.split(':')[1] \n : modelStats.model;\n const suggestedPricing = MODEL_PRICING[suggestedModelName as keyof typeof MODEL_PRICING];\n \n let costImprovement = 0;\n if (currentPricing && suggestedPricing) {\n // Use average of input/output pricing for comparison\n const currentAvgCost = (currentPricing.input + currentPricing.output) / 2;\n const suggestedAvgCost = (suggestedPricing.input + suggestedPricing.output) / 2;\n costImprovement = (currentAvgCost - suggestedAvgCost) / currentAvgCost;\n }\n\n // Check if this model is significantly better\n // Better = higher success OR faster OR cheaper (with acceptable success rate)\n const isSignificantlyBetter =\n successImprovement > MIN_IMPROVEMENT_THRESHOLD ||\n (successImprovement >= 0 && latencyImprovement > MIN_IMPROVEMENT_THRESHOLD) ||\n (successImprovement >= -0.05 && costImprovement > MIN_COST_IMPROVEMENT_THRESHOLD); // Allow 5% worse success for 20%+ cost savings\n\n if (!isSignificantlyBetter) continue;\n\n // Calculate confidence based on sample size and improvement magnitude\n const sampleConfidence = Math.min(modelStats.runs / 50, 1); // Max confidence at 50 runs\n const improvementConfidence = Math.min(\n Math.abs(successImprovement) / 0.3 + \n Math.abs(latencyImprovement) / 0.5 +\n Math.abs(costImprovement) / 0.5,\n 1\n );\n const confidence = (sampleConfidence + improvementConfidence) / 2;\n\n if (confidence < MIN_CONFIDENCE_THRESHOLD) continue;\n\n // Generate reason\n const reasons: string[] = [];\n if (successImprovement > 0) {\n reasons.push(`${(successImprovement * 100).toFixed(0)}% higher success rate`);\n }\n if (latencyImprovement > 0) {\n reasons.push(`${(latencyImprovement * 100).toFixed(0)}% faster`);\n }\n if (costImprovement > 0) {\n reasons.push(`${(costImprovement * 100).toFixed(0)}% cheaper`);\n }\n\n const suggestion: Suggestion = {\n id: nanoid(),\n taskType,\n currentModel,\n suggestedModel: modelStats.model,\n reason: reasons.join(', '),\n confidence,\n expectedImprovement: {\n successRate: successImprovement > 0 ? successImprovement : undefined,\n latency: latencyImprovement > 0 ? latencyImprovement : undefined,\n cost: costImprovement > 0 ? costImprovement : undefined,\n },\n sampleCount: modelStats.runs,\n createdAt: new Date().toISOString(),\n };\n\n suggestions.push(suggestion);\n }\n\n // Sort by confidence descending\n suggestions.sort((a, b) => b.confidence - a.confidence);\n\n return suggestions;\n }\n\n /**\n * Analyzes all task types and generates suggestions.\n *\n * @returns Array of all suggestions across task types\n */\n analyzeAll(): Suggestion[] {\n const taskTypes: TaskType[] = [\n 'code_generation',\n 'code_review',\n 'summarization',\n 'analysis',\n 'creative_writing',\n 'data_extraction',\n 'translation',\n 'question_answering',\n 'general',\n ];\n\n const allSuggestions: Suggestion[] = [];\n\n for (const taskType of taskTypes) {\n const suggestions = this.analyzeTaskType(taskType);\n allSuggestions.push(...suggestions);\n }\n\n // Sort by confidence descending\n allSuggestions.sort((a, b) => b.confidence - a.confidence);\n\n return allSuggestions;\n }\n\n /**\n * Stores suggestions in the database.\n *\n * @param suggestions - The suggestions to store\n * @returns Array of suggestion IDs\n */\n storeSuggestions(suggestions: Suggestion[]): string[] {\n const ids: string[] = [];\n\n for (const suggestion of suggestions) {\n const id = this.store.recordSuggestion({\n taskType: suggestion.taskType,\n currentModel: suggestion.currentModel,\n suggestedModel: suggestion.suggestedModel,\n reason: suggestion.reason,\n confidence: suggestion.confidence,\n expectedImprovement: JSON.stringify(suggestion.expectedImprovement),\n sampleCount: suggestion.sampleCount,\n accepted: null,\n });\n ids.push(id);\n }\n\n return ids;\n }\n\n /**\n * Generates and stores new suggestions, returning only new ones.\n *\n * @returns Array of new suggestions\n */\n generateSuggestions(): Suggestion[] {\n const suggestions = this.analyzeAll();\n\n // Filter out suggestions that already exist (same task type + suggested model)\n const pending = this.store.getPendingSuggestions();\n const existingKeys = new Set(\n pending.map((s) => `${s.taskType}:${s.suggestedModel}`)\n );\n\n const newSuggestions = suggestions.filter(\n (s) => !existingKeys.has(`${s.taskType}:${s.suggestedModel}`)\n );\n\n // Store new suggestions\n this.storeSuggestions(newSuggestions);\n\n return newSuggestions;\n }\n}\n","/**\n * RelayPlane Main Class\n *\n * The main entry point for the agent optimization layer.\n *\n * @packageDocumentation\n */\n\nimport { Store, getDefaultDbPath } from './storage/index.js';\nimport { RoutingEngine } from './routing/index.js';\nimport { OutcomeRecorder } from './learning/outcomes.js';\nimport { PatternDetector } from './learning/patterns.js';\nimport { calculateCost, calculateSavings, type SavingsReport } from './learning/savings.js';\nimport type {\n RelayPlaneConfig,\n RunInput,\n RunResult,\n OutcomeInput,\n Outcome,\n Stats,\n Suggestion,\n TaskType,\n Provider,\n ProviderConfig,\n} from './types.js';\n\n// Type-only import for adapters to avoid runtime dependency if not used\ntype ModelAdapter = {\n execute(args: {\n model: string;\n input: any;\n apiKey: string;\n baseUrl?: string;\n }): Promise<{\n success: boolean;\n output?: any;\n error?: { message: string };\n durationMs: number;\n tokensIn?: number;\n tokensOut?: number;\n }>;\n};\n\n/**\n * RelayPlane - Agent Optimization Layer\n *\n * Provides intelligent routing, outcome tracking, and learning for AI model selection.\n *\n * @example Basic usage\n * ```typescript\n * import { RelayPlane } from '@relayplane/core';\n *\n * const relay = new RelayPlane();\n *\n * // Run a task - automatically infers type and routes to best model\n * const result = await relay.run({\n * prompt: 'Review this code for bugs...',\n * });\n *\n * // Record the outcome for learning\n * await relay.recordOutcome(result.runId, { success: true, quality: 'good' });\n *\n * // Get suggestions for routing improvements\n * const suggestions = await relay.getSuggestions();\n * ```\n */\nexport class RelayPlane {\n private store: Store;\n private _routing: RoutingEngine;\n private outcomeRecorder: OutcomeRecorder;\n private patternDetector: PatternDetector;\n private config: RelayPlaneConfig;\n private adapterRegistry: any | null = null;\n\n /**\n * Creates a new RelayPlane instance.\n *\n * @param config - Configuration options\n */\n constructor(config: RelayPlaneConfig = {}) {\n this.config = {\n dbPath: config.dbPath ?? getDefaultDbPath(),\n defaultProvider: config.defaultProvider ?? 'local',\n defaultModel: config.defaultModel ?? 'llama3.2',\n providers: config.providers ?? {},\n };\n\n // Initialize storage\n this.store = new Store(this.config.dbPath);\n\n // Initialize components\n this._routing = new RoutingEngine(this.store);\n this.outcomeRecorder = new OutcomeRecorder(this.store);\n this.patternDetector = new PatternDetector(this.store);\n }\n\n /**\n * Gets the routing engine for direct access.\n */\n get routing(): RoutingEngine {\n return this._routing;\n }\n\n /**\n * Runs a prompt through the appropriate model.\n *\n * @param input - The run input\n * @returns The run result\n */\n async run(input: RunInput): Promise<RunResult> {\n const startTime = Date.now();\n\n // Resolve routing\n const resolved = this._routing.resolve(input.prompt, input.taskType, input.model);\n\n // Get the adapter\n const adapter = await this.getAdapter(resolved.provider as Provider);\n if (!adapter) {\n // No adapter available - record and return error\n const runId = this.store.recordRun({\n prompt: input.prompt,\n systemPrompt: input.systemPrompt ?? null,\n taskType: resolved.taskType,\n model: resolved.model,\n success: false,\n output: null,\n error: `No adapter configured for provider: ${resolved.provider}`,\n durationMs: Date.now() - startTime,\n tokensIn: null,\n tokensOut: null,\n costUsd: null,\n metadata: input.metadata ? JSON.stringify(input.metadata) : null,\n });\n\n return {\n runId,\n success: false,\n error: `No adapter configured for provider: ${resolved.provider}`,\n taskType: resolved.taskType,\n model: resolved.model,\n durationMs: Date.now() - startTime,\n timestamp: new Date().toISOString(),\n };\n }\n\n // Get API key for the provider\n const providerConfig = this.config.providers?.[resolved.provider as Provider];\n const apiKey = providerConfig?.apiKey ?? this.getEnvApiKey(resolved.provider as Provider);\n\n // Build the full prompt\n const fullInput = input.systemPrompt\n ? `${input.systemPrompt}\\n\\n${input.prompt}`\n : input.prompt;\n\n // Execute the adapter\n const result = await adapter.execute({\n model: resolved.modelName,\n input: fullInput,\n apiKey: apiKey ?? '',\n baseUrl: providerConfig?.baseUrl,\n });\n\n const durationMs = Date.now() - startTime;\n\n // Calculate cost based on tokens\n const tokensIn = result.tokensIn ?? 0;\n const tokensOut = result.tokensOut ?? 0;\n const costUsd = calculateCost(resolved.model, tokensIn, tokensOut);\n\n // Record the run\n const runId = this.store.recordRun({\n prompt: input.prompt,\n systemPrompt: input.systemPrompt ?? null,\n taskType: resolved.taskType,\n model: resolved.model,\n success: result.success,\n output: result.output ?? null,\n error: result.error?.message ?? null,\n durationMs,\n tokensIn: result.tokensIn ?? null,\n tokensOut: result.tokensOut ?? null,\n costUsd: costUsd > 0 ? costUsd : null,\n metadata: input.metadata ? JSON.stringify(input.metadata) : null,\n });\n\n return {\n runId,\n success: result.success,\n output: result.output,\n error: result.error?.message,\n taskType: resolved.taskType,\n model: resolved.model,\n durationMs,\n tokensIn: result.tokensIn,\n tokensOut: result.tokensOut,\n timestamp: new Date().toISOString(),\n };\n }\n\n /**\n * Gets an adapter for a provider.\n * Note: In the standalone proxy package, adapters are not used.\n * The proxy handles provider calls directly via HTTP.\n */\n private async getAdapter(_provider: Provider): Promise<ModelAdapter | null> {\n // Adapters not available in standalone proxy package\n // The proxy handles all provider calls directly\n return null;\n }\n\n /**\n * Gets an API key from environment variables.\n */\n private getEnvApiKey(provider: Provider): string | undefined {\n const envVars: Record<Provider, string> = {\n openai: 'OPENAI_API_KEY',\n anthropic: 'ANTHROPIC_API_KEY',\n google: 'GOOGLE_API_KEY',\n xai: 'XAI_API_KEY',\n moonshot: 'MOONSHOT_API_KEY',\n local: '',\n };\n\n const envVar = envVars[provider];\n return envVar ? process.env[envVar] : undefined;\n }\n\n /**\n * Records an outcome for a run.\n *\n * @param runId - The run ID\n * @param outcome - The outcome details\n * @returns The recorded outcome\n */\n recordOutcome(runId: string, outcome: Omit<OutcomeInput, 'runId'>): Outcome {\n return this.outcomeRecorder.record({\n runId,\n ...outcome,\n });\n }\n\n /**\n * Gets an outcome for a run.\n *\n * @param runId - The run ID\n * @returns The outcome, or null if not found\n */\n getOutcome(runId: string): Outcome | null {\n return this.outcomeRecorder.get(runId);\n }\n\n /**\n * Gets statistics for runs.\n *\n * @param options - Optional filters\n * @returns Statistics object\n */\n stats(options?: { from?: string; to?: string }): Stats {\n const raw = this.store.getStats(options);\n\n // Build stats by task type\n const byTaskType: Stats['byTaskType'] = {} as Stats['byTaskType'];\n const taskTypes: TaskType[] = [\n 'code_generation',\n 'code_review',\n 'summarization',\n 'analysis',\n 'creative_writing',\n 'data_extraction',\n 'translation',\n 'question_answering',\n 'general',\n ];\n\n for (const taskType of taskTypes) {\n const taskStats = raw.byTaskType[taskType];\n byTaskType[taskType] = {\n taskType,\n totalRuns: taskStats?.runs ?? 0,\n successfulRuns: Math.round((taskStats?.runs ?? 0) * (taskStats?.successRate ?? 0)),\n successRate: taskStats?.successRate ?? 0,\n avgDurationMs: taskStats?.avgDurationMs ?? 0,\n byModel: {},\n };\n }\n\n // Add model breakdown\n for (const [model, modelStats] of Object.entries(raw.byModel)) {\n // Find which task type this model belongs to (simplified - assumes model is used for one task type)\n // In a real implementation, we'd query runs grouped by task type AND model\n for (const taskType of taskTypes) {\n if (!byTaskType[taskType].byModel[model]) {\n byTaskType[taskType].byModel[model] = {\n runs: 0,\n successRate: 0,\n avgDurationMs: 0,\n };\n }\n }\n }\n\n return {\n totalRuns: raw.totalRuns,\n overallSuccessRate: raw.totalRuns > 0 ? raw.successfulRuns / raw.totalRuns : 0,\n byTaskType,\n period: {\n from: options?.from ?? '',\n to: options?.to ?? new Date().toISOString(),\n },\n };\n }\n\n /**\n * Gets a savings report.\n *\n * @param days - Number of days to include (default: 30)\n * @returns Savings report\n */\n savingsReport(days: number = 30): SavingsReport {\n return calculateSavings(this.store, days);\n }\n\n /**\n * Gets routing improvement suggestions.\n *\n * @returns Array of suggestions\n */\n getSuggestions(): Suggestion[] {\n // Get pending suggestions from the database\n const pending = this.store.getPendingSuggestions();\n\n return pending.map((record) => ({\n id: record.id,\n taskType: record.taskType,\n currentModel: record.currentModel,\n suggestedModel: record.suggestedModel,\n reason: record.reason,\n confidence: record.confidence,\n expectedImprovement: JSON.parse(record.expectedImprovement),\n sampleCount: record.sampleCount,\n createdAt: record.createdAt,\n accepted: record.accepted ?? undefined,\n acceptedAt: record.acceptedAt ?? undefined,\n }));\n }\n\n /**\n * Generates new suggestions based on current data.\n *\n * @returns Array of newly generated suggestions\n */\n generateSuggestions(): Suggestion[] {\n return this.patternDetector.generateSuggestions();\n }\n\n /**\n * Accepts a suggestion and updates routing.\n *\n * @param suggestionId - The suggestion ID to accept\n * @returns True if successful\n */\n acceptSuggestion(suggestionId: string): boolean {\n return this.store.acceptSuggestion(suggestionId);\n }\n\n /**\n * Rejects a suggestion.\n *\n * @param suggestionId - The suggestion ID to reject\n * @returns True if successful\n */\n rejectSuggestion(suggestionId: string): boolean {\n return this.store.rejectSuggestion(suggestionId);\n }\n\n /**\n * Closes the RelayPlane instance and releases resources.\n */\n close(): void {\n this.store.close();\n }\n}\n","#!/usr/bin/env node\n/**\n * RelayPlane Proxy CLI\n * \n * Intelligent AI model routing proxy server.\n * \n * Usage:\n * npx @relayplane/proxy [options]\n * relayplane-proxy [options]\n * \n * Options:\n * --port <number> Port to listen on (default: 3001)\n * --host <string> Host to bind to (default: 127.0.0.1)\n * -v, --verbose Enable verbose logging\n * -h, --help Show this help message\n * \n * Environment Variables:\n * ANTHROPIC_API_KEY Anthropic API key\n * OPENAI_API_KEY OpenAI API key\n * GEMINI_API_KEY Google Gemini API key\n * XAI_API_KEY xAI/Grok API key\n * MOONSHOT_API_KEY Moonshot API key\n * \n * @packageDocumentation\n */\n\nimport { startProxy } from './proxy.js';\n\nfunction printHelp(): void {\n console.log(`\nRelayPlane Proxy - Intelligent AI Model Routing\n\nUsage:\n npx @relayplane/proxy [options]\n relayplane-proxy [options]\n\nOptions:\n --port <number> Port to listen on (default: 3001)\n --host <string> Host to bind to (default: 127.0.0.1)\n -v, --verbose Enable verbose logging\n -h, --help Show this help message\n\nEnvironment Variables:\n ANTHROPIC_API_KEY Anthropic API key\n OPENAI_API_KEY OpenAI API key\n GEMINI_API_KEY Google Gemini API key (optional)\n XAI_API_KEY xAI/Grok API key (optional)\n MOONSHOT_API_KEY Moonshot API key (optional)\n\nExample:\n # Start proxy on default port\n npx @relayplane/proxy\n\n # Start on custom port with verbose logging\n npx @relayplane/proxy --port 8080 -v\n\n # Then point your SDKs to the proxy\n export ANTHROPIC_BASE_URL=http://localhost:3001\n export OPENAI_BASE_URL=http://localhost:3001\n\nLearn more: https://relayplane.com/integrations/openclaw\n`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n // Check for help\n if (args.includes('-h') || args.includes('--help')) {\n printHelp();\n process.exit(0);\n }\n\n // Parse arguments\n let port = 3001;\n let host = '127.0.0.1';\n let verbose = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n \n if (arg === '--port' && args[i + 1]) {\n port = parseInt(args[i + 1]!, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error('Error: Invalid port number');\n process.exit(1);\n }\n i++;\n } else if (arg === '--host' && args[i + 1]) {\n host = args[i + 1]!;\n i++;\n } else if (arg === '-v' || arg === '--verbose') {\n verbose = true;\n }\n }\n\n // Check for at least one API key\n const hasAnthropicKey = !!process.env['ANTHROPIC_API_KEY'];\n const hasOpenAIKey = !!process.env['OPENAI_API_KEY'];\n const hasGeminiKey = !!process.env['GEMINI_API_KEY'];\n const hasXAIKey = !!process.env['XAI_API_KEY'];\n const hasMoonshotKey = !!process.env['MOONSHOT_API_KEY'];\n\n if (!hasAnthropicKey && !hasOpenAIKey && !hasGeminiKey && !hasXAIKey && !hasMoonshotKey) {\n console.error('Error: No API keys found. Set at least one of:');\n console.error(' ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, XAI_API_KEY, MOONSHOT_API_KEY');\n process.exit(1);\n }\n\n // Print startup info\n console.log('');\n console.log(' ╭─────────────────────────────────────────╮');\n console.log(' │ RelayPlane Proxy v0.1.0 │');\n console.log(' │ Intelligent AI Model Routing │');\n console.log(' ╰─────────────────────────────────────────╯');\n console.log('');\n console.log(' Providers:');\n if (hasAnthropicKey) console.log(' ✓ Anthropic');\n if (hasOpenAIKey) console.log(' ✓ OpenAI');\n if (hasGeminiKey) console.log(' ✓ Google Gemini');\n if (hasXAIKey) console.log(' ✓ xAI (Grok)');\n if (hasMoonshotKey) console.log(' ✓ Moonshot');\n console.log('');\n\n try {\n await startProxy({ port, host, verbose });\n \n console.log('');\n console.log(' To use, set these environment variables:');\n console.log(` export ANTHROPIC_BASE_URL=http://${host}:${port}`);\n console.log(` export OPENAI_BASE_URL=http://${host}:${port}`);\n console.log('');\n console.log(' Then run your agent (OpenClaw, Cursor, Aider, etc.)');\n console.log('');\n } catch (err) {\n console.error('Failed to start proxy:', err);\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":["crypto","Database","runId"]}
|