@wener/mcps 1.0.2 → 1.0.5
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 +144 -0
- package/dist/index.mjs +213076 -1
- package/dist/mcps-cli.mjs +102632 -59429
- package/lib/audit/AuditContract.js.map +1 -0
- package/lib/{chat/audit.js → audit/chat.js} +1 -1
- package/lib/audit/chat.js.map +1 -0
- package/lib/audit/entities/ChatRequestEntity.js.map +1 -0
- package/lib/audit/entities/McpRequestEntity.js.map +1 -0
- package/lib/audit/entities/RequestLogEntity.js.map +1 -0
- package/lib/audit/entities/ResponseEntity.js.map +1 -0
- package/lib/audit/entities/index.js +6 -0
- package/lib/audit/entities/index.js.map +1 -0
- package/lib/audit/server/db.js +64 -0
- package/lib/audit/server/db.js.map +1 -0
- package/lib/audit/server/index.js +2 -0
- package/lib/audit/server/index.js.map +1 -0
- package/lib/{server/audit.js → audit/server/plugin.js} +73 -127
- package/lib/audit/server/plugin.js.map +1 -0
- package/lib/audit/types.js.map +1 -0
- package/lib/chat/handler.js +5 -5
- package/lib/chat/handler.js.map +1 -1
- package/lib/chat/index.js +1 -1
- package/lib/chat/index.js.map +1 -1
- package/lib/cli-start.js +36 -0
- package/lib/cli-start.js.map +1 -0
- package/lib/cli.js +19 -0
- package/lib/cli.js.map +1 -0
- package/lib/contracts/index.js +1 -1
- package/lib/contracts/index.js.map +1 -1
- package/lib/dev.server.js +7 -1
- package/lib/dev.server.js.map +1 -1
- package/lib/entities/index.js +2 -10
- package/lib/entities/index.js.map +1 -1
- package/lib/index.js +21 -3
- package/lib/index.js.map +1 -1
- package/lib/mcps-cli.js +6 -35
- package/lib/mcps-cli.js.map +1 -1
- package/lib/providers/feishu/def.js +35 -0
- package/lib/providers/feishu/def.js.map +1 -0
- package/lib/providers/findMcpServerDef.js +1 -0
- package/lib/providers/findMcpServerDef.js.map +1 -1
- package/lib/scripts/bundle.js +7 -1
- package/lib/scripts/bundle.js.map +1 -1
- package/lib/server/api-routes.js +7 -8
- package/lib/server/api-routes.js.map +1 -1
- package/lib/server/events.js +13 -0
- package/lib/server/events.js.map +1 -0
- package/lib/server/mcp-routes.js +31 -60
- package/lib/server/mcp-routes.js.map +1 -1
- package/lib/server/mcps-router.js +19 -24
- package/lib/server/mcps-router.js.map +1 -1
- package/lib/server/schema.js +22 -2
- package/lib/server/schema.js.map +1 -1
- package/lib/server/server.js +142 -87
- package/lib/server/server.js.map +1 -1
- package/package.json +145 -85
- package/src/{chat/audit.ts → audit/chat.ts} +3 -3
- package/src/audit/entities/index.ts +6 -0
- package/src/audit/server/db.ts +65 -0
- package/src/audit/server/index.ts +8 -0
- package/src/{server/audit.ts → audit/server/plugin.ts} +71 -144
- package/src/chat/handler.ts +5 -5
- package/src/chat/index.ts +1 -1
- package/src/cli-start.ts +43 -0
- package/src/cli.ts +45 -0
- package/src/contracts/index.ts +1 -1
- package/src/dev.server.ts +8 -1
- package/src/entities/index.ts +2 -12
- package/src/index.ts +47 -1
- package/src/mcps-cli.ts +6 -48
- package/src/providers/feishu/def.ts +37 -0
- package/src/providers/findMcpServerDef.ts +1 -0
- package/src/scripts/bundle.ts +12 -1
- package/src/server/api-routes.ts +11 -8
- package/src/server/events.ts +29 -0
- package/src/server/mcp-routes.ts +30 -58
- package/src/server/mcps-router.ts +21 -29
- package/src/server/schema.ts +23 -2
- package/src/server/server.ts +149 -81
- package/LICENSE +0 -21
- package/lib/chat/audit.js.map +0 -1
- package/lib/contracts/AuditContract.js.map +0 -1
- package/lib/entities/ChatRequestEntity.js.map +0 -1
- package/lib/entities/McpRequestEntity.js.map +0 -1
- package/lib/entities/RequestLogEntity.js.map +0 -1
- package/lib/entities/ResponseEntity.js.map +0 -1
- package/lib/entities/types.js.map +0 -1
- package/lib/server/audit.js.map +0 -1
- package/lib/server/db.js +0 -97
- package/lib/server/db.js.map +0 -1
- package/src/server/db.ts +0 -115
- /package/lib/{contracts → audit}/AuditContract.js +0 -0
- /package/lib/{entities → audit/entities}/ChatRequestEntity.js +0 -0
- /package/lib/{entities → audit/entities}/McpRequestEntity.js +0 -0
- /package/lib/{entities → audit/entities}/RequestLogEntity.js +0 -0
- /package/lib/{entities → audit/entities}/ResponseEntity.js +0 -0
- /package/lib/{entities → audit}/types.js +0 -0
- /package/src/{contracts → audit}/AuditContract.ts +0 -0
- /package/src/{entities → audit/entities}/ChatRequestEntity.ts +0 -0
- /package/src/{entities → audit/entities}/McpRequestEntity.ts +0 -0
- /package/src/{entities → audit/entities}/RequestLogEntity.ts +0 -0
- /package/src/{entities → audit/entities}/ResponseEntity.ts +0 -0
- /package/src/{entities → audit}/types.ts +0 -0
package/lib/chat/handler.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/ import consola from "consola";
|
|
5
5
|
import { Hono } from "hono";
|
|
6
6
|
import { streamSSE } from "hono/streaming";
|
|
7
|
-
import { ChatProtocol, createAuditContext, extractClientIp } from "
|
|
7
|
+
import { ChatProtocol, createAuditContext, extractClientIp } from "../audit/chat.js";
|
|
8
8
|
import { openaiToAnthropicRequest, anthropicToOpenaiResponse, openaiToGeminiRequest, geminiToOpenaiResponse } from "./converters.js";
|
|
9
9
|
import { CreateChatCompletionRequestSchema, CreateResponseRequestSchema } from "@wener/ai/openai";
|
|
10
10
|
import { CreateMessageRequestSchema } from "@wener/ai/anthropic";
|
|
@@ -634,8 +634,8 @@ const log = consola.withTag("chat");
|
|
|
634
634
|
let previousContext = null;
|
|
635
635
|
if (request.previous_response_id) {
|
|
636
636
|
try {
|
|
637
|
-
const { isDbInitialized, getEntityManager } = await import("../server/db.js");
|
|
638
|
-
const { ResponseEntity } = await import("../entities/index.js");
|
|
637
|
+
const { isDbInitialized, getEntityManager } = await import("../audit/server/db.js");
|
|
638
|
+
const { ResponseEntity } = await import("../audit/entities/index.js");
|
|
639
639
|
if (isDbInitialized()) {
|
|
640
640
|
const em = getEntityManager().fork();
|
|
641
641
|
const prevResponse = await em.findOne(ResponseEntity, {
|
|
@@ -709,8 +709,8 @@ const log = consola.withTag("chat");
|
|
|
709
709
|
const result = chatCompletionsToResponses(chatResponse, request.model);
|
|
710
710
|
// Store response for future previous_response_id lookups
|
|
711
711
|
try {
|
|
712
|
-
const { isDbInitialized, getEntityManager } = await import("../server/db.js");
|
|
713
|
-
const { ResponseEntity } = await import("../entities/index.js");
|
|
712
|
+
const { isDbInitialized, getEntityManager } = await import("../audit/server/db.js");
|
|
713
|
+
const { ResponseEntity } = await import("../audit/entities/index.js");
|
|
714
714
|
if (isDbInitialized()) {
|
|
715
715
|
const em = getEntityManager().fork();
|
|
716
716
|
const responseEntity = new ResponseEntity();
|
package/lib/chat/handler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/chat/handler.ts"],"sourcesContent":["/**\n * Chat API Handler\n * Provides unified AI model gateway with protocol conversion\n */\nimport consola from 'consola';\nimport { Hono } from 'hono';\nimport { streamSSE } from 'hono/streaming';\nimport type { ChatConfig, ModelConfig } from '../server/schema';\nimport { ChatProtocol, createAuditContext, extractClientIp } from './audit';\nimport {\n\topenaiToAnthropicRequest,\n\tanthropicToOpenaiResponse,\n\topenaiToGeminiRequest,\n\tgeminiToOpenaiResponse,\n} from './converters';\nimport {\n\tCreateChatCompletionRequestSchema,\n\ttype CreateChatCompletionRequest,\n\tCreateResponseRequestSchema,\n\ttype CreateResponseRequest,\n} from '@wener/ai/openai';\nimport { CreateMessageRequestSchema } from '@wener/ai/anthropic';\nimport { CreateGenerateContentRequestSchema } from '@wener/ai/google';\n\nconst log = consola.withTag('chat');\n\nexport interface ChatHandlerOptions {\n\tconfig?: ChatConfig;\n}\n\n/**\n * Create chat handler Hono app\n */\nexport function createChatHandler(options: ChatHandlerOptions = {}) {\n\tconst app = new Hono();\n\tconst { config = {} } = options;\n\n\t/**\n\t * Resolve model configuration\n\t */\n\tfunction resolveModelConfig(modelName: string): ModelConfig | null {\n\t\tconst models = config.models;\n\t\tif (!models || models.length === 0) return null;\n\n\t\t// First pass: exact match\n\t\tfor (const modelConfig of models) {\n\t\t\tif (modelConfig.name === modelName) {\n\t\t\t\treturn modelConfig;\n\t\t\t}\n\t\t}\n\n\t\t// Second pass: wildcard matches (e.g., \"gpt-*\" or \"claude-*\")\n\t\tfor (const modelConfig of models) {\n\t\t\tconst pattern = modelConfig.name;\n\t\t\tif (pattern.includes('*')) {\n\t\t\t\tconst regex = new RegExp(`^${pattern.replace(/\\*/g, '.*')}$`);\n\t\t\t\tif (regex.test(modelName)) {\n\t\t\t\t\treturn modelConfig;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Make request to upstream provider\n\t */\n\tasync function makeUpstreamRequest(\n\t\turl: string,\n\t\tbody: unknown,\n\t\theaders: Record<string, string>,\n\t\t_stream: boolean = false,\n\t): Promise<Response> {\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t...headers,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text();\n\t\t\tlog.error('Upstream error:', response.status, errorText);\n\t\t\tthrow new Error(`Upstream error: ${response.status} ${errorText}`);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Normalize base URL - strip trailing /v1 if present\n\t * This allows baseUrl to be specified as either \"http://example.com\" or \"http://example.com/v1\"\n\t */\n\tfunction normalizeBaseUrl(url: string): string {\n\t\treturn url.replace(/\\/v1\\/?$/, '');\n\t}\n\n\t/**\n\t * Build headers for upstream request\n\t */\n\tfunction buildUpstreamHeaders(\n\t\tmodelConfig: ModelConfig,\n\t\tadapter: 'openai' | 'anthropic' | 'gemini',\n\t): Record<string, string> {\n\t\tconst headers: Record<string, string> = {};\n\n\t\t// Add API key if configured\n\t\tif (modelConfig.apiKey) {\n\t\t\tif (adapter === 'anthropic') {\n\t\t\t\theaders['x-api-key'] = modelConfig.apiKey;\n\t\t\t\theaders['anthropic-version'] = '2023-06-01';\n\t\t\t} else {\n\t\t\t\theaders.Authorization = `Bearer ${modelConfig.apiKey}`;\n\t\t\t}\n\t\t}\n\n\t\t// Add custom headers\n\t\tif (modelConfig.headers) {\n\t\t\tObject.assign(headers, modelConfig.headers);\n\t\t}\n\n\t\t// Add adapter-specific headers\n\t\tif (modelConfig.adapters?.[adapter]?.headers) {\n\t\t\tObject.assign(headers, modelConfig.adapters[adapter]?.headers);\n\t\t}\n\n\t\treturn headers;\n\t}\n\n\t/**\n\t * Normalize OpenAI request for different providers\n\t * Handles max_tokens/max_completion_tokens compatibility and thinking parameters\n\t */\n\tfunction normalizeOpenAIRequest(request: CreateChatCompletionRequest): Record<string, unknown> {\n\t\tconst normalized: Record<string, unknown> = { ...request };\n\n\t\t// Handle max_tokens vs max_completion_tokens compatibility\n\t\t// Some providers only support max_tokens, others prefer max_completion_tokens\n\t\tif (request.max_completion_tokens && !request.max_tokens) {\n\t\t\tnormalized.max_tokens = request.max_completion_tokens;\n\t\t}\n\n\t\t// Handle enable_thinking parameter (used by Qwen, DeepSeek thinking models)\n\t\t// Convert to thinking object format if needed\n\t\tif (request.enable_thinking !== undefined && !request.thinking) {\n\t\t\tnormalized.thinking = {\n\t\t\t\ttype: request.enable_thinking ? 'enabled' : 'disabled',\n\t\t\t};\n\t\t}\n\n\t\treturn normalized;\n\t}\n\n\t// =========================================================================\n\t// OpenAI Chat Completions API\n\t// =========================================================================\n\n\tapp.post('/v1/chat/completions', async (c) => {\n\t\t// Create audit context early\n\t\tlet auditCtx: ReturnType<typeof createAuditContext> | null = null;\n\n\t\ttry {\n\t\t\tconst body = await c.req.json();\n\t\t\tconst parseResult = CreateChatCompletionRequestSchema.safeParse(body);\n\n\t\t\tif (!parseResult.success) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: 'Invalid request',\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tparam: null,\n\t\t\t\t\t\t\tcode: 'invalid_request',\n\t\t\t\t\t\t\tdetails: parseResult.error.issues,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst request = parseResult.data;\n\t\t\tconst modelConfig = resolveModelConfig(request.model);\n\n\t\t\tif (!modelConfig) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: `Model ${request.model} not configured`,\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tparam: 'model',\n\t\t\t\t\t\t\tcode: 'model_not_found',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Determine upstream adapter\n\t\t\tconst adapter = modelConfig.adapter || 'openai';\n\t\t\tconst baseUrl = normalizeBaseUrl(\n\t\t\t\tmodelConfig.adapters?.[adapter]?.baseUrl || modelConfig.baseUrl || 'https://api.openai.com',\n\t\t\t);\n\n\t\t\t// Create audit context\n\t\t\tconst outputProtocol =\n\t\t\t\tadapter === 'anthropic'\n\t\t\t\t\t? ChatProtocol.ANTHROPIC\n\t\t\t\t\t: adapter === 'gemini'\n\t\t\t\t\t\t? ChatProtocol.GEMINI\n\t\t\t\t\t\t: ChatProtocol.OPENAI;\n\n\t\t\tauditCtx = createAuditContext({\n\t\t\t\tmethod: 'POST',\n\t\t\t\tendpoint: '/v1/chat/completions',\n\t\t\t\tmodel: request.model,\n\t\t\t\tinputProtocol: ChatProtocol.OPENAI,\n\t\t\t\toutputProtocol,\n\t\t\t\tstreaming: request.stream || false,\n\t\t\t\tclientIp: extractClientIp(c),\n\t\t\t\tuserAgent: c.req.header('user-agent'),\n\t\t\t\trequestMeta: {\n\t\t\t\t\ttemperature: request.temperature,\n\t\t\t\t\tmax_tokens: request.max_tokens || request.max_completion_tokens,\n\t\t\t\t\ttop_p: request.top_p,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Log incoming request\n\t\t\tlog.info(\n\t\t\t\t`→ POST /v1/chat/completions model=${request.model} stream=${request.stream || false} messages=${request.messages.length}`,\n\t\t\t);\n\n\t\t\t// Build upstream request based on protocol\n\t\t\tlet upstreamUrl: string;\n\t\t\tlet upstreamBody: unknown;\n\t\t\tlet upstreamHeaders: Record<string, string>;\n\n\t\t\tswitch (adapter) {\n\t\t\t\tcase 'anthropic': {\n\t\t\t\t\tupstreamUrl = `${baseUrl}/v1/messages`;\n\t\t\t\t\tupstreamBody = openaiToAnthropicRequest(request);\n\t\t\t\t\tupstreamHeaders = buildUpstreamHeaders(modelConfig, 'anthropic');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'gemini': {\n\t\t\t\t\tconst method = request.stream ? 'streamGenerateContent' : 'generateContent';\n\t\t\t\t\tupstreamUrl = `${baseUrl}/v1/models/${request.model}:${method}`;\n\t\t\t\t\tupstreamBody = openaiToGeminiRequest(request);\n\t\t\t\t\tupstreamHeaders = buildUpstreamHeaders(modelConfig, 'gemini');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\t// OpenAI adapter - passthrough with parameter normalization\n\t\t\t\t\tupstreamUrl = `${baseUrl}/v1/chat/completions`;\n\t\t\t\t\tupstreamBody = normalizeOpenAIRequest(request);\n\t\t\t\t\tupstreamHeaders = buildUpstreamHeaders(modelConfig, 'openai');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set provider info in audit context\n\t\t\tauditCtx.setProvider({\n\t\t\t\tprovider: adapter,\n\t\t\t\tupstreamUrl,\n\t\t\t});\n\n\t\t\t// Handle streaming\n\t\t\tif (request.stream) {\n\t\t\t\treturn handleStreamingRequest(c, upstreamUrl, upstreamBody, upstreamHeaders, adapter, request.model, auditCtx);\n\t\t\t}\n\n\t\t\t// Non-streaming request\n\t\t\tconst response = await makeUpstreamRequest(upstreamUrl, upstreamBody, upstreamHeaders);\n\t\t\tconst responseData = await response.json();\n\n\t\t\t// Convert response if needed\n\t\t\tlet result: any;\n\t\t\tswitch (adapter) {\n\t\t\t\tcase 'anthropic':\n\t\t\t\t\tresult = anthropicToOpenaiResponse(responseData, request.model);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'gemini':\n\t\t\t\t\tresult = geminiToOpenaiResponse(responseData, request.model);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tresult = responseData;\n\t\t\t}\n\n\t\t\t// Record token usage and complete audit\n\t\t\tif (result.usage) {\n\t\t\t\tauditCtx.setTokenUsage(result.usage.prompt_tokens || 0, result.usage.completion_tokens || 0);\n\t\t\t}\n\t\t\tauditCtx.setResponseMeta({\n\t\t\t\tfinish_reason: result.choices?.[0]?.finish_reason,\n\t\t\t\tmodel: result.model,\n\t\t\t});\n\t\t\tawait auditCtx.complete(200);\n\n\t\t\t// Log response\n\t\t\tconst usage = result.usage;\n\t\t\tlog.info(\n\t\t\t\t`← 200 /v1/chat/completions model=${result.model || request.model} tokens=${usage?.total_tokens || 0} (in=${usage?.prompt_tokens || 0} out=${usage?.completion_tokens || 0})`,\n\t\t\t);\n\n\t\t\treturn c.json(result);\n\t\t} catch (error) {\n\t\t\t// Record error in audit\n\t\t\tif (auditCtx) {\n\t\t\t\tawait auditCtx.error(error instanceof Error ? error.message : 'Unknown error', 'internal_error', 500);\n\t\t\t}\n\t\t\tlog.error('Chat completion error:', error);\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\terror: {\n\t\t\t\t\t\tmessage: error instanceof Error ? error.message : 'Internal server error',\n\t\t\t\t\t\ttype: 'api_error',\n\t\t\t\t\t\tcode: 'internal_error',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t});\n\n\t/**\n\t * Handle streaming request\n\t */\n\tasync function handleStreamingRequest(\n\t\tc: any,\n\t\tupstreamUrl: string,\n\t\tupstreamBody: unknown,\n\t\tupstreamHeaders: Record<string, string>,\n\t\tadapter: string,\n\t\tmodel: string,\n\t\tauditCtx?: ReturnType<typeof createAuditContext>,\n\t) {\n\t\tconst response = await makeUpstreamRequest(upstreamUrl, upstreamBody, upstreamHeaders, true);\n\n\t\tlet firstTokenRecorded = false;\n\t\tlet totalOutputTokens = 0;\n\n\t\t// For streaming, we need to convert events on the fly\n\t\treturn streamSSE(c, async (stream) => {\n\t\t\tconst reader = response.body?.getReader();\n\t\t\tif (!reader) {\n\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\t\t\t\tif (auditCtx) await auditCtx.complete(200);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst decoder = new TextDecoder();\n\t\t\tlet buffer = '';\n\n\t\t\ttry {\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\tif (done) break;\n\n\t\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\t\tconst lines = buffer.split('\\n');\n\t\t\t\t\tbuffer = lines.pop() || '';\n\n\t\t\t\t\tfor (const line of lines) {\n\t\t\t\t\t\tif (!line.trim()) continue;\n\n\t\t\t\t\t\tif (line.startsWith('data: ')) {\n\t\t\t\t\t\t\tconst data = line.slice(6);\n\t\t\t\t\t\t\tif (data === '[DONE]') {\n\t\t\t\t\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst parsed = JSON.parse(data);\n\t\t\t\t\t\t\t\tconst converted = convertStreamEvent(parsed, adapter, model);\n\t\t\t\t\t\t\t\tif (converted) {\n\t\t\t\t\t\t\t\t\t// Record first token for TTFT\n\t\t\t\t\t\t\t\t\tif (!firstTokenRecorded && auditCtx) {\n\t\t\t\t\t\t\t\t\t\tauditCtx.recordFirstToken();\n\t\t\t\t\t\t\t\t\t\tfirstTokenRecorded = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// Track usage from stream events\n\t\t\t\t\t\t\t\t\tif (converted.usage) {\n\t\t\t\t\t\t\t\t\t\ttotalOutputTokens = converted.usage.completion_tokens || totalOutputTokens;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tawait stream.writeSSE({ data: JSON.stringify(converted) });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// Skip invalid JSON\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (line.startsWith('event: ')) {\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Send done signal\n\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\n\t\t\t\t// Complete audit\n\t\t\t\tif (auditCtx) {\n\t\t\t\t\tauditCtx.setTokenUsage(0, totalOutputTokens); // Input tokens not available in streaming\n\t\t\t\t\tawait auditCtx.complete(200);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// Record streaming error\n\t\t\t\tif (auditCtx) {\n\t\t\t\t\tawait auditCtx.error(err instanceof Error ? err.message : 'Streaming error', 'streaming_error', 500);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t} finally {\n\t\t\t\treader.releaseLock();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Convert stream event to OpenAI format\n\t */\n\tfunction convertStreamEvent(event: any, adapter: string, model: string): any {\n\t\tswitch (adapter) {\n\t\t\tcase 'anthropic':\n\t\t\t\treturn convertAnthropicStreamEvent(event, model);\n\t\t\tcase 'gemini':\n\t\t\t\treturn convertGeminiStreamEvent(event, model);\n\t\t\tdefault:\n\t\t\t\treturn event;\n\t\t}\n\t}\n\n\t/**\n\t * Convert Anthropic stream event to OpenAI format\n\t */\n\tfunction convertAnthropicStreamEvent(event: any, model: string): any {\n\t\tif (event.type === 'content_block_delta') {\n\t\t\tif (event.delta?.type === 'text_delta') {\n\t\t\t\treturn {\n\t\t\t\t\tid: `chatcmpl-${Date.now()}`,\n\t\t\t\t\tobject: 'chat.completion.chunk',\n\t\t\t\t\tcreated: Math.floor(Date.now() / 1000),\n\t\t\t\t\tmodel,\n\t\t\t\t\tchoices: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tindex: 0,\n\t\t\t\t\t\t\tdelta: { content: event.delta.text },\n\t\t\t\t\t\t\tfinish_reason: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t}\n\t\t} else if (event.type === 'message_delta') {\n\t\t\tconst finishReason =\n\t\t\t\tevent.delta?.stop_reason === 'end_turn'\n\t\t\t\t\t? 'stop'\n\t\t\t\t\t: event.delta?.stop_reason === 'tool_use'\n\t\t\t\t\t\t? 'tool_calls'\n\t\t\t\t\t\t: null;\n\t\t\treturn {\n\t\t\t\tid: `chatcmpl-${Date.now()}`,\n\t\t\t\tobject: 'chat.completion.chunk',\n\t\t\t\tcreated: Math.floor(Date.now() / 1000),\n\t\t\t\tmodel,\n\t\t\t\tchoices: [\n\t\t\t\t\t{\n\t\t\t\t\t\tindex: 0,\n\t\t\t\t\t\tdelta: {},\n\t\t\t\t\t\tfinish_reason: finishReason,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tusage: event.usage\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tprompt_tokens: 0,\n\t\t\t\t\t\t\tcompletion_tokens: event.usage.output_tokens,\n\t\t\t\t\t\t\ttotal_tokens: event.usage.output_tokens,\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t};\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Convert Gemini stream event to OpenAI format\n\t */\n\tfunction convertGeminiStreamEvent(event: any, model: string): any {\n\t\tif (event.candidates?.[0]?.content?.parts) {\n\t\t\tconst parts = event.candidates[0].content.parts;\n\t\t\tconst textParts = parts.filter((p: any) => p.text);\n\n\t\t\tif (textParts.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tid: `chatcmpl-${Date.now()}`,\n\t\t\t\t\tobject: 'chat.completion.chunk',\n\t\t\t\t\tcreated: Math.floor(Date.now() / 1000),\n\t\t\t\t\tmodel,\n\t\t\t\t\tchoices: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tindex: 0,\n\t\t\t\t\t\t\tdelta: { content: textParts.map((p: any) => p.text).join('') },\n\t\t\t\t\t\t\tfinish_reason: event.candidates[0].finishReason === 'STOP' ? 'stop' : null,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t// =========================================================================\n\t// Anthropic Messages API\n\t// =========================================================================\n\n\tapp.post('/v1/messages', async (c) => {\n\t\ttry {\n\t\t\tconst body = await c.req.json();\n\t\t\tconst parseResult = CreateMessageRequestSchema.safeParse(body);\n\n\t\t\tif (!parseResult.success) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tmessage: 'Invalid request',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst request = parseResult.data;\n\t\t\tconst modelConfig = resolveModelConfig(request.model);\n\n\t\t\tif (!modelConfig) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tmessage: `Model ${request.model} not configured`,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// For Anthropic endpoint, we pass through to Anthropic or convert from OpenAI\n\t\t\tconst adapter = modelConfig.adapter || 'anthropic';\n\t\t\tconst baseUrl = normalizeBaseUrl(\n\t\t\t\tmodelConfig.adapters?.[adapter]?.baseUrl || modelConfig.baseUrl || 'https://api.anthropic.com',\n\t\t\t);\n\n\t\t\tconst upstreamUrl = `${baseUrl}/v1/messages`;\n\t\t\tconst upstreamHeaders = buildUpstreamHeaders(modelConfig, 'anthropic');\n\n\t\t\t// Log incoming request\n\t\t\tlog.info(`→ POST /v1/messages model=${request.model} messages=${request.messages.length}`);\n\n\t\t\tconst response = await makeUpstreamRequest(upstreamUrl, request, upstreamHeaders);\n\t\t\tconst responseData = await response.json();\n\n\t\t\t// Log response\n\t\t\tconst usage = responseData.usage;\n\t\t\tlog.info(\n\t\t\t\t`← 200 /v1/messages model=${responseData.model || request.model} tokens=${(usage?.input_tokens || 0) + (usage?.output_tokens || 0)} (in=${usage?.input_tokens || 0} out=${usage?.output_tokens || 0})`,\n\t\t\t);\n\n\t\t\treturn c.json(responseData);\n\t\t} catch (error) {\n\t\t\tlog.error('Messages error:', error);\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\terror: {\n\t\t\t\t\t\ttype: 'api_error',\n\t\t\t\t\t\tmessage: error instanceof Error ? error.message : 'Internal server error',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t});\n\n\t// =========================================================================\n\t// Gemini Generate Content API\n\t// =========================================================================\n\n\tapp.post('/v1/models/:model\\\\:generateContent', async (c) => {\n\t\ttry {\n\t\t\tconst model = c.req.param('model');\n\t\t\tif (!model) {\n\t\t\t\treturn c.json({ error: { message: 'Model parameter is required' } }, 400);\n\t\t\t}\n\n\t\t\tconst body = await c.req.json();\n\t\t\tconst parseResult = CreateGenerateContentRequestSchema.safeParse(body);\n\n\t\t\tif (!parseResult.success) {\n\t\t\t\treturn c.json({ error: { message: 'Invalid request' } }, 400);\n\t\t\t}\n\n\t\t\tconst request = parseResult.data;\n\t\t\tconst modelConfig = resolveModelConfig(model);\n\n\t\t\tif (!modelConfig) {\n\t\t\t\treturn c.json({ error: { message: `Model ${model} not configured` } }, 404);\n\t\t\t}\n\n\t\t\tconst baseUrl = normalizeBaseUrl(\n\t\t\t\tmodelConfig.adapters?.gemini?.baseUrl || modelConfig.baseUrl || 'https://generativelanguage.googleapis.com',\n\t\t\t);\n\n\t\t\tconst upstreamUrl = `${baseUrl}/v1/models/${model}:generateContent`;\n\t\t\tconst upstreamHeaders = buildUpstreamHeaders(modelConfig, 'gemini');\n\n\t\t\t// Log incoming request\n\t\t\tlog.info(`→ POST /v1/models/${model}:generateContent contents=${request.contents?.length || 0}`);\n\n\t\t\tconst response = await makeUpstreamRequest(upstreamUrl, request, upstreamHeaders);\n\t\t\tconst responseData = await response.json();\n\n\t\t\t// Log response\n\t\t\tconst usage = responseData.usageMetadata;\n\t\t\tlog.info(\n\t\t\t\t`← 200 /v1/models/${model}:generateContent tokens=${usage?.totalTokenCount || 0} (in=${usage?.promptTokenCount || 0} out=${usage?.candidatesTokenCount || 0})`,\n\t\t\t);\n\n\t\t\treturn c.json(responseData);\n\t\t} catch (error) {\n\t\t\tlog.error('Generate content error:', error);\n\t\t\treturn c.json({ error: { message: error instanceof Error ? error.message : 'Internal server error' } }, 500);\n\t\t}\n\t});\n\n\t// =========================================================================\n\t// Gemini Streaming Generate Content API\n\t// =========================================================================\n\n\tapp.post('/v1/models/:model\\\\:streamGenerateContent', async (c) => {\n\t\ttry {\n\t\t\tconst model = c.req.param('model');\n\t\t\tif (!model) {\n\t\t\t\treturn c.json({ error: { message: 'Model parameter is required' } }, 400);\n\t\t\t}\n\n\t\t\tconst body = await c.req.json();\n\t\t\tconst parseResult = CreateGenerateContentRequestSchema.safeParse(body);\n\n\t\t\tif (!parseResult.success) {\n\t\t\t\treturn c.json({ error: { message: 'Invalid request' } }, 400);\n\t\t\t}\n\n\t\t\tconst request = parseResult.data;\n\n\t\t\t// Log incoming request\n\t\t\tlog.info(`→ POST /v1/models/${model}:streamGenerateContent contents=${request.contents?.length || 0}`);\n\n\t\t\tconst modelConfig = resolveModelConfig(model);\n\n\t\t\tif (!modelConfig) {\n\t\t\t\treturn c.json({ error: { message: `Model ${model} not configured` } }, 404);\n\t\t\t}\n\n\t\t\tconst baseUrl = normalizeBaseUrl(\n\t\t\t\tmodelConfig.adapters?.gemini?.baseUrl || modelConfig.baseUrl || 'https://generativelanguage.googleapis.com',\n\t\t\t);\n\n\t\t\tconst upstreamUrl = `${baseUrl}/v1/models/${model}:streamGenerateContent`;\n\t\t\tconst upstreamHeaders = buildUpstreamHeaders(modelConfig, 'gemini');\n\n\t\t\tconst response = await makeUpstreamRequest(upstreamUrl, request, upstreamHeaders, true);\n\n\t\t\t// Stream the response directly\n\t\t\treturn streamSSE(c, async (stream) => {\n\t\t\t\tconst reader = response.body?.getReader();\n\t\t\t\tif (!reader) {\n\t\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst decoder = new TextDecoder();\n\t\t\t\tlet buffer = '';\n\n\t\t\t\ttry {\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\t\tif (done) break;\n\n\t\t\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\t\t\tconst lines = buffer.split('\\n');\n\t\t\t\t\t\tbuffer = lines.pop() || '';\n\n\t\t\t\t\t\tfor (const line of lines) {\n\t\t\t\t\t\t\tif (!line.trim()) continue;\n\n\t\t\t\t\t\t\tif (line.startsWith('data: ')) {\n\t\t\t\t\t\t\t\tconst data = line.slice(6);\n\t\t\t\t\t\t\t\tif (data === '[DONE]') {\n\t\t\t\t\t\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tawait stream.writeSSE({ data });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\t\t\t\t} finally {\n\t\t\t\t\treader.releaseLock();\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tlog.error('Stream generate content error:', error);\n\t\t\treturn c.json({ error: { message: error instanceof Error ? error.message : 'Internal server error' } }, 500);\n\t\t}\n\t});\n\n\t// =========================================================================\n\t// OpenAI Responses API\n\t// =========================================================================\n\n\tapp.post('/v1/responses', async (c) => {\n\t\tlet auditCtx: ReturnType<typeof createAuditContext> | null = null;\n\n\t\ttry {\n\t\t\tconst body = await c.req.json();\n\t\t\tconst parseResult = CreateResponseRequestSchema.safeParse(body);\n\n\t\t\tif (!parseResult.success) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: 'Invalid request',\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tparam: null,\n\t\t\t\t\t\t\tcode: 'invalid_request',\n\t\t\t\t\t\t\tdetails: parseResult.error.issues,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst request = parseResult.data;\n\n\t\t\t// Handle previous_response_id - load previous context\n\t\t\tlet previousContext: { input: unknown; output: unknown[] } | null = null;\n\t\t\tif (request.previous_response_id) {\n\t\t\t\ttry {\n\t\t\t\t\tconst { isDbInitialized, getEntityManager } = await import('../server/db');\n\t\t\t\t\tconst { ResponseEntity } = await import('../entities');\n\t\t\t\t\tif (isDbInitialized()) {\n\t\t\t\t\t\tconst em = getEntityManager().fork();\n\t\t\t\t\t\tconst prevResponse = await em.findOne(ResponseEntity, { responseId: request.previous_response_id });\n\t\t\t\t\t\tif (prevResponse) {\n\t\t\t\t\t\t\tpreviousContext = {\n\t\t\t\t\t\t\t\tinput: prevResponse.input,\n\t\t\t\t\t\t\t\toutput: prevResponse.output,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tlog.info(`Loaded previous response: ${request.previous_response_id}`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlog.warn(`Previous response not found: ${request.previous_response_id}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlog.warn('Failed to load previous response:', e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst modelConfig = resolveModelConfig(request.model);\n\n\t\t\tif (!modelConfig) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: `Model ${request.model} not configured`,\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tparam: 'model',\n\t\t\t\t\t\t\tcode: 'model_not_found',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Determine adapter - for Responses API, we convert to Chat Completions\n\t\t\tconst adapter = modelConfig.adapter || 'openai';\n\t\t\tconst baseUrl = normalizeBaseUrl(\n\t\t\t\tmodelConfig.adapters?.[adapter]?.baseUrl || modelConfig.baseUrl || 'https://api.openai.com',\n\t\t\t);\n\n\t\t\t// Create audit context\n\t\t\tauditCtx = createAuditContext({\n\t\t\t\tmethod: 'POST',\n\t\t\t\tendpoint: '/v1/responses',\n\t\t\t\tmodel: request.model,\n\t\t\t\tinputProtocol: ChatProtocol.OPENAI,\n\t\t\t\toutputProtocol: ChatProtocol.OPENAI,\n\t\t\t\tstreaming: request.stream || false,\n\t\t\t\tclientIp: extractClientIp(c),\n\t\t\t\tuserAgent: c.req.header('user-agent'),\n\t\t\t\trequestMeta: {\n\t\t\t\t\ttemperature: request.temperature,\n\t\t\t\t\tmax_output_tokens: request.max_output_tokens,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Log incoming request\n\t\t\tconst inputType =\n\t\t\t\ttypeof request.input === 'string'\n\t\t\t\t\t? 'string'\n\t\t\t\t\t: Array.isArray(request.input)\n\t\t\t\t\t\t? `array[${request.input.length}]`\n\t\t\t\t\t\t: 'object';\n\t\t\tlog.info(`→ POST /v1/responses model=${request.model} stream=${request.stream || false} input=${inputType}`);\n\n\t\t\t// Convert Responses API request to Chat Completions format\n\t\t\tconst chatRequest = responsesToChatCompletions(request, previousContext);\n\n\t\t\t// Build upstream request\n\t\t\tconst upstreamUrl = `${baseUrl}/v1/chat/completions`;\n\t\t\tconst upstreamHeaders = buildUpstreamHeaders(modelConfig, 'openai');\n\n\t\t\tauditCtx.setProvider({\n\t\t\t\tprovider: adapter,\n\t\t\t\tupstreamUrl,\n\t\t\t});\n\n\t\t\t// Handle streaming\n\t\t\tif (request.stream) {\n\t\t\t\treturn handleResponsesStreamingRequest(c, upstreamUrl, chatRequest, upstreamHeaders, request.model, auditCtx);\n\t\t\t}\n\n\t\t\t// Non-streaming request\n\t\t\tconst response = await makeUpstreamRequest(upstreamUrl, chatRequest, upstreamHeaders);\n\t\t\tconst chatResponse = await response.json();\n\n\t\t\t// Convert Chat Completions response to Responses format\n\t\t\tconst result = chatCompletionsToResponses(chatResponse, request.model);\n\n\t\t\t// Store response for future previous_response_id lookups\n\t\t\ttry {\n\t\t\t\tconst { isDbInitialized, getEntityManager } = await import('../server/db');\n\t\t\t\tconst { ResponseEntity } = await import('../entities');\n\t\t\t\tif (isDbInitialized()) {\n\t\t\t\t\tconst em = getEntityManager().fork();\n\t\t\t\t\tconst responseEntity = new ResponseEntity();\n\t\t\t\t\tresponseEntity.responseId = result.id;\n\t\t\t\t\tresponseEntity.model = result.model;\n\t\t\t\t\tresponseEntity.status = result.status;\n\t\t\t\t\tresponseEntity.input = request.input;\n\t\t\t\t\tresponseEntity.output = result.output;\n\t\t\t\t\tresponseEntity.usage = result.usage;\n\t\t\t\t\tresponseEntity.instructions = request.instructions ?? undefined;\n\t\t\t\t\tresponseEntity.previousResponseId = request.previous_response_id ?? undefined;\n\t\t\t\t\tresponseEntity.tools = request.tools ?? undefined;\n\t\t\t\t\tresponseEntity.toolChoice = request.tool_choice ?? undefined;\n\t\t\t\t\tresponseEntity.metadata = request.metadata as Record<string, unknown>;\n\t\t\t\t\tresponseEntity.durationMs = auditCtx?.getDuration();\n\t\t\t\t\tem.persist(responseEntity);\n\t\t\t\t\tawait em.flush();\n\t\t\t\t\tlog.debug(`Stored response: ${result.id}`);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tlog.warn('Failed to store response:', e);\n\t\t\t}\n\n\t\t\t// Record usage\n\t\t\tif (chatResponse.usage) {\n\t\t\t\tauditCtx.setTokenUsage(chatResponse.usage.prompt_tokens || 0, chatResponse.usage.completion_tokens || 0);\n\t\t\t}\n\t\t\tauditCtx.setResponseMeta({\n\t\t\t\tstatus: result.status,\n\t\t\t\toutput_items: result.output.length,\n\t\t\t});\n\t\t\tawait auditCtx.complete(200);\n\n\t\t\t// Log response\n\t\t\tconst usage = chatResponse.usage;\n\t\t\tlog.info(\n\t\t\t\t`← 200 /v1/responses model=${result.model || request.model} status=${result.status} tokens=${usage?.total_tokens || 0}`,\n\t\t\t);\n\n\t\t\treturn c.json(result);\n\t\t} catch (error) {\n\t\t\tif (auditCtx) {\n\t\t\t\tawait auditCtx.error(error instanceof Error ? error.message : 'Unknown error', 'internal_error', 500);\n\t\t\t}\n\t\t\tlog.error('Responses API error:', error);\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\terror: {\n\t\t\t\t\t\tmessage: error instanceof Error ? error.message : 'Internal server error',\n\t\t\t\t\t\ttype: 'api_error',\n\t\t\t\t\t\tcode: 'internal_error',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t});\n\n\t/**\n\t * Convert Responses API request to Chat Completions format\n\t */\n\tfunction responsesToChatCompletions(\n\t\trequest: CreateResponseRequest,\n\t\tpreviousContext?: { input: unknown; output: unknown[] } | null,\n\t): CreateChatCompletionRequest {\n\t\tconst messages: CreateChatCompletionRequest['messages'] = [];\n\n\t\t// Add system instruction if present\n\t\tif (request.instructions) {\n\t\t\tmessages.push({\n\t\t\t\trole: 'system',\n\t\t\t\tcontent: request.instructions,\n\t\t\t});\n\t\t}\n\n\t\t// Add previous context if available (previous_response_id)\n\t\tif (previousContext) {\n\t\t\t// Add previous input\n\t\t\tconst prevInput = previousContext.input;\n\t\t\tif (typeof prevInput === 'string') {\n\t\t\t\tmessages.push({ role: 'user', content: prevInput });\n\t\t\t} else if (Array.isArray(prevInput)) {\n\t\t\t\tfor (const item of prevInput as any[]) {\n\t\t\t\t\tif (item.type === 'message') {\n\t\t\t\t\t\tmessages.push({\n\t\t\t\t\t\t\trole: item.role as 'user' | 'assistant' | 'system',\n\t\t\t\t\t\t\tcontent: typeof item.content === 'string' ? item.content : JSON.stringify(item.content),\n\t\t\t\t\t\t} as any);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add previous output as assistant messages\n\t\t\tfor (const item of previousContext.output as any[]) {\n\t\t\t\tif (item.type === 'message' && item.role === 'assistant') {\n\t\t\t\t\tconst textContent = item.content?.find((c: any) => c.type === 'text' || c.type === 'output_text');\n\t\t\t\t\tif (textContent) {\n\t\t\t\t\t\tmessages.push({\n\t\t\t\t\t\t\trole: 'assistant',\n\t\t\t\t\t\t\tcontent: textContent.text,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Convert current input to messages\n\t\tif (typeof request.input === 'string') {\n\t\t\tmessages.push({\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: request.input,\n\t\t\t});\n\t\t} else if (Array.isArray(request.input)) {\n\t\t\tfor (const item of request.input) {\n\t\t\t\tif (item.type === 'message') {\n\t\t\t\t\tmessages.push({\n\t\t\t\t\t\trole: item.role as 'user' | 'assistant' | 'system',\n\t\t\t\t\t\tcontent: typeof item.content === 'string' ? item.content : JSON.stringify(item.content),\n\t\t\t\t\t} as any);\n\t\t\t\t}\n\t\t\t\t// item_reference is handled differently - would need to fetch the referenced item\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tmodel: request.model,\n\t\t\tmessages,\n\t\t\ttemperature: request.temperature,\n\t\t\ttop_p: request.top_p,\n\t\t\tmax_tokens: request.max_output_tokens,\n\t\t\tstream: request.stream,\n\t\t\ttools: request.tools,\n\t\t\ttool_choice: request.tool_choice,\n\t\t\tparallel_tool_calls: request.parallel_tool_calls,\n\t\t\tmetadata: request.metadata,\n\t\t\tstore: request.store,\n\t\t\tuser: request.user,\n\t\t} as CreateChatCompletionRequest;\n\t}\n\n\t/**\n\t * Convert Chat Completions response to Responses format\n\t */\n\tfunction chatCompletionsToResponses(chatResponse: any, model: string): any {\n\t\tconst responseId = `resp_${chatResponse.id || Date.now()}`;\n\t\tconst output: any[] = [];\n\n\t\tfor (const choice of chatResponse.choices || []) {\n\t\t\tconst message = choice.message;\n\t\t\tif (message) {\n\t\t\t\toutput.push({\n\t\t\t\t\tid: `item_${responseId}_${choice.index}`,\n\t\t\t\t\ttype: 'message',\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: message.content ? [{ type: 'text', text: message.content }] : [],\n\t\t\t\t\tstatus: 'completed',\n\t\t\t\t});\n\n\t\t\t\t// Handle tool calls\n\t\t\t\tif (message.tool_calls) {\n\t\t\t\t\tfor (const toolCall of message.tool_calls) {\n\t\t\t\t\t\toutput.push({\n\t\t\t\t\t\t\tid: toolCall.id,\n\t\t\t\t\t\t\ttype: 'function_call',\n\t\t\t\t\t\t\tname: toolCall.function?.name,\n\t\t\t\t\t\t\targuments: toolCall.function?.arguments,\n\t\t\t\t\t\t\tstatus: 'completed',\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tid: responseId,\n\t\t\tobject: 'response',\n\t\t\tcreated_at: chatResponse.created || Math.floor(Date.now() / 1000),\n\t\t\tmodel: chatResponse.model || model,\n\t\t\tstatus: 'completed',\n\t\t\toutput,\n\t\t\tusage: chatResponse.usage,\n\t\t\tmetadata: {},\n\t\t\terror: null,\n\t\t};\n\t}\n\n\t/**\n\t * Handle Responses API streaming\n\t */\n\tasync function handleResponsesStreamingRequest(\n\t\tc: any,\n\t\tupstreamUrl: string,\n\t\tupstreamBody: unknown,\n\t\tupstreamHeaders: Record<string, string>,\n\t\tmodel: string,\n\t\tauditCtx?: ReturnType<typeof createAuditContext>,\n\t) {\n\t\tconst response = await makeUpstreamRequest(\n\t\t\tupstreamUrl,\n\t\t\t{ ...(upstreamBody as any), stream: true },\n\t\t\tupstreamHeaders,\n\t\t\ttrue,\n\t\t);\n\n\t\tlet firstTokenRecorded = false;\n\t\tconst responseId = `resp_${Date.now()}`;\n\n\t\treturn streamSSE(c, async (stream) => {\n\t\t\tconst reader = response.body?.getReader();\n\t\t\tif (!reader) {\n\t\t\t\tawait stream.writeSSE({ event: 'response.done', data: JSON.stringify({ type: 'response.done' }) });\n\t\t\t\tif (auditCtx) await auditCtx.complete(200);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Send initial event\n\t\t\tawait stream.writeSSE({\n\t\t\t\tevent: 'response.created',\n\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\ttype: 'response.created',\n\t\t\t\t\tresponse: {\n\t\t\t\t\t\tid: responseId,\n\t\t\t\t\t\tobject: 'response',\n\t\t\t\t\t\tcreated_at: Math.floor(Date.now() / 1000),\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tstatus: 'in_progress',\n\t\t\t\t\t\toutput: [],\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tconst decoder = new TextDecoder();\n\t\t\tlet buffer = '';\n\t\t\tlet outputItemId = `item_${responseId}_0`;\n\n\t\t\ttry {\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\tif (done) break;\n\n\t\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\t\tconst lines = buffer.split('\\n');\n\t\t\t\t\tbuffer = lines.pop() || '';\n\n\t\t\t\t\tfor (const line of lines) {\n\t\t\t\t\t\tif (!line.trim() || !line.startsWith('data: ')) continue;\n\n\t\t\t\t\t\tconst data = line.slice(6);\n\t\t\t\t\t\tif (data === '[DONE]') continue;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst parsed = JSON.parse(data);\n\t\t\t\t\t\t\tconst delta = parsed.choices?.[0]?.delta;\n\n\t\t\t\t\t\t\tif (delta?.content) {\n\t\t\t\t\t\t\t\tif (!firstTokenRecorded && auditCtx) {\n\t\t\t\t\t\t\t\t\tauditCtx.recordFirstToken();\n\t\t\t\t\t\t\t\t\tfirstTokenRecorded = true;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tawait stream.writeSSE({\n\t\t\t\t\t\t\t\t\tevent: 'response.output_text.delta',\n\t\t\t\t\t\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\t\t\t\t\t\ttype: 'response.output_text.delta',\n\t\t\t\t\t\t\t\t\t\toutput_index: 0,\n\t\t\t\t\t\t\t\t\t\tcontent_index: 0,\n\t\t\t\t\t\t\t\t\t\tdelta: delta.content,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Skip invalid JSON\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Send completion events\n\t\t\t\tawait stream.writeSSE({\n\t\t\t\t\tevent: 'response.output_item.done',\n\t\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\t\ttype: 'response.output_item.done',\n\t\t\t\t\t\toutput_index: 0,\n\t\t\t\t\t\titem: {\n\t\t\t\t\t\t\tid: outputItemId,\n\t\t\t\t\t\t\ttype: 'message',\n\t\t\t\t\t\t\trole: 'assistant',\n\t\t\t\t\t\t\tstatus: 'completed',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t});\n\n\t\t\t\tawait stream.writeSSE({\n\t\t\t\t\tevent: 'response.done',\n\t\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\t\ttype: 'response.done',\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tid: responseId,\n\t\t\t\t\t\t\tstatus: 'completed',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t});\n\n\t\t\t\tif (auditCtx) await auditCtx.complete(200);\n\t\t\t} catch (err) {\n\t\t\t\tif (auditCtx) {\n\t\t\t\t\tawait auditCtx.error(err instanceof Error ? err.message : 'Streaming error', 'streaming_error', 500);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t} finally {\n\t\t\t\treader.releaseLock();\n\t\t\t}\n\t\t});\n\t}\n\n\t// =========================================================================\n\t// Models endpoint\n\t// =========================================================================\n\n\tapp.get('/v1/models', async (c) => {\n\t\tconst fetchUpstream = c.req.query('fetch') === 'true';\n\t\tconst allModels: Array<{\n\t\t\tid: string;\n\t\t\tobject: string;\n\t\t\tcreated: number;\n\t\t\towned_by: string;\n\t\t\tcontext_window?: number;\n\t\t\tmax_input_tokens?: number;\n\t\t\tmax_output_tokens?: number;\n\t\t}> = [];\n\n\t\t// Add configured models\n\t\tfor (const m of config.models || []) {\n\t\t\tallModels.push({\n\t\t\t\tid: m.name,\n\t\t\t\tobject: 'model',\n\t\t\t\tcreated: Math.floor(Date.now() / 1000),\n\t\t\t\towned_by: 'mcps',\n\t\t\t\tcontext_window: m.contextWindow,\n\t\t\t\tmax_input_tokens: m.maxInputTokens,\n\t\t\t\tmax_output_tokens: m.maxOutputTokens,\n\t\t\t});\n\n\t\t\t// Fetch upstream models if enabled\n\t\t\tif (fetchUpstream && m.fetchUpstreamModels && m.baseUrl) {\n\t\t\t\ttry {\n\t\t\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t};\n\t\t\t\t\tif (m.apiKey) {\n\t\t\t\t\t\theaders.Authorization = `Bearer ${m.apiKey}`;\n\t\t\t\t\t}\n\t\t\t\t\tObject.assign(headers, m.headers || {});\n\n\t\t\t\t\tconst normalizedUrl = normalizeBaseUrl(m.baseUrl);\n\t\t\t\t\tconst upstreamUrl = `${normalizedUrl}/v1/models`;\n\n\t\t\t\t\tconst res = await fetch(upstreamUrl, { headers });\n\t\t\t\t\tif (res.ok) {\n\t\t\t\t\t\tconst data = await res.json();\n\t\t\t\t\t\tif (data.data && Array.isArray(data.data)) {\n\t\t\t\t\t\t\tfor (const model of data.data) {\n\t\t\t\t\t\t\t\t// Avoid duplicates\n\t\t\t\t\t\t\t\tif (!allModels.some((existing) => existing.id === model.id)) {\n\t\t\t\t\t\t\t\t\tallModels.push({\n\t\t\t\t\t\t\t\t\t\tid: model.id,\n\t\t\t\t\t\t\t\t\t\tobject: model.object || 'model',\n\t\t\t\t\t\t\t\t\t\tcreated: model.created || Math.floor(Date.now() / 1000),\n\t\t\t\t\t\t\t\t\t\towned_by: model.owned_by || m.name.split('/')[0] || 'upstream',\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlog.warn(`Failed to fetch upstream models from ${m.baseUrl}: ${e}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlog.debug(`→ GET /v1/models count=${allModels.length} fetch=${fetchUpstream}`);\n\n\t\treturn c.json({\n\t\t\tobject: 'list',\n\t\t\tdata: allModels,\n\t\t});\n\t});\n\n\treturn app;\n}\n"],"names":["consola","Hono","streamSSE","ChatProtocol","createAuditContext","extractClientIp","openaiToAnthropicRequest","anthropicToOpenaiResponse","openaiToGeminiRequest","geminiToOpenaiResponse","CreateChatCompletionRequestSchema","CreateResponseRequestSchema","CreateMessageRequestSchema","CreateGenerateContentRequestSchema","log","withTag","createChatHandler","options","app","config","resolveModelConfig","modelName","models","length","modelConfig","name","pattern","includes","regex","RegExp","replace","test","makeUpstreamRequest","url","body","headers","_stream","response","fetch","method","JSON","stringify","ok","errorText","text","error","status","Error","normalizeBaseUrl","buildUpstreamHeaders","adapter","apiKey","Authorization","Object","assign","adapters","normalizeOpenAIRequest","request","normalized","max_completion_tokens","max_tokens","enable_thinking","undefined","thinking","type","post","c","auditCtx","req","json","parseResult","safeParse","success","message","param","code","details","issues","data","model","baseUrl","outputProtocol","ANTHROPIC","GEMINI","OPENAI","endpoint","inputProtocol","streaming","stream","clientIp","userAgent","header","requestMeta","temperature","top_p","info","messages","upstreamUrl","upstreamBody","upstreamHeaders","setProvider","provider","handleStreamingRequest","responseData","result","usage","setTokenUsage","prompt_tokens","completion_tokens","setResponseMeta","finish_reason","choices","complete","total_tokens","firstTokenRecorded","totalOutputTokens","reader","getReader","writeSSE","decoder","TextDecoder","buffer","done","value","read","decode","lines","split","pop","line","trim","startsWith","slice","parsed","parse","converted","convertStreamEvent","recordFirstToken","err","releaseLock","event","convertAnthropicStreamEvent","convertGeminiStreamEvent","delta","id","Date","now","object","created","Math","floor","index","content","finishReason","stop_reason","output_tokens","candidates","parts","textParts","filter","p","map","join","input_tokens","gemini","contents","usageMetadata","totalTokenCount","promptTokenCount","candidatesTokenCount","previousContext","previous_response_id","isDbInitialized","getEntityManager","ResponseEntity","em","fork","prevResponse","findOne","responseId","input","output","warn","e","max_output_tokens","inputType","Array","isArray","chatRequest","responsesToChatCompletions","handleResponsesStreamingRequest","chatResponse","chatCompletionsToResponses","responseEntity","instructions","previousResponseId","tools","toolChoice","tool_choice","metadata","durationMs","getDuration","persist","flush","debug","output_items","push","role","prevInput","item","textContent","find","parallel_tool_calls","store","user","choice","tool_calls","toolCall","function","arguments","created_at","outputItemId","output_index","content_index","get","fetchUpstream","query","allModels","m","owned_by","context_window","contextWindow","max_input_tokens","maxInputTokens","maxOutputTokens","fetchUpstreamModels","normalizedUrl","res","some","existing"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/chat/handler.ts"],"sourcesContent":["/**\n * Chat API Handler\n * Provides unified AI model gateway with protocol conversion\n */\nimport consola from 'consola';\nimport { Hono } from 'hono';\nimport { streamSSE } from 'hono/streaming';\nimport type { ChatConfig, ModelConfig } from '../server/schema';\nimport { ChatProtocol, createAuditContext, extractClientIp } from '../audit/chat';\nimport {\n\topenaiToAnthropicRequest,\n\tanthropicToOpenaiResponse,\n\topenaiToGeminiRequest,\n\tgeminiToOpenaiResponse,\n} from './converters';\nimport {\n\tCreateChatCompletionRequestSchema,\n\ttype CreateChatCompletionRequest,\n\tCreateResponseRequestSchema,\n\ttype CreateResponseRequest,\n} from '@wener/ai/openai';\nimport { CreateMessageRequestSchema } from '@wener/ai/anthropic';\nimport { CreateGenerateContentRequestSchema } from '@wener/ai/google';\n\nconst log = consola.withTag('chat');\n\nexport interface ChatHandlerOptions {\n\tconfig?: ChatConfig;\n}\n\n/**\n * Create chat handler Hono app\n */\nexport function createChatHandler(options: ChatHandlerOptions = {}) {\n\tconst app = new Hono();\n\tconst { config = {} } = options;\n\n\t/**\n\t * Resolve model configuration\n\t */\n\tfunction resolveModelConfig(modelName: string): ModelConfig | null {\n\t\tconst models = config.models;\n\t\tif (!models || models.length === 0) return null;\n\n\t\t// First pass: exact match\n\t\tfor (const modelConfig of models) {\n\t\t\tif (modelConfig.name === modelName) {\n\t\t\t\treturn modelConfig;\n\t\t\t}\n\t\t}\n\n\t\t// Second pass: wildcard matches (e.g., \"gpt-*\" or \"claude-*\")\n\t\tfor (const modelConfig of models) {\n\t\t\tconst pattern = modelConfig.name;\n\t\t\tif (pattern.includes('*')) {\n\t\t\t\tconst regex = new RegExp(`^${pattern.replace(/\\*/g, '.*')}$`);\n\t\t\t\tif (regex.test(modelName)) {\n\t\t\t\t\treturn modelConfig;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Make request to upstream provider\n\t */\n\tasync function makeUpstreamRequest(\n\t\turl: string,\n\t\tbody: unknown,\n\t\theaders: Record<string, string>,\n\t\t_stream: boolean = false,\n\t): Promise<Response> {\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t...headers,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text();\n\t\t\tlog.error('Upstream error:', response.status, errorText);\n\t\t\tthrow new Error(`Upstream error: ${response.status} ${errorText}`);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Normalize base URL - strip trailing /v1 if present\n\t * This allows baseUrl to be specified as either \"http://example.com\" or \"http://example.com/v1\"\n\t */\n\tfunction normalizeBaseUrl(url: string): string {\n\t\treturn url.replace(/\\/v1\\/?$/, '');\n\t}\n\n\t/**\n\t * Build headers for upstream request\n\t */\n\tfunction buildUpstreamHeaders(\n\t\tmodelConfig: ModelConfig,\n\t\tadapter: 'openai' | 'anthropic' | 'gemini',\n\t): Record<string, string> {\n\t\tconst headers: Record<string, string> = {};\n\n\t\t// Add API key if configured\n\t\tif (modelConfig.apiKey) {\n\t\t\tif (adapter === 'anthropic') {\n\t\t\t\theaders['x-api-key'] = modelConfig.apiKey;\n\t\t\t\theaders['anthropic-version'] = '2023-06-01';\n\t\t\t} else {\n\t\t\t\theaders.Authorization = `Bearer ${modelConfig.apiKey}`;\n\t\t\t}\n\t\t}\n\n\t\t// Add custom headers\n\t\tif (modelConfig.headers) {\n\t\t\tObject.assign(headers, modelConfig.headers);\n\t\t}\n\n\t\t// Add adapter-specific headers\n\t\tif (modelConfig.adapters?.[adapter]?.headers) {\n\t\t\tObject.assign(headers, modelConfig.adapters[adapter]?.headers);\n\t\t}\n\n\t\treturn headers;\n\t}\n\n\t/**\n\t * Normalize OpenAI request for different providers\n\t * Handles max_tokens/max_completion_tokens compatibility and thinking parameters\n\t */\n\tfunction normalizeOpenAIRequest(request: CreateChatCompletionRequest): Record<string, unknown> {\n\t\tconst normalized: Record<string, unknown> = { ...request };\n\n\t\t// Handle max_tokens vs max_completion_tokens compatibility\n\t\t// Some providers only support max_tokens, others prefer max_completion_tokens\n\t\tif (request.max_completion_tokens && !request.max_tokens) {\n\t\t\tnormalized.max_tokens = request.max_completion_tokens;\n\t\t}\n\n\t\t// Handle enable_thinking parameter (used by Qwen, DeepSeek thinking models)\n\t\t// Convert to thinking object format if needed\n\t\tif (request.enable_thinking !== undefined && !request.thinking) {\n\t\t\tnormalized.thinking = {\n\t\t\t\ttype: request.enable_thinking ? 'enabled' : 'disabled',\n\t\t\t};\n\t\t}\n\n\t\treturn normalized;\n\t}\n\n\t// =========================================================================\n\t// OpenAI Chat Completions API\n\t// =========================================================================\n\n\tapp.post('/v1/chat/completions', async (c) => {\n\t\t// Create audit context early\n\t\tlet auditCtx: ReturnType<typeof createAuditContext> | null = null;\n\n\t\ttry {\n\t\t\tconst body = await c.req.json();\n\t\t\tconst parseResult = CreateChatCompletionRequestSchema.safeParse(body);\n\n\t\t\tif (!parseResult.success) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: 'Invalid request',\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tparam: null,\n\t\t\t\t\t\t\tcode: 'invalid_request',\n\t\t\t\t\t\t\tdetails: parseResult.error.issues,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst request = parseResult.data;\n\t\t\tconst modelConfig = resolveModelConfig(request.model);\n\n\t\t\tif (!modelConfig) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: `Model ${request.model} not configured`,\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tparam: 'model',\n\t\t\t\t\t\t\tcode: 'model_not_found',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Determine upstream adapter\n\t\t\tconst adapter = modelConfig.adapter || 'openai';\n\t\t\tconst baseUrl = normalizeBaseUrl(\n\t\t\t\tmodelConfig.adapters?.[adapter]?.baseUrl || modelConfig.baseUrl || 'https://api.openai.com',\n\t\t\t);\n\n\t\t\t// Create audit context\n\t\t\tconst outputProtocol =\n\t\t\t\tadapter === 'anthropic'\n\t\t\t\t\t? ChatProtocol.ANTHROPIC\n\t\t\t\t\t: adapter === 'gemini'\n\t\t\t\t\t\t? ChatProtocol.GEMINI\n\t\t\t\t\t\t: ChatProtocol.OPENAI;\n\n\t\t\tauditCtx = createAuditContext({\n\t\t\t\tmethod: 'POST',\n\t\t\t\tendpoint: '/v1/chat/completions',\n\t\t\t\tmodel: request.model,\n\t\t\t\tinputProtocol: ChatProtocol.OPENAI,\n\t\t\t\toutputProtocol,\n\t\t\t\tstreaming: request.stream || false,\n\t\t\t\tclientIp: extractClientIp(c),\n\t\t\t\tuserAgent: c.req.header('user-agent'),\n\t\t\t\trequestMeta: {\n\t\t\t\t\ttemperature: request.temperature,\n\t\t\t\t\tmax_tokens: request.max_tokens || request.max_completion_tokens,\n\t\t\t\t\ttop_p: request.top_p,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Log incoming request\n\t\t\tlog.info(\n\t\t\t\t`→ POST /v1/chat/completions model=${request.model} stream=${request.stream || false} messages=${request.messages.length}`,\n\t\t\t);\n\n\t\t\t// Build upstream request based on protocol\n\t\t\tlet upstreamUrl: string;\n\t\t\tlet upstreamBody: unknown;\n\t\t\tlet upstreamHeaders: Record<string, string>;\n\n\t\t\tswitch (adapter) {\n\t\t\t\tcase 'anthropic': {\n\t\t\t\t\tupstreamUrl = `${baseUrl}/v1/messages`;\n\t\t\t\t\tupstreamBody = openaiToAnthropicRequest(request);\n\t\t\t\t\tupstreamHeaders = buildUpstreamHeaders(modelConfig, 'anthropic');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'gemini': {\n\t\t\t\t\tconst method = request.stream ? 'streamGenerateContent' : 'generateContent';\n\t\t\t\t\tupstreamUrl = `${baseUrl}/v1/models/${request.model}:${method}`;\n\t\t\t\t\tupstreamBody = openaiToGeminiRequest(request);\n\t\t\t\t\tupstreamHeaders = buildUpstreamHeaders(modelConfig, 'gemini');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\t// OpenAI adapter - passthrough with parameter normalization\n\t\t\t\t\tupstreamUrl = `${baseUrl}/v1/chat/completions`;\n\t\t\t\t\tupstreamBody = normalizeOpenAIRequest(request);\n\t\t\t\t\tupstreamHeaders = buildUpstreamHeaders(modelConfig, 'openai');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set provider info in audit context\n\t\t\tauditCtx.setProvider({\n\t\t\t\tprovider: adapter,\n\t\t\t\tupstreamUrl,\n\t\t\t});\n\n\t\t\t// Handle streaming\n\t\t\tif (request.stream) {\n\t\t\t\treturn handleStreamingRequest(c, upstreamUrl, upstreamBody, upstreamHeaders, adapter, request.model, auditCtx);\n\t\t\t}\n\n\t\t\t// Non-streaming request\n\t\t\tconst response = await makeUpstreamRequest(upstreamUrl, upstreamBody, upstreamHeaders);\n\t\t\tconst responseData = await response.json();\n\n\t\t\t// Convert response if needed\n\t\t\tlet result: any;\n\t\t\tswitch (adapter) {\n\t\t\t\tcase 'anthropic':\n\t\t\t\t\tresult = anthropicToOpenaiResponse(responseData, request.model);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'gemini':\n\t\t\t\t\tresult = geminiToOpenaiResponse(responseData, request.model);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tresult = responseData;\n\t\t\t}\n\n\t\t\t// Record token usage and complete audit\n\t\t\tif (result.usage) {\n\t\t\t\tauditCtx.setTokenUsage(result.usage.prompt_tokens || 0, result.usage.completion_tokens || 0);\n\t\t\t}\n\t\t\tauditCtx.setResponseMeta({\n\t\t\t\tfinish_reason: result.choices?.[0]?.finish_reason,\n\t\t\t\tmodel: result.model,\n\t\t\t});\n\t\t\tawait auditCtx.complete(200);\n\n\t\t\t// Log response\n\t\t\tconst usage = result.usage;\n\t\t\tlog.info(\n\t\t\t\t`← 200 /v1/chat/completions model=${result.model || request.model} tokens=${usage?.total_tokens || 0} (in=${usage?.prompt_tokens || 0} out=${usage?.completion_tokens || 0})`,\n\t\t\t);\n\n\t\t\treturn c.json(result);\n\t\t} catch (error) {\n\t\t\t// Record error in audit\n\t\t\tif (auditCtx) {\n\t\t\t\tawait auditCtx.error(error instanceof Error ? error.message : 'Unknown error', 'internal_error', 500);\n\t\t\t}\n\t\t\tlog.error('Chat completion error:', error);\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\terror: {\n\t\t\t\t\t\tmessage: error instanceof Error ? error.message : 'Internal server error',\n\t\t\t\t\t\ttype: 'api_error',\n\t\t\t\t\t\tcode: 'internal_error',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t});\n\n\t/**\n\t * Handle streaming request\n\t */\n\tasync function handleStreamingRequest(\n\t\tc: any,\n\t\tupstreamUrl: string,\n\t\tupstreamBody: unknown,\n\t\tupstreamHeaders: Record<string, string>,\n\t\tadapter: string,\n\t\tmodel: string,\n\t\tauditCtx?: ReturnType<typeof createAuditContext>,\n\t) {\n\t\tconst response = await makeUpstreamRequest(upstreamUrl, upstreamBody, upstreamHeaders, true);\n\n\t\tlet firstTokenRecorded = false;\n\t\tlet totalOutputTokens = 0;\n\n\t\t// For streaming, we need to convert events on the fly\n\t\treturn streamSSE(c, async (stream) => {\n\t\t\tconst reader = response.body?.getReader();\n\t\t\tif (!reader) {\n\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\t\t\t\tif (auditCtx) await auditCtx.complete(200);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst decoder = new TextDecoder();\n\t\t\tlet buffer = '';\n\n\t\t\ttry {\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\tif (done) break;\n\n\t\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\t\tconst lines = buffer.split('\\n');\n\t\t\t\t\tbuffer = lines.pop() || '';\n\n\t\t\t\t\tfor (const line of lines) {\n\t\t\t\t\t\tif (!line.trim()) continue;\n\n\t\t\t\t\t\tif (line.startsWith('data: ')) {\n\t\t\t\t\t\t\tconst data = line.slice(6);\n\t\t\t\t\t\t\tif (data === '[DONE]') {\n\t\t\t\t\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst parsed = JSON.parse(data);\n\t\t\t\t\t\t\t\tconst converted = convertStreamEvent(parsed, adapter, model);\n\t\t\t\t\t\t\t\tif (converted) {\n\t\t\t\t\t\t\t\t\t// Record first token for TTFT\n\t\t\t\t\t\t\t\t\tif (!firstTokenRecorded && auditCtx) {\n\t\t\t\t\t\t\t\t\t\tauditCtx.recordFirstToken();\n\t\t\t\t\t\t\t\t\t\tfirstTokenRecorded = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// Track usage from stream events\n\t\t\t\t\t\t\t\t\tif (converted.usage) {\n\t\t\t\t\t\t\t\t\t\ttotalOutputTokens = converted.usage.completion_tokens || totalOutputTokens;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tawait stream.writeSSE({ data: JSON.stringify(converted) });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// Skip invalid JSON\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (line.startsWith('event: ')) {\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Send done signal\n\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\n\t\t\t\t// Complete audit\n\t\t\t\tif (auditCtx) {\n\t\t\t\t\tauditCtx.setTokenUsage(0, totalOutputTokens); // Input tokens not available in streaming\n\t\t\t\t\tawait auditCtx.complete(200);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// Record streaming error\n\t\t\t\tif (auditCtx) {\n\t\t\t\t\tawait auditCtx.error(err instanceof Error ? err.message : 'Streaming error', 'streaming_error', 500);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t} finally {\n\t\t\t\treader.releaseLock();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Convert stream event to OpenAI format\n\t */\n\tfunction convertStreamEvent(event: any, adapter: string, model: string): any {\n\t\tswitch (adapter) {\n\t\t\tcase 'anthropic':\n\t\t\t\treturn convertAnthropicStreamEvent(event, model);\n\t\t\tcase 'gemini':\n\t\t\t\treturn convertGeminiStreamEvent(event, model);\n\t\t\tdefault:\n\t\t\t\treturn event;\n\t\t}\n\t}\n\n\t/**\n\t * Convert Anthropic stream event to OpenAI format\n\t */\n\tfunction convertAnthropicStreamEvent(event: any, model: string): any {\n\t\tif (event.type === 'content_block_delta') {\n\t\t\tif (event.delta?.type === 'text_delta') {\n\t\t\t\treturn {\n\t\t\t\t\tid: `chatcmpl-${Date.now()}`,\n\t\t\t\t\tobject: 'chat.completion.chunk',\n\t\t\t\t\tcreated: Math.floor(Date.now() / 1000),\n\t\t\t\t\tmodel,\n\t\t\t\t\tchoices: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tindex: 0,\n\t\t\t\t\t\t\tdelta: { content: event.delta.text },\n\t\t\t\t\t\t\tfinish_reason: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t}\n\t\t} else if (event.type === 'message_delta') {\n\t\t\tconst finishReason =\n\t\t\t\tevent.delta?.stop_reason === 'end_turn'\n\t\t\t\t\t? 'stop'\n\t\t\t\t\t: event.delta?.stop_reason === 'tool_use'\n\t\t\t\t\t\t? 'tool_calls'\n\t\t\t\t\t\t: null;\n\t\t\treturn {\n\t\t\t\tid: `chatcmpl-${Date.now()}`,\n\t\t\t\tobject: 'chat.completion.chunk',\n\t\t\t\tcreated: Math.floor(Date.now() / 1000),\n\t\t\t\tmodel,\n\t\t\t\tchoices: [\n\t\t\t\t\t{\n\t\t\t\t\t\tindex: 0,\n\t\t\t\t\t\tdelta: {},\n\t\t\t\t\t\tfinish_reason: finishReason,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tusage: event.usage\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tprompt_tokens: 0,\n\t\t\t\t\t\t\tcompletion_tokens: event.usage.output_tokens,\n\t\t\t\t\t\t\ttotal_tokens: event.usage.output_tokens,\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t};\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Convert Gemini stream event to OpenAI format\n\t */\n\tfunction convertGeminiStreamEvent(event: any, model: string): any {\n\t\tif (event.candidates?.[0]?.content?.parts) {\n\t\t\tconst parts = event.candidates[0].content.parts;\n\t\t\tconst textParts = parts.filter((p: any) => p.text);\n\n\t\t\tif (textParts.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tid: `chatcmpl-${Date.now()}`,\n\t\t\t\t\tobject: 'chat.completion.chunk',\n\t\t\t\t\tcreated: Math.floor(Date.now() / 1000),\n\t\t\t\t\tmodel,\n\t\t\t\t\tchoices: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tindex: 0,\n\t\t\t\t\t\t\tdelta: { content: textParts.map((p: any) => p.text).join('') },\n\t\t\t\t\t\t\tfinish_reason: event.candidates[0].finishReason === 'STOP' ? 'stop' : null,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t// =========================================================================\n\t// Anthropic Messages API\n\t// =========================================================================\n\n\tapp.post('/v1/messages', async (c) => {\n\t\ttry {\n\t\t\tconst body = await c.req.json();\n\t\t\tconst parseResult = CreateMessageRequestSchema.safeParse(body);\n\n\t\t\tif (!parseResult.success) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tmessage: 'Invalid request',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst request = parseResult.data;\n\t\t\tconst modelConfig = resolveModelConfig(request.model);\n\n\t\t\tif (!modelConfig) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tmessage: `Model ${request.model} not configured`,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// For Anthropic endpoint, we pass through to Anthropic or convert from OpenAI\n\t\t\tconst adapter = modelConfig.adapter || 'anthropic';\n\t\t\tconst baseUrl = normalizeBaseUrl(\n\t\t\t\tmodelConfig.adapters?.[adapter]?.baseUrl || modelConfig.baseUrl || 'https://api.anthropic.com',\n\t\t\t);\n\n\t\t\tconst upstreamUrl = `${baseUrl}/v1/messages`;\n\t\t\tconst upstreamHeaders = buildUpstreamHeaders(modelConfig, 'anthropic');\n\n\t\t\t// Log incoming request\n\t\t\tlog.info(`→ POST /v1/messages model=${request.model} messages=${request.messages.length}`);\n\n\t\t\tconst response = await makeUpstreamRequest(upstreamUrl, request, upstreamHeaders);\n\t\t\tconst responseData = await response.json();\n\n\t\t\t// Log response\n\t\t\tconst usage = responseData.usage;\n\t\t\tlog.info(\n\t\t\t\t`← 200 /v1/messages model=${responseData.model || request.model} tokens=${(usage?.input_tokens || 0) + (usage?.output_tokens || 0)} (in=${usage?.input_tokens || 0} out=${usage?.output_tokens || 0})`,\n\t\t\t);\n\n\t\t\treturn c.json(responseData);\n\t\t} catch (error) {\n\t\t\tlog.error('Messages error:', error);\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\terror: {\n\t\t\t\t\t\ttype: 'api_error',\n\t\t\t\t\t\tmessage: error instanceof Error ? error.message : 'Internal server error',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t});\n\n\t// =========================================================================\n\t// Gemini Generate Content API\n\t// =========================================================================\n\n\tapp.post('/v1/models/:model\\\\:generateContent', async (c) => {\n\t\ttry {\n\t\t\tconst model = c.req.param('model');\n\t\t\tif (!model) {\n\t\t\t\treturn c.json({ error: { message: 'Model parameter is required' } }, 400);\n\t\t\t}\n\n\t\t\tconst body = await c.req.json();\n\t\t\tconst parseResult = CreateGenerateContentRequestSchema.safeParse(body);\n\n\t\t\tif (!parseResult.success) {\n\t\t\t\treturn c.json({ error: { message: 'Invalid request' } }, 400);\n\t\t\t}\n\n\t\t\tconst request = parseResult.data;\n\t\t\tconst modelConfig = resolveModelConfig(model);\n\n\t\t\tif (!modelConfig) {\n\t\t\t\treturn c.json({ error: { message: `Model ${model} not configured` } }, 404);\n\t\t\t}\n\n\t\t\tconst baseUrl = normalizeBaseUrl(\n\t\t\t\tmodelConfig.adapters?.gemini?.baseUrl || modelConfig.baseUrl || 'https://generativelanguage.googleapis.com',\n\t\t\t);\n\n\t\t\tconst upstreamUrl = `${baseUrl}/v1/models/${model}:generateContent`;\n\t\t\tconst upstreamHeaders = buildUpstreamHeaders(modelConfig, 'gemini');\n\n\t\t\t// Log incoming request\n\t\t\tlog.info(`→ POST /v1/models/${model}:generateContent contents=${request.contents?.length || 0}`);\n\n\t\t\tconst response = await makeUpstreamRequest(upstreamUrl, request, upstreamHeaders);\n\t\t\tconst responseData = await response.json();\n\n\t\t\t// Log response\n\t\t\tconst usage = responseData.usageMetadata;\n\t\t\tlog.info(\n\t\t\t\t`← 200 /v1/models/${model}:generateContent tokens=${usage?.totalTokenCount || 0} (in=${usage?.promptTokenCount || 0} out=${usage?.candidatesTokenCount || 0})`,\n\t\t\t);\n\n\t\t\treturn c.json(responseData);\n\t\t} catch (error) {\n\t\t\tlog.error('Generate content error:', error);\n\t\t\treturn c.json({ error: { message: error instanceof Error ? error.message : 'Internal server error' } }, 500);\n\t\t}\n\t});\n\n\t// =========================================================================\n\t// Gemini Streaming Generate Content API\n\t// =========================================================================\n\n\tapp.post('/v1/models/:model\\\\:streamGenerateContent', async (c) => {\n\t\ttry {\n\t\t\tconst model = c.req.param('model');\n\t\t\tif (!model) {\n\t\t\t\treturn c.json({ error: { message: 'Model parameter is required' } }, 400);\n\t\t\t}\n\n\t\t\tconst body = await c.req.json();\n\t\t\tconst parseResult = CreateGenerateContentRequestSchema.safeParse(body);\n\n\t\t\tif (!parseResult.success) {\n\t\t\t\treturn c.json({ error: { message: 'Invalid request' } }, 400);\n\t\t\t}\n\n\t\t\tconst request = parseResult.data;\n\n\t\t\t// Log incoming request\n\t\t\tlog.info(`→ POST /v1/models/${model}:streamGenerateContent contents=${request.contents?.length || 0}`);\n\n\t\t\tconst modelConfig = resolveModelConfig(model);\n\n\t\t\tif (!modelConfig) {\n\t\t\t\treturn c.json({ error: { message: `Model ${model} not configured` } }, 404);\n\t\t\t}\n\n\t\t\tconst baseUrl = normalizeBaseUrl(\n\t\t\t\tmodelConfig.adapters?.gemini?.baseUrl || modelConfig.baseUrl || 'https://generativelanguage.googleapis.com',\n\t\t\t);\n\n\t\t\tconst upstreamUrl = `${baseUrl}/v1/models/${model}:streamGenerateContent`;\n\t\t\tconst upstreamHeaders = buildUpstreamHeaders(modelConfig, 'gemini');\n\n\t\t\tconst response = await makeUpstreamRequest(upstreamUrl, request, upstreamHeaders, true);\n\n\t\t\t// Stream the response directly\n\t\t\treturn streamSSE(c, async (stream) => {\n\t\t\t\tconst reader = response.body?.getReader();\n\t\t\t\tif (!reader) {\n\t\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst decoder = new TextDecoder();\n\t\t\t\tlet buffer = '';\n\n\t\t\t\ttry {\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\t\tif (done) break;\n\n\t\t\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\t\t\tconst lines = buffer.split('\\n');\n\t\t\t\t\t\tbuffer = lines.pop() || '';\n\n\t\t\t\t\t\tfor (const line of lines) {\n\t\t\t\t\t\t\tif (!line.trim()) continue;\n\n\t\t\t\t\t\t\tif (line.startsWith('data: ')) {\n\t\t\t\t\t\t\t\tconst data = line.slice(6);\n\t\t\t\t\t\t\t\tif (data === '[DONE]') {\n\t\t\t\t\t\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tawait stream.writeSSE({ data });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tawait stream.writeSSE({ data: '[DONE]' });\n\t\t\t\t} finally {\n\t\t\t\t\treader.releaseLock();\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tlog.error('Stream generate content error:', error);\n\t\t\treturn c.json({ error: { message: error instanceof Error ? error.message : 'Internal server error' } }, 500);\n\t\t}\n\t});\n\n\t// =========================================================================\n\t// OpenAI Responses API\n\t// =========================================================================\n\n\tapp.post('/v1/responses', async (c) => {\n\t\tlet auditCtx: ReturnType<typeof createAuditContext> | null = null;\n\n\t\ttry {\n\t\t\tconst body = await c.req.json();\n\t\t\tconst parseResult = CreateResponseRequestSchema.safeParse(body);\n\n\t\t\tif (!parseResult.success) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: 'Invalid request',\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tparam: null,\n\t\t\t\t\t\t\tcode: 'invalid_request',\n\t\t\t\t\t\t\tdetails: parseResult.error.issues,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst request = parseResult.data;\n\n\t\t\t// Handle previous_response_id - load previous context\n\t\t\tlet previousContext: { input: unknown; output: unknown[] } | null = null;\n\t\t\tif (request.previous_response_id) {\n\t\t\t\ttry {\n\t\t\t\t\tconst { isDbInitialized, getEntityManager } = await import('../audit/server/db');\n\t\t\t\t\tconst { ResponseEntity } = await import('../audit/entities');\n\t\t\t\t\tif (isDbInitialized()) {\n\t\t\t\t\t\tconst em = getEntityManager().fork();\n\t\t\t\t\t\tconst prevResponse = await em.findOne(ResponseEntity, { responseId: request.previous_response_id });\n\t\t\t\t\t\tif (prevResponse) {\n\t\t\t\t\t\t\tpreviousContext = {\n\t\t\t\t\t\t\t\tinput: prevResponse.input,\n\t\t\t\t\t\t\t\toutput: prevResponse.output,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tlog.info(`Loaded previous response: ${request.previous_response_id}`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlog.warn(`Previous response not found: ${request.previous_response_id}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlog.warn('Failed to load previous response:', e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst modelConfig = resolveModelConfig(request.model);\n\n\t\t\tif (!modelConfig) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: `Model ${request.model} not configured`,\n\t\t\t\t\t\t\ttype: 'invalid_request_error',\n\t\t\t\t\t\t\tparam: 'model',\n\t\t\t\t\t\t\tcode: 'model_not_found',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Determine adapter - for Responses API, we convert to Chat Completions\n\t\t\tconst adapter = modelConfig.adapter || 'openai';\n\t\t\tconst baseUrl = normalizeBaseUrl(\n\t\t\t\tmodelConfig.adapters?.[adapter]?.baseUrl || modelConfig.baseUrl || 'https://api.openai.com',\n\t\t\t);\n\n\t\t\t// Create audit context\n\t\t\tauditCtx = createAuditContext({\n\t\t\t\tmethod: 'POST',\n\t\t\t\tendpoint: '/v1/responses',\n\t\t\t\tmodel: request.model,\n\t\t\t\tinputProtocol: ChatProtocol.OPENAI,\n\t\t\t\toutputProtocol: ChatProtocol.OPENAI,\n\t\t\t\tstreaming: request.stream || false,\n\t\t\t\tclientIp: extractClientIp(c),\n\t\t\t\tuserAgent: c.req.header('user-agent'),\n\t\t\t\trequestMeta: {\n\t\t\t\t\ttemperature: request.temperature,\n\t\t\t\t\tmax_output_tokens: request.max_output_tokens,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Log incoming request\n\t\t\tconst inputType =\n\t\t\t\ttypeof request.input === 'string'\n\t\t\t\t\t? 'string'\n\t\t\t\t\t: Array.isArray(request.input)\n\t\t\t\t\t\t? `array[${request.input.length}]`\n\t\t\t\t\t\t: 'object';\n\t\t\tlog.info(`→ POST /v1/responses model=${request.model} stream=${request.stream || false} input=${inputType}`);\n\n\t\t\t// Convert Responses API request to Chat Completions format\n\t\t\tconst chatRequest = responsesToChatCompletions(request, previousContext);\n\n\t\t\t// Build upstream request\n\t\t\tconst upstreamUrl = `${baseUrl}/v1/chat/completions`;\n\t\t\tconst upstreamHeaders = buildUpstreamHeaders(modelConfig, 'openai');\n\n\t\t\tauditCtx.setProvider({\n\t\t\t\tprovider: adapter,\n\t\t\t\tupstreamUrl,\n\t\t\t});\n\n\t\t\t// Handle streaming\n\t\t\tif (request.stream) {\n\t\t\t\treturn handleResponsesStreamingRequest(c, upstreamUrl, chatRequest, upstreamHeaders, request.model, auditCtx);\n\t\t\t}\n\n\t\t\t// Non-streaming request\n\t\t\tconst response = await makeUpstreamRequest(upstreamUrl, chatRequest, upstreamHeaders);\n\t\t\tconst chatResponse = await response.json();\n\n\t\t\t// Convert Chat Completions response to Responses format\n\t\t\tconst result = chatCompletionsToResponses(chatResponse, request.model);\n\n\t\t\t// Store response for future previous_response_id lookups\n\t\t\ttry {\n\t\t\t\tconst { isDbInitialized, getEntityManager } = await import('../audit/server/db');\n\t\t\t\tconst { ResponseEntity } = await import('../audit/entities');\n\t\t\t\tif (isDbInitialized()) {\n\t\t\t\t\tconst em = getEntityManager().fork();\n\t\t\t\t\tconst responseEntity = new ResponseEntity();\n\t\t\t\t\tresponseEntity.responseId = result.id;\n\t\t\t\t\tresponseEntity.model = result.model;\n\t\t\t\t\tresponseEntity.status = result.status;\n\t\t\t\t\tresponseEntity.input = request.input;\n\t\t\t\t\tresponseEntity.output = result.output;\n\t\t\t\t\tresponseEntity.usage = result.usage;\n\t\t\t\t\tresponseEntity.instructions = request.instructions ?? undefined;\n\t\t\t\t\tresponseEntity.previousResponseId = request.previous_response_id ?? undefined;\n\t\t\t\t\tresponseEntity.tools = request.tools ?? undefined;\n\t\t\t\t\tresponseEntity.toolChoice = request.tool_choice ?? undefined;\n\t\t\t\t\tresponseEntity.metadata = request.metadata as Record<string, unknown>;\n\t\t\t\t\tresponseEntity.durationMs = auditCtx?.getDuration();\n\t\t\t\t\tem.persist(responseEntity);\n\t\t\t\t\tawait em.flush();\n\t\t\t\t\tlog.debug(`Stored response: ${result.id}`);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tlog.warn('Failed to store response:', e);\n\t\t\t}\n\n\t\t\t// Record usage\n\t\t\tif (chatResponse.usage) {\n\t\t\t\tauditCtx.setTokenUsage(chatResponse.usage.prompt_tokens || 0, chatResponse.usage.completion_tokens || 0);\n\t\t\t}\n\t\t\tauditCtx.setResponseMeta({\n\t\t\t\tstatus: result.status,\n\t\t\t\toutput_items: result.output.length,\n\t\t\t});\n\t\t\tawait auditCtx.complete(200);\n\n\t\t\t// Log response\n\t\t\tconst usage = chatResponse.usage;\n\t\t\tlog.info(\n\t\t\t\t`← 200 /v1/responses model=${result.model || request.model} status=${result.status} tokens=${usage?.total_tokens || 0}`,\n\t\t\t);\n\n\t\t\treturn c.json(result);\n\t\t} catch (error) {\n\t\t\tif (auditCtx) {\n\t\t\t\tawait auditCtx.error(error instanceof Error ? error.message : 'Unknown error', 'internal_error', 500);\n\t\t\t}\n\t\t\tlog.error('Responses API error:', error);\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\terror: {\n\t\t\t\t\t\tmessage: error instanceof Error ? error.message : 'Internal server error',\n\t\t\t\t\t\ttype: 'api_error',\n\t\t\t\t\t\tcode: 'internal_error',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t});\n\n\t/**\n\t * Convert Responses API request to Chat Completions format\n\t */\n\tfunction responsesToChatCompletions(\n\t\trequest: CreateResponseRequest,\n\t\tpreviousContext?: { input: unknown; output: unknown[] } | null,\n\t): CreateChatCompletionRequest {\n\t\tconst messages: CreateChatCompletionRequest['messages'] = [];\n\n\t\t// Add system instruction if present\n\t\tif (request.instructions) {\n\t\t\tmessages.push({\n\t\t\t\trole: 'system',\n\t\t\t\tcontent: request.instructions,\n\t\t\t});\n\t\t}\n\n\t\t// Add previous context if available (previous_response_id)\n\t\tif (previousContext) {\n\t\t\t// Add previous input\n\t\t\tconst prevInput = previousContext.input;\n\t\t\tif (typeof prevInput === 'string') {\n\t\t\t\tmessages.push({ role: 'user', content: prevInput });\n\t\t\t} else if (Array.isArray(prevInput)) {\n\t\t\t\tfor (const item of prevInput as any[]) {\n\t\t\t\t\tif (item.type === 'message') {\n\t\t\t\t\t\tmessages.push({\n\t\t\t\t\t\t\trole: item.role as 'user' | 'assistant' | 'system',\n\t\t\t\t\t\t\tcontent: typeof item.content === 'string' ? item.content : JSON.stringify(item.content),\n\t\t\t\t\t\t} as any);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add previous output as assistant messages\n\t\t\tfor (const item of previousContext.output as any[]) {\n\t\t\t\tif (item.type === 'message' && item.role === 'assistant') {\n\t\t\t\t\tconst textContent = item.content?.find((c: any) => c.type === 'text' || c.type === 'output_text');\n\t\t\t\t\tif (textContent) {\n\t\t\t\t\t\tmessages.push({\n\t\t\t\t\t\t\trole: 'assistant',\n\t\t\t\t\t\t\tcontent: textContent.text,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Convert current input to messages\n\t\tif (typeof request.input === 'string') {\n\t\t\tmessages.push({\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: request.input,\n\t\t\t});\n\t\t} else if (Array.isArray(request.input)) {\n\t\t\tfor (const item of request.input) {\n\t\t\t\tif (item.type === 'message') {\n\t\t\t\t\tmessages.push({\n\t\t\t\t\t\trole: item.role as 'user' | 'assistant' | 'system',\n\t\t\t\t\t\tcontent: typeof item.content === 'string' ? item.content : JSON.stringify(item.content),\n\t\t\t\t\t} as any);\n\t\t\t\t}\n\t\t\t\t// item_reference is handled differently - would need to fetch the referenced item\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tmodel: request.model,\n\t\t\tmessages,\n\t\t\ttemperature: request.temperature,\n\t\t\ttop_p: request.top_p,\n\t\t\tmax_tokens: request.max_output_tokens,\n\t\t\tstream: request.stream,\n\t\t\ttools: request.tools,\n\t\t\ttool_choice: request.tool_choice,\n\t\t\tparallel_tool_calls: request.parallel_tool_calls,\n\t\t\tmetadata: request.metadata,\n\t\t\tstore: request.store,\n\t\t\tuser: request.user,\n\t\t} as CreateChatCompletionRequest;\n\t}\n\n\t/**\n\t * Convert Chat Completions response to Responses format\n\t */\n\tfunction chatCompletionsToResponses(chatResponse: any, model: string): any {\n\t\tconst responseId = `resp_${chatResponse.id || Date.now()}`;\n\t\tconst output: any[] = [];\n\n\t\tfor (const choice of chatResponse.choices || []) {\n\t\t\tconst message = choice.message;\n\t\t\tif (message) {\n\t\t\t\toutput.push({\n\t\t\t\t\tid: `item_${responseId}_${choice.index}`,\n\t\t\t\t\ttype: 'message',\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: message.content ? [{ type: 'text', text: message.content }] : [],\n\t\t\t\t\tstatus: 'completed',\n\t\t\t\t});\n\n\t\t\t\t// Handle tool calls\n\t\t\t\tif (message.tool_calls) {\n\t\t\t\t\tfor (const toolCall of message.tool_calls) {\n\t\t\t\t\t\toutput.push({\n\t\t\t\t\t\t\tid: toolCall.id,\n\t\t\t\t\t\t\ttype: 'function_call',\n\t\t\t\t\t\t\tname: toolCall.function?.name,\n\t\t\t\t\t\t\targuments: toolCall.function?.arguments,\n\t\t\t\t\t\t\tstatus: 'completed',\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tid: responseId,\n\t\t\tobject: 'response',\n\t\t\tcreated_at: chatResponse.created || Math.floor(Date.now() / 1000),\n\t\t\tmodel: chatResponse.model || model,\n\t\t\tstatus: 'completed',\n\t\t\toutput,\n\t\t\tusage: chatResponse.usage,\n\t\t\tmetadata: {},\n\t\t\terror: null,\n\t\t};\n\t}\n\n\t/**\n\t * Handle Responses API streaming\n\t */\n\tasync function handleResponsesStreamingRequest(\n\t\tc: any,\n\t\tupstreamUrl: string,\n\t\tupstreamBody: unknown,\n\t\tupstreamHeaders: Record<string, string>,\n\t\tmodel: string,\n\t\tauditCtx?: ReturnType<typeof createAuditContext>,\n\t) {\n\t\tconst response = await makeUpstreamRequest(\n\t\t\tupstreamUrl,\n\t\t\t{ ...(upstreamBody as any), stream: true },\n\t\t\tupstreamHeaders,\n\t\t\ttrue,\n\t\t);\n\n\t\tlet firstTokenRecorded = false;\n\t\tconst responseId = `resp_${Date.now()}`;\n\n\t\treturn streamSSE(c, async (stream) => {\n\t\t\tconst reader = response.body?.getReader();\n\t\t\tif (!reader) {\n\t\t\t\tawait stream.writeSSE({ event: 'response.done', data: JSON.stringify({ type: 'response.done' }) });\n\t\t\t\tif (auditCtx) await auditCtx.complete(200);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Send initial event\n\t\t\tawait stream.writeSSE({\n\t\t\t\tevent: 'response.created',\n\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\ttype: 'response.created',\n\t\t\t\t\tresponse: {\n\t\t\t\t\t\tid: responseId,\n\t\t\t\t\t\tobject: 'response',\n\t\t\t\t\t\tcreated_at: Math.floor(Date.now() / 1000),\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tstatus: 'in_progress',\n\t\t\t\t\t\toutput: [],\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tconst decoder = new TextDecoder();\n\t\t\tlet buffer = '';\n\t\t\tlet outputItemId = `item_${responseId}_0`;\n\n\t\t\ttry {\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\tif (done) break;\n\n\t\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\t\tconst lines = buffer.split('\\n');\n\t\t\t\t\tbuffer = lines.pop() || '';\n\n\t\t\t\t\tfor (const line of lines) {\n\t\t\t\t\t\tif (!line.trim() || !line.startsWith('data: ')) continue;\n\n\t\t\t\t\t\tconst data = line.slice(6);\n\t\t\t\t\t\tif (data === '[DONE]') continue;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst parsed = JSON.parse(data);\n\t\t\t\t\t\t\tconst delta = parsed.choices?.[0]?.delta;\n\n\t\t\t\t\t\t\tif (delta?.content) {\n\t\t\t\t\t\t\t\tif (!firstTokenRecorded && auditCtx) {\n\t\t\t\t\t\t\t\t\tauditCtx.recordFirstToken();\n\t\t\t\t\t\t\t\t\tfirstTokenRecorded = true;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tawait stream.writeSSE({\n\t\t\t\t\t\t\t\t\tevent: 'response.output_text.delta',\n\t\t\t\t\t\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\t\t\t\t\t\ttype: 'response.output_text.delta',\n\t\t\t\t\t\t\t\t\t\toutput_index: 0,\n\t\t\t\t\t\t\t\t\t\tcontent_index: 0,\n\t\t\t\t\t\t\t\t\t\tdelta: delta.content,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Skip invalid JSON\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Send completion events\n\t\t\t\tawait stream.writeSSE({\n\t\t\t\t\tevent: 'response.output_item.done',\n\t\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\t\ttype: 'response.output_item.done',\n\t\t\t\t\t\toutput_index: 0,\n\t\t\t\t\t\titem: {\n\t\t\t\t\t\t\tid: outputItemId,\n\t\t\t\t\t\t\ttype: 'message',\n\t\t\t\t\t\t\trole: 'assistant',\n\t\t\t\t\t\t\tstatus: 'completed',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t});\n\n\t\t\t\tawait stream.writeSSE({\n\t\t\t\t\tevent: 'response.done',\n\t\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\t\ttype: 'response.done',\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tid: responseId,\n\t\t\t\t\t\t\tstatus: 'completed',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t});\n\n\t\t\t\tif (auditCtx) await auditCtx.complete(200);\n\t\t\t} catch (err) {\n\t\t\t\tif (auditCtx) {\n\t\t\t\t\tawait auditCtx.error(err instanceof Error ? err.message : 'Streaming error', 'streaming_error', 500);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t} finally {\n\t\t\t\treader.releaseLock();\n\t\t\t}\n\t\t});\n\t}\n\n\t// =========================================================================\n\t// Models endpoint\n\t// =========================================================================\n\n\tapp.get('/v1/models', async (c) => {\n\t\tconst fetchUpstream = c.req.query('fetch') === 'true';\n\t\tconst allModels: Array<{\n\t\t\tid: string;\n\t\t\tobject: string;\n\t\t\tcreated: number;\n\t\t\towned_by: string;\n\t\t\tcontext_window?: number;\n\t\t\tmax_input_tokens?: number;\n\t\t\tmax_output_tokens?: number;\n\t\t}> = [];\n\n\t\t// Add configured models\n\t\tfor (const m of config.models || []) {\n\t\t\tallModels.push({\n\t\t\t\tid: m.name,\n\t\t\t\tobject: 'model',\n\t\t\t\tcreated: Math.floor(Date.now() / 1000),\n\t\t\t\towned_by: 'mcps',\n\t\t\t\tcontext_window: m.contextWindow,\n\t\t\t\tmax_input_tokens: m.maxInputTokens,\n\t\t\t\tmax_output_tokens: m.maxOutputTokens,\n\t\t\t});\n\n\t\t\t// Fetch upstream models if enabled\n\t\t\tif (fetchUpstream && m.fetchUpstreamModels && m.baseUrl) {\n\t\t\t\ttry {\n\t\t\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t};\n\t\t\t\t\tif (m.apiKey) {\n\t\t\t\t\t\theaders.Authorization = `Bearer ${m.apiKey}`;\n\t\t\t\t\t}\n\t\t\t\t\tObject.assign(headers, m.headers || {});\n\n\t\t\t\t\tconst normalizedUrl = normalizeBaseUrl(m.baseUrl);\n\t\t\t\t\tconst upstreamUrl = `${normalizedUrl}/v1/models`;\n\n\t\t\t\t\tconst res = await fetch(upstreamUrl, { headers });\n\t\t\t\t\tif (res.ok) {\n\t\t\t\t\t\tconst data = await res.json();\n\t\t\t\t\t\tif (data.data && Array.isArray(data.data)) {\n\t\t\t\t\t\t\tfor (const model of data.data) {\n\t\t\t\t\t\t\t\t// Avoid duplicates\n\t\t\t\t\t\t\t\tif (!allModels.some((existing) => existing.id === model.id)) {\n\t\t\t\t\t\t\t\t\tallModels.push({\n\t\t\t\t\t\t\t\t\t\tid: model.id,\n\t\t\t\t\t\t\t\t\t\tobject: model.object || 'model',\n\t\t\t\t\t\t\t\t\t\tcreated: model.created || Math.floor(Date.now() / 1000),\n\t\t\t\t\t\t\t\t\t\towned_by: model.owned_by || m.name.split('/')[0] || 'upstream',\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlog.warn(`Failed to fetch upstream models from ${m.baseUrl}: ${e}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlog.debug(`→ GET /v1/models count=${allModels.length} fetch=${fetchUpstream}`);\n\n\t\treturn c.json({\n\t\t\tobject: 'list',\n\t\t\tdata: allModels,\n\t\t});\n\t});\n\n\treturn app;\n}\n"],"names":["consola","Hono","streamSSE","ChatProtocol","createAuditContext","extractClientIp","openaiToAnthropicRequest","anthropicToOpenaiResponse","openaiToGeminiRequest","geminiToOpenaiResponse","CreateChatCompletionRequestSchema","CreateResponseRequestSchema","CreateMessageRequestSchema","CreateGenerateContentRequestSchema","log","withTag","createChatHandler","options","app","config","resolveModelConfig","modelName","models","length","modelConfig","name","pattern","includes","regex","RegExp","replace","test","makeUpstreamRequest","url","body","headers","_stream","response","fetch","method","JSON","stringify","ok","errorText","text","error","status","Error","normalizeBaseUrl","buildUpstreamHeaders","adapter","apiKey","Authorization","Object","assign","adapters","normalizeOpenAIRequest","request","normalized","max_completion_tokens","max_tokens","enable_thinking","undefined","thinking","type","post","c","auditCtx","req","json","parseResult","safeParse","success","message","param","code","details","issues","data","model","baseUrl","outputProtocol","ANTHROPIC","GEMINI","OPENAI","endpoint","inputProtocol","streaming","stream","clientIp","userAgent","header","requestMeta","temperature","top_p","info","messages","upstreamUrl","upstreamBody","upstreamHeaders","setProvider","provider","handleStreamingRequest","responseData","result","usage","setTokenUsage","prompt_tokens","completion_tokens","setResponseMeta","finish_reason","choices","complete","total_tokens","firstTokenRecorded","totalOutputTokens","reader","getReader","writeSSE","decoder","TextDecoder","buffer","done","value","read","decode","lines","split","pop","line","trim","startsWith","slice","parsed","parse","converted","convertStreamEvent","recordFirstToken","err","releaseLock","event","convertAnthropicStreamEvent","convertGeminiStreamEvent","delta","id","Date","now","object","created","Math","floor","index","content","finishReason","stop_reason","output_tokens","candidates","parts","textParts","filter","p","map","join","input_tokens","gemini","contents","usageMetadata","totalTokenCount","promptTokenCount","candidatesTokenCount","previousContext","previous_response_id","isDbInitialized","getEntityManager","ResponseEntity","em","fork","prevResponse","findOne","responseId","input","output","warn","e","max_output_tokens","inputType","Array","isArray","chatRequest","responsesToChatCompletions","handleResponsesStreamingRequest","chatResponse","chatCompletionsToResponses","responseEntity","instructions","previousResponseId","tools","toolChoice","tool_choice","metadata","durationMs","getDuration","persist","flush","debug","output_items","push","role","prevInput","item","textContent","find","parallel_tool_calls","store","user","choice","tool_calls","toolCall","function","arguments","created_at","outputItemId","output_index","content_index","get","fetchUpstream","query","allModels","m","owned_by","context_window","contextWindow","max_input_tokens","maxInputTokens","maxOutputTokens","fetchUpstreamModels","normalizedUrl","res","some","existing"],"mappings":"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"}
|
package/lib/chat/index.js
CHANGED
package/lib/chat/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/chat/index.ts"],"sourcesContent":["/**\n * Chat API Module\n * Provides unified AI model gateway with protocol conversion\n */\n\n// Types\nexport * from './types';\n\n// Converters\nexport * from './converters';\n\n// Audit\nexport * from '
|
|
1
|
+
{"version":3,"sources":["../../src/chat/index.ts"],"sourcesContent":["/**\n * Chat API Module\n * Provides unified AI model gateway with protocol conversion\n */\n\n// Types\nexport * from './types';\n\n// Converters\nexport * from './converters';\n\n// Audit\nexport * from '../audit/chat';\n\n// Handler\nexport { createChatHandler, type ChatHandlerOptions } from './handler';\n"],"names":["createChatHandler"],"mappings":"AAAA;;;CAGC,GAED,QAAQ;AACR,cAAc,UAAU;AAExB,aAAa;AACb,cAAc,eAAe;AAE7B,QAAQ;AACR,cAAc,gBAAgB;AAE9B,UAAU;AACV,SAASA,iBAAiB,QAAiC,YAAY"}
|
package/lib/cli-start.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { serve } from "@hono/node-server";
|
|
2
|
+
import consola from "consola";
|
|
3
|
+
import { createServer } from "./server/server.js";
|
|
4
|
+
const log = consola.withTag("mcps");
|
|
5
|
+
let serverHandle;
|
|
6
|
+
function shutdown() {
|
|
7
|
+
log.info("Shutting down...");
|
|
8
|
+
if (serverHandle) {
|
|
9
|
+
serverHandle.close(() => process.exit(0));
|
|
10
|
+
setTimeout(() => process.exit(1), 3000);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
process.exit(0);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
process.on("SIGINT", shutdown);
|
|
17
|
+
process.on("SIGTERM", shutdown);
|
|
18
|
+
export async function startServer(options) {
|
|
19
|
+
const port = Number.parseInt(options.port, 10);
|
|
20
|
+
const { app, printEndpoints, finalize } = createServer({
|
|
21
|
+
cwd: options.cwd,
|
|
22
|
+
port,
|
|
23
|
+
discoveryConfig: options.discoveryConfig,
|
|
24
|
+
setup: options.setup
|
|
25
|
+
});
|
|
26
|
+
await finalize();
|
|
27
|
+
log.info(`Starting MCPS server on port ${port}`);
|
|
28
|
+
serverHandle = serve({
|
|
29
|
+
fetch: app.fetch,
|
|
30
|
+
port,
|
|
31
|
+
hostname: "0.0.0.0"
|
|
32
|
+
});
|
|
33
|
+
log.success(`MCPS server running at http://localhost:${port}`);
|
|
34
|
+
printEndpoints();
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=cli-start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-start.ts"],"sourcesContent":["import { serve } from '@hono/node-server';\nimport consola from 'consola';\nimport { createServer, type CreateServerOptions } from './server/server';\n\nconst log = consola.withTag('mcps');\n\nlet serverHandle: ReturnType<typeof serve> | undefined;\n\nfunction shutdown() {\n\tlog.info('Shutting down...');\n\tif (serverHandle) {\n\t\tserverHandle.close(() => process.exit(0));\n\t\tsetTimeout(() => process.exit(1), 3000);\n\t} else {\n\t\tprocess.exit(0);\n\t}\n}\n\nprocess.on('SIGINT', shutdown);\nprocess.on('SIGTERM', shutdown);\n\nexport async function startServer(options: { port: string; cwd: string; discoveryConfig: boolean; setup?: CreateServerOptions['setup'] }) {\n\tconst port = Number.parseInt(options.port, 10);\n\tconst { app, printEndpoints, finalize } = createServer({\n\t\tcwd: options.cwd,\n\t\tport,\n\t\tdiscoveryConfig: options.discoveryConfig,\n\t\tsetup: options.setup,\n\t});\n\n\tawait finalize();\n\n\tlog.info(`Starting MCPS server on port ${port}`);\n\n\tserverHandle = serve({\n\t\tfetch: app.fetch,\n\t\tport,\n\t\thostname: '0.0.0.0',\n\t});\n\n\tlog.success(`MCPS server running at http://localhost:${port}`);\n\tprintEndpoints();\n}\n"],"names":["serve","consola","createServer","log","withTag","serverHandle","shutdown","info","close","process","exit","setTimeout","on","startServer","options","port","Number","parseInt","app","printEndpoints","finalize","cwd","discoveryConfig","setup","fetch","hostname","success"],"mappings":"AAAA,SAASA,KAAK,QAAQ,oBAAoB;AAC1C,OAAOC,aAAa,UAAU;AAC9B,SAASC,YAAY,QAAkC,kBAAkB;AAEzE,MAAMC,MAAMF,QAAQG,OAAO,CAAC;AAE5B,IAAIC;AAEJ,SAASC;IACRH,IAAII,IAAI,CAAC;IACT,IAAIF,cAAc;QACjBA,aAAaG,KAAK,CAAC,IAAMC,QAAQC,IAAI,CAAC;QACtCC,WAAW,IAAMF,QAAQC,IAAI,CAAC,IAAI;IACnC,OAAO;QACND,QAAQC,IAAI,CAAC;IACd;AACD;AAEAD,QAAQG,EAAE,CAAC,UAAUN;AACrBG,QAAQG,EAAE,CAAC,WAAWN;AAEtB,OAAO,eAAeO,YAAYC,OAAsG;IACvI,MAAMC,OAAOC,OAAOC,QAAQ,CAACH,QAAQC,IAAI,EAAE;IAC3C,MAAM,EAAEG,GAAG,EAAEC,cAAc,EAAEC,QAAQ,EAAE,GAAGlB,aAAa;QACtDmB,KAAKP,QAAQO,GAAG;QAChBN;QACAO,iBAAiBR,QAAQQ,eAAe;QACxCC,OAAOT,QAAQS,KAAK;IACrB;IAEA,MAAMH;IAENjB,IAAII,IAAI,CAAC,CAAC,6BAA6B,EAAEQ,MAAM;IAE/CV,eAAeL,MAAM;QACpBwB,OAAON,IAAIM,KAAK;QAChBT;QACAU,UAAU;IACX;IAEAtB,IAAIuB,OAAO,CAAC,CAAC,wCAAwC,EAAEX,MAAM;IAC7DI;AACD"}
|
package/lib/cli.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* Create a reusable Commander program for MCPS server.
|
|
4
|
+
* Consumers can register providers before calling `program.parseAsync()`.
|
|
5
|
+
*/ export function createProgram(options = {}) {
|
|
6
|
+
const { name = 'mcps', description = 'MCP Proxy Server - Unified MCP service with relay, SQL, CLS, and Prometheus support', version = '0.1.0', defaultPort = '8036', beforeStart, setup } = options;
|
|
7
|
+
const program = new Command();
|
|
8
|
+
program.name(name).description(description).version(version).option('-p, --port <port>', 'Port to listen on', defaultPort).option('-c, --cwd <path>', 'Working directory for config files', process.cwd()).option('--discovery-config', 'Enable server config discovery endpoints', false).action(async (opts)=>{
|
|
9
|
+
await beforeStart?.();
|
|
10
|
+
const { startServer } = await import('./cli-start.js');
|
|
11
|
+
await startServer({
|
|
12
|
+
...opts,
|
|
13
|
+
setup
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
return program;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=cli.js.map
|
package/lib/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { Command } from 'commander';\nimport type { CreateServerOptions } from './server/server';\n\nexport interface CreateProgramOptions {\n\tname?: string;\n\tdescription?: string;\n\tversion?: string;\n\tdefaultPort?: string;\n\t/** Called before the server starts, allows registering additional providers via side-effect imports */\n\tbeforeStart?: () => void | Promise<void>;\n\t/** Server setup callback, passed to createServer. Use to register plugins like audit. */\n\tsetup?: CreateServerOptions['setup'];\n}\n\n/**\n * Create a reusable Commander program for MCPS server.\n * Consumers can register providers before calling `program.parseAsync()`.\n */\nexport function createProgram(options: CreateProgramOptions = {}): Command {\n\tconst {\n\t\tname = 'mcps',\n\t\tdescription = 'MCP Proxy Server - Unified MCP service with relay, SQL, CLS, and Prometheus support',\n\t\tversion = '0.1.0',\n\t\tdefaultPort = '8036',\n\t\tbeforeStart,\n\t\tsetup,\n\t} = options;\n\n\tconst program = new Command();\n\n\tprogram\n\t\t.name(name)\n\t\t.description(description)\n\t\t.version(version)\n\t\t.option('-p, --port <port>', 'Port to listen on', defaultPort)\n\t\t.option('-c, --cwd <path>', 'Working directory for config files', process.cwd())\n\t\t.option('--discovery-config', 'Enable server config discovery endpoints', false)\n\t\t.action(async (opts) => {\n\t\t\tawait beforeStart?.();\n\t\t\tconst { startServer } = await import('./cli-start.js');\n\t\t\tawait startServer({ ...opts, setup });\n\t\t});\n\n\treturn program;\n}\n"],"names":["Command","createProgram","options","name","description","version","defaultPort","beforeStart","setup","program","option","process","cwd","action","opts","startServer"],"mappings":"AAAA,SAASA,OAAO,QAAQ,YAAY;AAcpC;;;CAGC,GACD,OAAO,SAASC,cAAcC,UAAgC,CAAC,CAAC;IAC/D,MAAM,EACLC,OAAO,MAAM,EACbC,cAAc,qFAAqF,EACnGC,UAAU,OAAO,EACjBC,cAAc,MAAM,EACpBC,WAAW,EACXC,KAAK,EACL,GAAGN;IAEJ,MAAMO,UAAU,IAAIT;IAEpBS,QACEN,IAAI,CAACA,MACLC,WAAW,CAACA,aACZC,OAAO,CAACA,SACRK,MAAM,CAAC,qBAAqB,qBAAqBJ,aACjDI,MAAM,CAAC,oBAAoB,sCAAsCC,QAAQC,GAAG,IAC5EF,MAAM,CAAC,sBAAsB,4CAA4C,OACzEG,MAAM,CAAC,OAAOC;QACd,MAAMP;QACN,MAAM,EAAEQ,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC;QACrC,MAAMA,YAAY;YAAE,GAAGD,IAAI;YAAEN;QAAM;IACpC;IAED,OAAOC;AACR"}
|
package/lib/contracts/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { AuditContract, AuditEventSchema, AuditQuerySchema, AuditStatsSchema } from "
|
|
1
|
+
export { AuditContract, AuditEventSchema, AuditQuerySchema, AuditStatsSchema } from "../audit/AuditContract.js";
|
|
2
2
|
export { McpsContract, ServiceOverviewSchema, ServerInfoSchema, ServerTypeInfoSchema, ModelInfoSchema, RequestStatsSchema, ToolInfoSchema, ToolParameterSchema } from "./McpsContract.js";
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/contracts/index.ts"],"sourcesContent":["export { AuditContract, AuditEventSchema, AuditQuerySchema, AuditStatsSchema, type AuditEvent } from '
|
|
1
|
+
{"version":3,"sources":["../../src/contracts/index.ts"],"sourcesContent":["export { AuditContract, AuditEventSchema, AuditQuerySchema, AuditStatsSchema, type AuditEvent } from '../audit/AuditContract';\nexport {\n\tMcpsContract,\n\tServiceOverviewSchema,\n\tServerInfoSchema,\n\tServerTypeInfoSchema,\n\tModelInfoSchema,\n\tRequestStatsSchema,\n\tToolInfoSchema,\n\tToolParameterSchema,\n\ttype ServiceOverview,\n\ttype ServerInfo,\n\ttype ServerTypeInfo,\n\ttype ModelInfo,\n\ttype RequestStats,\n\ttype ToolInfo,\n\ttype ToolParameter,\n} from './McpsContract';"],"names":["AuditContract","AuditEventSchema","AuditQuerySchema","AuditStatsSchema","McpsContract","ServiceOverviewSchema","ServerInfoSchema","ServerTypeInfoSchema","ModelInfoSchema","RequestStatsSchema","ToolInfoSchema","ToolParameterSchema"],"mappings":"AAAA,SAASA,aAAa,EAAEC,gBAAgB,EAAEC,gBAAgB,EAAEC,gBAAgB,QAAyB,yBAAyB;AAC9H,SACCC,YAAY,EACZC,qBAAqB,EACrBC,gBAAgB,EAChBC,oBAAoB,EACpBC,eAAe,EACfC,kBAAkB,EAClBC,cAAc,EACdC,mBAAmB,QAQb,iBAAiB"}
|
package/lib/dev.server.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import { setupAudit } from '#/audit/server';
|
|
1
2
|
import { createServer } from '#/server/server';
|
|
2
|
-
const { app } = createServer({
|
|
3
|
+
const { app, finalize } = createServer({
|
|
4
|
+
setup: (ctx)=>{
|
|
5
|
+
setupAudit(ctx);
|
|
6
|
+
}
|
|
7
|
+
});
|
|
8
|
+
await finalize();
|
|
3
9
|
export default {
|
|
4
10
|
fetch: app.fetch
|
|
5
11
|
};
|
package/lib/dev.server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dev.server.ts"],"sourcesContent":["import { createServer } from '#/server/server';\n\nconst { app } = createServer({});\n\nexport default {\n\tfetch: app.fetch,\n};\n"],"names":["createServer","app","fetch"],"mappings":"AAAA,SAASA,YAAY,QAAQ,kBAAkB;AAE/C,MAAM,EAAEC,GAAG,EAAE,
|
|
1
|
+
{"version":3,"sources":["../src/dev.server.ts"],"sourcesContent":["import { setupAudit } from '#/audit/server';\nimport { createServer } from '#/server/server';\n\nconst { app, finalize } = createServer({\n\tsetup: (ctx) => {\n\t\tsetupAudit(ctx);\n\t},\n});\n\nawait finalize();\n\nexport default {\n\tfetch: app.fetch,\n};\n"],"names":["setupAudit","createServer","app","finalize","setup","ctx","fetch"],"mappings":"AAAA,SAASA,UAAU,QAAQ,iBAAiB;AAC5C,SAASC,YAAY,QAAQ,kBAAkB;AAE/C,MAAM,EAAEC,GAAG,EAAEC,QAAQ,EAAE,GAAGF,aAAa;IACtCG,OAAO,CAACC;QACPL,WAAWK;IACZ;AACD;AAEA,MAAMF;AAEN,eAAe;IACdG,OAAOJ,IAAII,KAAK;AACjB,EAAE"}
|
package/lib/entities/index.js
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
* These are pure TypeScript types without decorators
|
|
4
|
-
* Can be used with any ORM or database layer
|
|
5
|
-
*/ export * from "./types.js";
|
|
6
|
-
// MikroORM Entities
|
|
7
|
-
export { ChatRequestEntity, ChatProtocolType, RequestStatus } from "./ChatRequestEntity.js";
|
|
8
|
-
export { McpRequestEntity, McpServerType, McpRequestType } from "./McpRequestEntity.js";
|
|
9
|
-
export { RequestLogEntity } from "./RequestLogEntity.js";
|
|
10
|
-
export { ResponseEntity } from "./ResponseEntity.js";
|
|
1
|
+
// Re-export from new location for backward compatibility
|
|
2
|
+
export * from "../audit/entities/index.js";
|
|
11
3
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/entities/index.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../src/entities/index.ts"],"sourcesContent":["// Re-export from new location for backward compatibility\nexport * from '../audit/entities/index';\n"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,cAAc,0BAA0B"}
|
package/lib/index.js
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// Core server
|
|
2
|
+
export { createServer } from "./server/server.js";
|
|
3
|
+
// Events (emittery-based decoupling)
|
|
4
|
+
export { McpsEventType, createMcpsEmitter } from "./server/events.js";
|
|
5
|
+
// Configuration
|
|
6
|
+
export { loadConfig, substituteEnvVars, loadEnvFiles } from "./server/config.js";
|
|
7
|
+
export { McpsConfigSchema, ServerConfigSchema, ModelConfigSchema, AuditConfigSchema, DbConfigSchema, HeaderNames } from "./server/schema.js";
|
|
8
|
+
// MCP routes and handler
|
|
9
|
+
export { registerMcpRoutes } from "./server/mcp-routes.js";
|
|
10
|
+
export { registerChatRoutes } from "./server/chat-routes.js";
|
|
11
|
+
export { registerApiRoutes } from "./server/api-routes.js";
|
|
12
|
+
export { createMcpLoggingHandler } from "./server/mcp-handler.js";
|
|
13
|
+
export { createMcpsRouter } from "./server/mcps-router.js";
|
|
14
|
+
// Providers
|
|
15
|
+
export { defineMcpServerHandler, registerMcpServerHandler, getAllMcpServerHandlerDefs, getMcpServerHandlerDef } from "./providers/McpServerHandlerDef.js";
|
|
16
|
+
export { findMcpServerDef, resolveMcpServerDef, getMcpServerDefCount } from "./providers/findMcpServerDef.js";
|
|
17
|
+
// Contracts
|
|
18
|
+
export * from "./contracts/index.js";
|
|
19
|
+
// Chat
|
|
20
|
+
export { createChatHandler } from "./chat/index.js";
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Core server\nexport { createServer, type CreateServerOptions, type McpsServerContext, type StatsProvider } from './server/server';\n\n// Events (emittery-based decoupling)\nexport { McpsEventType, createMcpsEmitter, type McpsEmitter, type McpsEventData, type McpsRequestEvent } from './server/events';\n\n// Configuration\nexport { loadConfig, substituteEnvVars, loadEnvFiles } from './server/config';\nexport {\n\ttype McpsConfig,\n\ttype ServerConfig,\n\ttype ModelConfig,\n\ttype AuditConfig,\n\ttype DbConfig,\n\tMcpsConfigSchema,\n\tServerConfigSchema,\n\tModelConfigSchema,\n\tAuditConfigSchema,\n\tDbConfigSchema,\n\tHeaderNames,\n} from './server/schema';\n\n// MCP routes and handler\nexport { registerMcpRoutes } from './server/mcp-routes';\nexport { registerChatRoutes } from './server/chat-routes';\nexport { registerApiRoutes } from './server/api-routes';\nexport { createMcpLoggingHandler } from './server/mcp-handler';\nexport { createMcpsRouter } from './server/mcps-router';\n\n// Providers\nexport {\n\ttype McpServerHandlerDef,\n\ttype McpServerHandlerDef as McpServerDef,\n\ttype HeaderMapping,\n\ttype DefineMcpServerHandlerOptions,\n\tdefineMcpServerHandler,\n\tregisterMcpServerHandler,\n\tgetAllMcpServerHandlerDefs,\n\tgetMcpServerHandlerDef,\n} from './providers/McpServerHandlerDef';\nexport { findMcpServerDef, resolveMcpServerDef, getMcpServerDefCount } from './providers/findMcpServerDef';\n\n// Contracts\nexport * from './contracts';\n\n// Chat\nexport { createChatHandler, type ChatHandlerOptions } from './chat';\n"],"names":["createServer","McpsEventType","createMcpsEmitter","loadConfig","substituteEnvVars","loadEnvFiles","McpsConfigSchema","ServerConfigSchema","ModelConfigSchema","AuditConfigSchema","DbConfigSchema","HeaderNames","registerMcpRoutes","registerChatRoutes","registerApiRoutes","createMcpLoggingHandler","createMcpsRouter","defineMcpServerHandler","registerMcpServerHandler","getAllMcpServerHandlerDefs","getMcpServerHandlerDef","findMcpServerDef","resolveMcpServerDef","getMcpServerDefCount","createChatHandler"],"mappings":"AAAA,cAAc;AACd,SAASA,YAAY,QAA8E,kBAAkB;AAErH,qCAAqC;AACrC,SAASC,aAAa,EAAEC,iBAAiB,QAAqE,kBAAkB;AAEhI,gBAAgB;AAChB,SAASC,UAAU,EAAEC,iBAAiB,EAAEC,YAAY,QAAQ,kBAAkB;AAC9E,SAMCC,gBAAgB,EAChBC,kBAAkB,EAClBC,iBAAiB,EACjBC,iBAAiB,EACjBC,cAAc,EACdC,WAAW,QACL,kBAAkB;AAEzB,yBAAyB;AACzB,SAASC,iBAAiB,QAAQ,sBAAsB;AACxD,SAASC,kBAAkB,QAAQ,uBAAuB;AAC1D,SAASC,iBAAiB,QAAQ,sBAAsB;AACxD,SAASC,uBAAuB,QAAQ,uBAAuB;AAC/D,SAASC,gBAAgB,QAAQ,uBAAuB;AAExD,YAAY;AACZ,SAKCC,sBAAsB,EACtBC,wBAAwB,EACxBC,0BAA0B,EAC1BC,sBAAsB,QAChB,kCAAkC;AACzC,SAASC,gBAAgB,EAAEC,mBAAmB,EAAEC,oBAAoB,QAAQ,+BAA+B;AAE3G,YAAY;AACZ,cAAc,cAAc;AAE5B,OAAO;AACP,SAASC,iBAAiB,QAAiC,SAAS"}
|