@wener/mcps 1.0.4 → 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/dist/index.mjs +22 -22
- package/dist/mcps-cli.mjs +37 -37
- 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/{server/audit-db.js → audit/server/db.js} +1 -1
- 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-plugin.js → audit/server/plugin.js} +4 -4
- 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/contracts/index.js +1 -1
- package/lib/contracts/index.js.map +1 -1
- package/lib/dev.server.js +1 -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/mcps-cli.js +1 -1
- package/lib/mcps-cli.js.map +1 -1
- package/package.json +145 -112
- package/src/{chat/audit.ts → audit/chat.ts} +3 -3
- package/src/audit/entities/index.ts +6 -0
- package/src/{server/audit-db.ts → audit/server/db.ts} +1 -1
- package/src/audit/server/index.ts +8 -0
- package/src/{server/audit-plugin.ts → audit/server/plugin.ts} +5 -5
- package/src/chat/handler.ts +5 -5
- package/src/chat/index.ts +1 -1
- package/src/contracts/index.ts +1 -1
- package/src/dev.server.ts +1 -1
- package/src/entities/index.ts +2 -12
- package/src/mcps-cli.ts +1 -1
- 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-db.js.map +0 -1
- package/lib/server/audit-plugin.js.map +0 -1
- /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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/audit/server/plugin.ts"],"sourcesContent":["import { implement } from '@orpc/server';\nimport { LRUCache } from 'lru-cache';\nimport { McpsEventType } from '../../server/events';\nimport type { AuditConfig, DbConfig } from '../../server/schema';\nimport type { McpsServerContext } from '../../server/server';\nimport { AuditContract, type AuditEvent } from '../AuditContract';\n\nfunction headersToRecord(headers: Headers): Record<string, string> {\n\tconst record: Record<string, string> = {};\n\theaders.forEach((value, key) => {\n\t\trecord[key] = value;\n\t});\n\treturn record;\n}\n\nconst auditStore = new LRUCache<string, AuditEvent>({\n\tmax: 10000,\n\tttl: 1000 * 60 * 60 * 24,\n});\n\nlet eventCounter = 0;\nlet dbConfigured = false;\nlet storedAuditConfig: AuditConfig | undefined;\nlet storedDbConfig: DbConfig | undefined;\n\nasync function persistToDb(event: AuditEvent, id: string): Promise<void> {\n\tif (!dbConfigured) return;\n\n\ttry {\n\t\tconst { ensureDbInitialized, RequestLogEntity } = await import('./db.js');\n\t\tconst orm = await ensureDbInitialized(storedDbConfig);\n\t\tconst em = orm.em.fork();\n\n\t\tconst logEntry = new RequestLogEntity();\n\t\tlogEntry.requestId = id;\n\t\tlogEntry.timestamp = new Date(event.timestamp);\n\t\tlogEntry.method = event.method;\n\t\tlogEntry.path = event.path;\n\t\tlogEntry.serverName = event.serverName ?? undefined;\n\t\tlogEntry.serverType = event.serverType ?? undefined;\n\t\tlogEntry.status = event.status ?? undefined;\n\t\tlogEntry.durationMs = event.durationMs ?? undefined;\n\t\tlogEntry.error = event.error ?? undefined;\n\t\tlogEntry.requestHeaders = event.requestHeaders ?? undefined;\n\t\tif (event.path.startsWith('/mcp/')) {\n\t\t\tlogEntry.requestType = 'mcp';\n\t\t} else if (event.path.startsWith('/v1/')) {\n\t\t\tlogEntry.requestType = 'chat';\n\t\t} else {\n\t\t\tlogEntry.requestType = 'api';\n\t\t}\n\t\tem.persist(logEntry);\n\t\tawait em.flush();\n\t} catch (e) {\n\t\tconsole.error('Failed to persist audit log:', e);\n\t}\n}\n\nexport function addAuditEvent(event: Omit<AuditEvent, 'id'>): AuditEvent {\n\tconst id = `${Date.now()}-${++eventCounter}`;\n\tconst fullEvent: AuditEvent = { ...event, id };\n\tauditStore.set(id, fullEvent);\n\n\tpersistToDb(fullEvent, id).catch(() => {});\n\n\treturn fullEvent;\n}\n\nexport function queryAuditEvents(options: {\n\tlimit?: number;\n\toffset?: number;\n\tserverName?: string | null;\n\tserverType?: string | null;\n\tmethod?: string | null;\n\tfrom?: string | null;\n\tto?: string | null;\n}): { events: AuditEvent[]; total: number } {\n\tconst { limit = 50, offset = 0, serverName, serverType, method, from, to } = options;\n\n\tlet events: AuditEvent[] = [];\n\tfor (const [, event] of auditStore.entries()) {\n\t\tevents.push(event);\n\t}\n\n\tevents.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());\n\n\tif (serverName) events = events.filter((e) => e.serverName === serverName);\n\tif (serverType) events = events.filter((e) => e.serverType === serverType);\n\tif (method) events = events.filter((e) => e.method === method);\n\tif (from) {\n\t\tconst fromTime = new Date(from).getTime();\n\t\tevents = events.filter((e) => new Date(e.timestamp).getTime() >= fromTime);\n\t}\n\tif (to) {\n\t\tconst toTime = new Date(to).getTime();\n\t\tevents = events.filter((e) => new Date(e.timestamp).getTime() <= toTime);\n\t}\n\n\tconst total = events.length;\n\tevents = events.slice(offset, offset + limit);\n\n\treturn { events, total };\n}\n\nexport function getAuditStats(options: { from?: string | null; to?: string | null }) {\n\tlet events: AuditEvent[] = [];\n\tfor (const [, event] of auditStore.entries()) {\n\t\tevents.push(event);\n\t}\n\n\tif (options.from) {\n\t\tconst fromTime = new Date(options.from).getTime();\n\t\tevents = events.filter((e) => new Date(e.timestamp).getTime() >= fromTime);\n\t}\n\tif (options.to) {\n\t\tconst toTime = new Date(options.to).getTime();\n\t\tevents = events.filter((e) => new Date(e.timestamp).getTime() <= toTime);\n\t}\n\n\tconst totalRequests = events.length;\n\tconst totalErrors = events.filter((e) => e.error || (e.status && e.status >= 400)).length;\n\n\tconst durations = events.map((e) => e.durationMs).filter((d): d is number => d != null);\n\tconst avgDurationMs = durations.length > 0 ? durations.reduce((a, b) => a + b, 0) / durations.length : 0;\n\n\tconst serverCounts = new Map<string, number>();\n\tfor (const event of events) {\n\t\tconst name = event.serverName || 'unknown';\n\t\tserverCounts.set(name, (serverCounts.get(name) || 0) + 1);\n\t}\n\tconst byServer = Array.from(serverCounts.entries())\n\t\t.map(([name, count]) => ({ name, count }))\n\t\t.sort((a, b) => b.count - a.count);\n\n\tconst methodCounts = new Map<string, number>();\n\tfor (const event of events) {\n\t\tconst m = event.method || 'unknown';\n\t\tmethodCounts.set(m, (methodCounts.get(m) || 0) + 1);\n\t}\n\tconst byMethod = Array.from(methodCounts.entries())\n\t\t.map(([method, count]) => ({ method, count }))\n\t\t.sort((a, b) => b.count - a.count);\n\n\treturn { totalRequests, totalErrors, avgDurationMs, byServer, byMethod };\n}\n\nexport function clearAuditEvents(before: string): number {\n\tconst beforeTime = new Date(before).getTime();\n\tlet deleted = 0;\n\n\tfor (const [id, event] of auditStore.entries()) {\n\t\tif (new Date(event.timestamp).getTime() < beforeTime) {\n\t\t\tauditStore.delete(id);\n\t\t\tdeleted++;\n\t\t}\n\t}\n\n\treturn deleted;\n}\n\nexport const AuditRouter = implement(AuditContract).router({\n\tlist: implement(AuditContract.list).handler(async ({ input }) => {\n\t\treturn queryAuditEvents(input);\n\t}),\n\tget: implement(AuditContract.get).handler(async ({ input }) => {\n\t\treturn auditStore.get(input.id) ?? null;\n\t}),\n\tstats: implement(AuditContract.stats).handler(async ({ input }) => {\n\t\treturn getAuditStats(input);\n\t}),\n\tclear: implement(AuditContract.clear).handler(async ({ input }) => {\n\t\tconst deleted = clearAuditEvents(input.before);\n\t\treturn { deleted };\n\t}),\n});\n\n/**\n * Set up audit by subscribing to the server emitter.\n * Call this from the `setup` callback of `createServer` to opt in to audit.\n *\n * @example\n * ```ts\n * createServer({\n * setup: (ctx) => {\n * setupAudit(ctx);\n * },\n * });\n * ```\n */\nexport function setupAudit(ctx: McpsServerContext, options?: { auditConfig?: AuditConfig; dbConfig?: DbConfig }) {\n\tconst auditConfig = options?.auditConfig ?? ctx.config.audit;\n\tconst dbConfig = options?.dbConfig ?? ctx.config.db;\n\n\tconst enabled = auditConfig?.enabled !== false;\n\tif (!enabled) return;\n\n\tconst auditDbConfig = auditConfig?.db ?? dbConfig;\n\tif (auditDbConfig) {\n\t\tstoredDbConfig = auditDbConfig;\n\t\tdbConfigured = true;\n\t}\n\tstoredAuditConfig = auditConfig;\n\n\t// Subscribe to request events\n\tctx.emitter.on(McpsEventType.Request, (event) => {\n\t\tconst shouldAudit =\n\t\t\tevent.path.startsWith('/mcp/') ||\n\t\t\tevent.path.startsWith('/v1/') ||\n\t\t\t(event.path.startsWith('/api/') && event.method !== 'GET');\n\n\t\tif (shouldAudit) {\n\t\t\taddAuditEvent({\n\t\t\t\ttimestamp: event.timestamp,\n\t\t\t\tmethod: event.method,\n\t\t\t\tpath: event.path,\n\t\t\t\tserverName: event.serverName,\n\t\t\t\tserverType: event.serverType,\n\t\t\t\tstatus: event.status,\n\t\t\t\tdurationMs: event.durationMs,\n\t\t\t\terror: event.error,\n\t\t\t\trequestHeaders: event.requestHeaders,\n\t\t\t});\n\t\t}\n\t});\n\n\t// Register audit API router\n\tctx.apiRouters.audit = AuditRouter;\n\n\t// Register stats provider so mcps-router can access stats\n\tctx.statsProvider = {\n\t\tgetStats: getAuditStats,\n\t\tqueryEvents: (opts) => {\n\t\t\tconst result = queryAuditEvents(opts);\n\t\t\treturn { events: result.events.map((e) => ({ path: e.path })), total: result.total };\n\t\t},\n\t};\n}\n"],"names":["implement","LRUCache","McpsEventType","AuditContract","headersToRecord","headers","record","forEach","value","key","auditStore","max","ttl","eventCounter","dbConfigured","storedAuditConfig","storedDbConfig","persistToDb","event","id","ensureDbInitialized","RequestLogEntity","orm","em","fork","logEntry","requestId","timestamp","Date","method","path","serverName","undefined","serverType","status","durationMs","error","requestHeaders","startsWith","requestType","persist","flush","e","console","addAuditEvent","now","fullEvent","set","catch","queryAuditEvents","options","limit","offset","from","to","events","entries","push","sort","a","b","getTime","filter","fromTime","toTime","total","length","slice","getAuditStats","totalRequests","totalErrors","durations","map","d","avgDurationMs","reduce","serverCounts","Map","name","get","byServer","Array","count","methodCounts","m","byMethod","clearAuditEvents","before","beforeTime","deleted","delete","AuditRouter","router","list","handler","input","stats","clear","setupAudit","ctx","auditConfig","config","audit","dbConfig","db","enabled","auditDbConfig","emitter","on","Request","shouldAudit","apiRouters","statsProvider","getStats","queryEvents","opts","result"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/audit/types.ts"],"sourcesContent":["/**\n * Entity Type Definitions\n * These types can be used with MikroORM or other ORMs\n * Avoids decorator issues in test environments\n */\n\n/**\n * Base entity fields\n */\nexport interface BaseEntity {\n\tid: number;\n\tcreatedAt: Date;\n\tupdatedAt: Date;\n}\n\n/**\n * Request status\n */\nexport type RequestStatus = 'pending' | 'success' | 'error' | 'timeout';\n\n/**\n * Chat protocol type\n */\nexport type ChatProtocolType = 'openai' | 'anthropic' | 'gemini';\n\n/**\n * MCP server type\n */\nexport type McpServerType = 'tencent-cls' | 'sql' | 'prometheus' | 'relay' | 'custom';\n\n/**\n * MCP request type\n */\nexport type McpRequestType =\n\t| 'initialize'\n\t| 'tools/list'\n\t| 'tools/call'\n\t| 'resources/list'\n\t| 'resources/read'\n\t| 'prompts/list'\n\t| 'prompts/get'\n\t| 'completion/complete'\n\t| 'logging/setLevel'\n\t| 'ping'\n\t| 'other';\n\n/**\n * Chat request entity for auditing and metering\n */\nexport interface ChatRequest extends BaseEntity {\n\t/** Unique request ID for tracing */\n\trequestId: string;\n\t/** Request timestamp */\n\trequestedAt: Date;\n\t/** Response timestamp */\n\tcompletedAt?: Date;\n\t/** Request status */\n\tstatus: RequestStatus;\n\t/** HTTP method */\n\tmethod: string;\n\t/** Request path/endpoint */\n\tendpoint: string;\n\t/** Input protocol (client-facing) */\n\tinputProtocol: ChatProtocolType;\n\t/** Output protocol (upstream provider) */\n\toutputProtocol: ChatProtocolType;\n\t/** Model name requested */\n\tmodel: string;\n\t/** Resolved model name */\n\tresolvedModel?: string;\n\t/** Provider name */\n\tprovider?: string;\n\t/** Upstream base URL */\n\tupstreamUrl?: string;\n\t/** Whether request was streaming */\n\tstreaming: boolean;\n\t/** Input token count */\n\tinputTokens?: number;\n\t/** Output token count */\n\toutputTokens?: number;\n\t/** Total token count */\n\ttotalTokens?: number;\n\t/** Request duration in ms */\n\tdurationMs?: number;\n\t/** Time to first token in ms */\n\tttftMs?: number;\n\t/** HTTP status code */\n\thttpStatus?: number;\n\t/** Error message */\n\terrorMessage?: string;\n\t/** Error code */\n\terrorCode?: string;\n\t/** Client IP */\n\tclientIp?: string;\n\t/** User agent */\n\tuserAgent?: string;\n\t/** User ID */\n\tuserId?: string;\n\t/** Organization ID */\n\torgId?: string;\n\t/** API key ID (not the actual key) */\n\tapiKeyId?: string;\n\t/** Request metadata */\n\trequestMeta?: Record<string, unknown>;\n\t/** Response metadata */\n\tresponseMeta?: Record<string, unknown>;\n\t/** Cost in credits */\n\tcost?: string;\n\t/** Currency */\n\tcurrency?: string;\n}\n\n/**\n * MCP request entity for auditing\n */\nexport interface McpRequest extends BaseEntity {\n\t/** Unique request ID */\n\trequestId: string;\n\t/** MCP session ID */\n\tsessionId?: string;\n\t/** Request timestamp */\n\trequestedAt: Date;\n\t/** Response timestamp */\n\tcompletedAt?: Date;\n\t/** Request status */\n\tstatus: RequestStatus;\n\t/** HTTP method */\n\tmethod: string;\n\t/** Request path */\n\tpath: string;\n\t/** MCP server name */\n\tserverName: string;\n\t/** MCP server type */\n\tserverType: McpServerType;\n\t/** MCP request type */\n\tmcpMethod: McpRequestType;\n\t/** Tool name (for tools/call) */\n\ttoolName?: string;\n\t/** Resource URI (for resources/read) */\n\tresourceUri?: string;\n\t/** Prompt name (for prompts/get) */\n\tpromptName?: string;\n\t/** Request duration in ms */\n\tdurationMs?: number;\n\t/** HTTP status code */\n\thttpStatus?: number;\n\t/** Error message */\n\terrorMessage?: string;\n\t/** Error code */\n\terrorCode?: string;\n\t/** Client IP */\n\tclientIp?: string;\n\t/** User agent */\n\tuserAgent?: string;\n\t/** User ID */\n\tuserId?: string;\n\t/** Request headers */\n\trequestHeaders?: Record<string, string>;\n\t/** Request body */\n\trequestBody?: Record<string, unknown>;\n\t/** Response metadata */\n\tresponseMeta?: Record<string, unknown>;\n}\n\n/**\n * Chat audit statistics\n */\nexport interface ChatAuditStats {\n\ttotalRequests: number;\n\tsuccessfulRequests: number;\n\tfailedRequests: number;\n\ttotalInputTokens: number;\n\ttotalOutputTokens: number;\n\tavgDurationMs: number;\n\tbyModel: { model: string; count: number; tokens: number }[];\n\tbyProvider: { provider: string; count: number; tokens: number }[];\n}\n\n/**\n * MCP audit statistics\n */\nexport interface McpAuditStats {\n\ttotalRequests: number;\n\ttotalErrors: number;\n\tavgDurationMs: number;\n\tbyServer: { name: string; count: number }[];\n\tbyMethod: { method: string; count: number }[];\n}\n"],"names":[],"mappings":"AAAA;;;;CAIC,GAED;;CAEC,GA0KD;;CAEC,GACD,WAMC"}
|
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/
|
|
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/
|
|
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/audit-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/audit-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":"AAAA;;;CAGC,GACD,OAAOA,aAAa,UAAU;AAC9B,SAASC,IAAI,QAAQ,OAAO;AAC5B,SAASC,SAAS,QAAQ,iBAAiB;AAE3C,SAASC,YAAY,EAAEC,kBAAkB,EAAEC,eAAe,QAAQ,gBAAgB;AAClF,SACCC,wBAAwB,EACxBC,yBAAyB,EACzBC,qBAAqB,EACrBC,sBAAsB,QAChB,eAAe;AACtB,SACCC,iCAAiC,EAEjCC,2BAA2B,QAErB,mBAAmB;AAC1B,SAASC,0BAA0B,QAAQ,sBAAsB;AACjE,SAASC,kCAAkC,QAAQ,mBAAmB;AAEtE,MAAMC,MAAMd,QAAQe,OAAO,CAAC;AAM5B;;CAEC,GACD,OAAO,SAASC,kBAAkBC,UAA8B,CAAC,CAAC;IACjE,MAAMC,MAAM,IAAIjB;IAChB,MAAM,EAAEkB,SAAS,CAAC,CAAC,EAAE,GAAGF;IAExB;;EAEC,GACD,SAASG,mBAAmBC,SAAiB;QAC5C,MAAMC,SAASH,OAAOG,MAAM;QAC5B,IAAI,CAACA,UAAUA,OAAOC,MAAM,KAAK,GAAG,OAAO;QAE3C,0BAA0B;QAC1B,KAAK,MAAMC,eAAeF,OAAQ;YACjC,IAAIE,YAAYC,IAAI,KAAKJ,WAAW;gBACnC,OAAOG;YACR;QACD;QAEA,8DAA8D;QAC9D,KAAK,MAAMA,eAAeF,OAAQ;YACjC,MAAMI,UAAUF,YAAYC,IAAI;YAChC,IAAIC,QAAQC,QAAQ,CAAC,MAAM;gBAC1B,MAAMC,QAAQ,IAAIC,OAAO,CAAC,CAAC,EAAEH,QAAQI,OAAO,CAAC,OAAO,MAAM,CAAC,CAAC;gBAC5D,IAAIF,MAAMG,IAAI,CAACV,YAAY;oBAC1B,OAAOG;gBACR;YACD;QACD;QAEA,OAAO;IACR;IAEA;;EAEC,GACD,eAAeQ,oBACdC,GAAW,EACXC,IAAa,EACbC,OAA+B,EAC/BC,UAAmB,KAAK;QAExB,MAAMC,WAAW,MAAMC,MAAML,KAAK;YACjCM,QAAQ;YACRJ,SAAS;gBACR,gBAAgB;gBAChB,GAAGA,OAAO;YACX;YACAD,MAAMM,KAAKC,SAAS,CAACP;QACtB;QAEA,IAAI,CAACG,SAASK,EAAE,EAAE;YACjB,MAAMC,YAAY,MAAMN,SAASO,IAAI;YACrC9B,IAAI+B,KAAK,CAAC,mBAAmBR,SAASS,MAAM,EAAEH;YAC9C,MAAM,IAAII,MAAM,CAAC,gBAAgB,EAAEV,SAASS,MAAM,CAAC,CAAC,EAAEH,WAAW;QAClE;QAEA,OAAON;IACR;IAEA;;;EAGC,GACD,SAASW,iBAAiBf,GAAW;QACpC,OAAOA,IAAIH,OAAO,CAAC,YAAY;IAChC;IAEA;;EAEC,GACD,SAASmB,qBACRzB,WAAwB,EACxB0B,OAA0C;QAE1C,MAAMf,UAAkC,CAAC;QAEzC,4BAA4B;QAC5B,IAAIX,YAAY2B,MAAM,EAAE;YACvB,IAAID,YAAY,aAAa;gBAC5Bf,OAAO,CAAC,YAAY,GAAGX,YAAY2B,MAAM;gBACzChB,OAAO,CAAC,oBAAoB,GAAG;YAChC,OAAO;gBACNA,QAAQiB,aAAa,GAAG,CAAC,OAAO,EAAE5B,YAAY2B,MAAM,EAAE;YACvD;QACD;QAEA,qBAAqB;QACrB,IAAI3B,YAAYW,OAAO,EAAE;YACxBkB,OAAOC,MAAM,CAACnB,SAASX,YAAYW,OAAO;QAC3C;QAEA,+BAA+B;QAC/B,IAAIX,YAAY+B,QAAQ,EAAE,CAACL,QAAQ,EAAEf,SAAS;YAC7CkB,OAAOC,MAAM,CAACnB,SAASX,YAAY+B,QAAQ,CAACL,QAAQ,EAAEf;QACvD;QAEA,OAAOA;IACR;IAEA;;;EAGC,GACD,SAASqB,uBAAuBC,OAAoC;QACnE,MAAMC,aAAsC;YAAE,GAAGD,OAAO;QAAC;QAEzD,2DAA2D;QAC3D,8EAA8E;QAC9E,IAAIA,QAAQE,qBAAqB,IAAI,CAACF,QAAQG,UAAU,EAAE;YACzDF,WAAWE,UAAU,GAAGH,QAAQE,qBAAqB;QACtD;QAEA,4EAA4E;QAC5E,8CAA8C;QAC9C,IAAIF,QAAQI,eAAe,KAAKC,aAAa,CAACL,QAAQM,QAAQ,EAAE;YAC/DL,WAAWK,QAAQ,GAAG;gBACrBC,MAAMP,QAAQI,eAAe,GAAG,YAAY;YAC7C;QACD;QAEA,OAAOH;IACR;IAEA,4EAA4E;IAC5E,8BAA8B;IAC9B,4EAA4E;IAE5ExC,IAAI+C,IAAI,CAAC,wBAAwB,OAAOC;QACvC,6BAA6B;QAC7B,IAAIC,WAAyD;QAE7D,IAAI;YACH,MAAMjC,OAAO,MAAMgC,EAAEE,GAAG,CAACC,IAAI;YAC7B,MAAMC,cAAc5D,kCAAkC6D,SAAS,CAACrC;YAEhE,IAAI,CAACoC,YAAYE,OAAO,EAAE;gBACzB,OAAON,EAAEG,IAAI,CACZ;oBACCxB,OAAO;wBACN4B,SAAS;wBACTT,MAAM;wBACNU,OAAO;wBACPC,MAAM;wBACNC,SAASN,YAAYzB,KAAK,CAACgC,MAAM;oBAClC;gBACD,GACA;YAEF;YAEA,MAAMpB,UAAUa,YAAYQ,IAAI;YAChC,MAAMtD,cAAcJ,mBAAmBqC,QAAQsB,KAAK;YAEpD,IAAI,CAACvD,aAAa;gBACjB,OAAO0C,EAAEG,IAAI,CACZ;oBACCxB,OAAO;wBACN4B,SAAS,CAAC,MAAM,EAAEhB,QAAQsB,KAAK,CAAC,eAAe,CAAC;wBAChDf,MAAM;wBACNU,OAAO;wBACPC,MAAM;oBACP;gBACD,GACA;YAEF;YAEA,6BAA6B;YAC7B,MAAMzB,UAAU1B,YAAY0B,OAAO,IAAI;YACvC,MAAM8B,UAAUhC,iBACfxB,YAAY+B,QAAQ,EAAE,CAACL,QAAQ,EAAE8B,WAAWxD,YAAYwD,OAAO,IAAI;YAGpE,uBAAuB;YACvB,MAAMC,iBACL/B,YAAY,cACT/C,aAAa+E,SAAS,GACtBhC,YAAY,WACX/C,aAAagF,MAAM,GACnBhF,aAAaiF,MAAM;YAExBjB,WAAW/D,mBAAmB;gBAC7BmC,QAAQ;gBACR8C,UAAU;gBACVN,OAAOtB,QAAQsB,KAAK;gBACpBO,eAAenF,aAAaiF,MAAM;gBAClCH;gBACAM,WAAW9B,QAAQ+B,MAAM,IAAI;gBAC7BC,UAAUpF,gBAAgB6D;gBAC1BwB,WAAWxB,EAAEE,GAAG,CAACuB,MAAM,CAAC;gBACxBC,aAAa;oBACZC,aAAapC,QAAQoC,WAAW;oBAChCjC,YAAYH,QAAQG,UAAU,IAAIH,QAAQE,qBAAqB;oBAC/DmC,OAAOrC,QAAQqC,KAAK;gBACrB;YACD;YAEA,uBAAuB;YACvBhF,IAAIiF,IAAI,CACP,CAAC,kCAAkC,EAAEtC,QAAQsB,KAAK,CAAC,QAAQ,EAAEtB,QAAQ+B,MAAM,IAAI,MAAM,UAAU,EAAE/B,QAAQuC,QAAQ,CAACzE,MAAM,EAAE;YAG3H,2CAA2C;YAC3C,IAAI0E;YACJ,IAAIC;YACJ,IAAIC;YAEJ,OAAQjD;gBACP,KAAK;oBAAa;wBACjB+C,cAAc,GAAGjB,QAAQ,YAAY,CAAC;wBACtCkB,eAAe5F,yBAAyBmD;wBACxC0C,kBAAkBlD,qBAAqBzB,aAAa;wBACpD;oBACD;gBACA,KAAK;oBAAU;wBACd,MAAMe,SAASkB,QAAQ+B,MAAM,GAAG,0BAA0B;wBAC1DS,cAAc,GAAGjB,QAAQ,WAAW,EAAEvB,QAAQsB,KAAK,CAAC,CAAC,EAAExC,QAAQ;wBAC/D2D,eAAe1F,sBAAsBiD;wBACrC0C,kBAAkBlD,qBAAqBzB,aAAa;wBACpD;oBACD;gBACA;oBAAS;wBACR,4DAA4D;wBAC5DyE,cAAc,GAAGjB,QAAQ,oBAAoB,CAAC;wBAC9CkB,eAAe1C,uBAAuBC;wBACtC0C,kBAAkBlD,qBAAqBzB,aAAa;oBACrD;YACD;YAEA,qCAAqC;YACrC2C,SAASiC,WAAW,CAAC;gBACpBC,UAAUnD;gBACV+C;YACD;YAEA,mBAAmB;YACnB,IAAIxC,QAAQ+B,MAAM,EAAE;gBACnB,OAAOc,uBAAuBpC,GAAG+B,aAAaC,cAAcC,iBAAiBjD,SAASO,QAAQsB,KAAK,EAAEZ;YACtG;YAEA,wBAAwB;YACxB,MAAM9B,WAAW,MAAML,oBAAoBiE,aAAaC,cAAcC;YACtE,MAAMI,eAAe,MAAMlE,SAASgC,IAAI;YAExC,6BAA6B;YAC7B,IAAImC;YACJ,OAAQtD;gBACP,KAAK;oBACJsD,SAASjG,0BAA0BgG,cAAc9C,QAAQsB,KAAK;oBAC9D;gBACD,KAAK;oBACJyB,SAAS/F,uBAAuB8F,cAAc9C,QAAQsB,KAAK;oBAC3D;gBACD;oBACCyB,SAASD;YACX;YAEA,wCAAwC;YACxC,IAAIC,OAAOC,KAAK,EAAE;gBACjBtC,SAASuC,aAAa,CAACF,OAAOC,KAAK,CAACE,aAAa,IAAI,GAAGH,OAAOC,KAAK,CAACG,iBAAiB,IAAI;YAC3F;YACAzC,SAAS0C,eAAe,CAAC;gBACxBC,eAAeN,OAAOO,OAAO,EAAE,CAAC,EAAE,EAAED;gBACpC/B,OAAOyB,OAAOzB,KAAK;YACpB;YACA,MAAMZ,SAAS6C,QAAQ,CAAC;YAExB,eAAe;YACf,MAAMP,QAAQD,OAAOC,KAAK;YAC1B3F,IAAIiF,IAAI,CACP,CAAC,iCAAiC,EAAES,OAAOzB,KAAK,IAAItB,QAAQsB,KAAK,CAAC,QAAQ,EAAE0B,OAAOQ,gBAAgB,EAAE,KAAK,EAAER,OAAOE,iBAAiB,EAAE,KAAK,EAAEF,OAAOG,qBAAqB,EAAE,CAAC,CAAC;YAG9K,OAAO1C,EAAEG,IAAI,CAACmC;QACf,EAAE,OAAO3D,OAAO;YACf,wBAAwB;YACxB,IAAIsB,UAAU;gBACb,MAAMA,SAAStB,KAAK,CAACA,iBAAiBE,QAAQF,MAAM4B,OAAO,GAAG,iBAAiB,kBAAkB;YAClG;YACA3D,IAAI+B,KAAK,CAAC,0BAA0BA;YACpC,OAAOqB,EAAEG,IAAI,CACZ;gBACCxB,OAAO;oBACN4B,SAAS5B,iBAAiBE,QAAQF,MAAM4B,OAAO,GAAG;oBAClDT,MAAM;oBACNW,MAAM;gBACP;YACD,GACA;QAEF;IACD;IAEA;;EAEC,GACD,eAAe2B,uBACdpC,CAAM,EACN+B,WAAmB,EACnBC,YAAqB,EACrBC,eAAuC,EACvCjD,OAAe,EACf6B,KAAa,EACbZ,QAAgD;QAEhD,MAAM9B,WAAW,MAAML,oBAAoBiE,aAAaC,cAAcC,iBAAiB;QAEvF,IAAIe,qBAAqB;QACzB,IAAIC,oBAAoB;QAExB,sDAAsD;QACtD,OAAOjH,UAAUgE,GAAG,OAAOsB;YAC1B,MAAM4B,SAAS/E,SAASH,IAAI,EAAEmF;YAC9B,IAAI,CAACD,QAAQ;gBACZ,MAAM5B,OAAO8B,QAAQ,CAAC;oBAAExC,MAAM;gBAAS;gBACvC,IAAIX,UAAU,MAAMA,SAAS6C,QAAQ,CAAC;gBACtC;YACD;YAEA,MAAMO,UAAU,IAAIC;YACpB,IAAIC,SAAS;YAEb,IAAI;gBACH,MAAO,KAAM;oBACZ,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAG,MAAMP,OAAOQ,IAAI;oBACzC,IAAIF,MAAM;oBAEVD,UAAUF,QAAQM,MAAM,CAACF,OAAO;wBAAEnC,QAAQ;oBAAK;oBAC/C,MAAMsC,QAAQL,OAAOM,KAAK,CAAC;oBAC3BN,SAASK,MAAME,GAAG,MAAM;oBAExB,KAAK,MAAMC,QAAQH,MAAO;wBACzB,IAAI,CAACG,KAAKC,IAAI,IAAI;wBAElB,IAAID,KAAKE,UAAU,CAAC,WAAW;4BAC9B,MAAMrD,OAAOmD,KAAKG,KAAK,CAAC;4BACxB,IAAItD,SAAS,UAAU;gCACtB,MAAMU,OAAO8B,QAAQ,CAAC;oCAAExC,MAAM;gCAAS;gCACvC;4BACD;4BAEA,IAAI;gCACH,MAAMuD,SAAS7F,KAAK8F,KAAK,CAACxD;gCAC1B,MAAMyD,YAAYC,mBAAmBH,QAAQnF,SAAS6B;gCACtD,IAAIwD,WAAW;oCACd,8BAA8B;oCAC9B,IAAI,CAACrB,sBAAsB/C,UAAU;wCACpCA,SAASsE,gBAAgB;wCACzBvB,qBAAqB;oCACtB;oCACA,iCAAiC;oCACjC,IAAIqB,UAAU9B,KAAK,EAAE;wCACpBU,oBAAoBoB,UAAU9B,KAAK,CAACG,iBAAiB,IAAIO;oCAC1D;oCACA,MAAM3B,OAAO8B,QAAQ,CAAC;wCAAExC,MAAMtC,KAAKC,SAAS,CAAC8F;oCAAW;gCACzD;4BACD,EAAE,OAAM;4BACP,oBAAoB;4BACrB;wBACD,OAAO,IAAIN,KAAKE,UAAU,CAAC,YAAY,CACvC;oBACD;gBACD;gBAEA,mBAAmB;gBACnB,MAAM3C,OAAO8B,QAAQ,CAAC;oBAAExC,MAAM;gBAAS;gBAEvC,iBAAiB;gBACjB,IAAIX,UAAU;oBACbA,SAASuC,aAAa,CAAC,GAAGS,oBAAoB,0CAA0C;oBACxF,MAAMhD,SAAS6C,QAAQ,CAAC;gBACzB;YACD,EAAE,OAAO0B,KAAK;gBACb,yBAAyB;gBACzB,IAAIvE,UAAU;oBACb,MAAMA,SAAStB,KAAK,CAAC6F,eAAe3F,QAAQ2F,IAAIjE,OAAO,GAAG,mBAAmB,mBAAmB;gBACjG;gBACA,MAAMiE;YACP,SAAU;gBACTtB,OAAOuB,WAAW;YACnB;QACD;IACD;IAEA;;EAEC,GACD,SAASH,mBAAmBI,KAAU,EAAE1F,OAAe,EAAE6B,KAAa;QACrE,OAAQ7B;YACP,KAAK;gBACJ,OAAO2F,4BAA4BD,OAAO7D;YAC3C,KAAK;gBACJ,OAAO+D,yBAAyBF,OAAO7D;YACxC;gBACC,OAAO6D;QACT;IACD;IAEA;;EAEC,GACD,SAASC,4BAA4BD,KAAU,EAAE7D,KAAa;QAC7D,IAAI6D,MAAM5E,IAAI,KAAK,uBAAuB;YACzC,IAAI4E,MAAMG,KAAK,EAAE/E,SAAS,cAAc;gBACvC,OAAO;oBACNgF,IAAI,CAAC,SAAS,EAAEC,KAAKC,GAAG,IAAI;oBAC5BC,QAAQ;oBACRC,SAASC,KAAKC,KAAK,CAACL,KAAKC,GAAG,KAAK;oBACjCnE;oBACAgC,SAAS;wBACR;4BACCwC,OAAO;4BACPR,OAAO;gCAAES,SAASZ,MAAMG,KAAK,CAACnG,IAAI;4BAAC;4BACnCkE,eAAe;wBAChB;qBACA;gBACF;YACD;QACD,OAAO,IAAI8B,MAAM5E,IAAI,KAAK,iBAAiB;YAC1C,MAAMyF,eACLb,MAAMG,KAAK,EAAEW,gBAAgB,aAC1B,SACAd,MAAMG,KAAK,EAAEW,gBAAgB,aAC5B,eACA;YACL,OAAO;gBACNV,IAAI,CAAC,SAAS,EAAEC,KAAKC,GAAG,IAAI;gBAC5BC,QAAQ;gBACRC,SAASC,KAAKC,KAAK,CAACL,KAAKC,GAAG,KAAK;gBACjCnE;gBACAgC,SAAS;oBACR;wBACCwC,OAAO;wBACPR,OAAO,CAAC;wBACRjC,eAAe2C;oBAChB;iBACA;gBACDhD,OAAOmC,MAAMnC,KAAK,GACf;oBACAE,eAAe;oBACfC,mBAAmBgC,MAAMnC,KAAK,CAACkD,aAAa;oBAC5C1C,cAAc2B,MAAMnC,KAAK,CAACkD,aAAa;gBACxC,IACC7F;YACJ;QACD;QACA,OAAO;IACR;IAEA;;EAEC,GACD,SAASgF,yBAAyBF,KAAU,EAAE7D,KAAa;QAC1D,IAAI6D,MAAMgB,UAAU,EAAE,CAAC,EAAE,EAAEJ,SAASK,OAAO;YAC1C,MAAMA,QAAQjB,MAAMgB,UAAU,CAAC,EAAE,CAACJ,OAAO,CAACK,KAAK;YAC/C,MAAMC,YAAYD,MAAME,MAAM,CAAC,CAACC,IAAWA,EAAEpH,IAAI;YAEjD,IAAIkH,UAAUvI,MAAM,GAAG,GAAG;gBACzB,OAAO;oBACNyH,IAAI,CAAC,SAAS,EAAEC,KAAKC,GAAG,IAAI;oBAC5BC,QAAQ;oBACRC,SAASC,KAAKC,KAAK,CAACL,KAAKC,GAAG,KAAK;oBACjCnE;oBACAgC,SAAS;wBACR;4BACCwC,OAAO;4BACPR,OAAO;gCAAES,SAASM,UAAUG,GAAG,CAAC,CAACD,IAAWA,EAAEpH,IAAI,EAAEsH,IAAI,CAAC;4BAAI;4BAC7DpD,eAAe8B,MAAMgB,UAAU,CAAC,EAAE,CAACH,YAAY,KAAK,SAAS,SAAS;wBACvE;qBACA;gBACF;YACD;QACD;QACA,OAAO;IACR;IAEA,4EAA4E;IAC5E,yBAAyB;IACzB,4EAA4E;IAE5EvI,IAAI+C,IAAI,CAAC,gBAAgB,OAAOC;QAC/B,IAAI;YACH,MAAMhC,OAAO,MAAMgC,EAAEE,GAAG,CAACC,IAAI;YAC7B,MAAMC,cAAc1D,2BAA2B2D,SAAS,CAACrC;YAEzD,IAAI,CAACoC,YAAYE,OAAO,EAAE;gBACzB,OAAON,EAAEG,IAAI,CACZ;oBACCL,MAAM;oBACNnB,OAAO;wBACNmB,MAAM;wBACNS,SAAS;oBACV;gBACD,GACA;YAEF;YAEA,MAAMhB,UAAUa,YAAYQ,IAAI;YAChC,MAAMtD,cAAcJ,mBAAmBqC,QAAQsB,KAAK;YAEpD,IAAI,CAACvD,aAAa;gBACjB,OAAO0C,EAAEG,IAAI,CACZ;oBACCL,MAAM;oBACNnB,OAAO;wBACNmB,MAAM;wBACNS,SAAS,CAAC,MAAM,EAAEhB,QAAQsB,KAAK,CAAC,eAAe,CAAC;oBACjD;gBACD,GACA;YAEF;YAEA,8EAA8E;YAC9E,MAAM7B,UAAU1B,YAAY0B,OAAO,IAAI;YACvC,MAAM8B,UAAUhC,iBACfxB,YAAY+B,QAAQ,EAAE,CAACL,QAAQ,EAAE8B,WAAWxD,YAAYwD,OAAO,IAAI;YAGpE,MAAMiB,cAAc,GAAGjB,QAAQ,YAAY,CAAC;YAC5C,MAAMmB,kBAAkBlD,qBAAqBzB,aAAa;YAE1D,uBAAuB;YACvBV,IAAIiF,IAAI,CAAC,CAAC,0BAA0B,EAAEtC,QAAQsB,KAAK,CAAC,UAAU,EAAEtB,QAAQuC,QAAQ,CAACzE,MAAM,EAAE;YAEzF,MAAMc,WAAW,MAAML,oBAAoBiE,aAAaxC,SAAS0C;YACjE,MAAMI,eAAe,MAAMlE,SAASgC,IAAI;YAExC,eAAe;YACf,MAAMoC,QAAQF,aAAaE,KAAK;YAChC3F,IAAIiF,IAAI,CACP,CAAC,yBAAyB,EAAEQ,aAAaxB,KAAK,IAAItB,QAAQsB,KAAK,CAAC,QAAQ,EAAE,AAAC0B,CAAAA,OAAO0D,gBAAgB,CAAA,IAAM1D,CAAAA,OAAOkD,iBAAiB,CAAA,EAAG,KAAK,EAAElD,OAAO0D,gBAAgB,EAAE,KAAK,EAAE1D,OAAOkD,iBAAiB,EAAE,CAAC,CAAC;YAGvM,OAAOzF,EAAEG,IAAI,CAACkC;QACf,EAAE,OAAO1D,OAAO;YACf/B,IAAI+B,KAAK,CAAC,mBAAmBA;YAC7B,OAAOqB,EAAEG,IAAI,CACZ;gBACCL,MAAM;gBACNnB,OAAO;oBACNmB,MAAM;oBACNS,SAAS5B,iBAAiBE,QAAQF,MAAM4B,OAAO,GAAG;gBACnD;YACD,GACA;QAEF;IACD;IAEA,4EAA4E;IAC5E,8BAA8B;IAC9B,4EAA4E;IAE5EvD,IAAI+C,IAAI,CAAC,uCAAuC,OAAOC;QACtD,IAAI;YACH,MAAMa,QAAQb,EAAEE,GAAG,CAACM,KAAK,CAAC;YAC1B,IAAI,CAACK,OAAO;gBACX,OAAOb,EAAEG,IAAI,CAAC;oBAAExB,OAAO;wBAAE4B,SAAS;oBAA8B;gBAAE,GAAG;YACtE;YAEA,MAAMvC,OAAO,MAAMgC,EAAEE,GAAG,CAACC,IAAI;YAC7B,MAAMC,cAAczD,mCAAmC0D,SAAS,CAACrC;YAEjE,IAAI,CAACoC,YAAYE,OAAO,EAAE;gBACzB,OAAON,EAAEG,IAAI,CAAC;oBAAExB,OAAO;wBAAE4B,SAAS;oBAAkB;gBAAE,GAAG;YAC1D;YAEA,MAAMhB,UAAUa,YAAYQ,IAAI;YAChC,MAAMtD,cAAcJ,mBAAmB2D;YAEvC,IAAI,CAACvD,aAAa;gBACjB,OAAO0C,EAAEG,IAAI,CAAC;oBAAExB,OAAO;wBAAE4B,SAAS,CAAC,MAAM,EAAEM,MAAM,eAAe,CAAC;oBAAC;gBAAE,GAAG;YACxE;YAEA,MAAMC,UAAUhC,iBACfxB,YAAY+B,QAAQ,EAAE6G,QAAQpF,WAAWxD,YAAYwD,OAAO,IAAI;YAGjE,MAAMiB,cAAc,GAAGjB,QAAQ,WAAW,EAAED,MAAM,gBAAgB,CAAC;YACnE,MAAMoB,kBAAkBlD,qBAAqBzB,aAAa;YAE1D,uBAAuB;YACvBV,IAAIiF,IAAI,CAAC,CAAC,kBAAkB,EAAEhB,MAAM,0BAA0B,EAAEtB,QAAQ4G,QAAQ,EAAE9I,UAAU,GAAG;YAE/F,MAAMc,WAAW,MAAML,oBAAoBiE,aAAaxC,SAAS0C;YACjE,MAAMI,eAAe,MAAMlE,SAASgC,IAAI;YAExC,eAAe;YACf,MAAMoC,QAAQF,aAAa+D,aAAa;YACxCxJ,IAAIiF,IAAI,CACP,CAAC,iBAAiB,EAAEhB,MAAM,wBAAwB,EAAE0B,OAAO8D,mBAAmB,EAAE,KAAK,EAAE9D,OAAO+D,oBAAoB,EAAE,KAAK,EAAE/D,OAAOgE,wBAAwB,EAAE,CAAC,CAAC;YAG/J,OAAOvG,EAAEG,IAAI,CAACkC;QACf,EAAE,OAAO1D,OAAO;YACf/B,IAAI+B,KAAK,CAAC,2BAA2BA;YACrC,OAAOqB,EAAEG,IAAI,CAAC;gBAAExB,OAAO;oBAAE4B,SAAS5B,iBAAiBE,QAAQF,MAAM4B,OAAO,GAAG;gBAAwB;YAAE,GAAG;QACzG;IACD;IAEA,4EAA4E;IAC5E,wCAAwC;IACxC,4EAA4E;IAE5EvD,IAAI+C,IAAI,CAAC,6CAA6C,OAAOC;QAC5D,IAAI;YACH,MAAMa,QAAQb,EAAEE,GAAG,CAACM,KAAK,CAAC;YAC1B,IAAI,CAACK,OAAO;gBACX,OAAOb,EAAEG,IAAI,CAAC;oBAAExB,OAAO;wBAAE4B,SAAS;oBAA8B;gBAAE,GAAG;YACtE;YAEA,MAAMvC,OAAO,MAAMgC,EAAEE,GAAG,CAACC,IAAI;YAC7B,MAAMC,cAAczD,mCAAmC0D,SAAS,CAACrC;YAEjE,IAAI,CAACoC,YAAYE,OAAO,EAAE;gBACzB,OAAON,EAAEG,IAAI,CAAC;oBAAExB,OAAO;wBAAE4B,SAAS;oBAAkB;gBAAE,GAAG;YAC1D;YAEA,MAAMhB,UAAUa,YAAYQ,IAAI;YAEhC,uBAAuB;YACvBhE,IAAIiF,IAAI,CAAC,CAAC,kBAAkB,EAAEhB,MAAM,gCAAgC,EAAEtB,QAAQ4G,QAAQ,EAAE9I,UAAU,GAAG;YAErG,MAAMC,cAAcJ,mBAAmB2D;YAEvC,IAAI,CAACvD,aAAa;gBACjB,OAAO0C,EAAEG,IAAI,CAAC;oBAAExB,OAAO;wBAAE4B,SAAS,CAAC,MAAM,EAAEM,MAAM,eAAe,CAAC;oBAAC;gBAAE,GAAG;YACxE;YAEA,MAAMC,UAAUhC,iBACfxB,YAAY+B,QAAQ,EAAE6G,QAAQpF,WAAWxD,YAAYwD,OAAO,IAAI;YAGjE,MAAMiB,cAAc,GAAGjB,QAAQ,WAAW,EAAED,MAAM,sBAAsB,CAAC;YACzE,MAAMoB,kBAAkBlD,qBAAqBzB,aAAa;YAE1D,MAAMa,WAAW,MAAML,oBAAoBiE,aAAaxC,SAAS0C,iBAAiB;YAElF,+BAA+B;YAC/B,OAAOjG,UAAUgE,GAAG,OAAOsB;gBAC1B,MAAM4B,SAAS/E,SAASH,IAAI,EAAEmF;gBAC9B,IAAI,CAACD,QAAQ;oBACZ,MAAM5B,OAAO8B,QAAQ,CAAC;wBAAExC,MAAM;oBAAS;oBACvC;gBACD;gBAEA,MAAMyC,UAAU,IAAIC;gBACpB,IAAIC,SAAS;gBAEb,IAAI;oBACH,MAAO,KAAM;wBACZ,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAG,MAAMP,OAAOQ,IAAI;wBACzC,IAAIF,MAAM;wBAEVD,UAAUF,QAAQM,MAAM,CAACF,OAAO;4BAAEnC,QAAQ;wBAAK;wBAC/C,MAAMsC,QAAQL,OAAOM,KAAK,CAAC;wBAC3BN,SAASK,MAAME,GAAG,MAAM;wBAExB,KAAK,MAAMC,QAAQH,MAAO;4BACzB,IAAI,CAACG,KAAKC,IAAI,IAAI;4BAElB,IAAID,KAAKE,UAAU,CAAC,WAAW;gCAC9B,MAAMrD,OAAOmD,KAAKG,KAAK,CAAC;gCACxB,IAAItD,SAAS,UAAU;oCACtB,MAAMU,OAAO8B,QAAQ,CAAC;wCAAExC,MAAM;oCAAS;oCACvC;gCACD;gCACA,MAAMU,OAAO8B,QAAQ,CAAC;oCAAExC;gCAAK;4BAC9B;wBACD;oBACD;oBACA,MAAMU,OAAO8B,QAAQ,CAAC;wBAAExC,MAAM;oBAAS;gBACxC,SAAU;oBACTsC,OAAOuB,WAAW;gBACnB;YACD;QACD,EAAE,OAAO9F,OAAO;YACf/B,IAAI+B,KAAK,CAAC,kCAAkCA;YAC5C,OAAOqB,EAAEG,IAAI,CAAC;gBAAExB,OAAO;oBAAE4B,SAAS5B,iBAAiBE,QAAQF,MAAM4B,OAAO,GAAG;gBAAwB;YAAE,GAAG;QACzG;IACD;IAEA,4EAA4E;IAC5E,uBAAuB;IACvB,4EAA4E;IAE5EvD,IAAI+C,IAAI,CAAC,iBAAiB,OAAOC;QAChC,IAAIC,WAAyD;QAE7D,IAAI;YACH,MAAMjC,OAAO,MAAMgC,EAAEE,GAAG,CAACC,IAAI;YAC7B,MAAMC,cAAc3D,4BAA4B4D,SAAS,CAACrC;YAE1D,IAAI,CAACoC,YAAYE,OAAO,EAAE;gBACzB,OAAON,EAAEG,IAAI,CACZ;oBACCxB,OAAO;wBACN4B,SAAS;wBACTT,MAAM;wBACNU,OAAO;wBACPC,MAAM;wBACNC,SAASN,YAAYzB,KAAK,CAACgC,MAAM;oBAClC;gBACD,GACA;YAEF;YAEA,MAAMpB,UAAUa,YAAYQ,IAAI;YAEhC,sDAAsD;YACtD,IAAI4F,kBAAgE;YACpE,IAAIjH,QAAQkH,oBAAoB,EAAE;gBACjC,IAAI;oBACH,MAAM,EAAEC,eAAe,EAAEC,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC;oBAC3D,MAAM,EAAEC,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC;oBACxC,IAAIF,mBAAmB;wBACtB,MAAMG,KAAKF,mBAAmBG,IAAI;wBAClC,MAAMC,eAAe,MAAMF,GAAGG,OAAO,CAACJ,gBAAgB;4BAAEK,YAAY1H,QAAQkH,oBAAoB;wBAAC;wBACjG,IAAIM,cAAc;4BACjBP,kBAAkB;gCACjBU,OAAOH,aAAaG,KAAK;gCACzBC,QAAQJ,aAAaI,MAAM;4BAC5B;4BACAvK,IAAIiF,IAAI,CAAC,CAAC,0BAA0B,EAAEtC,QAAQkH,oBAAoB,EAAE;wBACrE,OAAO;4BACN7J,IAAIwK,IAAI,CAAC,CAAC,6BAA6B,EAAE7H,QAAQkH,oBAAoB,EAAE;wBACxE;oBACD;gBACD,EAAE,OAAOY,GAAG;oBACXzK,IAAIwK,IAAI,CAAC,qCAAqCC;gBAC/C;YACD;YAEA,MAAM/J,cAAcJ,mBAAmBqC,QAAQsB,KAAK;YAEpD,IAAI,CAACvD,aAAa;gBACjB,OAAO0C,EAAEG,IAAI,CACZ;oBACCxB,OAAO;wBACN4B,SAAS,CAAC,MAAM,EAAEhB,QAAQsB,KAAK,CAAC,eAAe,CAAC;wBAChDf,MAAM;wBACNU,OAAO;wBACPC,MAAM;oBACP;gBACD,GACA;YAEF;YAEA,wEAAwE;YACxE,MAAMzB,UAAU1B,YAAY0B,OAAO,IAAI;YACvC,MAAM8B,UAAUhC,iBACfxB,YAAY+B,QAAQ,EAAE,CAACL,QAAQ,EAAE8B,WAAWxD,YAAYwD,OAAO,IAAI;YAGpE,uBAAuB;YACvBb,WAAW/D,mBAAmB;gBAC7BmC,QAAQ;gBACR8C,UAAU;gBACVN,OAAOtB,QAAQsB,KAAK;gBACpBO,eAAenF,aAAaiF,MAAM;gBAClCH,gBAAgB9E,aAAaiF,MAAM;gBACnCG,WAAW9B,QAAQ+B,MAAM,IAAI;gBAC7BC,UAAUpF,gBAAgB6D;gBAC1BwB,WAAWxB,EAAEE,GAAG,CAACuB,MAAM,CAAC;gBACxBC,aAAa;oBACZC,aAAapC,QAAQoC,WAAW;oBAChC2F,mBAAmB/H,QAAQ+H,iBAAiB;gBAC7C;YACD;YAEA,uBAAuB;YACvB,MAAMC,YACL,OAAOhI,QAAQ2H,KAAK,KAAK,WACtB,WACAM,MAAMC,OAAO,CAAClI,QAAQ2H,KAAK,IAC1B,CAAC,MAAM,EAAE3H,QAAQ2H,KAAK,CAAC7J,MAAM,CAAC,CAAC,CAAC,GAChC;YACLT,IAAIiF,IAAI,CAAC,CAAC,2BAA2B,EAAEtC,QAAQsB,KAAK,CAAC,QAAQ,EAAEtB,QAAQ+B,MAAM,IAAI,MAAM,OAAO,EAAEiG,WAAW;YAE3G,2DAA2D;YAC3D,MAAMG,cAAcC,2BAA2BpI,SAASiH;YAExD,yBAAyB;YACzB,MAAMzE,cAAc,GAAGjB,QAAQ,oBAAoB,CAAC;YACpD,MAAMmB,kBAAkBlD,qBAAqBzB,aAAa;YAE1D2C,SAASiC,WAAW,CAAC;gBACpBC,UAAUnD;gBACV+C;YACD;YAEA,mBAAmB;YACnB,IAAIxC,QAAQ+B,MAAM,EAAE;gBACnB,OAAOsG,gCAAgC5H,GAAG+B,aAAa2F,aAAazF,iBAAiB1C,QAAQsB,KAAK,EAAEZ;YACrG;YAEA,wBAAwB;YACxB,MAAM9B,WAAW,MAAML,oBAAoBiE,aAAa2F,aAAazF;YACrE,MAAM4F,eAAe,MAAM1J,SAASgC,IAAI;YAExC,wDAAwD;YACxD,MAAMmC,SAASwF,2BAA2BD,cAActI,QAAQsB,KAAK;YAErE,yDAAyD;YACzD,IAAI;gBACH,MAAM,EAAE6F,eAAe,EAAEC,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC;gBAC3D,MAAM,EAAEC,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC;gBACxC,IAAIF,mBAAmB;oBACtB,MAAMG,KAAKF,mBAAmBG,IAAI;oBAClC,MAAMiB,iBAAiB,IAAInB;oBAC3BmB,eAAed,UAAU,GAAG3E,OAAOwC,EAAE;oBACrCiD,eAAelH,KAAK,GAAGyB,OAAOzB,KAAK;oBACnCkH,eAAenJ,MAAM,GAAG0D,OAAO1D,MAAM;oBACrCmJ,eAAeb,KAAK,GAAG3H,QAAQ2H,KAAK;oBACpCa,eAAeZ,MAAM,GAAG7E,OAAO6E,MAAM;oBACrCY,eAAexF,KAAK,GAAGD,OAAOC,KAAK;oBACnCwF,eAAeC,YAAY,GAAGzI,QAAQyI,YAAY,IAAIpI;oBACtDmI,eAAeE,kBAAkB,GAAG1I,QAAQkH,oBAAoB,IAAI7G;oBACpEmI,eAAeG,KAAK,GAAG3I,QAAQ2I,KAAK,IAAItI;oBACxCmI,eAAeI,UAAU,GAAG5I,QAAQ6I,WAAW,IAAIxI;oBACnDmI,eAAeM,QAAQ,GAAG9I,QAAQ8I,QAAQ;oBAC1CN,eAAeO,UAAU,GAAGrI,UAAUsI;oBACtC1B,GAAG2B,OAAO,CAACT;oBACX,MAAMlB,GAAG4B,KAAK;oBACd7L,IAAI8L,KAAK,CAAC,CAAC,iBAAiB,EAAEpG,OAAOwC,EAAE,EAAE;gBAC1C;YACD,EAAE,OAAOuC,GAAG;gBACXzK,IAAIwK,IAAI,CAAC,6BAA6BC;YACvC;YAEA,eAAe;YACf,IAAIQ,aAAatF,KAAK,EAAE;gBACvBtC,SAASuC,aAAa,CAACqF,aAAatF,KAAK,CAACE,aAAa,IAAI,GAAGoF,aAAatF,KAAK,CAACG,iBAAiB,IAAI;YACvG;YACAzC,SAAS0C,eAAe,CAAC;gBACxB/D,QAAQ0D,OAAO1D,MAAM;gBACrB+J,cAAcrG,OAAO6E,MAAM,CAAC9J,MAAM;YACnC;YACA,MAAM4C,SAAS6C,QAAQ,CAAC;YAExB,eAAe;YACf,MAAMP,QAAQsF,aAAatF,KAAK;YAChC3F,IAAIiF,IAAI,CACP,CAAC,0BAA0B,EAAES,OAAOzB,KAAK,IAAItB,QAAQsB,KAAK,CAAC,QAAQ,EAAEyB,OAAO1D,MAAM,CAAC,QAAQ,EAAE2D,OAAOQ,gBAAgB,GAAG;YAGxH,OAAO/C,EAAEG,IAAI,CAACmC;QACf,EAAE,OAAO3D,OAAO;YACf,IAAIsB,UAAU;gBACb,MAAMA,SAAStB,KAAK,CAACA,iBAAiBE,QAAQF,MAAM4B,OAAO,GAAG,iBAAiB,kBAAkB;YAClG;YACA3D,IAAI+B,KAAK,CAAC,wBAAwBA;YAClC,OAAOqB,EAAEG,IAAI,CACZ;gBACCxB,OAAO;oBACN4B,SAAS5B,iBAAiBE,QAAQF,MAAM4B,OAAO,GAAG;oBAClDT,MAAM;oBACNW,MAAM;gBACP;YACD,GACA;QAEF;IACD;IAEA;;EAEC,GACD,SAASkH,2BACRpI,OAA8B,EAC9BiH,eAA8D;QAE9D,MAAM1E,WAAoD,EAAE;QAE5D,oCAAoC;QACpC,IAAIvC,QAAQyI,YAAY,EAAE;YACzBlG,SAAS8G,IAAI,CAAC;gBACbC,MAAM;gBACNvD,SAAS/F,QAAQyI,YAAY;YAC9B;QACD;QAEA,2DAA2D;QAC3D,IAAIxB,iBAAiB;YACpB,qBAAqB;YACrB,MAAMsC,YAAYtC,gBAAgBU,KAAK;YACvC,IAAI,OAAO4B,cAAc,UAAU;gBAClChH,SAAS8G,IAAI,CAAC;oBAAEC,MAAM;oBAAQvD,SAASwD;gBAAU;YAClD,OAAO,IAAItB,MAAMC,OAAO,CAACqB,YAAY;gBACpC,KAAK,MAAMC,QAAQD,UAAoB;oBACtC,IAAIC,KAAKjJ,IAAI,KAAK,WAAW;wBAC5BgC,SAAS8G,IAAI,CAAC;4BACbC,MAAME,KAAKF,IAAI;4BACfvD,SAAS,OAAOyD,KAAKzD,OAAO,KAAK,WAAWyD,KAAKzD,OAAO,GAAGhH,KAAKC,SAAS,CAACwK,KAAKzD,OAAO;wBACvF;oBACD;gBACD;YACD;YAEA,4CAA4C;YAC5C,KAAK,MAAMyD,QAAQvC,gBAAgBW,MAAM,CAAW;gBACnD,IAAI4B,KAAKjJ,IAAI,KAAK,aAAaiJ,KAAKF,IAAI,KAAK,aAAa;oBACzD,MAAMG,cAAcD,KAAKzD,OAAO,EAAE2D,KAAK,CAACjJ,IAAWA,EAAEF,IAAI,KAAK,UAAUE,EAAEF,IAAI,KAAK;oBACnF,IAAIkJ,aAAa;wBAChBlH,SAAS8G,IAAI,CAAC;4BACbC,MAAM;4BACNvD,SAAS0D,YAAYtK,IAAI;wBAC1B;oBACD;gBACD;YACD;QACD;QAEA,oCAAoC;QACpC,IAAI,OAAOa,QAAQ2H,KAAK,KAAK,UAAU;YACtCpF,SAAS8G,IAAI,CAAC;gBACbC,MAAM;gBACNvD,SAAS/F,QAAQ2H,KAAK;YACvB;QACD,OAAO,IAAIM,MAAMC,OAAO,CAAClI,QAAQ2H,KAAK,GAAG;YACxC,KAAK,MAAM6B,QAAQxJ,QAAQ2H,KAAK,CAAE;gBACjC,IAAI6B,KAAKjJ,IAAI,KAAK,WAAW;oBAC5BgC,SAAS8G,IAAI,CAAC;wBACbC,MAAME,KAAKF,IAAI;wBACfvD,SAAS,OAAOyD,KAAKzD,OAAO,KAAK,WAAWyD,KAAKzD,OAAO,GAAGhH,KAAKC,SAAS,CAACwK,KAAKzD,OAAO;oBACvF;gBACD;YACA,kFAAkF;YACnF;QACD;QAEA,OAAO;YACNzE,OAAOtB,QAAQsB,KAAK;YACpBiB;YACAH,aAAapC,QAAQoC,WAAW;YAChCC,OAAOrC,QAAQqC,KAAK;YACpBlC,YAAYH,QAAQ+H,iBAAiB;YACrChG,QAAQ/B,QAAQ+B,MAAM;YACtB4G,OAAO3I,QAAQ2I,KAAK;YACpBE,aAAa7I,QAAQ6I,WAAW;YAChCc,qBAAqB3J,QAAQ2J,mBAAmB;YAChDb,UAAU9I,QAAQ8I,QAAQ;YAC1Bc,OAAO5J,QAAQ4J,KAAK;YACpBC,MAAM7J,QAAQ6J,IAAI;QACnB;IACD;IAEA;;EAEC,GACD,SAAStB,2BAA2BD,YAAiB,EAAEhH,KAAa;QACnE,MAAMoG,aAAa,CAAC,KAAK,EAAEY,aAAa/C,EAAE,IAAIC,KAAKC,GAAG,IAAI;QAC1D,MAAMmC,SAAgB,EAAE;QAExB,KAAK,MAAMkC,UAAUxB,aAAahF,OAAO,IAAI,EAAE,CAAE;YAChD,MAAMtC,UAAU8I,OAAO9I,OAAO;YAC9B,IAAIA,SAAS;gBACZ4G,OAAOyB,IAAI,CAAC;oBACX9D,IAAI,CAAC,KAAK,EAAEmC,WAAW,CAAC,EAAEoC,OAAOhE,KAAK,EAAE;oBACxCvF,MAAM;oBACN+I,MAAM;oBACNvD,SAAS/E,QAAQ+E,OAAO,GAAG;wBAAC;4BAAExF,MAAM;4BAAQpB,MAAM6B,QAAQ+E,OAAO;wBAAC;qBAAE,GAAG,EAAE;oBACzE1G,QAAQ;gBACT;gBAEA,oBAAoB;gBACpB,IAAI2B,QAAQ+I,UAAU,EAAE;oBACvB,KAAK,MAAMC,YAAYhJ,QAAQ+I,UAAU,CAAE;wBAC1CnC,OAAOyB,IAAI,CAAC;4BACX9D,IAAIyE,SAASzE,EAAE;4BACfhF,MAAM;4BACNvC,MAAMgM,SAASC,QAAQ,EAAEjM;4BACzBkM,WAAWF,SAASC,QAAQ,EAAEC;4BAC9B7K,QAAQ;wBACT;oBACD;gBACD;YACD;QACD;QAEA,OAAO;YACNkG,IAAImC;YACJhC,QAAQ;YACRyE,YAAY7B,aAAa3C,OAAO,IAAIC,KAAKC,KAAK,CAACL,KAAKC,GAAG,KAAK;YAC5DnE,OAAOgH,aAAahH,KAAK,IAAIA;YAC7BjC,QAAQ;YACRuI;YACA5E,OAAOsF,aAAatF,KAAK;YACzB8F,UAAU,CAAC;YACX1J,OAAO;QACR;IACD;IAEA;;EAEC,GACD,eAAeiJ,gCACd5H,CAAM,EACN+B,WAAmB,EACnBC,YAAqB,EACrBC,eAAuC,EACvCpB,KAAa,EACbZ,QAAgD;QAEhD,MAAM9B,WAAW,MAAML,oBACtBiE,aACA;YAAE,GAAIC,YAAY;YAAUV,QAAQ;QAAK,GACzCW,iBACA;QAGD,IAAIe,qBAAqB;QACzB,MAAMiE,aAAa,CAAC,KAAK,EAAElC,KAAKC,GAAG,IAAI;QAEvC,OAAOhJ,UAAUgE,GAAG,OAAOsB;YAC1B,MAAM4B,SAAS/E,SAASH,IAAI,EAAEmF;YAC9B,IAAI,CAACD,QAAQ;gBACZ,MAAM5B,OAAO8B,QAAQ,CAAC;oBAAEsB,OAAO;oBAAiB9D,MAAMtC,KAAKC,SAAS,CAAC;wBAAEuB,MAAM;oBAAgB;gBAAG;gBAChG,IAAIG,UAAU,MAAMA,SAAS6C,QAAQ,CAAC;gBACtC;YACD;YAEA,qBAAqB;YACrB,MAAMxB,OAAO8B,QAAQ,CAAC;gBACrBsB,OAAO;gBACP9D,MAAMtC,KAAKC,SAAS,CAAC;oBACpBuB,MAAM;oBACN3B,UAAU;wBACT2G,IAAImC;wBACJhC,QAAQ;wBACRyE,YAAYvE,KAAKC,KAAK,CAACL,KAAKC,GAAG,KAAK;wBACpCnE;wBACAjC,QAAQ;wBACRuI,QAAQ,EAAE;oBACX;gBACD;YACD;YAEA,MAAM9D,UAAU,IAAIC;YACpB,IAAIC,SAAS;YACb,IAAIoG,eAAe,CAAC,KAAK,EAAE1C,WAAW,EAAE,CAAC;YAEzC,IAAI;gBACH,MAAO,KAAM;oBACZ,MAAM,EAAEzD,IAAI,EAAEC,KAAK,EAAE,GAAG,MAAMP,OAAOQ,IAAI;oBACzC,IAAIF,MAAM;oBAEVD,UAAUF,QAAQM,MAAM,CAACF,OAAO;wBAAEnC,QAAQ;oBAAK;oBAC/C,MAAMsC,QAAQL,OAAOM,KAAK,CAAC;oBAC3BN,SAASK,MAAME,GAAG,MAAM;oBAExB,KAAK,MAAMC,QAAQH,MAAO;wBACzB,IAAI,CAACG,KAAKC,IAAI,MAAM,CAACD,KAAKE,UAAU,CAAC,WAAW;wBAEhD,MAAMrD,OAAOmD,KAAKG,KAAK,CAAC;wBACxB,IAAItD,SAAS,UAAU;wBAEvB,IAAI;4BACH,MAAMuD,SAAS7F,KAAK8F,KAAK,CAACxD;4BAC1B,MAAMiE,QAAQV,OAAOtB,OAAO,EAAE,CAAC,EAAE,EAAEgC;4BAEnC,IAAIA,OAAOS,SAAS;gCACnB,IAAI,CAACtC,sBAAsB/C,UAAU;oCACpCA,SAASsE,gBAAgB;oCACzBvB,qBAAqB;gCACtB;gCAEA,MAAM1B,OAAO8B,QAAQ,CAAC;oCACrBsB,OAAO;oCACP9D,MAAMtC,KAAKC,SAAS,CAAC;wCACpBuB,MAAM;wCACN8J,cAAc;wCACdC,eAAe;wCACfhF,OAAOA,MAAMS,OAAO;oCACrB;gCACD;4BACD;wBACD,EAAE,OAAM;wBACP,oBAAoB;wBACrB;oBACD;gBACD;gBAEA,yBAAyB;gBACzB,MAAMhE,OAAO8B,QAAQ,CAAC;oBACrBsB,OAAO;oBACP9D,MAAMtC,KAAKC,SAAS,CAAC;wBACpBuB,MAAM;wBACN8J,cAAc;wBACdb,MAAM;4BACLjE,IAAI6E;4BACJ7J,MAAM;4BACN+I,MAAM;4BACNjK,QAAQ;wBACT;oBACD;gBACD;gBAEA,MAAM0C,OAAO8B,QAAQ,CAAC;oBACrBsB,OAAO;oBACP9D,MAAMtC,KAAKC,SAAS,CAAC;wBACpBuB,MAAM;wBACN3B,UAAU;4BACT2G,IAAImC;4BACJrI,QAAQ;wBACT;oBACD;gBACD;gBAEA,IAAIqB,UAAU,MAAMA,SAAS6C,QAAQ,CAAC;YACvC,EAAE,OAAO0B,KAAK;gBACb,IAAIvE,UAAU;oBACb,MAAMA,SAAStB,KAAK,CAAC6F,eAAe3F,QAAQ2F,IAAIjE,OAAO,GAAG,mBAAmB,mBAAmB;gBACjG;gBACA,MAAMiE;YACP,SAAU;gBACTtB,OAAOuB,WAAW;YACnB;QACD;IACD;IAEA,4EAA4E;IAC5E,kBAAkB;IAClB,4EAA4E;IAE5EzH,IAAI8M,GAAG,CAAC,cAAc,OAAO9J;QAC5B,MAAM+J,gBAAgB/J,EAAEE,GAAG,CAAC8J,KAAK,CAAC,aAAa;QAC/C,MAAMC,YAQD,EAAE;QAEP,wBAAwB;QACxB,KAAK,MAAMC,KAAKjN,OAAOG,MAAM,IAAI,EAAE,CAAE;YACpC6M,UAAUrB,IAAI,CAAC;gBACd9D,IAAIoF,EAAE3M,IAAI;gBACV0H,QAAQ;gBACRC,SAASC,KAAKC,KAAK,CAACL,KAAKC,GAAG,KAAK;gBACjCmF,UAAU;gBACVC,gBAAgBF,EAAEG,aAAa;gBAC/BC,kBAAkBJ,EAAEK,cAAc;gBAClCjD,mBAAmB4C,EAAEM,eAAe;YACrC;YAEA,mCAAmC;YACnC,IAAIT,iBAAiBG,EAAEO,mBAAmB,IAAIP,EAAEpJ,OAAO,EAAE;gBACxD,IAAI;oBACH,MAAM7C,UAAkC;wBACvC,gBAAgB;oBACjB;oBACA,IAAIiM,EAAEjL,MAAM,EAAE;wBACbhB,QAAQiB,aAAa,GAAG,CAAC,OAAO,EAAEgL,EAAEjL,MAAM,EAAE;oBAC7C;oBACAE,OAAOC,MAAM,CAACnB,SAASiM,EAAEjM,OAAO,IAAI,CAAC;oBAErC,MAAMyM,gBAAgB5L,iBAAiBoL,EAAEpJ,OAAO;oBAChD,MAAMiB,cAAc,GAAG2I,cAAc,UAAU,CAAC;oBAEhD,MAAMC,MAAM,MAAMvM,MAAM2D,aAAa;wBAAE9D;oBAAQ;oBAC/C,IAAI0M,IAAInM,EAAE,EAAE;wBACX,MAAMoC,OAAO,MAAM+J,IAAIxK,IAAI;wBAC3B,IAAIS,KAAKA,IAAI,IAAI4G,MAAMC,OAAO,CAAC7G,KAAKA,IAAI,GAAG;4BAC1C,KAAK,MAAMC,SAASD,KAAKA,IAAI,CAAE;gCAC9B,mBAAmB;gCACnB,IAAI,CAACqJ,UAAUW,IAAI,CAAC,CAACC,WAAaA,SAAS/F,EAAE,KAAKjE,MAAMiE,EAAE,GAAG;oCAC5DmF,UAAUrB,IAAI,CAAC;wCACd9D,IAAIjE,MAAMiE,EAAE;wCACZG,QAAQpE,MAAMoE,MAAM,IAAI;wCACxBC,SAASrE,MAAMqE,OAAO,IAAIC,KAAKC,KAAK,CAACL,KAAKC,GAAG,KAAK;wCAClDmF,UAAUtJ,MAAMsJ,QAAQ,IAAID,EAAE3M,IAAI,CAACsG,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI;oCACrD;gCACD;4BACD;wBACD;oBACD;gBACD,EAAE,OAAOwD,GAAG;oBACXzK,IAAIwK,IAAI,CAAC,CAAC,qCAAqC,EAAE8C,EAAEpJ,OAAO,CAAC,EAAE,EAAEuG,GAAG;gBACnE;YACD;QACD;QAEAzK,IAAI8L,KAAK,CAAC,CAAC,uBAAuB,EAAEuB,UAAU5M,MAAM,CAAC,OAAO,EAAE0M,eAAe;QAE7E,OAAO/J,EAAEG,IAAI,CAAC;YACb8E,QAAQ;YACRrE,MAAMqJ;QACP;IACD;IAEA,OAAOjN;AACR"}
|
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/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
package/lib/dev.server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dev.server.ts"],"sourcesContent":["import { setupAudit } from '#/server
|
|
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/mcps-cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createProgram } from "./cli.js";
|
|
|
4
4
|
const log = consola.withTag("mcps");
|
|
5
5
|
const program = createProgram({
|
|
6
6
|
setup: async (ctx) => {
|
|
7
|
-
const { setupAudit } = await import("./server/
|
|
7
|
+
const { setupAudit } = await import("./audit/server/plugin.js");
|
|
8
8
|
setupAudit(ctx);
|
|
9
9
|
}
|
|
10
10
|
});
|
package/lib/mcps-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcps-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport consola from 'consola';\nimport { createProgram } from './cli';\n\nconst log = consola.withTag('mcps');\n\nconst program = createProgram({\n\tsetup: async (ctx) => {\n\t\tconst { setupAudit } = await import('./server/
|
|
1
|
+
{"version":3,"sources":["../src/mcps-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport consola from 'consola';\nimport { createProgram } from './cli';\n\nconst log = consola.withTag('mcps');\n\nconst program = createProgram({\n\tsetup: async (ctx) => {\n\t\tconst { setupAudit } = await import('./audit/server/plugin.js');\n\t\tsetupAudit(ctx);\n\t},\n});\n\nprogram.parseAsync(process.argv).catch((error) => {\n\tlog.error(error.message);\n\tprocess.exit(1);\n});\n"],"names":["consola","createProgram","log","withTag","program","setup","ctx","setupAudit","parseAsync","process","argv","catch","error","message","exit"],"mappings":";AACA,OAAOA,aAAa,UAAU;AAC9B,SAASC,aAAa,QAAQ,QAAQ;AAEtC,MAAMC,MAAMF,QAAQG,OAAO,CAAC;AAE5B,MAAMC,UAAUH,cAAc;IAC7BI,OAAO,OAAOC;QACb,MAAM,EAAEC,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC;QACpCA,WAAWD;IACZ;AACD;AAEAF,QAAQI,UAAU,CAACC,QAAQC,IAAI,EAAEC,KAAK,CAAC,CAACC;IACvCV,IAAIU,KAAK,CAACA,MAAMC,OAAO;IACvBJ,QAAQK,IAAI,CAAC;AACd"}
|