@nick3/copilot-api 1.0.3
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/LICENSE +21 -0
- package/README.md +599 -0
- package/dist/accounts-manager-CxuKJ4qv.js +1326 -0
- package/dist/accounts-manager-CxuKJ4qv.js.map +1 -0
- package/dist/admin/assets/index-CFHE7_Zc.js +55 -0
- package/dist/admin/assets/index-DwLAH2FE.css +1 -0
- package/dist/admin/index.html +27 -0
- package/dist/admin/vite.svg +1 -0
- package/dist/main.js +746 -0
- package/dist/main.js.map +1 -0
- package/dist/server-D05YP0C0.js +5513 -0
- package/dist/server-D05YP0C0.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-D05YP0C0.js","names":["sharedDb: Database | null","where: Array<string>","values: Array<SQLQueryBindings>","map: Record<string, AccountStatsRow | undefined>","disabledStore: RequestHistoryStoreApi","sharedStore: RequestHistoryStoreApi | null","target: string | undefined","allowOriginal: boolean | undefined","next: AppConfig","error: string | undefined","payload: unknown","statsByAccount: Record<string, AccountStatsRow | undefined>","items: Array<AccountItem>","path","CONTENT_TYPES: Record<string, string>","headers: Record<string, string>","fs","stats: fs.Stats","state","headers: Record<string, string>","THINKING_TEXT","input: Array<ResponseInputItem>","items: Array<ResponseInputItem>","pendingContent: Array<ResponseInputContent>","contentBlocks: Array<AnthropicAssistantContentBlock>","segments: Array<string>","parsed: unknown","result: Array<ResponseInputContent>","x","headers: Record<string, string>","logger","CHAT_COMPLETIONS_ENDPOINT","handleCompletion","buildRequestContext","selectionFailureResponse","path","insertRequestLog","recordSelectionFailure","response: ChatCompletionsResult","handleUpstreamCreateError","isNonStreaming","streamChatCompletionsAndLog","usage: NormalizedUsage","errorName: string | undefined","errorStatus: number | undefined","errorMessage: string | undefined","ttfbMs: number | undefined","lastUsage: NormalizedUsage","finishedAtMs: number | undefined","handleCompletion","path","ctx: RequestContext","selectionFailureResponse","recordSelectionFailure","usage: NormalizedUsage","errorName: string | undefined","errorStatus: number | undefined","errorMessage: string | undefined","finishedAtMs: number | undefined","toolResults: Array<AnthropicToolResultBlock>","textBlocks: Array<AnthropicTextBlock>","newMessages: Array<Message>","contentParts: Array<ContentPart>","assistantContentBlocks: Array<AnthropicAssistantContentBlock>","state","handleOutputItemAdded","handleOutputItemDone","events","THINKING_TEXT","blockIndex","result: Array<ResponseInputItem>","headers: Record<string, string>","state","events: Array<AnthropicStreamEventData>","events","logger","RESPONSES_ENDPOINT","path","instr: InstrumentationContext","response: ChatCompletionsResult","response: Awaited<ReturnType<typeof createResponses>>","isAsyncIterable","streamResponsesAndLog","insertRequestLog","usage: NormalizedUsage","errorName: string | undefined","errorStatus: number | undefined","errorMessage: string | undefined","ttfbMs: number | undefined","lastUsage: NormalizedUsage","streamState: AnthropicStreamState","events","response: MessagesResult","logger","path","response: Awaited<ReturnType<typeof createResponses>>","usage: NormalizedUsage","errorName: string | undefined","errorStatus: number | undefined","errorMessage: string | undefined","ttfbMs: number | undefined","lastUsage: NormalizedUsage","finishedAtMs: number | undefined"],"sources":["../src/lib/api-key-auth.ts","../src/lib/admin-db.ts","../src/lib/request-history.ts","../src/routes/admin-api/route.ts","../src/routes/admin/route.ts","../src/lib/approval.ts","../src/lib/handler-utils.ts","../src/lib/logger.ts","../src/lib/rate-limit.ts","../src/lib/tokenizer.ts","../src/services/copilot/create-responses.ts","../src/routes/messages/responses-translation.ts","../src/services/copilot/create-chat-completions.ts","../src/routes/chat-completions/handler.ts","../src/routes/chat-completions/route.ts","../src/services/copilot/create-embeddings.ts","../src/routes/embeddings/route.ts","../src/routes/messages/utils.ts","../src/routes/messages/non-stream-translation.ts","../src/routes/messages/count-tokens-handler.ts","../src/routes/messages/responses-stream-translation.ts","../src/routes/responses/utils.ts","../src/services/copilot/create-messages.ts","../src/routes/messages/stream-translation.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/routes/responses/stream-id-sync.ts","../src/routes/responses/handler.ts","../src/routes/responses/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts"],"sourcesContent":["import type { MiddlewareHandler } from \"hono\"\n\nimport { timingSafeEqual } from \"node:crypto\"\n\nimport { getConfig } from \"~/lib/config\"\n\nconst API_KEY_ENV_VAR = \"COPILOT_API_KEY\"\n\nexport type ApiKeyAuthOptions = {\n /**\n * Injected for tests; defaults to env+config resolution.\n */\n getConfiguredApiKey?: () => string | undefined\n\n /**\n * Injected for tests; defaults to the built-in protected path matcher.\n */\n isProtectedPath?: (pathname: string) => boolean\n}\n\nexport function resolveConfiguredApiKey(): string | undefined {\n const envKey = process.env[API_KEY_ENV_VAR]?.trim()\n if (envKey) return envKey\n\n const configKey = getConfig().apiKey?.trim()\n if (configKey) return configKey\n\n return undefined\n}\n\nexport function parseBearerToken(value: string): string | undefined {\n const trimmed = value.trim()\n if (!trimmed.toLowerCase().startsWith(\"bearer \")) return undefined\n\n const token = trimmed.slice(\"bearer \".length).trim()\n return token || undefined\n}\n\nexport function extractRequestApiKey(headers: Headers): string | undefined {\n const headerToken = headers.get(\"x-api-key\")?.trim()\n if (headerToken) return headerToken\n\n const bearer = headers.get(\"authorization\")\n if (bearer) {\n const token = parseBearerToken(bearer)\n if (token) return token\n }\n\n return undefined\n}\n\nfunction normalizePathname(pathname: string): string {\n if (pathname.length > 1 && pathname.endsWith(\"/\")) {\n return pathname.slice(0, -1)\n }\n return pathname\n}\n\nfunction hasPrefixBoundary(pathname: string, prefix: string): boolean {\n return pathname === prefix || pathname.startsWith(`${prefix}/`)\n}\n\nexport function isProtectedPath(pathnameRaw: string): boolean {\n const pathname = normalizePathname(pathnameRaw)\n\n return (\n hasPrefixBoundary(pathname, \"/v1\")\n || hasPrefixBoundary(pathname, \"/token\")\n || hasPrefixBoundary(pathname, \"/usage\")\n || hasPrefixBoundary(pathname, \"/chat/completions\")\n || hasPrefixBoundary(pathname, \"/embeddings\")\n || hasPrefixBoundary(pathname, \"/models\")\n || hasPrefixBoundary(pathname, \"/responses\")\n )\n}\n\nfunction timingSafeKeyCompare(a: string, b: string): boolean {\n try {\n const aBuf = Buffer.from(a)\n const bBuf = Buffer.from(b)\n if (aBuf.length !== bBuf.length) return false\n return timingSafeEqual(aBuf, bBuf)\n } catch {\n return false\n }\n}\n\nexport function createApiKeyAuthMiddleware(\n options: ApiKeyAuthOptions = {},\n): MiddlewareHandler {\n const getConfiguredKey =\n options.getConfiguredApiKey ?? resolveConfiguredApiKey\n const isPathProtected = options.isProtectedPath ?? isProtectedPath\n\n return async (c, next) => {\n if (c.req.method === \"OPTIONS\") {\n await next()\n return\n }\n\n const url = new URL(c.req.url, \"http://local\")\n if (!isPathProtected(url.pathname)) {\n await next()\n return\n }\n\n // User requirement: when key is not configured at all, allow all traffic.\n const configuredKey = getConfiguredKey()\n if (!configuredKey) {\n await next()\n return\n }\n\n const providedKey = extractRequestApiKey(c.req.raw.headers)\n\n if (!providedKey || !timingSafeKeyCompare(providedKey, configuredKey)) {\n return c.json(\n {\n error: {\n message:\n \"Unauthorized. Provide Authorization: Bearer <key> or x-api-key.\",\n type: \"unauthorized\",\n },\n },\n 401,\n )\n }\n\n await next()\n }\n}\n","import { Database } from \"bun:sqlite\"\nimport consola from \"consola\"\nimport path from \"node:path\"\n\nimport { PATHS } from \"./paths\"\n\nconst ADMIN_DB_FILENAME = \"admin.sqlite\"\nconst DEFAULT_DB_PATH = path.join(PATHS.APP_DIR, ADMIN_DB_FILENAME)\n\nlet sharedDb: Database | null = null\nlet initialized = false\n\nconst INIT_WARN_THROTTLE_MS = 30_000\n\nlet lastInitWarnAtMs = 0\nlet suppressedInitWarnCount = 0\n\nfunction warnAdminDbInitFailure(error: unknown): void {\n const now = Date.now()\n\n if (now - lastInitWarnAtMs < INIT_WARN_THROTTLE_MS) {\n suppressedInitWarnCount++\n return\n }\n\n const suppressed = suppressedInitWarnCount\n suppressedInitWarnCount = 0\n lastInitWarnAtMs = now\n\n const suffix =\n suppressed > 0 ? ` (suppressed ${suppressed} similar errors)` : \"\"\n consola.warn(\n `Failed to initialize admin DB; admin features disabled${suffix}`,\n error,\n )\n}\n\nexport function getAdminDbPath(): string {\n return DEFAULT_DB_PATH\n}\n\nexport function openAdminDb(filePath: string = DEFAULT_DB_PATH): Database {\n return new Database(filePath)\n}\n\nexport function initAdminDb(db: Database): void {\n // Pragmas: prefer WAL for concurrent reads, keep writes fast.\n // Note: journal_mode=WAL is per-database and persists in the DB file.\n db.run(\"PRAGMA journal_mode = WAL;\")\n db.run(\"PRAGMA synchronous = NORMAL;\")\n db.run(\"PRAGMA busy_timeout = 3000;\")\n db.run(\"PRAGMA foreign_keys = ON;\")\n\n migrateAdminDb(db)\n}\n\nexport function getAdminDb(): Database {\n if (!sharedDb) {\n sharedDb = openAdminDb()\n }\n if (!initialized) {\n try {\n initAdminDb(sharedDb)\n initialized = true\n } catch (error) {\n // Admin DB is a best-effort feature; server should continue to run.\n warnAdminDbInitFailure(error)\n }\n }\n return sharedDb\n}\n\nexport function getAdminDbUserVersion(db: Database = getAdminDb()): number {\n try {\n const row = db.query(\"PRAGMA user_version;\").get() as {\n user_version?: number\n } | null\n return row?.user_version ?? 0\n } catch {\n return 0\n }\n}\n\nfunction migrateAdminDb(db: Database): void {\n const row = db.query(\"PRAGMA user_version;\").get() as {\n user_version?: number\n } | null\n const current = row?.user_version ?? 0\n\n if (current >= 4) {\n return\n }\n\n if (current < 1) {\n // v1: request_log table\n db.run(`\n CREATE TABLE IF NOT EXISTS request_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n request_id TEXT NOT NULL UNIQUE,\n\n started_at_ms INTEGER NOT NULL,\n finished_at_ms INTEGER,\n duration_ms INTEGER,\n ttfb_ms INTEGER,\n\n method TEXT NOT NULL,\n path TEXT NOT NULL,\n upstream_endpoint TEXT,\n stream INTEGER NOT NULL DEFAULT 0,\n\n account_id TEXT,\n account_type TEXT,\n cost_units REAL,\n client_model TEXT,\n upstream_model TEXT,\n\n client_ip TEXT,\n client_ip_source TEXT,\n user_agent TEXT,\n\n tokens_input INTEGER,\n tokens_output INTEGER,\n tokens_total INTEGER,\n tokens_cached_input INTEGER,\n usage_json TEXT,\n\n premium_remaining_before REAL,\n premium_remaining_after REAL,\n premium_remaining_diff REAL,\n premium_unlimited_before INTEGER,\n premium_unlimited_after INTEGER,\n\n http_status INTEGER,\n error_name TEXT,\n error_status INTEGER,\n error_message TEXT,\n selection_failure_reason TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_request_log_started_at\n ON request_log(started_at_ms DESC);\n CREATE INDEX IF NOT EXISTS idx_request_log_account_started_at\n ON request_log(account_id, started_at_ms DESC);\n CREATE INDEX IF NOT EXISTS idx_request_log_model_started_at\n ON request_log(upstream_model, started_at_ms DESC);\n CREATE INDEX IF NOT EXISTS idx_request_log_endpoint_started_at\n ON request_log(upstream_endpoint, started_at_ms DESC);\n CREATE INDEX IF NOT EXISTS idx_request_log_status_started_at\n ON request_log(http_status, started_at_ms DESC);\n\n PRAGMA user_version = 1;\n `)\n }\n\n if (current < 2) {\n // v2: request_log session correlation fields\n db.run(`\n ALTER TABLE request_log ADD COLUMN user_id TEXT;\n ALTER TABLE request_log ADD COLUMN safety_identifier TEXT;\n ALTER TABLE request_log ADD COLUMN prompt_cache_key TEXT;\n ALTER TABLE request_log ADD COLUMN initiator TEXT;\n ALTER TABLE request_log ADD COLUMN upstream_request_id TEXT;\n\n PRAGMA user_version = 2;\n `)\n }\n\n if (current < 3) {\n // v3: index for session lookup\n db.run(`\n CREATE INDEX IF NOT EXISTS idx_request_log_session_finished\n ON request_log(\n prompt_cache_key,\n safety_identifier,\n finished_at_ms DESC\n )\n WHERE finished_at_ms IS NOT NULL\n AND tokens_input IS NOT NULL;\n\n PRAGMA user_version = 3;\n `)\n }\n\n if (current < 4) {\n // v4: index for session lookup by client model\n db.run(`\n CREATE INDEX IF NOT EXISTS idx_request_log_session_finished_by_client_model\n ON request_log(\n prompt_cache_key,\n safety_identifier,\n client_model,\n finished_at_ms DESC\n )\n WHERE finished_at_ms IS NOT NULL\n AND tokens_input IS NOT NULL;\n\n PRAGMA user_version = 4;\n `)\n }\n}\n","import type { Database, SQLQueryBindings } from \"bun:sqlite\"\nimport type { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport type {\n ChatCompletionChunk,\n ChatCompletionResponse,\n} from \"~/services/copilot/create-chat-completions\"\nimport type { EmbeddingResponse } from \"~/services/copilot/create-embeddings\"\nimport type {\n ResponseStreamEvent,\n ResponsesResult,\n ResponseUsage,\n} from \"~/services/copilot/create-responses\"\n\nimport { getAdminDb, getAdminDbPath, getAdminDbUserVersion } from \"./admin-db\"\n\nconst DEFAULT_RETENTION_DAYS = 14\nconst DEFAULT_MAX_ROWS = 200_000\n\nconst INSERT_WARN_THROTTLE_MS = 30_000\n\nlet lastInsertWarnAtMs = 0\nlet suppressedInsertWarnCount = 0\n\nfunction warnInsertFailure(error: unknown): void {\n const now = Date.now()\n\n if (now - lastInsertWarnAtMs < INSERT_WARN_THROTTLE_MS) {\n suppressedInsertWarnCount++\n return\n }\n\n const suppressed = suppressedInsertWarnCount\n suppressedInsertWarnCount = 0\n lastInsertWarnAtMs = now\n\n const suffix =\n suppressed > 0 ? ` (suppressed ${suppressed} similar errors)` : \"\"\n consola.warn(`Failed to insert request log${suffix}`, error)\n}\n\nfunction toDbNull<T>(value: T | null | undefined): T | null {\n return value === undefined ? null : value\n}\n\nfunction toDbBool(value: boolean | undefined): 0 | 1 | null {\n if (value === true) return 1\n if (value === false) return 0\n return null\n}\n\nexport type ClientIpInfo = {\n ip?: string\n source?: string\n}\n\nexport function getClientIpInfo(c: Context): ClientIpInfo {\n const cf = c.req.header(\"cf-connecting-ip\")\n if (cf) return { ip: cf.trim(), source: \"cf-connecting-ip\" }\n\n const xff = c.req.header(\"x-forwarded-for\")\n if (xff) {\n const first = xff.split(\",\")[0]?.trim()\n if (first) return { ip: first, source: \"x-forwarded-for\" }\n }\n\n const xri = c.req.header(\"x-real-ip\")\n if (xri) return { ip: xri.trim(), source: \"x-real-ip\" }\n\n return {}\n}\n\nexport type NormalizedUsage = {\n tokensInput?: number\n tokensOutput?: number\n tokensTotal?: number\n tokensCachedInput?: number\n usageJson?: string\n}\n\nexport function normalizeChatCompletionsUsage(\n usage?: ChatCompletionResponse[\"usage\"] | ChatCompletionChunk[\"usage\"],\n): NormalizedUsage {\n if (!usage) return {}\n\n const cached = usage.prompt_tokens_details?.cached_tokens ?? 0\n const prompt = usage.prompt_tokens\n const completion = usage.completion_tokens\n const total = usage.total_tokens\n\n return {\n tokensCachedInput: cached,\n tokensInput: Math.max(0, prompt - cached),\n tokensOutput: completion,\n tokensTotal: total,\n usageJson: JSON.stringify(usage),\n }\n}\n\nexport function normalizeResponsesUsage(\n usage?: ResponseUsage | null,\n): NormalizedUsage {\n if (!usage) return {}\n\n const cached = usage.input_tokens_details?.cached_tokens ?? 0\n const input = usage.input_tokens\n const output = usage.output_tokens ?? 0\n const total = usage.total_tokens\n\n return {\n tokensCachedInput: cached,\n tokensInput: Math.max(0, input - cached),\n tokensOutput: output,\n tokensTotal: total,\n usageJson: JSON.stringify(usage),\n }\n}\n\ntype AnthropicUsage = {\n input_tokens?: number\n output_tokens?: number\n cache_creation_input_tokens?: number\n cache_read_input_tokens?: number\n service_tier?: \"standard\" | \"priority\" | \"batch\"\n}\n\nexport function normalizeMessagesUsage(\n usage?: AnthropicUsage | null,\n): NormalizedUsage {\n if (!usage) return {}\n\n const cached = usage.cache_read_input_tokens ?? 0\n const input = usage.input_tokens\n const output = usage.output_tokens\n const hasInput = typeof input === \"number\"\n const hasOutput = typeof output === \"number\"\n const tokensInput = hasInput ? Math.max(0, input - cached) : undefined\n const tokensOutput = hasOutput ? output : undefined\n const tokensTotal =\n hasInput || hasOutput ? (input ?? 0) + (output ?? 0) : undefined\n\n return {\n tokensCachedInput: cached,\n tokensInput,\n tokensOutput,\n tokensTotal,\n usageJson: JSON.stringify(usage),\n }\n}\n\nexport function normalizeEmbeddingsUsage(\n usage?: EmbeddingResponse[\"usage\"],\n): NormalizedUsage {\n if (!usage) return {}\n\n return {\n tokensCachedInput: 0,\n tokensInput: usage.prompt_tokens,\n tokensOutput: 0,\n tokensTotal: usage.total_tokens,\n usageJson: JSON.stringify(usage),\n }\n}\n\nexport type RequestLogInsert = {\n requestId: string\n startedAtMs: number\n finishedAtMs?: number\n durationMs?: number\n ttfbMs?: number\n\n method: string\n path: string\n upstreamEndpoint?: string\n stream: boolean\n\n accountId?: string\n accountType?: string\n costUnits?: number\n clientModel?: string\n upstreamModel?: string\n\n clientIp?: string\n clientIpSource?: string\n userAgent?: string\n\n userId?: string\n safetyIdentifier?: string\n promptCacheKey?: string\n initiator?: \"agent\" | \"user\"\n upstreamRequestId?: string\n\n tokensInput?: number\n tokensOutput?: number\n tokensTotal?: number\n tokensCachedInput?: number\n usageJson?: string\n\n premiumRemainingBefore?: number\n premiumRemainingAfter?: number\n premiumRemainingDiff?: number\n premiumUnlimitedBefore?: boolean\n premiumUnlimitedAfter?: boolean\n\n httpStatus?: number\n errorName?: string\n errorStatus?: number\n errorMessage?: string\n selectionFailureReason?: string\n}\n\nexport type RequestLogRow = {\n id: number\n request_id: string\n started_at_ms: number\n finished_at_ms: number | null\n duration_ms: number | null\n ttfb_ms: number | null\n\n method: string\n path: string\n upstream_endpoint: string | null\n stream: number\n\n account_id: string | null\n account_type: string | null\n cost_units: number | null\n client_model: string | null\n upstream_model: string | null\n\n client_ip: string | null\n client_ip_source: string | null\n user_agent: string | null\n\n user_id: string | null\n safety_identifier: string | null\n prompt_cache_key: string | null\n initiator: string | null\n upstream_request_id: string | null\n\n tokens_input: number | null\n tokens_output: number | null\n tokens_total: number | null\n tokens_cached_input: number | null\n usage_json: string | null\n\n premium_remaining_before: number | null\n premium_remaining_after: number | null\n premium_remaining_diff: number | null\n premium_unlimited_before: number | null\n premium_unlimited_after: number | null\n\n http_status: number | null\n error_name: string | null\n error_status: number | null\n error_message: string | null\n selection_failure_reason: string | null\n}\n\nexport type RequestLogQuery = {\n limit: number\n cursorId?: number\n\n accountId?: string\n upstreamModel?: string\n clientModel?: string\n upstreamEndpoint?: string\n path?: string\n status?: number\n hasError?: boolean\n fromMs?: number\n toMs?: number\n}\n\nexport type SessionUsageKey = {\n promptCacheKey: string\n safetyIdentifier: string\n clientModel: string\n}\n\nexport type RequestLogQueryResult = {\n items: Array<RequestLogRow>\n nextCursorId?: number\n hasMore: boolean\n}\n\nexport type AccountStatsRow = {\n account_id: string\n request_count: number\n error_count: number\n tokens_total: number\n avg_duration_ms: number\n last_request_at_ms: number\n}\n\nexport class RequestHistoryStore {\n private readonly db: Database\n private readonly insertStmt: ReturnType<Database[\"query\"]>\n\n private readonly getByRequestIdStmt: ReturnType<Database[\"query\"]>\n private readonly getLastCompletedUsageBySessionStmt: ReturnType<\n Database[\"query\"]\n >\n\n constructor(db: Database) {\n this.db = db\n\n this.insertStmt = db.query(`\n INSERT INTO request_log (\n request_id,\n started_at_ms,\n finished_at_ms,\n duration_ms,\n ttfb_ms,\n method,\n path,\n upstream_endpoint,\n stream,\n account_id,\n account_type,\n cost_units,\n client_model,\n upstream_model,\n client_ip,\n client_ip_source,\n user_agent,\n user_id,\n safety_identifier,\n prompt_cache_key,\n initiator,\n upstream_request_id,\n tokens_input,\n tokens_output,\n tokens_total,\n tokens_cached_input,\n usage_json,\n premium_remaining_before,\n premium_remaining_after,\n premium_remaining_diff,\n premium_unlimited_before,\n premium_unlimited_after,\n http_status,\n error_name,\n error_status,\n error_message,\n selection_failure_reason\n ) VALUES (\n ?,?,?,?,?,?,?,?,\n ?,?,?,?,?,?,?,?,\n ?,?,?,?,?,?,?,?,\n ?,?,?,?,?,?,?,?,\n ?,?,?,?,?\n );\n `)\n\n this.getByRequestIdStmt = db.query(\n \"SELECT * FROM request_log WHERE request_id = ? LIMIT 1;\",\n )\n\n this.getLastCompletedUsageBySessionStmt = db.query(`\n SELECT\n tokens_input,\n tokens_output,\n tokens_total,\n tokens_cached_input\n FROM request_log\n WHERE prompt_cache_key = ?\n AND safety_identifier = ?\n AND client_model = ?\n AND finished_at_ms IS NOT NULL\n AND tokens_input IS NOT NULL\n ORDER BY finished_at_ms DESC\n LIMIT 1;\n `)\n }\n\n insert(record: RequestLogInsert): void {\n try {\n const args = [\n record.requestId,\n record.startedAtMs,\n toDbNull(record.finishedAtMs),\n toDbNull(record.durationMs),\n toDbNull(record.ttfbMs),\n\n record.method,\n record.path,\n toDbNull(record.upstreamEndpoint),\n record.stream ? 1 : 0,\n\n toDbNull(record.accountId),\n toDbNull(record.accountType),\n toDbNull(record.costUnits),\n toDbNull(record.clientModel),\n toDbNull(record.upstreamModel),\n\n toDbNull(record.clientIp),\n toDbNull(record.clientIpSource),\n toDbNull(record.userAgent),\n toDbNull(record.userId),\n toDbNull(record.safetyIdentifier),\n toDbNull(record.promptCacheKey),\n toDbNull(record.initiator),\n toDbNull(record.upstreamRequestId),\n\n toDbNull(record.tokensInput),\n toDbNull(record.tokensOutput),\n toDbNull(record.tokensTotal),\n toDbNull(record.tokensCachedInput),\n toDbNull(record.usageJson),\n\n toDbNull(record.premiumRemainingBefore),\n toDbNull(record.premiumRemainingAfter),\n toDbNull(record.premiumRemainingDiff),\n toDbBool(record.premiumUnlimitedBefore),\n toDbBool(record.premiumUnlimitedAfter),\n\n toDbNull(record.httpStatus),\n toDbNull(record.errorName),\n toDbNull(record.errorStatus),\n toDbNull(record.errorMessage),\n toDbNull(record.selectionFailureReason),\n ] as const\n\n this.insertStmt.run(...args)\n } catch (error) {\n warnInsertFailure(error)\n }\n }\n\n getByRequestId(requestId: string): RequestLogRow | null {\n try {\n const row = this.getByRequestIdStmt.get(requestId) as\n | RequestLogRow\n | null\n | undefined\n return row ?? null\n } catch (error) {\n consola.debug(\"Failed to fetch request log by request_id\", error)\n return null\n }\n }\n\n getLastCompletedUsageBySession(\n session: SessionUsageKey,\n ): NormalizedUsage | null {\n if (\n !session.promptCacheKey\n || !session.safetyIdentifier\n || !session.clientModel\n ) {\n return null\n }\n\n try {\n const row = this.getLastCompletedUsageBySessionStmt.get(\n session.promptCacheKey,\n session.safetyIdentifier,\n session.clientModel,\n ) as\n | {\n tokens_input: number | null\n tokens_output: number | null\n tokens_total: number | null\n tokens_cached_input: number | null\n }\n | null\n | undefined\n\n if (!row || row.tokens_input === null) {\n return null\n }\n\n const tokensOutput =\n row.tokens_output === null ? undefined : row.tokens_output\n const tokensTotal =\n row.tokens_total === null ? undefined : row.tokens_total\n const tokensCachedInput =\n row.tokens_cached_input === null ? undefined : row.tokens_cached_input\n\n return {\n tokensInput: row.tokens_input,\n tokensOutput,\n tokensTotal,\n tokensCachedInput,\n }\n } catch (error) {\n consola.debug(\"Failed to fetch last completed usage by session\", error)\n return null\n }\n }\n\n query(params: RequestLogQuery): RequestLogQueryResult {\n const limit = Math.max(1, Math.min(params.limit, 200))\n\n const where: Array<string> = []\n const values: Array<SQLQueryBindings> = []\n\n if (params.cursorId !== undefined) {\n where.push(\"id < ?\")\n values.push(params.cursorId)\n }\n\n if (params.accountId) {\n where.push(\"account_id = ?\")\n values.push(params.accountId)\n }\n\n if (params.upstreamModel) {\n where.push(\"upstream_model = ?\")\n values.push(params.upstreamModel)\n }\n\n if (params.clientModel) {\n where.push(\"client_model = ?\")\n values.push(params.clientModel)\n }\n\n if (params.upstreamEndpoint) {\n where.push(\"upstream_endpoint = ?\")\n values.push(params.upstreamEndpoint)\n }\n\n if (params.path) {\n where.push(\"path = ?\")\n values.push(params.path)\n }\n\n if (params.status !== undefined) {\n where.push(\"http_status = ?\")\n values.push(params.status)\n }\n\n if (params.hasError === true) {\n where.push(\"http_status >= 400\")\n }\n if (params.hasError === false) {\n where.push(\"http_status < 400\")\n }\n\n if (params.fromMs !== undefined) {\n where.push(\"started_at_ms >= ?\")\n values.push(params.fromMs)\n }\n\n if (params.toMs !== undefined) {\n where.push(\"started_at_ms <= ?\")\n values.push(params.toMs)\n }\n\n const whereSql = where.length > 0 ? `WHERE ${where.join(\" AND \")}` : \"\"\n\n const sql = `\n SELECT *\n FROM request_log\n ${whereSql}\n ORDER BY id DESC\n LIMIT ?;\n `\n\n const rows = this.db\n .query(sql)\n .all(...values, limit + 1) as Array<RequestLogRow>\n\n const items = rows.slice(0, limit)\n const hasMore = rows.length > limit\n const nextCursorId = hasMore ? items.at(-1)?.id : undefined\n\n return {\n items,\n nextCursorId,\n hasMore,\n }\n }\n\n getAccountStatsSince(\n sinceMs: number,\n ): Record<string, AccountStatsRow | undefined> {\n try {\n const sql = `\n SELECT\n account_id,\n COUNT(*) AS request_count,\n SUM(CASE WHEN http_status >= 400 THEN 1 ELSE 0 END) AS error_count,\n COALESCE(SUM(tokens_total), 0) AS tokens_total,\n COALESCE(AVG(duration_ms), 0) AS avg_duration_ms,\n COALESCE(MAX(started_at_ms), 0) AS last_request_at_ms\n FROM request_log\n WHERE started_at_ms >= ? AND account_id IS NOT NULL\n GROUP BY account_id;\n `\n\n const rows = this.db.query(sql).all(sinceMs) as Array<AccountStatsRow>\n const map: Record<string, AccountStatsRow | undefined> = {}\n for (const row of rows) {\n map[row.account_id] = row\n }\n return map\n } catch (error) {\n consola.debug(\"Failed to fetch account stats\", error)\n return {}\n }\n }\n\n cleanupRetention(\n retentionDays: number = DEFAULT_RETENTION_DAYS,\n maxRows: number = DEFAULT_MAX_ROWS,\n ): void {\n try {\n const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1000\n this.db\n .query(\"DELETE FROM request_log WHERE started_at_ms < ?;\")\n .run(cutoffMs)\n\n const countRow = this.db\n .query(\"SELECT COUNT(*) AS c FROM request_log;\")\n .get() as { c: number }\n\n const count = countRow.c\n if (count <= maxRows) {\n return\n }\n\n const offset = maxRows - 1\n const threshold = this.db\n .query(\"SELECT id FROM request_log ORDER BY id DESC LIMIT 1 OFFSET ?;\")\n .get(offset) as { id?: number } | null\n\n const thresholdId = threshold?.id\n if (!thresholdId) {\n return\n }\n\n this.db.query(\"DELETE FROM request_log WHERE id < ?;\").run(thresholdId)\n } catch (error) {\n consola.debug(\"Failed to cleanup request_log retention\", error)\n }\n }\n\n meta(): {\n dbPath: string\n userVersion: number\n retentionDays: number\n maxRows: number\n } {\n return {\n dbPath: getAdminDbPath(),\n userVersion: getAdminDbUserVersion(this.db),\n retentionDays: DEFAULT_RETENTION_DAYS,\n maxRows: DEFAULT_MAX_ROWS,\n }\n }\n}\n\nexport type RequestHistoryStoreApi = {\n insert(record: RequestLogInsert): void\n getByRequestId(requestId: string): RequestLogRow | null\n getLastCompletedUsageBySession(\n session: SessionUsageKey,\n ): NormalizedUsage | null\n query(params: RequestLogQuery): RequestLogQueryResult\n getAccountStatsSince(\n sinceMs: number,\n ): Record<string, AccountStatsRow | undefined>\n cleanupRetention(retentionDays?: number, maxRows?: number): void\n meta(): {\n dbPath: string\n userVersion: number\n retentionDays: number\n maxRows: number\n }\n}\n\nconst STORE_INIT_WARN_THROTTLE_MS = 30_000\nconst STORE_INIT_RETRY_DELAY_MS = 30_000\n\nlet lastStoreInitWarnAtMs = 0\nlet suppressedStoreInitWarnCount = 0\nlet nextStoreRetryAtMs = 0\n\nfunction warnStoreInitFailure(error: unknown): void {\n const now = Date.now()\n\n if (now - lastStoreInitWarnAtMs < STORE_INIT_WARN_THROTTLE_MS) {\n suppressedStoreInitWarnCount++\n return\n }\n\n const suppressed = suppressedStoreInitWarnCount\n suppressedStoreInitWarnCount = 0\n lastStoreInitWarnAtMs = now\n\n const suffix =\n suppressed > 0 ? ` (suppressed ${suppressed} similar errors)` : \"\"\n consola.warn(`Request history store is disabled${suffix}`, error)\n}\n\nconst disabledStore: RequestHistoryStoreApi = {\n insert: () => {},\n getByRequestId: () => null,\n getLastCompletedUsageBySession: () => null,\n query: () => ({ items: [], hasMore: false }),\n getAccountStatsSince: () => ({}),\n cleanupRetention: () => {},\n meta: () => ({\n dbPath: getAdminDbPath(),\n userVersion: 0,\n retentionDays: DEFAULT_RETENTION_DAYS,\n maxRows: DEFAULT_MAX_ROWS,\n }),\n}\n\nlet sharedStore: RequestHistoryStoreApi | null = null\nlet maintenanceStarted = false\n\nexport function getRequestHistoryStore(): RequestHistoryStoreApi {\n if (sharedStore) {\n return sharedStore\n }\n\n const now = Date.now()\n if (now < nextStoreRetryAtMs) {\n return disabledStore\n }\n\n try {\n sharedStore = new RequestHistoryStore(getAdminDb())\n\n if (!maintenanceStarted) {\n maintenanceStarted = true\n\n // Run once at startup.\n sharedStore.cleanupRetention()\n\n // Then daily.\n setInterval(\n () => {\n sharedStore?.cleanupRetention()\n },\n 24 * 60 * 60 * 1000,\n )\n }\n\n return sharedStore\n } catch (error) {\n nextStoreRetryAtMs = now + STORE_INIT_RETRY_DELAY_MS\n warnStoreInitFailure(error)\n return disabledStore\n }\n}\n\nexport function extractResponsesUsageFromStreamEvent(\n event: ResponseStreamEvent,\n): NormalizedUsage {\n if (\n event.type === \"response.completed\"\n || event.type === \"response.incomplete\"\n ) {\n return normalizeResponsesUsage(event.response.usage)\n }\n\n if (event.type === \"response.failed\") {\n return normalizeResponsesUsage(event.response.usage)\n }\n\n return {}\n}\n\nexport function extractResponsesUsageFromResult(\n result: ResponsesResult,\n): NormalizedUsage {\n return normalizeResponsesUsage(result.usage)\n}\n","import { Hono, type Context } from \"hono\"\nimport { randomUUID } from \"node:crypto\"\nimport fs from \"node:fs/promises\"\n\nimport { accountsManager } from \"~/lib/accounts-manager\"\nimport { listAccountsFromRegistry } from \"~/lib/accounts-registry\"\nimport {\n getConfig,\n getModelAliases,\n isFreeModelLoadBalancingEnabled,\n mergeConfigWithDefaults,\n type AppConfig,\n} from \"~/lib/config\"\nimport { PATHS } from \"~/lib/paths\"\nimport {\n getRequestHistoryStore,\n type AccountStatsRow,\n} from \"~/lib/request-history\"\n\nconst ADMIN_TOKEN = process.env.ADMIN_TOKEN?.trim() || undefined\n\ntype AdminAccessDecision =\n | { ok: true }\n | {\n ok: false\n status: 401 | 403\n message: string\n errorType: \"unauthorized\" | \"forbidden\"\n }\n\nfunction isLoopbackHostname(hostname: string): boolean {\n return (\n hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"::1\"\n )\n}\n\nfunction getBearerToken(value: string): string | undefined {\n const trimmed = value.trim()\n if (!trimmed.toLowerCase().startsWith(\"bearer \")) return undefined\n const token = trimmed.slice(\"bearer \".length).trim()\n return token || undefined\n}\n\nfunction getRequestAdminToken(c: Context): string | undefined {\n const headerToken = c.req.header(\"x-admin-token\")?.trim()\n if (headerToken) return headerToken\n\n const bearer = c.req.header(\"authorization\")\n if (bearer) {\n return getBearerToken(bearer)\n }\n\n return undefined\n}\n\nfunction isSameOrigin(requestUrl: URL, originHeader: string): boolean {\n try {\n return new URL(originHeader).origin === requestUrl.origin\n } catch {\n return false\n }\n}\n\nfunction decideAdminAccess(c: Context): AdminAccessDecision {\n const url = new URL(c.req.url, \"http://local\")\n\n const token = getRequestAdminToken(c)\n const tokenOk = Boolean(ADMIN_TOKEN) && token === ADMIN_TOKEN\n\n const origin = c.req.header(\"origin\")\n if (origin && !tokenOk && !isSameOrigin(url, origin)) {\n return {\n ok: false,\n status: 403,\n message: \"Cross-origin access to admin API is forbidden.\",\n errorType: \"forbidden\",\n }\n }\n\n if (isLoopbackHostname(url.hostname) || tokenOk) {\n return { ok: true }\n }\n\n if (ADMIN_TOKEN) {\n return {\n ok: false,\n status: 401,\n message:\n \"Admin API requires x-admin-token or Authorization: Bearer <token>.\",\n errorType: \"unauthorized\",\n }\n }\n\n return {\n ok: false,\n status: 403,\n message:\n \"Admin API is only available on localhost. Set ADMIN_TOKEN to enable remote access.\",\n errorType: \"forbidden\",\n }\n}\n\ntype AccountItem = {\n account_id: string\n account_type?: string\n runtime: {\n entitlement?: number\n remaining?: number\n unlimited?: boolean\n failed?: boolean\n failureReason?: string\n }\n stats?: {\n since_ms: number\n request_count?: number\n error_count?: number\n tokens_total?: number\n avg_duration_ms?: number\n last_request_at_ms?: number\n }\n}\n\nfunction parseFiniteNumber(value: string | null): number | undefined {\n if (!value) return undefined\n const n = Number(value)\n return Number.isFinite(n) ? n : undefined\n}\n\nfunction parseTriStateBool(value: string | null): boolean | undefined {\n if (value === \"1\") return true\n if (value === \"0\") return false\n return undefined\n}\n\ntype ReasoningEffort = \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\"\n\ntype ConfigErrorType = \"bad_request\" | \"internal_error\"\n\ntype ConfigErrorPayload = {\n message: string\n type: ConfigErrorType\n}\n\nconst CONFIG_KEYS = new Set<keyof AppConfig>([\n \"extraPrompts\",\n \"smallModel\",\n \"freeModelLoadBalancing\",\n \"apiKey\",\n \"modelReasoningEfforts\",\n \"modelAliases\",\n \"allowOriginalModelNamesForAliases\",\n \"useFunctionApplyPatch\",\n \"forceAgent\",\n \"compactUseSmallModel\",\n])\n\nconst REASONING_EFFORTS = new Set<ReasoningEffort>([\n \"none\",\n \"minimal\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n])\n\nconst BLOCKED_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"])\n\nfunction jsonError(\n c: Context,\n status: 400 | 500,\n error: ConfigErrorPayload,\n): Response {\n return c.json(\n {\n error,\n },\n status,\n )\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\ntype ParseFieldResult<T> = { clear: true } | { value: T } | { error: string }\n\nfunction parseOptionalString(\n value: unknown,\n field: string,\n): ParseFieldResult<string> {\n if (value === null || value === undefined) return { clear: true }\n if (typeof value !== \"string\") return { error: `${field} must be a string` }\n\n const trimmed = value.trim()\n if (!trimmed) return { clear: true }\n\n return { value: trimmed }\n}\n\nfunction parseOptionalBoolean(\n value: unknown,\n field: string,\n): ParseFieldResult<boolean> {\n if (value === null || value === undefined) return { clear: true }\n if (typeof value !== \"boolean\") return { error: `${field} must be a boolean` }\n return { value }\n}\n\nfunction parseStringRecord(\n value: unknown,\n field: string,\n): ParseFieldResult<Record<string, string>> {\n if (value === null || value === undefined) return { clear: true }\n if (!isPlainObject(value)) {\n return { error: `${field} must be an object with string values` }\n }\n\n const record = Object.create(null) as Record<string, string>\n for (const [key, entry] of Object.entries(value)) {\n if (BLOCKED_KEYS.has(key)) {\n return { error: `${field}.${key} is not allowed` }\n }\n if (typeof entry !== \"string\") {\n return { error: `${field}.${key} must be a string` }\n }\n record[key] = entry\n }\n\n return { value: record }\n}\n\nfunction parseReasoningRecord(\n value: unknown,\n): ParseFieldResult<Record<string, ReasoningEffort>> {\n if (value === null || value === undefined) return { clear: true }\n if (!isPlainObject(value)) {\n return { error: \"modelReasoningEfforts must be an object\" }\n }\n\n const record = Object.create(null) as Record<string, ReasoningEffort>\n for (const [model, effort] of Object.entries(value)) {\n if (BLOCKED_KEYS.has(model)) {\n return { error: `modelReasoningEfforts.${model} is not allowed` }\n }\n if (typeof effort !== \"string\") {\n return { error: `modelReasoningEfforts.${model} must be a string` }\n }\n if (!REASONING_EFFORTS.has(effort as ReasoningEffort)) {\n return {\n error: `modelReasoningEfforts.${model} must be one of ${[\n ...REASONING_EFFORTS,\n ].join(\", \")}`,\n }\n }\n record[model] = effort as ReasoningEffort\n }\n\n return { value: record }\n}\n\ntype ParsedModelAlias = {\n alias: string\n target: string\n allowOriginal?: boolean\n}\n\nfunction parseModelAliasEntry(\n rawAlias: string,\n rawTarget: unknown,\n): ParseFieldResult<ParsedModelAlias> {\n if (BLOCKED_KEYS.has(rawAlias)) {\n return { error: `modelAliases.${rawAlias} is not allowed` }\n }\n\n const alias = rawAlias.trim().toLowerCase()\n if (!alias) {\n return { error: \"modelAliases keys must be non-empty strings\" }\n }\n if (BLOCKED_KEYS.has(alias)) {\n return { error: `modelAliases.${alias} is not allowed` }\n }\n\n let target: string | undefined\n let allowOriginal: boolean | undefined\n\n if (typeof rawTarget === \"string\") {\n target = rawTarget.trim()\n } else if (isPlainObject(rawTarget)) {\n const rawTargetValue = rawTarget.target\n if (typeof rawTargetValue !== \"string\") {\n return { error: `modelAliases.${rawAlias}.target must be a string` }\n }\n target = rawTargetValue.trim()\n\n if (\"allowOriginal\" in rawTarget) {\n if (typeof rawTarget.allowOriginal !== \"boolean\") {\n return {\n error: `modelAliases.${rawAlias}.allowOriginal must be a boolean`,\n }\n }\n allowOriginal = rawTarget.allowOriginal\n }\n } else {\n return { error: `modelAliases.${rawAlias} must be a string or object` }\n }\n\n if (!target) {\n return { error: `modelAliases.${rawAlias} must be a non-empty string` }\n }\n if (alias === target.toLowerCase()) {\n return { error: `modelAliases.${rawAlias} cannot map to itself` }\n }\n\n return { value: { alias, target, allowOriginal } }\n}\n\nfunction parseModelAliases(\n value: unknown,\n): ParseFieldResult<\n Record<string, { target: string; allowOriginal?: boolean }>\n> {\n if (value === null || value === undefined) return { clear: true }\n if (!isPlainObject(value)) {\n return { error: \"modelAliases must be an object\" }\n }\n\n const record = Object.create(null) as Record<\n string,\n { target: string; allowOriginal?: boolean }\n >\n\n for (const [rawAlias, rawTarget] of Object.entries(value)) {\n const parsed = parseModelAliasEntry(rawAlias, rawTarget)\n if (\"error\" in parsed) return parsed\n if (\"clear\" in parsed) continue\n\n const { alias, target, allowOriginal } = parsed.value\n const existing = Object.hasOwn(record, alias) ? record[alias] : undefined\n if (\n existing\n && (existing.target !== target\n || existing.allowOriginal !== allowOriginal)\n ) {\n return { error: `modelAliases.${rawAlias} conflicts with ${alias}` }\n }\n\n record[alias] =\n allowOriginal === undefined ? { target } : { target, allowOriginal }\n }\n\n return { value: record }\n}\n\nfunction applyOptionalString(\n next: AppConfig,\n key: \"smallModel\" | \"apiKey\",\n value: unknown,\n): string | undefined {\n const parsed = parseOptionalString(value, key)\n if (\"error\" in parsed) return parsed.error\n if (\"clear\" in parsed) {\n next[key] = undefined\n return undefined\n }\n next[key] = parsed.value\n return undefined\n}\n\nfunction applyOptionalBoolean(\n next: AppConfig,\n key:\n | \"freeModelLoadBalancing\"\n | \"useFunctionApplyPatch\"\n | \"forceAgent\"\n | \"compactUseSmallModel\"\n | \"allowOriginalModelNamesForAliases\",\n value: unknown,\n): string | undefined {\n const parsed = parseOptionalBoolean(value, key)\n if (\"error\" in parsed) return parsed.error\n if (\"clear\" in parsed) {\n next[key] = undefined\n return undefined\n }\n next[key] = parsed.value\n return undefined\n}\n\nfunction applyExtraPrompts(\n next: AppConfig,\n value: unknown,\n): string | undefined {\n const parsed = parseStringRecord(value, \"extraPrompts\")\n if (\"error\" in parsed) return parsed.error\n if (\"clear\" in parsed) {\n delete next.extraPrompts\n return undefined\n }\n next.extraPrompts = parsed.value\n return undefined\n}\n\nfunction applyReasoningEfforts(\n next: AppConfig,\n value: unknown,\n): string | undefined {\n const parsed = parseReasoningRecord(value)\n if (\"error\" in parsed) return parsed.error\n if (\"clear\" in parsed) {\n delete next.modelReasoningEfforts\n return undefined\n }\n next.modelReasoningEfforts = parsed.value\n return undefined\n}\n\nfunction applyModelAliases(\n next: AppConfig,\n value: unknown,\n): string | undefined {\n const parsed = parseModelAliases(value)\n if (\"error\" in parsed) return parsed.error\n if (\"clear\" in parsed) {\n delete next.modelAliases\n return undefined\n }\n next.modelAliases = parsed.value\n return undefined\n}\n\nfunction applyConfigPatch(\n base: AppConfig,\n input: Record<string, unknown>,\n): { config?: AppConfig; error?: string } {\n const next: AppConfig = { ...base }\n\n for (const [rawKey, value] of Object.entries(input)) {\n const key = rawKey as keyof AppConfig\n if (!CONFIG_KEYS.has(key)) {\n return { error: `Unknown config key: ${rawKey}` }\n }\n\n let error: string | undefined\n\n switch (rawKey) {\n case \"extraPrompts\": {\n error = applyExtraPrompts(next, value)\n break\n }\n case \"smallModel\": {\n error = applyOptionalString(next, \"smallModel\", value)\n break\n }\n case \"freeModelLoadBalancing\": {\n error = applyOptionalBoolean(next, \"freeModelLoadBalancing\", value)\n break\n }\n case \"apiKey\": {\n error = applyOptionalString(next, \"apiKey\", value)\n break\n }\n case \"modelReasoningEfforts\": {\n error = applyReasoningEfforts(next, value)\n break\n }\n case \"modelAliases\": {\n error = applyModelAliases(next, value)\n break\n }\n case \"allowOriginalModelNamesForAliases\": {\n error = applyOptionalBoolean(\n next,\n \"allowOriginalModelNamesForAliases\",\n value,\n )\n break\n }\n case \"useFunctionApplyPatch\": {\n error = applyOptionalBoolean(next, \"useFunctionApplyPatch\", value)\n break\n }\n case \"forceAgent\": {\n error = applyOptionalBoolean(next, \"forceAgent\", value)\n break\n }\n case \"compactUseSmallModel\": {\n error = applyOptionalBoolean(next, \"compactUseSmallModel\", value)\n break\n }\n default: {\n return { error: `Unsupported config key: ${rawKey}` }\n }\n }\n\n if (error) return { error }\n }\n\n return { config: next }\n}\n\nasync function writeConfigFile(config: AppConfig): Promise<void> {\n await fs.mkdir(PATHS.APP_DIR, { recursive: true })\n\n const content = `${JSON.stringify(config, null, 2)}\\n`\n const tmpPath = `${PATHS.CONFIG_PATH}.tmp-${randomUUID()}`\n\n try {\n await fs.writeFile(tmpPath, content, \"utf8\")\n try {\n await fs.chmod(tmpPath, 0o600)\n } catch {\n // Ignore chmod errors (e.g. unsupported filesystem).\n }\n await fs.rename(tmpPath, PATHS.CONFIG_PATH)\n } catch (error) {\n await fs.rm(tmpPath, { force: true }).catch(() => {})\n throw error\n }\n}\n\nexport const adminApiRoutes = new Hono()\n\nadminApiRoutes.use(\"*\", async (c, next) => {\n const decision = decideAdminAccess(c)\n if (!decision.ok) {\n return c.json(\n {\n error: {\n message: decision.message,\n type: decision.errorType,\n },\n },\n decision.status,\n )\n }\n\n await next()\n})\n\nadminApiRoutes.get(\"/meta\", (c) => {\n const store = getRequestHistoryStore()\n return c.json(store.meta())\n})\n\nadminApiRoutes.get(\"/config\", (c) => {\n try {\n const config = mergeConfigWithDefaults()\n return c.json({ ...config, _configPath: PATHS.CONFIG_PATH })\n } catch {\n return jsonError(c, 500, {\n message: \"Failed to load config.\",\n type: \"internal_error\",\n })\n }\n})\n\nadminApiRoutes.post(\"/config\", async (c) => {\n let payload: unknown\n try {\n payload = await c.req.json()\n } catch {\n return jsonError(c, 400, {\n message: \"Config payload must be valid JSON.\",\n type: \"bad_request\",\n })\n }\n\n if (!isPlainObject(payload)) {\n return jsonError(c, 400, {\n message: \"Config payload must be an object.\",\n type: \"bad_request\",\n })\n }\n\n const result = applyConfigPatch(getConfig(), payload)\n if (!result.config) {\n return jsonError(c, 400, {\n message: result.error ?? \"Invalid config payload.\",\n type: \"bad_request\",\n })\n }\n\n try {\n await writeConfigFile(result.config)\n const merged = mergeConfigWithDefaults()\n accountsManager.setFreeModelLoadBalancingEnabled(\n isFreeModelLoadBalancingEnabled(),\n )\n return c.json({ ...merged, _configPath: PATHS.CONFIG_PATH })\n } catch {\n return jsonError(c, 500, {\n message: \"Failed to write config.\",\n type: \"internal_error\",\n })\n }\n})\n\nadminApiRoutes.get(\"/models\", (c) => {\n try {\n const accountModels = accountsManager.getFirstAccountModels()\n const items =\n accountModels?.data\n .map((model) => model.id)\n .filter(\n (id): id is string => typeof id === \"string\" && id.trim().length > 0,\n ) ?? []\n const aliasItems = Object.keys(getModelAliases())\n const uniqueItems = Array.from(new Set([...items, ...aliasItems])).sort()\n return c.json({ items: uniqueItems })\n } catch {\n return jsonError(c, 500, {\n message: \"Failed to load models.\",\n type: \"internal_error\",\n })\n }\n})\n\nadminApiRoutes.get(\"/accounts\", async (c) => {\n const url = new URL(c.req.url, \"http://local\")\n const sinceMs = Number(url.searchParams.get(\"since_ms\") ?? \"\")\n const includeStats = url.searchParams.get(\"include_stats\") !== \"0\"\n\n let since = Date.now() - 24 * 60 * 60 * 1000\n if (Number.isFinite(sinceMs) && sinceMs > 0) {\n since = sinceMs\n }\n\n const registry = await listAccountsFromRegistry().catch(() => [])\n const registryTypeById = new Map(registry.map((a) => [a.id, a.accountType]))\n\n const statuses = accountsManager.getAccountStatus()\n\n const store = getRequestHistoryStore()\n const statsByAccount: Record<string, AccountStatsRow | undefined> =\n includeStats ? store.getAccountStatsSince(since) : {}\n\n const items: Array<AccountItem> = statuses.map((s) => {\n const accountType = registryTypeById.get(s.id)\n const statsRow = includeStats ? statsByAccount[s.id] : undefined\n\n const stats =\n includeStats ?\n {\n since_ms: since,\n request_count: statsRow?.request_count,\n error_count: statsRow?.error_count,\n tokens_total: statsRow?.tokens_total,\n avg_duration_ms: statsRow?.avg_duration_ms,\n last_request_at_ms: statsRow?.last_request_at_ms,\n }\n : undefined\n\n return {\n account_id: s.id,\n account_type: accountType,\n runtime: {\n entitlement: s.entitlement,\n remaining: s.remaining,\n unlimited: s.unlimited,\n failed: s.failed,\n failureReason: s.failureReason,\n },\n stats,\n }\n })\n\n return c.json({ items })\n})\n\nadminApiRoutes.get(\"/requests\", (c) => {\n const url = new URL(c.req.url, \"http://local\")\n const p = url.searchParams\n\n const limit = parseFiniteNumber(p.get(\"limit\")) ?? 50\n const cursorId = parseFiniteNumber(p.get(\"cursor_id\"))\n\n const status = parseFiniteNumber(p.get(\"status\"))\n const hasError = parseTriStateBool(p.get(\"has_error\"))\n\n const fromMs = parseFiniteNumber(p.get(\"from_ms\"))\n const toMs = parseFiniteNumber(p.get(\"to_ms\"))\n\n const store = getRequestHistoryStore()\n const result = store.query({\n limit,\n cursorId,\n\n accountId: p.get(\"account_id\") || undefined,\n upstreamModel: p.get(\"upstream_model\") || undefined,\n clientModel: p.get(\"client_model\") || undefined,\n upstreamEndpoint: p.get(\"upstream_endpoint\") || undefined,\n path: p.get(\"path\") || undefined,\n\n status,\n hasError,\n fromMs,\n toMs,\n })\n\n return c.json({\n items: result.items,\n next_cursor_id: result.nextCursorId,\n has_more: result.hasMore,\n })\n})\n\nadminApiRoutes.get(\"/requests/:requestId\", (c) => {\n const requestId = c.req.param(\"requestId\")\n const store = getRequestHistoryStore()\n const item = store.getByRequestId(requestId)\n return c.json({ item })\n})\n","import { Hono } from \"hono\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport * as path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\nfunction resolveAdminDistDir(): string | null {\n // Prefer locating dist/admin relative to the compiled output (dist/*.js).\n const candidates = [\n fileURLToPath(new URL(\"./admin/\", import.meta.url)),\n // Fallback for local dev (src/routes/admin/route.ts -> ../../../dist/admin).\n fileURLToPath(new URL(\"../../../dist/admin/\", import.meta.url)),\n ]\n\n for (const dir of candidates) {\n if (existsSync(dir)) return dir\n }\n\n return null\n}\n\nfunction safeResolveFile(distDir: string, relPath: string): string | null {\n const normalized = relPath.startsWith(\"/\") ? relPath.slice(1) : relPath\n const full = path.resolve(distDir, normalized)\n const rel = path.relative(distDir, full)\n\n if (rel.startsWith(\"..\") || path.isAbsolute(rel)) return null\n return full\n}\n\nconst CONTENT_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"application/javascript; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".json\": \"application/json; charset=utf-8\",\n \".map\": \"application/json; charset=utf-8\",\n \".png\": \"image/png\",\n \".ico\": \"image/x-icon\",\n \".woff2\": \"font/woff2\",\n}\n\nfunction contentTypeFor(filePath: string): string | undefined {\n return CONTENT_TYPES[path.extname(filePath).toLowerCase()]\n}\n\nconst html = `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>copilot-api admin</title>\n <style>\n :root {\n --bg: #0b1020;\n --panel: #121a33;\n --text: #e6e9f2;\n --muted: #aab3d0;\n --border: #243055;\n --good: #28c37b;\n --bad: #ff5b5b;\n --warn: #ffb020;\n --mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,\n \"Liberation Mono\", \"Courier New\", monospace;\n --sans: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto,\n Helvetica, Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\";\n }\n * { box-sizing: border-box; }\n body {\n margin: 0;\n background: var(--bg);\n color: var(--text);\n font-family: var(--sans);\n }\n a { color: inherit; }\n header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--border);\n background: linear-gradient(180deg, rgba(18,26,51,.9), rgba(11,16,32,.9));\n position: sticky;\n top: 0;\n z-index: 10;\n backdrop-filter: blur(6px);\n }\n header h1 {\n margin: 0;\n font-size: 14px;\n letter-spacing: .2px;\n font-weight: 650;\n }\n header nav {\n display: flex;\n gap: 10px;\n }\n header nav a {\n padding: 6px 10px;\n border: 1px solid var(--border);\n border-radius: 8px;\n text-decoration: none;\n color: var(--muted);\n }\n header nav a.active {\n color: var(--text);\n border-color: #3a4a7e;\n background: rgba(255,255,255,.04);\n }\n .header-right {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n .token-controls {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .token-controls input {\n min-width: 160px;\n }\n main {\n padding: 16px;\n max-width: 1200px;\n margin: 0 auto;\n }\n .panel {\n border: 1px solid var(--border);\n background: rgba(18,26,51,.65);\n border-radius: 12px;\n padding: 12px;\n margin-bottom: 16px;\n }\n .row {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n align-items: end;\n }\n label {\n display: flex;\n flex-direction: column;\n gap: 6px;\n font-size: 12px;\n color: var(--muted);\n }\n input, select {\n background: rgba(0,0,0,.18);\n color: var(--text);\n border: 1px solid var(--border);\n border-radius: 10px;\n padding: 8px 10px;\n min-width: 180px;\n outline: none;\n }\n button {\n background: rgba(255,255,255,.06);\n color: var(--text);\n border: 1px solid var(--border);\n border-radius: 10px;\n padding: 8px 10px;\n cursor: pointer;\n }\n button:hover { border-color: #3a4a7e; }\n table {\n width: 100%;\n border-collapse: collapse;\n font-size: 12px;\n }\n th, td {\n border-bottom: 1px solid rgba(36,48,85,.7);\n padding: 8px 8px;\n vertical-align: top;\n }\n th {\n text-align: left;\n color: var(--muted);\n font-weight: 600;\n }\n .mono { font-family: var(--mono); }\n .pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 8px;\n border: 1px solid var(--border);\n border-radius: 999px;\n color: var(--muted);\n }\n .pill.good { color: var(--good); border-color: rgba(40,195,123,.35); }\n .pill.bad { color: var(--bad); border-color: rgba(255,91,91,.35); }\n .pill.warn { color: var(--warn); border-color: rgba(255,176,32,.35); }\n .muted { color: var(--muted); }\n pre {\n margin: 0;\n padding: 10px;\n border: 1px solid var(--border);\n border-radius: 10px;\n background: rgba(0,0,0,.25);\n overflow: auto;\n font-size: 12px;\n }\n .split {\n display: grid;\n grid-template-columns: 1fr;\n gap: 12px;\n }\n @media (min-width: 960px) {\n .split { grid-template-columns: 1fr 1fr; }\n }\n </style>\n </head>\n <body>\n <header>\n <h1>copilot-api / admin</h1>\n <div class=\"header-right\">\n <nav>\n <a href=\"#/accounts\" data-nav=\"accounts\">Accounts</a>\n <a href=\"#/requests\" data-nav=\"requests\">Requests</a>\n </nav>\n <div class=\"token-controls\">\n <input id=\"adminToken\" type=\"password\" placeholder=\"x-admin-token\" />\n <button id=\"adminTokenSave\">Set</button>\n <button id=\"adminTokenClear\">Clear</button>\n <span id=\"adminTokenStatus\" class=\"muted\"></span>\n </div>\n </div>\n </header>\n\n <main id=\"app\"></main>\n\n <script type=\"module\">\n const app = document.getElementById('app')\n const navLinks = [...document.querySelectorAll('a[data-nav]')]\n\n const ADMIN_TOKEN_STORAGE_KEY = 'adminToken'\n\n function getAdminToken() {\n return sessionStorage.getItem(ADMIN_TOKEN_STORAGE_KEY) || ''\n }\n\n function setAdminToken(value) {\n const token = (value || '').trim()\n if (!token) sessionStorage.removeItem(ADMIN_TOKEN_STORAGE_KEY)\n else sessionStorage.setItem(ADMIN_TOKEN_STORAGE_KEY, token)\n }\n\n function refreshAdminTokenUi() {\n const el = document.getElementById('adminTokenStatus')\n if (!el) return\n el.textContent = getAdminToken() ? 'token set' : ''\n }\n\n function initAdminTokenControls() {\n const input = document.getElementById('adminToken')\n const saveBtn = document.getElementById('adminTokenSave')\n const clearBtn = document.getElementById('adminTokenClear')\n\n if (saveBtn && input) {\n saveBtn.addEventListener('click', () => {\n setAdminToken(input.value)\n input.value = ''\n refreshAdminTokenUi()\n })\n }\n\n if (clearBtn && input) {\n clearBtn.addEventListener('click', () => {\n setAdminToken('')\n input.value = ''\n refreshAdminTokenUi()\n })\n }\n\n refreshAdminTokenUi()\n }\n\n initAdminTokenControls()\n\n function setActiveNav(key) {\n for (const a of navLinks) {\n a.classList.toggle('active', a.dataset.nav === key)\n }\n }\n\n function fmtMs(ms) {\n if (ms == null) return ''\n return new Date(ms).toISOString()\n }\n\n function fmtNum(x) {\n if (x == null || Number.isNaN(Number(x))) return ''\n return String(x)\n }\n\n function pill(text, kind) {\n return '<span class=\"pill ' + (kind || '') + '\">' + escapeHtml(text) + '</span>'\n }\n\n function qs() {\n return new URLSearchParams(location.hash.includes('?') ? location.hash.split('?')[1] : '')\n }\n\n async function api(path) {\n const token = getAdminToken()\n const headers = token ? { 'x-admin-token': token } : {}\n const res = await fetch(path, { headers })\n if (!res.ok) {\n const txt = await res.text().catch(() => '')\n throw new Error('HTTP ' + res.status + ': ' + txt)\n }\n return await res.json()\n }\n\n async function renderAccounts() {\n setActiveNav('accounts')\n app.innerHTML = [\n '<div class=\"panel\">',\n ' <div class=\"row\">',\n ' <label>Stats window',\n ' <select id=\"since\">',\n ' <option value=\"86400000\">Last 24h</option>',\n ' <option value=\"604800000\">Last 7d</option>',\n ' </select>',\n ' </label>',\n ' <button id=\"refresh\">Refresh</button>',\n ' <span class=\"muted\" id=\"meta\"></span>',\n ' </div>',\n '</div>',\n '<div class=\"panel\">',\n ' <table>',\n ' <thead>',\n ' <tr>',\n ' <th>Account</th>',\n ' <th>Status</th>',\n ' <th>Remaining</th>',\n ' <th>Requests</th>',\n ' <th>Errors</th>',\n ' <th>Tokens</th>',\n ' <th>Avg ms</th>',\n ' <th>Last req</th>',\n ' </tr>',\n ' </thead>',\n ' <tbody id=\"rows\"></tbody>',\n ' </table>',\n '</div>',\n ].join('')\n\n const sinceEl = document.getElementById('since')\n const refresh = document.getElementById('refresh')\n const rowsEl = document.getElementById('rows')\n const metaEl = document.getElementById('meta')\n\n async function load() {\n rowsEl.innerHTML = '<tr><td colspan=\"8\" class=\"muted\">Loading...</td></tr>'\n const windowMs = Number(sinceEl.value)\n const sinceMs = Date.now() - windowMs\n const [accounts, meta] = await Promise.all([\n api('/api/admin/accounts?since_ms=' + sinceMs + '&include_stats=1'),\n api('/api/admin/meta'),\n ])\n\n metaEl.textContent = 'DB v' + meta.userVersion + ' · ' + meta.dbPath\n\n rowsEl.innerHTML = accounts.items.map((a) => {\n const failed = a.runtime?.failed\n const statusPill = failed ? pill('failed', 'bad') : pill('ok', 'good')\n const rem = a.runtime?.unlimited ? pill('unlimited', 'good') : fmtNum(a.runtime?.remaining)\n const stats = a.stats || {}\n const last = stats.last_request_at_ms ? fmtMs(stats.last_request_at_ms) : ''\n const accountId = a.account_id\n const failureReason = failed\n ? '<div class=\"muted\">' + escapeHtml(a.runtime?.failureReason || '') + '</div>'\n : ''\n\n return '<tr>'\n + '<td class=\"mono\"><a href=\"#/requests?account_id='\n + encodeURIComponent(accountId)\n + '\">' + escapeHtml(accountId) + '</a></td>'\n + '<td>' + statusPill + failureReason + '</td>'\n + '<td>' + rem + '</td>'\n + '<td>' + fmtNum(stats.request_count) + '</td>'\n + '<td>' + fmtNum(stats.error_count) + '</td>'\n + '<td>' + fmtNum(stats.tokens_total) + '</td>'\n + '<td>' + fmtNum(Math.round(stats.avg_duration_ms || 0)) + '</td>'\n + '<td class=\"mono\">' + last + '</td>'\n + '</tr>'\n }).join('')\n }\n\n refresh.addEventListener('click', () => load())\n await load()\n }\n\n function buildRequestsQuery(extra = {}) {\n const p = qs()\n const out = new URLSearchParams()\n\n const keys = [\n 'account_id','upstream_model','client_model','upstream_endpoint','path',\n 'status','has_error','from_ms','to_ms','limit','cursor_id'\n ]\n for (const k of keys) {\n const v = p.get(k)\n if (v != null && v !== '') out.set(k, v)\n }\n for (const [k, v] of Object.entries(extra)) {\n if (v == null || v === '') out.delete(k)\n else out.set(k, String(v))\n }\n return out\n }\n\n async function renderRequests() {\n setActiveNav('requests')\n app.innerHTML = [\n '<div class=\"panel\">',\n ' <div class=\"row\">',\n ' <label>Account',\n ' <input id=\"account_id\" placeholder=\"octocat\" />',\n ' </label>',\n ' <label>Upstream model',\n ' <input id=\"upstream_model\" placeholder=\"gpt-5\" />',\n ' </label>',\n ' <label>Endpoint',\n ' <input id=\"upstream_endpoint\" placeholder=\"/responses\" />',\n ' </label>',\n ' <label>Status',\n ' <input id=\"status\" placeholder=\"200\" />',\n ' </label>',\n ' <label>Has error',\n ' <select id=\"has_error\">',\n ' <option value=\"\">(any)</option>',\n ' <option value=\"1\">yes</option>',\n ' <option value=\"0\">no</option>',\n ' </select>',\n ' </label>',\n ' <label>From (ms)',\n ' <input id=\"from_ms\" placeholder=\"\" />',\n ' </label>',\n ' <label>To (ms)',\n ' <input id=\"to_ms\" placeholder=\"\" />',\n ' </label>',\n ' <button id=\"apply\">Apply</button>',\n ' <button id=\"more\">Load more</button>',\n ' </div>',\n '</div>',\n '<div class=\"panel\">',\n ' <table>',\n ' <thead>',\n ' <tr>',\n ' <th>Time</th>',\n ' <th>Path</th>',\n ' <th>Endpoint</th>',\n ' <th>Account</th>',\n ' <th>Model</th>',\n ' <th>Tokens</th>',\n ' <th>Cost</th>',\n ' <th>Quota</th>',\n ' <th>Dur</th>',\n ' <th>Status</th>',\n ' </tr>',\n ' </thead>',\n ' <tbody id=\"rows\"></tbody>',\n ' </table>',\n '</div>',\n ].join('')\n\n const rowsEl = document.getElementById('rows')\n const applyBtn = document.getElementById('apply')\n const moreBtn = document.getElementById('more')\n\n const fields = ['account_id','upstream_model','upstream_endpoint','status','has_error','from_ms','to_ms']\n for (const f of fields) {\n const el = document.getElementById(f)\n const v = qs().get(f) || ''\n el.value = v\n }\n\n let nextCursor = qs().get('cursor_id') || ''\n let loading = false\n\n function setHashFromForm(cursorId) {\n const out = new URLSearchParams()\n for (const f of fields) {\n const v = document.getElementById(f).value.trim()\n if (v) out.set(f, v)\n }\n out.set('limit', '50')\n if (cursorId) out.set('cursor_id', cursorId)\n location.hash = '#/requests?' + out.toString()\n }\n\n async function load(reset) {\n if (loading) return\n loading = true\n try {\n const q = buildRequestsQuery({ limit: 50, cursor_id: reset ? '' : nextCursor })\n const data = await api('/api/admin/requests?' + q.toString())\n\n if (reset) rowsEl.innerHTML = ''\n\n for (const r of data.items) {\n const status = r.http_status\n const statusP = status >= 400 ? pill(status, 'bad') : pill(status, 'good')\n const when = fmtMs(r.started_at_ms)\n const quota = r.premium_unlimited_after\n ? '∞'\n : (r.premium_remaining_after != null ? fmtNum(r.premium_remaining_after) : '')\n const dur = r.duration_ms != null ? fmtNum(r.duration_ms) : ''\n const acct = r.account_id || ''\n const model = r.upstream_model || ''\n const tokens = r.tokens_total != null ? fmtNum(r.tokens_total) : ''\n\n rowsEl.insertAdjacentHTML('beforeend',\n '<tr>'\n + '<td class=\"mono\">' + when + '</td>'\n + '<td class=\"mono\"><a href=\"#/request/' + encodeURIComponent(r.request_id) + '\">' + escapeHtml(r.path) + '</a></td>'\n + '<td class=\"mono\">' + escapeHtml(r.upstream_endpoint || '') + '</td>'\n + '<td class=\"mono\">' + escapeHtml(acct) + '</td>'\n + '<td class=\"mono\">' + escapeHtml(model) + '</td>'\n + '<td class=\"mono\">' + tokens + '</td>'\n + '<td class=\"mono\">' + (r.cost_units ?? '') + '</td>'\n + '<td class=\"mono\">' + quota + '</td>'\n + '<td class=\"mono\">' + dur + '</td>'\n + '<td>' + statusP + '</td>'\n + '</tr>'\n )\n }\n\n nextCursor = data.next_cursor_id || ''\n moreBtn.disabled = !data.has_more\n } catch (e) {\n rowsEl.innerHTML = '<tr><td colspan=\"10\" class=\"muted\">' + escapeHtml(String(e)) + '</td></tr>'\n } finally {\n loading = false\n }\n }\n\n applyBtn.addEventListener('click', () => setHashFromForm(''))\n moreBtn.addEventListener('click', () => load(false))\n\n await load(true)\n }\n\n async function renderRequestDetail(requestId) {\n setActiveNav('requests')\n app.innerHTML = '<div class=\"panel\"><div class=\"muted\">Loading...</div></div>'\n const data = await api('/api/admin/requests/' + encodeURIComponent(requestId))\n const r = data.item\n if (!r) {\n app.innerHTML = '<div class=\"panel\"><div class=\"muted\">Not found</div></div>'\n return\n }\n\n app.innerHTML = [\n '<div class=\"panel\">',\n ' <div class=\"row\">',\n ' <div class=\"mono\">request_id: ' + escapeHtml(r.request_id) + '</div>',\n ' <div class=\"mono\">status: ' + r.http_status + '</div>',\n ' <div class=\"mono\">dur_ms: ' + (r.duration_ms ?? '') + '</div>',\n ' <div class=\"mono\">ttfb_ms: ' + (r.ttfb_ms ?? '') + '</div>',\n ' </div>',\n '</div>',\n '',\n '<div class=\"split\">',\n ' <div class=\"panel\">',\n ' <h3 style=\"margin:0 0 8px 0; font-size: 13px;\">Summary</h3>',\n ' <table>',\n ' <tbody>',\n ' <tr><th>time</th><td class=\"mono\">' + fmtMs(r.started_at_ms) + '</td></tr>',\n ' <tr><th>path</th><td class=\"mono\">' + escapeHtml(r.path) + '</td></tr>',\n ' <tr><th>endpoint</th><td class=\"mono\">' + escapeHtml(r.upstream_endpoint || '') + '</td></tr>',\n ' <tr><th>account</th><td class=\"mono\">' + escapeHtml(r.account_id || '') + '</td></tr>',\n ' <tr><th>model</th><td class=\"mono\">' + escapeHtml(r.upstream_model || '') + '</td></tr>',\n ' <tr><th>client</th><td class=\"mono\">' + escapeHtml(r.client_ip || '') + ' ' + (r.user_agent ? '(' + escapeHtml(r.user_agent) + ')' : '') + '</td></tr>',\n ' <tr><th>tokens</th><td class=\"mono\">in=' + (r.tokens_input ?? '') + ' out=' + (r.tokens_output ?? '') + ' total=' + (r.tokens_total ?? '') + ' cached=' + (r.tokens_cached_input ?? '') + '</td></tr>',\n ' <tr><th>quota</th><td class=\"mono\">before=' + (r.premium_remaining_before ?? '') + ' after=' + (r.premium_remaining_after ?? '') + ' diff=' + (r.premium_remaining_diff ?? '') + '</td></tr>',\n ' </tbody>',\n ' </table>',\n ' </div>',\n '',\n ' <div class=\"panel\">',\n ' <h3 style=\"margin:0 0 8px 0; font-size: 13px;\">Raw</h3>',\n ' <pre class=\"mono\">' + escapeHtml(JSON.stringify(r, null, 2)) + '</pre>',\n ' </div>',\n '</div>',\n ].join('')\n }\n\n function escapeHtml(s) {\n return String(s)\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''')\n }\n\n function route() {\n const h = location.hash || '#/accounts'\n const [path] = h.slice(1).split('?')\n if (path === '/accounts') return renderAccounts()\n if (path === '/requests') return renderRequests()\n if (path.startsWith('/request/')) {\n const requestId = decodeURIComponent(path.slice('/request/'.length))\n return renderRequestDetail(requestId)\n }\n location.hash = '#/accounts'\n }\n\n window.addEventListener('hashchange', route)\n route()\n </script>\n </body>\n</html>\n`\n\nexport const adminRoutes = new Hono()\n\nadminRoutes.get(\"*\", async (c) => {\n // Optional rollback: serve legacy inlined admin UI.\n if (process.env.ADMIN_UI_LEGACY === \"1\") {\n return c.html(html)\n }\n\n const distDir = resolveAdminDistDir()\n if (!distDir) {\n return c.html(html)\n }\n\n const url = new URL(c.req.url)\n\n // Compute path relative to the mounted /admin prefix.\n let relPath = url.pathname\n if (relPath.startsWith(\"/admin\")) {\n relPath = relPath.slice(\"/admin\".length)\n if (relPath === \"\") relPath = \"/\"\n }\n\n const requested = relPath === \"/\" ? \"/index.html\" : relPath\n const filePath = safeResolveFile(distDir, requested)\n if (!filePath) {\n return c.html(html)\n }\n\n try {\n const fileBuf = await readFile(filePath)\n const data = new Uint8Array(\n fileBuf.buffer.slice(\n fileBuf.byteOffset,\n fileBuf.byteOffset + fileBuf.byteLength,\n ) as ArrayBuffer,\n )\n const headers: Record<string, string> = {}\n\n const contentType = contentTypeFor(filePath)\n if (contentType) headers[\"content-type\"] = contentType\n\n if (requested.startsWith(\"/assets/\")) {\n headers[\"cache-control\"] = \"public, max-age=31536000, immutable\"\n } else if (requested.endsWith(\".html\")) {\n headers[\"cache-control\"] = \"no-cache\"\n } else {\n headers[\"cache-control\"] = \"public, max-age=31536000\"\n }\n\n return c.body(data, 200, headers)\n } catch {\n // For non-asset paths (e.g. /admin/settings), fall back to index.html.\n if (!relPath.includes(\".\")) {\n const indexPath = safeResolveFile(distDir, \"/index.html\")\n if (indexPath) {\n try {\n const indexBuf = await readFile(indexPath)\n const indexData = new Uint8Array(\n indexBuf.buffer.slice(\n indexBuf.byteOffset,\n indexBuf.byteOffset + indexBuf.byteLength,\n ) as ArrayBuffer,\n )\n return c.body(indexData, 200, {\n \"content-type\": \"text/html; charset=utf-8\",\n \"cache-control\": \"no-cache\",\n })\n } catch {\n // ignore\n }\n }\n }\n\n return c.html(html)\n }\n})\n","import consola from \"consola\"\n\nimport { HTTPError } from \"./error\"\n\nexport const awaitApproval = async () => {\n const response = await consola.prompt(`Accept incoming request?`, {\n type: \"confirm\",\n })\n\n if (!response)\n throw new HTTPError(\n \"Request rejected\",\n Response.json({ message: \"Request rejected\" }, { status: 403 }),\n )\n}\n","import type { AccountContext, AccountRuntime } from \"~/lib/types/account\"\n\nimport { HTTPError } from \"~/lib/error\"\n\nexport type ErrorDetails = {\n httpStatus: number\n errorName: string\n errorStatus: number | undefined\n errorMessage: string\n unauthorized: boolean\n}\n\nexport function truncate(value: string, max: number = 2000): string {\n if (value.length <= max) return value\n return `${value.slice(0, max)}…`\n}\n\nexport function computeDiff(\n before?: number,\n after?: number,\n): number | undefined {\n if (typeof before !== \"number\" || typeof after !== \"number\") return undefined\n return after - before\n}\n\nexport function toAccountContext(account: AccountRuntime): AccountContext {\n return {\n githubToken: account.githubToken,\n copilotToken: account.copilotToken,\n accountType: account.accountType,\n vsCodeVersion: account.vsCodeVersion,\n }\n}\n\nexport function extractErrorDetails(error: unknown): ErrorDetails {\n const errorName = error instanceof Error ? error.name : \"Error\"\n const errorMessage =\n error instanceof Error ? truncate(error.message) : truncate(String(error))\n\n const errorStatus =\n error instanceof HTTPError ? error.response.status : undefined\n const httpStatus = errorStatus ?? 500\n\n return {\n httpStatus,\n errorName,\n errorStatus,\n errorMessage,\n unauthorized: errorStatus === 401,\n }\n}\n","import consola, { type ConsolaInstance } from \"consola\"\nimport fs from \"node:fs\"\nimport path from \"node:path\"\nimport util from \"node:util\"\n\nimport { PATHS } from \"./paths\"\nimport { state } from \"./state\"\n\nconst LOG_RETENTION_DAYS = 7\nconst LOG_RETENTION_MS = LOG_RETENTION_DAYS * 24 * 60 * 60 * 1000\nconst CLEANUP_INTERVAL_MS = 24 * 60 * 60 * 1000\nconst LOG_DIR = path.join(PATHS.APP_DIR, \"logs\")\nconst FLUSH_INTERVAL_MS = 1000\nconst MAX_BUFFER_SIZE = 100\n\nconst logStreams = new Map<string, fs.WriteStream>()\nconst logBuffers = new Map<string, Array<string>>()\n\nconst ensureLogDirectory = () => {\n if (!fs.existsSync(LOG_DIR)) {\n fs.mkdirSync(LOG_DIR, { recursive: true })\n }\n}\n\nconst cleanupOldLogs = () => {\n if (!fs.existsSync(LOG_DIR)) {\n return\n }\n\n const now = Date.now()\n\n for (const entry of fs.readdirSync(LOG_DIR)) {\n const filePath = path.join(LOG_DIR, entry)\n\n let stats: fs.Stats\n try {\n stats = fs.statSync(filePath)\n } catch {\n continue\n }\n\n if (!stats.isFile()) {\n continue\n }\n\n if (now - stats.mtimeMs > LOG_RETENTION_MS) {\n try {\n fs.rmSync(filePath)\n } catch {\n continue\n }\n }\n }\n}\n\nconst formatArgs = (args: Array<unknown>) =>\n args\n .map((arg) =>\n typeof arg === \"string\" ? arg : (\n util.inspect(arg, { depth: null, colors: false })\n ),\n )\n .join(\" \")\n\nconst sanitizeName = (name: string) => {\n const normalized = name\n .toLowerCase()\n .replaceAll(/[^a-z0-9]+/g, \"-\")\n .replaceAll(/^-+|-+$/g, \"\")\n\n return normalized === \"\" ? \"handler\" : normalized\n}\n\nconst getLogStream = (filePath: string): fs.WriteStream => {\n let stream = logStreams.get(filePath)\n if (!stream || stream.destroyed) {\n stream = fs.createWriteStream(filePath, { flags: \"a\" })\n logStreams.set(filePath, stream)\n\n stream.on(\"error\", (error: unknown) => {\n console.warn(\"Log stream error\", error)\n logStreams.delete(filePath)\n })\n }\n return stream\n}\n\nconst flushBuffer = (filePath: string) => {\n const buffer = logBuffers.get(filePath)\n if (!buffer || buffer.length === 0) {\n return\n }\n\n const stream = getLogStream(filePath)\n const content = buffer.join(\"\\n\") + \"\\n\"\n stream.write(content, (error) => {\n if (error) {\n console.warn(\"Failed to write handler log\", error)\n }\n })\n\n logBuffers.set(filePath, [])\n}\n\nconst flushAllBuffers = () => {\n for (const filePath of logBuffers.keys()) {\n flushBuffer(filePath)\n }\n}\n\nconst appendLine = (filePath: string, line: string) => {\n let buffer = logBuffers.get(filePath)\n if (!buffer) {\n buffer = []\n logBuffers.set(filePath, buffer)\n }\n\n buffer.push(line)\n\n if (buffer.length >= MAX_BUFFER_SIZE) {\n flushBuffer(filePath)\n }\n}\n\nsetInterval(flushAllBuffers, FLUSH_INTERVAL_MS)\n\nconst cleanup = () => {\n flushAllBuffers()\n for (const stream of logStreams.values()) {\n stream.end()\n }\n logStreams.clear()\n logBuffers.clear()\n}\n\nprocess.on(\"exit\", cleanup)\nprocess.on(\"SIGINT\", () => {\n cleanup()\n process.exit(0)\n})\nprocess.on(\"SIGTERM\", () => {\n cleanup()\n process.exit(0)\n})\n\nlet lastCleanup = 0\n\nexport const createHandlerLogger = (name: string): ConsolaInstance => {\n ensureLogDirectory()\n\n const sanitizedName = sanitizeName(name)\n const instance = consola.withTag(name)\n\n if (state.verbose) {\n instance.level = 5\n }\n instance.setReporters([])\n\n instance.addReporter({\n log(logObj) {\n ensureLogDirectory()\n\n if (Date.now() - lastCleanup > CLEANUP_INTERVAL_MS) {\n cleanupOldLogs()\n lastCleanup = Date.now()\n }\n\n const date = logObj.date\n const dateKey = date.toLocaleDateString(\"sv-SE\")\n const timestamp = date.toLocaleString(\"sv-SE\", { hour12: false })\n const filePath = path.join(LOG_DIR, `${sanitizedName}-${dateKey}.log`)\n const message = formatArgs(logObj.args as Array<unknown>)\n const line = `[${timestamp}] [${logObj.type}] [${logObj.tag || name}]${\n message ? ` ${message}` : \"\"\n }`\n\n appendLine(filePath, line)\n },\n })\n\n return instance\n}\n","import consola from \"consola\"\n\nimport type { State } from \"./state\"\n\nimport { HTTPError } from \"./error\"\nimport { sleep } from \"./utils\"\n\nexport async function checkRateLimit(state: State) {\n if (state.rateLimitSeconds === undefined) return\n\n const now = Date.now()\n\n if (!state.lastRequestTimestamp) {\n state.lastRequestTimestamp = now\n return\n }\n\n const elapsedSeconds = (now - state.lastRequestTimestamp) / 1000\n\n if (elapsedSeconds > state.rateLimitSeconds) {\n state.lastRequestTimestamp = now\n return\n }\n\n const waitTimeSeconds = Math.ceil(state.rateLimitSeconds - elapsedSeconds)\n\n if (!state.rateLimitWait) {\n consola.warn(\n `Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`,\n )\n throw new HTTPError(\n \"Rate limit exceeded\",\n Response.json({ message: \"Rate limit exceeded\" }, { status: 429 }),\n )\n }\n\n const waitTimeMs = waitTimeSeconds * 1000\n consola.warn(\n `Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`,\n )\n await sleep(waitTimeMs)\n // eslint-disable-next-line require-atomic-updates\n state.lastRequestTimestamp = now\n consola.info(\"Rate limit wait completed, proceeding with request\")\n return\n}\n","import type {\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\nimport type { Model } from \"~/services/copilot/get-models\"\n\n// Encoder type mapping\nconst ENCODING_MAP = {\n o200k_base: () => import(\"gpt-tokenizer/encoding/o200k_base\"),\n cl100k_base: () => import(\"gpt-tokenizer/encoding/cl100k_base\"),\n p50k_base: () => import(\"gpt-tokenizer/encoding/p50k_base\"),\n p50k_edit: () => import(\"gpt-tokenizer/encoding/p50k_edit\"),\n r50k_base: () => import(\"gpt-tokenizer/encoding/r50k_base\"),\n} as const\n\ntype SupportedEncoding = keyof typeof ENCODING_MAP\n\n// Define encoder interface\ninterface Encoder {\n encode: (text: string) => Array<number>\n}\n\n// Cache loaded encoders to avoid repeated imports\nconst encodingCache = new Map<string, Encoder>()\n\n/**\n * Calculate tokens for tool calls\n */\nconst calculateToolCallsTokens = (\n toolCalls: Array<ToolCall>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = 0\n for (const toolCall of toolCalls) {\n tokens += constants.funcInit\n tokens += encoder.encode(toolCall.id).length\n tokens += encoder.encode(toolCall.function.name).length\n tokens += encoder.encode(toolCall.function.arguments).length\n }\n tokens += constants.funcEnd\n return tokens\n}\n\n/**\n * Calculate tokens for content parts\n */\nconst calculateContentPartsTokens = (\n contentParts: Array<ContentPart>,\n encoder: Encoder,\n): number => {\n let tokens = 0\n for (const part of contentParts) {\n if (part.type === \"image_url\") {\n tokens += encoder.encode(part.image_url.url).length + 85\n } else if (part.text) {\n tokens += encoder.encode(part.text).length\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens for a single message\n */\nconst calculateMessageTokens = (\n message: Message,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n const tokensPerMessage = 3\n const tokensPerName = 1\n let tokens = tokensPerMessage\n for (const [key, value] of Object.entries(message)) {\n if (key === \"reasoning_opaque\") {\n continue\n }\n if (typeof value === \"string\") {\n tokens += encoder.encode(value).length\n }\n if (key === \"name\") {\n tokens += tokensPerName\n }\n if (key === \"tool_calls\") {\n tokens += calculateToolCallsTokens(\n value as Array<ToolCall>,\n encoder,\n constants,\n )\n }\n if (key === \"content\" && Array.isArray(value)) {\n tokens += calculateContentPartsTokens(\n value as Array<ContentPart>,\n encoder,\n )\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens using custom algorithm\n */\nconst calculateTokens = (\n messages: Array<Message>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (messages.length === 0) {\n return 0\n }\n let numTokens = 0\n for (const message of messages) {\n numTokens += calculateMessageTokens(message, encoder, constants)\n }\n // every reply is primed with <|start|>assistant<|message|>\n numTokens += 3\n return numTokens\n}\n\n/**\n * Get the corresponding encoder module based on encoding type\n */\nconst getEncodeChatFunction = async (encoding: string): Promise<Encoder> => {\n if (encodingCache.has(encoding)) {\n const cached = encodingCache.get(encoding)\n if (cached) {\n return cached\n }\n }\n\n const supportedEncoding = encoding as SupportedEncoding\n if (!(supportedEncoding in ENCODING_MAP)) {\n const fallbackModule = (await ENCODING_MAP.o200k_base()) as Encoder\n encodingCache.set(encoding, fallbackModule)\n return fallbackModule\n }\n\n const encodingModule = (await ENCODING_MAP[supportedEncoding]()) as Encoder\n encodingCache.set(encoding, encodingModule)\n return encodingModule\n}\n\n/**\n * Get tokenizer type from model information\n */\nexport const getTokenizerFromModel = (model: Model): string => {\n return model.capabilities.tokenizer || \"o200k_base\"\n}\n\n/**\n * Get model-specific constants for token calculation\n */\nconst getModelConstants = (model: Model) => {\n return model.id === \"gpt-3.5-turbo\" || model.id === \"gpt-4\" ?\n {\n funcInit: 10,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n isGpt: true,\n }\n : {\n funcInit: 7,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n isGpt: model.id.startsWith(\"gpt-\"),\n }\n}\n\n/**\n * Calculate tokens for a single parameter\n */\nconst calculateParameterTokens = (\n key: string,\n prop: unknown,\n context: {\n encoder: Encoder\n constants: ReturnType<typeof getModelConstants>\n },\n): number => {\n const { encoder, constants } = context\n let tokens = constants.propKey\n\n // Early return if prop is not an object\n if (typeof prop !== \"object\" || prop === null) {\n return tokens\n }\n\n // Type assertion for parameter properties\n const param = prop as {\n type?: string\n description?: string\n enum?: Array<unknown>\n [key: string]: unknown\n }\n\n const paramName = key\n const paramType = param.type || \"string\"\n let paramDesc = param.description || \"\"\n\n // Handle enum values\n if (param.enum && Array.isArray(param.enum)) {\n tokens += constants.enumInit\n for (const item of param.enum) {\n tokens += constants.enumItem\n tokens += encoder.encode(String(item)).length\n }\n }\n\n // Clean up description\n if (paramDesc.endsWith(\".\")) {\n paramDesc = paramDesc.slice(0, -1)\n }\n\n // Encode the main parameter line\n const line = `${paramName}:${paramType}:${paramDesc}`\n tokens += encoder.encode(line).length\n\n if (param.type === \"array\" && param[\"items\"]) {\n tokens += calculateParametersTokens(param[\"items\"], encoder, constants)\n }\n\n // Handle additional properties (excluding standard ones)\n const excludedKeys = new Set([\"type\", \"description\", \"enum\", \"items\"])\n for (const propertyName of Object.keys(param)) {\n if (!excludedKeys.has(propertyName)) {\n const propertyValue = param[propertyName]\n const propertyText =\n typeof propertyValue === \"string\" ? propertyValue : (\n JSON.stringify(propertyValue)\n )\n tokens += encoder.encode(`${propertyName}:${propertyText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for properties object\n */\nconst calculatePropertiesTokens = (\n properties: Record<string, unknown>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = 0\n if (Object.keys(properties).length > 0) {\n tokens += constants.propInit\n for (const propKey of Object.keys(properties)) {\n tokens += calculateParameterTokens(propKey, properties[propKey], {\n encoder,\n constants,\n })\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens for function parameters\n */\nconst calculateParametersTokens = (\n parameters: unknown,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (!parameters || typeof parameters !== \"object\") {\n return 0\n }\n\n const params = parameters as Record<string, unknown>\n let tokens = 0\n\n const excludedKeys = new Set([\"$schema\", \"additionalProperties\"])\n for (const [key, value] of Object.entries(params)) {\n if (excludedKeys.has(key)) {\n continue\n }\n if (key === \"properties\") {\n tokens += calculatePropertiesTokens(\n value as Record<string, unknown>,\n encoder,\n constants,\n )\n } else {\n const paramText =\n typeof value === \"string\" ? value : JSON.stringify(value)\n tokens += encoder.encode(`${key}:${paramText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for a single tool\n */\nconst calculateToolTokens = (\n tool: Tool,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = constants.funcInit\n const func = tool.function\n const fName = func.name\n let fDesc = func.description || \"\"\n if (fDesc.endsWith(\".\")) {\n fDesc = fDesc.slice(0, -1)\n }\n const line = fName + \":\" + fDesc\n tokens += encoder.encode(line).length\n if (\n typeof func.parameters === \"object\" // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n && func.parameters !== null\n ) {\n tokens += calculateParametersTokens(func.parameters, encoder, constants)\n }\n return tokens\n}\n\n/**\n * Calculate token count for tools based on model\n */\nexport const numTokensForTools = (\n tools: Array<Tool>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let funcTokenCount = 0\n if (constants.isGpt) {\n for (const tool of tools) {\n funcTokenCount += calculateToolTokens(tool, encoder, constants)\n }\n funcTokenCount += constants.funcEnd\n } else {\n for (const tool of tools) {\n funcTokenCount += encoder.encode(JSON.stringify(tool)).length\n }\n }\n return funcTokenCount\n}\n\n/**\n * Calculate the token count of messages, supporting multiple GPT encoders\n */\nexport const getTokenCount = async (\n payload: ChatCompletionsPayload,\n model: Model,\n): Promise<{ input: number; output: number }> => {\n // Get tokenizer string\n const tokenizer = getTokenizerFromModel(model)\n\n // Get corresponding encoder module\n const encoder = await getEncodeChatFunction(tokenizer)\n\n const simplifiedMessages = payload.messages\n const inputMessages = simplifiedMessages.filter(\n (msg) => msg.role !== \"assistant\",\n )\n const outputMessages = simplifiedMessages.filter(\n (msg) => msg.role === \"assistant\",\n )\n\n const constants = getModelConstants(model)\n // gpt count token https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n let inputTokens = calculateTokens(inputMessages, encoder, constants)\n if (payload.tools && payload.tools.length > 0) {\n inputTokens += numTokensForTools(payload.tools, encoder, constants)\n }\n const outputTokens = calculateTokens(outputMessages, encoder, constants)\n\n return {\n input: inputTokens,\n output: outputTokens,\n }\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport type { AccountContext } from \"~/lib/types/account\"\n\nimport { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { accountFromState } from \"~/lib/state\"\n\nexport interface ResponsesPayload {\n model: string\n instructions?: string | null\n input?: string | Array<ResponseInputItem>\n tools?: Array<Tool> | null\n tool_choice?: ToolChoiceOptions | ToolChoiceFunction\n temperature?: number | null\n top_p?: number | null\n max_output_tokens?: number | null\n metadata?: Metadata | null\n stream?: boolean | null\n safety_identifier?: string | null\n prompt_cache_key?: string | null\n parallel_tool_calls?: boolean | null\n store?: boolean | null\n reasoning?: Reasoning | null\n include?: Array<ResponseIncludable>\n service_tier?: string | null // NOTE: Unsupported by GitHub Copilot\n [key: string]: unknown\n}\n\nexport type ToolChoiceOptions = \"none\" | \"auto\" | \"required\"\n\nexport interface ToolChoiceFunction {\n name: string\n type: \"function\"\n}\n\nexport type Tool = FunctionTool | Record<string, unknown>\n\nexport interface FunctionTool {\n name: string\n parameters: { [key: string]: unknown } | null\n strict: boolean | null\n type: \"function\"\n description?: string | null\n}\n\nexport type ResponseIncludable =\n | \"file_search_call.results\"\n | \"message.input_image.image_url\"\n | \"computer_call_output.output.image_url\"\n | \"reasoning.encrypted_content\"\n | \"code_interpreter_call.outputs\"\n\nexport interface Reasoning {\n effort?: \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | null\n summary?: \"auto\" | \"concise\" | \"detailed\" | null\n}\n\nexport interface ResponseInputMessage {\n type?: \"message\"\n role: \"user\" | \"assistant\" | \"system\" | \"developer\"\n content?: string | Array<ResponseInputContent>\n status?: string\n}\n\nexport interface ResponseFunctionToolCallItem {\n type: \"function_call\"\n call_id: string\n name: string\n arguments: string\n status?: \"in_progress\" | \"completed\" | \"incomplete\"\n}\n\nexport interface ResponseFunctionCallOutputItem {\n type: \"function_call_output\"\n call_id: string\n output: string | Array<ResponseInputContent>\n status?: \"in_progress\" | \"completed\" | \"incomplete\"\n}\n\nexport interface ResponseInputReasoning {\n id?: string\n type: \"reasoning\"\n summary: Array<{\n type: \"summary_text\"\n text: string\n }>\n encrypted_content: string\n}\n\nexport type ResponseInputItem =\n | ResponseInputMessage\n | ResponseFunctionToolCallItem\n | ResponseFunctionCallOutputItem\n | ResponseInputReasoning\n | Record<string, unknown>\n\nexport type ResponseInputContent =\n | ResponseInputText\n | ResponseInputImage\n | Record<string, unknown>\n\nexport interface ResponseInputText {\n type: \"input_text\" | \"output_text\"\n text: string\n}\n\nexport interface ResponseInputImage {\n type: \"input_image\"\n image_url?: string | null\n file_id?: string | null\n detail: \"low\" | \"high\" | \"auto\"\n}\n\nexport interface ResponsesResult {\n id: string\n object: \"response\"\n created_at: number\n model: string\n output: Array<ResponseOutputItem>\n output_text: string\n status: string\n usage?: ResponseUsage | null\n error: ResponseError | null\n incomplete_details: IncompleteDetails | null\n instructions: string | null\n metadata: Metadata | null\n parallel_tool_calls: boolean\n temperature: number | null\n tool_choice: unknown\n tools: Array<Tool>\n top_p: number | null\n}\n\nexport type Metadata = { [key: string]: string }\n\nexport interface IncompleteDetails {\n reason?: \"max_output_tokens\" | \"content_filter\"\n}\n\nexport interface ResponseError {\n message: string\n}\n\nexport type ResponseOutputItem =\n | ResponseOutputMessage\n | ResponseOutputReasoning\n | ResponseOutputFunctionCall\n\nexport interface ResponseOutputMessage {\n id: string\n type: \"message\"\n role: \"assistant\"\n status: \"completed\" | \"in_progress\" | \"incomplete\"\n content?: Array<ResponseOutputContentBlock>\n}\n\nexport interface ResponseOutputReasoning {\n id: string\n type: \"reasoning\"\n summary?: Array<ResponseReasoningBlock>\n encrypted_content?: string\n status?: \"completed\" | \"in_progress\" | \"incomplete\"\n}\n\nexport interface ResponseReasoningBlock {\n type: string\n text?: string\n}\n\nexport interface ResponseOutputFunctionCall {\n id?: string\n type: \"function_call\"\n call_id: string\n name: string\n arguments: string\n status?: \"in_progress\" | \"completed\" | \"incomplete\"\n}\n\nexport type ResponseOutputContentBlock =\n | ResponseOutputText\n | ResponseOutputRefusal\n | Record<string, unknown>\n\nexport interface ResponseOutputText {\n type: \"output_text\"\n text: string\n annotations: Array<unknown>\n}\n\nexport interface ResponseOutputRefusal {\n type: \"refusal\"\n refusal: string\n}\n\nexport interface ResponseUsage {\n input_tokens: number\n output_tokens?: number\n total_tokens: number\n input_tokens_details?: {\n cached_tokens: number\n }\n output_tokens_details?: {\n reasoning_tokens: number\n }\n}\n\nexport type ResponseStreamEvent =\n | ResponseCompletedEvent\n | ResponseIncompleteEvent\n | ResponseCreatedEvent\n | ResponseErrorEvent\n | ResponseFunctionCallArgumentsDeltaEvent\n | ResponseFunctionCallArgumentsDoneEvent\n | ResponseFailedEvent\n | ResponseOutputItemAddedEvent\n | ResponseOutputItemDoneEvent\n | ResponseReasoningSummaryTextDeltaEvent\n | ResponseReasoningSummaryTextDoneEvent\n | ResponseTextDeltaEvent\n | ResponseTextDoneEvent\n\nexport interface ResponseCompletedEvent {\n response: ResponsesResult\n sequence_number: number\n type: \"response.completed\"\n}\n\nexport interface ResponseIncompleteEvent {\n response: ResponsesResult\n sequence_number: number\n type: \"response.incomplete\"\n}\n\nexport interface ResponseCreatedEvent {\n response: ResponsesResult\n sequence_number: number\n type: \"response.created\"\n}\n\nexport interface ResponseErrorEvent {\n code: string | null\n message: string\n param: string | null\n sequence_number: number\n type: \"error\"\n}\n\nexport interface ResponseFunctionCallArgumentsDeltaEvent {\n delta: string\n item_id: string\n output_index: number\n sequence_number: number\n type: \"response.function_call_arguments.delta\"\n}\n\nexport interface ResponseFunctionCallArgumentsDoneEvent {\n arguments: string\n item_id: string\n name: string\n output_index: number\n sequence_number: number\n type: \"response.function_call_arguments.done\"\n}\n\nexport interface ResponseFailedEvent {\n response: ResponsesResult\n sequence_number: number\n type: \"response.failed\"\n}\n\nexport interface ResponseOutputItemAddedEvent {\n item: ResponseOutputItem\n output_index: number\n sequence_number: number\n type: \"response.output_item.added\"\n}\n\nexport interface ResponseOutputItemDoneEvent {\n item: ResponseOutputItem\n output_index: number\n sequence_number: number\n type: \"response.output_item.done\"\n}\n\nexport interface ResponseReasoningSummaryTextDeltaEvent {\n delta: string\n item_id: string\n output_index: number\n sequence_number: number\n summary_index: number\n type: \"response.reasoning_summary_text.delta\"\n}\n\nexport interface ResponseReasoningSummaryTextDoneEvent {\n item_id: string\n output_index: number\n sequence_number: number\n summary_index: number\n text: string\n type: \"response.reasoning_summary_text.done\"\n}\n\nexport interface ResponseTextDeltaEvent {\n content_index: number\n delta: string\n item_id: string\n output_index: number\n sequence_number: number\n type: \"response.output_text.delta\"\n}\n\nexport interface ResponseTextDoneEvent {\n content_index: number\n item_id: string\n output_index: number\n sequence_number: number\n text: string\n type: \"response.output_text.done\"\n}\n\nexport type ResponsesStream = ReturnType<typeof events>\nexport type CreateResponsesReturn = ResponsesResult | ResponsesStream\n\ninterface ResponsesRequestOptions {\n vision: boolean\n initiator: \"agent\" | \"user\"\n upstreamRequestId?: string\n}\n\nexport const createResponses = async (\n payload: ResponsesPayload,\n { vision, initiator, upstreamRequestId }: ResponsesRequestOptions,\n account?: AccountContext,\n): Promise<CreateResponsesReturn> => {\n const ctx = account ?? accountFromState()\n if (!ctx.copilotToken) throw new Error(\"Copilot token not found\")\n\n const headers: Record<string, string> = {\n ...copilotHeaders(ctx, vision, upstreamRequestId),\n \"X-Initiator\": initiator,\n }\n\n // service_tier is not supported by github copilot\n payload.service_tier = null\n\n const response = await fetch(`${copilotBaseUrl(ctx)}/responses`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n consola.error(\"Failed to create responses\", response)\n throw new HTTPError(\"Failed to create responses\", response)\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ResponsesResult\n}\n","import consola from \"consola\"\n\nimport {\n getExtraPromptForModel,\n getReasoningEffortForModel,\n} from \"~/lib/config\"\nimport {\n type ResponsesPayload,\n type ResponseInputContent,\n type ResponseInputImage,\n type ResponseInputItem,\n type ResponseInputMessage,\n type ResponseInputReasoning,\n type ResponseInputText,\n type ResponsesResult,\n type ResponseOutputContentBlock,\n type ResponseOutputFunctionCall,\n type ResponseOutputItem,\n type ResponseOutputReasoning,\n type ResponseReasoningBlock,\n type ResponseOutputRefusal,\n type ResponseOutputText,\n type ResponseFunctionToolCallItem,\n type ResponseFunctionCallOutputItem,\n type Tool,\n type ToolChoiceFunction,\n type ToolChoiceOptions,\n} from \"~/services/copilot/create-responses\"\n\nimport {\n type AnthropicAssistantContentBlock,\n type AnthropicAssistantMessage,\n type AnthropicResponse,\n type AnthropicImageBlock,\n type AnthropicMessage,\n type AnthropicMessagesPayload,\n type AnthropicTextBlock,\n type AnthropicThinkingBlock,\n type AnthropicTool,\n type AnthropicToolResultBlock,\n type AnthropicToolUseBlock,\n type AnthropicUserContentBlock,\n type AnthropicUserMessage,\n} from \"./anthropic-types\"\n\nconst MESSAGE_TYPE = \"message\"\n\nexport const THINKING_TEXT = \"Thinking...\"\n\nexport const translateAnthropicMessagesToResponsesPayload = (\n payload: AnthropicMessagesPayload,\n modelOverride?: string,\n): ResponsesPayload => {\n const model = modelOverride ?? payload.model\n const input: Array<ResponseInputItem> = []\n\n for (const message of payload.messages) {\n input.push(...translateMessage(message))\n }\n\n const translatedTools = convertAnthropicTools(payload.tools)\n const toolChoice = convertAnthropicToolChoice(payload.tool_choice)\n\n const { safetyIdentifier, promptCacheKey } = parseUserId(\n payload.metadata?.user_id,\n )\n\n const responsesPayload: ResponsesPayload = {\n model,\n input,\n instructions: translateSystemPrompt(payload.system, model),\n temperature: 1, // reasoning high temperature fixed to 1\n top_p: payload.top_p ?? null,\n max_output_tokens: Math.max(payload.max_tokens, 12800),\n tools: translatedTools,\n tool_choice: toolChoice,\n metadata: payload.metadata ? { ...payload.metadata } : null,\n safety_identifier: safetyIdentifier,\n prompt_cache_key: promptCacheKey,\n stream: payload.stream ?? null,\n store: false,\n parallel_tool_calls: true,\n reasoning: {\n effort: getReasoningEffortForModel(model),\n summary: \"auto\",\n },\n include: [\"reasoning.encrypted_content\"],\n }\n\n return responsesPayload\n}\n\nconst translateMessage = (\n message: AnthropicMessage,\n): Array<ResponseInputItem> => {\n if (message.role === \"user\") {\n return translateUserMessage(message)\n }\n\n return translateAssistantMessage(message)\n}\n\nconst translateUserMessage = (\n message: AnthropicUserMessage,\n): Array<ResponseInputItem> => {\n if (typeof message.content === \"string\") {\n return [createMessage(\"user\", message.content)]\n }\n\n if (!Array.isArray(message.content)) {\n return []\n }\n\n const items: Array<ResponseInputItem> = []\n const pendingContent: Array<ResponseInputContent> = []\n\n for (const block of message.content) {\n if (block.type === \"tool_result\") {\n flushPendingContent(\"user\", pendingContent, items)\n items.push(createFunctionCallOutput(block))\n continue\n }\n\n const converted = translateUserContentBlock(block)\n if (converted) {\n pendingContent.push(converted)\n }\n }\n\n flushPendingContent(\"user\", pendingContent, items)\n\n return items\n}\n\nconst translateAssistantMessage = (\n message: AnthropicAssistantMessage,\n): Array<ResponseInputItem> => {\n if (typeof message.content === \"string\") {\n return [createMessage(\"assistant\", message.content)]\n }\n\n if (!Array.isArray(message.content)) {\n return []\n }\n\n const items: Array<ResponseInputItem> = []\n const pendingContent: Array<ResponseInputContent> = []\n\n for (const block of message.content) {\n if (block.type === \"tool_use\") {\n flushPendingContent(\"assistant\", pendingContent, items)\n items.push(createFunctionToolCall(block))\n continue\n }\n\n if (\n block.type === \"thinking\"\n && block.signature\n && block.signature.includes(\"@\")\n ) {\n flushPendingContent(\"assistant\", pendingContent, items)\n items.push(createReasoningContent(block))\n continue\n }\n\n const converted = translateAssistantContentBlock(block)\n if (converted) {\n pendingContent.push(converted)\n }\n }\n\n flushPendingContent(\"assistant\", pendingContent, items)\n\n return items\n}\n\nconst translateUserContentBlock = (\n block: AnthropicUserContentBlock,\n): ResponseInputContent | undefined => {\n switch (block.type) {\n case \"text\": {\n return createTextContent(block.text)\n }\n case \"image\": {\n return createImageContent(block)\n }\n default: {\n return undefined\n }\n }\n}\n\nconst translateAssistantContentBlock = (\n block: AnthropicAssistantContentBlock,\n): ResponseInputContent | undefined => {\n switch (block.type) {\n case \"text\": {\n return createOutPutTextContent(block.text)\n }\n default: {\n return undefined\n }\n }\n}\n\nconst flushPendingContent = (\n role: ResponseInputMessage[\"role\"],\n pendingContent: Array<ResponseInputContent>,\n target: Array<ResponseInputItem>,\n) => {\n if (pendingContent.length === 0) {\n return\n }\n\n const messageContent = [...pendingContent]\n\n target.push(createMessage(role, messageContent))\n pendingContent.length = 0\n}\n\nconst createMessage = (\n role: ResponseInputMessage[\"role\"],\n content: string | Array<ResponseInputContent>,\n): ResponseInputMessage => ({\n type: MESSAGE_TYPE,\n role,\n content,\n})\n\nconst createTextContent = (text: string): ResponseInputText => ({\n type: \"input_text\",\n text,\n})\n\nconst createOutPutTextContent = (text: string): ResponseInputText => ({\n type: \"output_text\",\n text,\n})\n\nconst createImageContent = (\n block: AnthropicImageBlock,\n): ResponseInputImage => ({\n type: \"input_image\",\n image_url: `data:${block.source.media_type};base64,${block.source.data}`,\n detail: \"auto\",\n})\n\nconst createReasoningContent = (\n block: AnthropicThinkingBlock,\n): ResponseInputReasoning => {\n // align with vscode-copilot-chat extractThinkingData, should add id, otherwise it will cause miss cache occasionally —— the usage input cached tokens to be 0\n // https://github.com/microsoft/vscode-copilot-chat/blob/main/src/platform/endpoint/node/responsesApi.ts#L162\n // when use in codex cli, reasoning id is empty, so it will cause miss cache occasionally\n const array = block.signature.split(\"@\")\n const signature = array[0]\n const id = array[1]\n const thinking = block.thinking === THINKING_TEXT ? \"\" : block.thinking\n return {\n id,\n type: \"reasoning\",\n summary: thinking ? [{ type: \"summary_text\", text: thinking }] : [],\n encrypted_content: signature,\n }\n}\n\nconst createFunctionToolCall = (\n block: AnthropicToolUseBlock,\n): ResponseFunctionToolCallItem => ({\n type: \"function_call\",\n call_id: block.id,\n name: block.name,\n arguments: JSON.stringify(block.input),\n status: \"completed\",\n})\n\nconst createFunctionCallOutput = (\n block: AnthropicToolResultBlock,\n): ResponseFunctionCallOutputItem => ({\n type: \"function_call_output\",\n call_id: block.tool_use_id,\n output: convertToolResultContent(block.content),\n status: block.is_error ? \"incomplete\" : \"completed\",\n})\n\nconst translateSystemPrompt = (\n system: string | Array<AnthropicTextBlock> | undefined,\n model: string,\n): string | null => {\n if (!system) {\n return null\n }\n\n const extraPrompt = getExtraPromptForModel(model)\n\n if (typeof system === \"string\") {\n return system + extraPrompt\n }\n\n const text = system\n .map((block, index) => {\n if (index === 0) {\n return block.text + extraPrompt\n }\n return block.text\n })\n .join(\" \")\n return text.length > 0 ? text : null\n}\n\nconst convertAnthropicTools = (\n tools: Array<AnthropicTool> | undefined,\n): Array<Tool> | null => {\n if (!tools || tools.length === 0) {\n return null\n }\n\n return tools.map((tool) => ({\n type: \"function\",\n name: tool.name,\n parameters: tool.input_schema,\n strict: false,\n ...(tool.description ? { description: tool.description } : {}),\n }))\n}\n\nconst convertAnthropicToolChoice = (\n choice: AnthropicMessagesPayload[\"tool_choice\"],\n): ToolChoiceOptions | ToolChoiceFunction => {\n if (!choice) {\n return \"auto\"\n }\n\n switch (choice.type) {\n case \"auto\": {\n return \"auto\"\n }\n case \"any\": {\n return \"required\"\n }\n case \"tool\": {\n return choice.name ? { type: \"function\", name: choice.name } : \"auto\"\n }\n case \"none\": {\n return \"none\"\n }\n default: {\n return \"auto\"\n }\n }\n}\n\nexport const translateResponsesResultToAnthropic = (\n response: ResponsesResult,\n): AnthropicResponse => {\n const contentBlocks = mapOutputToAnthropicContent(response.output)\n const usage = mapResponsesUsage(response)\n let anthropicContent = fallbackContentBlocks(response.output_text)\n if (contentBlocks.length > 0) {\n anthropicContent = contentBlocks\n }\n\n const stopReason = mapResponsesStopReason(response)\n\n return {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n content: anthropicContent,\n model: response.model,\n stop_reason: stopReason,\n stop_sequence: null,\n usage,\n }\n}\n\nconst mapOutputToAnthropicContent = (\n output: Array<ResponseOutputItem>,\n): Array<AnthropicAssistantContentBlock> => {\n const contentBlocks: Array<AnthropicAssistantContentBlock> = []\n\n for (const item of output) {\n switch (item.type) {\n case \"reasoning\": {\n const thinkingText = extractReasoningText(item)\n if (thinkingText.length > 0) {\n contentBlocks.push({\n type: \"thinking\",\n thinking: thinkingText,\n signature: (item.encrypted_content ?? \"\") + \"@\" + item.id,\n })\n }\n break\n }\n case \"function_call\": {\n const toolUseBlock = createToolUseContentBlock(item)\n if (toolUseBlock) {\n contentBlocks.push(toolUseBlock)\n }\n break\n }\n case \"message\": {\n const combinedText = combineMessageTextContent(item.content)\n if (combinedText.length > 0) {\n contentBlocks.push({ type: \"text\", text: combinedText })\n }\n break\n }\n default: {\n // Future compatibility for unrecognized output item types.\n const combinedText = combineMessageTextContent(\n (item as { content?: Array<ResponseOutputContentBlock> }).content,\n )\n if (combinedText.length > 0) {\n contentBlocks.push({ type: \"text\", text: combinedText })\n }\n }\n }\n }\n\n return contentBlocks\n}\n\nconst combineMessageTextContent = (\n content: Array<ResponseOutputContentBlock> | undefined,\n): string => {\n if (!Array.isArray(content)) {\n return \"\"\n }\n\n let aggregated = \"\"\n\n for (const block of content) {\n if (isResponseOutputText(block)) {\n aggregated += block.text\n continue\n }\n\n if (isResponseOutputRefusal(block)) {\n aggregated += block.refusal\n continue\n }\n\n if (typeof (block as { text?: unknown }).text === \"string\") {\n aggregated += (block as { text: string }).text\n continue\n }\n\n if (typeof (block as { reasoning?: unknown }).reasoning === \"string\") {\n aggregated += (block as { reasoning: string }).reasoning\n continue\n }\n }\n\n return aggregated\n}\n\nconst extractReasoningText = (item: ResponseOutputReasoning): string => {\n const segments: Array<string> = []\n\n const collectFromBlocks = (blocks?: Array<ResponseReasoningBlock>) => {\n if (!Array.isArray(blocks)) {\n return\n }\n\n for (const block of blocks) {\n if (typeof block.text === \"string\") {\n segments.push(block.text)\n continue\n }\n }\n }\n\n // Compatible with opencode, it will filter out blocks where the thinking text is empty, so we add a default thinking text here\n if (!item.summary || item.summary.length === 0) {\n return THINKING_TEXT\n }\n\n collectFromBlocks(item.summary)\n\n return segments.join(\"\").trim()\n}\n\nconst createToolUseContentBlock = (\n call: ResponseOutputFunctionCall,\n): AnthropicToolUseBlock | null => {\n const toolId = call.call_id\n if (!call.name || !toolId) {\n return null\n }\n\n const input = parseFunctionCallArguments(call.arguments)\n\n return {\n type: \"tool_use\",\n id: toolId,\n name: call.name,\n input,\n }\n}\n\nconst parseFunctionCallArguments = (\n rawArguments: string,\n): Record<string, unknown> => {\n if (typeof rawArguments !== \"string\" || rawArguments.trim().length === 0) {\n return {}\n }\n\n try {\n const parsed: unknown = JSON.parse(rawArguments)\n\n if (Array.isArray(parsed)) {\n return { arguments: parsed }\n }\n\n if (parsed && typeof parsed === \"object\") {\n return parsed as Record<string, unknown>\n }\n } catch (error) {\n consola.warn(\"Failed to parse function call arguments\", {\n error,\n rawArguments,\n })\n }\n\n return { raw_arguments: rawArguments }\n}\n\nconst fallbackContentBlocks = (\n outputText: string,\n): Array<AnthropicAssistantContentBlock> => {\n if (!outputText) {\n return []\n }\n\n return [\n {\n type: \"text\",\n text: outputText,\n },\n ]\n}\n\nconst mapResponsesStopReason = (\n response: ResponsesResult,\n): AnthropicResponse[\"stop_reason\"] => {\n const { status, incomplete_details: incompleteDetails } = response\n\n if (status === \"completed\") {\n if (response.output.some((item) => item.type === \"function_call\")) {\n return \"tool_use\"\n }\n return \"end_turn\"\n }\n\n if (status === \"incomplete\") {\n if (incompleteDetails?.reason === \"max_output_tokens\") {\n return \"max_tokens\"\n }\n if (incompleteDetails?.reason === \"content_filter\") {\n return \"end_turn\"\n }\n }\n\n return null\n}\n\nconst mapResponsesUsage = (\n response: ResponsesResult,\n): AnthropicResponse[\"usage\"] => {\n const inputTokens = response.usage?.input_tokens ?? 0\n const outputTokens = response.usage?.output_tokens ?? 0\n const inputCachedTokens = response.usage?.input_tokens_details?.cached_tokens\n\n return {\n input_tokens: inputTokens - (inputCachedTokens ?? 0),\n output_tokens: outputTokens,\n ...(response.usage?.input_tokens_details?.cached_tokens !== undefined && {\n cache_read_input_tokens:\n response.usage.input_tokens_details.cached_tokens,\n }),\n }\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null\n\nconst isResponseOutputText = (\n block: ResponseOutputContentBlock,\n): block is ResponseOutputText =>\n isRecord(block)\n && \"type\" in block\n && (block as { type?: unknown }).type === \"output_text\"\n\nconst isResponseOutputRefusal = (\n block: ResponseOutputContentBlock,\n): block is ResponseOutputRefusal =>\n isRecord(block)\n && \"type\" in block\n && (block as { type?: unknown }).type === \"refusal\"\n\nexport const parseUserId = (\n userId: string | undefined,\n): { safetyIdentifier: string | null; promptCacheKey: string | null } => {\n if (!userId || typeof userId !== \"string\") {\n return { safetyIdentifier: null, promptCacheKey: null }\n }\n\n // Parse safety_identifier: content between \"user_\" and \"_account\"\n const userMatch = userId.match(/user_([^_]+)_account/)\n const safetyIdentifier = userMatch ? userMatch[1] : null\n\n // Parse prompt_cache_key: content after \"_session_\"\n const sessionMatch = userId.match(/_session_(.+)$/)\n const promptCacheKey = sessionMatch ? sessionMatch[1] : null\n\n return { safetyIdentifier, promptCacheKey }\n}\n\nconst convertToolResultContent = (\n content: string | Array<AnthropicTextBlock | AnthropicImageBlock>,\n): string | Array<ResponseInputContent> => {\n if (typeof content === \"string\") {\n return content\n }\n\n if (Array.isArray(content)) {\n const result: Array<ResponseInputContent> = []\n for (const block of content) {\n switch (block.type) {\n case \"text\": {\n result.push(createTextContent(block.text))\n break\n }\n case \"image\": {\n result.push(createImageContent(block))\n break\n }\n default: {\n break\n }\n }\n }\n return result\n }\n\n return \"\"\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport type { AccountContext } from \"~/lib/types/account\"\n\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { getReasoningEffortForModel, isForceAgentEnabled } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { accountFromState } from \"~/lib/state\"\n\nfunction isGpt5MiniFamily(modelId: string): boolean {\n return modelId === \"gpt-5-mini\" || modelId.startsWith(\"gpt-5-mini-\")\n}\n\nfunction applyDefaultReasoningEffort(\n payload: ChatCompletionsPayload,\n): ChatCompletionsPayload {\n if (!isGpt5MiniFamily(payload.model)) return payload\n\n // Only inject when omitted/null; allow callers to explicitly override.\n if (\n payload.reasoning_effort !== null\n && payload.reasoning_effort !== undefined\n )\n return payload\n\n return {\n ...payload,\n reasoning_effort: getReasoningEffortForModel(\"gpt-5-mini\"),\n }\n}\n\nexport const getChatInitiator = (\n messages: Array<Message>,\n): \"agent\" | \"user\" => {\n if (isForceAgentEnabled()) {\n const hasAgent = messages.some((msg) =>\n [\"assistant\", \"tool\"].includes(msg.role),\n )\n return hasAgent ? \"agent\" : \"user\"\n }\n\n const lastMessage = messages.at(-1)\n if (!lastMessage) return \"user\"\n\n return [\"assistant\", \"tool\"].includes(lastMessage.role) ? \"agent\" : \"user\"\n}\n\nexport const createChatCompletions = async (\n payload: ChatCompletionsPayload,\n account?: AccountContext,\n options?: { upstreamRequestId?: string },\n) => {\n const ctx = account ?? accountFromState()\n if (!ctx.copilotToken) throw new Error(\"Copilot token not found\")\n\n const enableVision = payload.messages.some(\n (x) =>\n typeof x.content !== \"string\"\n && x.content?.some((x) => x.type === \"image_url\"),\n )\n\n const initiator = getChatInitiator(payload.messages)\n\n // Build headers and add X-Initiator\n const headers: Record<string, string> = {\n ...copilotHeaders(ctx, enableVision, options?.upstreamRequestId),\n \"X-Initiator\": initiator,\n }\n\n const upstreamPayload = applyDefaultReasoningEffort(payload)\n\n const response = await fetch(`${copilotBaseUrl(ctx)}/chat/completions`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(upstreamPayload),\n })\n\n if (!response.ok) {\n consola.error(\"Failed to create chat completions\", response)\n throw new HTTPError(\"Failed to create chat completions\", response)\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n}\n\n// Streaming types\n\nexport interface ChatCompletionChunk {\n id: string\n object: \"chat.completion.chunk\"\n created: number\n model: string\n choices: Array<Choice>\n system_fingerprint?: string\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n prompt_tokens_details?: {\n cached_tokens: number\n }\n completion_tokens_details?: {\n accepted_prediction_tokens: number\n rejected_prediction_tokens: number\n }\n }\n}\n\nexport interface Delta {\n content?: string | null\n role?: \"user\" | \"assistant\" | \"system\" | \"tool\"\n tool_calls?: Array<{\n index: number\n id?: string\n type?: \"function\"\n function?: {\n name?: string\n arguments?: string\n }\n }>\n reasoning_text?: string | null\n reasoning_opaque?: string | null\n}\n\nexport interface Choice {\n index: number\n delta: Delta\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null\n logprobs: object | null\n}\n\n// Non-streaming types\n\nexport interface ChatCompletionResponse {\n id: string\n object: \"chat.completion\"\n created: number\n model: string\n choices: Array<ChoiceNonStreaming>\n system_fingerprint?: string\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n prompt_tokens_details?: {\n cached_tokens: number\n }\n }\n}\n\ninterface ResponseMessage {\n role: \"assistant\"\n content: string | null\n reasoning_text?: string | null\n reasoning_opaque?: string | null\n tool_calls?: Array<ToolCall>\n}\n\ninterface ChoiceNonStreaming {\n index: number\n message: ResponseMessage\n logprobs: object | null\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\"\n}\n\n// Payload types\n\nexport interface ChatCompletionsPayload {\n messages: Array<Message>\n model: string\n temperature?: number | null\n top_p?: number | null\n max_tokens?: number | null\n stop?: string | Array<string> | null\n n?: number | null\n stream?: boolean | null\n\n frequency_penalty?: number | null\n presence_penalty?: number | null\n logit_bias?: Record<string, number> | null\n logprobs?: boolean | null\n response_format?: { type: \"json_object\" } | null\n seed?: number | null\n tools?: Array<Tool> | null\n tool_choice?:\n | \"none\"\n | \"auto\"\n | \"required\"\n | { type: \"function\"; function: { name: string } }\n | null\n user?: string | null\n reasoning_effort?:\n | \"none\"\n | \"minimal\"\n | \"low\"\n | \"medium\"\n | \"high\"\n | \"xhigh\"\n | null\n thinking_budget?: number\n}\n\nexport interface Tool {\n type: \"function\"\n function: {\n name: string\n description?: string\n parameters: Record<string, unknown>\n }\n}\n\nexport interface Message {\n role: \"user\" | \"assistant\" | \"system\" | \"tool\" | \"developer\"\n content: string | Array<ContentPart> | null\n\n name?: string\n tool_calls?: Array<ToolCall>\n tool_call_id?: string\n reasoning_text?: string | null\n reasoning_opaque?: string | null\n}\n\nexport interface ToolCall {\n id: string\n type: \"function\"\n function: {\n name: string\n arguments: string\n }\n}\n\nexport type ContentPart = TextPart | ImagePart\n\nexport interface TextPart {\n type: \"text\"\n text: string\n}\n\nexport interface ImagePart {\n type: \"image_url\"\n image_url: {\n url: string\n detail?: \"low\" | \"high\" | \"auto\"\n }\n}\n","import type { Context } from \"hono\"\n\nimport { streamSSE, type SSEMessage } from \"hono/streaming\"\nimport { randomUUID } from \"node:crypto\"\n\nimport { accountsManager } from \"~/lib/accounts-manager\"\nimport { awaitApproval } from \"~/lib/approval\"\nimport { getAliasTargetSet } from \"~/lib/config\"\nimport {\n computeDiff,\n extractErrorDetails,\n toAccountContext,\n} from \"~/lib/handler-utils\"\nimport { createHandlerLogger } from \"~/lib/logger\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport {\n getClientIpInfo,\n getRequestHistoryStore,\n normalizeChatCompletionsUsage,\n type NormalizedUsage,\n} from \"~/lib/request-history\"\nimport { state } from \"~/lib/state\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\nimport { isNullish } from \"~/lib/utils\"\nimport { parseUserId } from \"~/routes/messages/responses-translation\"\nimport {\n createChatCompletions,\n getChatInitiator,\n type ChatCompletionChunk,\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n} from \"~/services/copilot/create-chat-completions\"\n\nconst logger = createHandlerLogger(\"chat-completions-handler\")\n\nconst CHAT_COMPLETIONS_ENDPOINT = \"/chat/completions\"\n\nexport async function handleCompletion(c: Context) {\n await checkRateLimit(state)\n\n const store = getRequestHistoryStore()\n const request = buildRequestContext(c)\n\n const payload = await c.req.json<ChatCompletionsPayload>()\n const clientModel = payload.model\n const streamRequested = Boolean(payload.stream)\n\n const initiator = getChatInitiator(payload.messages)\n const userId = payload.user ?? undefined\n const { safetyIdentifier, promptCacheKey } = parseUserId(userId)\n const normalizedSafetyIdentifier = safetyIdentifier ?? undefined\n const normalizedPromptCacheKey = promptCacheKey ?? undefined\n\n request.userId = userId\n request.safetyIdentifier = normalizedSafetyIdentifier\n request.promptCacheKey = normalizedPromptCacheKey\n request.initiator = initiator\n\n const blockedTargets = getAliasTargetSet()\n if (blockedTargets.has(clientModel.toLowerCase())) {\n recordSelectionFailure(store, {\n request,\n clientModel,\n stream: streamRequested,\n reason: \"MODEL_NOT_SUPPORTED\",\n })\n\n return selectionFailureResponse(c, {\n clientModel,\n reason: \"MODEL_NOT_SUPPORTED\",\n })\n }\n\n logger.debug(\"Request payload:\", JSON.stringify(payload).slice(-400))\n\n const selection = await accountsManager.selectAccountForRequest([\n {\n modelId: clientModel,\n endpoint: CHAT_COMPLETIONS_ENDPOINT,\n },\n ])\n\n if (!selection.ok) {\n recordSelectionFailure(store, {\n request,\n clientModel,\n stream: streamRequested,\n reason: selection.reason,\n })\n\n return selectionFailureResponse(c, {\n clientModel,\n reason: selection.reason,\n })\n }\n\n const { account, selectedModel } = selection\n\n const upstreamPayload = { ...payload, model: selectedModel.id }\n\n const premiumRemainingBefore = account.premiumRemaining\n const premiumUnlimitedBefore = account.unlimited\n\n await logTokenCountForRequest({ payload: upstreamPayload, selectedModel })\n\n if (state.manualApprove) await awaitApproval()\n\n const payloadWithMaxTokens = applyDefaultMaxTokens(\n upstreamPayload,\n selectedModel,\n )\n\n const accountCtx = toAccountContext(account)\n const upstreamRequestId = randomUUID()\n request.upstreamRequestId = upstreamRequestId\n\n if (streamRequested) {\n return handleStreamingRequest({\n c,\n store,\n request,\n payload: payloadWithMaxTokens,\n selection,\n accountCtx,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n })\n }\n\n return handleNonStreamingRequest({\n c,\n store,\n request,\n payload: payloadWithMaxTokens,\n selection,\n accountCtx,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n })\n}\n\ntype AccountSelection = Awaited<\n ReturnType<(typeof accountsManager)[\"selectAccountForRequest\"]>\n>\n\ntype AccountSelectionOk = Extract<AccountSelection, { ok: true }>\n\ntype AccountSelectionErr = Extract<AccountSelection, { ok: false }>\n\ntype RequestContext = {\n requestId: string\n startedAtMs: number\n\n method: string\n path: string\n\n clientIp?: string\n clientIpSource?: string\n userAgent?: string\n\n userId?: string\n safetyIdentifier?: string\n promptCacheKey?: string\n initiator?: \"agent\" | \"user\"\n upstreamRequestId?: string\n}\n\ntype Store = ReturnType<typeof getRequestHistoryStore>\n\ntype RequestLogInsert = Parameters<Store[\"insert\"]>[0]\n\ntype ChatCompletionsResult = Awaited<ReturnType<typeof createChatCompletions>>\n\ntype ChatCompletionsStream = Exclude<\n ChatCompletionsResult,\n ChatCompletionResponse\n>\n\ntype StreamSseStream = Parameters<Parameters<typeof streamSSE>[1]>[0]\n\nfunction buildRequestContext(c: Context): RequestContext {\n const requestId = randomUUID()\n const startedAtMs = Date.now()\n\n const method = c.req.raw.method\n const path = new URL(c.req.url, \"http://local\").pathname\n\n const { ip: clientIp, source: clientIpSource } = getClientIpInfo(c)\n const userAgent = c.req.header(\"user-agent\") ?? undefined\n\n return {\n requestId,\n startedAtMs,\n method,\n path,\n clientIp,\n clientIpSource,\n userAgent,\n }\n}\n\nfunction insertRequestLog(\n store: Store,\n request: RequestContext,\n record: Omit<\n RequestLogInsert,\n | \"requestId\"\n | \"startedAtMs\"\n | \"method\"\n | \"path\"\n | \"clientIp\"\n | \"clientIpSource\"\n | \"userAgent\"\n >,\n): void {\n store.insert({\n requestId: request.requestId,\n startedAtMs: request.startedAtMs,\n method: request.method,\n path: request.path,\n clientIp: request.clientIp,\n clientIpSource: request.clientIpSource,\n userAgent: request.userAgent,\n userId: request.userId,\n safetyIdentifier: request.safetyIdentifier,\n promptCacheKey: request.promptCacheKey,\n initiator: request.initiator,\n upstreamRequestId: request.upstreamRequestId,\n ...record,\n })\n}\n\nfunction recordSelectionFailure(\n store: Store,\n params: {\n request: RequestContext\n stream: boolean\n clientModel: string\n reason: AccountSelectionErr[\"reason\"]\n },\n): void {\n const { request, stream, clientModel, reason } = params\n\n const finishedAtMs = Date.now()\n\n insertRequestLog(store, request, {\n finishedAtMs,\n durationMs: finishedAtMs - request.startedAtMs,\n upstreamEndpoint: CHAT_COMPLETIONS_ENDPOINT,\n stream,\n clientModel,\n httpStatus: reason === \"MODEL_NOT_SUPPORTED\" ? 400 : 429,\n selectionFailureReason: reason,\n })\n}\n\nfunction selectionFailureResponse(\n c: Context,\n params: {\n clientModel: string\n reason: AccountSelectionErr[\"reason\"]\n },\n) {\n const { clientModel, reason } = params\n\n if (reason === \"MODEL_NOT_SUPPORTED\") {\n return c.json(\n {\n error: {\n message: `Model \"${clientModel}\" is not available for any configured account.`,\n type: \"invalid_request_error\",\n },\n },\n 400,\n )\n }\n\n return c.json(\n {\n error: {\n message:\n \"All accounts have exhausted their quota. Please wait for quota refresh or add additional accounts.\",\n type: \"rate_limit_error\",\n },\n },\n 429,\n )\n}\n\nasync function logTokenCountForRequest(params: {\n payload: ChatCompletionsPayload\n selectedModel: AccountSelectionOk[\"selectedModel\"]\n}) {\n try {\n const tokenCount = await getTokenCount(params.payload, params.selectedModel)\n logger.info(\"Current token count:\", tokenCount)\n } catch (error) {\n logger.warn(\"Failed to calculate token count:\", error)\n }\n}\n\nfunction applyDefaultMaxTokens(\n payload: ChatCompletionsPayload,\n selectedModel: AccountSelectionOk[\"selectedModel\"],\n): ChatCompletionsPayload {\n if (!isNullish(payload.max_tokens)) {\n return payload\n }\n\n const updated = {\n ...payload,\n max_tokens: selectedModel.capabilities.limits.max_output_tokens,\n }\n\n logger.debug(\"Set max_tokens to:\", JSON.stringify(updated.max_tokens))\n\n return updated\n}\n\nasync function handleStreamingRequest(params: {\n c: Context\n store: Store\n request: RequestContext\n payload: ChatCompletionsPayload\n selection: AccountSelectionOk\n accountCtx: Parameters<typeof createChatCompletions>[1]\n clientModel: string\n premiumRemainingBefore: number | undefined\n premiumUnlimitedBefore: boolean | undefined\n}): Promise<Response> {\n const {\n c,\n store,\n request,\n payload,\n selection,\n accountCtx,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n } = params\n\n let response: ChatCompletionsResult\n\n try {\n response = await createChatCompletions(payload, accountCtx, {\n upstreamRequestId: request.upstreamRequestId,\n })\n } catch (error) {\n return handleUpstreamCreateError({\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n error,\n })\n }\n\n // A defensive guard: stream requested, but upstream returned a non-stream response.\n if (isNonStreaming(response)) {\n return handleNonStreamingUpstreamResponse({\n c,\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n response,\n })\n }\n\n logger.debug(\"Streaming response\")\n\n return streamSSE(c, (stream) =>\n streamChatCompletionsAndLog({\n stream,\n response,\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n }),\n )\n}\n\nasync function handleUpstreamCreateError(params: {\n store: Store\n request: RequestContext\n selection: AccountSelectionOk\n clientModel: string\n premiumRemainingBefore: number | undefined\n premiumUnlimitedBefore: boolean | undefined\n error: unknown\n}): Promise<never> {\n const {\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n error,\n } = params\n\n const { account, reservation, selectedModel, endpoint, costUnits } = selection\n\n const finishedAtMs = Date.now()\n const details = extractErrorDetails(error)\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(account.id, \"Unauthorized (401)\")\n }\n\n await accountsManager.finalizeQuota(account, reservation)\n\n const premiumRemainingAfter = account.premiumRemaining\n const premiumUnlimitedAfter = account.unlimited\n\n insertRequestLog(store, request, {\n finishedAtMs,\n durationMs: finishedAtMs - request.startedAtMs,\n upstreamEndpoint: endpoint,\n stream: true,\n accountId: account.id,\n accountType: account.accountType,\n costUnits,\n clientModel,\n upstreamModel: selectedModel.id,\n premiumRemainingBefore,\n premiumRemainingAfter,\n premiumRemainingDiff: computeDiff(\n premiumRemainingBefore,\n premiumRemainingAfter,\n ),\n premiumUnlimitedBefore,\n premiumUnlimitedAfter,\n httpStatus: details.httpStatus,\n errorName: details.errorName,\n errorStatus: details.errorStatus,\n errorMessage: details.errorMessage,\n })\n\n throw error\n}\n\nasync function handleNonStreamingUpstreamResponse(params: {\n c: Context\n store: Store\n request: RequestContext\n selection: AccountSelectionOk\n clientModel: string\n premiumRemainingBefore: number | undefined\n premiumUnlimitedBefore: boolean | undefined\n response: ChatCompletionResponse\n}): Promise<Response> {\n const {\n c,\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n response,\n } = params\n\n const { account, reservation, selectedModel, endpoint, costUnits } = selection\n\n let httpStatus = 200\n const usage: NormalizedUsage = normalizeChatCompletionsUsage(response.usage)\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n const finishedAtMs = Date.now()\n\n try {\n logger.debug(\"Non-streaming response:\", JSON.stringify(response))\n return c.json(response)\n } catch (error) {\n const details = extractErrorDetails(error)\n httpStatus = details.httpStatus\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n throw error\n } finally {\n await accountsManager.finalizeQuota(account, reservation)\n\n const premiumRemainingAfter = account.premiumRemaining\n const premiumUnlimitedAfter = account.unlimited\n\n insertRequestLog(store, request, {\n finishedAtMs,\n durationMs: finishedAtMs - request.startedAtMs,\n upstreamEndpoint: endpoint,\n stream: false,\n accountId: account.id,\n accountType: account.accountType,\n costUnits,\n clientModel,\n upstreamModel: selectedModel.id,\n ...usage,\n premiumRemainingBefore,\n premiumRemainingAfter,\n premiumRemainingDiff: computeDiff(\n premiumRemainingBefore,\n premiumRemainingAfter,\n ),\n premiumUnlimitedBefore,\n premiumUnlimitedAfter,\n httpStatus,\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nasync function streamChatCompletionsAndLog(params: {\n stream: StreamSseStream\n response: ChatCompletionsStream\n store: Store\n request: RequestContext\n selection: AccountSelectionOk\n clientModel: string\n premiumRemainingBefore: number | undefined\n premiumUnlimitedBefore: boolean | undefined\n}): Promise<void> {\n const {\n stream,\n response,\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n } = params\n\n const { account, reservation, selectedModel, endpoint, costUnits } = selection\n\n let ttfbMs: number | undefined\n let lastUsage: NormalizedUsage = {}\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n try {\n for await (const rawChunk of response) {\n const chunk = rawChunk as SSEMessage\n\n if (ttfbMs === undefined) {\n ttfbMs = Date.now() - request.startedAtMs\n }\n\n const usage = await extractUsageFromChunk(chunk)\n if (usage) {\n lastUsage = usage\n }\n\n logger.debug(\"Streaming chunk:\", JSON.stringify(chunk))\n await stream.writeSSE(chunk)\n }\n } catch (error) {\n const details = extractErrorDetails(error)\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n logger.warn(\"Streaming error:\", error)\n } finally {\n const finishedAtMs = Date.now()\n\n await accountsManager.finalizeQuota(account, reservation)\n\n const premiumRemainingAfter = account.premiumRemaining\n const premiumUnlimitedAfter = account.unlimited\n\n insertRequestLog(store, request, {\n finishedAtMs,\n durationMs: finishedAtMs - request.startedAtMs,\n ttfbMs,\n upstreamEndpoint: endpoint,\n stream: true,\n accountId: account.id,\n accountType: account.accountType,\n costUnits,\n clientModel,\n upstreamModel: selectedModel.id,\n ...lastUsage,\n premiumRemainingBefore,\n premiumRemainingAfter,\n premiumRemainingDiff: computeDiff(\n premiumRemainingBefore,\n premiumRemainingAfter,\n ),\n premiumUnlimitedBefore,\n premiumUnlimitedAfter,\n httpStatus: errorStatus ?? (errorName ? 500 : 200),\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nasync function extractUsageFromChunk(\n chunk: SSEMessage,\n): Promise<NormalizedUsage | undefined> {\n const data = typeof chunk.data === \"string\" ? chunk.data : await chunk.data\n\n if (!data || data === \"[DONE]\") {\n return undefined\n }\n\n try {\n const parsed = JSON.parse(data) as ChatCompletionChunk\n if (!parsed.usage) return undefined\n return normalizeChatCompletionsUsage(parsed.usage)\n } catch {\n return undefined\n }\n}\n\nasync function handleNonStreamingRequest(params: {\n c: Context\n store: Store\n request: RequestContext\n payload: ChatCompletionsPayload\n selection: AccountSelectionOk\n accountCtx: Parameters<typeof createChatCompletions>[1]\n clientModel: string\n premiumRemainingBefore: number | undefined\n premiumUnlimitedBefore: boolean | undefined\n}): Promise<Response> {\n const {\n c,\n store,\n request,\n payload,\n selection,\n accountCtx,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n } = params\n\n const { account, reservation, selectedModel, endpoint, costUnits } = selection\n\n let httpStatus = 200\n let usage: NormalizedUsage = {}\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n let finishedAtMs: number | undefined\n\n try {\n const response = await createChatCompletions(payload, accountCtx, {\n upstreamRequestId: request.upstreamRequestId,\n })\n finishedAtMs = Date.now()\n\n if (!isNonStreaming(response)) {\n logger.debug(\"Unexpected streaming response\")\n // If upstream returns streaming unexpectedly, we just forward it.\n // Note: This will not have \"true completion\" accounting.\n return streamSSE(c, async (stream) => {\n for await (const chunk of response) {\n await stream.writeSSE(chunk as SSEMessage)\n }\n })\n }\n\n usage = normalizeChatCompletionsUsage(response.usage)\n\n logger.debug(\"Non-streaming response:\", JSON.stringify(response))\n return c.json(response)\n } catch (error) {\n finishedAtMs = Date.now()\n\n const details = extractErrorDetails(error)\n httpStatus = details.httpStatus\n\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(account.id, \"Unauthorized (401)\")\n }\n\n throw error\n } finally {\n const finishedAtMsFinal = finishedAtMs ?? Date.now()\n\n await accountsManager.finalizeQuota(account, reservation)\n\n const premiumRemainingAfter = account.premiumRemaining\n const premiumUnlimitedAfter = account.unlimited\n\n insertRequestLog(store, request, {\n finishedAtMs: finishedAtMsFinal,\n durationMs: finishedAtMsFinal - request.startedAtMs,\n upstreamEndpoint: endpoint,\n stream: false,\n accountId: account.id,\n accountType: account.accountType,\n costUnits,\n clientModel,\n upstreamModel: selectedModel.id,\n ...usage,\n premiumRemainingBefore,\n premiumRemainingAfter,\n premiumRemainingDiff: computeDiff(\n premiumRemainingBefore,\n premiumRemainingAfter,\n ),\n premiumUnlimitedBefore,\n premiumUnlimitedAfter,\n httpStatus,\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCompletion } from \"./handler\"\n\nexport const completionRoutes = new Hono()\n\ncompletionRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import type { AccountContext } from \"~/lib/types/account\"\n\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { accountFromState } from \"~/lib/state\"\n\nexport const createEmbeddings = async (\n payload: EmbeddingRequest,\n account?: AccountContext,\n) => {\n const ctx = account ?? accountFromState()\n if (!ctx.copilotToken) throw new Error(\"Copilot token not found\")\n\n const response = await fetch(`${copilotBaseUrl(ctx)}/embeddings`, {\n method: \"POST\",\n headers: copilotHeaders(ctx),\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to create embeddings\", response)\n\n return (await response.json()) as EmbeddingResponse\n}\n\nexport interface EmbeddingRequest {\n input: string | Array<string>\n model: string\n}\n\nexport interface Embedding {\n object: string\n embedding: Array<number>\n index: number\n}\n\nexport interface EmbeddingResponse {\n object: string\n data: Array<Embedding>\n model: string\n usage: {\n prompt_tokens: number\n total_tokens: number\n }\n}\n","import { Hono, type Context } from \"hono\"\nimport { randomUUID } from \"node:crypto\"\n\nimport { accountsManager } from \"~/lib/accounts-manager\"\nimport { getAliasTargetSet } from \"~/lib/config\"\nimport { forwardError } from \"~/lib/error\"\nimport {\n computeDiff,\n extractErrorDetails,\n toAccountContext,\n} from \"~/lib/handler-utils\"\nimport {\n getClientIpInfo,\n getRequestHistoryStore,\n normalizeEmbeddingsUsage,\n type NormalizedUsage,\n} from \"~/lib/request-history\"\nimport {\n createEmbeddings,\n type EmbeddingRequest,\n} from \"~/services/copilot/create-embeddings\"\n\nexport const embeddingRoutes = new Hono()\n\nconst EMBEDDINGS_ENDPOINT = \"/embeddings\"\n\ntype AccountSelection = Awaited<\n ReturnType<(typeof accountsManager)[\"selectAccountForRequest\"]>\n>\n\ntype AccountSelectionOk = Extract<AccountSelection, { ok: true }>\n\ntype AccountSelectionErr = Extract<AccountSelection, { ok: false }>\n\ntype RequestContext = {\n requestId: string\n startedAtMs: number\n\n method: string\n path: string\n\n clientIp?: string\n clientIpSource?: string\n userAgent?: string\n}\n\nembeddingRoutes.post(\"/\", async (c) => {\n try {\n const store = getRequestHistoryStore()\n\n const requestId = randomUUID()\n const startedAtMs = Date.now()\n\n const method = c.req.raw.method\n const path = new URL(c.req.url, \"http://local\").pathname\n\n const { ip: clientIp, source: clientIpSource } = getClientIpInfo(c)\n const userAgent = c.req.header(\"user-agent\") ?? undefined\n\n const ctx: RequestContext = {\n requestId,\n startedAtMs,\n method,\n path,\n clientIp,\n clientIpSource,\n userAgent,\n }\n\n const payload = await c.req.json<EmbeddingRequest>()\n const clientModel = payload.model\n\n const blockedTargets = getAliasTargetSet()\n if (blockedTargets.has(clientModel.toLowerCase())) {\n recordSelectionFailure(store, {\n ctx,\n clientModel,\n reason: \"MODEL_NOT_SUPPORTED\",\n })\n return selectionFailureResponse(c, clientModel, \"MODEL_NOT_SUPPORTED\")\n }\n\n const selection = await accountsManager.selectAccountForRequest([\n {\n modelId: clientModel,\n endpoint: EMBEDDINGS_ENDPOINT,\n },\n ])\n\n if (!selection.ok) {\n recordSelectionFailure(store, {\n ctx,\n clientModel,\n reason: selection.reason,\n })\n return selectionFailureResponse(c, clientModel, selection.reason)\n }\n\n const upstreamPayload = { ...payload, model: selection.selectedModel.id }\n\n return await runEmbeddingsWithAccount({\n c,\n store,\n ctx,\n payload: upstreamPayload,\n clientModel,\n selection,\n })\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n\nfunction recordSelectionFailure(\n store: ReturnType<typeof getRequestHistoryStore>,\n params: {\n ctx: RequestContext\n clientModel: string\n reason: AccountSelectionErr[\"reason\"]\n },\n): void {\n const { ctx, clientModel, reason } = params\n\n const finishedAtMs = Date.now()\n\n store.insert({\n requestId: ctx.requestId,\n startedAtMs: ctx.startedAtMs,\n finishedAtMs,\n durationMs: finishedAtMs - ctx.startedAtMs,\n method: ctx.method,\n path: ctx.path,\n upstreamEndpoint: EMBEDDINGS_ENDPOINT,\n stream: false,\n clientModel,\n clientIp: ctx.clientIp,\n clientIpSource: ctx.clientIpSource,\n userAgent: ctx.userAgent,\n httpStatus: reason === \"MODEL_NOT_SUPPORTED\" ? 400 : 429,\n selectionFailureReason: reason,\n })\n}\n\nfunction selectionFailureResponse(\n c: Context,\n clientModel: string,\n reason: AccountSelectionErr[\"reason\"],\n) {\n if (reason === \"MODEL_NOT_SUPPORTED\") {\n return c.json(\n {\n error: {\n message: `Model \"${clientModel}\" is not available for any configured account.`,\n type: \"invalid_request_error\",\n },\n },\n 400,\n )\n }\n\n return c.json(\n {\n error: {\n message:\n \"All accounts have exhausted their quota. Please wait for quota refresh or add additional accounts.\",\n type: \"rate_limit_error\",\n },\n },\n 429,\n )\n}\n\nasync function runEmbeddingsWithAccount({\n c,\n store,\n ctx,\n payload,\n clientModel,\n selection,\n}: {\n c: Context\n store: ReturnType<typeof getRequestHistoryStore>\n ctx: RequestContext\n payload: EmbeddingRequest\n clientModel: string\n selection: AccountSelectionOk\n}) {\n const { account, reservation, selectedModel, endpoint, costUnits } = selection\n\n const premiumRemainingBefore = account.premiumRemaining\n const premiumUnlimitedBefore = account.unlimited\n\n let httpStatus = 200\n let usage: NormalizedUsage = {}\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n let finishedAtMs: number | undefined\n\n try {\n const accountCtx = toAccountContext(account)\n\n const response = await createEmbeddings(payload, accountCtx)\n\n usage = normalizeEmbeddingsUsage(response.usage)\n\n finishedAtMs = Date.now()\n return c.json(response)\n } catch (error) {\n finishedAtMs = Date.now()\n\n const details = extractErrorDetails(error)\n\n httpStatus = details.httpStatus\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(account.id, \"Unauthorized (401)\")\n }\n\n throw error\n } finally {\n const finishedAtMsFinal = finishedAtMs ?? Date.now()\n\n await accountsManager.finalizeQuota(account, reservation)\n\n const premiumRemainingAfter = account.premiumRemaining\n const premiumUnlimitedAfter = account.unlimited\n\n store.insert({\n requestId: ctx.requestId,\n startedAtMs: ctx.startedAtMs,\n finishedAtMs: finishedAtMsFinal,\n durationMs: finishedAtMsFinal - ctx.startedAtMs,\n method: ctx.method,\n path: ctx.path,\n upstreamEndpoint: endpoint,\n stream: false,\n accountId: account.id,\n accountType: account.accountType,\n costUnits,\n clientModel,\n upstreamModel: selectedModel.id,\n clientIp: ctx.clientIp,\n clientIpSource: ctx.clientIpSource,\n userAgent: ctx.userAgent,\n ...usage,\n premiumRemainingBefore,\n premiumRemainingAfter,\n premiumRemainingDiff: computeDiff(\n premiumRemainingBefore,\n premiumRemainingAfter,\n ),\n premiumUnlimitedBefore,\n premiumUnlimitedAfter,\n httpStatus,\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n","import type { ConsolaInstance } from \"consola\"\nimport type { Context } from \"hono\"\n\nimport type { ChatCompletionsPayload } from \"~/services/copilot/create-chat-completions\"\nimport type { Model } from \"~/services/copilot/get-models\"\n\nimport { getAliasTargetSet } from \"~/lib/config\"\nimport { getRequestHistoryStore } from \"~/lib/request-history\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\n\nimport type {\n AnthropicMessagesPayload,\n AnthropicResponse,\n AnthropicTextBlock,\n AnthropicToolResultBlock,\n} from \"./anthropic-types\"\n\nexport function mapOpenAIStopReasonToAnthropic(\n finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null,\n): AnthropicResponse[\"stop_reason\"] {\n if (finishReason === null) {\n return null\n }\n const stopReasonMap = {\n stop: \"end_turn\",\n length: \"max_tokens\",\n tool_calls: \"tool_use\",\n content_filter: \"end_turn\",\n } as const\n return stopReasonMap[finishReason]\n}\n\nconst mergeContentWithText = (\n toolResult: AnthropicToolResultBlock,\n textBlock: AnthropicTextBlock,\n): AnthropicToolResultBlock => {\n if (typeof toolResult.content === \"string\") {\n return {\n ...toolResult,\n content: `${toolResult.content}\\n\\n${textBlock.text}`,\n }\n }\n return {\n ...toolResult,\n content: [...toolResult.content, textBlock],\n }\n}\n\nconst mergeContentWithTexts = (\n toolResult: AnthropicToolResultBlock,\n textBlocks: Array<AnthropicTextBlock>,\n): AnthropicToolResultBlock => {\n if (typeof toolResult.content === \"string\") {\n const appendedTexts = textBlocks.map((tb) => tb.text).join(\"\\n\\n\")\n return {\n ...toolResult,\n content: `${toolResult.content}\\n\\n${appendedTexts}`,\n }\n }\n return { ...toolResult, content: [...toolResult.content, ...textBlocks] }\n}\n\nconst mergeToolResult = (\n toolResults: Array<AnthropicToolResultBlock>,\n textBlocks: Array<AnthropicTextBlock>,\n): Array<AnthropicToolResultBlock> => {\n if (toolResults.length === textBlocks.length) {\n return toolResults.map((toolResult, index) =>\n mergeContentWithText(toolResult, textBlocks[index]),\n )\n }\n\n const lastIndex = toolResults.length - 1\n return toolResults.map((toolResult, index) =>\n index === lastIndex ?\n mergeContentWithTexts(toolResult, textBlocks)\n : toolResult,\n )\n}\n\nexport const mergeToolResultForClaude = (\n anthropicPayload: AnthropicMessagesPayload,\n): void => {\n for (const msg of anthropicPayload.messages) {\n if (msg.role !== \"user\" || !Array.isArray(msg.content)) continue\n\n const toolResults: Array<AnthropicToolResultBlock> = []\n const textBlocks: Array<AnthropicTextBlock> = []\n let valid = true\n\n for (const block of msg.content) {\n if (block.type === \"tool_result\") {\n toolResults.push(block)\n } else if (block.type === \"text\") {\n textBlocks.push(block)\n } else {\n valid = false\n break\n }\n }\n\n if (!valid || toolResults.length === 0 || textBlocks.length === 0) continue\n\n msg.content = mergeToolResult(toolResults, textBlocks)\n }\n}\n\nexport const estimateInputTokens = async (\n payload: ChatCompletionsPayload,\n selectedModel: Model,\n logger: Pick<ConsolaInstance, \"warn\">,\n): Promise<number | undefined> => {\n try {\n const tokenCount = await getTokenCount(payload, selectedModel)\n return tokenCount.input\n } catch (error) {\n logger.warn(\"Failed to estimate input tokens for message_start\", error)\n return undefined\n }\n}\n\ntype SelectionFailureReason = \"MODEL_NOT_SUPPORTED\" | \"NO_QUOTA\" | \"NO_ACCOUNTS\"\n\ntype SelectionFailure = {\n ok: false\n reason: SelectionFailureReason\n}\n\ntype SelectionFailureContext = {\n c: Context\n store: ReturnType<typeof getRequestHistoryStore>\n requestId: string\n startedAtMs: number\n method: string\n path: string\n streamRequested: boolean\n clientModel: string\n clientIp?: string\n clientIpSource?: string\n userAgent?: string\n userId?: string\n safetyIdentifier?: string\n promptCacheKey?: string\n initiator?: \"agent\" | \"user\"\n selection: SelectionFailure\n}\n\nexport const isWarmupProbeRequest = (\n payload: AnthropicMessagesPayload,\n): boolean => {\n const lastMsg = payload.messages.at(-1)\n if (!lastMsg || lastMsg.role !== \"user\" || !Array.isArray(lastMsg.content)) {\n return false\n }\n\n const lastBlock = lastMsg.content.at(-1)\n if (!lastBlock || lastBlock.type !== \"text\") {\n return false\n }\n\n const text = lastBlock.text.trim().toLowerCase()\n return text === \"warmup\" && lastBlock.cache_control?.type === \"ephemeral\"\n}\n\nexport const handleSelectionFailure = (\n context: SelectionFailureContext,\n): Response => {\n const {\n c,\n store,\n requestId,\n startedAtMs,\n method,\n path,\n streamRequested,\n clientModel,\n clientIp,\n clientIpSource,\n userAgent,\n userId,\n safetyIdentifier,\n promptCacheKey,\n initiator,\n selection,\n } = context\n const finishedAtMs = Date.now()\n\n store.insert({\n requestId,\n startedAtMs,\n finishedAtMs,\n durationMs: finishedAtMs - startedAtMs,\n method,\n path,\n stream: streamRequested,\n clientModel,\n clientIp,\n clientIpSource,\n userAgent,\n userId,\n safetyIdentifier,\n promptCacheKey,\n initiator,\n httpStatus: selection.reason === \"MODEL_NOT_SUPPORTED\" ? 400 : 429,\n selectionFailureReason: selection.reason,\n })\n\n if (selection.reason === \"MODEL_NOT_SUPPORTED\") {\n return c.json(\n {\n error: {\n message: `Model \"${clientModel}\" is not available for any configured account.`,\n type: \"invalid_request_error\",\n },\n },\n 400,\n )\n }\n\n return c.json(\n {\n error: {\n message:\n \"All accounts have exhausted their quota. Please wait for quota refresh or add additional accounts.\",\n type: \"rate_limit_error\",\n },\n },\n 429,\n )\n}\n\nexport const maybeBlockOriginalModelName = (\n context: Omit<SelectionFailureContext, \"selection\">,\n): Response | null => {\n const blockedTargets = getAliasTargetSet()\n if (!blockedTargets.has(context.clientModel.toLowerCase())) {\n return null\n }\n\n return handleSelectionFailure({\n ...context,\n selection: { ok: false, reason: \"MODEL_NOT_SUPPORTED\" },\n })\n}\n","import type { Model } from \"~/services/copilot/get-models\"\n\nimport { state } from \"~/lib/state\"\nimport {\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n type ContentPart,\n type Message,\n type TextPart,\n type Tool,\n type ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicAssistantContentBlock,\n type AnthropicAssistantMessage,\n type AnthropicMessagesPayload,\n type AnthropicResponse,\n type AnthropicTextBlock,\n type AnthropicThinkingBlock,\n type AnthropicTool,\n type AnthropicToolResultBlock,\n type AnthropicToolUseBlock,\n type AnthropicUserContentBlock,\n type AnthropicUserMessage,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\n// Compatible with opencode, it will filter out blocks where the thinking text is empty, so we need add a default thinking text\nexport const THINKING_TEXT = \"Thinking...\"\n\n// Payload translation\nexport function translateToOpenAI(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload {\n const modelId = translateModelName(payload.model)\n const model = state.models?.data.find((m) => m.id === modelId)\n const thinkingBudget = getThinkingBudget(payload, model)\n return {\n model: modelId,\n messages: translateAnthropicMessagesToOpenAI(\n payload,\n modelId,\n thinkingBudget,\n ),\n max_tokens: payload.max_tokens,\n stop: payload.stop_sequences,\n stream: payload.stream,\n temperature: payload.temperature,\n top_p: payload.top_p,\n user: payload.metadata?.user_id,\n tools: translateAnthropicToolsToOpenAI(payload.tools),\n tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),\n thinking_budget: thinkingBudget,\n }\n}\n\nfunction getThinkingBudget(\n payload: AnthropicMessagesPayload,\n model: Model | undefined,\n): number | undefined {\n const thinking = payload.thinking\n if (model && thinking) {\n const maxThinkingBudget = Math.min(\n model.capabilities.supports.max_thinking_budget ?? 0,\n (model.capabilities.limits.max_output_tokens ?? 0) - 1,\n )\n if (maxThinkingBudget > 0 && thinking.budget_tokens !== undefined) {\n const budgetTokens = Math.min(thinking.budget_tokens, maxThinkingBudget)\n return Math.max(\n budgetTokens,\n model.capabilities.supports.min_thinking_budget ?? 1024,\n )\n }\n }\n return undefined\n}\n\nfunction translateModelName(model: string): string {\n // Subagent requests use a specific model number which Copilot doesn't support\n if (model.startsWith(\"claude-sonnet-4-\")) {\n return model.replace(/^claude-sonnet-4-.*/, \"claude-sonnet-4\")\n } else if (model.startsWith(\"claude-opus-4-\")) {\n return model.replace(/^claude-opus-4-.*/, \"claude-opus-4\")\n }\n return model\n}\n\nfunction translateAnthropicMessagesToOpenAI(\n payload: AnthropicMessagesPayload,\n modelId: string,\n thinkingBudget: number | undefined,\n): Array<Message> {\n const systemMessages = handleSystemPrompt(\n payload.system,\n modelId,\n thinkingBudget,\n )\n const otherMessages = payload.messages.flatMap((message) =>\n message.role === \"user\" ?\n handleUserMessage(message)\n : handleAssistantMessage(message, modelId),\n )\n if (modelId.startsWith(\"claude\") && thinkingBudget) {\n const reminder =\n \"<system-reminder>you MUST follow interleaved_thinking_protocol</system-reminder>\"\n const firstUserIndex = otherMessages.findIndex((m) => m.role === \"user\")\n if (firstUserIndex !== -1) {\n const userMessage = otherMessages[firstUserIndex]\n if (typeof userMessage.content === \"string\") {\n userMessage.content = reminder + \"\\n\\n\" + userMessage.content\n } else if (Array.isArray(userMessage.content)) {\n userMessage.content = [\n { type: \"text\", text: reminder },\n ...userMessage.content,\n ] as Array<ContentPart>\n }\n }\n }\n return [...systemMessages, ...otherMessages]\n}\n\nfunction handleSystemPrompt(\n system: string | Array<AnthropicTextBlock> | undefined,\n modelId: string,\n thinkingBudget: number | undefined,\n): Array<Message> {\n if (!system) {\n return []\n }\n\n let extraPrompt = \"\"\n if (modelId.startsWith(\"claude\") && thinkingBudget) {\n extraPrompt = `\n<interleaved_thinking_protocol>\nABSOLUTE REQUIREMENT - NON-NEGOTIABLE:\nThe current thinking_mode is interleaved, Whenever you have the result of a function call, think carefully , MUST output a thinking block\nRULES:\nTool result → thinking block (ALWAYS, no exceptions)\nThis is NOT optional - it is a hard requirement\nThe thinking block must contain substantive reasoning (minimum 3-5 sentences)\nThink about: what the results mean, what to do next, how to answer the user\nNEVER skip this step, even if the result seems simple or obvious\n</interleaved_thinking_protocol>`\n }\n\n if (typeof system === \"string\") {\n return [{ role: \"system\", content: system + extraPrompt }]\n } else {\n const systemText = system\n .map((block, index) => {\n if (index === 0) {\n return block.text + extraPrompt\n }\n return block.text\n })\n .join(\"\\n\\n\")\n return [{ role: \"system\", content: systemText }]\n }\n}\n\nfunction handleUserMessage(message: AnthropicUserMessage): Array<Message> {\n const newMessages: Array<Message> = []\n\n if (Array.isArray(message.content)) {\n const toolResultBlocks = message.content.filter(\n (block): block is AnthropicToolResultBlock =>\n block.type === \"tool_result\",\n )\n const otherBlocks = message.content.filter(\n (block) => block.type !== \"tool_result\",\n )\n\n // Tool results must come first to maintain protocol: tool_use -> tool_result -> user\n for (const block of toolResultBlocks) {\n newMessages.push({\n role: \"tool\",\n tool_call_id: block.tool_use_id,\n content: mapContent(block.content),\n })\n }\n\n if (otherBlocks.length > 0) {\n newMessages.push({\n role: \"user\",\n content: mapContent(otherBlocks),\n })\n }\n } else {\n newMessages.push({\n role: \"user\",\n content: mapContent(message.content),\n })\n }\n\n return newMessages\n}\n\nfunction handleAssistantMessage(\n message: AnthropicAssistantMessage,\n modelId: string,\n): Array<Message> {\n if (!Array.isArray(message.content)) {\n return [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n }\n\n const toolUseBlocks = message.content.filter(\n (block): block is AnthropicToolUseBlock => block.type === \"tool_use\",\n )\n\n let thinkingBlocks = message.content.filter(\n (block): block is AnthropicThinkingBlock => block.type === \"thinking\",\n )\n\n if (modelId.startsWith(\"claude\")) {\n thinkingBlocks = thinkingBlocks.filter(\n (b) =>\n b.thinking\n && b.thinking !== THINKING_TEXT\n && b.signature\n // gpt signature has @ in it, so filter those out for claude models\n && !b.signature.includes(\"@\"),\n )\n }\n\n const thinkingContents = thinkingBlocks\n .filter((b) => b.thinking && b.thinking !== THINKING_TEXT)\n .map((b) => b.thinking)\n\n const allThinkingContent =\n thinkingContents.length > 0 ? thinkingContents.join(\"\\n\\n\") : undefined\n\n const signature = thinkingBlocks.find((b) => b.signature)?.signature\n\n return toolUseBlocks.length > 0 ?\n [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n reasoning_text: allThinkingContent,\n reasoning_opaque: signature,\n tool_calls: toolUseBlocks.map((toolUse) => ({\n id: toolUse.id,\n type: \"function\",\n function: {\n name: toolUse.name,\n arguments: JSON.stringify(toolUse.input),\n },\n })),\n },\n ]\n : [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n reasoning_text: allThinkingContent,\n reasoning_opaque: signature,\n },\n ]\n}\n\nfunction mapContent(\n content:\n | string\n | Array<AnthropicUserContentBlock | AnthropicAssistantContentBlock>,\n): string | Array<ContentPart> | null {\n if (typeof content === \"string\") {\n return content\n }\n if (!Array.isArray(content)) {\n return null\n }\n\n const hasImage = content.some((block) => block.type === \"image\")\n if (!hasImage) {\n return content\n .filter((block): block is AnthropicTextBlock => block.type === \"text\")\n .map((block) => block.text)\n .join(\"\\n\\n\")\n }\n\n const contentParts: Array<ContentPart> = []\n for (const block of content) {\n switch (block.type) {\n case \"text\": {\n contentParts.push({ type: \"text\", text: block.text })\n break\n }\n case \"image\": {\n contentParts.push({\n type: \"image_url\",\n image_url: {\n url: `data:${block.source.media_type};base64,${block.source.data}`,\n },\n })\n break\n }\n // No default\n }\n }\n return contentParts\n}\n\nfunction translateAnthropicToolsToOpenAI(\n anthropicTools: Array<AnthropicTool> | undefined,\n): Array<Tool> | undefined {\n if (!anthropicTools) {\n return undefined\n }\n return anthropicTools.map((tool) => ({\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.input_schema,\n },\n }))\n}\n\nfunction translateAnthropicToolChoiceToOpenAI(\n anthropicToolChoice: AnthropicMessagesPayload[\"tool_choice\"],\n): ChatCompletionsPayload[\"tool_choice\"] {\n if (!anthropicToolChoice) {\n return undefined\n }\n\n switch (anthropicToolChoice.type) {\n case \"auto\": {\n return \"auto\"\n }\n case \"any\": {\n return \"required\"\n }\n case \"tool\": {\n if (anthropicToolChoice.name) {\n return {\n type: \"function\",\n function: { name: anthropicToolChoice.name },\n }\n }\n return undefined\n }\n case \"none\": {\n return \"none\"\n }\n default: {\n return undefined\n }\n }\n}\n\n// Response translation\n\nexport function translateToAnthropic(\n response: ChatCompletionResponse,\n): AnthropicResponse {\n // Merge content from all choices\n const assistantContentBlocks: Array<AnthropicAssistantContentBlock> = []\n let stopReason = response.choices[0]?.finish_reason ?? null\n\n // Process all choices to extract text and tool use blocks\n for (const choice of response.choices) {\n const textBlocks = getAnthropicTextBlocks(choice.message.content)\n const thinkBlocks = getAnthropicThinkBlocks(\n choice.message.reasoning_text,\n choice.message.reasoning_opaque,\n )\n const toolUseBlocks = getAnthropicToolUseBlocks(choice.message.tool_calls)\n\n assistantContentBlocks.push(...thinkBlocks, ...textBlocks, ...toolUseBlocks)\n\n // Use the finish_reason from the first choice, or prioritize tool_calls\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\n stopReason = choice.finish_reason\n }\n }\n\n return {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n model: response.model,\n content: assistantContentBlocks,\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\n stop_sequence: null,\n usage: {\n input_tokens:\n (response.usage?.prompt_tokens ?? 0)\n - (response.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: response.usage?.completion_tokens ?? 0,\n ...(response.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n response.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n }\n}\n\nfunction getAnthropicTextBlocks(\n messageContent: Message[\"content\"],\n): Array<AnthropicTextBlock> {\n if (typeof messageContent === \"string\" && messageContent.length > 0) {\n return [{ type: \"text\", text: messageContent }]\n }\n\n if (Array.isArray(messageContent)) {\n return messageContent\n .filter((part): part is TextPart => part.type === \"text\")\n .map((part) => ({ type: \"text\", text: part.text }))\n }\n\n return []\n}\n\nfunction getAnthropicThinkBlocks(\n reasoningText: string | null | undefined,\n reasoningOpaque: string | null | undefined,\n): Array<AnthropicThinkingBlock> {\n if (reasoningText && reasoningText.length > 0) {\n return [\n {\n type: \"thinking\",\n thinking: reasoningText,\n signature: reasoningOpaque || \"\",\n },\n ]\n }\n if (reasoningOpaque && reasoningOpaque.length > 0) {\n return [\n {\n type: \"thinking\",\n thinking: THINKING_TEXT, // Compatible with opencode, it will filter out blocks where the thinking text is empty, so we add a default thinking text here\n signature: reasoningOpaque,\n },\n ]\n }\n return []\n}\n\nfunction getAnthropicToolUseBlocks(\n toolCalls: Array<ToolCall> | undefined,\n): Array<AnthropicToolUseBlock> {\n if (!toolCalls) {\n return []\n }\n return toolCalls.map((toolCall) => ({\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: JSON.parse(toolCall.function.arguments) as Record<string, unknown>,\n }))\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport { state } from \"~/lib/state\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\n\nimport { type AnthropicMessagesPayload } from \"./anthropic-types\"\nimport { translateToOpenAI } from \"./non-stream-translation\"\n\n/**\n * Handles token counting for Anthropic messages\n */\nexport async function handleCountTokens(c: Context) {\n try {\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n const selectedModel = state.models?.data.find(\n (model) => model.id === anthropicPayload.model,\n )\n\n if (!selectedModel) {\n consola.warn(\"Model not found, returning default token count\")\n return c.json({\n input_tokens: 1,\n })\n }\n\n const tokenCount = await getTokenCount(openAIPayload, selectedModel)\n\n if (anthropicPayload.tools && anthropicPayload.tools.length > 0) {\n let addToolSystemPromptCount = false\n if (anthropicBeta) {\n const toolsLength = anthropicPayload.tools.length\n addToolSystemPromptCount = !anthropicPayload.tools.some(\n (tool) =>\n tool.name.startsWith(\"mcp__\")\n || (tool.name === \"Skill\" && toolsLength === 1),\n )\n }\n if (addToolSystemPromptCount) {\n if (anthropicPayload.model.startsWith(\"claude\")) {\n // https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview#pricing\n tokenCount.input = tokenCount.input + 346\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n tokenCount.input = tokenCount.input + 120\n }\n }\n }\n\n let finalTokenCount = tokenCount.input + tokenCount.output\n if (anthropicPayload.model.startsWith(\"claude\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.15)\n }\n\n consola.info(\"Token count:\", finalTokenCount)\n\n return c.json({\n input_tokens: finalTokenCount,\n })\n } catch (error) {\n consola.error(\"Error counting tokens:\", error)\n return c.json({\n input_tokens: 1,\n })\n }\n}\n","import {\n type ResponseCompletedEvent,\n type ResponseCreatedEvent,\n type ResponseErrorEvent,\n type ResponseFailedEvent,\n type ResponseFunctionCallArgumentsDeltaEvent,\n type ResponseFunctionCallArgumentsDoneEvent,\n type ResponseIncompleteEvent,\n type ResponseOutputItemAddedEvent,\n type ResponseOutputItemDoneEvent,\n type ResponseReasoningSummaryTextDeltaEvent,\n type ResponseReasoningSummaryTextDoneEvent,\n type ResponsesResult,\n type ResponseStreamEvent,\n type ResponseTextDeltaEvent,\n type ResponseTextDoneEvent,\n} from \"~/services/copilot/create-responses\"\n\nimport { type AnthropicStreamEventData } from \"./anthropic-types\"\nimport {\n THINKING_TEXT,\n translateResponsesResultToAnthropic,\n} from \"./responses-translation\"\n\nconst MAX_CONSECUTIVE_FUNCTION_CALL_WHITESPACE = 20\n\nclass FunctionCallArgumentsValidationError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"FunctionCallArgumentsValidationError\"\n }\n}\n\nconst updateWhitespaceRunState = (\n previousCount: number,\n chunk: string,\n): {\n nextCount: number\n exceeded: boolean\n} => {\n let count = previousCount\n\n for (const char of chunk) {\n if (char === \"\\r\" || char === \"\\n\" || char === \"\\t\") {\n count += 1\n if (count > MAX_CONSECUTIVE_FUNCTION_CALL_WHITESPACE) {\n return { nextCount: count, exceeded: true }\n }\n continue\n }\n\n if (char !== \" \") {\n count = 0\n }\n }\n\n return { nextCount: count, exceeded: false }\n}\n\nexport interface ResponsesStreamState {\n messageStartSent: boolean\n messageCompleted: boolean\n nextContentBlockIndex: number\n blockIndexByKey: Map<string, number>\n openBlocks: Set<number>\n blockHasDelta: Set<number>\n functionCallStateByOutputIndex: Map<number, FunctionCallStreamState>\n estimatedInputTokens?: number\n historicalInputTokens?: number\n historicalOutputTokens?: number\n historicalCachedInputTokens?: number\n}\n\ntype FunctionCallStreamState = {\n blockIndex: number\n toolCallId: string\n name: string\n consecutiveWhitespaceCount: number\n}\n\nexport const createResponsesStreamState = (): ResponsesStreamState => ({\n messageStartSent: false,\n messageCompleted: false,\n nextContentBlockIndex: 0,\n blockIndexByKey: new Map(),\n openBlocks: new Set(),\n blockHasDelta: new Set(),\n functionCallStateByOutputIndex: new Map(),\n})\n\nexport const translateResponsesStreamEvent = (\n rawEvent: ResponseStreamEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const eventType = rawEvent.type\n switch (eventType) {\n case \"response.created\": {\n return handleResponseCreated(rawEvent, state)\n }\n\n case \"response.output_item.added\": {\n return handleOutputItemAdded(rawEvent, state)\n }\n\n case \"response.reasoning_summary_text.delta\": {\n return handleReasoningSummaryTextDelta(rawEvent, state)\n }\n\n case \"response.output_text.delta\": {\n return handleOutputTextDelta(rawEvent, state)\n }\n\n case \"response.reasoning_summary_text.done\": {\n return handleReasoningSummaryTextDone(rawEvent, state)\n }\n\n case \"response.output_text.done\": {\n return handleOutputTextDone(rawEvent, state)\n }\n case \"response.output_item.done\": {\n return handleOutputItemDone(rawEvent, state)\n }\n\n case \"response.function_call_arguments.delta\": {\n return handleFunctionCallArgumentsDelta(rawEvent, state)\n }\n\n case \"response.function_call_arguments.done\": {\n return handleFunctionCallArgumentsDone(rawEvent, state)\n }\n\n case \"response.completed\":\n case \"response.incomplete\": {\n return handleResponseCompleted(rawEvent, state)\n }\n\n case \"response.failed\": {\n return handleResponseFailed(rawEvent, state)\n }\n\n case \"error\": {\n return handleErrorEvent(rawEvent, state)\n }\n\n default: {\n return []\n }\n }\n}\n\n// Helper handlers to keep translateResponsesStreamEvent concise\nconst handleResponseCreated = (\n rawEvent: ResponseCreatedEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n return messageStart(state, rawEvent.response)\n}\n\nconst handleOutputItemAdded = (\n rawEvent: ResponseOutputItemAddedEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const events = new Array<AnthropicStreamEventData>()\n const functionCallDetails = extractFunctionCallDetails(rawEvent)\n if (!functionCallDetails) {\n return events\n }\n\n const { outputIndex, toolCallId, name, initialArguments } =\n functionCallDetails\n const blockIndex = openFunctionCallBlock(state, {\n outputIndex,\n toolCallId,\n name,\n events,\n })\n\n if (initialArguments !== undefined && initialArguments.length > 0) {\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: initialArguments,\n },\n })\n state.blockHasDelta.add(blockIndex)\n }\n\n return events\n}\n\nconst handleOutputItemDone = (\n rawEvent: ResponseOutputItemDoneEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const events = new Array<AnthropicStreamEventData>()\n const item = rawEvent.item\n const itemType = item.type\n if (itemType !== \"reasoning\") {\n return events\n }\n\n const outputIndex = rawEvent.output_index\n const blockIndex = openThinkingBlockIfNeeded(state, outputIndex, events)\n const signature = (item.encrypted_content ?? \"\") + \"@\" + item.id\n if (signature) {\n // Compatible with opencode, it will filter out blocks where the thinking text is empty, so we add a default thinking text here\n if (!item.summary || item.summary.length === 0) {\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: {\n type: \"thinking_delta\",\n thinking: THINKING_TEXT,\n },\n })\n }\n\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: {\n type: \"signature_delta\",\n signature,\n },\n })\n state.blockHasDelta.add(blockIndex)\n }\n\n return events\n}\n\nconst handleFunctionCallArgumentsDelta = (\n rawEvent: ResponseFunctionCallArgumentsDeltaEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const events = new Array<AnthropicStreamEventData>()\n const outputIndex = rawEvent.output_index\n const deltaText = rawEvent.delta\n\n if (!deltaText) {\n return events\n }\n\n const blockIndex = openFunctionCallBlock(state, {\n outputIndex,\n events,\n })\n\n const functionCallState =\n state.functionCallStateByOutputIndex.get(outputIndex)\n if (!functionCallState) {\n return handleFunctionCallArgumentsValidationError(\n new FunctionCallArgumentsValidationError(\n \"Received function call arguments delta without an open tool call block.\",\n ),\n state,\n events,\n )\n }\n\n // fix: copolit function call returning infinite line breaks until max_tokens limit\n // \"arguments\": \"{\\\"path\\\":\\\"xxx\\\",\\\"pattern\\\":\\\"**/*.ts\\\",\\\"} }? Wait extra braces. Need correct. I should run? Wait overcame. Need proper JSON with pattern \\\"\\n\\n\\n\\n\\n\\n\\n\\n...\n const { nextCount, exceeded } = updateWhitespaceRunState(\n functionCallState.consecutiveWhitespaceCount,\n deltaText,\n )\n if (exceeded) {\n return handleFunctionCallArgumentsValidationError(\n new FunctionCallArgumentsValidationError(\n \"Received function call arguments delta containing more than 20 consecutive whitespace characters.\",\n ),\n state,\n events,\n )\n }\n functionCallState.consecutiveWhitespaceCount = nextCount\n\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: deltaText,\n },\n })\n state.blockHasDelta.add(blockIndex)\n\n return events\n}\n\nconst handleFunctionCallArgumentsDone = (\n rawEvent: ResponseFunctionCallArgumentsDoneEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const events = new Array<AnthropicStreamEventData>()\n const outputIndex = rawEvent.output_index\n const blockIndex = openFunctionCallBlock(state, {\n outputIndex,\n events,\n })\n\n const finalArguments =\n typeof rawEvent.arguments === \"string\" ? rawEvent.arguments : undefined\n\n if (!state.blockHasDelta.has(blockIndex) && finalArguments) {\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: finalArguments,\n },\n })\n state.blockHasDelta.add(blockIndex)\n }\n\n state.functionCallStateByOutputIndex.delete(outputIndex)\n return events\n}\n\nconst handleOutputTextDelta = (\n rawEvent: ResponseTextDeltaEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const events = new Array<AnthropicStreamEventData>()\n const outputIndex = rawEvent.output_index\n const contentIndex = rawEvent.content_index\n const deltaText = rawEvent.delta\n\n if (!deltaText) {\n return events\n }\n\n const blockIndex = openTextBlockIfNeeded(state, {\n outputIndex,\n contentIndex,\n events,\n })\n\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: {\n type: \"text_delta\",\n text: deltaText,\n },\n })\n state.blockHasDelta.add(blockIndex)\n\n return events\n}\n\nconst handleReasoningSummaryTextDelta = (\n rawEvent: ResponseReasoningSummaryTextDeltaEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const outputIndex = rawEvent.output_index\n const deltaText = rawEvent.delta\n const events = new Array<AnthropicStreamEventData>()\n const blockIndex = openThinkingBlockIfNeeded(state, outputIndex, events)\n\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: {\n type: \"thinking_delta\",\n thinking: deltaText,\n },\n })\n state.blockHasDelta.add(blockIndex)\n\n return events\n}\n\nconst handleReasoningSummaryTextDone = (\n rawEvent: ResponseReasoningSummaryTextDoneEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const outputIndex = rawEvent.output_index\n const text = rawEvent.text\n const events = new Array<AnthropicStreamEventData>()\n const blockIndex = openThinkingBlockIfNeeded(state, outputIndex, events)\n\n if (text && !state.blockHasDelta.has(blockIndex)) {\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: {\n type: \"thinking_delta\",\n thinking: text,\n },\n })\n }\n\n return events\n}\n\nconst handleOutputTextDone = (\n rawEvent: ResponseTextDoneEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const events = new Array<AnthropicStreamEventData>()\n const outputIndex = rawEvent.output_index\n const contentIndex = rawEvent.content_index\n const text = rawEvent.text\n\n const blockIndex = openTextBlockIfNeeded(state, {\n outputIndex,\n contentIndex,\n events,\n })\n\n if (text && !state.blockHasDelta.has(blockIndex)) {\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: {\n type: \"text_delta\",\n text,\n },\n })\n }\n\n return events\n}\n\nconst handleResponseCompleted = (\n rawEvent: ResponseCompletedEvent | ResponseIncompleteEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const response = rawEvent.response\n const events = new Array<AnthropicStreamEventData>()\n\n closeAllOpenBlocks(state, events)\n const anthropic = translateResponsesResultToAnthropic(response)\n events.push(\n {\n type: \"message_delta\",\n delta: {\n stop_reason: anthropic.stop_reason,\n stop_sequence: anthropic.stop_sequence,\n },\n usage: anthropic.usage,\n },\n { type: \"message_stop\" },\n )\n state.messageCompleted = true\n return events\n}\n\nconst handleResponseFailed = (\n rawEvent: ResponseFailedEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const response = rawEvent.response\n const events = new Array<AnthropicStreamEventData>()\n closeAllOpenBlocks(state, events)\n\n const message =\n response.error?.message ?? \"The response failed due to an unknown error.\"\n\n events.push(buildErrorEvent(message))\n state.messageCompleted = true\n\n return events\n}\n\nconst handleErrorEvent = (\n rawEvent: ResponseErrorEvent,\n state: ResponsesStreamState,\n): Array<AnthropicStreamEventData> => {\n const message =\n typeof rawEvent.message === \"string\" ?\n rawEvent.message\n : \"An unexpected error occurred during streaming.\"\n\n state.messageCompleted = true\n return [buildErrorEvent(message)]\n}\n\nconst handleFunctionCallArgumentsValidationError = (\n error: FunctionCallArgumentsValidationError,\n state: ResponsesStreamState,\n events: Array<AnthropicStreamEventData> = [],\n): Array<AnthropicStreamEventData> => {\n const reason = error.message\n\n closeAllOpenBlocks(state, events)\n state.messageCompleted = true\n\n events.push(buildErrorEvent(reason))\n\n return events\n}\n\nconst messageStart = (\n state: ResponsesStreamState,\n response: ResponsesResult,\n): Array<AnthropicStreamEventData> => {\n state.messageStartSent = true\n const inputCachedTokens = response.usage?.input_tokens_details?.cached_tokens\n const upstreamInputTokens = response.usage?.input_tokens\n const historicalInputTokens = state.historicalInputTokens\n const historicalOutputTokens = state.historicalOutputTokens ?? 0\n const historicalTotalTokens =\n historicalInputTokens !== undefined ?\n historicalInputTokens + historicalOutputTokens\n : undefined\n const inputTokens =\n upstreamInputTokens !== undefined ?\n upstreamInputTokens - (inputCachedTokens ?? 0)\n : (historicalTotalTokens ?? state.estimatedInputTokens ?? 0)\n const cacheReadTokens =\n upstreamInputTokens !== undefined ?\n (inputCachedTokens ?? 0)\n : (state.historicalCachedInputTokens ?? 0)\n return [\n {\n type: \"message_start\",\n message: {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: response.model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens: inputTokens,\n output_tokens: 0,\n cache_read_input_tokens: cacheReadTokens,\n },\n },\n },\n ]\n}\n\nconst openTextBlockIfNeeded = (\n state: ResponsesStreamState,\n params: {\n outputIndex: number\n contentIndex: number\n events: Array<AnthropicStreamEventData>\n },\n): number => {\n const { outputIndex, contentIndex, events } = params\n const key = getBlockKey(outputIndex, contentIndex)\n let blockIndex = state.blockIndexByKey.get(key)\n\n if (blockIndex === undefined) {\n blockIndex = state.nextContentBlockIndex\n state.nextContentBlockIndex += 1\n state.blockIndexByKey.set(key, blockIndex)\n }\n\n if (!state.openBlocks.has(blockIndex)) {\n closeOpenBlocks(state, events)\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: {\n type: \"text\",\n text: \"\",\n },\n })\n state.openBlocks.add(blockIndex)\n }\n\n return blockIndex\n}\n\nconst openThinkingBlockIfNeeded = (\n state: ResponsesStreamState,\n outputIndex: number,\n events: Array<AnthropicStreamEventData>,\n): number => {\n //thinking blocks has multiple summary_index, should combine into one block\n const summaryIndex = 0\n const key = getBlockKey(outputIndex, summaryIndex)\n let blockIndex = state.blockIndexByKey.get(key)\n\n if (blockIndex === undefined) {\n blockIndex = state.nextContentBlockIndex\n state.nextContentBlockIndex += 1\n state.blockIndexByKey.set(key, blockIndex)\n }\n\n if (!state.openBlocks.has(blockIndex)) {\n closeOpenBlocks(state, events)\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: {\n type: \"thinking\",\n thinking: \"\",\n },\n })\n state.openBlocks.add(blockIndex)\n }\n\n return blockIndex\n}\n\nconst closeBlockIfOpen = (\n state: ResponsesStreamState,\n blockIndex: number,\n events: Array<AnthropicStreamEventData>,\n) => {\n if (!state.openBlocks.has(blockIndex)) {\n return\n }\n\n events.push({ type: \"content_block_stop\", index: blockIndex })\n state.openBlocks.delete(blockIndex)\n state.blockHasDelta.delete(blockIndex)\n}\n\nconst closeOpenBlocks = (\n state: ResponsesStreamState,\n events: Array<AnthropicStreamEventData>,\n) => {\n for (const blockIndex of state.openBlocks) {\n closeBlockIfOpen(state, blockIndex, events)\n }\n}\n\nconst closeAllOpenBlocks = (\n state: ResponsesStreamState,\n events: Array<AnthropicStreamEventData>,\n) => {\n closeOpenBlocks(state, events)\n\n state.functionCallStateByOutputIndex.clear()\n}\n\nexport const buildErrorEvent = (message: string): AnthropicStreamEventData => ({\n type: \"error\",\n error: {\n type: \"api_error\",\n message,\n },\n})\n\nconst getBlockKey = (outputIndex: number, contentIndex: number): string =>\n `${outputIndex}:${contentIndex}`\n\nconst openFunctionCallBlock = (\n state: ResponsesStreamState,\n params: {\n outputIndex: number\n toolCallId?: string\n name?: string\n events: Array<AnthropicStreamEventData>\n },\n): number => {\n const { outputIndex, toolCallId, name, events } = params\n\n let functionCallState = state.functionCallStateByOutputIndex.get(outputIndex)\n\n if (!functionCallState) {\n const blockIndex = state.nextContentBlockIndex\n state.nextContentBlockIndex += 1\n\n const resolvedToolCallId = toolCallId ?? `tool_call_${blockIndex}`\n const resolvedName = name ?? \"function\"\n\n functionCallState = {\n blockIndex,\n toolCallId: resolvedToolCallId,\n name: resolvedName,\n consecutiveWhitespaceCount: 0,\n }\n\n state.functionCallStateByOutputIndex.set(outputIndex, functionCallState)\n }\n\n const { blockIndex } = functionCallState\n\n if (!state.openBlocks.has(blockIndex)) {\n closeOpenBlocks(state, events)\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: {\n type: \"tool_use\",\n id: functionCallState.toolCallId,\n name: functionCallState.name,\n input: {},\n },\n })\n state.openBlocks.add(blockIndex)\n }\n\n return blockIndex\n}\n\ntype FunctionCallDetails = {\n outputIndex: number\n toolCallId: string\n name: string\n initialArguments?: string\n}\n\nconst extractFunctionCallDetails = (\n rawEvent: ResponseOutputItemAddedEvent,\n): FunctionCallDetails | undefined => {\n const item = rawEvent.item\n const itemType = item.type\n if (itemType !== \"function_call\") {\n return undefined\n }\n\n const outputIndex = rawEvent.output_index\n const toolCallId = item.call_id\n const name = item.name\n const initialArguments = item.arguments\n return {\n outputIndex,\n toolCallId,\n name,\n initialArguments,\n }\n}\n","import type {\n ResponseInputItem,\n ResponsesPayload,\n} from \"~/services/copilot/create-responses\"\n\nimport { isForceAgentEnabled } from \"~/lib/config\"\n\nexport const getResponsesRequestOptions = (\n payload: ResponsesPayload,\n): { vision: boolean; initiator: \"agent\" | \"user\" } => {\n const vision = hasVisionInput(payload)\n const initiator = hasAgentInitiator(payload) ? \"agent\" : \"user\"\n\n return { vision, initiator }\n}\n\nexport const hasAgentInitiator = (payload: ResponsesPayload): boolean => {\n const items = getPayloadItems(payload)\n\n if (isForceAgentEnabled()) {\n // forceAgent mode: check if ANY item has assistant role\n return items.some((item) => isAgentRole(item))\n }\n\n // Default mode: only check the last item\n const lastItem = items.at(-1)\n if (!lastItem) {\n return false\n }\n return isAgentRole(lastItem)\n}\n\n// Helper function: check if a single item has agent role\nconst isAgentRole = (item: ResponseInputItem): boolean => {\n if (!(\"role\" in item) || !item.role) {\n return true // No role means agent (preserve original logic)\n }\n const role = typeof item.role === \"string\" ? item.role.toLowerCase() : \"\"\n return role === \"assistant\"\n}\n\nexport const hasVisionInput = (payload: ResponsesPayload): boolean => {\n const values = getPayloadItems(payload)\n return values.some((item) => containsVisionContent(item))\n}\n\nconst getPayloadItems = (\n payload: ResponsesPayload,\n): Array<ResponseInputItem> => {\n const result: Array<ResponseInputItem> = []\n\n const { input } = payload\n\n if (Array.isArray(input)) {\n result.push(...input)\n }\n\n return result\n}\n\nconst containsVisionContent = (value: unknown): boolean => {\n if (!value) return false\n\n if (Array.isArray(value)) {\n return value.some((entry) => containsVisionContent(entry))\n }\n\n if (typeof value !== \"object\") {\n return false\n }\n\n const record = value as Record<string, unknown>\n const type =\n typeof record.type === \"string\" ? record.type.toLowerCase() : undefined\n\n if (type === \"input_image\") {\n return true\n }\n\n if (Array.isArray(record.content)) {\n return record.content.some((entry) => containsVisionContent(entry))\n }\n\n return false\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport type { AccountContext } from \"~/lib/types/account\"\nimport type {\n AnthropicMessagesPayload,\n AnthropicResponse,\n} from \"~/routes/messages/anthropic-types\"\n\nimport { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { accountFromState } from \"~/lib/state\"\n\nexport const getMessagesInitiator = (\n payload: AnthropicMessagesPayload,\n): \"agent\" | \"user\" => {\n const lastMessage = payload.messages.at(-1)\n if (!lastMessage || lastMessage.role !== \"user\") {\n return \"agent\"\n }\n\n if (!Array.isArray(lastMessage.content)) {\n return \"user\"\n }\n\n const hasNonToolResult = lastMessage.content.some(\n (block) => block.type !== \"tool_result\",\n )\n return hasNonToolResult ? \"user\" : \"agent\"\n}\n\nexport type MessagesStream = ReturnType<typeof events>\nexport type CreateMessagesReturn = AnthropicResponse | MessagesStream\n\nexport const createMessages = async (\n payload: AnthropicMessagesPayload,\n account?: AccountContext,\n options?: {\n anthropicBetaHeader?: string\n upstreamRequestId?: string\n },\n): Promise<CreateMessagesReturn> => {\n const ctx = account ?? accountFromState()\n if (!ctx.copilotToken) throw new Error(\"Copilot token not found\")\n\n const enableVision = payload.messages.some(\n (message) =>\n Array.isArray(message.content)\n && message.content.some((block) => block.type === \"image\"),\n )\n\n const initiator = getMessagesInitiator(payload)\n\n const headers: Record<string, string> = {\n ...copilotHeaders(ctx, enableVision, options?.upstreamRequestId),\n \"X-Initiator\": initiator,\n }\n\n if (options?.anthropicBetaHeader) {\n headers[\"anthropic-beta\"] = options.anthropicBetaHeader\n } else if (payload.thinking?.budget_tokens) {\n headers[\"anthropic-beta\"] = \"interleaved-thinking-2025-05-14\"\n }\n\n const response = await fetch(`${copilotBaseUrl(ctx)}/v1/messages`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n consola.error(\"Failed to create messages\", response)\n throw new HTTPError(\"Failed to create messages\", response)\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as AnthropicResponse\n}\n","import {\n type ChatCompletionChunk,\n type Choice,\n type Delta,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicStreamEventData,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport { THINKING_TEXT } from \"./non-stream-translation\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\nfunction isToolBlockOpen(state: AnthropicStreamState): boolean {\n if (!state.contentBlockOpen) {\n return false\n }\n // Check if the current block index corresponds to any known tool call\n return Object.values(state.toolCalls).some(\n (tc) => tc.anthropicBlockIndex === state.contentBlockIndex,\n )\n}\n\nexport function translateChunkToAnthropicEvents(\n chunk: ChatCompletionChunk,\n state: AnthropicStreamState,\n): Array<AnthropicStreamEventData> {\n const events: Array<AnthropicStreamEventData> = []\n\n if (chunk.choices.length === 0) {\n return events\n }\n\n const choice = chunk.choices[0]\n const { delta } = choice\n\n handleMessageStart(state, events, chunk)\n\n handleThinkingText(delta, state, events)\n\n handleContent(delta, state, events)\n\n handleToolCalls(delta, state, events)\n\n handleFinish(choice, state, { events, chunk })\n\n return events\n}\n\nfunction handleFinish(\n choice: Choice,\n state: AnthropicStreamState,\n context: {\n events: Array<AnthropicStreamEventData>\n chunk: ChatCompletionChunk\n },\n) {\n const { events, chunk } = context\n if (choice.finish_reason && choice.finish_reason.length > 0) {\n if (state.contentBlockOpen) {\n const toolBlockOpen = isToolBlockOpen(state)\n context.events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockOpen = false\n state.contentBlockIndex++\n if (!toolBlockOpen) {\n handleReasoningOpaque(choice.delta, events, state)\n }\n }\n\n events.push(\n {\n type: \"message_delta\",\n delta: {\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\n stop_sequence: null,\n },\n usage: {\n input_tokens:\n (chunk.usage?.prompt_tokens ?? 0)\n - (chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: chunk.usage?.completion_tokens ?? 0,\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n {\n type: \"message_stop\",\n },\n )\n }\n}\n\nfunction handleToolCalls(\n delta: Delta,\n state: AnthropicStreamState,\n events: Array<AnthropicStreamEventData>,\n) {\n if (delta.tool_calls && delta.tool_calls.length > 0) {\n closeThinkingBlockIfOpen(state, events)\n\n handleReasoningOpaqueInToolCalls(state, events, delta)\n\n for (const toolCall of delta.tool_calls) {\n if (toolCall.id && toolCall.function?.name) {\n // New tool call starting.\n if (state.contentBlockOpen) {\n // Close any previously open block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n const anthropicBlockIndex = state.contentBlockIndex\n state.toolCalls[toolCall.index] = {\n id: toolCall.id,\n name: toolCall.function.name,\n anthropicBlockIndex,\n }\n\n events.push({\n type: \"content_block_start\",\n index: anthropicBlockIndex,\n content_block: {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: {},\n },\n })\n state.contentBlockOpen = true\n }\n\n if (toolCall.function?.arguments) {\n const toolCallInfo = state.toolCalls[toolCall.index]\n // Tool call can still be empty\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (toolCallInfo) {\n events.push({\n type: \"content_block_delta\",\n index: toolCallInfo.anthropicBlockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: toolCall.function.arguments,\n },\n })\n }\n }\n }\n }\n}\n\nfunction handleReasoningOpaqueInToolCalls(\n state: AnthropicStreamState,\n events: Array<AnthropicStreamEventData>,\n delta: Delta,\n) {\n if (state.contentBlockOpen && !isToolBlockOpen(state)) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n handleReasoningOpaque(delta, events, state)\n}\n\nfunction handleContent(\n delta: Delta,\n state: AnthropicStreamState,\n events: Array<AnthropicStreamEventData>,\n) {\n if (delta.content && delta.content.length > 0) {\n closeThinkingBlockIfOpen(state, events)\n\n if (isToolBlockOpen(state)) {\n // A tool block was open, so close it before starting a text block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n if (!state.contentBlockOpen) {\n events.push({\n type: \"content_block_start\",\n index: state.contentBlockIndex,\n content_block: {\n type: \"text\",\n text: \"\",\n },\n })\n state.contentBlockOpen = true\n }\n\n events.push({\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"text_delta\",\n text: delta.content,\n },\n })\n }\n\n // handle for claude model\n if (\n delta.content === \"\"\n && delta.reasoning_opaque\n && delta.reasoning_opaque.length > 0\n && state.thinkingBlockOpen\n ) {\n events.push(\n {\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"signature_delta\",\n signature: delta.reasoning_opaque,\n },\n },\n {\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n },\n )\n state.contentBlockIndex++\n state.thinkingBlockOpen = false\n }\n}\n\nfunction handleMessageStart(\n state: AnthropicStreamState,\n events: Array<AnthropicStreamEventData>,\n chunk: ChatCompletionChunk,\n) {\n if (!state.messageStartSent) {\n const cachedTokens = chunk.usage?.prompt_tokens_details?.cached_tokens\n const upstreamPromptTokens = chunk.usage?.prompt_tokens\n const historicalInputTokens = state.historicalInputTokens\n const historicalOutputTokens = state.historicalOutputTokens ?? 0\n const historicalTotalTokens =\n historicalInputTokens !== undefined ?\n historicalInputTokens + historicalOutputTokens\n : undefined\n const inputTokens =\n upstreamPromptTokens !== undefined ?\n upstreamPromptTokens - (cachedTokens ?? 0)\n : (historicalTotalTokens ?? state.estimatedInputTokens ?? 0)\n const cacheReadTokens =\n upstreamPromptTokens !== undefined ? cachedTokens : (\n state.historicalCachedInputTokens\n )\n\n events.push({\n type: \"message_start\",\n message: {\n id: chunk.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: chunk.model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens: inputTokens,\n output_tokens: 0, // Will be updated in message_delta when finished\n ...(cacheReadTokens !== undefined && {\n cache_read_input_tokens: cacheReadTokens,\n }),\n },\n },\n })\n state.messageStartSent = true\n }\n}\n\nfunction handleReasoningOpaque(\n delta: Delta,\n events: Array<AnthropicStreamEventData>,\n state: AnthropicStreamState,\n) {\n if (delta.reasoning_opaque && delta.reasoning_opaque.length > 0) {\n events.push(\n {\n type: \"content_block_start\",\n index: state.contentBlockIndex,\n content_block: {\n type: \"thinking\",\n thinking: \"\",\n },\n },\n {\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"thinking_delta\",\n thinking: THINKING_TEXT, // Compatible with opencode, it will filter out blocks where the thinking text is empty, so we add a default thinking text here\n },\n },\n {\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"signature_delta\",\n signature: delta.reasoning_opaque,\n },\n },\n {\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n },\n )\n state.contentBlockIndex++\n }\n}\n\nfunction handleThinkingText(\n delta: Delta,\n state: AnthropicStreamState,\n events: Array<AnthropicStreamEventData>,\n) {\n if (delta.reasoning_text && delta.reasoning_text.length > 0) {\n // compatible with copilot API returning content->reasoning_text->reasoning_opaque in different deltas\n // this is an extremely abnormal situation, probably a server-side bug\n // only occurs in the claude model, with a very low probability of occurrence\n if (state.contentBlockOpen) {\n delta.content = delta.reasoning_text\n delta.reasoning_text = undefined\n return\n }\n\n if (!state.thinkingBlockOpen) {\n events.push({\n type: \"content_block_start\",\n index: state.contentBlockIndex,\n content_block: {\n type: \"thinking\",\n thinking: \"\",\n },\n })\n state.thinkingBlockOpen = true\n }\n\n events.push({\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"thinking_delta\",\n thinking: delta.reasoning_text,\n },\n })\n }\n}\n\nfunction closeThinkingBlockIfOpen(\n state: AnthropicStreamState,\n events: Array<AnthropicStreamEventData>,\n): void {\n if (state.thinkingBlockOpen) {\n events.push(\n {\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"signature_delta\",\n signature: \"\",\n },\n },\n {\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n },\n )\n state.contentBlockIndex++\n state.thinkingBlockOpen = false\n }\n}\n\nexport function translateErrorToAnthropicErrorEvent(): AnthropicStreamEventData {\n return {\n type: \"error\",\n error: {\n type: \"api_error\",\n message: \"An unexpected error occurred during streaming.\",\n },\n }\n}\n","/* eslint-disable max-lines */\nimport type { Context } from \"hono\"\n\nimport { streamSSE } from \"hono/streaming\"\nimport { randomUUID } from \"node:crypto\"\n\nimport type { AccountRuntime } from \"~/lib/types/account\"\nimport type { Model } from \"~/services/copilot/get-models\"\n\nimport { accountsManager } from \"~/lib/accounts-manager\"\nimport { awaitApproval } from \"~/lib/approval\"\nimport { getSmallModel, shouldCompactUseSmallModel } from \"~/lib/config\"\nimport {\n computeDiff,\n extractErrorDetails,\n toAccountContext,\n} from \"~/lib/handler-utils\"\nimport { createHandlerLogger } from \"~/lib/logger\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport {\n extractResponsesUsageFromResult,\n extractResponsesUsageFromStreamEvent,\n getClientIpInfo,\n getRequestHistoryStore,\n normalizeChatCompletionsUsage,\n normalizeMessagesUsage,\n type NormalizedUsage,\n} from \"~/lib/request-history\"\nimport { state } from \"~/lib/state\"\nimport {\n buildErrorEvent,\n createResponsesStreamState,\n translateResponsesStreamEvent,\n} from \"~/routes/messages/responses-stream-translation\"\nimport {\n parseUserId,\n translateAnthropicMessagesToResponsesPayload,\n translateResponsesResultToAnthropic,\n} from \"~/routes/messages/responses-translation\"\nimport { getResponsesRequestOptions } from \"~/routes/responses/utils\"\nimport {\n createChatCompletions,\n getChatInitiator,\n type ChatCompletionChunk,\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n} from \"~/services/copilot/create-chat-completions\"\nimport {\n createMessages,\n getMessagesInitiator,\n} from \"~/services/copilot/create-messages\"\nimport {\n createResponses,\n type ResponsesResult,\n type ResponseStreamEvent,\n} from \"~/services/copilot/create-responses\"\n\nimport {\n type AnthropicMessagesPayload,\n type AnthropicResponse,\n type AnthropicStreamEventData,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport {\n translateToAnthropic,\n translateToOpenAI,\n} from \"./non-stream-translation\"\nimport { translateChunkToAnthropicEvents } from \"./stream-translation\"\nimport {\n estimateInputTokens,\n handleSelectionFailure,\n isWarmupProbeRequest,\n maybeBlockOriginalModelName,\n mergeToolResultForClaude,\n} from \"./utils\"\n\nconst logger = createHandlerLogger(\"messages-handler\")\n\nconst CHAT_COMPLETIONS_ENDPOINT = \"/chat/completions\"\nconst RESPONSES_ENDPOINT = \"/responses\"\nconst MESSAGES_ENDPOINT = \"/v1/messages\"\n\nconst compactSystemPromptStart =\n \"You are a helpful AI assistant tasked with summarizing conversations\"\n\ntype AccountSelection = Awaited<\n ReturnType<(typeof accountsManager)[\"selectAccountForRequest\"]>\n>\ntype AccountSelectionOk = Extract<AccountSelection, { ok: true }>\n\ntype InstrumentationContext = {\n store: ReturnType<typeof getRequestHistoryStore>\n requestId: string\n startedAtMs: number\n\n method: string\n path: string\n\n clientIp?: string\n clientIpSource?: string\n userAgent?: string\n\n userId?: string\n safetyIdentifier?: string\n promptCacheKey?: string\n initiator?: \"agent\" | \"user\"\n upstreamRequestId?: string\n\n clientModel: string\n\n account: AccountRuntime\n reservation: AccountSelectionOk[\"reservation\"]\n upstreamModel: string\n upstreamEndpoint: string\n costUnits: number\n\n premiumRemainingBefore?: number\n premiumUnlimitedBefore?: boolean\n}\n\n// eslint-disable-next-line max-lines-per-function\nexport async function handleCompletion(c: Context) {\n await checkRateLimit(state)\n const store = getRequestHistoryStore()\n const requestId = randomUUID()\n const startedAtMs = Date.now()\n const method = c.req.raw.method\n const path = new URL(c.req.url, \"http://local\").pathname\n const { ip: clientIp, source: clientIpSource } = getClientIpInfo(c)\n const userAgent = c.req.header(\"user-agent\") ?? undefined\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n logger.debug(\"Anthropic request payload:\", JSON.stringify(anthropicPayload))\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n const isCompact = isCompactRequest(anthropicPayload)\n\n // Fix warmup probe: force small model for Claude Code warmup requests (CLAUDE_CODE_SUBAGENT_MODEL also works).\n if (anthropicBeta && isWarmupProbeRequest(anthropicPayload)) {\n anthropicPayload.model = getSmallModel()\n }\n\n if (isCompact) {\n logger.debug(\"Is compact request:\", isCompact)\n if (shouldCompactUseSmallModel()) {\n anthropicPayload.model = getSmallModel()\n }\n } else {\n // Merge tool_result and text blocks into tool_result to avoid consuming premium requests\n // (caused by skill invocations, edit hooks, plan or to do reminders)\n // e.g. {\"role\":\"user\",\"content\":[{\"type\":\"tool_result\",\"content\":\"Launching skill: xxx\"},{\"type\":\"text\",\"text\":\"xxx\"}]}\n // not only for claude, but also for opencode\n mergeToolResultForClaude(anthropicPayload)\n }\n\n const clientModel = anthropicPayload.model\n const streamRequested = Boolean(anthropicPayload.stream)\n const rawUserId = anthropicPayload.metadata?.user_id\n const userId = typeof rawUserId === \"string\" ? rawUserId : undefined\n const { safetyIdentifier, promptCacheKey } = parseUserId(userId)\n const normalizedSafetyIdentifier = safetyIdentifier ?? undefined\n const normalizedPromptCacheKey = promptCacheKey ?? undefined\n const blockedResponse = maybeBlockOriginalModelName({\n c,\n store,\n requestId,\n startedAtMs,\n method,\n path,\n streamRequested,\n clientModel,\n clientIp,\n clientIpSource,\n userAgent,\n userId,\n safetyIdentifier: normalizedSafetyIdentifier,\n promptCacheKey: normalizedPromptCacheKey,\n })\n if (blockedResponse) return blockedResponse\n\n const openAIPayload = translateToOpenAI(anthropicPayload)\n const fallbackInitiator = getChatInitiator(openAIPayload.messages)\n\n const selection = await accountsManager.selectAccountForRequest([\n {\n modelId: clientModel,\n endpoint: MESSAGES_ENDPOINT,\n },\n {\n modelId: clientModel,\n endpoint: RESPONSES_ENDPOINT,\n },\n {\n modelId: openAIPayload.model,\n endpoint: CHAT_COMPLETIONS_ENDPOINT,\n },\n ])\n if (!selection.ok) {\n return handleSelectionFailure({\n c,\n store,\n requestId,\n startedAtMs,\n method,\n path,\n streamRequested,\n clientModel,\n clientIp,\n clientIpSource,\n userAgent,\n userId,\n safetyIdentifier: normalizedSafetyIdentifier,\n promptCacheKey: normalizedPromptCacheKey,\n initiator: fallbackInitiator,\n selection,\n })\n }\n const { account, reservation, selectedModel, endpoint, costUnits } = selection\n openAIPayload.model = selectedModel.id\n const premiumRemainingBefore = account.premiumRemaining\n const premiumUnlimitedBefore = account.unlimited\n if (state.manualApprove) {\n await awaitApproval()\n }\n const instr: InstrumentationContext = {\n store,\n requestId,\n startedAtMs,\n method,\n path,\n clientIp,\n clientIpSource,\n userAgent,\n userId,\n safetyIdentifier: normalizedSafetyIdentifier,\n promptCacheKey: normalizedPromptCacheKey,\n clientModel,\n account,\n reservation,\n upstreamEndpoint: endpoint,\n upstreamModel: selectedModel.id,\n costUnits,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n }\n if (endpoint === MESSAGES_ENDPOINT) {\n return await handleWithMessagesApi({\n c,\n anthropicPayload,\n anthropicBetaHeader: anthropicBeta ?? undefined,\n instr,\n })\n }\n if (endpoint === RESPONSES_ENDPOINT) {\n return await handleWithResponsesApi({\n c,\n anthropicPayload,\n openAIPayload,\n selectedModel,\n instr,\n })\n }\n\n return await handleWithChatCompletions({\n c,\n openAIPayload,\n selectedModel,\n instr,\n })\n}\n\nconst handleWithChatCompletions = async (params: {\n c: Context\n openAIPayload: ChatCompletionsPayload\n selectedModel: Model\n instr: InstrumentationContext\n}): Promise<Response> => {\n const { c, openAIPayload, selectedModel, instr } = params\n logger.debug(\n \"Translated OpenAI request payload:\",\n JSON.stringify(openAIPayload),\n )\n\n const ctx = toAccountContext(instr.account)\n const initiator = getChatInitiator(openAIPayload.messages)\n const upstreamRequestId = randomUUID()\n\n instr.initiator = initiator\n instr.upstreamRequestId = upstreamRequestId\n\n let response: ChatCompletionsResult\n\n try {\n response = await createChatCompletions(openAIPayload, ctx, {\n upstreamRequestId,\n })\n } catch (error) {\n return await handleChatCompletionsCreateError({\n error,\n instr,\n stream: Boolean(openAIPayload.stream),\n })\n }\n\n if (isNonStreaming(response)) {\n return handleChatCompletionsNonStreaming({\n c,\n response,\n instr,\n })\n }\n\n logger.debug(\"Streaming response from Copilot\")\n\n const estimatedInputTokens = await estimateInputTokens(\n openAIPayload,\n selectedModel,\n logger,\n )\n\n const historicalUsage =\n instr.promptCacheKey && instr.safetyIdentifier ?\n instr.store.getLastCompletedUsageBySession({\n promptCacheKey: instr.promptCacheKey,\n safetyIdentifier: instr.safetyIdentifier,\n clientModel: instr.clientModel,\n })\n : null\n\n return streamSSE(c, (stream) =>\n streamChatCompletionsAndLog({\n stream,\n response,\n instr,\n estimatedInputTokens,\n historicalUsage: historicalUsage ?? undefined,\n }),\n )\n}\n\nconst handleWithResponsesApi = async (params: {\n c: Context\n anthropicPayload: AnthropicMessagesPayload\n openAIPayload: ChatCompletionsPayload\n selectedModel: Model\n instr: InstrumentationContext\n}): Promise<Response> => {\n const { c, anthropicPayload, openAIPayload, selectedModel, instr } = params\n const responsesPayload = translateAnthropicMessagesToResponsesPayload(\n anthropicPayload,\n selectedModel.id,\n )\n logger.debug(\n \"Translated Responses payload:\",\n JSON.stringify(responsesPayload),\n )\n\n const { vision, initiator } = getResponsesRequestOptions(responsesPayload)\n const ctx = toAccountContext(instr.account)\n const upstreamRequestId = randomUUID()\n\n instr.initiator = initiator\n instr.upstreamRequestId = upstreamRequestId\n\n let response: Awaited<ReturnType<typeof createResponses>>\n\n try {\n response = await createResponses(\n responsesPayload,\n {\n vision,\n initiator,\n upstreamRequestId,\n },\n ctx,\n )\n } catch (error) {\n return await handleResponsesCreateError({\n error,\n instr,\n stream: Boolean(responsesPayload.stream),\n })\n }\n\n if (responsesPayload.stream && isAsyncIterable(response)) {\n logger.debug(\"Streaming response from Copilot (Responses API)\")\n\n const estimatedInputTokens = await estimateInputTokens(\n openAIPayload,\n selectedModel,\n logger,\n )\n\n const historicalUsage =\n instr.promptCacheKey && instr.safetyIdentifier ?\n instr.store.getLastCompletedUsageBySession({\n promptCacheKey: instr.promptCacheKey,\n safetyIdentifier: instr.safetyIdentifier,\n clientModel: instr.clientModel,\n })\n : null\n\n return streamSSE(c, (stream) =>\n streamResponsesAndLog({\n stream,\n response,\n instr,\n estimatedInputTokens,\n historicalUsage: historicalUsage ?? undefined,\n }),\n )\n }\n\n return handleResponsesNonStreaming({\n c,\n result: response as ResponsesResult,\n instr,\n })\n}\n\ntype Store = ReturnType<typeof getRequestHistoryStore>\n\ntype RequestLogInsert = Parameters<Store[\"insert\"]>[0]\n\ntype StreamSseStream = Parameters<Parameters<typeof streamSSE>[1]>[0]\n\ntype ChatCompletionsResult = Awaited<ReturnType<typeof createChatCompletions>>\n\ntype ChatCompletionsStream = Exclude<\n ChatCompletionsResult,\n ChatCompletionResponse\n>\n\ntype MessagesResult = Awaited<ReturnType<typeof createMessages>>\n\nfunction insertRequestLog(\n instr: InstrumentationContext,\n record: Omit<\n RequestLogInsert,\n | \"requestId\"\n | \"startedAtMs\"\n | \"method\"\n | \"path\"\n | \"clientIp\"\n | \"clientIpSource\"\n | \"userAgent\"\n | \"clientModel\"\n | \"upstreamEndpoint\"\n | \"accountId\"\n | \"accountType\"\n | \"costUnits\"\n | \"upstreamModel\"\n | \"premiumRemainingBefore\"\n | \"premiumUnlimitedBefore\"\n >,\n): void {\n const {\n store,\n requestId,\n startedAtMs,\n method,\n path,\n clientIp,\n clientIpSource,\n userAgent,\n clientModel,\n account,\n upstreamEndpoint,\n upstreamModel,\n costUnits,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n } = instr\n\n store.insert({\n requestId,\n startedAtMs,\n method,\n path,\n clientIp,\n clientIpSource,\n userAgent,\n userId: instr.userId,\n safetyIdentifier: instr.safetyIdentifier,\n promptCacheKey: instr.promptCacheKey,\n initiator: instr.initiator,\n upstreamRequestId: instr.upstreamRequestId,\n clientModel,\n upstreamEndpoint,\n accountId: account.id,\n accountType: account.accountType,\n costUnits,\n upstreamModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n ...record,\n })\n}\n\nasync function finalizeQuotaAndGetPremiumSnapshot(\n instr: InstrumentationContext,\n): Promise<{\n premiumRemainingAfter: number | undefined\n premiumUnlimitedAfter: boolean | undefined\n premiumRemainingDiff: number | undefined\n}> {\n await accountsManager.finalizeQuota(instr.account, instr.reservation)\n\n const premiumRemainingAfter = instr.account.premiumRemaining\n const premiumUnlimitedAfter = instr.account.unlimited\n\n return {\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff: computeDiff(\n instr.premiumRemainingBefore,\n premiumRemainingAfter,\n ),\n }\n}\n\nasync function handleChatCompletionsCreateError(params: {\n error: unknown\n instr: InstrumentationContext\n stream: boolean\n}): Promise<never> {\n const { error, instr, stream } = params\n\n const finishedAtMs = Date.now()\n const details = extractErrorDetails(error)\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(instr.account.id, \"Unauthorized (401)\")\n }\n\n const { premiumRemainingAfter, premiumUnlimitedAfter, premiumRemainingDiff } =\n await finalizeQuotaAndGetPremiumSnapshot(instr)\n\n insertRequestLog(instr, {\n finishedAtMs,\n durationMs: finishedAtMs - instr.startedAtMs,\n stream,\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n httpStatus: details.httpStatus,\n errorName: details.errorName,\n errorStatus: details.errorStatus,\n errorMessage: details.errorMessage,\n })\n\n throw error\n}\n\nasync function handleChatCompletionsNonStreaming(params: {\n c: Context\n response: ChatCompletionResponse\n instr: InstrumentationContext\n}): Promise<Response> {\n const { c, response, instr } = params\n\n let httpStatus = 200\n const usage: NormalizedUsage = normalizeChatCompletionsUsage(response.usage)\n\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n const finishedAtMs = Date.now()\n\n try {\n logger.debug(\n \"Non-streaming response from Copilot:\",\n JSON.stringify(response),\n )\n\n const anthropicResponse = translateToAnthropic(response)\n logger.debug(\n \"Translated Anthropic response:\",\n JSON.stringify(anthropicResponse),\n )\n\n return c.json(anthropicResponse)\n } catch (error) {\n const details = extractErrorDetails(error)\n\n httpStatus = details.httpStatus\n\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(instr.account.id, \"Unauthorized (401)\")\n }\n\n throw error\n } finally {\n const {\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n } = await finalizeQuotaAndGetPremiumSnapshot(instr)\n\n insertRequestLog(instr, {\n finishedAtMs,\n durationMs: finishedAtMs - instr.startedAtMs,\n stream: false,\n ...usage,\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n httpStatus,\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nasync function streamChatCompletionsAndLog(params: {\n stream: StreamSseStream\n response: ChatCompletionsStream\n instr: InstrumentationContext\n estimatedInputTokens?: number\n historicalUsage?: NormalizedUsage\n}): Promise<void> {\n const { stream, response, instr, estimatedInputTokens, historicalUsage } =\n params\n\n let ttfbMs: number | undefined\n let lastUsage: NormalizedUsage = {}\n\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n const streamState: AnthropicStreamState = {\n messageStartSent: false,\n contentBlockIndex: 0,\n contentBlockOpen: false,\n toolCalls: {},\n thinkingBlockOpen: false,\n estimatedInputTokens,\n historicalInputTokens: historicalUsage?.tokensInput,\n historicalOutputTokens: historicalUsage?.tokensOutput,\n historicalCachedInputTokens: historicalUsage?.tokensCachedInput,\n }\n\n try {\n for await (const rawEvent of response) {\n if (ttfbMs === undefined) {\n ttfbMs = Date.now() - instr.startedAtMs\n }\n\n logger.debug(\"Copilot raw stream event:\", JSON.stringify(rawEvent))\n\n const { data: rawData } = rawEvent as {\n data?: string | Promise<string>\n }\n const data = typeof rawData === \"string\" ? rawData : await rawData\n\n if (data === \"[DONE]\") {\n break\n }\n\n if (!data) {\n continue\n }\n\n const chunk = JSON.parse(data) as ChatCompletionChunk\n if (chunk.usage) {\n lastUsage = normalizeChatCompletionsUsage(chunk.usage)\n }\n\n const events = translateChunkToAnthropicEvents(chunk, streamState)\n for (const event of events) {\n logger.debug(\"Translated Anthropic event:\", JSON.stringify(event))\n\n await stream.writeSSE({\n event: event.type,\n data: JSON.stringify(event),\n })\n }\n }\n } catch (error) {\n const details = extractErrorDetails(error)\n\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n logger.warn(\"Streaming error:\", error)\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(instr.account.id, \"Unauthorized (401)\")\n }\n } finally {\n const finishedAtMs = Date.now()\n\n const {\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n } = await finalizeQuotaAndGetPremiumSnapshot(instr)\n\n insertRequestLog(instr, {\n finishedAtMs,\n durationMs: finishedAtMs - instr.startedAtMs,\n ttfbMs,\n stream: true,\n ...lastUsage,\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n httpStatus: errorStatus ?? (errorName ? 500 : 200),\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nasync function handleResponsesCreateError(params: {\n error: unknown\n instr: InstrumentationContext\n stream: boolean\n}): Promise<never> {\n const { error, instr, stream } = params\n\n const finishedAtMs = Date.now()\n const details = extractErrorDetails(error)\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(instr.account.id, \"Unauthorized (401)\")\n }\n\n const { premiumRemainingAfter, premiumUnlimitedAfter, premiumRemainingDiff } =\n await finalizeQuotaAndGetPremiumSnapshot(instr)\n\n insertRequestLog(instr, {\n finishedAtMs,\n durationMs: finishedAtMs - instr.startedAtMs,\n stream,\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n httpStatus: details.httpStatus,\n errorName: details.errorName,\n errorStatus: details.errorStatus,\n errorMessage: details.errorMessage,\n })\n\n throw error\n}\n\nasync function handleResponsesNonStreaming(params: {\n c: Context\n result: ResponsesResult\n instr: InstrumentationContext\n}): Promise<Response> {\n const { c, result, instr } = params\n\n let httpStatus = 200\n let usage: NormalizedUsage = {}\n\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n const finishedAtMs = Date.now()\n\n try {\n usage = extractResponsesUsageFromResult(result)\n\n logger.debug(\n \"Non-streaming Responses result:\",\n JSON.stringify(result).slice(-400),\n )\n\n const anthropicResponse = translateResponsesResultToAnthropic(result)\n logger.debug(\n \"Translated Anthropic response:\",\n JSON.stringify(anthropicResponse),\n )\n\n return c.json(anthropicResponse)\n } catch (error) {\n const details = extractErrorDetails(error)\n\n httpStatus = details.httpStatus\n\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(instr.account.id, \"Unauthorized (401)\")\n }\n\n throw error\n } finally {\n const {\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n } = await finalizeQuotaAndGetPremiumSnapshot(instr)\n\n insertRequestLog(instr, {\n finishedAtMs,\n durationMs: finishedAtMs - instr.startedAtMs,\n stream: false,\n ...usage,\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n httpStatus,\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nasync function ensureResponsesStreamCompleted(params: {\n stream: StreamSseStream\n streamState: ReturnType<typeof createResponsesStreamState>\n setStreamError: (name: string, message: string) => void\n}): Promise<void> {\n const { stream, streamState, setStreamError } = params\n\n if (streamState.messageCompleted) {\n return\n }\n\n logger.warn(\"Responses stream ended without completion; sending error event\")\n\n const msg = \"Responses stream ended without completion\"\n const errorEvent = buildErrorEvent(msg)\n\n setStreamError(\"StreamIncomplete\", msg)\n\n await stream.writeSSE({\n event: errorEvent.type,\n data: JSON.stringify(errorEvent),\n })\n}\n\nasync function streamResponsesAndLog(params: {\n stream: StreamSseStream\n response: AsyncIterable<unknown>\n instr: InstrumentationContext\n estimatedInputTokens?: number\n historicalUsage?: NormalizedUsage\n}): Promise<void> {\n const { stream, response, instr, estimatedInputTokens, historicalUsage } =\n params\n\n let ttfbMs: number | undefined\n let lastUsage: NormalizedUsage = {}\n\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n const streamState = createResponsesStreamState()\n streamState.estimatedInputTokens = estimatedInputTokens\n streamState.historicalInputTokens = historicalUsage?.tokensInput\n streamState.historicalOutputTokens = historicalUsage?.tokensOutput\n streamState.historicalCachedInputTokens = historicalUsage?.tokensCachedInput\n\n try {\n for await (const chunk of response) {\n if (ttfbMs === undefined) {\n ttfbMs = Date.now() - instr.startedAtMs\n }\n\n const eventName = (chunk as { event?: string }).event\n if (eventName === \"ping\") {\n await stream.writeSSE({ event: \"ping\", data: \"\" })\n continue\n }\n\n const data = (chunk as { data?: string }).data\n if (!data) {\n continue\n }\n\n logger.debug(\"Responses raw stream event:\", data)\n\n const parsed = JSON.parse(data) as ResponseStreamEvent\n const u = extractResponsesUsageFromStreamEvent(parsed)\n if (u.usageJson) {\n lastUsage = u\n }\n\n const events = translateResponsesStreamEvent(parsed, streamState)\n for (const event of events) {\n const eventData = JSON.stringify(event)\n logger.debug(\"Translated Anthropic event:\", eventData)\n await stream.writeSSE({\n event: event.type,\n data: eventData,\n })\n }\n\n if (streamState.messageCompleted) {\n logger.debug(\"Message completed, ending stream\")\n break\n }\n }\n\n await ensureResponsesStreamCompleted({\n stream,\n streamState,\n setStreamError: (name, message) => {\n errorName = name\n errorMessage = message\n },\n })\n } catch (error) {\n const details = extractErrorDetails(error)\n\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n logger.warn(\"Streaming error:\", error)\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(instr.account.id, \"Unauthorized (401)\")\n }\n } finally {\n const finishedAtMs = Date.now()\n\n const {\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n } = await finalizeQuotaAndGetPremiumSnapshot(instr)\n\n insertRequestLog(instr, {\n finishedAtMs,\n durationMs: finishedAtMs - instr.startedAtMs,\n ttfbMs,\n stream: true,\n ...lastUsage,\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n httpStatus: errorStatus ?? (errorName ? 500 : 200),\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nasync function handleMessagesCreateError(params: {\n error: unknown\n instr: InstrumentationContext\n stream: boolean\n}): Promise<never> {\n const { error, instr, stream } = params\n\n const finishedAtMs = Date.now()\n const details = extractErrorDetails(error)\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(instr.account.id, \"Unauthorized (401)\")\n }\n\n const { premiumRemainingAfter, premiumUnlimitedAfter, premiumRemainingDiff } =\n await finalizeQuotaAndGetPremiumSnapshot(instr)\n\n insertRequestLog(instr, {\n finishedAtMs,\n durationMs: finishedAtMs - instr.startedAtMs,\n stream,\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n httpStatus: details.httpStatus,\n errorName: details.errorName,\n errorStatus: details.errorStatus,\n errorMessage: details.errorMessage,\n })\n\n throw error\n}\n\nasync function handleMessagesNonStreaming(params: {\n c: Context\n response: AnthropicResponse\n instr: InstrumentationContext\n}): Promise<Response> {\n const { c, response, instr } = params\n\n let httpStatus = 200\n const usage = normalizeMessagesUsage(response.usage)\n\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n const finishedAtMs = Date.now()\n\n try {\n logger.debug(\n \"Non-streaming Messages result:\",\n JSON.stringify(response).slice(-400),\n )\n return c.json(response)\n } catch (error) {\n const details = extractErrorDetails(error)\n\n httpStatus = details.httpStatus\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(instr.account.id, \"Unauthorized (401)\")\n }\n\n throw error\n } finally {\n const {\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n } = await finalizeQuotaAndGetPremiumSnapshot(instr)\n\n insertRequestLog(instr, {\n finishedAtMs,\n durationMs: finishedAtMs - instr.startedAtMs,\n stream: false,\n ...usage,\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n httpStatus,\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nconst parseMessagesStreamUsage = (data: string): NormalizedUsage | null => {\n if (!data) return null\n\n try {\n const parsed = JSON.parse(data) as AnthropicStreamEventData\n if (parsed.type !== \"message_delta\" || !parsed.usage) {\n return null\n }\n\n return normalizeMessagesUsage(parsed.usage)\n } catch (error) {\n logger.warn(\"Failed to parse messages stream event\", error)\n return null\n }\n}\n\nasync function streamMessagesAndLog(params: {\n stream: StreamSseStream\n response: AsyncIterable<unknown>\n instr: InstrumentationContext\n}): Promise<void> {\n const { stream, response, instr } = params\n\n let ttfbMs: number | undefined\n let lastUsage: NormalizedUsage = {}\n\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n try {\n for await (const rawEvent of response) {\n if (ttfbMs === undefined) {\n ttfbMs = Date.now() - instr.startedAtMs\n }\n\n const eventNameRaw = (rawEvent as { event?: string }).event\n const eventName =\n typeof eventNameRaw === \"string\" && eventNameRaw.length > 0 ?\n eventNameRaw\n : \"message\"\n const data = (rawEvent as { data?: string }).data ?? \"\"\n logger.debug(\"Messages raw stream event:\", data)\n\n const usage = parseMessagesStreamUsage(data)\n if (usage) {\n lastUsage = usage\n }\n\n await stream.writeSSE({\n event: eventName,\n data,\n })\n }\n } catch (error) {\n const details = extractErrorDetails(error)\n\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n logger.warn(\"Streaming error:\", error)\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(instr.account.id, \"Unauthorized (401)\")\n }\n } finally {\n const finishedAtMs = Date.now()\n\n const {\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n } = await finalizeQuotaAndGetPremiumSnapshot(instr)\n\n insertRequestLog(instr, {\n finishedAtMs,\n durationMs: finishedAtMs - instr.startedAtMs,\n ttfbMs,\n stream: true,\n ...lastUsage,\n premiumRemainingAfter,\n premiumUnlimitedAfter,\n premiumRemainingDiff,\n httpStatus: errorStatus ?? (errorName ? 500 : 200),\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nconst handleWithMessagesApi = async (params: {\n c: Context\n anthropicPayload: AnthropicMessagesPayload\n anthropicBetaHeader?: string\n instr: InstrumentationContext\n}): Promise<Response> => {\n const { c, anthropicPayload, anthropicBetaHeader, instr } = params\n\n // Pre-request processing: filter thinking blocks for Claude models so only\n // valid thinking blocks are sent to the Copilot Messages API.\n for (const msg of anthropicPayload.messages) {\n if (msg.role === \"assistant\" && Array.isArray(msg.content)) {\n msg.content = msg.content.filter((block) => {\n if (block.type !== \"thinking\") return true\n return (\n block.thinking\n && block.thinking !== \"Thinking...\"\n && block.signature\n && !block.signature.includes(\"@\")\n )\n })\n }\n }\n\n const ctx = toAccountContext(instr.account)\n const upstreamRequestId = randomUUID()\n const initiator = getMessagesInitiator(anthropicPayload)\n\n instr.initiator = initiator\n instr.upstreamRequestId = upstreamRequestId\n\n let response: MessagesResult\n\n try {\n response = await createMessages(anthropicPayload, ctx, {\n anthropicBetaHeader,\n upstreamRequestId,\n })\n } catch (error) {\n return await handleMessagesCreateError({\n error,\n instr,\n stream: Boolean(anthropicPayload.stream),\n })\n }\n\n if (isAsyncIterable(response)) {\n logger.debug(\"Streaming response from Copilot (Messages API)\")\n return streamSSE(c, (stream) =>\n streamMessagesAndLog({\n stream,\n response,\n instr,\n }),\n )\n }\n\n return handleMessagesNonStreaming({\n c,\n response,\n instr,\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n\nconst isAsyncIterable = <T>(value: unknown): value is AsyncIterable<T> =>\n Boolean(value)\n && typeof (value as AsyncIterable<T>)[Symbol.asyncIterator] === \"function\"\n\nconst isCompactRequest = (\n anthropicPayload: AnthropicMessagesPayload,\n): boolean => {\n const system = anthropicPayload.system\n if (typeof system === \"string\") {\n return system.startsWith(compactSystemPromptStart)\n }\n if (!Array.isArray(system)) return false\n\n return system.some(\n (msg) =>\n typeof msg.text === \"string\"\n && msg.text.startsWith(compactSystemPromptStart),\n )\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCountTokens } from \"./count-tokens-handler\"\nimport { handleCompletion } from \"./handler\"\n\nexport const messageRoutes = new Hono()\n\nmessageRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n return await handleCountTokens(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { accountsManager } from \"~/lib/accounts-manager\"\nimport { getAliasTargetSet, getModelAliases } from \"~/lib/config\"\nimport { forwardError } from \"~/lib/error\"\n\nexport const modelRoutes = new Hono()\n\nmodelRoutes.get(\"/\", async (c) => {\n try {\n const accountModels = accountsManager.getFirstAccountModels()\n\n const blockedTargets = getAliasTargetSet()\n const models =\n accountModels?.data\n .filter((model) => !blockedTargets.has(model.id.toLowerCase()))\n .map((model) => ({\n id: model.id,\n object: \"model\",\n type: \"model\",\n created: 0, // No date available from source\n created_at: new Date(0).toISOString(), // No date available from source\n owned_by: model.vendor,\n display_name: model.name,\n })) ?? []\n\n const aliasItems = Object.keys(getModelAliases())\n const aliasModels = aliasItems.map((alias) => ({\n id: alias,\n object: \"model\",\n type: \"model\",\n created: 0,\n created_at: new Date(0).toISOString(),\n owned_by: \"alias\",\n display_name: alias,\n }))\n\n const merged = new Map<string, (typeof models)[number]>()\n for (const model of models) {\n merged.set(model.id, model)\n }\n for (const model of aliasModels) {\n if (!merged.has(model.id)) {\n merged.set(model.id, model)\n }\n }\n\n return c.json({\n object: \"list\",\n data: Array.from(merged.values()),\n has_more: false,\n })\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","/**\n * Stream ID Synchronization for @ai-sdk/openai compatibility\n *\n * Problem: GitHub Copilot's Responses API returns different IDs for the same\n * item in 'added' vs 'done' events. This breaks @ai-sdk/openai which expects\n * consistent IDs across the stream lifecycle.\n *\n * Errors without this fix:\n * - \"activeReasoningPart.summaryParts\" undefined\n * - \"text part not found\"\n *\n * Use case: OpenCode (AI coding assistant) using Codex models (gpt-5.2-codex)\n * via @ai-sdk/openai provider requires the Responses API endpoint.\n */\n\nimport type {\n ResponseOutputItemAddedEvent,\n ResponseOutputItemDoneEvent,\n ResponseStreamEvent,\n} from \"~/services/copilot/create-responses\"\n\ninterface StreamIdTracker {\n outputItems: Map<number, string>\n}\n\nexport const createStreamIdTracker = (): StreamIdTracker => ({\n outputItems: new Map(),\n})\n\nexport const fixStreamIds = (\n data: string,\n event: string | undefined,\n tracker: StreamIdTracker,\n): string => {\n if (!data) return data\n const parsed = JSON.parse(data) as ResponseStreamEvent\n switch (event) {\n case \"response.output_item.added\": {\n return handleOutputItemAdded(\n parsed as ResponseOutputItemAddedEvent,\n tracker,\n )\n }\n case \"response.output_item.done\": {\n return handleOutputItemDone(\n parsed as ResponseOutputItemDoneEvent,\n tracker,\n )\n }\n default: {\n return handleItemId(parsed, tracker)\n }\n }\n}\n\nconst handleOutputItemAdded = (\n parsed: ResponseOutputItemAddedEvent,\n tracker: StreamIdTracker,\n): string => {\n if (!parsed.item.id) {\n let randomSuffix = \"\"\n while (randomSuffix.length < 16) {\n randomSuffix += Math.random().toString(36).slice(2)\n }\n parsed.item.id = `oi_${parsed.output_index}_${randomSuffix.slice(0, 16)}`\n }\n\n const outputIndex = parsed.output_index\n tracker.outputItems.set(outputIndex, parsed.item.id)\n return JSON.stringify(parsed)\n}\n\nconst handleOutputItemDone = (\n parsed: ResponseOutputItemDoneEvent,\n tracker: StreamIdTracker,\n): string => {\n const outputIndex = parsed.output_index\n const originalId = tracker.outputItems.get(outputIndex)\n if (originalId) {\n parsed.item.id = originalId\n }\n return JSON.stringify(parsed)\n}\n\nconst handleItemId = (\n parsed: ResponseStreamEvent & { output_index?: number; item_id?: string },\n tracker: StreamIdTracker,\n): string => {\n const outputIndex = parsed.output_index\n if (outputIndex !== undefined) {\n const itemId = tracker.outputItems.get(outputIndex)\n if (itemId) {\n parsed.item_id = itemId\n }\n }\n return JSON.stringify(parsed)\n}\n","import type { Context } from \"hono\"\n\nimport { streamSSE } from \"hono/streaming\"\nimport { randomUUID } from \"node:crypto\"\n\nimport { accountsManager } from \"~/lib/accounts-manager\"\nimport { awaitApproval } from \"~/lib/approval\"\nimport { getAliasTargetSet, getConfig } from \"~/lib/config\"\nimport {\n computeDiff,\n extractErrorDetails,\n toAccountContext,\n} from \"~/lib/handler-utils\"\nimport { createHandlerLogger } from \"~/lib/logger\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport {\n extractResponsesUsageFromResult,\n extractResponsesUsageFromStreamEvent,\n getClientIpInfo,\n getRequestHistoryStore,\n type NormalizedUsage,\n} from \"~/lib/request-history\"\nimport { state } from \"~/lib/state\"\nimport { parseUserId } from \"~/routes/messages/responses-translation\"\nimport {\n createResponses,\n type ResponsesPayload,\n type ResponsesResult,\n type ResponseStreamEvent,\n} from \"~/services/copilot/create-responses\"\n\nimport { createStreamIdTracker, fixStreamIds } from \"./stream-id-sync\"\nimport { getResponsesRequestOptions } from \"./utils\"\n\nconst logger = createHandlerLogger(\"responses-handler\")\n\nconst RESPONSES_ENDPOINT = \"/responses\"\n\nexport const handleResponses = async (c: Context) => {\n await checkRateLimit(state)\n\n const store = getRequestHistoryStore()\n const request = buildRequestContext(c)\n\n const payload = await c.req.json<ResponsesPayload>()\n const clientModel = payload.model\n logger.debug(\"Responses request payload:\", JSON.stringify(payload))\n\n // Remove web_search tool as it's not supported by GitHub Copilot\n removeWebSearchTool(payload)\n\n const streamRequested = Boolean(payload.stream)\n\n const { initiator: initialInitiator } = getResponsesRequestOptions(payload)\n const userId = (payload.metadata as { user_id?: string } | null | undefined)\n ?.user_id\n const { safetyIdentifier, promptCacheKey } = parseUserId(userId)\n const normalizedSafetyIdentifier = safetyIdentifier ?? undefined\n const normalizedPromptCacheKey = promptCacheKey ?? undefined\n\n request.userId = userId\n request.safetyIdentifier = normalizedSafetyIdentifier\n request.promptCacheKey = normalizedPromptCacheKey\n request.initiator = initialInitiator\n\n const blockedTargets = getAliasTargetSet()\n if (blockedTargets.has(clientModel.toLowerCase())) {\n recordSelectionFailure(store, {\n request,\n stream: streamRequested,\n clientModel,\n reason: \"MODEL_NOT_SUPPORTED\",\n })\n\n return selectionFailureResponse(c, {\n reason: \"MODEL_NOT_SUPPORTED\",\n message:\n \"This model is only available via an alias. Please use the alias model name.\",\n })\n }\n\n const selection = await accountsManager.selectAccountForRequest([\n {\n modelId: clientModel,\n endpoint: RESPONSES_ENDPOINT,\n },\n ])\n\n if (!selection.ok) {\n recordSelectionFailure(store, {\n request,\n stream: streamRequested,\n clientModel,\n reason: selection.reason,\n })\n\n return selectionFailureResponse(c, {\n reason: selection.reason,\n })\n }\n\n const { account, selectedModel } = selection\n\n const upstreamPayload = { ...payload, model: selectedModel.id }\n useFunctionApplyPatch(upstreamPayload)\n\n const premiumRemainingBefore = account.premiumRemaining\n const premiumUnlimitedBefore = account.unlimited\n\n const { vision, initiator } = getResponsesRequestOptions(upstreamPayload)\n request.initiator = initiator\n if (state.manualApprove) await awaitApproval()\n\n const accountCtx = toAccountContext(account)\n const upstreamRequestId = randomUUID()\n request.upstreamRequestId = upstreamRequestId\n\n if (streamRequested) {\n return handleStreamingResponses({\n c,\n store,\n request,\n payload: upstreamPayload,\n selection,\n clientModel,\n accountCtx,\n vision,\n initiator,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n })\n }\n\n return handleNonStreamingResponses({\n c,\n store,\n request,\n payload: upstreamPayload,\n selection,\n clientModel,\n accountCtx,\n vision,\n initiator,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n })\n}\n\ntype AccountSelection = Awaited<\n ReturnType<(typeof accountsManager)[\"selectAccountForRequest\"]>\n>\n\ntype AccountSelectionOk = Extract<AccountSelection, { ok: true }>\n\ntype AccountSelectionErr = Extract<AccountSelection, { ok: false }>\n\ntype RequestContext = {\n requestId: string\n startedAtMs: number\n\n method: string\n path: string\n\n clientIp?: string\n clientIpSource?: string\n userAgent?: string\n\n userId?: string\n safetyIdentifier?: string\n promptCacheKey?: string\n initiator?: \"agent\" | \"user\"\n upstreamRequestId?: string\n}\n\ntype Store = ReturnType<typeof getRequestHistoryStore>\n\ntype RequestLogInsert = Parameters<Store[\"insert\"]>[0]\n\ntype StreamSseStream = Parameters<Parameters<typeof streamSSE>[1]>[0]\n\nfunction buildRequestContext(c: Context): RequestContext {\n const requestId = randomUUID()\n const startedAtMs = Date.now()\n\n const method = c.req.raw.method\n const path = new URL(c.req.url, \"http://local\").pathname\n\n const { ip: clientIp, source: clientIpSource } = getClientIpInfo(c)\n const userAgent = c.req.header(\"user-agent\") ?? undefined\n\n return {\n requestId,\n startedAtMs,\n method,\n path,\n clientIp,\n clientIpSource,\n userAgent,\n }\n}\n\nfunction insertRequestLog(\n store: Store,\n request: RequestContext,\n record: Omit<\n RequestLogInsert,\n | \"requestId\"\n | \"startedAtMs\"\n | \"method\"\n | \"path\"\n | \"clientIp\"\n | \"clientIpSource\"\n | \"userAgent\"\n >,\n): void {\n store.insert({\n requestId: request.requestId,\n startedAtMs: request.startedAtMs,\n method: request.method,\n path: request.path,\n clientIp: request.clientIp,\n clientIpSource: request.clientIpSource,\n userAgent: request.userAgent,\n userId: request.userId,\n safetyIdentifier: request.safetyIdentifier,\n promptCacheKey: request.promptCacheKey,\n initiator: request.initiator,\n upstreamRequestId: request.upstreamRequestId,\n ...record,\n })\n}\n\nfunction recordSelectionFailure(\n store: Store,\n params: {\n request: RequestContext\n stream: boolean\n clientModel: string\n reason: AccountSelectionErr[\"reason\"]\n },\n): void {\n const { request, stream, clientModel, reason } = params\n\n const finishedAtMs = Date.now()\n\n insertRequestLog(store, request, {\n finishedAtMs,\n durationMs: finishedAtMs - request.startedAtMs,\n upstreamEndpoint: RESPONSES_ENDPOINT,\n stream,\n clientModel,\n httpStatus: reason === \"MODEL_NOT_SUPPORTED\" ? 400 : 429,\n selectionFailureReason: reason,\n })\n}\n\nfunction selectionFailureResponse(\n c: Context,\n params: {\n reason: AccountSelectionErr[\"reason\"]\n message?: string\n },\n) {\n const { reason, message } = params\n\n if (reason === \"MODEL_NOT_SUPPORTED\") {\n return c.json(\n {\n error: {\n message:\n message\n ?? \"This model does not support the responses endpoint. Please choose a different model.\",\n type: \"invalid_request_error\",\n },\n },\n 400,\n )\n }\n\n return c.json(\n {\n error: {\n message:\n \"All accounts have exhausted their quota. Please wait for quota refresh or add additional accounts.\",\n type: \"rate_limit_error\",\n },\n },\n 429,\n )\n}\n\nfunction extractUsageFromChunkData(\n data: string | undefined,\n): NormalizedUsage | undefined {\n if (!data) return undefined\n\n try {\n const event = JSON.parse(data) as ResponseStreamEvent\n const usage = extractResponsesUsageFromStreamEvent(event)\n return usage.usageJson ? usage : undefined\n } catch {\n return undefined\n }\n}\n\ntype StreamChunk = {\n id?: string\n event?: string\n data?: string\n}\n\nfunction getStreamChunkFields(chunk: unknown): StreamChunk {\n const c = chunk as StreamChunk\n return {\n id: c.id,\n event: c.event,\n data: c.data,\n }\n}\n\nasync function handleStreamingResponses(params: {\n c: Context\n store: Store\n request: RequestContext\n payload: ResponsesPayload\n selection: AccountSelectionOk\n clientModel: string\n accountCtx: Parameters<typeof createResponses>[2]\n vision: boolean\n initiator: \"agent\" | \"user\"\n premiumRemainingBefore: number | undefined\n premiumUnlimitedBefore: boolean | undefined\n}): Promise<Response> {\n const {\n c,\n store,\n request,\n payload,\n selection,\n clientModel,\n accountCtx,\n vision,\n initiator,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n } = params\n\n let response: Awaited<ReturnType<typeof createResponses>>\n\n try {\n response = await createResponses(\n payload,\n {\n vision,\n initiator,\n upstreamRequestId: request.upstreamRequestId,\n },\n accountCtx,\n )\n } catch (error) {\n return handleUpstreamCreateError({\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n error,\n })\n }\n\n if (isAsyncIterable(response)) {\n logger.debug(\"Forwarding native Responses stream\")\n\n return streamSSE(c, (stream) =>\n streamResponsesAndLog({\n stream,\n response,\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n }),\n )\n }\n\n return handleNonStreamingUpstreamResult({\n c,\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n result: response,\n })\n}\n\nasync function handleUpstreamCreateError(params: {\n store: Store\n request: RequestContext\n selection: AccountSelectionOk\n clientModel: string\n premiumRemainingBefore: number | undefined\n premiumUnlimitedBefore: boolean | undefined\n error: unknown\n}): Promise<never> {\n const {\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n error,\n } = params\n\n const { account, reservation, selectedModel, endpoint, costUnits } = selection\n\n const finishedAtMs = Date.now()\n const details = extractErrorDetails(error)\n\n if (details.unauthorized) {\n accountsManager.markAccountFailed(account.id, \"Unauthorized (401)\")\n }\n\n await accountsManager.finalizeQuota(account, reservation)\n\n const premiumRemainingAfter = account.premiumRemaining\n const premiumUnlimitedAfter = account.unlimited\n\n insertRequestLog(store, request, {\n finishedAtMs,\n durationMs: finishedAtMs - request.startedAtMs,\n upstreamEndpoint: endpoint,\n stream: true,\n accountId: account.id,\n accountType: account.accountType,\n costUnits,\n clientModel,\n upstreamModel: selectedModel.id,\n premiumRemainingBefore,\n premiumRemainingAfter,\n premiumRemainingDiff: computeDiff(\n premiumRemainingBefore,\n premiumRemainingAfter,\n ),\n premiumUnlimitedBefore,\n premiumUnlimitedAfter,\n httpStatus: details.httpStatus,\n errorName: details.errorName,\n errorStatus: details.errorStatus,\n errorMessage: details.errorMessage,\n })\n\n throw error\n}\n\nasync function handleNonStreamingUpstreamResult(params: {\n c: Context\n store: Store\n request: RequestContext\n selection: AccountSelectionOk\n clientModel: string\n premiumRemainingBefore: number | undefined\n premiumUnlimitedBefore: boolean | undefined\n result: ResponsesResult\n}): Promise<Response> {\n const {\n c,\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n result,\n } = params\n\n const { account, reservation, selectedModel, endpoint, costUnits } = selection\n\n let httpStatus = 200\n const usage: NormalizedUsage = extractResponsesUsageFromResult(result)\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n const finishedAtMs = Date.now()\n\n try {\n logger.debug(\n \"Forwarding native Responses result:\",\n JSON.stringify(result).slice(-400),\n )\n return c.json(result)\n } catch (error) {\n const details = extractErrorDetails(error)\n httpStatus = details.httpStatus\n\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n throw error\n } finally {\n await accountsManager.finalizeQuota(account, reservation)\n\n const premiumRemainingAfter = account.premiumRemaining\n const premiumUnlimitedAfter = account.unlimited\n\n insertRequestLog(store, request, {\n finishedAtMs,\n durationMs: finishedAtMs - request.startedAtMs,\n upstreamEndpoint: endpoint,\n stream: false,\n accountId: account.id,\n accountType: account.accountType,\n costUnits,\n clientModel,\n upstreamModel: selectedModel.id,\n ...usage,\n premiumRemainingBefore,\n premiumRemainingAfter,\n premiumRemainingDiff: computeDiff(\n premiumRemainingBefore,\n premiumRemainingAfter,\n ),\n premiumUnlimitedBefore,\n premiumUnlimitedAfter,\n httpStatus,\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nasync function streamResponsesAndLog(params: {\n stream: StreamSseStream\n response: AsyncIterable<unknown>\n store: Store\n request: RequestContext\n selection: AccountSelectionOk\n clientModel: string\n premiumRemainingBefore: number | undefined\n premiumUnlimitedBefore: boolean | undefined\n}): Promise<void> {\n const {\n stream,\n response,\n store,\n request,\n selection,\n clientModel,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n } = params\n\n const { account, reservation, selectedModel, endpoint, costUnits } = selection\n\n const idTracker = createStreamIdTracker()\n let ttfbMs: number | undefined\n let lastUsage: NormalizedUsage = {}\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n\n try {\n for await (const chunk of response) {\n if (ttfbMs === undefined) {\n ttfbMs = Date.now() - request.startedAtMs\n }\n\n const { id, event, data } = getStreamChunkFields(chunk)\n const processedData = fixStreamIds(data ?? \"\", event, idTracker)\n\n const usage = extractUsageFromChunkData(processedData)\n if (usage) {\n lastUsage = usage\n }\n\n logger.debug(\"Responses stream chunk:\", JSON.stringify(chunk))\n\n await stream.writeSSE({\n id,\n event,\n data: processedData,\n })\n }\n } catch (error) {\n const details = extractErrorDetails(error)\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n\n logger.warn(\"Responses streaming error:\", error)\n } finally {\n const finishedAtMs = Date.now()\n\n await accountsManager.finalizeQuota(account, reservation)\n\n const premiumRemainingAfter = account.premiumRemaining\n const premiumUnlimitedAfter = account.unlimited\n\n insertRequestLog(store, request, {\n finishedAtMs,\n durationMs: finishedAtMs - request.startedAtMs,\n ttfbMs,\n upstreamEndpoint: endpoint,\n stream: true,\n accountId: account.id,\n accountType: account.accountType,\n costUnits,\n clientModel,\n upstreamModel: selectedModel.id,\n ...lastUsage,\n premiumRemainingBefore,\n premiumRemainingAfter,\n premiumRemainingDiff: computeDiff(\n premiumRemainingBefore,\n premiumRemainingAfter,\n ),\n premiumUnlimitedBefore,\n premiumUnlimitedAfter,\n httpStatus: errorStatus ?? (errorName ? 500 : 200),\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nasync function handleNonStreamingResponses(params: {\n c: Context\n store: Store\n request: RequestContext\n payload: ResponsesPayload\n selection: AccountSelectionOk\n clientModel: string\n accountCtx: Parameters<typeof createResponses>[2]\n vision: boolean\n initiator: \"agent\" | \"user\"\n premiumRemainingBefore: number | undefined\n premiumUnlimitedBefore: boolean | undefined\n}): Promise<Response> {\n const {\n c,\n store,\n request,\n payload,\n selection,\n clientModel,\n accountCtx,\n vision,\n initiator,\n premiumRemainingBefore,\n premiumUnlimitedBefore,\n } = params\n const { account, reservation, selectedModel, endpoint, costUnits } = selection\n let httpStatus = 200\n let usage: NormalizedUsage = {}\n let errorName: string | undefined\n let errorStatus: number | undefined\n let errorMessage: string | undefined\n let finishedAtMs: number | undefined\n try {\n const response = await createResponses(\n payload,\n { vision, initiator, upstreamRequestId: request.upstreamRequestId },\n accountCtx,\n )\n finishedAtMs = Date.now()\n const streamResponse = handleUnexpectedResponsesStream(c, response)\n if (streamResponse) {\n return streamResponse\n }\n const result = response as ResponsesResult\n usage = extractResponsesUsageFromResult(result)\n logger.debug(\n \"Forwarding native Responses result:\",\n JSON.stringify(result).slice(-400),\n )\n return c.json(result)\n } catch (error) {\n finishedAtMs = Date.now()\n const details = extractErrorDetails(error)\n httpStatus = details.httpStatus\n errorName = details.errorName\n errorStatus = details.errorStatus\n errorMessage = details.errorMessage\n if (details.unauthorized) {\n accountsManager.markAccountFailed(account.id, \"Unauthorized (401)\")\n }\n throw error\n } finally {\n const finishedAtMsFinal = finishedAtMs ?? Date.now()\n\n await accountsManager.finalizeQuota(account, reservation)\n\n const premiumRemainingAfter = account.premiumRemaining\n const premiumUnlimitedAfter = account.unlimited\n\n insertRequestLog(store, request, {\n finishedAtMs: finishedAtMsFinal,\n durationMs: finishedAtMsFinal - request.startedAtMs,\n upstreamEndpoint: endpoint,\n stream: false,\n accountId: account.id,\n accountType: account.accountType,\n costUnits,\n clientModel,\n upstreamModel: selectedModel.id,\n ...usage,\n premiumRemainingBefore,\n premiumRemainingAfter,\n premiumRemainingDiff: computeDiff(\n premiumRemainingBefore,\n premiumRemainingAfter,\n ),\n premiumUnlimitedBefore,\n premiumUnlimitedAfter,\n httpStatus,\n errorName,\n errorStatus,\n errorMessage,\n })\n }\n}\n\nfunction handleUnexpectedResponsesStream(\n c: Context,\n response: Awaited<ReturnType<typeof createResponses>>,\n): Response | null {\n if (!isAsyncIterable(response)) {\n return null\n }\n\n // Defensive guard: upstream returned stream unexpectedly.\n logger.debug(\"Forwarding native Responses stream (unexpected)\")\n\n return streamSSE(c, async (stream) => {\n const idTracker = createStreamIdTracker()\n\n for await (const chunk of response) {\n const { id, event, data } = getStreamChunkFields(chunk)\n const processedData = fixStreamIds(data ?? \"\", event, idTracker)\n await stream.writeSSE({\n id,\n event,\n data: processedData,\n })\n }\n })\n}\n\nconst isAsyncIterable = <T>(value: unknown): value is AsyncIterable<T> =>\n Boolean(value)\n && typeof (value as AsyncIterable<T>)[Symbol.asyncIterator] === \"function\"\n\nconst useFunctionApplyPatch = (payload: ResponsesPayload): void => {\n const config = getConfig()\n const enabled = config.useFunctionApplyPatch ?? true\n if (!enabled) return\n\n logger.debug(\"Using function tool apply_patch for responses\")\n if (Array.isArray(payload.tools)) {\n const toolsArr = payload.tools\n for (let i = 0; i < toolsArr.length; i++) {\n const t = toolsArr[i]\n if (t.type === \"custom\" && t.name === \"apply_patch\") {\n toolsArr[i] = {\n type: \"function\",\n name: t.name,\n description: \"Use the `apply_patch` tool to edit files\",\n parameters: {\n type: \"object\",\n properties: {\n input: {\n type: \"string\",\n description: \"The entire contents of the apply_patch command\",\n },\n },\n required: [\"input\"],\n },\n strict: false,\n }\n }\n }\n }\n}\n\nconst removeWebSearchTool = (payload: ResponsesPayload): void => {\n if (!Array.isArray(payload.tools) || payload.tools.length === 0) return\n\n payload.tools = payload.tools.filter((t) => {\n return t.type !== \"web_search\"\n })\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleResponses } from \"./handler\"\n\nexport const responsesRoutes = new Hono()\n\nresponsesRoutes.post(\"/\", async (c) => {\n try {\n return await handleResponses(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\n\nexport const tokenRoute = new Hono()\n\ntokenRoute.get(\"/\", (c) => {\n try {\n return c.json({\n token: state.copilotToken,\n })\n } catch (error) {\n console.error(\"Error fetching token:\", error)\n return c.json({ error: \"Failed to fetch token\", token: null }, 500)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { accountsManager } from \"~/lib/accounts-manager\"\nimport { getCopilotUsage } from \"~/services/github/get-copilot-usage\"\n\nexport const usageRoute = new Hono()\n\nusageRoute.get(\"/\", (c) => {\n try {\n const accountStatuses = accountsManager.getAccountStatus()\n return c.json({\n accounts: accountStatuses,\n })\n } catch (error) {\n console.error(\"Error fetching account status:\", error)\n return c.json({ error: \"Failed to fetch account status\" }, 500)\n }\n})\n\n/**\n * Get detailed usage information for a specific account by index.\n * Index 0 is the temporary account (if exists), otherwise the first registered account.\n */\nusageRoute.get(\"/:accountIndex\", async (c) => {\n try {\n const indexParam = c.req.param(\"accountIndex\")\n const index = Number.parseInt(indexParam, 10)\n\n if (Number.isNaN(index) || index < 0) {\n return c.json({ error: \"Invalid account index\" }, 400)\n }\n\n const accountContext = accountsManager.getAccountContextByIndex(index)\n\n if (!accountContext) {\n const accountCount = accountsManager.getAccountCount()\n return c.json(\n {\n error: `Account index ${index} not found`,\n availableIndices: accountCount > 0 ? `0-${accountCount - 1}` : \"none\",\n },\n 404,\n )\n }\n\n const usage = await getCopilotUsage(accountContext)\n\n return c.json(usage)\n } catch (error) {\n console.error(\"Error fetching account usage:\", error)\n return c.json({ error: \"Failed to fetch account usage\" }, 500)\n }\n})\n","import { Hono } from \"hono\"\nimport { cors } from \"hono/cors\"\nimport { logger } from \"hono/logger\"\n\nimport { createApiKeyAuthMiddleware } from \"~/lib/api-key-auth\"\n\nimport { adminApiRoutes } from \"./routes/admin-api/route\"\nimport { adminRoutes } from \"./routes/admin/route\"\nimport { completionRoutes } from \"./routes/chat-completions/route\"\nimport { embeddingRoutes } from \"./routes/embeddings/route\"\nimport { messageRoutes } from \"./routes/messages/route\"\nimport { modelRoutes } from \"./routes/models/route\"\nimport { responsesRoutes } from \"./routes/responses/route\"\nimport { tokenRoute } from \"./routes/token/route\"\nimport { usageRoute } from \"./routes/usage/route\"\n\nexport const server = new Hono()\n\nserver.use(logger())\nserver.use(cors())\nserver.use(\"*\", createApiKeyAuthMiddleware())\n\nserver.get(\"/\", (c) => c.text(\"Server running\"))\n\nserver.route(\"/chat/completions\", completionRoutes)\nserver.route(\"/models\", modelRoutes)\nserver.route(\"/embeddings\", embeddingRoutes)\nserver.route(\"/usage\", usageRoute)\nserver.route(\"/token\", tokenRoute)\nserver.route(\"/responses\", responsesRoutes)\n\n// Admin UI / APIs (no auth; intended for localhost/intranet)\nserver.route(\"/admin\", adminRoutes)\nserver.route(\"/api/admin\", adminApiRoutes)\n\n// Compatibility with tools that expect v1/ prefix\nserver.route(\"/v1/chat/completions\", completionRoutes)\nserver.route(\"/v1/models\", modelRoutes)\nserver.route(\"/v1/embeddings\", embeddingRoutes)\nserver.route(\"/v1/responses\", responsesRoutes)\n\n// Anthropic compatible endpoints\nserver.route(\"/v1/messages\", messageRoutes)\n"],"mappings":"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"}
|