@jeffreycao/copilot-api 2.4.2 → 2.5.2
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 +19 -9
- package/README.zh-CN.md +19 -9
- package/dist/{auth-DvqwYkJr.js → auth-DQZ-A7MU.js} +3 -3
- package/dist/{auth-DvqwYkJr.js.map → auth-DQZ-A7MU.js.map} +1 -1
- package/dist/auth-GHhmC1D5.js +2 -0
- package/dist/{config-DVWu2hKk.js → config-Dj2ZvQuL.js} +39 -23
- package/dist/config-Dj2ZvQuL.js.map +1 -0
- package/dist/{debug-DwoWAiuC.js → debug-g1B6CGzU.js} +2 -2
- package/dist/{debug-DwoWAiuC.js.map → debug-g1B6CGzU.js.map} +1 -1
- package/dist/main.js +3 -3
- package/dist/{models-DKNAPa_j.js → models-12Y1nB8k.js} +2 -2
- package/dist/{models-DKNAPa_j.js.map → models-12Y1nB8k.js.map} +1 -1
- package/dist/{server-BvDQf9Nd.js → server-B4-mT5EU.js} +190 -128
- package/dist/server-B4-mT5EU.js.map +1 -0
- package/dist/{start-BGY-GA8y.js → start-BcGt4v2F.js} +99 -13
- package/dist/start-BcGt4v2F.js.map +1 -0
- package/dist/{token-D0GGk3E8.js → token-CaFzyRJX.js} +84 -77
- package/dist/token-CaFzyRJX.js.map +1 -0
- package/package.json +8 -4
- package/dist/auth-BCZdnMmK.js +0 -2
- package/dist/config-DVWu2hKk.js.map +0 -1
- package/dist/server-BvDQf9Nd.js.map +0 -1
- package/dist/start-BGY-GA8y.js.map +0 -1
- package/dist/token-D0GGk3E8.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as ensurePaths, i as listEnabledProviders, j as mergeConfigWithDefaults } from "./config-
|
|
2
|
-
import {
|
|
3
|
-
import { i as runProviderSetup } from "./auth-
|
|
4
|
-
import { n as getLatestModelForFamily } from "./models-
|
|
1
|
+
import { P as ensurePaths, i as listEnabledProviders, j as mergeConfigWithDefaults } from "./config-Dj2ZvQuL.js";
|
|
2
|
+
import { J as state, M as getConfiguredApiKeys, N as getMissingApiKeysMessage, Y as HTTPError, _ as copilotBaseUrl, g as readGitHubTokenFromEnv, h as readGitHubToken, i as setupCopilotToken, m as GITHUB_TOKEN_ENV, t as logUser, w as initOpencodeVersion, y as copilotModelsHeaders } from "./token-CaFzyRJX.js";
|
|
3
|
+
import { i as runProviderSetup } from "./auth-DQZ-A7MU.js";
|
|
4
|
+
import { n as getLatestModelForFamily } from "./models-12Y1nB8k.js";
|
|
5
5
|
import { defineCommand } from "citty";
|
|
6
6
|
import consola from "consola";
|
|
7
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -13,6 +13,7 @@ import { execSync } from "node:child_process";
|
|
|
13
13
|
import clipboard from "clipboardy";
|
|
14
14
|
import { serve } from "srvx";
|
|
15
15
|
import invariant from "tiny-invariant";
|
|
16
|
+
import { isIP } from "node:net";
|
|
16
17
|
import process$1 from "node:process";
|
|
17
18
|
//#region src/lib/proxy.ts
|
|
18
19
|
let proxyEnvDispatcher;
|
|
@@ -64,6 +65,65 @@ function initProxyFromEnv() {
|
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
//#endregion
|
|
68
|
+
//#region src/lib/server-host-shared.ts
|
|
69
|
+
const INVALID_HOST_CHARACTERS = /[\s/?#]/;
|
|
70
|
+
const NORMALIZED_WILDCARD_HOSTS = new Set(["0.0.0.0", "::"]);
|
|
71
|
+
function stripIpv6Brackets(hostname) {
|
|
72
|
+
if (hostname.startsWith("[") && hostname.endsWith("]")) return hostname.slice(1, -1);
|
|
73
|
+
return hostname;
|
|
74
|
+
}
|
|
75
|
+
function normalizeHostnameBase(hostname) {
|
|
76
|
+
const normalized = stripIpv6Brackets(hostname.trim());
|
|
77
|
+
if (!normalized || INVALID_HOST_CHARACTERS.test(normalized)) throw new Error(`Invalid server host: ${JSON.stringify(hostname)}`);
|
|
78
|
+
return normalized;
|
|
79
|
+
}
|
|
80
|
+
function isWildcardHostname(hostname) {
|
|
81
|
+
return NORMALIZED_WILDCARD_HOSTS.has(stripIpv6Brackets(hostname.trim()));
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/lib/server-host.ts
|
|
85
|
+
const DEFAULT_SERVER_HOST = "127.0.0.1";
|
|
86
|
+
function isLoopbackIpv4(hostname) {
|
|
87
|
+
return isIP(hostname) === 4 && hostname.split(".", 1)[0] === "127";
|
|
88
|
+
}
|
|
89
|
+
function isLoopbackMappedIpv4(hostname) {
|
|
90
|
+
try {
|
|
91
|
+
const mappedIpv4 = new URL(`http://[${hostname}]/`).hostname.slice(1, -1).match(/^::ffff:([\da-f]{1,4}):[\da-f]{1,4}$/);
|
|
92
|
+
if (!mappedIpv4) return false;
|
|
93
|
+
return (Number.parseInt(mappedIpv4[1], 16) & 65280) === 32512;
|
|
94
|
+
} catch {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function normalizeServerHostname(hostname) {
|
|
99
|
+
return normalizeHostnameBase(hostname);
|
|
100
|
+
}
|
|
101
|
+
function isLoopbackHostname(hostname) {
|
|
102
|
+
const normalized = normalizeServerHostname(hostname).toLowerCase();
|
|
103
|
+
if (normalized === "localhost" || normalized === "localhost.") return true;
|
|
104
|
+
if (isLoopbackIpv4(normalized)) return true;
|
|
105
|
+
if (isIP(normalized) !== 6) return false;
|
|
106
|
+
if (normalized === "::1" || normalized === "0:0:0:0:0:0:0:1") return true;
|
|
107
|
+
return isLoopbackMappedIpv4(normalized);
|
|
108
|
+
}
|
|
109
|
+
function resolveServerBinding(hostname, hasApiKeys) {
|
|
110
|
+
const normalizedHostname = normalizeServerHostname(hostname);
|
|
111
|
+
const networkExposed = !isLoopbackHostname(normalizedHostname);
|
|
112
|
+
if (networkExposed && !hasApiKeys) throw new Error(`Refusing to listen on non-loopback host ${JSON.stringify(normalizedHostname)} without gateway API keys. Run \`npx copilot-api auth keys --add <key>\` first, or use \`--host ${DEFAULT_SERVER_HOST}\`.`);
|
|
113
|
+
return {
|
|
114
|
+
hostname: normalizedHostname,
|
|
115
|
+
clientHostname: resolveClientHostname(normalizedHostname),
|
|
116
|
+
networkExposed
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function resolveClientHostname(hostname) {
|
|
120
|
+
const normalizedHostname = normalizeServerHostname(hostname);
|
|
121
|
+
return isWildcardHostname(normalizedHostname) ? DEFAULT_SERVER_HOST : normalizedHostname.toLowerCase();
|
|
122
|
+
}
|
|
123
|
+
function formatServerUrl(hostname, port) {
|
|
124
|
+
return `http://${isIP(hostname) === 6 ? `[${hostname.replace("%", "%25")}]` : hostname}:${port}`;
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
67
127
|
//#region src/lib/shell.ts
|
|
68
128
|
function getShell() {
|
|
69
129
|
const { platform, ppid, env } = process$1;
|
|
@@ -382,9 +442,26 @@ const cacheVsCodeSessionId = () => {
|
|
|
382
442
|
};
|
|
383
443
|
//#endregion
|
|
384
444
|
//#region src/start.ts
|
|
385
|
-
async function
|
|
445
|
+
async function resolveGitHubToken(cliToken) {
|
|
446
|
+
if (cliToken) return {
|
|
447
|
+
token: cliToken,
|
|
448
|
+
source: "cli"
|
|
449
|
+
};
|
|
450
|
+
const envToken = readGitHubTokenFromEnv();
|
|
451
|
+
if (envToken) return {
|
|
452
|
+
token: envToken,
|
|
453
|
+
source: "env"
|
|
454
|
+
};
|
|
455
|
+
const fileToken = await readGitHubToken();
|
|
456
|
+
if (fileToken) return {
|
|
457
|
+
token: fileToken,
|
|
458
|
+
source: "file"
|
|
459
|
+
};
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
async function setupCopilotMode(githubToken, source, serverUrl, claudeCode) {
|
|
386
463
|
state.githubToken = githubToken;
|
|
387
|
-
consola.info(
|
|
464
|
+
consola.info(source === "cli" ? "Using provided GitHub token" : source === "env" ? `Using GitHub token from the ${GITHUB_TOKEN_ENV} environment variable` : "Using GitHub token from local file");
|
|
388
465
|
await logUser();
|
|
389
466
|
await cacheVSCodeVersion();
|
|
390
467
|
cacheMacMachineId();
|
|
@@ -439,7 +516,7 @@ async function setupProviderMode(serverUrl, claudeCode) {
|
|
|
439
516
|
consola.info("No enabled providers found. Setting one up...");
|
|
440
517
|
await runProviderSetup();
|
|
441
518
|
if (state.githubToken) {
|
|
442
|
-
await setupCopilotMode(state.githubToken,
|
|
519
|
+
await setupCopilotMode(state.githubToken, "file", serverUrl, claudeCode);
|
|
443
520
|
return;
|
|
444
521
|
}
|
|
445
522
|
const providersAfterSetup = listEnabledProviders();
|
|
@@ -450,6 +527,8 @@ async function runServer(options) {
|
|
|
450
527
|
(await import("./tls-Aq1Dd8E2.js")).enableSystemCACompat();
|
|
451
528
|
consola.options.throttle = 0;
|
|
452
529
|
mergeConfigWithDefaults();
|
|
530
|
+
const configuredApiKeys = getConfiguredApiKeys();
|
|
531
|
+
const binding = resolveServerBinding(options.host, configuredApiKeys.length > 0);
|
|
453
532
|
const missingApiKeysMessage = getMissingApiKeysMessage();
|
|
454
533
|
if (missingApiKeysMessage) consola.info(missingApiKeysMessage);
|
|
455
534
|
await initOpencodeVersion();
|
|
@@ -461,14 +540,15 @@ async function runServer(options) {
|
|
|
461
540
|
}
|
|
462
541
|
state.showToken = options.showToken;
|
|
463
542
|
await ensurePaths();
|
|
464
|
-
const serverUrl =
|
|
465
|
-
const
|
|
466
|
-
if (
|
|
543
|
+
const serverUrl = formatServerUrl(binding.clientHostname, options.port);
|
|
544
|
+
const resolvedGitHubToken = await resolveGitHubToken(options.githubToken);
|
|
545
|
+
if (resolvedGitHubToken) await setupCopilotMode(resolvedGitHubToken.token, resolvedGitHubToken.source, serverUrl, options.claudeCode);
|
|
467
546
|
else await setupProviderMode(serverUrl, options.claudeCode);
|
|
468
547
|
consola.box(`🌐 Usage Viewer: ${serverUrl}/usage-viewer?endpoint=${serverUrl}/usage`);
|
|
469
|
-
const {
|
|
548
|
+
const { createServer } = await import("./server-B4-mT5EU.js");
|
|
470
549
|
serve({
|
|
471
|
-
fetch:
|
|
550
|
+
fetch: createServer({ networkExposed: binding.networkExposed }).fetch,
|
|
551
|
+
hostname: binding.hostname,
|
|
472
552
|
port: options.port,
|
|
473
553
|
bun: { idleTimeout: 0 }
|
|
474
554
|
});
|
|
@@ -479,6 +559,11 @@ const start = defineCommand({
|
|
|
479
559
|
description: "Start the Copilot API server"
|
|
480
560
|
},
|
|
481
561
|
args: {
|
|
562
|
+
host: {
|
|
563
|
+
type: "string",
|
|
564
|
+
default: process.env.HOST?.trim() || "127.0.0.1",
|
|
565
|
+
description: "Host to listen on"
|
|
566
|
+
},
|
|
482
567
|
port: {
|
|
483
568
|
alias: "p",
|
|
484
569
|
type: "string",
|
|
@@ -515,6 +600,7 @@ const start = defineCommand({
|
|
|
515
600
|
},
|
|
516
601
|
run({ args }) {
|
|
517
602
|
return runServer({
|
|
603
|
+
host: args.host,
|
|
518
604
|
port: Number.parseInt(args.port, 10),
|
|
519
605
|
verbose: args.verbose,
|
|
520
606
|
githubToken: args["github-token"],
|
|
@@ -527,4 +613,4 @@ const start = defineCommand({
|
|
|
527
613
|
//#endregion
|
|
528
614
|
export { start };
|
|
529
615
|
|
|
530
|
-
//# sourceMappingURL=start-
|
|
616
|
+
//# sourceMappingURL=start-BcGt4v2F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start-BcGt4v2F.js","names":["get","process","getCopilotModels"],"sources":["../src/lib/proxy.ts","../src/lib/server-host-shared.ts","../src/lib/server-host.ts","../src/lib/shell.ts","../src/services/copilot/get-models.ts","../src/services/copilot/models-cache.ts","../src/lib/deviceid.ts","../src/services/get-vscode-version.ts","../src/services/vscode-env.ts","../src/start.ts"],"sourcesContent":["import consola from \"consola\"\nimport { getProxyForUrl } from \"proxy-from-env\"\nimport { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from \"undici\"\n\nlet proxyEnvDispatcher: Dispatcher | undefined\n\nexport function getProxyEnvDispatcher(): Dispatcher | undefined {\n return proxyEnvDispatcher\n}\n\nexport function initProxyFromEnv(): void {\n try {\n const direct = new Agent()\n const proxies = new Map<string, ProxyAgent>()\n\n // We only need a minimal dispatcher that implements `dispatch` at runtime.\n // Typing the object as `Dispatcher` forces TypeScript to require many\n // additional methods. Instead, keep a plain object and cast when passing\n // to `setGlobalDispatcher`.\n const dispatcher = {\n dispatch(\n options: Dispatcher.DispatchOptions,\n handler: Dispatcher.DispatchHandler,\n ) {\n try {\n const origin =\n typeof options.origin === \"string\" ?\n new URL(options.origin)\n : (options.origin as URL)\n const get = getProxyForUrl as unknown as (\n u: string,\n ) => string | undefined\n const raw = get(origin.toString())\n const proxyUrl = raw && raw.length > 0 ? raw : undefined\n if (!proxyUrl) {\n consola.debug(`HTTP proxy bypass: ${origin.hostname}`)\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n let agent = proxies.get(proxyUrl)\n if (!agent) {\n agent = new ProxyAgent(proxyUrl)\n proxies.set(proxyUrl, agent)\n }\n let label = proxyUrl\n try {\n const u = new URL(proxyUrl)\n label = `${u.protocol}//${u.host}`\n } catch {\n /* noop */\n }\n consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`)\n return (agent as unknown as Dispatcher).dispatch(options, handler)\n } catch {\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n },\n close() {\n return direct.close()\n },\n destroy() {\n return direct.destroy()\n },\n }\n\n proxyEnvDispatcher = dispatcher as unknown as Dispatcher\n\n if (typeof Bun !== \"undefined\") {\n consola.debug(\"WebSocket proxy configured from environment (per-URL)\")\n return\n }\n\n setGlobalDispatcher(proxyEnvDispatcher)\n consola.debug(\"HTTP proxy configured from environment (per-URL)\")\n } catch (err) {\n consola.debug(\"Proxy setup skipped:\", err)\n }\n}\n","// Pure hostname helpers shared by the gateway server (Node) and the desktop\n// app (including the renderer bundle). This module must stay free of\n// `node:*` imports because the renderer cannot use `node:net`; all\n// address-family checks live in `server-host.ts`.\nexport const INVALID_HOST_CHARACTERS = /[\\s/?#]/\n\n// Bind hosts that listen on every interface, in normalized form (no\n// brackets, so \"[::]\" is covered via `stripIpv6Brackets`).\nexport const NORMALIZED_WILDCARD_HOSTS = new Set([\"0.0.0.0\", \"::\"])\n\nexport function stripIpv6Brackets(hostname: string): string {\n if (hostname.startsWith(\"[\") && hostname.endsWith(\"]\")) {\n return hostname.slice(1, -1)\n }\n return hostname\n}\n\nexport function normalizeHostnameBase(hostname: string): string {\n const normalized = stripIpv6Brackets(hostname.trim())\n if (!normalized || INVALID_HOST_CHARACTERS.test(normalized)) {\n throw new Error(`Invalid server host: ${JSON.stringify(hostname)}`)\n }\n return normalized\n}\n\nexport function isWildcardHostname(hostname: string): boolean {\n return NORMALIZED_WILDCARD_HOSTS.has(stripIpv6Brackets(hostname.trim()))\n}\n","import { isIP } from \"node:net\"\n\nimport { isWildcardHostname, normalizeHostnameBase } from \"./server-host-shared\"\n\nexport const DEFAULT_SERVER_HOST = \"127.0.0.1\"\n\n// Listen failures that mean the hostname itself cannot be bound, as opposed\n// to the port being occupied (EADDRINUSE) or forbidden (EACCES). ENOTFOUND\n// covers unresolvable names such as typos, EADDRNOTAVAIL covers valid IPs\n// that are not assigned to this machine.\nconst INVALID_BIND_ERROR_CODES = new Set([\n \"ENOTFOUND\",\n \"EADDRNOTAVAIL\",\n \"EINVAL\",\n \"EAFNOSUPPORT\",\n \"ENXIO\",\n])\n\nexport function isInvalidBindErrorCode(code?: string): boolean {\n return !!code && INVALID_BIND_ERROR_CODES.has(code)\n}\n\nexport interface ServerBinding {\n hostname: string\n clientHostname: string\n networkExposed: boolean\n}\n\nfunction isLoopbackIpv4(hostname: string): boolean {\n return isIP(hostname) === 4 && hostname.split(\".\", 1)[0] === \"127\"\n}\n\nfunction isLoopbackMappedIpv4(hostname: string): boolean {\n try {\n const canonicalHostname = new URL(`http://[${hostname}]/`).hostname.slice(\n 1,\n -1,\n )\n const mappedIpv4 = canonicalHostname.match(\n /^::ffff:([\\da-f]{1,4}):[\\da-f]{1,4}$/,\n )\n if (!mappedIpv4) {\n return false\n }\n\n return (Number.parseInt(mappedIpv4[1], 16) & 0xff00) === 0x7f00\n } catch {\n return false\n }\n}\n\nexport function normalizeServerHostname(hostname: string): string {\n return normalizeHostnameBase(hostname)\n}\n\nexport function isLoopbackHostname(hostname: string): boolean {\n const normalized = normalizeServerHostname(hostname).toLowerCase()\n if (normalized === \"localhost\" || normalized === \"localhost.\") {\n return true\n }\n if (isLoopbackIpv4(normalized)) {\n return true\n }\n if (isIP(normalized) !== 6) {\n return false\n }\n\n if (normalized === \"::1\" || normalized === \"0:0:0:0:0:0:0:1\") {\n return true\n }\n\n return isLoopbackMappedIpv4(normalized)\n}\n\nexport function resolveServerBinding(\n hostname: string,\n hasApiKeys: boolean,\n): ServerBinding {\n const normalizedHostname = normalizeServerHostname(hostname)\n const networkExposed = !isLoopbackHostname(normalizedHostname)\n\n if (networkExposed && !hasApiKeys) {\n throw new Error(\n `Refusing to listen on non-loopback host ${JSON.stringify(normalizedHostname)} without gateway API keys. Run \\`npx copilot-api auth keys --add <key>\\` first, or use \\`--host ${DEFAULT_SERVER_HOST}\\`.`,\n )\n }\n\n return {\n hostname: normalizedHostname,\n clientHostname: resolveClientHostname(normalizedHostname),\n networkExposed,\n }\n}\n\nexport function resolveClientHostname(hostname: string): string {\n const normalizedHostname = normalizeServerHostname(hostname)\n // Wildcard binds listen on every interface, which clients cannot dial\n // directly (0.0.0.0 is not a routable destination).\n return isWildcardHostname(normalizedHostname) ? DEFAULT_SERVER_HOST : (\n normalizedHostname.toLowerCase()\n )\n}\n\nexport function resolveClientHostnameOrDefault(\n hostname: string | null | undefined,\n): string {\n const normalizedHostname = hostname?.trim()\n return normalizedHostname ?\n resolveClientHostname(normalizedHostname)\n : DEFAULT_SERVER_HOST\n}\n\nexport function formatServerUrl(hostname: string, port: number): string {\n const urlHostname =\n isIP(hostname) === 6 ? `[${hostname.replace(\"%\", \"%25\")}]` : hostname\n return `http://${urlHostname}:${port}`\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","import consola from \"consola\"\n\nimport { copilotBaseUrl, copilotModelsHeaders } from \"~/lib/api-config\"\n\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\nimport type { ModelsResponse } from \"~/lib/types/models\"\n\nexport const getModels = async () => {\n consola.info(`Fetching models from ${copilotBaseUrl(state)}/models`)\n const response = await fetch(`${copilotBaseUrl(state)}/models`, {\n headers: copilotModelsHeaders(state),\n })\n\n if (!response.ok) {\n const errorText = await response.clone().text()\n\n consola.error(\"Failed to get models response body\", errorText)\n\n throw new HTTPError(\"Failed to get models\", response)\n }\n\n return (await response.json()) as ModelsResponse\n}\n","import consola from \"consola\"\n\nimport { state } from \"~/lib/state\"\nimport { getModels as getCopilotModels } from \"~/services/copilot/get-models\"\n\n// Periodically refresh models so long-running daemons pick up new SKUs.\nconst MODELS_REFRESH_BASE_MS = 30 * 60 * 1000\nlet modelsRefreshTimer: ReturnType<typeof setTimeout> | null = null\n\nexport const stopModelsRefreshLoop = () => {\n if (modelsRefreshTimer) {\n clearTimeout(modelsRefreshTimer)\n modelsRefreshTimer = null\n }\n}\n\ntype ModelsFetcher = typeof getCopilotModels\n\nconst refreshModels = async (fetcher: ModelsFetcher) => {\n const prevIds = new Set(state.models?.data.map((m) => m.id) ?? [])\n const models = await fetcher()\n state.models = {\n ...models,\n data: models.data.filter(\n (model) =>\n model.policy?.state !== \"disabled\"\n && (model.model_picker_enabled\n || model.capabilities.type === \"embeddings\"),\n ),\n }\n const nextIds = state.models.data.map((m) => m.id)\n const added = nextIds.filter((id) => !prevIds.has(id))\n if (added.length > 0) {\n consola.info(`Models refresh: ${added.length} new`)\n } else {\n consola.debug(`Models refresh: no changes (${nextIds.length} total)`)\n }\n}\n\nconst scheduleModelsRefresh = (fetcher: ModelsFetcher, intervalMs: number) => {\n const jitter = Math.floor(Math.random() * (intervalMs / 6))\n const delay = intervalMs + jitter\n consola.debug(\n `Scheduling next models refresh in ${Math.round(delay / 1000)} seconds`,\n )\n\n stopModelsRefreshLoop()\n modelsRefreshTimer = setTimeout(async () => {\n try {\n await refreshModels(fetcher)\n } catch (error) {\n consola.warn(\"Failed to refresh models, keeping previous cache.\", error)\n } finally {\n scheduleModelsRefresh(fetcher, intervalMs)\n }\n }, delay)\n}\n\nexport async function cacheModels(\n fetcher: ModelsFetcher = getCopilotModels,\n intervalMs: number = MODELS_REFRESH_BASE_MS,\n): Promise<void> {\n await refreshModels(fetcher)\n scheduleModelsRefresh(fetcher, intervalMs)\n}\n","import consola from \"consola\"\nimport { randomUUID } from \"node:crypto\"\nimport path from \"node:path\"\n\nconst WINDOWS_DEVICE_ID_KEY = String.raw`\\SOFTWARE\\Microsoft\\DeveloperTools`\nconst WINDOWS_DEVICE_ID_NAME = \"deviceid\"\n\ntype RegistryArch = \"x86\" | \"x64\"\n\ninterface WinregConstructor {\n new (options: {\n hive: string\n key: string\n arch?: RegistryArch\n }): WinregRegistry\n HKCU: string\n REG_SZ: string\n}\n\ninterface WinregRegistry {\n get(\n name: string,\n callback: (error: RegistryError | null, item: RegistryItem | null) => void,\n ): void\n set(\n name: string,\n type: string,\n value: string,\n callback: (error: RegistryError | null) => void,\n ): void\n}\n\ninterface RegistryItem {\n value?: string\n}\n\ninterface RegistryError extends Error {\n code?: number | string\n}\n\nconst windows64Architectures = new Set([\"AMD64\", \"ARM64\", \"IA64\"])\n\nconst getPosixHomeDir = (): string => {\n if (!process.env.HOME) {\n throw new Error(\"Home directory not found\")\n }\n\n return process.env.HOME\n}\n\nconst getDeviceIdFilePath = (): string => {\n let folder: string\n\n switch (process.platform) {\n case \"darwin\": {\n folder = path.posix.join(\n getPosixHomeDir(),\n \"Library\",\n \"Application Support\",\n )\n break\n }\n case \"linux\": {\n folder =\n process.env.XDG_CACHE_HOME\n ?? path.posix.join(getPosixHomeDir(), \".cache\")\n break\n }\n default: {\n throw new Error(\"Unsupported platform\")\n }\n }\n\n return path.posix.join(folder, \"Microsoft\", \"DeveloperTools\", \"deviceid\")\n}\n\nconst isMissingFileError = (error: unknown): error is NodeJS.ErrnoException => {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\"\n}\n\nconst readStoredDeviceIdFile = async (\n filePath: string,\n): Promise<string | undefined> => {\n const { readFile } = await import(\"node:fs/promises\")\n\n try {\n return await readFile(filePath, \"utf8\")\n } catch (error) {\n if (isMissingFileError(error)) {\n return undefined\n }\n\n throw error\n }\n}\n\nconst writeStoredDeviceIdFile = async (\n filePath: string,\n deviceId: string,\n): Promise<void> => {\n const { mkdir, writeFile } = await import(\"node:fs/promises\")\n\n await mkdir(path.posix.dirname(filePath), { recursive: true })\n await writeFile(filePath, deviceId, \"utf8\")\n}\n\nconst getWindowsRegistryArch = (): RegistryArch | undefined => {\n const architecture = (\n process.env.PROCESSOR_ARCHITEW6432 ?? process.env.PROCESSOR_ARCHITECTURE\n )?.toUpperCase()\n\n return architecture && windows64Architectures.has(architecture) ?\n \"x64\"\n : undefined\n}\n\nconst loadWinreg = async (): Promise<WinregConstructor> => {\n const module = await import(\"winreg\")\n const winreg =\n \"default\" in module ? (module.default as unknown) : (module as unknown)\n\n return winreg as WinregConstructor\n}\n\nconst isMissingRegistryError = (error: RegistryError | null): boolean => {\n if (!error) {\n return false\n }\n\n const errorCode = Number(error.code)\n\n return Number.isFinite(errorCode) && errorCode === 1\n}\n\nconst createWindowsRegistry = async (): Promise<{\n registry: WinregRegistry\n regSz: string\n}> => {\n const Winreg = await loadWinreg()\n\n return {\n registry: new Winreg({\n hive: Winreg.HKCU,\n key: WINDOWS_DEVICE_ID_KEY,\n arch: getWindowsRegistryArch(),\n }),\n regSz: Winreg.REG_SZ,\n }\n}\n\nconst readRegistryString = async (\n registry: WinregRegistry,\n name: string,\n): Promise<string | undefined> => {\n return new Promise((resolve, reject) => {\n registry.get(name, (error, item) => {\n if (isMissingRegistryError(error)) {\n resolve(undefined)\n return\n }\n\n if (error) {\n reject(\n error instanceof Error ? error : new Error(\"Unknown registry error\"),\n )\n return\n }\n\n resolve(item?.value)\n })\n })\n}\n\nconst writeRegistryString = async ({\n registry,\n regSz,\n name,\n value,\n}: {\n registry: WinregRegistry\n regSz: string\n name: string\n value: string\n}): Promise<void> => {\n return new Promise((resolve, reject) => {\n registry.set(name, regSz, value, (error) => {\n if (error) {\n reject(\n error instanceof Error ? error : new Error(\"Unknown registry error\"),\n )\n return\n }\n\n resolve()\n })\n })\n}\n\nexport const getStoredVSCodeDeviceId = async (): Promise<\n string | undefined\n> => {\n switch (process.platform) {\n case \"win32\": {\n const { registry } = await createWindowsRegistry()\n\n return readRegistryString(registry, WINDOWS_DEVICE_ID_NAME)\n }\n case \"darwin\":\n case \"linux\": {\n return readStoredDeviceIdFile(getDeviceIdFilePath())\n }\n default: {\n throw new Error(\"Unsupported platform\")\n }\n }\n}\n\nconst setStoredVSCodeDeviceId = async (deviceId: string): Promise<void> => {\n switch (process.platform) {\n case \"win32\": {\n const { registry, regSz } = await createWindowsRegistry()\n\n await writeRegistryString({\n registry,\n regSz,\n name: WINDOWS_DEVICE_ID_NAME,\n value: deviceId,\n })\n return\n }\n case \"darwin\":\n case \"linux\": {\n await writeStoredDeviceIdFile(getDeviceIdFilePath(), deviceId)\n return\n }\n default: {\n throw new Error(\"Unsupported platform\")\n }\n }\n}\n\nconst createVSCodeDeviceId = (): string => randomUUID().toLowerCase()\n\nexport async function getVSCodeDeviceId(): Promise<string> {\n let deviceId: string | undefined\n\n try {\n deviceId = await getStoredVSCodeDeviceId()\n } catch (error) {\n consola.debug(\"Failed to read VSCode device id\", error)\n }\n\n if (deviceId) {\n return deviceId\n }\n\n const newDeviceId = createVSCodeDeviceId()\n\n try {\n await setStoredVSCodeDeviceId(newDeviceId)\n } catch (error) {\n consola.warn(\n \"Failed to persist VSCode device id, using ephemeral id\",\n error,\n )\n }\n\n return newDeviceId\n}\n","const FALLBACK = \"1.130.0\"\n\nexport async function getVSCodeVersion() {\n await Promise.resolve()\n return FALLBACK\n}\n","import consola from \"consola\"\nimport { createHash, randomUUID } from \"node:crypto\"\nimport { networkInterfaces } from \"node:os\"\n\nimport { getVSCodeDeviceId } from \"~/lib/deviceid\"\nimport { state } from \"~/lib/state\"\nimport { getVSCodeVersion } from \"~/services/get-vscode-version\"\n\nexport const cacheVSCodeVersion = async () => {\n const response = await getVSCodeVersion()\n state.vsCodeVersion = response\n\n consola.info(`Using VSCode version: ${response}`)\n}\n\nconst invalidMacAddresses = new Set([\n \"00:00:00:00:00:00\",\n \"ff:ff:ff:ff:ff:ff\",\n \"ac:de:48:00:11:22\",\n])\n\nfunction validateMacAddress(candidate: string): boolean {\n const tempCandidate = candidate.replaceAll(\"-\", \":\").toLowerCase()\n return !invalidMacAddresses.has(tempCandidate)\n}\n\nexport function getMac(): string | null {\n const ifaces = networkInterfaces()\n // eslint-disable-next-line guard-for-in\n for (const name in ifaces) {\n const networkInterface = ifaces[name]\n if (networkInterface) {\n for (const { mac } of networkInterface) {\n if (validateMacAddress(mac)) {\n return mac\n }\n }\n }\n }\n return null\n}\n\nexport const cacheMacMachineId = () => {\n const macAddress = getMac() ?? randomUUID()\n state.macMachineId = createHash(\"sha256\")\n .update(macAddress, \"utf8\")\n .digest(\"hex\")\n consola.debug(`Using machine ID: ${state.macMachineId}`)\n}\n\nexport const cacheVsCodeDeviceId = async () => {\n state.vsCodeDeviceId = await getVSCodeDeviceId()\n consola.debug(`Using VSCode device ID: ${state.vsCodeDeviceId}`)\n}\n\nconst SESSION_REFRESH_BASE_MS = 60 * 60 * 1000\nconst SESSION_REFRESH_JITTER_MS = 20 * 60 * 1000\nlet vsCodeSessionRefreshTimer: ReturnType<typeof setTimeout> | null = null\n\nconst generateSessionId = () => {\n state.vsCodeSessionId = randomUUID() + Date.now().toString()\n consola.debug(`Generated VSCode session ID: ${state.vsCodeSessionId}`)\n}\n\nexport const stopVsCodeSessionRefreshLoop = () => {\n if (vsCodeSessionRefreshTimer) {\n clearTimeout(vsCodeSessionRefreshTimer)\n vsCodeSessionRefreshTimer = null\n }\n}\n\nconst scheduleSessionIdRefresh = () => {\n const randomDelay = Math.floor(Math.random() * SESSION_REFRESH_JITTER_MS)\n const delay = SESSION_REFRESH_BASE_MS + randomDelay\n consola.debug(\n `Scheduling next VSCode session ID refresh in ${Math.round(\n delay / 1000,\n )} seconds`,\n )\n\n stopVsCodeSessionRefreshLoop()\n vsCodeSessionRefreshTimer = setTimeout(() => {\n try {\n generateSessionId()\n } catch (error) {\n consola.error(\"Failed to refresh session ID, rescheduling...\", error)\n } finally {\n scheduleSessionIdRefresh()\n }\n }, delay)\n}\n\nexport const cacheVsCodeSessionId = () => {\n stopVsCodeSessionRefreshLoop()\n generateSessionId()\n scheduleSessionIdRefresh()\n}\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\nimport { serve, type ServerHandler } from \"srvx\"\nimport invariant from \"tiny-invariant\"\n\nimport { runProviderSetup } from \"./auth\"\nimport { listEnabledProviders, mergeConfigWithDefaults } from \"./lib/config\"\nimport {\n GITHUB_TOKEN_ENV,\n readGitHubToken,\n readGitHubTokenFromEnv,\n} from \"./lib/credential-store\"\nimport { getLatestModelForFamily } from \"./lib/models\"\nimport { initOpencodeVersion } from \"./lib/opencode\"\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport {\n getConfiguredApiKeys,\n getMissingApiKeysMessage,\n} from \"./lib/request-auth\"\nimport {\n DEFAULT_SERVER_HOST,\n formatServerUrl,\n resolveServerBinding,\n} from \"./lib/server-host\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport { logUser, setupCopilotToken } from \"./lib/token\"\nimport { cacheModels } from \"./services/copilot/models-cache\"\nimport {\n cacheMacMachineId,\n cacheVSCodeVersion,\n cacheVsCodeSessionId,\n cacheVsCodeDeviceId,\n} from \"./services/vscode-env\"\n\ninterface RunServerOptions {\n host: string\n port: number\n verbose: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n proxyEnv: boolean\n}\n\ntype GitHubTokenSource = \"cli\" | \"env\" | \"file\"\n\n// The environment is preferred over the token file so the token never has to\n// travel through the process list; --github-token stays first for callers that\n// opt in explicitly.\nasync function resolveGitHubToken(\n cliToken: string | undefined,\n): Promise<{ token: string; source: GitHubTokenSource } | null> {\n if (cliToken) return { token: cliToken, source: \"cli\" }\n\n const envToken = readGitHubTokenFromEnv()\n if (envToken) return { token: envToken, source: \"env\" }\n\n const fileToken = await readGitHubToken()\n if (fileToken) return { token: fileToken, source: \"file\" }\n\n return null\n}\n\nasync function setupCopilotMode(\n githubToken: string,\n source: GitHubTokenSource,\n serverUrl: string,\n claudeCode: boolean,\n): Promise<void> {\n state.githubToken = githubToken\n consola.info(\n source === \"cli\" ? \"Using provided GitHub token\"\n : source === \"env\" ?\n `Using GitHub token from the ${GITHUB_TOKEN_ENV} environment variable`\n : \"Using GitHub token from local file\",\n )\n\n await logUser()\n\n await cacheVSCodeVersion()\n cacheMacMachineId()\n cacheVsCodeSessionId()\n await cacheVsCodeDeviceId()\n\n await setupCopilotToken()\n await cacheModels()\n\n consola.info(\n `Available models: \\n${state.models?.data.map((model) => `- ${model.id}`).join(\"\\n\")}`,\n )\n\n if (claudeCode) {\n runClaudeCode(serverUrl)\n }\n}\n\nfunction runClaudeCode(serverUrl: string): 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 invariant(state.models, \"Models should be loaded by now\")\n\n // Default to the latest available model for each Claude Code size tier so\n // opus maps to opus, sonnet maps to sonnet, and haiku maps to haiku.\n const opusModel = getLatestModelForFamily(\"opus\")?.id\n const sonnetModel = getLatestModelForFamily(\"sonnet\")?.id\n const haikuModel = getLatestModelForFamily(\"haiku\")?.id\n\n consola.info(\n \"Selected default Claude Code models:\\n\"\n + `- Opus: ${opusModel ?? \"(none available)\"}\\n`\n + `- Sonnet: ${sonnetModel ?? \"(none available)\"}\\n`\n + `- Haiku: ${haikuModel ?? \"(none available)\"}`,\n )\n\n const command = generateEnvScript(\n {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: \"dummy\",\n ANTHROPIC_MODEL: sonnetModel ?? opusModel,\n ANTHROPIC_DEFAULT_OPUS_MODEL: opusModel,\n ANTHROPIC_DEFAULT_SONNET_MODEL: sonnetModel,\n ANTHROPIC_DEFAULT_HAIKU_MODEL: haikuModel,\n CLAUDE_CODE_USE_VERTEX: \"0\",\n CLAUDE_CODE_USE_BEDROCK: \"0\",\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_CODE_TOTAL_TOKENS_REMINDER: \"off\",\n CLAUDE_CODE_EFFORT_LEVEL: \"max\",\n MCP_CONNECT_TIMEOUT_MS: \"20000\",\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\nasync function setupProviderMode(\n serverUrl: string,\n claudeCode: boolean,\n): Promise<void> {\n const enabledProviders = listEnabledProviders()\n\n if (enabledProviders.length > 0) {\n consola.info(`Using enabled providers: ${enabledProviders.join(\", \")}`)\n return\n }\n\n consola.info(\"No enabled providers found. Setting one up...\")\n await runProviderSetup()\n\n if (state.githubToken) {\n // The setup flow persisted the token with the credential store.\n await setupCopilotMode(state.githubToken, \"file\", serverUrl, claudeCode)\n return\n }\n\n const providersAfterSetup = listEnabledProviders()\n if (providersAfterSetup.length === 0) {\n throw new Error(\n \"Failed to configure any provider. Run `copilot-api auth login` to set one up.\",\n )\n }\n consola.info(`Configured providers: ${providersAfterSetup.join(\", \")}`)\n}\n\nexport async function runServer(options: RunServerOptions): Promise<void> {\n const tlsModule = await import(\"./lib/tls\")\n tlsModule.enableSystemCACompat()\n\n consola.options.throttle = 0\n\n mergeConfigWithDefaults()\n\n const configuredApiKeys = getConfiguredApiKeys()\n const binding = resolveServerBinding(\n options.host,\n configuredApiKeys.length > 0,\n )\n\n const missingApiKeysMessage = getMissingApiKeysMessage()\n if (missingApiKeysMessage) {\n consola.info(missingApiKeysMessage)\n }\n\n await initOpencodeVersion()\n\n if (options.proxyEnv) {\n initProxyFromEnv()\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.showToken = options.showToken\n\n await ensurePaths()\n\n const serverUrl = formatServerUrl(binding.clientHostname, options.port)\n\n const resolvedGitHubToken = await resolveGitHubToken(options.githubToken)\n if (resolvedGitHubToken) {\n await setupCopilotMode(\n resolvedGitHubToken.token,\n resolvedGitHubToken.source,\n serverUrl,\n options.claudeCode,\n )\n } else {\n await setupProviderMode(serverUrl, options.claudeCode)\n }\n\n consola.box(\n `🌐 Usage Viewer: ${serverUrl}/usage-viewer?endpoint=${serverUrl}/usage`,\n )\n\n const { createServer } = await import(\"./server\")\n const server = createServer({ networkExposed: binding.networkExposed })\n\n serve({\n fetch: server.fetch as ServerHandler,\n hostname: binding.hostname,\n port: options.port,\n bun: {\n idleTimeout: 0,\n },\n })\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the Copilot API server\",\n },\n args: {\n host: {\n type: \"string\",\n default: process.env.HOST?.trim() || DEFAULT_SERVER_HOST,\n description: \"Host to listen on\",\n },\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 \"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 },\n run({ args }) {\n return runServer({\n host: args.host,\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n githubToken: args[\"github-token\"],\n claudeCode: args[\"claude-code\"],\n showToken: args[\"show-token\"],\n proxyEnv: args[\"proxy-env\"],\n })\n },\n})\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as isResponsesApiWebSocketEnabled, E as
|
|
1
|
+
import { A as isResponsesApiWebSocketEnabled, E as getUpstreamTransportConfig, F as writeFileAtomically, N as PATHS, c as setProviderConfig, n as getRawProviderConfig, w as getConfig } from "./config-Dj2ZvQuL.js";
|
|
2
2
|
import consola from "consola";
|
|
3
3
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
4
4
|
import path from "node:path";
|
|
@@ -18,7 +18,30 @@ var HTTPError = class extends Error {
|
|
|
18
18
|
this.response = response;
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
|
+
var UpstreamHeadersTimeoutError = class extends Error {
|
|
22
|
+
timeoutMs;
|
|
23
|
+
constructor(timeoutMs) {
|
|
24
|
+
super(`Upstream did not return headers within ${timeoutMs}ms`);
|
|
25
|
+
this.name = "UpstreamHeadersTimeoutError";
|
|
26
|
+
this.timeoutMs = timeoutMs;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var UpstreamStreamInactivityTimeoutError = class extends Error {
|
|
30
|
+
timeoutMs;
|
|
31
|
+
constructor(timeoutMs) {
|
|
32
|
+
super(`Upstream stream was inactive for ${timeoutMs}ms`);
|
|
33
|
+
this.name = "UpstreamStreamInactivityTimeoutError";
|
|
34
|
+
this.timeoutMs = timeoutMs;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
21
37
|
async function forwardError(c, error) {
|
|
38
|
+
if (error instanceof UpstreamHeadersTimeoutError || error instanceof UpstreamStreamInactivityTimeoutError) {
|
|
39
|
+
consola.error("Error occurred:", error);
|
|
40
|
+
return c.json({ error: {
|
|
41
|
+
message: error.message,
|
|
42
|
+
type: "upstream_timeout"
|
|
43
|
+
} }, 504);
|
|
44
|
+
}
|
|
22
45
|
if (c.req.raw.signal.aborted || isAbortError$1(error)) return new Response(null, {
|
|
23
46
|
status: 499,
|
|
24
47
|
statusText: "Client Closed Request"
|
|
@@ -510,19 +533,37 @@ const createResponsesSafeStream = async function* (source, options = {}) {
|
|
|
510
533
|
const isAbortError = (error) => error instanceof Error && error.name === "AbortError";
|
|
511
534
|
//#endregion
|
|
512
535
|
//#region src/services/responses-http.ts
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
536
|
+
const createResponsesHttpEventStream = async function* (response) {
|
|
537
|
+
const responseBody = response.body;
|
|
538
|
+
if (!responseBody) return;
|
|
539
|
+
const reader = responseBody.getReader();
|
|
540
|
+
const readerBackedBody = new ReadableStream({
|
|
541
|
+
async pull(controller) {
|
|
542
|
+
const result = await reader.read();
|
|
543
|
+
if (result.done) {
|
|
544
|
+
controller.close();
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
controller.enqueue(result.value);
|
|
548
|
+
},
|
|
549
|
+
async cancel(reason) {
|
|
550
|
+
await reader.cancel(reason);
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
try {
|
|
554
|
+
yield* events(new Response(readerBackedBody));
|
|
555
|
+
} finally {
|
|
556
|
+
try {
|
|
557
|
+
await reader.cancel();
|
|
558
|
+
} catch {} finally {
|
|
559
|
+
reader.releaseLock();
|
|
560
|
+
}
|
|
523
561
|
}
|
|
524
562
|
};
|
|
525
|
-
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region src/services/upstream-http.ts
|
|
565
|
+
async function fetchUpstreamWithLifecycle(input, init, options) {
|
|
566
|
+
options.clientSignal?.throwIfAborted();
|
|
526
567
|
const lifecycle = createRequestLifecycle(options);
|
|
527
568
|
try {
|
|
528
569
|
const response = await fetch(input, {
|
|
@@ -537,16 +578,9 @@ async function fetchResponsesWithLifecycle(input, init, options) {
|
|
|
537
578
|
}
|
|
538
579
|
const createRequestLifecycle = (options) => {
|
|
539
580
|
const controller = new AbortController();
|
|
540
|
-
const downstreamSignal = options.signal;
|
|
541
581
|
let finished = false;
|
|
542
|
-
let headersTimer =
|
|
543
|
-
|
|
544
|
-
controller.abort(toAbortReason(downstreamSignal?.reason));
|
|
545
|
-
};
|
|
546
|
-
if (downstreamSignal?.aborted) abortFromDownstream();
|
|
547
|
-
else downstreamSignal?.addEventListener("abort", abortFromDownstream, { once: true });
|
|
548
|
-
if (!controller.signal.aborted) headersTimer = setTimeout(() => {
|
|
549
|
-
controller.abort(new ResponsesHeadersTimeoutError(options.headersTimeoutMs));
|
|
582
|
+
let headersTimer = setTimeout(() => {
|
|
583
|
+
controller.abort(new UpstreamHeadersTimeoutError(options.headersTimeoutMs));
|
|
550
584
|
}, options.headersTimeoutMs);
|
|
551
585
|
const clearHeadersTimer = () => {
|
|
552
586
|
if (headersTimer === null) return;
|
|
@@ -557,7 +591,6 @@ const createRequestLifecycle = (options) => {
|
|
|
557
591
|
if (finished) return;
|
|
558
592
|
finished = true;
|
|
559
593
|
clearHeadersTimer();
|
|
560
|
-
downstreamSignal?.removeEventListener("abort", abortFromDownstream);
|
|
561
594
|
};
|
|
562
595
|
return {
|
|
563
596
|
abort: (reason) => {
|
|
@@ -565,7 +598,6 @@ const createRequestLifecycle = (options) => {
|
|
|
565
598
|
},
|
|
566
599
|
finish,
|
|
567
600
|
finishWithError: (error) => {
|
|
568
|
-
clearHeadersTimer();
|
|
569
601
|
const reason = controller.signal.reason;
|
|
570
602
|
finish();
|
|
571
603
|
return reason instanceof Error ? reason : toError(error);
|
|
@@ -628,38 +660,11 @@ const createManagedResponseBody = (body, lifecycle, options) => {
|
|
|
628
660
|
}
|
|
629
661
|
});
|
|
630
662
|
};
|
|
631
|
-
const createResponsesHttpEventStream = async function* (response, signal) {
|
|
632
|
-
const responseBody = response.body;
|
|
633
|
-
if (!responseBody) return;
|
|
634
|
-
const reader = responseBody.getReader();
|
|
635
|
-
const readerBackedBody = new ReadableStream({
|
|
636
|
-
async pull(controller) {
|
|
637
|
-
const result = await reader.read();
|
|
638
|
-
if (result.done) {
|
|
639
|
-
controller.close();
|
|
640
|
-
return;
|
|
641
|
-
}
|
|
642
|
-
controller.enqueue(result.value);
|
|
643
|
-
},
|
|
644
|
-
async cancel(reason) {
|
|
645
|
-
await reader.cancel(reason);
|
|
646
|
-
}
|
|
647
|
-
});
|
|
648
|
-
try {
|
|
649
|
-
yield* events(new Response(readerBackedBody), signal);
|
|
650
|
-
} finally {
|
|
651
|
-
try {
|
|
652
|
-
await reader.cancel();
|
|
653
|
-
} catch {} finally {
|
|
654
|
-
reader.releaseLock();
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
};
|
|
658
663
|
const readWithLifecycle = async (reader, lifecycle, options) => await new Promise((resolve, reject) => {
|
|
659
664
|
let settled = false;
|
|
660
665
|
const signal = lifecycle.signal;
|
|
661
666
|
const timer = setTimeout(() => {
|
|
662
|
-
const error = new
|
|
667
|
+
const error = new UpstreamStreamInactivityTimeoutError(options.streamInactivityTimeoutMs);
|
|
663
668
|
lifecycle.abort(error);
|
|
664
669
|
settle(() => reject(error));
|
|
665
670
|
}, options.streamInactivityTimeoutMs);
|
|
@@ -804,33 +809,33 @@ function buildCodexResponsesWebSocketPayload(payload) {
|
|
|
804
809
|
function buildCodexResponsesWebSocketUrl(baseUrl = CODEX_API_BASE_URL) {
|
|
805
810
|
return createWebSocketUrl(resolveCodexResponsesUrl(baseUrl));
|
|
806
811
|
}
|
|
807
|
-
function prepareCodexResponsesWebSocketRequest(payload, requestHeaders, baseUrl = CODEX_API_BASE_URL
|
|
812
|
+
function prepareCodexResponsesWebSocketRequest(payload, requestHeaders, baseUrl = CODEX_API_BASE_URL) {
|
|
808
813
|
const headers = buildCodexResponsesWebSocketHeaders(requestHeaders);
|
|
809
814
|
return {
|
|
810
815
|
headers,
|
|
811
816
|
payload: buildCodexResponsesWebSocketPayload(payload),
|
|
812
817
|
poolKey: buildCodexResponsesWebSocketPoolKey(payload, headers, baseUrl),
|
|
813
|
-
signal,
|
|
814
818
|
url: buildCodexResponsesWebSocketUrl(baseUrl)
|
|
815
819
|
};
|
|
816
820
|
}
|
|
817
821
|
async function forwardCodexResponses(payload, requestHeaders, baseUrl = CODEX_API_BASE_URL, options = {}) {
|
|
818
822
|
consola.log(`<-- model: ${payload.model}`);
|
|
823
|
+
options.clientSignal?.throwIfAborted();
|
|
819
824
|
const transport = resolveCodexResponsesTransport(options.transport);
|
|
820
|
-
if (payload.stream && transport === "websocket") return forwardCodexResponsesOverWebSocket(payload, requestHeaders, baseUrl, options.
|
|
825
|
+
if (payload.stream && transport === "websocket") return forwardCodexResponsesOverWebSocket(payload, requestHeaders, baseUrl, options.clientSignal);
|
|
821
826
|
const normalizedPayload = normalizeCodexResponsesPayload(payload);
|
|
822
|
-
const transportConfig =
|
|
823
|
-
const response = await
|
|
827
|
+
const transportConfig = getUpstreamTransportConfig();
|
|
828
|
+
const response = await fetchUpstreamWithLifecycle(resolveCodexResponsesUrl(baseUrl), {
|
|
824
829
|
method: "POST",
|
|
825
830
|
headers: buildCodexResponsesHeaders(requestHeaders, { stream: normalizedPayload.stream }),
|
|
826
831
|
body: JSON.stringify(normalizedPayload)
|
|
827
832
|
}, {
|
|
833
|
+
clientSignal: options.clientSignal,
|
|
828
834
|
headersTimeoutMs: transportConfig.headersTimeoutMs,
|
|
829
|
-
signal: options.signal,
|
|
830
835
|
streamInactivityTimeoutMs: transportConfig.streamInactivityTimeoutMs
|
|
831
836
|
});
|
|
832
837
|
if (!response.ok) throw new HTTPError("Failed to create codex responses", response);
|
|
833
|
-
if (normalizedPayload.stream) return createResponsesSafeStream(createResponsesHttpEventStream(response
|
|
838
|
+
if (normalizedPayload.stream) return createResponsesSafeStream(createResponsesHttpEventStream(response));
|
|
834
839
|
return await response.json();
|
|
835
840
|
}
|
|
836
841
|
const normalizeCodexResponsesPayload = (payload) => {
|
|
@@ -896,12 +901,12 @@ const buildCodexResponsesWebSocketPoolKey = (payload, headers, baseUrl) => {
|
|
|
896
901
|
headerFingerprint
|
|
897
902
|
].map(encodePoolKeyPart).join("|");
|
|
898
903
|
};
|
|
899
|
-
const forwardCodexResponsesOverWebSocket = (payload, requestHeaders, baseUrl,
|
|
900
|
-
return createCodexResponsesWebSocketStream(prepareCodexResponsesWebSocketRequest(payload, requestHeaders, baseUrl,
|
|
904
|
+
const forwardCodexResponsesOverWebSocket = (payload, requestHeaders, baseUrl, clientSignal) => {
|
|
905
|
+
return createCodexResponsesWebSocketStream(prepareCodexResponsesWebSocketRequest(payload, requestHeaders, baseUrl), clientSignal);
|
|
901
906
|
};
|
|
902
|
-
const createCodexResponsesWebSocketStream = (request) => {
|
|
903
|
-
const transportConfig =
|
|
904
|
-
return createResponsesSafeStream(createPooledWebSocketStream(request, {
|
|
907
|
+
const createCodexResponsesWebSocketStream = (request, clientSignal) => {
|
|
908
|
+
const transportConfig = getUpstreamTransportConfig();
|
|
909
|
+
return createResponsesSafeStream(createClientPreflightStream(createPooledWebSocketStream(request, {
|
|
905
910
|
createChunk: createCodexResponsesWebSocketStreamChunk,
|
|
906
911
|
maxBufferedBytes: transportConfig.websocketMaxBufferedBytes,
|
|
907
912
|
maxBufferedMessages: transportConfig.websocketMaxBufferedMessages,
|
|
@@ -912,7 +917,11 @@ const createCodexResponsesWebSocketStream = (request) => {
|
|
|
912
917
|
streamInactivityTimeoutMs: transportConfig.streamInactivityTimeoutMs,
|
|
913
918
|
streamErrorMessage: "Upstream connection lost, Codex responses websocket stream error",
|
|
914
919
|
terminalChunkMissingMessage: "Codex responses websocket ended without a terminal response, retry your request."
|
|
915
|
-
}),
|
|
920
|
+
}), clientSignal));
|
|
921
|
+
};
|
|
922
|
+
const createClientPreflightStream = async function* (source, clientSignal) {
|
|
923
|
+
if (clientSignal?.aborted) return;
|
|
924
|
+
yield* source;
|
|
916
925
|
};
|
|
917
926
|
const createCodexResponsesWebSocketStreamChunk = (data) => {
|
|
918
927
|
if (data === "[DONE]") return { data };
|
|
@@ -1080,7 +1089,7 @@ async function exchangeAuthorizationCode(code, verifier) {
|
|
|
1080
1089
|
throw new Error(`Codex token exchange failed (${response.status}): ${details || response.statusText}`);
|
|
1081
1090
|
}
|
|
1082
1091
|
const payload = await response.json();
|
|
1083
|
-
if (typeof payload.access_token !== "string" || typeof payload.refresh_token !== "string" || typeof payload.expires_in !== "number") throw new TypeError(
|
|
1092
|
+
if (typeof payload.access_token !== "string" || typeof payload.refresh_token !== "string" || typeof payload.expires_in !== "number") throw new TypeError("Codex token exchange response missing required fields");
|
|
1084
1093
|
return {
|
|
1085
1094
|
accessToken: payload.access_token,
|
|
1086
1095
|
refreshToken: payload.refresh_token,
|
|
@@ -1102,7 +1111,7 @@ async function refreshAccessToken(refreshToken) {
|
|
|
1102
1111
|
throw new Error(`Codex token refresh failed (${response.status}): ${details || response.statusText}`);
|
|
1103
1112
|
}
|
|
1104
1113
|
const payload = await response.json();
|
|
1105
|
-
if (typeof payload.access_token !== "string" || typeof payload.refresh_token !== "string" || typeof payload.expires_in !== "number") throw new TypeError(
|
|
1114
|
+
if (typeof payload.access_token !== "string" || typeof payload.refresh_token !== "string" || typeof payload.expires_in !== "number") throw new TypeError("Codex token refresh response missing required fields");
|
|
1106
1115
|
return {
|
|
1107
1116
|
accessToken: payload.access_token,
|
|
1108
1117
|
refreshToken: payload.refresh_token,
|
|
@@ -1565,14 +1574,8 @@ async function readOptionalFile(filePath) {
|
|
|
1565
1574
|
throw error;
|
|
1566
1575
|
}
|
|
1567
1576
|
}
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
await fs.writeFile(filePath, content, "utf8");
|
|
1571
|
-
try {
|
|
1572
|
-
await fs.chmod(filePath, 384);
|
|
1573
|
-
} catch {
|
|
1574
|
-
return;
|
|
1575
|
-
}
|
|
1577
|
+
function writeProtectedFile(filePath, content) {
|
|
1578
|
+
return Promise.resolve().then(() => writeFileAtomically(filePath, content));
|
|
1576
1579
|
}
|
|
1577
1580
|
function normalizeCodexCredentials(credentials) {
|
|
1578
1581
|
if (!credentials || typeof credentials !== "object") return null;
|
|
@@ -1588,6 +1591,10 @@ function normalizeCodexCredentials(credentials) {
|
|
|
1588
1591
|
async function readGitHubToken() {
|
|
1589
1592
|
return (await readOptionalFile(PATHS.GITHUB_TOKEN_PATH))?.trim() || null;
|
|
1590
1593
|
}
|
|
1594
|
+
const GITHUB_TOKEN_ENV = "COPILOT_API_GITHUB_TOKEN";
|
|
1595
|
+
function readGitHubTokenFromEnv() {
|
|
1596
|
+
return process.env["COPILOT_API_GITHUB_TOKEN"]?.trim() || void 0;
|
|
1597
|
+
}
|
|
1591
1598
|
async function writeGitHubToken(token) {
|
|
1592
1599
|
await writeProtectedFile(PATHS.GITHUB_TOKEN_PATH, token.trim());
|
|
1593
1600
|
}
|
|
@@ -1744,7 +1751,7 @@ async function pollAccessToken(deviceCode) {
|
|
|
1744
1751
|
continue;
|
|
1745
1752
|
}
|
|
1746
1753
|
const json = await response.json();
|
|
1747
|
-
consola.debug("Polling access token response
|
|
1754
|
+
consola.debug("Polling access token response received");
|
|
1748
1755
|
const { access_token } = json;
|
|
1749
1756
|
if (access_token) return access_token;
|
|
1750
1757
|
else await sleep(sleepDuration);
|
|
@@ -1951,6 +1958,6 @@ async function logUser(dependencies = defaultCopilotTokenDependencies) {
|
|
|
1951
1958
|
state.tokenBasedBilling = copilotUser.token_based_billing;
|
|
1952
1959
|
}
|
|
1953
1960
|
//#endregion
|
|
1954
|
-
export {
|
|
1961
|
+
export { createAuthMiddleware as A, resolveTraceId as B, prepareMessageProxyHeaders as C, compactSummaryPromptStart as D, compactMessageSections as E, CODEX_API_BASE_URL as F, isTerminalResponsesStreamChunk as G, createResponsesHttpEventStream as H, buildCodexRequestHeaders as I, state as J, createPooledWebSocketStream as K, forwardCodexResponses as L, getConfiguredApiKeys as M, getMissingApiKeysMessage as N, compactSystemPromptStarts as O, loginCodex as P, generateTraceId as R, prepareInteractionHeaders as S, compactAutoContinuePromptStarts as T, createResponsesSafeStream as U, fetchUpstreamWithLifecycle as V, encodePoolKeyPart as W, forwardError as X, HTTPError as Y, copilotBaseUrl as _, setupGitHubToken as a, copilotWebSocketHeaders as b, getUUID as c, isResponsesStream as d, parseUserIdMetadata as f, readGitHubTokenFromEnv as g, readGitHubToken as h, setupCopilotToken as i, getConfiguredAdminApiKeys as j, compactTextOnlyGuard as k, isAsyncIterable as l, GITHUB_TOKEN_ENV as m, persistCodexCredentials as n, generateRequestIdFromPayload as o, getCopilotUsage as p, createWebSocketUrl as q, setupCodexToken as r, getRootSessionId as s, logUser as t, isNullish as u, copilotHeaders as v, initOpencodeVersion as w, prepareForCompact as x, copilotModelsHeaders as y, requestContext as z };
|
|
1955
1962
|
|
|
1956
|
-
//# sourceMappingURL=token-
|
|
1963
|
+
//# sourceMappingURL=token-CaFzyRJX.js.map
|