@nick3/copilot-api 1.10.30 → 1.10.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -9
- package/README.zh-CN.md +39 -7
- package/dist/admin/assets/index-Cl_ViIW_.js +110 -0
- package/dist/admin/index.html +1 -1
- package/dist/{auth-CnwhQOu6.js → auth-Cc11G9V9.js} +2 -2
- package/dist/{auth-CnwhQOu6.js.map → auth-Cc11G9V9.js.map} +1 -1
- package/dist/{check-usage-CseltoFJ.js → check-usage-C2QE6R93.js} +2 -2
- package/dist/{check-usage-CseltoFJ.js.map → check-usage-C2QE6R93.js.map} +1 -1
- package/dist/{config-XZv75uoU.js → config-BaU_aWgi.js} +22 -4
- package/dist/config-BaU_aWgi.js.map +1 -0
- package/dist/{debug-D8xHblDV.js → debug-BKqoXB_p.js} +2 -2
- package/dist/{debug-D8xHblDV.js.map → debug-BKqoXB_p.js.map} +1 -1
- package/dist/main.js +4 -4
- package/dist/{responses-bridge-registry-JjUvTCST.js → responses-bridge-registry-DqCoY6Ex.js} +2 -2
- package/dist/{responses-bridge-registry-JjUvTCST.js.map → responses-bridge-registry-DqCoY6Ex.js.map} +1 -1
- package/dist/{server-BYKxAFro.js → server-C7pCkArb.js} +315 -147
- package/dist/server-C7pCkArb.js.map +1 -0
- package/dist/{start-DVlCJ0Ma.js → start-CdLbBkRA.js} +4 -4
- package/dist/{start-DVlCJ0Ma.js.map → start-CdLbBkRA.js.map} +1 -1
- package/dist/{token-9O2KJcF5.js → token-671YFxgv.js} +3 -2
- package/dist/token-671YFxgv.js.map +1 -0
- package/package.json +1 -1
- package/dist/admin/assets/index-BGmG-ckX.js +0 -110
- package/dist/config-XZv75uoU.js.map +0 -1
- package/dist/server-BYKxAFro.js.map +0 -1
- package/dist/token-9O2KJcF5.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { I as initOpencodeVersion, a as cacheVsCodeSessionId, h as getDeviceCode, i as cacheVsCodeDeviceId, j as state, m as getGitHubUser, n as cacheMacMachineId, r as cacheVSCodeVersion, t as pollAccessToken, y as initProxyFromEnv } from "./poll-access-token-GzVkiTH8.js";
|
|
2
2
|
import { h as saveAccountToken, n as parseAccountType, r as addAccountToRegistry } from "./account-DpW8RaT6.js";
|
|
3
3
|
import { r as ensurePaths } from "./paths-Bpsb62LK.js";
|
|
4
|
-
import {
|
|
4
|
+
import { E as mergeConfigWithDefaults, u as getModelRefreshIntervalMs, v as isAccountAffinityEnabled } from "./config-BaU_aWgi.js";
|
|
5
5
|
import { i as isMcpHttpEnabledFromEnv } from "./mcp-http-config-DMdUDz1D.js";
|
|
6
|
-
import { T as isAuthorizedHeaders, a as startQuotaRefreshSchedulerFromConfig, c as accountsManager, i as registerQuotaRefreshSchedulerShutdownCleanup, l as applySharedSessionAffinityRetention, n as registerResponsesBridge, o as stopQuotaRefreshScheduler, r as unregisterResponsesBridge, w as createUnauthorizedRawResponse } from "./responses-bridge-registry-
|
|
6
|
+
import { T as isAuthorizedHeaders, a as startQuotaRefreshSchedulerFromConfig, c as accountsManager, i as registerQuotaRefreshSchedulerShutdownCleanup, l as applySharedSessionAffinityRetention, n as registerResponsesBridge, o as stopQuotaRefreshScheduler, r as unregisterResponsesBridge, w as createUnauthorizedRawResponse } from "./responses-bridge-registry-DqCoY6Ex.js";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
import consola from "consola";
|
|
9
9
|
import { randomUUID } from "node:crypto";
|
|
@@ -408,7 +408,7 @@ async function runServer(options) {
|
|
|
408
408
|
await setupClaudeCode(models, serverUrl);
|
|
409
409
|
}
|
|
410
410
|
consola.box(`🌐 Admin UI: ${serverUrl}/admin`);
|
|
411
|
-
const { createServer } = await import("./server-
|
|
411
|
+
const { createServer } = await import("./server-C7pCkArb.js");
|
|
412
412
|
const server = createServer({ enableMcpHttp });
|
|
413
413
|
const responsesWebSocketHandler = createResponsesWebSocketHandler(server.fetch);
|
|
414
414
|
Bun.serve({
|
|
@@ -523,4 +523,4 @@ const start = defineCommand({
|
|
|
523
523
|
//#endregion
|
|
524
524
|
export { start };
|
|
525
525
|
|
|
526
|
-
//# sourceMappingURL=start-
|
|
526
|
+
//# sourceMappingURL=start-CdLbBkRA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start-DVlCJ0Ma.js","names":["process"],"sources":["../src/routes/responses/websocket.ts","../src/lib/shell.ts","../src/start.ts"],"sourcesContent":["import consola from \"consola\"\nimport { randomUUID } from \"node:crypto\"\n\nimport {\n createUnauthorizedRawResponse,\n isAuthorizedHeaders,\n} from \"~/lib/request-auth\"\nimport {\n registerResponsesBridge,\n unregisterResponsesBridge,\n} from \"~/services/copilot/responses-bridge-registry\"\n\nconst RESPONSES_BRIDGE_ID_HEADER = \"x-responses-bridge-id\"\n\nconst RESPONSES_WEBSOCKET_PATHS = new Set([\"/responses\", \"/v1/responses\"])\nconst SSE_RECORD_SEPARATOR = /\\r?\\n\\r?\\n/u\nconst FORWARDED_HEADER_NAMES = [\n \"authorization\",\n \"x-api-key\",\n \"user-agent\",\n \"x-session-id\",\n \"x-session-affinity\",\n \"x-parent-session-id\",\n \"x-trace-id\",\n]\n\ntype ServerWebSocket = Bun.ServerWebSocket<ResponsesWebSocketData>\ntype AppFetch = (request: Request) => Response | Promise<Response>\n\nexport type ResponsesWebSocketData = {\n // Codex keeps a single persistent websocket per session and pipelines turns\n // over it: a turn's `response.create` can arrive before the previous turn's\n // SSE relay has finished tearing down. Bun does not serialize async `message`\n // callbacks, so we chain work on this promise to process frames strictly in\n // arrival order instead of rejecting concurrent frames.\n queue: Promise<void>\n // In-flight upstream requests, one AbortController per active `response.create`\n // frame, so a client disconnect can abort all of them.\n controllers: Set<AbortController>\n headers: Array<[string, string]>\n url: string\n // Stable id minted per bridge connection. It is forwarded to the upstream\n // Responses pool (via `x-responses-bridge-id`) so the pool can close this exact\n // socket when its upstream connection is reaped, forcing Codex to rebuild a\n // fresh full-context session instead of stalling on a stale\n // `previous_response_id`.\n bridgeId: string\n}\n\ntype ResponsesWebSocketFrame = {\n type?: unknown\n [key: string]: unknown\n}\n\nexport function createResponsesWebSocketHandler(\n appFetch: AppFetch,\n): Bun.WebSocketHandler<ResponsesWebSocketData> {\n return {\n data: {} as ResponsesWebSocketData,\n idleTimeout: 0,\n open(ws) {\n // Register a closer so the upstream pool can drop this socket when its\n // GitHub connection is reaped while idle.\n registerResponsesBridge(ws.data.bridgeId, () => {\n try {\n ws.close()\n } catch (error) {\n consola.warn(\"Failed to close Responses websocket bridge:\", error)\n }\n })\n },\n async message(ws, message) {\n await handleResponsesWebSocketMessage(ws, message, appFetch)\n },\n close(ws) {\n unregisterResponsesBridge(ws.data.bridgeId)\n // Abort every in-flight upstream Responses request so we stop consuming\n // tokens/quota and worker time once the client disconnects.\n for (const controller of ws.data.controllers) {\n controller.abort()\n }\n ws.data.controllers.clear()\n },\n }\n}\n\nexport function handleResponsesWebSocketUpgrade(\n req: Request,\n server: Bun.Server<ResponsesWebSocketData>,\n): Response | null | undefined {\n if (!isResponsesWebSocketUpgrade(req)) {\n return null\n }\n\n if (!isAuthorizedHeaders(req.headers)) {\n return createUnauthorizedRawResponse()\n }\n\n const upgraded = server.upgrade(req, {\n data: buildResponsesWebSocketData(req),\n })\n\n if (upgraded) {\n return undefined\n }\n\n return new Response(\"WebSocket upgrade failed\", { status: 400 })\n}\n\nexport function isResponsesWebSocketUpgrade(req: Request): boolean {\n if (req.method !== \"GET\") {\n return false\n }\n\n const pathname = new URL(req.url).pathname\n if (!RESPONSES_WEBSOCKET_PATHS.has(pathname)) {\n return false\n }\n\n return req.headers.get(\"upgrade\")?.toLowerCase() === \"websocket\"\n}\n\nexport async function handleResponsesWebSocketMessage(\n ws: ServerWebSocket,\n message: string | ArrayBuffer | Uint8Array,\n appFetch: AppFetch,\n): Promise<void> {\n let frame: ResponsesWebSocketFrame\n try {\n frame = JSON.parse(\n normalizeWebSocketMessage(message),\n ) as ResponsesWebSocketFrame\n } catch {\n sendResponsesWebSocketError(ws, \"Invalid websocket JSON frame\", 400)\n return\n }\n\n if (frame.type === \"response.processed\") {\n return\n }\n\n if (frame.type !== \"response.create\") {\n sendResponsesWebSocketError(ws, \"Unsupported websocket frame type\", 400)\n return\n }\n\n // Chain this frame after any in-flight work so pipelined turns are processed\n // strictly in arrival order. The assignment is synchronous, so even though Bun\n // may dispatch overlapping `message` callbacks, the ordering reflects the order\n // frames were received. We swallow any rejection from the prior link before\n // chaining so a single failed turn (e.g. `ws.send` throwing while the socket is\n // closing) can never poison `ws.data.queue` and block every subsequent turn for\n // the lifetime of the connection.\n const queued = ws.data.queue\n .catch(() => {})\n .then(() => processResponseCreateFrame(ws, frame, appFetch))\n ws.data.queue = queued\n await queued.catch(() => {})\n}\n\nasync function processResponseCreateFrame(\n ws: ServerWebSocket,\n frame: ResponsesWebSocketFrame,\n appFetch: AppFetch,\n): Promise<void> {\n if (frame.generate === false) {\n sendResponsesWebSocketWarmupCompleted(ws)\n return\n }\n\n const controller = new AbortController()\n ws.data.controllers.add(controller)\n try {\n await forwardResponseCreateFrame(ws, frame, appFetch, controller)\n } catch (error) {\n // A client disconnect aborts in-flight controllers; that is expected\n // teardown, not a failure to report back to the (now gone) client.\n if (controller.signal.aborted) {\n return\n }\n consola.warn(\"Responses websocket bridge failed:\", error)\n sendResponsesWebSocketError(\n ws,\n error instanceof Error ? error.message : String(error),\n 500,\n )\n } finally {\n ws.data.controllers.delete(controller)\n }\n}\n\nexport function parseSseRecords(chunk: string): {\n events: Array<string>\n remainder: string\n} {\n const events: Array<string> = []\n let remainder = chunk\n\n while (true) {\n const match = SSE_RECORD_SEPARATOR.exec(remainder)\n if (!match) {\n break\n }\n\n const record = remainder.slice(0, match.index)\n remainder = remainder.slice(match.index + match[0].length)\n const data = parseSseRecordData(record)\n if (data !== null && data !== \"[DONE]\") {\n events.push(data)\n }\n }\n\n return { events, remainder }\n}\n\nfunction buildResponsesWebSocketData(req: Request): ResponsesWebSocketData {\n return {\n queue: Promise.resolve(),\n controllers: new Set(),\n headers: collectForwardedHeaders(req.headers),\n url: req.url,\n bridgeId: randomUUID(),\n }\n}\n\nfunction collectForwardedHeaders(headers: Headers): Array<[string, string]> {\n const forwarded: Array<[string, string]> = []\n for (const name of FORWARDED_HEADER_NAMES) {\n const value = headers.get(name)\n if (value) {\n forwarded.push([name, value])\n }\n }\n return forwarded\n}\n\nasync function forwardResponseCreateFrame(\n ws: ServerWebSocket,\n frame: ResponsesWebSocketFrame,\n appFetch: AppFetch,\n controller: AbortController,\n): Promise<void> {\n const payload = { ...frame, stream: true }\n delete payload.type\n\n const response = await appFetch(\n new Request(buildInternalResponsesUrl(ws.data.url), {\n method: \"POST\",\n headers: buildInternalResponsesHeaders(ws.data.headers, ws.data.bridgeId),\n body: JSON.stringify(payload),\n signal: controller.signal,\n }),\n )\n\n if (!response.ok) {\n sendResponsesWebSocketError(\n ws,\n await readErrorResponseMessage(response),\n response.status,\n )\n return\n }\n\n if (!response.body) {\n sendResponsesWebSocketError(ws, \"Responses stream body is empty\", 500)\n return\n }\n\n await streamSseResponseToWebSocket(ws, response.body, controller)\n}\n\nfunction buildInternalResponsesUrl(sourceUrl: string): string {\n const url = new URL(sourceUrl)\n url.protocol = \"http:\"\n url.pathname =\n url.pathname.startsWith(\"/v1/\") ? \"/v1/responses\" : \"/responses\"\n url.search = \"\"\n url.hash = \"\"\n return url.toString()\n}\n\nfunction buildInternalResponsesHeaders(\n forwardedHeaders: Array<[string, string]>,\n bridgeId: string,\n): Headers {\n const headers = new Headers(forwardedHeaders)\n headers.set(\"content-type\", \"application/json\")\n headers.set(RESPONSES_BRIDGE_ID_HEADER, bridgeId)\n return headers\n}\n\nasync function streamSseResponseToWebSocket(\n ws: ServerWebSocket,\n body: ReadableStream<Uint8Array>,\n controller: AbortController,\n): Promise<void> {\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = \"\"\n\n // Cancel the upstream reader as soon as the connection is aborted (client\n // close or a failed send) so the upstream stream is torn down promptly.\n const onAbort = () => {\n void reader.cancel()\n }\n controller.signal.addEventListener(\"abort\", onAbort)\n\n try {\n while (!controller.signal.aborted) {\n const { done, value } = await reader.read()\n if (done) {\n break\n }\n\n buffer += decoder.decode(value, { stream: true })\n const parsed = parseSseRecords(buffer)\n buffer = parsed.remainder\n if (!relaySseEvents(ws, parsed.events, controller)) {\n return\n }\n }\n\n if (controller.signal.aborted) {\n return\n }\n\n buffer += decoder.decode()\n const parsed = parseSseRecords(`${buffer}\\n\\n`)\n relaySseEvents(ws, parsed.events, controller)\n } finally {\n controller.signal.removeEventListener(\"abort\", onAbort)\n try {\n reader.releaseLock()\n } catch {\n // Reader may already be released after cancellation; ignore.\n }\n }\n}\n\n/**\n * Relay parsed SSE events to the client. Returns `false` if a send failed and\n * the upstream request was aborted, signalling the caller to stop streaming.\n */\nfunction relaySseEvents(\n ws: ServerWebSocket,\n events: Array<string>,\n controller: AbortController,\n): boolean {\n for (const event of events) {\n if (controller.signal.aborted) {\n return false\n }\n try {\n ws.send(event)\n } catch (error) {\n consola.warn(\"Responses websocket send failed:\", error)\n controller.abort()\n return false\n }\n }\n return true\n}\n\nfunction parseSseRecordData(record: string): string | null {\n const lines = record.split(/\\r?\\n/u)\n const dataLines = lines\n .filter((line) => line.startsWith(\"data:\"))\n // Per the SSE spec, strip only a single optional leading space after the\n // colon (not arbitrary whitespace), preserving whitespace-sensitive data.\n .map((line) => (line.startsWith(\"data: \") ? line.slice(6) : line.slice(5)))\n\n if (dataLines.length === 0) {\n return null\n }\n\n return dataLines.join(\"\\n\")\n}\n\nfunction normalizeWebSocketMessage(\n message: string | ArrayBuffer | Uint8Array,\n): string {\n if (typeof message === \"string\") {\n return message\n }\n\n return new TextDecoder().decode(message)\n}\n\nfunction sendResponsesWebSocketError(\n ws: ServerWebSocket,\n message: string,\n status: number,\n): void {\n // Mirror the Responses stream error contract (see ResponseErrorEvent in\n // src/services/copilot/create-responses.ts) so clients always receive the\n // same top-level event shape regardless of where the error originates.\n ws.send(\n JSON.stringify({\n code: status ? String(status) : null,\n message,\n param: null,\n sequence_number: 0,\n type: \"error\",\n }),\n )\n}\n\nfunction sendResponsesWebSocketWarmupCompleted(ws: ServerWebSocket): void {\n ws.send(\n JSON.stringify({\n response: {\n id: \"\",\n },\n sequence_number: 0,\n type: \"response.completed\",\n }),\n )\n}\n\nasync function readErrorResponseMessage(response: Response): Promise<string> {\n const body = await response.text()\n if (!body) {\n return `Responses request failed with status ${response.status}`\n }\n\n try {\n const parsed = JSON.parse(body) as {\n error?: { message?: unknown }\n message?: unknown\n }\n const message =\n typeof parsed.error?.message === \"string\" ? parsed.error.message\n : typeof parsed.message === \"string\" ? parsed.message\n : undefined\n return message ?? body\n } catch {\n return body\n }\n}\n","import { execSync } from \"node:child_process\"\nimport process from \"node:process\"\n\ntype ShellName = \"bash\" | \"zsh\" | \"fish\" | \"powershell\" | \"cmd\" | \"sh\"\ntype EnvVars = Record<string, string | undefined>\n\nfunction getShell(): ShellName {\n const { platform, ppid, env } = process\n\n if (platform === \"win32\") {\n try {\n const command = `wmic process get ParentProcessId,Name | findstr \"${ppid}\"`\n const parentProcess = execSync(command, { stdio: \"pipe\" }).toString()\n\n if (parentProcess.toLowerCase().includes(\"powershell.exe\")) {\n return \"powershell\"\n }\n } catch {\n return \"cmd\"\n }\n\n return \"cmd\"\n } else {\n const shellPath = env.SHELL\n if (shellPath) {\n if (shellPath.endsWith(\"zsh\")) return \"zsh\"\n if (shellPath.endsWith(\"fish\")) return \"fish\"\n if (shellPath.endsWith(\"bash\")) return \"bash\"\n }\n\n return \"sh\"\n }\n}\n\n/**\n * Generates a copy-pasteable script to set multiple environment variables\n * and run a subsequent command.\n * @param {EnvVars} envVars - An object of environment variables to set.\n * @param {string} commandToRun - The command to run after setting the variables.\n * @returns {string} The formatted script string.\n */\nexport function generateEnvScript(\n envVars: EnvVars,\n commandToRun: string = \"\",\n): string {\n const shell = getShell()\n const filteredEnvVars = Object.entries(envVars).filter(\n ([, value]) => value !== undefined,\n ) as Array<[string, string]>\n\n let commandBlock: string\n\n switch (shell) {\n case \"powershell\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `$env:${key} = ${value}`)\n .join(\"; \")\n break\n }\n case \"cmd\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set ${key}=${value}`)\n .join(\" & \")\n break\n }\n case \"fish\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set -gx ${key} ${value}`)\n .join(\"; \")\n break\n }\n default: {\n // bash, zsh, sh\n const assignments = filteredEnvVars\n .map(([key, value]) => `${key}=${value}`)\n .join(\" \")\n commandBlock = filteredEnvVars.length > 0 ? `export ${assignments}` : \"\"\n break\n }\n }\n\n if (commandBlock && commandToRun) {\n const separator = shell === \"cmd\" ? \" & \" : \" && \"\n return `${commandBlock}${separator}${commandToRun}`\n }\n\n return commandBlock || commandToRun\n}\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\n\nimport {\n registerQuotaRefreshSchedulerShutdownCleanup,\n startQuotaRefreshSchedulerFromConfig,\n stopQuotaRefreshScheduler,\n} from \"~/lib/quota-refresh-scheduler-runtime\"\nimport { isMcpHttpEnabledFromEnv } from \"~/mcp-http-config\"\nimport {\n createResponsesWebSocketHandler,\n handleResponsesWebSocketUpgrade,\n} from \"~/routes/responses/websocket\"\n\nimport { accountsManager } from \"./lib/accounts-manager\"\nimport { addAccountToRegistry, saveAccountToken } from \"./lib/accounts-registry\"\nimport {\n getModelRefreshIntervalMs,\n isAccountAffinityEnabled,\n mergeConfigWithDefaults,\n} from \"./lib/config\"\nimport { initOpencodeVersion } from \"./lib/opencode\"\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { applySharedSessionAffinityRetention } from \"./lib/session-affinity-store\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport { parseAccountType, type AccountType } from \"./lib/types/account\"\nimport {\n cacheMacMachineId,\n cacheVSCodeVersion,\n cacheVsCodeSessionId,\n cacheVsCodeDeviceId,\n} from \"./lib/utils\"\nimport { getDeviceCode } from \"./services/github/get-device-code\"\nimport { getGitHubUser } from \"./services/github/get-user\"\nimport { pollAccessToken } from \"./services/github/poll-access-token\"\n\ninterface RunServerOptions {\n port: number\n verbose: boolean\n accountType: AccountType\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n proxyEnv: boolean\n skipAuth: boolean\n enableMcpHttp: boolean\n}\n\n/**\n * Run the interactive authentication flow to add a new account.\n * Called automatically when no accounts are found.\n */\nasync function runAuthFlow(accountType: AccountType): Promise<void> {\n consola.warn(\"No accounts found. Starting authentication flow...\")\n\n // Start device code flow\n const deviceResponse = await getDeviceCode()\n consola.info(\n `Please enter the code \"${deviceResponse.user_code}\" at ${deviceResponse.verification_uri}`,\n )\n\n // Poll for access token\n const token = await pollAccessToken(deviceResponse)\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n\n // Get user info to determine account ID\n const user = await getGitHubUser({\n githubToken: token,\n accountType,\n })\n const accountId = user.login\n\n // Save token and add to registry\n await saveAccountToken(accountId, token)\n await addAccountToRegistry({\n id: accountId,\n accountType,\n addedAt: Date.now(),\n })\n\n consola.success(`Account \"${accountId}\" added successfully!`)\n}\n\nfunction logClaudeCodeTip(): void {\n consola.log(\n \"\\n💡 Tip: The --claude-code flag simply generates a clipboard command for launching Claude Code. \\n\"\n + \"All models remain fully accessible without this flag, just configure the model ID directly in your settings.json file.\",\n )\n}\n\ntype AvailableModels = NonNullable<\n ReturnType<typeof accountsManager.getFirstAccountModels>\n>\n\nasync function setupClaudeCode(\n models: AvailableModels,\n serverUrl: string,\n): Promise<void> {\n const selectedModel = await consola.prompt(\n \"Select a model to use with Claude Code\",\n {\n type: \"select\",\n options: models.data.map((model) => model.id),\n },\n )\n\n const selectedSmallModel = await consola.prompt(\n \"Select a small model to use with Claude Code\",\n {\n type: \"select\",\n options: models.data.map((model) => model.id),\n },\n )\n\n const command = generateEnvScript(\n {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: \"dummy\",\n ANTHROPIC_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_HAIKU_MODEL: selectedSmallModel,\n DISABLE_NON_ESSENTIAL_MODEL_CALLS: \"1\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\n CLAUDE_CODE_ATTRIBUTION_HEADER: \"0\",\n CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: \"false\",\n CLAUDE_CODE_DISABLE_TERMINAL_TITLE: \"true\",\n CLAUDE_CODE_ENABLE_AWAY_SUMMARY: \"0\",\n CLAUDE_PLUGIN_ENABLE_QUESTION_RULES: \"true\",\n },\n \"claude\",\n )\n\n try {\n clipboard.writeSync(command)\n consola.success(\"Copied Claude Code command to clipboard!\")\n } catch {\n consola.warn(\n \"Failed to copy to clipboard. Here is the Claude Code command:\",\n )\n consola.log(command)\n }\n}\n\nexport async function runServer(options: RunServerOptions): Promise<void> {\n // Fail fast before any config merge, account init, interactive auth, or quota\n // scheduler work: the server relies on Bun.serve for the Responses WebSocket\n // transport, so running under Node would otherwise crash with\n // \"ReferenceError: Bun is not defined\" only after all that setup.\n if (typeof Bun === \"undefined\") {\n consola.error(\n \"The Responses WebSocket transport requires the Bun runtime. Start the proxy with 'bun' or 'bunx --bun' instead of Node.\",\n )\n process.exit(1)\n }\n\n // Work around unjs/consola#357 until a release includes PR #359.\n consola.options.throttle = 0\n\n // Ensure config is merged with defaults at startup\n mergeConfigWithDefaults()\n accountsManager.setAccountAffinityEnabled(isAccountAffinityEnabled())\n accountsManager.setModelsRefreshIntervalMs(getModelRefreshIntervalMs())\n\n await initOpencodeVersion()\n\n if (options.proxyEnv) {\n initProxyFromEnv()\n }\n\n const enableMcpHttp = options.enableMcpHttp || isMcpHttpEnabledFromEnv()\n if (enableMcpHttp) {\n consola.warn(\n \"Main server MCP endpoint is enabled and unauthenticated at /mcp.\",\n )\n }\n\n state.verbose = options.verbose\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.accountType = options.accountType\n if (options.accountType !== \"individual\") {\n consola.info(`Using ${options.accountType} plan GitHub account`)\n }\n\n state.manualApprove = options.manual\n state.rateLimitSeconds = options.rateLimit\n state.rateLimitWait = options.rateLimitWait\n state.showToken = options.showToken\n\n await ensurePaths()\n applySharedSessionAffinityRetention()\n await cacheVSCodeVersion()\n cacheMacMachineId()\n cacheVsCodeSessionId()\n await cacheVsCodeDeviceId()\n\n // Initialize accounts manager with VS Code version\n await accountsManager.initialize(state.vsCodeVersion)\n\n // If --github-token is provided, set it as a temporary (high priority) account\n if (options.githubToken) {\n await accountsManager.setTemporaryAccount(\n options.githubToken,\n options.accountType,\n )\n consola.info(\"Using provided GitHub token as temporary account\")\n }\n\n // Check if we have any accounts, if not, start the auth flow\n if (!accountsManager.hasAccounts()) {\n if (options.skipAuth) {\n consola.warn(\n \"No accounts found. Skipping auth flow (--skip-auth). Add accounts via the Admin UI.\",\n )\n } else {\n try {\n await runAuthFlow(options.accountType)\n\n // Re-initialize accounts manager with the new account\n accountsManager.shutdown()\n stopQuotaRefreshScheduler()\n await accountsManager.initialize(state.vsCodeVersion)\n accountsManager.setModelsRefreshIntervalMs(getModelRefreshIntervalMs())\n } catch (error) {\n consola.error(\"Failed to add account:\", error)\n process.exit(1)\n }\n }\n }\n\n startQuotaRefreshSchedulerFromConfig()\n registerQuotaRefreshSchedulerShutdownCleanup()\n\n // Get models from the first available account\n const models = accountsManager.getFirstAccountModels()\n\n consola.info(\n `Available models: \\n${models?.data.map((model) => `- ${model.id}`).join(\"\\n\") ?? \"(no models loaded)\"}`,\n )\n\n const serverUrl = `http://localhost:${options.port}`\n\n if (options.claudeCode) {\n logClaudeCodeTip()\n if (!models?.data.length) {\n consola.error(\n \"Claude Code requires available models. Add an account via the Admin UI or remove --claude-code.\",\n )\n process.exit(1)\n }\n await setupClaudeCode(models, serverUrl)\n }\n\n consola.box(`🌐 Admin UI: ${serverUrl}/admin`)\n\n const { createServer } = await import(\"./server\")\n const server = createServer({ enableMcpHttp })\n const responsesWebSocketHandler = createResponsesWebSocketHandler(\n server.fetch,\n )\n\n Bun.serve({\n port: options.port,\n idleTimeout: 0,\n fetch: (request, bunServer) => {\n const websocketResponse = handleResponsesWebSocketUpgrade(\n request,\n bunServer,\n )\n if (websocketResponse !== null) {\n return websocketResponse\n }\n\n return server.fetch(request)\n },\n websocket: responsesWebSocketHandler,\n })\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the Copilot API server\",\n },\n args: {\n port: {\n alias: \"p\",\n type: \"string\",\n default: \"4141\",\n description: \"Port to listen on\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type to use (individual, business, enterprise)\",\n },\n manual: {\n type: \"boolean\",\n default: false,\n description: \"Enable manual request approval\",\n },\n \"rate-limit\": {\n alias: \"r\",\n type: \"string\",\n description: \"Rate limit in seconds between requests\",\n },\n wait: {\n alias: \"w\",\n type: \"boolean\",\n default: false,\n description:\n \"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set\",\n },\n \"github-token\": {\n alias: \"g\",\n type: \"string\",\n description:\n \"Provide GitHub token directly (must be generated using the `auth` subcommand)\",\n },\n \"claude-code\": {\n alias: \"c\",\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Claude Code with Copilot API config\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub and Copilot tokens on fetch and refresh\",\n },\n \"proxy-env\": {\n type: \"boolean\",\n default: false,\n description: \"Initialize proxy from environment variables\",\n },\n \"skip-auth\": {\n type: \"boolean\",\n default: false,\n description:\n \"Skip the initial CLI auth flow when no accounts are found. Use this to add accounts via the Admin UI instead.\",\n },\n \"enable-mcp-http\": {\n type: \"boolean\",\n default: false,\n description:\n \"Expose the unauthenticated MCP Streamable HTTP endpoint at /mcp.\",\n },\n },\n run({ args }) {\n const rateLimitRaw = args[\"rate-limit\"]\n const rateLimit =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n rateLimitRaw === undefined ? undefined : Number.parseInt(rateLimitRaw, 10)\n\n let accountType: AccountType\n try {\n accountType = parseAccountType(args[\"account-type\"])\n } catch (error) {\n consola.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n }\n\n return runServer({\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n accountType,\n manual: args.manual,\n rateLimit,\n rateLimitWait: args.wait,\n githubToken: args[\"github-token\"],\n claudeCode: args[\"claude-code\"],\n showToken: args[\"show-token\"],\n proxyEnv: args[\"proxy-env\"],\n skipAuth: args[\"skip-auth\"],\n enableMcpHttp: args[\"enable-mcp-http\"],\n })\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"start-CdLbBkRA.js","names":["process"],"sources":["../src/routes/responses/websocket.ts","../src/lib/shell.ts","../src/start.ts"],"sourcesContent":["import consola from \"consola\"\nimport { randomUUID } from \"node:crypto\"\n\nimport {\n createUnauthorizedRawResponse,\n isAuthorizedHeaders,\n} from \"~/lib/request-auth\"\nimport {\n registerResponsesBridge,\n unregisterResponsesBridge,\n} from \"~/services/copilot/responses-bridge-registry\"\n\nconst RESPONSES_BRIDGE_ID_HEADER = \"x-responses-bridge-id\"\n\nconst RESPONSES_WEBSOCKET_PATHS = new Set([\"/responses\", \"/v1/responses\"])\nconst SSE_RECORD_SEPARATOR = /\\r?\\n\\r?\\n/u\nconst FORWARDED_HEADER_NAMES = [\n \"authorization\",\n \"x-api-key\",\n \"user-agent\",\n \"x-session-id\",\n \"x-session-affinity\",\n \"x-parent-session-id\",\n \"x-trace-id\",\n]\n\ntype ServerWebSocket = Bun.ServerWebSocket<ResponsesWebSocketData>\ntype AppFetch = (request: Request) => Response | Promise<Response>\n\nexport type ResponsesWebSocketData = {\n // Codex keeps a single persistent websocket per session and pipelines turns\n // over it: a turn's `response.create` can arrive before the previous turn's\n // SSE relay has finished tearing down. Bun does not serialize async `message`\n // callbacks, so we chain work on this promise to process frames strictly in\n // arrival order instead of rejecting concurrent frames.\n queue: Promise<void>\n // In-flight upstream requests, one AbortController per active `response.create`\n // frame, so a client disconnect can abort all of them.\n controllers: Set<AbortController>\n headers: Array<[string, string]>\n url: string\n // Stable id minted per bridge connection. It is forwarded to the upstream\n // Responses pool (via `x-responses-bridge-id`) so the pool can close this exact\n // socket when its upstream connection is reaped, forcing Codex to rebuild a\n // fresh full-context session instead of stalling on a stale\n // `previous_response_id`.\n bridgeId: string\n}\n\ntype ResponsesWebSocketFrame = {\n type?: unknown\n [key: string]: unknown\n}\n\nexport function createResponsesWebSocketHandler(\n appFetch: AppFetch,\n): Bun.WebSocketHandler<ResponsesWebSocketData> {\n return {\n data: {} as ResponsesWebSocketData,\n idleTimeout: 0,\n open(ws) {\n // Register a closer so the upstream pool can drop this socket when its\n // GitHub connection is reaped while idle.\n registerResponsesBridge(ws.data.bridgeId, () => {\n try {\n ws.close()\n } catch (error) {\n consola.warn(\"Failed to close Responses websocket bridge:\", error)\n }\n })\n },\n async message(ws, message) {\n await handleResponsesWebSocketMessage(ws, message, appFetch)\n },\n close(ws) {\n unregisterResponsesBridge(ws.data.bridgeId)\n // Abort every in-flight upstream Responses request so we stop consuming\n // tokens/quota and worker time once the client disconnects.\n for (const controller of ws.data.controllers) {\n controller.abort()\n }\n ws.data.controllers.clear()\n },\n }\n}\n\nexport function handleResponsesWebSocketUpgrade(\n req: Request,\n server: Bun.Server<ResponsesWebSocketData>,\n): Response | null | undefined {\n if (!isResponsesWebSocketUpgrade(req)) {\n return null\n }\n\n if (!isAuthorizedHeaders(req.headers)) {\n return createUnauthorizedRawResponse()\n }\n\n const upgraded = server.upgrade(req, {\n data: buildResponsesWebSocketData(req),\n })\n\n if (upgraded) {\n return undefined\n }\n\n return new Response(\"WebSocket upgrade failed\", { status: 400 })\n}\n\nexport function isResponsesWebSocketUpgrade(req: Request): boolean {\n if (req.method !== \"GET\") {\n return false\n }\n\n const pathname = new URL(req.url).pathname\n if (!RESPONSES_WEBSOCKET_PATHS.has(pathname)) {\n return false\n }\n\n return req.headers.get(\"upgrade\")?.toLowerCase() === \"websocket\"\n}\n\nexport async function handleResponsesWebSocketMessage(\n ws: ServerWebSocket,\n message: string | ArrayBuffer | Uint8Array,\n appFetch: AppFetch,\n): Promise<void> {\n let frame: ResponsesWebSocketFrame\n try {\n frame = JSON.parse(\n normalizeWebSocketMessage(message),\n ) as ResponsesWebSocketFrame\n } catch {\n sendResponsesWebSocketError(ws, \"Invalid websocket JSON frame\", 400)\n return\n }\n\n if (frame.type === \"response.processed\") {\n return\n }\n\n if (frame.type !== \"response.create\") {\n sendResponsesWebSocketError(ws, \"Unsupported websocket frame type\", 400)\n return\n }\n\n // Chain this frame after any in-flight work so pipelined turns are processed\n // strictly in arrival order. The assignment is synchronous, so even though Bun\n // may dispatch overlapping `message` callbacks, the ordering reflects the order\n // frames were received. We swallow any rejection from the prior link before\n // chaining so a single failed turn (e.g. `ws.send` throwing while the socket is\n // closing) can never poison `ws.data.queue` and block every subsequent turn for\n // the lifetime of the connection.\n const queued = ws.data.queue\n .catch(() => {})\n .then(() => processResponseCreateFrame(ws, frame, appFetch))\n ws.data.queue = queued\n await queued.catch(() => {})\n}\n\nasync function processResponseCreateFrame(\n ws: ServerWebSocket,\n frame: ResponsesWebSocketFrame,\n appFetch: AppFetch,\n): Promise<void> {\n if (frame.generate === false) {\n sendResponsesWebSocketWarmupCompleted(ws)\n return\n }\n\n const controller = new AbortController()\n ws.data.controllers.add(controller)\n try {\n await forwardResponseCreateFrame(ws, frame, appFetch, controller)\n } catch (error) {\n // A client disconnect aborts in-flight controllers; that is expected\n // teardown, not a failure to report back to the (now gone) client.\n if (controller.signal.aborted) {\n return\n }\n consola.warn(\"Responses websocket bridge failed:\", error)\n sendResponsesWebSocketError(\n ws,\n error instanceof Error ? error.message : String(error),\n 500,\n )\n } finally {\n ws.data.controllers.delete(controller)\n }\n}\n\nexport function parseSseRecords(chunk: string): {\n events: Array<string>\n remainder: string\n} {\n const events: Array<string> = []\n let remainder = chunk\n\n while (true) {\n const match = SSE_RECORD_SEPARATOR.exec(remainder)\n if (!match) {\n break\n }\n\n const record = remainder.slice(0, match.index)\n remainder = remainder.slice(match.index + match[0].length)\n const data = parseSseRecordData(record)\n if (data !== null && data !== \"[DONE]\") {\n events.push(data)\n }\n }\n\n return { events, remainder }\n}\n\nfunction buildResponsesWebSocketData(req: Request): ResponsesWebSocketData {\n return {\n queue: Promise.resolve(),\n controllers: new Set(),\n headers: collectForwardedHeaders(req.headers),\n url: req.url,\n bridgeId: randomUUID(),\n }\n}\n\nfunction collectForwardedHeaders(headers: Headers): Array<[string, string]> {\n const forwarded: Array<[string, string]> = []\n for (const name of FORWARDED_HEADER_NAMES) {\n const value = headers.get(name)\n if (value) {\n forwarded.push([name, value])\n }\n }\n return forwarded\n}\n\nasync function forwardResponseCreateFrame(\n ws: ServerWebSocket,\n frame: ResponsesWebSocketFrame,\n appFetch: AppFetch,\n controller: AbortController,\n): Promise<void> {\n const payload = { ...frame, stream: true }\n delete payload.type\n\n const response = await appFetch(\n new Request(buildInternalResponsesUrl(ws.data.url), {\n method: \"POST\",\n headers: buildInternalResponsesHeaders(ws.data.headers, ws.data.bridgeId),\n body: JSON.stringify(payload),\n signal: controller.signal,\n }),\n )\n\n if (!response.ok) {\n sendResponsesWebSocketError(\n ws,\n await readErrorResponseMessage(response),\n response.status,\n )\n return\n }\n\n if (!response.body) {\n sendResponsesWebSocketError(ws, \"Responses stream body is empty\", 500)\n return\n }\n\n await streamSseResponseToWebSocket(ws, response.body, controller)\n}\n\nfunction buildInternalResponsesUrl(sourceUrl: string): string {\n const url = new URL(sourceUrl)\n url.protocol = \"http:\"\n url.pathname =\n url.pathname.startsWith(\"/v1/\") ? \"/v1/responses\" : \"/responses\"\n url.search = \"\"\n url.hash = \"\"\n return url.toString()\n}\n\nfunction buildInternalResponsesHeaders(\n forwardedHeaders: Array<[string, string]>,\n bridgeId: string,\n): Headers {\n const headers = new Headers(forwardedHeaders)\n headers.set(\"content-type\", \"application/json\")\n headers.set(RESPONSES_BRIDGE_ID_HEADER, bridgeId)\n return headers\n}\n\nasync function streamSseResponseToWebSocket(\n ws: ServerWebSocket,\n body: ReadableStream<Uint8Array>,\n controller: AbortController,\n): Promise<void> {\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = \"\"\n\n // Cancel the upstream reader as soon as the connection is aborted (client\n // close or a failed send) so the upstream stream is torn down promptly.\n const onAbort = () => {\n void reader.cancel()\n }\n controller.signal.addEventListener(\"abort\", onAbort)\n\n try {\n while (!controller.signal.aborted) {\n const { done, value } = await reader.read()\n if (done) {\n break\n }\n\n buffer += decoder.decode(value, { stream: true })\n const parsed = parseSseRecords(buffer)\n buffer = parsed.remainder\n if (!relaySseEvents(ws, parsed.events, controller)) {\n return\n }\n }\n\n if (controller.signal.aborted) {\n return\n }\n\n buffer += decoder.decode()\n const parsed = parseSseRecords(`${buffer}\\n\\n`)\n relaySseEvents(ws, parsed.events, controller)\n } finally {\n controller.signal.removeEventListener(\"abort\", onAbort)\n try {\n reader.releaseLock()\n } catch {\n // Reader may already be released after cancellation; ignore.\n }\n }\n}\n\n/**\n * Relay parsed SSE events to the client. Returns `false` if a send failed and\n * the upstream request was aborted, signalling the caller to stop streaming.\n */\nfunction relaySseEvents(\n ws: ServerWebSocket,\n events: Array<string>,\n controller: AbortController,\n): boolean {\n for (const event of events) {\n if (controller.signal.aborted) {\n return false\n }\n try {\n ws.send(event)\n } catch (error) {\n consola.warn(\"Responses websocket send failed:\", error)\n controller.abort()\n return false\n }\n }\n return true\n}\n\nfunction parseSseRecordData(record: string): string | null {\n const lines = record.split(/\\r?\\n/u)\n const dataLines = lines\n .filter((line) => line.startsWith(\"data:\"))\n // Per the SSE spec, strip only a single optional leading space after the\n // colon (not arbitrary whitespace), preserving whitespace-sensitive data.\n .map((line) => (line.startsWith(\"data: \") ? line.slice(6) : line.slice(5)))\n\n if (dataLines.length === 0) {\n return null\n }\n\n return dataLines.join(\"\\n\")\n}\n\nfunction normalizeWebSocketMessage(\n message: string | ArrayBuffer | Uint8Array,\n): string {\n if (typeof message === \"string\") {\n return message\n }\n\n return new TextDecoder().decode(message)\n}\n\nfunction sendResponsesWebSocketError(\n ws: ServerWebSocket,\n message: string,\n status: number,\n): void {\n // Mirror the Responses stream error contract (see ResponseErrorEvent in\n // src/services/copilot/create-responses.ts) so clients always receive the\n // same top-level event shape regardless of where the error originates.\n ws.send(\n JSON.stringify({\n code: status ? String(status) : null,\n message,\n param: null,\n sequence_number: 0,\n type: \"error\",\n }),\n )\n}\n\nfunction sendResponsesWebSocketWarmupCompleted(ws: ServerWebSocket): void {\n ws.send(\n JSON.stringify({\n response: {\n id: \"\",\n },\n sequence_number: 0,\n type: \"response.completed\",\n }),\n )\n}\n\nasync function readErrorResponseMessage(response: Response): Promise<string> {\n const body = await response.text()\n if (!body) {\n return `Responses request failed with status ${response.status}`\n }\n\n try {\n const parsed = JSON.parse(body) as {\n error?: { message?: unknown }\n message?: unknown\n }\n const message =\n typeof parsed.error?.message === \"string\" ? parsed.error.message\n : typeof parsed.message === \"string\" ? parsed.message\n : undefined\n return message ?? body\n } catch {\n return body\n }\n}\n","import { execSync } from \"node:child_process\"\nimport process from \"node:process\"\n\ntype ShellName = \"bash\" | \"zsh\" | \"fish\" | \"powershell\" | \"cmd\" | \"sh\"\ntype EnvVars = Record<string, string | undefined>\n\nfunction getShell(): ShellName {\n const { platform, ppid, env } = process\n\n if (platform === \"win32\") {\n try {\n const command = `wmic process get ParentProcessId,Name | findstr \"${ppid}\"`\n const parentProcess = execSync(command, { stdio: \"pipe\" }).toString()\n\n if (parentProcess.toLowerCase().includes(\"powershell.exe\")) {\n return \"powershell\"\n }\n } catch {\n return \"cmd\"\n }\n\n return \"cmd\"\n } else {\n const shellPath = env.SHELL\n if (shellPath) {\n if (shellPath.endsWith(\"zsh\")) return \"zsh\"\n if (shellPath.endsWith(\"fish\")) return \"fish\"\n if (shellPath.endsWith(\"bash\")) return \"bash\"\n }\n\n return \"sh\"\n }\n}\n\n/**\n * Generates a copy-pasteable script to set multiple environment variables\n * and run a subsequent command.\n * @param {EnvVars} envVars - An object of environment variables to set.\n * @param {string} commandToRun - The command to run after setting the variables.\n * @returns {string} The formatted script string.\n */\nexport function generateEnvScript(\n envVars: EnvVars,\n commandToRun: string = \"\",\n): string {\n const shell = getShell()\n const filteredEnvVars = Object.entries(envVars).filter(\n ([, value]) => value !== undefined,\n ) as Array<[string, string]>\n\n let commandBlock: string\n\n switch (shell) {\n case \"powershell\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `$env:${key} = ${value}`)\n .join(\"; \")\n break\n }\n case \"cmd\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set ${key}=${value}`)\n .join(\" & \")\n break\n }\n case \"fish\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set -gx ${key} ${value}`)\n .join(\"; \")\n break\n }\n default: {\n // bash, zsh, sh\n const assignments = filteredEnvVars\n .map(([key, value]) => `${key}=${value}`)\n .join(\" \")\n commandBlock = filteredEnvVars.length > 0 ? `export ${assignments}` : \"\"\n break\n }\n }\n\n if (commandBlock && commandToRun) {\n const separator = shell === \"cmd\" ? \" & \" : \" && \"\n return `${commandBlock}${separator}${commandToRun}`\n }\n\n return commandBlock || commandToRun\n}\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\n\nimport {\n registerQuotaRefreshSchedulerShutdownCleanup,\n startQuotaRefreshSchedulerFromConfig,\n stopQuotaRefreshScheduler,\n} from \"~/lib/quota-refresh-scheduler-runtime\"\nimport { isMcpHttpEnabledFromEnv } from \"~/mcp-http-config\"\nimport {\n createResponsesWebSocketHandler,\n handleResponsesWebSocketUpgrade,\n} from \"~/routes/responses/websocket\"\n\nimport { accountsManager } from \"./lib/accounts-manager\"\nimport { addAccountToRegistry, saveAccountToken } from \"./lib/accounts-registry\"\nimport {\n getModelRefreshIntervalMs,\n isAccountAffinityEnabled,\n mergeConfigWithDefaults,\n} from \"./lib/config\"\nimport { initOpencodeVersion } from \"./lib/opencode\"\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { applySharedSessionAffinityRetention } from \"./lib/session-affinity-store\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport { parseAccountType, type AccountType } from \"./lib/types/account\"\nimport {\n cacheMacMachineId,\n cacheVSCodeVersion,\n cacheVsCodeSessionId,\n cacheVsCodeDeviceId,\n} from \"./lib/utils\"\nimport { getDeviceCode } from \"./services/github/get-device-code\"\nimport { getGitHubUser } from \"./services/github/get-user\"\nimport { pollAccessToken } from \"./services/github/poll-access-token\"\n\ninterface RunServerOptions {\n port: number\n verbose: boolean\n accountType: AccountType\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n proxyEnv: boolean\n skipAuth: boolean\n enableMcpHttp: boolean\n}\n\n/**\n * Run the interactive authentication flow to add a new account.\n * Called automatically when no accounts are found.\n */\nasync function runAuthFlow(accountType: AccountType): Promise<void> {\n consola.warn(\"No accounts found. Starting authentication flow...\")\n\n // Start device code flow\n const deviceResponse = await getDeviceCode()\n consola.info(\n `Please enter the code \"${deviceResponse.user_code}\" at ${deviceResponse.verification_uri}`,\n )\n\n // Poll for access token\n const token = await pollAccessToken(deviceResponse)\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n\n // Get user info to determine account ID\n const user = await getGitHubUser({\n githubToken: token,\n accountType,\n })\n const accountId = user.login\n\n // Save token and add to registry\n await saveAccountToken(accountId, token)\n await addAccountToRegistry({\n id: accountId,\n accountType,\n addedAt: Date.now(),\n })\n\n consola.success(`Account \"${accountId}\" added successfully!`)\n}\n\nfunction logClaudeCodeTip(): void {\n consola.log(\n \"\\n💡 Tip: The --claude-code flag simply generates a clipboard command for launching Claude Code. \\n\"\n + \"All models remain fully accessible without this flag, just configure the model ID directly in your settings.json file.\",\n )\n}\n\ntype AvailableModels = NonNullable<\n ReturnType<typeof accountsManager.getFirstAccountModels>\n>\n\nasync function setupClaudeCode(\n models: AvailableModels,\n serverUrl: string,\n): Promise<void> {\n const selectedModel = await consola.prompt(\n \"Select a model to use with Claude Code\",\n {\n type: \"select\",\n options: models.data.map((model) => model.id),\n },\n )\n\n const selectedSmallModel = await consola.prompt(\n \"Select a small model to use with Claude Code\",\n {\n type: \"select\",\n options: models.data.map((model) => model.id),\n },\n )\n\n const command = generateEnvScript(\n {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: \"dummy\",\n ANTHROPIC_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_HAIKU_MODEL: selectedSmallModel,\n DISABLE_NON_ESSENTIAL_MODEL_CALLS: \"1\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\n CLAUDE_CODE_ATTRIBUTION_HEADER: \"0\",\n CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: \"false\",\n CLAUDE_CODE_DISABLE_TERMINAL_TITLE: \"true\",\n CLAUDE_CODE_ENABLE_AWAY_SUMMARY: \"0\",\n CLAUDE_PLUGIN_ENABLE_QUESTION_RULES: \"true\",\n },\n \"claude\",\n )\n\n try {\n clipboard.writeSync(command)\n consola.success(\"Copied Claude Code command to clipboard!\")\n } catch {\n consola.warn(\n \"Failed to copy to clipboard. Here is the Claude Code command:\",\n )\n consola.log(command)\n }\n}\n\nexport async function runServer(options: RunServerOptions): Promise<void> {\n // Fail fast before any config merge, account init, interactive auth, or quota\n // scheduler work: the server relies on Bun.serve for the Responses WebSocket\n // transport, so running under Node would otherwise crash with\n // \"ReferenceError: Bun is not defined\" only after all that setup.\n if (typeof Bun === \"undefined\") {\n consola.error(\n \"The Responses WebSocket transport requires the Bun runtime. Start the proxy with 'bun' or 'bunx --bun' instead of Node.\",\n )\n process.exit(1)\n }\n\n // Work around unjs/consola#357 until a release includes PR #359.\n consola.options.throttle = 0\n\n // Ensure config is merged with defaults at startup\n mergeConfigWithDefaults()\n accountsManager.setAccountAffinityEnabled(isAccountAffinityEnabled())\n accountsManager.setModelsRefreshIntervalMs(getModelRefreshIntervalMs())\n\n await initOpencodeVersion()\n\n if (options.proxyEnv) {\n initProxyFromEnv()\n }\n\n const enableMcpHttp = options.enableMcpHttp || isMcpHttpEnabledFromEnv()\n if (enableMcpHttp) {\n consola.warn(\n \"Main server MCP endpoint is enabled and unauthenticated at /mcp.\",\n )\n }\n\n state.verbose = options.verbose\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.accountType = options.accountType\n if (options.accountType !== \"individual\") {\n consola.info(`Using ${options.accountType} plan GitHub account`)\n }\n\n state.manualApprove = options.manual\n state.rateLimitSeconds = options.rateLimit\n state.rateLimitWait = options.rateLimitWait\n state.showToken = options.showToken\n\n await ensurePaths()\n applySharedSessionAffinityRetention()\n await cacheVSCodeVersion()\n cacheMacMachineId()\n cacheVsCodeSessionId()\n await cacheVsCodeDeviceId()\n\n // Initialize accounts manager with VS Code version\n await accountsManager.initialize(state.vsCodeVersion)\n\n // If --github-token is provided, set it as a temporary (high priority) account\n if (options.githubToken) {\n await accountsManager.setTemporaryAccount(\n options.githubToken,\n options.accountType,\n )\n consola.info(\"Using provided GitHub token as temporary account\")\n }\n\n // Check if we have any accounts, if not, start the auth flow\n if (!accountsManager.hasAccounts()) {\n if (options.skipAuth) {\n consola.warn(\n \"No accounts found. Skipping auth flow (--skip-auth). Add accounts via the Admin UI.\",\n )\n } else {\n try {\n await runAuthFlow(options.accountType)\n\n // Re-initialize accounts manager with the new account\n accountsManager.shutdown()\n stopQuotaRefreshScheduler()\n await accountsManager.initialize(state.vsCodeVersion)\n accountsManager.setModelsRefreshIntervalMs(getModelRefreshIntervalMs())\n } catch (error) {\n consola.error(\"Failed to add account:\", error)\n process.exit(1)\n }\n }\n }\n\n startQuotaRefreshSchedulerFromConfig()\n registerQuotaRefreshSchedulerShutdownCleanup()\n\n // Get models from the first available account\n const models = accountsManager.getFirstAccountModels()\n\n consola.info(\n `Available models: \\n${models?.data.map((model) => `- ${model.id}`).join(\"\\n\") ?? \"(no models loaded)\"}`,\n )\n\n const serverUrl = `http://localhost:${options.port}`\n\n if (options.claudeCode) {\n logClaudeCodeTip()\n if (!models?.data.length) {\n consola.error(\n \"Claude Code requires available models. Add an account via the Admin UI or remove --claude-code.\",\n )\n process.exit(1)\n }\n await setupClaudeCode(models, serverUrl)\n }\n\n consola.box(`🌐 Admin UI: ${serverUrl}/admin`)\n\n const { createServer } = await import(\"./server\")\n const server = createServer({ enableMcpHttp })\n const responsesWebSocketHandler = createResponsesWebSocketHandler(\n server.fetch,\n )\n\n Bun.serve({\n port: options.port,\n idleTimeout: 0,\n fetch: (request, bunServer) => {\n const websocketResponse = handleResponsesWebSocketUpgrade(\n request,\n bunServer,\n )\n if (websocketResponse !== null) {\n return websocketResponse\n }\n\n return server.fetch(request)\n },\n websocket: responsesWebSocketHandler,\n })\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the Copilot API server\",\n },\n args: {\n port: {\n alias: \"p\",\n type: \"string\",\n default: \"4141\",\n description: \"Port to listen on\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type to use (individual, business, enterprise)\",\n },\n manual: {\n type: \"boolean\",\n default: false,\n description: \"Enable manual request approval\",\n },\n \"rate-limit\": {\n alias: \"r\",\n type: \"string\",\n description: \"Rate limit in seconds between requests\",\n },\n wait: {\n alias: \"w\",\n type: \"boolean\",\n default: false,\n description:\n \"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set\",\n },\n \"github-token\": {\n alias: \"g\",\n type: \"string\",\n description:\n \"Provide GitHub token directly (must be generated using the `auth` subcommand)\",\n },\n \"claude-code\": {\n alias: \"c\",\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Claude Code with Copilot API config\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub and Copilot tokens on fetch and refresh\",\n },\n \"proxy-env\": {\n type: \"boolean\",\n default: false,\n description: \"Initialize proxy from environment variables\",\n },\n \"skip-auth\": {\n type: \"boolean\",\n default: false,\n description:\n \"Skip the initial CLI auth flow when no accounts are found. Use this to add accounts via the Admin UI instead.\",\n },\n \"enable-mcp-http\": {\n type: \"boolean\",\n default: false,\n description:\n \"Expose the unauthenticated MCP Streamable HTTP endpoint at /mcp.\",\n },\n },\n run({ args }) {\n const rateLimitRaw = args[\"rate-limit\"]\n const rateLimit =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n rateLimitRaw === undefined ? undefined : Number.parseInt(rateLimitRaw, 10)\n\n let accountType: AccountType\n try {\n accountType = parseAccountType(args[\"account-type\"])\n } catch (error) {\n consola.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n }\n\n return runServer({\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n accountType,\n manual: args.manual,\n rateLimit,\n rateLimitWait: args.wait,\n githubToken: args[\"github-token\"],\n claudeCode: args[\"claude-code\"],\n showToken: args[\"show-token\"],\n proxyEnv: args[\"proxy-env\"],\n skipAuth: args[\"skip-auth\"],\n enableMcpHttp: args[\"enable-mcp-http\"],\n })\n },\n})\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { P as requestContext, b as HTTPError, g as getCopilotUsage, h as getDeviceCode, j as state, m as getGitHubUser, t as pollAccessToken, v as getProxyEnvDispatcher } from "./poll-access-token-GzVkiTH8.js";
|
|
2
2
|
import { t as PATHS } from "./paths-Bpsb62LK.js";
|
|
3
|
-
import {
|
|
3
|
+
import { k as setProviderConfig, m as getRawProviderConfig, w as isResponsesApiWebSocketEnabled } from "./config-BaU_aWgi.js";
|
|
4
4
|
import consola from "consola";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
6
6
|
import { createHash, randomBytes } from "node:crypto";
|
|
@@ -421,6 +421,7 @@ const createCodexResponsesWebSocketStreamChunk = (data) => {
|
|
|
421
421
|
if (data === "[DONE]") return { data };
|
|
422
422
|
try {
|
|
423
423
|
const parsed = JSON.parse(data);
|
|
424
|
+
if (parsed.type === "error" && parsed.error) parsed.message = parsed.error.message;
|
|
424
425
|
return {
|
|
425
426
|
data: JSON.stringify(parsed),
|
|
426
427
|
event: typeof parsed.type === "string" ? parsed.type : void 0,
|
|
@@ -943,4 +944,4 @@ async function logUser() {
|
|
|
943
944
|
//#endregion
|
|
944
945
|
export { forwardCodexResponses as a, loginCodex as i, setupCodexToken as n, setupGitHubToken as r, persistCodexCredentials as t };
|
|
945
946
|
|
|
946
|
-
//# sourceMappingURL=token-
|
|
947
|
+
//# sourceMappingURL=token-671YFxgv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-671YFxgv.js","names":["isConfiguredResponsesApiWebSocketEnabled","delay"],"sources":["../src/services/responses-websocket.ts","../src/services/codex/create-responses.ts","../src/lib/oauth/codex.ts","../src/lib/credential-store.ts","../src/lib/token.ts"],"sourcesContent":["import { WebSocket } from \"undici\"\n\nimport { getProxyEnvDispatcher } from \"~/lib/proxy\"\n\nexport interface PooledWebSocketRequest<TPayload> {\n headers: Record<string, string>\n payload: TPayload\n poolKey: string\n url: string\n}\n\nexport interface PooledWebSocketStreamOptions<TChunk> {\n createChunk: (data: string) => TChunk\n idleTimeoutMs?: number\n isTerminalChunk: (chunk: TChunk) => boolean\n openErrorMessage: string\n streamErrorMessage: string\n terminalChunkMissingMessage: string\n unavailableErrorMessage?: string\n}\n\ntype WebSocketErrorEvent = Parameters<\n NonNullable<InstanceType<typeof WebSocket>[\"onerror\"]>\n>[0]\n\nconst DEFAULT_WEBSOCKET_IDLE_TIMEOUT_MS = 60_000\n\nconst websocketPool = new Map<string, PooledWebSocketEntry>()\nconst websocketActiveRequests = new Map<string, number>()\n\ninterface PooledWebSocketEntry {\n closed: boolean\n idleTimer: ReturnType<typeof setTimeout> | null\n requestCount: number\n websocketPromise: Promise<InstanceType<typeof WebSocket>>\n}\n\ninterface PooledWebSocketRequestTarget {\n entry: PooledWebSocketEntry\n pooled: boolean\n}\n\nexport const createWebSocketUrl = (url: string): string => {\n const websocketUrl = new URL(url)\n\n if (websocketUrl.protocol === \"https:\") {\n websocketUrl.protocol = \"wss:\"\n } else if (websocketUrl.protocol === \"http:\") {\n websocketUrl.protocol = \"ws:\"\n }\n\n return websocketUrl.toString()\n}\n\nexport const createPooledWebSocketStream = <TPayload, TChunk>(\n request: PooledWebSocketRequest<TPayload>,\n options: PooledWebSocketStreamOptions<TChunk>,\n): AsyncIterable<TChunk> => runPooledWebSocketRequest(request, options)\n\nconst runPooledWebSocketRequest = async function* <TPayload, TChunk>(\n request: PooledWebSocketRequest<TPayload>,\n options: PooledWebSocketStreamOptions<TChunk>,\n): AsyncIterable<TChunk> {\n const { entry, pooled } = getPooledWebSocketRequestTarget(request, options)\n const release = acquirePooledWebSocketEntry(\n request.poolKey,\n entry,\n pooled,\n options,\n )\n\n try {\n const websocket = await getReadyPooledWebSocket(\n request.poolKey,\n entry,\n pooled,\n options,\n )\n websocket.send(JSON.stringify(request.payload))\n\n for await (const data of createWebSocketMessageStream(websocket, options)) {\n const chunk = options.createChunk(data)\n yield chunk\n\n if (options.isTerminalChunk(chunk)) {\n return\n }\n }\n\n removePooledWebSocketEntry(request.poolKey, entry)\n throw new Error(options.terminalChunkMissingMessage)\n } catch (error) {\n removePooledWebSocketEntry(request.poolKey, entry)\n throw toError(error)\n } finally {\n release()\n }\n}\n\nconst getPooledWebSocketRequestTarget = <TPayload, TChunk>(\n request: PooledWebSocketRequest<TPayload>,\n options: PooledWebSocketStreamOptions<TChunk>,\n): PooledWebSocketRequestTarget => {\n if (getPooledWebSocketActiveRequestCount(request.poolKey) > 0) {\n return {\n entry: createPooledWebSocketEntry(request, options),\n pooled: false,\n }\n }\n\n const existing = websocketPool.get(request.poolKey)\n if (existing && !existing.closed) {\n clearPooledWebSocketIdleTimer(existing)\n return {\n entry: existing,\n pooled: true,\n }\n }\n\n const entry = createPooledWebSocketEntry(request, options)\n websocketPool.set(request.poolKey, entry)\n return {\n entry,\n pooled: true,\n }\n}\n\nconst createPooledWebSocketEntry = <TPayload, TChunk>(\n request: PooledWebSocketRequest<TPayload>,\n options: PooledWebSocketStreamOptions<TChunk>,\n): PooledWebSocketEntry => {\n const entry: PooledWebSocketEntry = {\n closed: false,\n idleTimer: null,\n requestCount: 0,\n websocketPromise: openWebSocket({\n headers: request.headers,\n openErrorMessage: options.openErrorMessage,\n url: request.url,\n }),\n }\n\n entry.websocketPromise\n .then((websocket) => {\n websocket.addEventListener(\"close\", () => {\n removePooledWebSocketEntry(request.poolKey, entry)\n })\n websocket.addEventListener(\"error\", () => {\n removePooledWebSocketEntry(request.poolKey, entry)\n })\n })\n .catch(() => {\n removePooledWebSocketEntry(request.poolKey, entry)\n })\n\n return entry\n}\n\nconst acquirePooledWebSocketEntry = <TChunk>(\n poolKey: string,\n entry: PooledWebSocketEntry,\n pooled: boolean,\n options: PooledWebSocketStreamOptions<TChunk>,\n): (() => void) => {\n clearPooledWebSocketIdleTimer(entry)\n incrementPooledWebSocketActiveRequestCount(poolKey)\n entry.requestCount += 1\n\n let released = false\n return () => {\n if (released) {\n return\n }\n\n released = true\n entry.requestCount -= 1\n\n decrementPooledWebSocketActiveRequestCount(poolKey)\n if (entry.closed || entry.requestCount > 0) {\n return\n }\n\n if (pooled && websocketPool.get(poolKey) === entry) {\n schedulePooledWebSocketIdleClose(poolKey, entry, options)\n return\n }\n\n removePooledWebSocketEntry(poolKey, entry)\n }\n}\n\nconst getReadyPooledWebSocket = async (\n poolKey: string,\n entry: PooledWebSocketEntry,\n pooled: boolean,\n options?: { unavailableErrorMessage?: string },\n): Promise<InstanceType<typeof WebSocket>> => {\n const unavailableErrorMessage =\n options?.unavailableErrorMessage\n ?? \"Websocket connection became unavailable before the request started\"\n\n if (entry.closed) {\n throw new Error(unavailableErrorMessage)\n }\n\n const websocket = await entry.websocketPromise\n if (entry.closed || (pooled && websocketPool.get(poolKey) !== entry)) {\n throw new Error(unavailableErrorMessage)\n }\n\n if (websocket.readyState !== WebSocket.OPEN) {\n removePooledWebSocketEntry(poolKey, entry)\n throw new Error(unavailableErrorMessage)\n }\n\n return websocket\n}\n\nconst schedulePooledWebSocketIdleClose = <TChunk>(\n poolKey: string,\n entry: PooledWebSocketEntry,\n options: PooledWebSocketStreamOptions<TChunk>,\n): void => {\n clearPooledWebSocketIdleTimer(entry)\n entry.idleTimer = setTimeout(() => {\n removePooledWebSocketEntry(poolKey, entry)\n }, options.idleTimeoutMs ?? DEFAULT_WEBSOCKET_IDLE_TIMEOUT_MS)\n unrefTimer(entry.idleTimer)\n}\n\nconst clearPooledWebSocketIdleTimer = (entry: PooledWebSocketEntry): void => {\n if (entry.idleTimer) {\n clearTimeout(entry.idleTimer)\n entry.idleTimer = null\n }\n}\n\nconst getPooledWebSocketActiveRequestCount = (poolKey: string): number =>\n websocketActiveRequests.get(poolKey) ?? 0\n\nconst incrementPooledWebSocketActiveRequestCount = (poolKey: string): void => {\n websocketActiveRequests.set(\n poolKey,\n getPooledWebSocketActiveRequestCount(poolKey) + 1,\n )\n}\n\nconst decrementPooledWebSocketActiveRequestCount = (poolKey: string): void => {\n const nextCount = getPooledWebSocketActiveRequestCount(poolKey) - 1\n if (nextCount <= 0) {\n websocketActiveRequests.delete(poolKey)\n return\n }\n\n websocketActiveRequests.set(poolKey, nextCount)\n}\n\nconst removePooledWebSocketEntry = (\n poolKey: string,\n entry: PooledWebSocketEntry,\n): void => {\n if (websocketPool.get(poolKey) === entry) {\n websocketPool.delete(poolKey)\n }\n\n if (entry.closed) {\n return\n }\n\n entry.closed = true\n clearPooledWebSocketIdleTimer(entry)\n entry.websocketPromise.then(closeWebSocket).catch(() => {})\n}\n\nconst unrefTimer = (timer: ReturnType<typeof setTimeout>): void => {\n if (\n typeof timer === \"object\"\n && \"unref\" in timer\n && typeof timer.unref === \"function\"\n ) {\n timer.unref()\n }\n}\n\nconst createWebSocketError = (\n message: string,\n event?: Pick<WebSocketErrorEvent, \"error\" | \"message\">,\n): Error => {\n const reason = event?.error ?? event?.message\n if (reason === undefined || reason === \"\") {\n return new Error(message)\n }\n\n const cause = toError(reason)\n return new Error(`${message}: ${cause.message}`, { cause })\n}\n\nconst openWebSocket = async ({\n headers,\n openErrorMessage,\n url,\n}: {\n headers: Record<string, string>\n openErrorMessage: string\n url: string\n}): Promise<InstanceType<typeof WebSocket>> =>\n await new Promise((resolve, reject) => {\n const dispatcher = getProxyEnvDispatcher()\n const init = dispatcher ? { dispatcher, headers } : { headers }\n const websocket = new WebSocket(url, init)\n\n const cleanup = () => {\n websocket.removeEventListener(\"open\", onOpen)\n websocket.removeEventListener(\"error\", onError)\n }\n\n const onOpen = () => {\n cleanup()\n resolve(websocket)\n }\n\n const onError = (event: WebSocketErrorEvent) => {\n cleanup()\n reject(createWebSocketError(openErrorMessage, event))\n }\n\n websocket.addEventListener(\"open\", onOpen)\n websocket.addEventListener(\"error\", onError)\n })\n\nconst createWebSocketMessageStream = async function* <TChunk>(\n websocket: InstanceType<typeof WebSocket>,\n options: PooledWebSocketStreamOptions<TChunk>,\n): AsyncIterable<string> {\n const queue: Array<Promise<string>> = []\n let closed = false\n let error: Error | null = null\n let notify: (() => void) | null = null\n\n const wake = () => {\n notify?.()\n notify = null\n }\n\n const onMessage = (event: { data: unknown }) => {\n queue.push(normalizeWebSocketMessageData(event.data))\n wake()\n }\n\n const onClose = () => {\n closed = true\n wake()\n }\n\n const onError = (event: WebSocketErrorEvent) => {\n error = createWebSocketError(options.streamErrorMessage, event)\n wake()\n }\n\n websocket.addEventListener(\"message\", onMessage)\n websocket.addEventListener(\"close\", onClose)\n websocket.addEventListener(\"error\", onError)\n\n try {\n while (true) {\n const item = queue.shift()\n if (item) {\n yield await item\n continue\n }\n\n if (error) {\n throw toError(error)\n }\n\n if (closed) {\n break\n }\n\n await new Promise<void>((resolve) => {\n notify = resolve\n })\n }\n } finally {\n websocket.removeEventListener(\"message\", onMessage)\n websocket.removeEventListener(\"close\", onClose)\n websocket.removeEventListener(\"error\", onError)\n }\n}\n\nconst normalizeWebSocketMessageData = async (\n data: unknown,\n): Promise<string> => {\n if (typeof data === \"string\") {\n return data\n }\n\n if (data instanceof ArrayBuffer) {\n return new TextDecoder().decode(data)\n }\n\n if (ArrayBuffer.isView(data)) {\n const view = data\n return new TextDecoder().decode(\n new Uint8Array(\n view.buffer as ArrayBuffer,\n view.byteOffset,\n view.byteLength,\n ),\n )\n }\n\n if (isTextReadable(data)) {\n return await data.text()\n }\n\n return String(data)\n}\n\nconst isTextReadable = (\n value: unknown,\n): value is { text: () => Promise<string> } => {\n if (!value || typeof value !== \"object\" || !(\"text\" in value)) {\n return false\n }\n\n return typeof (value as { text?: unknown }).text === \"function\"\n}\n\nconst toError = (value: unknown): Error => {\n if (value instanceof Error) {\n return value\n }\n\n return new Error(String(value))\n}\n\nconst closeWebSocket = (websocket: InstanceType<typeof WebSocket>): void => {\n if (\n websocket.readyState === WebSocket.CONNECTING\n || websocket.readyState === WebSocket.OPEN\n ) {\n websocket.close()\n }\n}\n","import { createHash } from \"node:crypto\"\n\nimport { events, type ServerSentEventMessage } from \"fetch-event-stream\"\n\nimport type {\n CreateResponsesReturn,\n ResponseInputContent,\n ResponseInputItem,\n ResponseInputMessage,\n ResponsesPayload,\n ResponseErrorEvent,\n ResponsesResult,\n ResponsesStream,\n ResponsesTransport,\n} from \"~/services/copilot/create-responses\"\n\nimport { isResponsesApiWebSocketEnabled as isConfiguredResponsesApiWebSocketEnabled } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\nimport {\n createPooledWebSocketStream,\n createWebSocketUrl,\n type PooledWebSocketRequest,\n} from \"~/services/responses-websocket\"\nimport { requestContext } from \"~/lib/request-context\"\n\nexport const CODEX_API_BASE_URL = \"https://chatgpt.com/backend-api\"\n\ntype CodexResponsesWebSocketPayload = ResponsesPayload & {\n type: \"response.create\"\n}\n\ntype ServerSentEventChunk = ServerSentEventMessage\n\ntype CodexResponsesWebSocketRequest =\n PooledWebSocketRequest<CodexResponsesWebSocketPayload>\n\ninterface CodexResponsesHeaderOptions {\n stream?: boolean | null\n}\n\nconst STRIPPED_CODEX_REQUEST_HEADERS = new Set([\n \"authorization\",\n \"connection\",\n \"content-length\",\n \"host\",\n \"keep-alive\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"te\",\n \"trailer\",\n \"transfer-encoding\",\n \"upgrade\",\n \"x-api-key\",\n])\n\nconst STRIPPED_CODEX_WEBSOCKET_HEADERS = new Set([\"accept\", \"content-type\"])\n\nconst requireCodexAuthContext = (): {\n accessToken: string\n accountId: string\n} => {\n const accessToken = state.codexAccessToken\n const accountId = state.codexAccountId\n\n if (!accessToken) {\n throw new Error(\"Codex access token is not loaded\")\n }\n\n if (!accountId) {\n throw new Error(\"Codex account id is not loaded\")\n }\n\n return { accessToken, accountId }\n}\n\nexport function resolveCodexResponsesUrl(\n baseUrl: string = CODEX_API_BASE_URL,\n): string {\n const normalized = baseUrl.trim().replace(/\\/+$/, \"\")\n if (!normalized) {\n return `${CODEX_API_BASE_URL}/codex/responses`\n }\n\n if (normalized.endsWith(\"/codex/responses\")) {\n return normalized\n }\n\n if (normalized.endsWith(\"/codex\")) {\n return `${normalized}/responses`\n }\n\n return `${normalized}/codex/responses`\n}\n\nexport function buildCodexResponsesHeaders(\n requestHeaders: Headers,\n options: CodexResponsesHeaderOptions = {},\n): Headers {\n const { accessToken, accountId } = requireCodexAuthContext()\n const headers = new Headers()\n for (const [headerName, headerValue] of requestHeaders) {\n const headerNameLower = headerName.toLowerCase()\n if (STRIPPED_CODEX_REQUEST_HEADERS.has(headerNameLower)) {\n continue\n }\n if (headerNameLower.includes(\"trace\")) {\n continue\n }\n headers.set(headerName, headerValue)\n }\n\n if (!headers.has(\"accept\")) {\n headers.set(\n \"accept\",\n options.stream ? \"text/event-stream\" : \"application/json\",\n )\n }\n\n headers.set(\"authorization\", `Bearer ${accessToken}`)\n headers.set(\"chatgpt-account-id\", accountId)\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\")\n }\n if (!headers.has(\"OpenAI-Beta\")) {\n headers.set(\"OpenAI-Beta\", \"responses=experimental\")\n }\n if (!headers.has(\"originator\")) {\n headers.set(\"originator\", \"copilot-api\")\n }\n if (!headers.has(\"user-agent\")) {\n headers.set(\"user-agent\", \"copilot-api\")\n }\n if (headers.get(\"user-agent\")?.startsWith(\"opencode\")) {\n headers.set(\"originator\", \"opencode\")\n const sessionId = requestContext.getStore()?.sessionAffinity\n if (sessionId) {\n headers.set(\"session-id\", sessionId)\n }\n }\n return headers\n}\n\nexport function resolveCodexResponsesTransport(\n transport?: ResponsesTransport,\n): ResponsesTransport {\n return (\n transport\n ?? (isConfiguredResponsesApiWebSocketEnabled() ? \"websocket\" : \"http\")\n )\n}\n\nexport function buildCodexResponsesWebSocketHeaders(\n requestHeaders: Headers,\n): Record<string, string> {\n const headers = buildCodexResponsesHeaders(requestHeaders)\n for (const headerName of STRIPPED_CODEX_WEBSOCKET_HEADERS) {\n headers.delete(headerName)\n }\n return Object.fromEntries(headers)\n}\n\nexport function buildCodexResponsesWebSocketPayload(\n payload: ResponsesPayload,\n): CodexResponsesWebSocketPayload {\n const websocketPayload: CodexResponsesWebSocketPayload = {\n ...normalizeCodexResponsesPayload(payload),\n type: \"response.create\",\n }\n\n delete websocketPayload.stream\n\n return websocketPayload\n}\n\nexport function buildCodexResponsesWebSocketUrl(\n baseUrl: string = CODEX_API_BASE_URL,\n): string {\n return createWebSocketUrl(resolveCodexResponsesUrl(baseUrl))\n}\n\nexport function prepareCodexResponsesWebSocketRequest(\n payload: ResponsesPayload,\n requestHeaders: Headers,\n baseUrl: string = CODEX_API_BASE_URL,\n): CodexResponsesWebSocketRequest {\n const headers = buildCodexResponsesWebSocketHeaders(requestHeaders)\n\n return {\n headers,\n payload: buildCodexResponsesWebSocketPayload(payload),\n poolKey: buildCodexResponsesWebSocketPoolKey(payload, headers, baseUrl),\n url: buildCodexResponsesWebSocketUrl(baseUrl),\n }\n}\n\nexport async function forwardCodexResponses(\n payload: ResponsesPayload,\n requestHeaders: Headers,\n baseUrl: string = CODEX_API_BASE_URL,\n options: {\n transport?: ResponsesTransport\n } = {},\n): Promise<CreateResponsesReturn> {\n const transport = resolveCodexResponsesTransport(options.transport)\n if (payload.stream && transport === \"websocket\") {\n return forwardCodexResponsesOverWebSocket(payload, requestHeaders, baseUrl)\n }\n\n const normalizedPayload = normalizeCodexResponsesPayload(payload)\n\n const response = await fetch(resolveCodexResponsesUrl(baseUrl), {\n method: \"POST\",\n headers: buildCodexResponsesHeaders(requestHeaders, {\n stream: normalizedPayload.stream,\n }),\n body: JSON.stringify(normalizedPayload),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to create codex responses\", response)\n }\n\n if (normalizedPayload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ResponsesResult\n}\n\nconst normalizeCodexResponsesPayload = (\n payload: ResponsesPayload,\n): ResponsesPayload => {\n const normalizedPayload: ResponsesPayload = {\n ...payload,\n store: false,\n }\n\n delete normalizedPayload.temperature\n delete normalizedPayload.top_p\n delete normalizedPayload.max_output_tokens\n delete normalizedPayload.metadata\n\n if (\n (typeof normalizedPayload.instructions === \"string\"\n && normalizedPayload.instructions.trim().length > 0)\n || !Array.isArray(normalizedPayload.input)\n ) {\n return normalizedPayload\n }\n\n const instructions: Array<string> = []\n let messageCount = 0\n const remainingInput = normalizedPayload.input.filter((inputItem) => {\n const message = getResponseInputMessage(inputItem)\n if (!message) {\n return true\n }\n\n messageCount += 1\n if (message.role !== \"system\" || messageCount > 3) {\n return true\n }\n\n const systemPrompt = getTextContent(message.content)\n if (systemPrompt === undefined) {\n return true\n }\n if (systemPrompt.trim().length > 0) {\n instructions.push(systemPrompt)\n }\n\n return false\n })\n\n if (remainingInput.length === normalizedPayload.input.length) {\n return normalizedPayload\n }\n\n if (instructions.length > 0) {\n // Codex expects system prompts in instructions instead of input messages.\n normalizedPayload.instructions = instructions.join(\"\\n\\n\")\n }\n\n if (remainingInput.length > 0) {\n normalizedPayload.input = remainingInput\n } else {\n delete normalizedPayload.input\n }\n\n return normalizedPayload\n}\n\nconst getResponseInputMessage = (\n inputItem: ResponseInputItem,\n): ResponseInputMessage | undefined => {\n if (typeof inputItem !== \"object\" || inputItem === null) {\n return undefined\n }\n\n const { role, type } = inputItem as {\n role?: unknown\n type?: unknown\n }\n if (typeof role !== \"string\" || (type !== undefined && type !== \"message\")) {\n return undefined\n }\n\n return inputItem as ResponseInputMessage\n}\n\nconst getTextContent = (\n content: ResponseInputMessage[\"content\"],\n): string | undefined => {\n if (typeof content === \"string\") {\n return content\n }\n\n if (content === undefined) {\n return \"\"\n }\n\n if (!Array.isArray(content)) {\n return undefined\n }\n\n const textBlocks: Array<string> = []\n for (const contentBlock of content) {\n const text = getTextBlock(contentBlock)\n if (text === undefined) {\n return undefined\n }\n\n if (text.length > 0) {\n textBlocks.push(text)\n }\n }\n\n return textBlocks.join(\"\\n\\n\")\n}\n\nconst getTextBlock = (\n contentBlock: ResponseInputContent,\n): string | undefined => {\n if (typeof contentBlock !== \"object\" || contentBlock === null) {\n return undefined\n }\n\n const { text, type } = contentBlock as {\n text?: unknown\n type?: unknown\n }\n\n if (type !== undefined && type !== \"input_text\" && type !== \"output_text\") {\n return undefined\n }\n\n return typeof text === \"string\" ? text : undefined\n}\n\nconst buildCodexResponsesWebSocketPoolKey = (\n payload: ResponsesPayload,\n headers: Record<string, string>,\n baseUrl: string,\n): string => {\n const authFingerprint = createHash(\"sha256\")\n .update(\n `${state.codexAccessToken ?? \"missing-token\"}:${state.codexAccountId ?? \"missing-account\"}`,\n )\n .digest(\"hex\")\n .slice(0, 16)\n const headerFingerprint = createHash(\"sha256\")\n .update(\n JSON.stringify(\n Object.entries(headers)\n .filter(([headerName]) => !headerName.toLowerCase().includes(\"trace\"))\n .sort(([left], [right]) => left.localeCompare(right)),\n ),\n )\n .digest(\"hex\")\n .slice(0, 16)\n\n return [\n \"codex\",\n resolveCodexResponsesUrl(baseUrl),\n payload.model,\n authFingerprint,\n headerFingerprint,\n ]\n .map(encodePoolKeyPart)\n .join(\"|\")\n}\n\nconst forwardCodexResponsesOverWebSocket = (\n payload: ResponsesPayload,\n requestHeaders: Headers,\n baseUrl: string,\n): ResponsesStream => {\n const websocketRequest = prepareCodexResponsesWebSocketRequest(\n payload,\n requestHeaders,\n baseUrl,\n )\n\n return createCodexResponsesWebSocketStream(websocketRequest)\n}\n\nconst createCodexResponsesWebSocketStream = (\n request: CodexResponsesWebSocketRequest,\n): ResponsesStream =>\n createCodexResponsesSafeStream(\n createPooledWebSocketStream(request, {\n createChunk: createCodexResponsesWebSocketStreamChunk,\n isTerminalChunk: isTerminalCodexResponsesWebSocketChunk,\n openErrorMessage: \"Failed to create codex responses websocket\",\n streamErrorMessage: \"Codex responses websocket stream error\",\n terminalChunkMissingMessage:\n \"Codex responses websocket ended without a terminal response\",\n }),\n )\n\nconst createCodexResponsesSafeStream = async function* (\n source: AsyncIterable<ServerSentEventChunk>,\n): AsyncGenerator<ServerSentEventChunk, void, unknown> {\n try {\n yield* source\n } catch (error) {\n yield createResponsesErrorServerSentEventChunk(getErrorMessage(error))\n }\n}\n\nconst createCodexResponsesWebSocketStreamChunk = (\n data: string,\n): ServerSentEventChunk => {\n if (data === \"[DONE]\") {\n return { data }\n }\n\n try {\n const parsed = JSON.parse(data) as {\n id?: unknown\n type?: unknown\n error?: {\n message: string\n }\n message?: string\n }\n\n if (parsed.type === \"error\" && parsed.error) {\n parsed.message = parsed.error.message\n }\n\n return {\n data: JSON.stringify(parsed),\n event: typeof parsed.type === \"string\" ? parsed.type : undefined,\n id: typeof parsed.id === \"string\" ? parsed.id : undefined,\n }\n } catch {\n return { data }\n }\n}\n\nconst isTerminalCodexResponsesWebSocketChunk = (\n chunk: ServerSentEventChunk,\n): boolean => {\n if (!chunk.data || chunk.data === \"[DONE]\") {\n return false\n }\n\n try {\n const parsed = JSON.parse(chunk.data) as { type?: unknown }\n return (\n parsed.type === \"response.completed\"\n || parsed.type === \"response.failed\"\n || parsed.type === \"response.incomplete\"\n || parsed.type === \"error\"\n )\n } catch {\n return false\n }\n}\n\nconst createResponsesErrorServerSentEventChunk = (\n message: string,\n): ServerSentEventChunk => {\n const errorEvent: ResponseErrorEvent = {\n code: null,\n message,\n param: null,\n sequence_number: 0,\n type: \"error\",\n }\n\n return {\n data: JSON.stringify(errorEvent),\n event: errorEvent.type,\n }\n}\n\nconst getErrorMessage = (error: unknown): string => {\n if (error instanceof Error && error.message) {\n return error.message\n }\n\n return String(error)\n}\n\nconst encodePoolKeyPart = (value: string): string => encodeURIComponent(value)\n","import { randomBytes } from \"node:crypto\"\nimport { createServer } from \"node:http\"\n\nexport { CODEX_API_BASE_URL } from \"~/services/codex/create-responses\"\n\nconst CALLBACK_HOST = \"127.0.0.1\"\nconst CALLBACK_PORT = 1455\nconst CALLBACK_PATH = \"/auth/callback\"\nconst CLIENT_ID = \"app_EMoamEEZ73f0CkXaXp7hrann\"\nconst AUTHORIZE_URL = \"https://auth.openai.com/oauth/authorize\"\nconst TOKEN_URL = \"https://auth.openai.com/oauth/token\"\nconst REDIRECT_URI = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`\nconst SCOPE = \"openid profile email offline_access\"\nconst JWT_CLAIM_PATH = \"https://api.openai.com/auth\"\nconst REFRESH_BUFFER_MS = 60_000\n\ninterface TokenSuccessResult {\n accessToken: string\n refreshToken: string\n expiresAt: number\n}\n\ninterface OAuthPageOptions {\n title: string\n heading: string\n message: string\n}\n\nexport interface CodexCredentials {\n accessToken: string\n refreshToken: string\n expiresAt: number\n accountId: string\n}\n\nexport interface CodexAuthInfo {\n url: string\n instructions?: string\n}\n\nexport interface LoginCodexOptions {\n onAuth: (info: CodexAuthInfo) => void\n onPrompt: (message: string) => Promise<string>\n onProgress?: (message: string) => void\n}\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString(\"base64url\")\n}\n\nasync function generatePkce(): Promise<{\n verifier: string\n challenge: string\n}> {\n const verifierBytes = new Uint8Array(32)\n crypto.getRandomValues(verifierBytes)\n const verifier = base64UrlEncode(verifierBytes)\n const hashBuffer = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(verifier),\n )\n\n return {\n verifier,\n challenge: base64UrlEncode(new Uint8Array(hashBuffer)),\n }\n}\n\nfunction createState(): string {\n return randomBytes(16).toString(\"hex\")\n}\n\nfunction parseAuthorizationInput(input: string): {\n code?: string\n state?: string\n} {\n const value = input.trim()\n if (!value) {\n return {}\n }\n\n try {\n const url = new URL(value)\n return {\n code: url.searchParams.get(\"code\") ?? undefined,\n state: url.searchParams.get(\"state\") ?? undefined,\n }\n } catch {\n // Continue and parse it as plain text.\n }\n\n if (value.includes(\"#\")) {\n const [code, state] = value.split(\"#\", 2)\n return { code, state }\n }\n\n if (value.includes(\"code=\")) {\n const params = new URLSearchParams(value)\n return {\n code: params.get(\"code\") ?? undefined,\n state: params.get(\"state\") ?? undefined,\n }\n }\n\n return { code: value }\n}\n\nfunction decodeJwt(accessToken: string): Record<string, unknown> | null {\n try {\n const payload = accessToken.split(\".\")[1]\n if (!payload) {\n return null\n }\n return JSON.parse(\n Buffer.from(payload, \"base64url\").toString(\"utf8\"),\n ) as Record<string, unknown>\n } catch {\n return null\n }\n}\n\nfunction getAccountId(accessToken: string): string | null {\n const payload = decodeJwt(accessToken)\n if (!payload) {\n return null\n }\n\n const authPayload = payload[JWT_CLAIM_PATH]\n if (!authPayload || typeof authPayload !== \"object\") {\n return null\n }\n\n const accountId = (authPayload as { chatgpt_account_id?: unknown })\n .chatgpt_account_id\n return typeof accountId === \"string\" && accountId ? accountId : null\n}\n\nfunction renderOAuthPage(options: OAuthPageOptions): string {\n return `<!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>${escapeHtml(options.title)}</title>\n <style>\n body {\n margin: 0;\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #09090b;\n color: #fafafa;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n text-align: center;\n }\n main {\n max-width: 560px;\n }\n h1 {\n margin: 0 0 12px;\n font-size: 28px;\n line-height: 1.15;\n }\n p {\n margin: 0;\n color: #a1a1aa;\n line-height: 1.6;\n }\n </style>\n</head>\n<body>\n <main>\n <h1>${escapeHtml(options.heading)}</h1>\n <p>${escapeHtml(options.message)}</p>\n </main>\n</body>\n</html>`\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\")\n}\n\nfunction renderOAuthSuccessPage(message: string): string {\n return renderOAuthPage({\n title: \"Authentication successful\",\n heading: \"Authentication successful\",\n message,\n })\n}\n\nfunction renderOAuthErrorPage(message: string): string {\n return renderOAuthPage({\n title: \"Authentication failed\",\n heading: \"Authentication failed\",\n message,\n })\n}\n\nasync function exchangeAuthorizationCode(\n code: string,\n verifier: string,\n): Promise<TokenSuccessResult> {\n const response = await fetch(TOKEN_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: CLIENT_ID,\n code,\n code_verifier: verifier,\n redirect_uri: REDIRECT_URI,\n }),\n })\n\n if (!response.ok) {\n const details = await response.text().catch(() => \"\")\n throw new Error(\n `Codex token exchange failed (${response.status}): ${details || response.statusText}`,\n )\n }\n\n const payload = (await response.json()) as {\n access_token?: unknown\n refresh_token?: unknown\n expires_in?: unknown\n }\n\n if (\n typeof payload.access_token !== \"string\"\n || typeof payload.refresh_token !== \"string\"\n || typeof payload.expires_in !== \"number\"\n ) {\n throw new TypeError(\n `Codex token exchange response missing fields: ${JSON.stringify(payload)}`,\n )\n }\n\n return {\n accessToken: payload.access_token,\n refreshToken: payload.refresh_token,\n expiresAt: Date.now() + payload.expires_in * 1000,\n }\n}\n\nasync function refreshAccessToken(\n refreshToken: string,\n): Promise<TokenSuccessResult> {\n const response = await fetch(TOKEN_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: refreshToken,\n client_id: CLIENT_ID,\n }),\n })\n\n if (!response.ok) {\n const details = await response.text().catch(() => \"\")\n throw new Error(\n `Codex token refresh failed (${response.status}): ${details || response.statusText}`,\n )\n }\n\n const payload = (await response.json()) as {\n access_token?: unknown\n refresh_token?: unknown\n expires_in?: unknown\n }\n\n if (\n typeof payload.access_token !== \"string\"\n || typeof payload.refresh_token !== \"string\"\n || typeof payload.expires_in !== \"number\"\n ) {\n throw new TypeError(\n `Codex token refresh response missing fields: ${JSON.stringify(payload)}`,\n )\n }\n\n return {\n accessToken: payload.access_token,\n refreshToken: payload.refresh_token,\n expiresAt: Date.now() + payload.expires_in * 1000,\n }\n}\n\nasync function createAuthorizationFlow(): Promise<{\n verifier: string\n state: string\n url: string\n}> {\n const { verifier, challenge } = await generatePkce()\n const state = createState()\n const url = new URL(AUTHORIZE_URL)\n url.searchParams.set(\"response_type\", \"code\")\n url.searchParams.set(\"client_id\", CLIENT_ID)\n url.searchParams.set(\"redirect_uri\", REDIRECT_URI)\n url.searchParams.set(\"scope\", SCOPE)\n url.searchParams.set(\"code_challenge\", challenge)\n url.searchParams.set(\"code_challenge_method\", \"S256\")\n url.searchParams.set(\"state\", state)\n url.searchParams.set(\"id_token_add_organizations\", \"true\")\n url.searchParams.set(\"codex_cli_simplified_flow\", \"true\")\n url.searchParams.set(\"originator\", \"copilot-api\")\n\n return { verifier, state, url: url.toString() }\n}\n\nasync function waitForAuthorizationCode(state: string): Promise<string | null> {\n let resolveCode: ((code: string | null) => void) | undefined\n const waitForCode = new Promise<string | null>((resolve) => {\n resolveCode = resolve\n })\n\n const server = createServer((request, response) => {\n try {\n const url = new URL(request.url || \"\", \"http://localhost\")\n if (url.pathname !== CALLBACK_PATH) {\n response.statusCode = 404\n response.setHeader(\"Content-Type\", \"text/html; charset=utf-8\")\n response.end(renderOAuthErrorPage(\"Callback route not found.\"))\n return\n }\n\n if (url.searchParams.get(\"state\") !== state) {\n response.statusCode = 400\n response.setHeader(\"Content-Type\", \"text/html; charset=utf-8\")\n response.end(renderOAuthErrorPage(\"State mismatch.\"))\n return\n }\n\n const code = url.searchParams.get(\"code\")\n if (!code) {\n response.statusCode = 400\n response.setHeader(\"Content-Type\", \"text/html; charset=utf-8\")\n response.end(renderOAuthErrorPage(\"Missing authorization code.\"))\n return\n }\n\n response.statusCode = 200\n response.setHeader(\"Content-Type\", \"text/html; charset=utf-8\")\n response.end(\n renderOAuthSuccessPage(\n \"OpenAI Codex authentication completed. You can close this window.\",\n ),\n )\n resolveCode?.(code)\n } catch {\n response.statusCode = 500\n response.setHeader(\"Content-Type\", \"text/html; charset=utf-8\")\n response.end(\n renderOAuthErrorPage(\"Internal error while processing OAuth callback.\"),\n )\n }\n })\n\n try {\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(CALLBACK_PORT, CALLBACK_HOST, () => {\n server.off(\"error\", reject)\n resolve()\n })\n })\n } catch {\n return null\n }\n\n try {\n return await waitForCode\n } finally {\n await new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error)\n return\n }\n resolve()\n })\n }).catch(() => undefined)\n }\n}\n\nexport async function loginCodex(\n options: LoginCodexOptions,\n): Promise<CodexCredentials> {\n const { verifier, state, url } = await createAuthorizationFlow()\n options.onAuth({\n url,\n instructions:\n \"Please complete the login in the browser. If the browser does not automatically redirect, please paste the callback URL or code back to the terminal.\",\n })\n options.onProgress?.(\"Waiting for Codex OAuth callback\")\n\n let code = await waitForAuthorizationCode(state)\n if (!code) {\n const input = await options.onPrompt(\n \"Paste the authorization code or full redirect URL:\",\n )\n const parsed = parseAuthorizationInput(input)\n if (parsed.state && parsed.state !== state) {\n throw new Error(\"Codex OAuth state mismatch\")\n }\n code = parsed.code ?? null\n }\n\n if (!code) {\n throw new Error(\"Missing Codex authorization code\")\n }\n\n const tokenResult = await exchangeAuthorizationCode(code, verifier)\n const accountId = getAccountId(tokenResult.accessToken)\n if (!accountId) {\n throw new Error(\"Failed to extract Codex account id from access token\")\n }\n\n return {\n accessToken: tokenResult.accessToken,\n refreshToken: tokenResult.refreshToken,\n expiresAt: tokenResult.expiresAt,\n accountId,\n }\n}\n\nexport async function refreshCodexCredentials(\n credentials: CodexCredentials,\n): Promise<CodexCredentials> {\n const tokenResult = await refreshAccessToken(credentials.refreshToken)\n const accountId = getAccountId(tokenResult.accessToken)\n if (!accountId) {\n throw new Error(\"Failed to extract Codex account id from access token\")\n }\n\n return {\n accessToken: tokenResult.accessToken,\n refreshToken: tokenResult.refreshToken,\n expiresAt: tokenResult.expiresAt,\n accountId,\n }\n}\n\nexport function isCodexCredentialsExpired(\n credentials: Pick<CodexCredentials, \"expiresAt\">,\n now: number = Date.now(),\n): boolean {\n return credentials.expiresAt <= now + REFRESH_BUFFER_MS\n}\n","import fs from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport type { CodexCredentials } from \"~/lib/oauth/codex\"\n\nimport { PATHS } from \"./paths\"\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error\n}\n\nasync function readOptionalFile(filePath: string): Promise<string | null> {\n try {\n return await fs.readFile(filePath, \"utf8\")\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return null\n }\n throw error\n }\n}\n\nasync function writeProtectedFile(\n filePath: string,\n content: string,\n): Promise<void> {\n await fs.mkdir(path.dirname(filePath), { recursive: true })\n await fs.writeFile(filePath, content, \"utf8\")\n try {\n await fs.chmod(filePath, 0o600)\n } catch {\n return\n }\n}\n\nfunction normalizeCodexCredentials(\n credentials: unknown,\n): CodexCredentials | null {\n if (!credentials || typeof credentials !== \"object\") {\n return null\n }\n\n const candidate = credentials as Partial<CodexCredentials>\n if (\n typeof candidate.accessToken !== \"string\"\n || typeof candidate.refreshToken !== \"string\"\n || typeof candidate.expiresAt !== \"number\"\n || typeof candidate.accountId !== \"string\"\n ) {\n return null\n }\n\n return {\n accessToken: candidate.accessToken,\n refreshToken: candidate.refreshToken,\n expiresAt: candidate.expiresAt,\n accountId: candidate.accountId,\n }\n}\n\nexport async function readGitHubToken(): Promise<string | null> {\n const token = await readOptionalFile(PATHS.GITHUB_TOKEN_PATH)\n const normalizedToken = token?.trim()\n return normalizedToken || null\n}\n\nexport async function writeGitHubToken(token: string): Promise<void> {\n await writeProtectedFile(PATHS.GITHUB_TOKEN_PATH, token.trim())\n}\n\nexport async function readCodexCredentials(): Promise<CodexCredentials | null> {\n const raw = await readOptionalFile(PATHS.CODEX_CREDENTIAL_PATH)\n if (!raw?.trim()) {\n return null\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw) as unknown\n } catch (error) {\n throw new Error(\n `Codex credentials file is not valid JSON: ${PATHS.CODEX_CREDENTIAL_PATH}`,\n {\n cause: error,\n },\n )\n }\n\n const credentials = normalizeCodexCredentials(parsed)\n if (!credentials) {\n throw new Error(\n `Codex credentials file is missing required fields: ${PATHS.CODEX_CREDENTIAL_PATH}`,\n )\n }\n\n return credentials\n}\n\nexport async function writeCodexCredentials(\n credentials: CodexCredentials,\n): Promise<void> {\n await writeProtectedFile(\n PATHS.CODEX_CREDENTIAL_PATH,\n `${JSON.stringify(credentials, null, 2)}\\n`,\n )\n}\n\nexport async function clearCodexCredentials(): Promise<void> {\n await writeProtectedFile(PATHS.CODEX_CREDENTIAL_PATH, \"\")\n}\n\nexport async function hasCodexCredentials(): Promise<boolean> {\n return (await readCodexCredentials()) !== null\n}\n","import consola from \"consola\"\nimport { setTimeout as delay } from \"node:timers/promises\"\n\nimport { isOpencodeOauthApp } from \"~/lib/api-config\"\nimport { getRawProviderConfig, setProviderConfig } from \"~/lib/config\"\nimport {\n readCodexCredentials,\n readGitHubToken,\n writeCodexCredentials,\n writeGitHubToken,\n} from \"~/lib/credential-store\"\nimport {\n isCodexCredentialsExpired,\n refreshCodexCredentials,\n type CodexCredentials,\n} from \"~/lib/oauth/codex\"\nimport { CODEX_API_BASE_URL } from \"~/services/codex/create-responses\"\nimport { getCopilotToken } from \"~/services/github/get-copilot-token\"\nimport { getCopilotUsage } from \"~/services/github/get-copilot-usage\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\nimport { getGitHubUser } from \"~/services/github/get-user\"\nimport { pollAccessToken } from \"~/services/github/poll-access-token\"\n\nimport { HTTPError } from \"./error\"\nimport { state } from \"./state\"\n\nlet copilotRefreshLoopController: AbortController | null = null\nlet codexRefreshLoopController: AbortController | null = null\n\nexport const stopCopilotRefreshLoop = () => {\n if (!copilotRefreshLoopController) {\n return\n }\n\n copilotRefreshLoopController.abort()\n copilotRefreshLoopController = null\n}\n\nexport const stopCodexRefreshLoop = () => {\n if (!codexRefreshLoopController) {\n return\n }\n\n codexRefreshLoopController.abort()\n codexRefreshLoopController = null\n}\n\nfunction applyCodexCredentials(credentials: CodexCredentials): void {\n state.codexAccessToken = credentials.accessToken\n state.codexRefreshToken = credentials.refreshToken\n state.codexExpiresAt = credentials.expiresAt\n state.codexAccountId = credentials.accountId\n\n consola.debug(\"Codex credentials loaded successfully\")\n if (state.showToken) {\n consola.info(\"Codex access token:\", credentials.accessToken)\n }\n}\n\nfunction getLoadedCodexCredentials(): CodexCredentials | null {\n if (\n !state.codexAccessToken\n || !state.codexRefreshToken\n || !state.codexExpiresAt\n || !state.codexAccountId\n ) {\n return null\n }\n\n return {\n accessToken: state.codexAccessToken,\n refreshToken: state.codexRefreshToken,\n expiresAt: state.codexExpiresAt,\n accountId: state.codexAccountId,\n }\n}\n\nfunction syncCodexProviderConfig(options?: { enabled?: boolean }): void {\n const existingProviderConfig = getRawProviderConfig(\"codex\") ?? {}\n setProviderConfig(\"codex\", {\n ...existingProviderConfig,\n type: \"openai-responses\",\n enabled: options?.enabled ?? existingProviderConfig.enabled,\n baseUrl: CODEX_API_BASE_URL,\n authType: \"oauth2\",\n })\n}\n\nexport async function persistCodexCredentials(\n credentials: CodexCredentials,\n options?: { enableProvider?: boolean },\n): Promise<void> {\n await writeCodexCredentials(credentials)\n syncCodexProviderConfig({\n enabled: options?.enableProvider ? true : undefined,\n })\n applyCodexCredentials(credentials)\n}\n\nexport const setupCopilotToken = async () => {\n if (isOpencodeOauthApp()) {\n if (!state.githubToken) throw new Error(`opencode token not found`)\n\n state.copilotToken = state.githubToken\n\n consola.debug(\"GitHub Copilot token set from opencode auth token\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", state.copilotToken)\n }\n\n stopCopilotRefreshLoop()\n return\n }\n\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n\n // Display the Copilot token to the screen\n consola.debug(\"GitHub Copilot Token fetched successfully!\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n stopCopilotRefreshLoop()\n\n const controller = new AbortController()\n copilotRefreshLoopController = controller\n\n runCopilotRefreshLoop(refresh_in, controller.signal)\n .catch(() => {\n consola.warn(\"Copilot token refresh loop stopped\")\n })\n .finally(() => {\n if (copilotRefreshLoopController === controller) {\n copilotRefreshLoopController = null\n }\n })\n}\n\nexport const setupCodexToken = async (): Promise<void> => {\n const loadedCredentials = getLoadedCodexCredentials()\n if (loadedCredentials && !isCodexCredentialsExpired(loadedCredentials)) {\n if (codexRefreshLoopController) {\n return\n }\n\n applyCodexCredentials(loadedCredentials)\n }\n\n const credentials = loadedCredentials ?? (await readCodexCredentials())\n if (!credentials) {\n throw new Error(\n `Codex credentials not found. Run \\`copilot-api auth login --provider codex\\` first.`,\n )\n }\n\n syncCodexProviderConfig()\n\n let nextCredentials = credentials\n if (isCodexCredentialsExpired(credentials)) {\n consola.debug(\"Refreshing expired Codex credentials\")\n nextCredentials = await refreshCodexCredentials(credentials)\n await persistCodexCredentials(nextCredentials)\n }\n\n applyCodexCredentials(nextCredentials)\n stopCodexRefreshLoop()\n\n const controller = new AbortController()\n codexRefreshLoopController = controller\n\n runCodexRefreshLoop(controller.signal)\n .catch(() => {\n consola.warn(\"Codex token refresh loop stopped\")\n })\n .finally(() => {\n if (codexRefreshLoopController === controller) {\n codexRefreshLoopController = null\n }\n })\n}\n\nconst REFRESH_POLL_INTERVAL_MS = 15_000\nconst EARLY_REFRESH_BUFFER_MS = 60_000\nconst RETRY_REFRESH_DELAY_MS = 15_000\nconst MIN_REFRESH_DELAY_MS = 1_000\n\nexport const getRefreshDeadlineMs = (\n refreshIn: number,\n nowMs: number = Date.now(),\n) =>\n nowMs\n + Math.max(refreshIn * 1000 - EARLY_REFRESH_BUFFER_MS, MIN_REFRESH_DELAY_MS)\n\n// Use short wall-clock chunks so the next wake after sleep notices elapsed time\n// quickly, without relying on the server's absolute expires_at matching local time.\nexport const getRefreshPollDelayMs = (\n refreshAtMs: number,\n nowMs: number = Date.now(),\n) => Math.min(Math.max(refreshAtMs - nowMs, 0), REFRESH_POLL_INTERVAL_MS)\n\nconst runCopilotRefreshLoop = async (\n refreshIn: number,\n signal: AbortSignal,\n) => {\n let refreshAtMs = getRefreshDeadlineMs(refreshIn)\n\n while (!signal.aborted) {\n const nextDelayMs = getRefreshPollDelayMs(refreshAtMs)\n if (nextDelayMs > 0) {\n await delay(nextDelayMs, undefined, { signal })\n continue\n }\n\n consola.debug(\"Refreshing Copilot token\")\n\n try {\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n refreshAtMs = getRefreshDeadlineMs(refresh_in)\n consola.debug(\"Copilot token refreshed\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n refreshAtMs = Date.now() + RETRY_REFRESH_DELAY_MS\n consola.warn(\n `Retrying Copilot token refresh in ${RETRY_REFRESH_DELAY_MS / 1000}s`,\n )\n }\n }\n}\n\nconst runCodexRefreshLoop = async (signal: AbortSignal) => {\n let refreshAtMs = Math.max(\n (state.codexExpiresAt ?? Date.now()) - EARLY_REFRESH_BUFFER_MS,\n Date.now(),\n )\n\n while (!signal.aborted) {\n const expiresAt = state.codexExpiresAt\n const refreshToken = state.codexRefreshToken\n if (!expiresAt || !refreshToken) {\n return\n }\n\n const nextDelayMs = getRefreshPollDelayMs(refreshAtMs)\n if (nextDelayMs > 0) {\n await delay(nextDelayMs, undefined, { signal })\n continue\n }\n\n consola.debug(\"Refreshing Codex credentials\")\n\n try {\n const credentials = await refreshCodexCredentials({\n accessToken: state.codexAccessToken ?? \"\",\n refreshToken,\n expiresAt,\n accountId: state.codexAccountId ?? \"\",\n })\n await persistCodexCredentials(credentials)\n refreshAtMs = Math.max(\n credentials.expiresAt - EARLY_REFRESH_BUFFER_MS,\n Date.now(),\n )\n consola.debug(\"Codex credentials refreshed\")\n } catch (error) {\n consola.error(\"Failed to refresh Codex credentials:\", error)\n refreshAtMs = Date.now() + RETRY_REFRESH_DELAY_MS\n consola.warn(\n `Retrying Codex token refresh in ${RETRY_REFRESH_DELAY_MS / 1000}s`,\n )\n }\n }\n}\n\ninterface SetupGitHubTokenOptions {\n force?: boolean\n}\n\nexport async function setupGitHubToken(\n options?: SetupGitHubTokenOptions,\n): Promise<void> {\n try {\n const githubToken = await readGitHubToken()\n\n if (githubToken && !options?.force) {\n state.githubToken = githubToken\n if (state.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n await logUser()\n\n return\n }\n\n consola.info(\"Not logged in, getting new access token\")\n const response = await getDeviceCode()\n consola.debug(\"Device code response:\", response)\n\n consola.info(\n `Please enter the code \"${response.user_code}\" in ${response.verification_uri}`,\n )\n\n const token = await pollAccessToken(response)\n await writeGitHubToken(token)\n state.githubToken = token\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n await logUser()\n } catch (error) {\n if (error instanceof HTTPError) {\n consola.error(\"Failed to get GitHub token:\", await error.response.json())\n throw error\n }\n\n consola.error(\"Failed to get GitHub token:\", error)\n throw error\n }\n}\n\nexport async function logUser() {\n const user = await getGitHubUser()\n state.userName = user.login\n consola.info(`Logged in as ${user.login}`)\n\n const copilotUser = await getCopilotUsage()\n state.copilotApiUrl = copilotUser.endpoints.api\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@nick3/copilot-api",
|
|
4
|
-
"version": "1.10.
|
|
4
|
+
"version": "1.10.34",
|
|
5
5
|
"description": "OpenAI and Anthropic-compatible gateway for GitHub Copilot or Codex or third-party providers.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"ai-gateway",
|