copilot-api-plus 1.2.8 → 1.2.9
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.en.md +5 -4
- package/README.md +5 -4
- package/dist/main.js +7 -3
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -46,7 +46,7 @@ English | [简体中文](README.md)
|
|
|
46
46
|
| 👥 **Multi-Account** | Multiple GitHub accounts with automatic failover on quota exhaustion/rate limiting/bans |
|
|
47
47
|
| 🔀 **Model Routing** | Flexible model name mapping and per-model concurrency control |
|
|
48
48
|
| 📱 **Visual Management** | Web dashboard for account management, model config, and runtime stats |
|
|
49
|
-
| 🛡️ **Network Resilience** | 120s connection timeout +
|
|
49
|
+
| 🛡️ **Network Resilience** | 120s connection timeout + smart retry (pool reset + fast-fail) |
|
|
50
50
|
| ✂️ **Context Passthrough** | Full context passthrough to upstream API; clients (e.g. Claude Code) manage compression |
|
|
51
51
|
| 🔍 **Smart Model Matching** | Handles model name format differences (date suffixes, dash/dot versions, etc.) |
|
|
52
52
|
| 🧠 **Thinking Chain** | Automatically enables deep thinking (thinking/reasoning) for supported models, improving code quality |
|
|
@@ -580,10 +580,11 @@ Each API request outputs a log line with model name, status code, and duration:
|
|
|
580
580
|
|
|
581
581
|
### Network Resilience
|
|
582
582
|
|
|
583
|
-
Built-in connection timeout and
|
|
583
|
+
Built-in connection timeout and smart retry for upstream API requests, minimizing Copilot request credit consumption:
|
|
584
584
|
|
|
585
|
-
- **Connection timeout**: 120 seconds (
|
|
586
|
-
- **Retry strategy**: Up to
|
|
585
|
+
- **Connection timeout**: 120 seconds for the first attempt, 20 seconds for retries (fail fast)
|
|
586
|
+
- **Retry strategy**: Up to 1 retry (2 total attempts), 2-second delay
|
|
587
|
+
- **Connection pool reset**: Automatically destroys all pooled connections on the first network error and creates fresh instances, preventing retries from hitting stale sockets
|
|
587
588
|
- Only retries network-layer errors (timeout, TLS disconnect, connection reset, etc.); HTTP error codes (e.g. 400/500) are not retried
|
|
588
589
|
- SSE stream interruptions gracefully send error events to the client
|
|
589
590
|
|
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
| 👥 **多账号管理** | 支持添加多个 GitHub 账号,额度耗尽/限流/封禁时自动切换下一个 |
|
|
48
48
|
| 🔀 **模型路由** | 灵活的模型名映射和每模型并发控制 |
|
|
49
49
|
| 📱 **可视化管理** | Web 仪表盘支持账号管理、模型管理、运行统计 |
|
|
50
|
-
| 🛡️ **网络弹性** | 120s 连接超时 +
|
|
50
|
+
| 🛡️ **网络弹性** | 120s 连接超时 + 智能重试(连接池重置 + 短超时快速失败) |
|
|
51
51
|
| ✂️ **上下文透传** | 全量透传上下文至上游 API,由客户端(如 Claude Code)自行管理压缩 |
|
|
52
52
|
| 🔍 **智能模型匹配** | 自动处理模型名格式差异(日期后缀、dash/dot 版本号等) |
|
|
53
53
|
| 🧠 **Thinking 思维链** | 自动为支持的模型启用深度思考(thinking/reasoning),提升代码质量 |
|
|
@@ -743,10 +743,11 @@ Anthropic 格式的模型名(如 `claude-opus-4-6`)和 Copilot 的模型列
|
|
|
743
743
|
|
|
744
744
|
### 网络弹性
|
|
745
745
|
|
|
746
|
-
对上游 API
|
|
746
|
+
对上游 API 的请求内置了连接超时和智能重试,以最小化 Copilot 请求次数消耗:
|
|
747
747
|
|
|
748
|
-
-
|
|
749
|
-
- **重试策略**:最多重试
|
|
748
|
+
- **连接超时**:首次请求 120 秒,重试请求 20 秒(快速失败,避免白等)
|
|
749
|
+
- **重试策略**:最多重试 1 次(共 2 次尝试),间隔 2 秒
|
|
750
|
+
- **连接池重置**:首次网络错误后自动销毁所有连接并创建新实例,避免后续请求复用坏连接
|
|
750
751
|
- 仅重试网络层错误(超时、TLS 断开、连接重置等),HTTP 错误码(如 400/500)不重试
|
|
751
752
|
- SSE 流传输中断时,优雅地向客户端发送错误事件
|
|
752
753
|
|
package/dist/main.js
CHANGED
|
@@ -121,9 +121,13 @@ async function applyProxyConfig() {
|
|
|
121
121
|
//#endregion
|
|
122
122
|
//#region src/lib/proxy.ts
|
|
123
123
|
const agentOptions = {
|
|
124
|
-
keepAliveTimeout:
|
|
125
|
-
keepAliveMaxTimeout:
|
|
126
|
-
connect: {
|
|
124
|
+
keepAliveTimeout: 6e4,
|
|
125
|
+
keepAliveMaxTimeout: 3e5,
|
|
126
|
+
connect: {
|
|
127
|
+
timeout: 15e3,
|
|
128
|
+
keepAlive: true,
|
|
129
|
+
keepAliveInitialDelay: 15e3
|
|
130
|
+
}
|
|
127
131
|
};
|
|
128
132
|
let direct;
|
|
129
133
|
let proxies = /* @__PURE__ */ new Map();
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","names":["fs","path","os","process","handleCompletion","isNonStreaming","handleCompletion"],"sources":["../src/lib/config.ts","../src/lib/proxy.ts","../src/account.ts","../src/auth.ts","../src/check-usage.ts","../src/debug.ts","../src/logout.ts","../src/proxy-config.ts","../node_modules/dotenv/package.json","../node_modules/dotenv/lib/main.js","../node_modules/dotenv/lib/env-options.js","../node_modules/dotenv/lib/cli-options.js","../node_modules/dotenv/config.js","../src/lib/model-router.ts","../src/lib/shell.ts","../src/lib/api-key-auth.ts","../src/lib/model-logger.ts","../src/routes/admin/accounts.ts","../src/routes/admin/models.ts","../src/routes/admin/stats.ts","../src/routes/admin/route.ts","../src/lib/approval.ts","../src/lib/rate-limit.ts","../src/services/copilot/create-chat-completions.ts","../src/routes/chat-completions/handler.ts","../src/routes/chat-completions/route.ts","../src/services/copilot/create-embeddings.ts","../src/routes/embeddings/route.ts","../src/lib/tokenizer.ts","../src/routes/messages/utils.ts","../src/routes/messages/non-stream-translation.ts","../src/routes/messages/count-tokens-handler.ts","../src/routes/messages/stream-translation.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["/**\n * Configuration file management\n * Handles persistent configuration storage for proxy settings and other options\n */\n\nimport consola from \"consola\"\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport { PATHS } from \"./paths\"\n\nconst CONFIG_FILENAME = \"config.json\"\n\nexport interface ProxyConfig {\n enabled: boolean\n httpProxy?: string\n httpsProxy?: string\n noProxy?: string\n}\n\nexport interface ModelMappingConfig {\n mapping?: Record<string, string>\n concurrency?: Record<string, number>\n}\n\nexport interface AppConfig {\n proxy?: ProxyConfig\n modelMapping?: ModelMappingConfig\n}\n\n/**\n * Get the path to the config file\n */\nexport function getConfigPath(): string {\n return path.join(PATHS.DATA_DIR, CONFIG_FILENAME)\n}\n\n/**\n * Load configuration from file\n */\nexport async function loadConfig(): Promise<AppConfig> {\n try {\n const configPath = getConfigPath()\n // eslint-disable-next-line unicorn/prefer-json-parse-buffer\n const content = await fs.readFile(configPath, \"utf8\")\n return JSON.parse(content) as AppConfig\n } catch {\n return {}\n }\n}\n\n/**\n * Save configuration to file\n */\nexport async function saveConfig(config: AppConfig): Promise<void> {\n const configPath = getConfigPath()\n await fs.writeFile(configPath, JSON.stringify(config, null, 2), \"utf8\")\n consola.debug(`Configuration saved to ${configPath}`)\n}\n\n/**\n * Get proxy configuration\n */\nexport async function getProxyConfig(): Promise<ProxyConfig | undefined> {\n const config = await loadConfig()\n return config.proxy\n}\n\n/**\n * Save proxy configuration\n */\nexport async function saveProxyConfig(proxyConfig: ProxyConfig): Promise<void> {\n const config = await loadConfig()\n config.proxy = proxyConfig\n await saveConfig(config)\n}\n\n/**\n * Clear proxy configuration\n */\nexport async function clearProxyConfig(): Promise<void> {\n const config = await loadConfig()\n delete config.proxy\n await saveConfig(config)\n}\n\n/**\n * Get model mapping configuration\n */\nexport async function getModelMappingConfig(): Promise<\n ModelMappingConfig | undefined\n> {\n const config = await loadConfig()\n return config.modelMapping\n}\n\n/**\n * Save model mapping configuration\n */\nexport async function saveModelMappingConfig(\n modelMapping: ModelMappingConfig,\n): Promise<void> {\n const config = await loadConfig()\n config.modelMapping = modelMapping\n await saveConfig(config)\n}\n\n/**\n * Apply saved proxy configuration to environment variables\n * This should be called at startup to restore proxy settings\n */\nexport async function applyProxyConfig(): Promise<boolean> {\n const proxyConfig = await getProxyConfig()\n\n if (!proxyConfig || !proxyConfig.enabled) {\n return false\n }\n\n if (proxyConfig.httpProxy) {\n process.env.HTTP_PROXY = proxyConfig.httpProxy\n process.env.http_proxy = proxyConfig.httpProxy\n }\n\n if (proxyConfig.httpsProxy) {\n process.env.HTTPS_PROXY = proxyConfig.httpsProxy\n process.env.https_proxy = proxyConfig.httpsProxy\n }\n\n if (proxyConfig.noProxy) {\n process.env.NO_PROXY = proxyConfig.noProxy\n process.env.no_proxy = proxyConfig.noProxy\n }\n\n consola.info(\"Proxy configuration loaded from saved settings\")\n if (proxyConfig.httpProxy) {\n consola.info(` HTTP_PROXY: ${proxyConfig.httpProxy}`)\n }\n if (proxyConfig.httpsProxy) {\n consola.info(` HTTPS_PROXY: ${proxyConfig.httpsProxy}`)\n }\n if (proxyConfig.noProxy) {\n consola.info(` NO_PROXY: ${proxyConfig.noProxy}`)\n }\n\n return true\n}\n","import consola from \"consola\"\nimport { getProxyForUrl } from \"proxy-from-env\"\nimport { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from \"undici\"\n\n// Module-level references so that `resetConnections` can swap them out.\n// Initialised by `initProxyFromEnv`; the dispatcher closure captures the\n// *variables* (not their values), so replacing them is enough.\nconst agentOptions = {\n keepAliveTimeout: 30_000,\n keepAliveMaxTimeout: 60_000,\n connect: { timeout: 15_000 },\n}\nlet direct: Agent | undefined\nlet proxies = new Map<string, ProxyAgent>()\n\nexport function initProxyFromEnv(): void {\n if (typeof Bun !== \"undefined\") return\n\n try {\n direct = new Agent(agentOptions)\n 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({ uri: proxyUrl, ...agentOptions })\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 for (const agent of proxies.values()) {\n void (agent as unknown as Dispatcher).close()\n }\n // `direct` is always set before the dispatcher is installed.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return direct!.close()\n },\n destroy() {\n for (const agent of proxies.values()) {\n void (agent as unknown as Dispatcher).destroy()\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return direct!.destroy()\n },\n }\n\n setGlobalDispatcher(dispatcher as unknown as Dispatcher)\n consola.debug(\"HTTP proxy configured from environment (per-URL)\")\n } catch (err) {\n consola.debug(\"Proxy setup skipped:\", err)\n }\n}\n\n/**\n * Destroy all pooled connections (direct + proxy agents) and replace them\n * with fresh instances. The global dispatcher's `dispatch` method captures\n * `direct` and `proxies` by reference, so subsequent requests automatically\n * use the new agents — no need to call `setGlobalDispatcher` again.\n *\n * Call this after a network error to discard stale/half-closed sockets that\n * would otherwise cause every retry to wait ~60 s before timing out.\n *\n * Under the Bun runtime (which doesn't use undici) this is a no-op.\n */\nexport function resetConnections(): void {\n if (typeof Bun !== \"undefined\") return\n if (!direct) return\n\n const oldDirect = direct\n const oldProxies = proxies\n\n direct = new Agent(agentOptions)\n proxies = new Map<string, ProxyAgent>()\n\n // Tear down old agents in the background — errors are non-fatal.\n void (oldDirect as unknown as Dispatcher).close().catch(() => {})\n for (const agent of oldProxies.values()) {\n void (agent as unknown as Dispatcher).close().catch(() => {})\n }\n\n consola.debug(\"Connection pool reset — stale sockets cleared\")\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { accountManager } from \"./lib/account-manager\"\nimport { applyProxyConfig } from \"./lib/config\"\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { state } from \"./lib/state\"\nimport { cacheVSCodeVersion, rootCause } from \"./lib/utils\"\nimport { getDeviceCode } from \"./services/github/get-device-code\"\nimport { pollAccessToken } from \"./services/github/poll-access-token\"\n\n// ---------------------------------------------------------------------------\n// copilot-api-plus add-account\n// ---------------------------------------------------------------------------\n\nexport const addAccount = defineCommand({\n meta: {\n name: \"add-account\",\n description: \"Add a new GitHub account via Device Code auth\",\n },\n args: {\n label: {\n alias: \"l\",\n type: \"string\",\n description: \"Label for the account\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type (individual/business/enterprise)\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n },\n async run({ args }) {\n if (args.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n try {\n await ensurePaths()\n await applyProxyConfig()\n initProxyFromEnv()\n state.accountType = args[\"account-type\"]\n await cacheVSCodeVersion()\n\n // Device Code flow\n consola.info(\"Starting GitHub Device Code authentication...\")\n const deviceCode = await getDeviceCode()\n\n consola.box(\n `Please visit: ${deviceCode.verification_uri}\\nand enter code: ${deviceCode.user_code}`,\n )\n\n const githubToken = await pollAccessToken(deviceCode)\n consola.success(\"GitHub token obtained\")\n\n // Add account\n await accountManager.loadAccounts()\n\n const label = args.label || `Account ${accountManager.accountCount + 1}`\n const accountType = args[\"account-type\"]\n\n const account = await accountManager.addAccount(\n githubToken,\n label,\n accountType,\n )\n\n consola.success(\n `Account added: ${account.githubLogin} (${account.label})`,\n )\n consola.info(`Total accounts: ${accountManager.accountCount}`)\n } catch (err) {\n consola.warn(`Failed to add account: ${rootCause(err)}`)\n consola.debug(\"Failed to add account:\", err)\n process.exitCode = 1\n }\n },\n})\n\n// ---------------------------------------------------------------------------\n// copilot-api-plus list-accounts\n// ---------------------------------------------------------------------------\n\nexport const listAccounts = defineCommand({\n meta: {\n name: \"list-accounts\",\n description: \"List all configured accounts\",\n },\n args: {\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n },\n async run({ args }) {\n if (args.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n try {\n await ensurePaths()\n await accountManager.loadAccounts()\n\n const accounts = accountManager.getAccounts()\n\n if (accounts.length === 0) {\n consola.info(\"No accounts configured. Use `add-account` to add one.\")\n return\n }\n\n // Calculate column widths\n const rows = accounts.map((a, i) => ({\n num: String(i + 1),\n label: a.label || \"-\",\n login: a.githubLogin || \"unknown\",\n status: a.status,\n premium:\n a.usage ?\n `${a.usage.premium_remaining}/${a.usage.premium_total}`\n : \"-\",\n }))\n\n const cols = {\n num: Math.max(1, ...rows.map((r) => r.num.length)),\n label: Math.max(5, ...rows.map((r) => r.label.length)),\n login: Math.max(5, ...rows.map((r) => r.login.length)),\n status: Math.max(6, ...rows.map((r) => r.status.length)),\n premium: Math.max(17, ...rows.map((r) => r.premium.length)),\n }\n\n const pad = (s: string, w: number) => s.padEnd(w)\n const sep = (w: number) => \"─\".repeat(w)\n\n const header = `│ ${pad(\"#\", cols.num)} │ ${pad(\"Label\", cols.label)} │ ${pad(\"Login\", cols.login)} │ ${pad(\"Status\", cols.status)} │ ${pad(\"Premium Remaining\", cols.premium)} │`\n const topBorder = `┌─${sep(cols.num)}─┬─${sep(cols.label)}─┬─${sep(cols.login)}─┬─${sep(cols.status)}─┬─${sep(cols.premium)}─┐`\n const midBorder = `├─${sep(cols.num)}─┼─${sep(cols.label)}─┼─${sep(cols.login)}─┼─${sep(cols.status)}─┼─${sep(cols.premium)}─┤`\n const botBorder = `└─${sep(cols.num)}─┴─${sep(cols.label)}─┴─${sep(cols.login)}─┴─${sep(cols.status)}─┴─${sep(cols.premium)}─┘`\n\n consola.log(\"\")\n consola.log(topBorder)\n consola.log(header)\n consola.log(midBorder)\n\n for (const row of rows) {\n consola.log(\n `│ ${pad(row.num, cols.num)} │ ${pad(row.label, cols.label)} │ ${pad(row.login, cols.login)} │ ${pad(row.status, cols.status)} │ ${pad(row.premium, cols.premium)} │`,\n )\n }\n\n consola.log(botBorder)\n consola.log(\"\")\n } catch (err) {\n consola.warn(`Failed to list accounts: ${rootCause(err)}`)\n consola.debug(\"Failed to list accounts:\", err)\n process.exitCode = 1\n }\n },\n})\n\n// ---------------------------------------------------------------------------\n// copilot-api-plus remove-account\n// ---------------------------------------------------------------------------\n\nexport const removeAccount = defineCommand({\n meta: {\n name: \"remove-account\",\n description: \"Remove an account by label or index\",\n },\n args: {\n id: {\n type: \"positional\",\n description: \"Label or index (1-based) of the account to remove\",\n required: false,\n },\n label: {\n alias: \"l\",\n type: \"string\",\n description: \"Label of the account to remove\",\n },\n force: {\n alias: \"f\",\n type: \"boolean\",\n default: false,\n description: \"Skip confirmation prompt\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n },\n async run({ args }) {\n if (args.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n try {\n await ensurePaths()\n await accountManager.loadAccounts()\n\n const accounts = accountManager.getAccounts()\n\n if (accounts.length === 0) {\n consola.warn(\"No accounts configured.\")\n return\n }\n\n // Resolve which account to remove\n const identifier = args.id || args.label\n if (!identifier) {\n consola.error(\n \"Please specify an account to remove (by label or index).\",\n )\n consola.info(\"Usage: remove-account <label-or-index>\")\n process.exitCode = 1\n return\n }\n\n let account: (typeof accounts)[0] | undefined\n\n // Try numeric index first (1-based)\n const idx = Number.parseInt(identifier, 10)\n if (!Number.isNaN(idx) && idx >= 1 && idx <= accounts.length) {\n account = accounts[idx - 1]\n }\n\n // Try label match\n if (!account) {\n account = accounts.find(\n (a) => a.label.toLowerCase() === identifier.toLowerCase(),\n )\n }\n\n if (!account) {\n consola.error(`Account not found: ${identifier}`)\n process.exitCode = 1\n return\n }\n\n // Confirmation\n if (!args.force) {\n const confirmed = await consola.prompt(\n `Remove account \"${account.label}\" (${account.githubLogin || \"unknown\"})? [y/N]`,\n { type: \"confirm\" },\n )\n if (!confirmed) {\n consola.info(\"Cancelled.\")\n return\n }\n }\n\n const removed = await accountManager.removeAccount(account.id)\n if (removed) {\n consola.success(\n `Account removed: ${account.label} (${account.githubLogin || \"unknown\"})`,\n )\n } else {\n consola.error(\"Failed to remove account.\")\n process.exitCode = 1\n }\n } catch (err) {\n consola.warn(`Failed to remove account: ${rootCause(err)}`)\n consola.debug(\"Failed to remove account:\", err)\n process.exitCode = 1\n }\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { PATHS, ensurePaths } from \"./lib/paths\"\nimport { state } from \"./lib/state\"\nimport { setupGitHubToken } from \"./lib/token\"\n\ninterface RunAuthOptions {\n verbose: boolean\n showToken: boolean\n}\n\nexport async function runAuth(options: RunAuthOptions): Promise<void> {\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 await setupGitHubToken({ force: true })\n consola.success(\"GitHub token written to\", PATHS.GITHUB_TOKEN_PATH)\n}\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run GitHub auth flow without running the server\",\n },\n args: {\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub token on auth\",\n },\n },\n run({ args }) {\n return runAuth({\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { setupGitHubToken } from \"./lib/token\"\nimport { rootCause } from \"./lib/utils\"\nimport {\n getCopilotUsage,\n type QuotaDetail,\n} from \"./services/github/get-copilot-usage\"\n\nexport const checkUsage = defineCommand({\n meta: {\n name: \"check-usage\",\n description: \"Show current GitHub Copilot usage/quota information\",\n },\n async run() {\n await ensurePaths()\n await setupGitHubToken()\n try {\n const usage = await getCopilotUsage()\n const premium = usage.quota_snapshots.premium_interactions\n const premiumTotal = premium.entitlement\n const premiumUsed = premiumTotal - premium.remaining\n const premiumPercentUsed =\n premiumTotal > 0 ? (premiumUsed / premiumTotal) * 100 : 0\n const premiumPercentRemaining = premium.percent_remaining\n\n // Helper to summarize a quota snapshot\n function summarizeQuota(name: string, snap: QuotaDetail | undefined) {\n if (!snap) return `${name}: N/A`\n const total = snap.entitlement\n const used = total - snap.remaining\n const percentUsed = total > 0 ? (used / total) * 100 : 0\n const percentRemaining = snap.percent_remaining\n return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`\n }\n\n const premiumLine = `Premium: ${premiumUsed}/${premiumTotal} used (${premiumPercentUsed.toFixed(1)}% used, ${premiumPercentRemaining.toFixed(1)}% remaining)`\n const chatLine = summarizeQuota(\"Chat\", usage.quota_snapshots.chat)\n const completionsLine = summarizeQuota(\n \"Completions\",\n usage.quota_snapshots.completions,\n )\n\n consola.box(\n `Copilot Usage (plan: ${usage.copilot_plan})\\n`\n + `Quota resets: ${usage.quota_reset_date}\\n`\n + `\\nQuotas:\\n`\n + ` ${premiumLine}\\n`\n + ` ${chatLine}\\n`\n + ` ${completionsLine}`,\n )\n } catch (err) {\n consola.warn(`Failed to fetch Copilot usage: ${rootCause(err)}`)\n consola.debug(\"Failed to fetch Copilot usage:\", err)\n process.exit(1)\n }\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\nimport fs from \"node:fs/promises\"\nimport os from \"node:os\"\n\nimport { getProxyConfig, type ProxyConfig } from \"./lib/config\"\nimport { PATHS } from \"./lib/paths\"\n\ninterface DebugInfo {\n version: string\n runtime: {\n name: string\n version: string\n platform: string\n arch: string\n }\n paths: {\n APP_DIR: string\n GITHUB_TOKEN_PATH: string\n }\n credentials: {\n github: boolean\n }\n proxy?: ProxyConfig\n}\n\ninterface RunDebugOptions {\n json: boolean\n}\n\nasync function getPackageVersion(): Promise<string> {\n try {\n const packageJsonPath = new URL(\"../package.json\", import.meta.url).pathname\n // @ts-expect-error https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v59.0.1/docs/rules/prefer-json-parse-buffer.md\n // JSON.parse() can actually parse buffers\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath)) as {\n version: string\n }\n return packageJson.version\n } catch {\n return \"unknown\"\n }\n}\n\nfunction getRuntimeInfo() {\n const isBun = typeof Bun !== \"undefined\"\n\n return {\n name: isBun ? \"bun\" : \"node\",\n version: isBun ? Bun.version : process.version.slice(1),\n platform: os.platform(),\n arch: os.arch(),\n }\n}\n\nasync function checkTokenExists(): Promise<boolean> {\n try {\n const stats = await fs.stat(PATHS.GITHUB_TOKEN_PATH)\n if (!stats.isFile()) return false\n\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim().length > 0\n } catch {\n return false\n }\n}\n\nasync function getDebugInfo(): Promise<DebugInfo> {\n const [version, githubExists, proxyConfig] = await Promise.all([\n getPackageVersion(),\n checkTokenExists(),\n getProxyConfig(),\n ])\n\n return {\n version,\n runtime: getRuntimeInfo(),\n paths: {\n APP_DIR: PATHS.APP_DIR,\n GITHUB_TOKEN_PATH: PATHS.GITHUB_TOKEN_PATH,\n },\n credentials: {\n github: githubExists,\n },\n proxy: proxyConfig,\n }\n}\n\nfunction printDebugInfoPlain(info: DebugInfo): void {\n let proxyStatus = \"Not configured\"\n if (info.proxy) {\n proxyStatus =\n info.proxy.enabled ?\n `Enabled (${info.proxy.httpProxy || info.proxy.httpsProxy})`\n : \"Disabled\"\n }\n\n consola.info(`copilot-api-plus debug\n\nVersion: ${info.version}\nRuntime: ${info.runtime.name} ${info.runtime.version} (${info.runtime.platform} ${info.runtime.arch})\n\nPaths:\n APP_DIR: ${info.paths.APP_DIR}\n GITHUB_TOKEN_PATH: ${info.paths.GITHUB_TOKEN_PATH}\n\nCredentials:\n GitHub Copilot: ${info.credentials.github ? \"✅ Configured\" : \"❌ Not configured\"}\n\nProxy: ${proxyStatus}`)\n}\n\nfunction printDebugInfoJson(info: DebugInfo): void {\n console.log(JSON.stringify(info, null, 2))\n}\n\nexport async function runDebug(options: RunDebugOptions): Promise<void> {\n const debugInfo = await getDebugInfo()\n\n if (options.json) {\n printDebugInfoJson(debugInfo)\n } else {\n printDebugInfoPlain(debugInfo)\n }\n}\n\nexport const debug = defineCommand({\n meta: {\n name: \"debug\",\n description: \"Print debug information about the application\",\n },\n args: {\n json: {\n type: \"boolean\",\n default: false,\n description: \"Output debug information as JSON\",\n },\n },\n run({ args }) {\n return runDebug({\n json: args.json,\n })\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths, PATHS } from \"./lib/paths\"\nimport { clearGithubToken } from \"./lib/token\"\n\nexport async function runLogout(options: {\n github?: boolean\n all?: boolean\n}): Promise<void> {\n await ensurePaths()\n\n if (options.all || options.github) {\n await clearGithubToken()\n consola.success(\"Logged out from GitHub Copilot\")\n consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`)\n return\n }\n\n // Default: clear GitHub token\n await clearGithubToken()\n consola.success(\"Logged out from GitHub Copilot\")\n consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`)\n}\n\nexport const logout = defineCommand({\n meta: {\n name: \"logout\",\n description: \"Clear stored credentials and logout\",\n },\n args: {\n github: {\n alias: \"g\",\n type: \"boolean\",\n default: false,\n description: \"Clear GitHub Copilot token\",\n },\n all: {\n alias: \"a\",\n type: \"boolean\",\n default: false,\n description: \"Clear all credentials\",\n },\n },\n run({ args }) {\n return runLogout({\n github: args.github,\n all: args.all,\n })\n },\n})\n","/**\n * Proxy configuration command\n * Allows users to configure, enable, disable, and view proxy settings\n */\n\n/* eslint-disable max-lines-per-function */\n/* eslint-disable complexity */\n\nimport * as p from \"@clack/prompts\"\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport {\n clearProxyConfig,\n getProxyConfig,\n saveProxyConfig,\n type ProxyConfig,\n} from \"./lib/config\"\nimport { ensurePaths } from \"./lib/paths\"\n\nexport const proxy = defineCommand({\n meta: {\n name: \"proxy\",\n description: \"Configure proxy settings (persistent)\",\n },\n args: {\n set: {\n type: \"boolean\",\n default: false,\n description: \"Set proxy configuration interactively\",\n },\n enable: {\n type: \"boolean\",\n default: false,\n description: \"Enable saved proxy configuration\",\n },\n disable: {\n type: \"boolean\",\n default: false,\n description: \"Disable proxy (keep settings)\",\n },\n clear: {\n type: \"boolean\",\n default: false,\n description: \"Clear all proxy settings\",\n },\n show: {\n type: \"boolean\",\n default: false,\n description: \"Show current proxy configuration\",\n },\n \"http-proxy\": {\n type: \"string\",\n description: \"HTTP proxy URL (e.g., http://proxy:8080)\",\n },\n \"https-proxy\": {\n type: \"string\",\n description: \"HTTPS proxy URL (e.g., http://proxy:8080)\",\n },\n \"no-proxy\": {\n type: \"string\",\n description: \"Comma-separated list of hosts to bypass proxy\",\n },\n },\n async run({ args }) {\n await ensurePaths()\n\n // Show current configuration\n if (\n args.show\n || (!args.set\n && !args.enable\n && !args.disable\n && !args.clear\n && !args[\"http-proxy\"]\n && !args[\"https-proxy\"])\n ) {\n const config = await getProxyConfig()\n if (!config) {\n consola.info(\"No proxy configuration saved.\")\n consola.info(\"\")\n consola.info(\"To configure proxy, use one of:\")\n consola.info(\n \" copilot-api-plus proxy --set # Interactive setup\",\n )\n consola.info(\n \" copilot-api-plus proxy --http-proxy http://proxy:8080 # Direct set\",\n )\n return\n }\n\n consola.info(\"Current proxy configuration:\")\n consola.info(` Status: ${config.enabled ? \"✅ Enabled\" : \"❌ Disabled\"}`)\n if (config.httpProxy) {\n consola.info(` HTTP_PROXY: ${config.httpProxy}`)\n }\n if (config.httpsProxy) {\n consola.info(` HTTPS_PROXY: ${config.httpsProxy}`)\n }\n if (config.noProxy) {\n consola.info(` NO_PROXY: ${config.noProxy}`)\n }\n return\n }\n\n // Clear proxy settings\n if (args.clear) {\n await clearProxyConfig()\n consola.success(\"Proxy configuration cleared.\")\n return\n }\n\n // Enable proxy\n if (args.enable) {\n const config = await getProxyConfig()\n if (!config) {\n consola.error(\n \"No proxy configuration saved. Use --set to configure first.\",\n )\n return\n }\n config.enabled = true\n await saveProxyConfig(config)\n consola.success(\"Proxy enabled. It will be used on next server start.\")\n return\n }\n\n // Disable proxy\n if (args.disable) {\n const config = await getProxyConfig()\n if (!config) {\n consola.info(\"No proxy configuration to disable.\")\n return\n }\n config.enabled = false\n await saveProxyConfig(config)\n consola.success(\"Proxy disabled. Settings are preserved.\")\n return\n }\n\n // Direct set via command line args\n if (args[\"http-proxy\"] || args[\"https-proxy\"]) {\n const newConfig: ProxyConfig = {\n enabled: true,\n httpProxy: args[\"http-proxy\"],\n httpsProxy: args[\"https-proxy\"] || args[\"http-proxy\"], // Use HTTP proxy for HTTPS if not specified\n noProxy: args[\"no-proxy\"],\n }\n await saveProxyConfig(newConfig)\n consola.success(\"Proxy configuration saved and enabled.\")\n consola.info(` HTTP_PROXY: ${newConfig.httpProxy || \"(not set)\"}`)\n consola.info(` HTTPS_PROXY: ${newConfig.httpsProxy || \"(not set)\"}`)\n if (newConfig.noProxy) {\n consola.info(` NO_PROXY: ${newConfig.noProxy}`)\n }\n return\n }\n\n // Interactive setup\n if (args.set) {\n p.intro(\"Proxy Configuration\")\n\n const existingConfig = await getProxyConfig()\n\n const httpProxy = await p.text({\n message: \"HTTP Proxy URL\",\n placeholder: \"http://proxy:8080\",\n initialValue: existingConfig?.httpProxy || \"\",\n })\n\n if (p.isCancel(httpProxy)) {\n p.cancel(\"Configuration cancelled.\")\n return\n }\n\n const httpsProxy = await p.text({\n message: \"HTTPS Proxy URL (leave empty to use HTTP proxy)\",\n placeholder: \"http://proxy:8080\",\n initialValue: existingConfig?.httpsProxy || \"\",\n })\n\n if (p.isCancel(httpsProxy)) {\n p.cancel(\"Configuration cancelled.\")\n return\n }\n\n const noProxy = await p.text({\n message: \"No Proxy (comma-separated hosts to bypass)\",\n placeholder: \"localhost,127.0.0.1,.local\",\n initialValue: existingConfig?.noProxy || \"\",\n })\n\n if (p.isCancel(noProxy)) {\n p.cancel(\"Configuration cancelled.\")\n return\n }\n\n const enable = await p.confirm({\n message: \"Enable proxy now?\",\n initialValue: true,\n })\n\n if (p.isCancel(enable)) {\n p.cancel(\"Configuration cancelled.\")\n return\n }\n\n const newConfig: ProxyConfig = {\n enabled: enable,\n httpProxy: httpProxy || undefined,\n httpsProxy: httpsProxy || httpProxy || undefined,\n noProxy: noProxy || undefined,\n }\n\n await saveProxyConfig(newConfig)\n\n p.outro(`Proxy configuration saved${enable ? \" and enabled\" : \"\"}.`)\n }\n },\n})\n","","const fs = require('fs')\nconst path = require('path')\nconst os = require('os')\nconst crypto = require('crypto')\nconst packageJson = require('../package.json')\n\nconst version = packageJson.version\n\n// Array of tips to display randomly\nconst TIPS = [\n '🔐 encrypt with Dotenvx: https://dotenvx.com',\n '🔐 prevent committing .env to code: https://dotenvx.com/precommit',\n '🔐 prevent building .env in docker: https://dotenvx.com/prebuild',\n '📡 add observability to secrets: https://dotenvx.com/ops',\n '👥 sync secrets across teammates & machines: https://dotenvx.com/ops',\n '🗂️ backup and recover secrets: https://dotenvx.com/ops',\n '✅ audit secrets and track compliance: https://dotenvx.com/ops',\n '🔄 add secrets lifecycle management: https://dotenvx.com/ops',\n '🔑 add access controls to secrets: https://dotenvx.com/ops',\n '🛠️ run anywhere with `dotenvx run -- yourcommand`',\n '⚙️ specify custom .env file path with { path: \\'/custom/path/.env\\' }',\n '⚙️ enable debug logging with { debug: true }',\n '⚙️ override existing env vars with { override: true }',\n '⚙️ suppress all logs with { quiet: true }',\n '⚙️ write to custom object with { processEnv: myObject }',\n '⚙️ load multiple .env files with { path: [\\'.env.local\\', \\'.env\\'] }'\n]\n\n// Get a random tip from the tips array\nfunction _getRandomTip () {\n return TIPS[Math.floor(Math.random() * TIPS.length)]\n}\n\nfunction parseBoolean (value) {\n if (typeof value === 'string') {\n return !['false', '0', 'no', 'off', ''].includes(value.toLowerCase())\n }\n return Boolean(value)\n}\n\nfunction supportsAnsi () {\n return process.stdout.isTTY // && process.env.TERM !== 'dumb'\n}\n\nfunction dim (text) {\n return supportsAnsi() ? `\\x1b[2m${text}\\x1b[0m` : text\n}\n\nconst LINE = /(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg\n\n// Parse src into an Object\nfunction parse (src) {\n const obj = {}\n\n // Convert buffer to string\n let lines = src.toString()\n\n // Convert line breaks to same format\n lines = lines.replace(/\\r\\n?/mg, '\\n')\n\n let match\n while ((match = LINE.exec(lines)) != null) {\n const key = match[1]\n\n // Default undefined or null to empty string\n let value = (match[2] || '')\n\n // Remove whitespace\n value = value.trim()\n\n // Check if double quoted\n const maybeQuote = value[0]\n\n // Remove surrounding quotes\n value = value.replace(/^(['\"`])([\\s\\S]*)\\1$/mg, '$2')\n\n // Expand newlines if double quoted\n if (maybeQuote === '\"') {\n value = value.replace(/\\\\n/g, '\\n')\n value = value.replace(/\\\\r/g, '\\r')\n }\n\n // Add to object\n obj[key] = value\n }\n\n return obj\n}\n\nfunction _parseVault (options) {\n options = options || {}\n\n const vaultPath = _vaultPath(options)\n options.path = vaultPath // parse .env.vault\n const result = DotenvModule.configDotenv(options)\n if (!result.parsed) {\n const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`)\n err.code = 'MISSING_DATA'\n throw err\n }\n\n // handle scenario for comma separated keys - for use with key rotation\n // example: DOTENV_KEY=\"dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenvx.com/vault/.env.vault?environment=prod\"\n const keys = _dotenvKey(options).split(',')\n const length = keys.length\n\n let decrypted\n for (let i = 0; i < length; i++) {\n try {\n // Get full key\n const key = keys[i].trim()\n\n // Get instructions for decrypt\n const attrs = _instructions(result, key)\n\n // Decrypt\n decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key)\n\n break\n } catch (error) {\n // last key\n if (i + 1 >= length) {\n throw error\n }\n // try next key\n }\n }\n\n // Parse decrypted .env string\n return DotenvModule.parse(decrypted)\n}\n\nfunction _warn (message) {\n console.error(`[dotenv@${version}][WARN] ${message}`)\n}\n\nfunction _debug (message) {\n console.log(`[dotenv@${version}][DEBUG] ${message}`)\n}\n\nfunction _log (message) {\n console.log(`[dotenv@${version}] ${message}`)\n}\n\nfunction _dotenvKey (options) {\n // prioritize developer directly setting options.DOTENV_KEY\n if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {\n return options.DOTENV_KEY\n }\n\n // secondary infra already contains a DOTENV_KEY environment variable\n if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {\n return process.env.DOTENV_KEY\n }\n\n // fallback to empty string\n return ''\n}\n\nfunction _instructions (result, dotenvKey) {\n // Parse DOTENV_KEY. Format is a URI\n let uri\n try {\n uri = new URL(dotenvKey)\n } catch (error) {\n if (error.code === 'ERR_INVALID_URL') {\n const err = new Error('INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n throw error\n }\n\n // Get decrypt key\n const key = uri.password\n if (!key) {\n const err = new Error('INVALID_DOTENV_KEY: Missing key part')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n // Get environment\n const environment = uri.searchParams.get('environment')\n if (!environment) {\n const err = new Error('INVALID_DOTENV_KEY: Missing environment part')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n // Get ciphertext payload\n const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`\n const ciphertext = result.parsed[environmentKey] // DOTENV_VAULT_PRODUCTION\n if (!ciphertext) {\n const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`)\n err.code = 'NOT_FOUND_DOTENV_ENVIRONMENT'\n throw err\n }\n\n return { ciphertext, key }\n}\n\nfunction _vaultPath (options) {\n let possibleVaultPath = null\n\n if (options && options.path && options.path.length > 0) {\n if (Array.isArray(options.path)) {\n for (const filepath of options.path) {\n if (fs.existsSync(filepath)) {\n possibleVaultPath = filepath.endsWith('.vault') ? filepath : `${filepath}.vault`\n }\n }\n } else {\n possibleVaultPath = options.path.endsWith('.vault') ? options.path : `${options.path}.vault`\n }\n } else {\n possibleVaultPath = path.resolve(process.cwd(), '.env.vault')\n }\n\n if (fs.existsSync(possibleVaultPath)) {\n return possibleVaultPath\n }\n\n return null\n}\n\nfunction _resolveHome (envPath) {\n return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath\n}\n\nfunction _configVault (options) {\n const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || (options && options.debug))\n const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || (options && options.quiet))\n\n if (debug || !quiet) {\n _log('Loading env from encrypted .env.vault')\n }\n\n const parsed = DotenvModule._parseVault(options)\n\n let processEnv = process.env\n if (options && options.processEnv != null) {\n processEnv = options.processEnv\n }\n\n DotenvModule.populate(processEnv, parsed, options)\n\n return { parsed }\n}\n\nfunction configDotenv (options) {\n const dotenvPath = path.resolve(process.cwd(), '.env')\n let encoding = 'utf8'\n let processEnv = process.env\n if (options && options.processEnv != null) {\n processEnv = options.processEnv\n }\n let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || (options && options.debug))\n let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || (options && options.quiet))\n\n if (options && options.encoding) {\n encoding = options.encoding\n } else {\n if (debug) {\n _debug('No encoding is specified. UTF-8 is used by default')\n }\n }\n\n let optionPaths = [dotenvPath] // default, look for .env\n if (options && options.path) {\n if (!Array.isArray(options.path)) {\n optionPaths = [_resolveHome(options.path)]\n } else {\n optionPaths = [] // reset default\n for (const filepath of options.path) {\n optionPaths.push(_resolveHome(filepath))\n }\n }\n }\n\n // Build the parsed data in a temporary object (because we need to return it). Once we have the final\n // parsed data, we will combine it with process.env (or options.processEnv if provided).\n let lastError\n const parsedAll = {}\n for (const path of optionPaths) {\n try {\n // Specifying an encoding returns a string instead of a buffer\n const parsed = DotenvModule.parse(fs.readFileSync(path, { encoding }))\n\n DotenvModule.populate(parsedAll, parsed, options)\n } catch (e) {\n if (debug) {\n _debug(`Failed to load ${path} ${e.message}`)\n }\n lastError = e\n }\n }\n\n const populated = DotenvModule.populate(processEnv, parsedAll, options)\n\n // handle user settings DOTENV_CONFIG_ options inside .env file(s)\n debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug)\n quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet)\n\n if (debug || !quiet) {\n const keysCount = Object.keys(populated).length\n const shortPaths = []\n for (const filePath of optionPaths) {\n try {\n const relative = path.relative(process.cwd(), filePath)\n shortPaths.push(relative)\n } catch (e) {\n if (debug) {\n _debug(`Failed to load ${filePath} ${e.message}`)\n }\n lastError = e\n }\n }\n\n _log(`injecting env (${keysCount}) from ${shortPaths.join(',')} ${dim(`-- tip: ${_getRandomTip()}`)}`)\n }\n\n if (lastError) {\n return { parsed: parsedAll, error: lastError }\n } else {\n return { parsed: parsedAll }\n }\n}\n\n// Populates process.env from .env file\nfunction config (options) {\n // fallback to original dotenv if DOTENV_KEY is not set\n if (_dotenvKey(options).length === 0) {\n return DotenvModule.configDotenv(options)\n }\n\n const vaultPath = _vaultPath(options)\n\n // dotenvKey exists but .env.vault file does not exist\n if (!vaultPath) {\n _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`)\n\n return DotenvModule.configDotenv(options)\n }\n\n return DotenvModule._configVault(options)\n}\n\nfunction decrypt (encrypted, keyStr) {\n const key = Buffer.from(keyStr.slice(-64), 'hex')\n let ciphertext = Buffer.from(encrypted, 'base64')\n\n const nonce = ciphertext.subarray(0, 12)\n const authTag = ciphertext.subarray(-16)\n ciphertext = ciphertext.subarray(12, -16)\n\n try {\n const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce)\n aesgcm.setAuthTag(authTag)\n return `${aesgcm.update(ciphertext)}${aesgcm.final()}`\n } catch (error) {\n const isRange = error instanceof RangeError\n const invalidKeyLength = error.message === 'Invalid key length'\n const decryptionFailed = error.message === 'Unsupported state or unable to authenticate data'\n\n if (isRange || invalidKeyLength) {\n const err = new Error('INVALID_DOTENV_KEY: It must be 64 characters long (or more)')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n } else if (decryptionFailed) {\n const err = new Error('DECRYPTION_FAILED: Please check your DOTENV_KEY')\n err.code = 'DECRYPTION_FAILED'\n throw err\n } else {\n throw error\n }\n }\n}\n\n// Populate process.env with parsed values\nfunction populate (processEnv, parsed, options = {}) {\n const debug = Boolean(options && options.debug)\n const override = Boolean(options && options.override)\n const populated = {}\n\n if (typeof parsed !== 'object') {\n const err = new Error('OBJECT_REQUIRED: Please check the processEnv argument being passed to populate')\n err.code = 'OBJECT_REQUIRED'\n throw err\n }\n\n // Set process.env\n for (const key of Object.keys(parsed)) {\n if (Object.prototype.hasOwnProperty.call(processEnv, key)) {\n if (override === true) {\n processEnv[key] = parsed[key]\n populated[key] = parsed[key]\n }\n\n if (debug) {\n if (override === true) {\n _debug(`\"${key}\" is already defined and WAS overwritten`)\n } else {\n _debug(`\"${key}\" is already defined and was NOT overwritten`)\n }\n }\n } else {\n processEnv[key] = parsed[key]\n populated[key] = parsed[key]\n }\n }\n\n return populated\n}\n\nconst DotenvModule = {\n configDotenv,\n _configVault,\n _parseVault,\n config,\n decrypt,\n parse,\n populate\n}\n\nmodule.exports.configDotenv = DotenvModule.configDotenv\nmodule.exports._configVault = DotenvModule._configVault\nmodule.exports._parseVault = DotenvModule._parseVault\nmodule.exports.config = DotenvModule.config\nmodule.exports.decrypt = DotenvModule.decrypt\nmodule.exports.parse = DotenvModule.parse\nmodule.exports.populate = DotenvModule.populate\n\nmodule.exports = DotenvModule\n","// ../config.js accepts options via environment variables\nconst options = {}\n\nif (process.env.DOTENV_CONFIG_ENCODING != null) {\n options.encoding = process.env.DOTENV_CONFIG_ENCODING\n}\n\nif (process.env.DOTENV_CONFIG_PATH != null) {\n options.path = process.env.DOTENV_CONFIG_PATH\n}\n\nif (process.env.DOTENV_CONFIG_QUIET != null) {\n options.quiet = process.env.DOTENV_CONFIG_QUIET\n}\n\nif (process.env.DOTENV_CONFIG_DEBUG != null) {\n options.debug = process.env.DOTENV_CONFIG_DEBUG\n}\n\nif (process.env.DOTENV_CONFIG_OVERRIDE != null) {\n options.override = process.env.DOTENV_CONFIG_OVERRIDE\n}\n\nif (process.env.DOTENV_CONFIG_DOTENV_KEY != null) {\n options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY\n}\n\nmodule.exports = options\n","const re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/\n\nmodule.exports = function optionMatcher (args) {\n const options = args.reduce(function (acc, cur) {\n const matches = cur.match(re)\n if (matches) {\n acc[matches[1]] = matches[2]\n }\n return acc\n }, {})\n\n if (!('quiet' in options)) {\n options.quiet = 'true'\n }\n\n return options\n}\n","(function () {\n require('./lib/main').config(\n Object.assign(\n {},\n require('./lib/env-options'),\n require('./lib/cli-options')(process.argv)\n )\n )\n})()\n","/**\n * Model Router - Model mapping and per-model concurrency control\n *\n * Provides flexible model name mapping (requested → actual) and\n * per-model concurrency limits using a semaphore pattern.\n */\n\nimport consola from \"consola\"\n\nexport interface ModelMappingConfig {\n /** Map from requested model name → actual model name sent to Copilot. Special key \"*\" is the default/fallback. */\n mapping: Record<string, string>\n /** Per-model max concurrent requests. Special key \"default\" is the fallback. */\n concurrency: Record<string, number>\n}\n\nconst DEFAULT_CONFIG: ModelMappingConfig = {\n mapping: {},\n concurrency: {\n default: 10,\n },\n}\n\nconst DEFAULT_MAX_CONCURRENCY = 10\n\nexport class ModelRouter {\n private config: ModelMappingConfig\n private queues: Map<string, { active: number; waiters: Array<() => void> }> =\n new Map()\n\n constructor(config?: ModelMappingConfig) {\n this.config =\n config ?\n { ...config }\n : { ...DEFAULT_CONFIG, mapping: {}, concurrency: { default: 10 } }\n }\n\n /**\n * Resolve a requested model name to the actual model name.\n *\n * Resolution order:\n * 1. Exact match in config.mapping\n * 2. Wildcard \"*\" in config.mapping\n * 3. Passthrough (return requestedModel as-is)\n */\n resolveModel(requestedModel: string): string {\n // 1. Exact match\n if (requestedModel in this.config.mapping) {\n const resolved = this.config.mapping[requestedModel]\n consola.debug(`Model mapping: \"${requestedModel}\" → \"${resolved}\"`)\n return resolved\n }\n\n // 2. Wildcard fallback\n if (\"*\" in this.config.mapping) {\n const resolved = this.config.mapping[\"*\"]\n consola.debug(\n `Model mapping (wildcard): \"${requestedModel}\" → \"${resolved}\"`,\n )\n return resolved\n }\n\n // 3. Passthrough\n return requestedModel\n }\n\n /**\n * Acquire a concurrency slot for the given model.\n *\n * The caller should pass the **already-resolved** model name (i.e. the\n * value returned by `resolveModel()`). This method does NOT re-resolve\n * the name so that concurrency limits are keyed by the actual model sent\n * to the backend, not the user-facing alias.\n *\n * Returns a release function that must be called when the request completes.\n * If the concurrency limit is reached, the returned promise will wait until\n * a slot becomes available.\n */\n async acquireSlot(resolvedModel: string): Promise<() => void> {\n const maxConcurrency =\n (this.config.concurrency as Partial<Record<string, number>>)[\n resolvedModel\n ]\n ?? (this.config.concurrency as Partial<Record<string, number>>)[\"default\"]\n ?? DEFAULT_MAX_CONCURRENCY\n\n let queue = this.queues.get(resolvedModel)\n if (!queue) {\n queue = { active: 0, waiters: [] }\n this.queues.set(resolvedModel, queue)\n }\n\n if (queue.active < maxConcurrency) {\n queue.active++\n consola.debug(\n `Slot acquired for \"${resolvedModel}\": ${queue.active}/${maxConcurrency} active`,\n )\n return () => this.releaseSlot(resolvedModel)\n }\n\n // Wait for a slot to open\n const currentQueue = queue\n consola.debug(\n `Concurrency limit reached for \"${resolvedModel}\" (${maxConcurrency}), queuing request`,\n )\n return new Promise<() => void>((resolve) => {\n currentQueue.waiters.push(() => {\n currentQueue.active++\n consola.debug(\n `Queued slot acquired for \"${resolvedModel}\": ${currentQueue.active}/${maxConcurrency} active`,\n )\n resolve(() => this.releaseSlot(resolvedModel))\n })\n })\n }\n\n private releaseSlot(model: string): void {\n const queue = this.queues.get(model)\n if (!queue) return\n\n queue.active--\n\n if (queue.waiters.length > 0) {\n const next = queue.waiters.shift()\n if (next) next()\n }\n\n consola.debug(\n `Slot released for \"${model}\": ${queue.active} active, ${queue.waiters.length} queued`,\n )\n }\n\n /**\n * Get current concurrency stats for all tracked models.\n */\n getStats(): Record<\n string,\n { active: number; queued: number; maxConcurrency: number }\n > {\n const stats: Record<\n string,\n { active: number; queued: number; maxConcurrency: number }\n > = {}\n\n for (const [model, queue] of this.queues) {\n const maxConcurrency =\n (this.config.concurrency as Partial<Record<string, number>>)[model]\n ?? (this.config.concurrency as Partial<Record<string, number>>)[\n \"default\"\n ]\n ?? DEFAULT_MAX_CONCURRENCY\n\n stats[model] = {\n active: queue.active,\n queued: queue.waiters.length,\n maxConcurrency,\n }\n }\n\n return stats\n }\n\n /**\n * Update the model name mapping configuration.\n */\n updateMapping(mapping: Record<string, string>): void {\n this.config.mapping = { ...mapping }\n consola.info(\"Model mapping updated:\", Object.keys(mapping).length, \"rules\")\n }\n\n /**\n * Update the per-model concurrency configuration.\n */\n updateConcurrency(concurrency: Record<string, number>): void {\n this.config.concurrency = { ...concurrency }\n consola.info(\n \"Model concurrency updated:\",\n Object.keys(concurrency).length,\n \"rules\",\n )\n }\n\n /**\n * Get the current configuration (returns a copy).\n */\n getConfig(): ModelMappingConfig {\n return {\n mapping: { ...this.config.mapping },\n concurrency: { ...this.config.concurrency },\n }\n }\n}\n\nexport const modelRouter = new ModelRouter()\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\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(\n ([key, value]) =>\n `set -gx ${key} '${value.replaceAll(\"'\", String.raw`\\'`)}'`,\n )\n .join(\"; \")\n break\n }\n default: {\n // bash, zsh, sh\n const assignments = filteredEnvVars\n .map(\n ([key, value]) =>\n `${key}='${value.replaceAll(\"'\", String.raw`'\\''`)}'`,\n )\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 type { Context, MiddlewareHandler } from \"hono\"\n\nimport { HTTPException } from \"hono/http-exception\"\nimport { timingSafeEqual } from \"node:crypto\"\n\nimport { state } from \"./state\"\n\n/**\n * Retrieve an API key from the incoming request.\n *\n * Checks common locations where clients supply keys (Authorization Bearer header, `x-api-key` header, or `apiKey` query parameter) and returns the first one found.\n *\n * @returns The extracted API key, or `undefined` if no key is present.\n */\nfunction extractApiKey(c: Context): string | undefined {\n // OpenAI format: Authorization header with Bearer prefix\n const authHeader = c.req.header(\"authorization\")\n if (authHeader?.startsWith(\"Bearer \")) {\n return authHeader.slice(7) // Remove 'Bearer ' prefix\n }\n\n // Anthropic format: x-api-key header\n const anthropicKey = c.req.header(\"x-api-key\")\n if (anthropicKey) {\n return anthropicKey\n }\n\n // Fallback: query parameter, for extra compatibility of `/usage` or `/token` route\n const queryKey = c.req.query(\"apiKey\")\n if (queryKey) {\n return queryKey\n }\n\n return undefined\n}\n\n/**\n * API key authentication middleware\n * Validates that the request contains a valid API key if API keys are configured\n */\nexport const apiKeyAuthMiddleware: MiddlewareHandler = async (c, next) => {\n // If no API keys are configured, skip authentication\n if (!state.apiKeys || state.apiKeys.length === 0) {\n await next()\n return\n }\n\n const providedKey = extractApiKey(c)\n\n // If no API key is provided, return 401\n if (!providedKey) {\n throw new HTTPException(401, {\n message:\n \"API key required. Please provide a valid API key in the Authorization header (Bearer token) or x-api-key header.\",\n })\n }\n\n // Check if the provided key matches any of the configured keys (timing-safe)\n const isValidKey = state.apiKeys.some((key) => {\n if (key.length !== providedKey.length) return false\n try {\n return timingSafeEqual(Buffer.from(key), Buffer.from(providedKey))\n } catch {\n return false\n }\n })\n\n if (!isValidKey) {\n throw new HTTPException(401, {\n message: \"Invalid API key. Please provide a valid API key.\",\n })\n }\n\n // Key is valid, continue with the request\n await next()\n}\n","/**\n * Custom logger middleware that displays model name + thinking status before timestamp\n */\n\nimport type { Context, MiddlewareHandler, Next } from \"hono\"\n\n/**\n * Get timestamp string in format HH:mm:ss\n */\nfunction getTime(): string {\n return new Date().toLocaleTimeString(\"en-US\", { hour12: false })\n}\n\n/**\n * Format duration in human readable format\n */\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`\n return `${(ms / 1000).toFixed(1)}s`\n}\n\n/**\n * Extract model name and thinking status from request body.\n *\n * Thinking is considered active when:\n * - The client explicitly passes reasoning_effort / thinking_budget / thinking\n * - OR the backend will auto-inject thinking (default for all supported models)\n *\n * Since the proxy injects thinking for every model except those known to reject\n * it, we always mark thinking=true here. The `create-chat-completions` layer\n * will log the precise injection path separately.\n */\nasync function extractModelInfo(\n c: Context,\n): Promise<{ model?: string; thinking?: boolean }> {\n try {\n // Clone the request to avoid consuming the body\n const clonedReq = c.req.raw.clone()\n const body = (await clonedReq.json()) as {\n model?: string\n // OpenAI-style thinking params\n reasoning_effort?: string\n thinking_budget?: number\n // Anthropic-style thinking params\n thinking?: { type?: string; budget_tokens?: number }\n }\n // Client-explicit thinking check\n const clientThinking =\n Boolean(body.reasoning_effort)\n || Boolean(body.thinking_budget)\n || body.thinking?.type === \"enabled\"\n\n // The proxy injects thinking by default, so mark true regardless\n // (the actual injection + fallback is logged in create-chat-completions)\n return { model: body.model, thinking: clientThinking || true }\n } catch {\n return {}\n }\n}\n\n/**\n * Custom logger middleware that shows model name + thinking before timestamp\n *\n * Output format:\n * [model thinking] HH:mm:ss <-- METHOD /path\n * [model thinking] HH:mm:ss --> METHOD /path STATUS DURATION\n */\nexport function modelLogger(): MiddlewareHandler {\n return async (c: Context, next: Next) => {\n const method = c.req.method\n const path = c.req.path\n const queryString =\n c.req.raw.url.includes(\"?\") ? `?${c.req.raw.url.split(\"?\")[1]}` : \"\"\n const fullPath = `${path}${queryString}`\n\n // Extract model and thinking status for POST requests with JSON body\n let model: string | undefined\n let thinking = false\n if (method === \"POST\" && c.req.header(\"content-type\")?.includes(\"json\")) {\n const info = await extractModelInfo(c)\n model = info.model\n thinking = info.thinking ?? false\n }\n\n const thinkingTag = thinking ? \" thinking\" : \"\"\n const modelPrefix = model ? `[${model}${thinkingTag}] ` : \"\"\n const startTime = getTime()\n\n // Log incoming request\n console.log(`${modelPrefix}${startTime} <-- ${method} ${fullPath}`)\n\n const start = Date.now()\n await next()\n\n const duration = Date.now() - start\n const endTime = getTime()\n\n // Log outgoing response\n console.log(\n `${modelPrefix}${endTime} --> ${method} ${fullPath} ${c.res.status} ${formatDuration(duration)}`,\n )\n }\n}\n","import consola from \"consola\"\nimport { Hono } from \"hono\"\n\nimport type { Account } from \"~/lib/account-manager\"\n\nimport { accountManager } from \"~/lib/account-manager\"\nimport {\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { rootCause } from \"~/lib/utils\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\n\nexport const accountRoutes = new Hono()\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction maskToken(token: string): string {\n if (token.length <= 8) return \"****\"\n return `${token.slice(0, 4)}...${token.slice(-4)}`\n}\n\n/**\n * Return a sanitised copy of an account safe for API responses.\n * - `githubToken` is masked.\n * - `copilotToken` is fully excluded.\n */\nfunction sanitiseAccount(account: Account) {\n const { copilotToken: _dropped, githubToken, ...rest } = account\n return {\n ...rest,\n githubToken: maskToken(githubToken),\n }\n}\n\n// ---------------------------------------------------------------------------\n// GET / — List all accounts (token masked)\n// ---------------------------------------------------------------------------\n\naccountRoutes.get(\"/\", (c) => {\n try {\n const accounts = accountManager.getAccounts().map((a) => sanitiseAccount(a))\n return c.json({ accounts })\n } catch (error) {\n consola.warn(`Error listing accounts: ${rootCause(error)}`)\n consola.debug(\"Error listing accounts:\", error)\n return c.json({ error: \"Failed to list accounts\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// POST / — Add account\n// ---------------------------------------------------------------------------\n\naccountRoutes.post(\"/\", async (c) => {\n try {\n const body = await c.req.json<{\n githubToken: string\n label: string\n accountType?: string\n }>()\n\n if (!body.githubToken || !body.label) {\n return c.json({ error: \"githubToken and label are required\" }, 400)\n }\n\n const account = await accountManager.addAccount(\n body.githubToken,\n body.label,\n body.accountType,\n )\n\n return c.json({ account: sanitiseAccount(account) }, 201)\n } catch (error) {\n consola.warn(`Error adding account: ${rootCause(error)}`)\n consola.debug(\"Error adding account:\", error)\n return c.json({ error: \"Failed to add account\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// DELETE /:id — Remove account\n// ---------------------------------------------------------------------------\n\naccountRoutes.delete(\"/:id\", async (c) => {\n try {\n const id = c.req.param(\"id\")\n const removed = await accountManager.removeAccount(id)\n\n if (!removed) {\n return c.json({ error: \"Account not found\" }, 404)\n }\n\n return c.json({ success: true })\n } catch (error) {\n consola.warn(`Error removing account: ${rootCause(error)}`)\n consola.debug(\"Error removing account:\", error)\n return c.json({ error: \"Failed to remove account\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// PUT /:id/status — Update account status (enable / disable)\n// ---------------------------------------------------------------------------\n\naccountRoutes.put(\"/:id/status\", async (c) => {\n try {\n const id = c.req.param(\"id\")\n const body = await c.req.json<{ status: string }>()\n\n if (body.status !== \"active\" && body.status !== \"disabled\") {\n return c.json({ error: 'status must be \"active\" or \"disabled\"' }, 400)\n }\n\n const account = accountManager.getAccountById(id)\n if (!account) {\n return c.json({ error: \"Account not found\" }, 404)\n }\n\n account.status = body.status\n account.statusMessage = undefined\n\n // When manually activating, also clear cooldown and failure counters\n if (body.status === \"active\") {\n account.cooldownUntil = undefined\n account.consecutiveFailures = 0\n }\n\n await accountManager.saveAccounts()\n\n return c.json({ account: sanitiseAccount(account) })\n } catch (error) {\n consola.warn(`Error updating account status: ${rootCause(error)}`)\n consola.debug(\"Error updating account status:\", error)\n return c.json({ error: \"Failed to update account status\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// POST /:id/refresh — Force refresh token + usage for one account\n// ---------------------------------------------------------------------------\n\naccountRoutes.post(\"/:id/refresh\", async (c) => {\n try {\n const id = c.req.param(\"id\")\n const account = accountManager.getAccountById(id)\n\n if (!account) {\n return c.json({ error: \"Account not found\" }, 404)\n }\n\n await accountManager.refreshAccountToken(account)\n await accountManager.refreshAccountUsage(account)\n\n return c.json({ account: sanitiseAccount(account) })\n } catch (error) {\n consola.warn(`Error refreshing account: ${rootCause(error)}`)\n consola.debug(\"Error refreshing account:\", error)\n return c.json({ error: \"Failed to refresh account\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// POST /auth/start — Initiate GitHub Device Code flow\n// ---------------------------------------------------------------------------\n\naccountRoutes.post(\"/auth/start\", async (c) => {\n try {\n const deviceCode = await getDeviceCode()\n return c.json(deviceCode)\n } catch (error) {\n consola.warn(`Error starting device code flow: ${rootCause(error)}`)\n consola.debug(\"Error starting device code flow:\", error)\n return c.json({ error: \"Failed to start device code authorization\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// POST /auth/poll — Poll for Device Code authorization completion\n// ---------------------------------------------------------------------------\n\naccountRoutes.post(\"/auth/poll\", async (c) => {\n try {\n const { device_code, label, account_type } = await c.req.json<{\n device_code: string\n label?: string\n account_type?: string\n }>()\n\n if (!device_code) {\n return c.json({ error: \"device_code is required\" }, 400)\n }\n\n // Single poll attempt to GitHub's token endpoint\n const response = await fetch(\n `${GITHUB_BASE_URL}/login/oauth/access_token`,\n {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n device_code,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n },\n )\n\n if (!response.ok) {\n return c.json({ status: \"pending\" })\n }\n\n const json = (await response.json()) as\n | { access_token: string; token_type: string; scope: string }\n | { error: string; error_description?: string }\n\n // Handle error responses from GitHub\n if (\"error\" in json) {\n switch (json.error) {\n case \"authorization_pending\": {\n return c.json({ status: \"pending\" })\n }\n case \"slow_down\": {\n return c.json({ status: \"pending\", interval: 10 })\n }\n case \"expired_token\": {\n return c.json({ status: \"expired\" })\n }\n case \"access_denied\": {\n return c.json({ status: \"denied\" })\n }\n default: {\n return c.json({\n status: \"error\",\n message: json.error_description || json.error,\n })\n }\n }\n }\n\n // Success — we have an access token\n if (\"access_token\" in json && json.access_token) {\n const accountLabel = label || `Account ${accountManager.accountCount + 1}`\n const account = await accountManager.addAccount(\n json.access_token,\n accountLabel,\n account_type || \"individual\",\n )\n return c.json({ status: \"complete\", account: sanitiseAccount(account) })\n }\n\n // Unexpected response shape\n return c.json({ status: \"pending\" })\n } catch (error) {\n consola.warn(`Error polling device code: ${rootCause(error)}`)\n consola.debug(\"Error polling device code:\", error)\n return c.json({ error: \"Failed to poll device code authorization\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// GET /usage — Aggregated usage across all accounts\n// ---------------------------------------------------------------------------\n\naccountRoutes.get(\"/usage\", (c) => {\n try {\n const accounts = accountManager.getAccounts()\n\n const aggregatedUsage = {\n premium_remaining: 0,\n premium_total: 0,\n chat_remaining: 0,\n chat_total: 0,\n }\n\n const accountSummaries = accounts.map((a) => {\n if (a.usage) {\n aggregatedUsage.premium_remaining += a.usage.premium_remaining\n aggregatedUsage.premium_total += a.usage.premium_total\n aggregatedUsage.chat_remaining += a.usage.chat_remaining\n aggregatedUsage.chat_total += a.usage.chat_total\n }\n\n return {\n id: a.id,\n label: a.label,\n status: a.status,\n usage: a.usage ?? null,\n }\n })\n\n return c.json({\n totalAccounts: accounts.length,\n activeAccounts: accounts.filter((a) => a.status === \"active\").length,\n aggregatedUsage,\n accounts: accountSummaries,\n })\n } catch (error) {\n consola.warn(`Error fetching aggregated usage: ${rootCause(error)}`)\n consola.debug(\"Error fetching aggregated usage:\", error)\n return c.json({ error: \"Failed to fetch aggregated usage\" }, 500)\n }\n})\n","import consola from \"consola\"\nimport { Hono } from \"hono\"\n\nimport { saveModelMappingConfig } from \"~/lib/config\"\nimport { modelRouter } from \"~/lib/model-router\"\nimport { state } from \"~/lib/state\"\nimport { rootCause } from \"~/lib/utils\"\n\nexport const modelAdminRoutes = new Hono()\n\n// ---------------------------------------------------------------------------\n// GET /available — List all models from Copilot\n// ---------------------------------------------------------------------------\n\nmodelAdminRoutes.get(\"/available\", (c) => {\n try {\n const models = state.models?.data ?? []\n return c.json(models)\n } catch (error) {\n consola.warn(`Error fetching available models: ${rootCause(error)}`)\n consola.debug(\"Error fetching available models:\", error)\n return c.json({ error: \"Failed to fetch available models\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// GET /mapping — Get current model mapping config\n// ---------------------------------------------------------------------------\n\nmodelAdminRoutes.get(\"/mapping\", (c) => {\n try {\n return c.json(modelRouter.getConfig())\n } catch (error) {\n consola.warn(`Error fetching model mapping: ${rootCause(error)}`)\n consola.debug(\"Error fetching model mapping:\", error)\n return c.json({ error: \"Failed to fetch model mapping\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// PUT /mapping — Update model mapping\n// ---------------------------------------------------------------------------\n\nmodelAdminRoutes.put(\"/mapping\", async (c) => {\n try {\n const body = await c.req.json<{ mapping?: Record<string, string> }>()\n\n if (!body.mapping || typeof body.mapping !== \"object\") {\n return c.json({ error: \"mapping object is required\" }, 400)\n }\n\n // Validate that all mapping values are non-empty strings\n for (const [key, value] of Object.entries(body.mapping)) {\n if (typeof value !== \"string\" || value.trim() === \"\") {\n return c.json(\n {\n error: `Invalid mapping value for \"${key}\": must be a non-empty string`,\n },\n 400,\n )\n }\n }\n\n modelRouter.updateMapping(body.mapping)\n await saveModelMappingConfig(modelRouter.getConfig())\n\n return c.json(modelRouter.getConfig())\n } catch (error) {\n consola.warn(`Error updating model mapping: ${rootCause(error)}`)\n consola.debug(\"Error updating model mapping:\", error)\n return c.json({ error: \"Failed to update model mapping\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// GET /concurrency — Get concurrency config\n// ---------------------------------------------------------------------------\n\nmodelAdminRoutes.get(\"/concurrency\", (c) => {\n try {\n return c.json({ concurrency: modelRouter.getConfig().concurrency })\n } catch (error) {\n consola.warn(`Error fetching concurrency config: ${rootCause(error)}`)\n consola.debug(\"Error fetching concurrency config:\", error)\n return c.json({ error: \"Failed to fetch concurrency config\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// PUT /concurrency — Update concurrency config\n// ---------------------------------------------------------------------------\n\nmodelAdminRoutes.put(\"/concurrency\", async (c) => {\n try {\n const body = await c.req.json<{ concurrency?: Record<string, number> }>()\n\n if (!body.concurrency || typeof body.concurrency !== \"object\") {\n return c.json({ error: \"concurrency object is required\" }, 400)\n }\n\n // Validate that all concurrency values are positive integers\n for (const [key, value] of Object.entries(body.concurrency)) {\n if (typeof value !== \"number\" || value < 1 || !Number.isInteger(value)) {\n return c.json(\n {\n error: `Invalid concurrency value for \"${key}\": must be a positive integer`,\n },\n 400,\n )\n }\n }\n\n modelRouter.updateConcurrency(body.concurrency)\n await saveModelMappingConfig(modelRouter.getConfig())\n\n return c.json({ concurrency: modelRouter.getConfig().concurrency })\n } catch (error) {\n consola.warn(`Error updating concurrency config: ${rootCause(error)}`)\n consola.debug(\"Error updating concurrency config:\", error)\n return c.json({ error: \"Failed to update concurrency config\" }, 500)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { accountManager } from \"~/lib/account-manager\"\nimport { modelRouter } from \"~/lib/model-router\"\n\nexport const statsRoute = new Hono()\n\nstatsRoute.get(\"/\", (c) => {\n return c.json({\n accounts: {\n total: accountManager.accountCount,\n active: accountManager.activeAccountCount,\n },\n models: modelRouter.getStats(),\n uptime: process.uptime(),\n })\n})\n","import { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\n\nimport { accountRoutes } from \"./accounts\"\nimport { modelAdminRoutes } from \"./models\"\nimport { statsRoute } from \"./stats\"\n\nexport const adminRoutes = new Hono()\n\nadminRoutes.route(\"/accounts\", accountRoutes)\nadminRoutes.route(\"/models\", modelAdminRoutes)\nadminRoutes.route(\"/stats\", statsRoute)\n\n// ---------------------------------------------------------------------------\n// GET /config — Export-ready config with selected models and API key\n// ---------------------------------------------------------------------------\n\nadminRoutes.get(\"/config\", (c) => {\n return c.json({\n selectedModel: state.selectedModel,\n selectedSmallModel: state.selectedSmallModel,\n apiKey: state.apiKeys?.[0] ?? \"dummy\",\n })\n})\n","import consola from \"consola\"\n\nimport { HTTPError } from \"./error\"\n\nexport const awaitApproval = async () => {\n const response = await consola.prompt(`Accept incoming request?`, {\n type: \"confirm\",\n })\n\n if (!response)\n throw new HTTPError(\n \"Request rejected\",\n Response.json({ message: \"Request rejected\" }, { status: 403 }),\n )\n}\n","import consola from \"consola\"\n\nimport type { State } from \"./state\"\n\nimport { HTTPError } from \"./error\"\nimport { sleep } from \"./utils\"\n\n/** Serialize concurrent rate-limit checks so only one request passes at a time. */\nlet rateLimitLock: Promise<void> = Promise.resolve()\n\nexport async function checkRateLimit(state: State) {\n if (state.rateLimitSeconds === undefined) return\n\n // Chain on the previous check so concurrent requests are serialized\n const previous = rateLimitLock\n let resolve!: () => void\n rateLimitLock = new Promise<void>((r) => {\n resolve = r\n })\n\n try {\n await previous\n\n const now = Date.now()\n\n if (!state.lastRequestTimestamp) {\n state.lastRequestTimestamp = now\n return\n }\n\n const elapsedSeconds = (now - state.lastRequestTimestamp) / 1000\n\n if (elapsedSeconds > state.rateLimitSeconds) {\n state.lastRequestTimestamp = now\n return\n }\n\n const waitTimeSeconds = Math.ceil(state.rateLimitSeconds - elapsedSeconds)\n\n if (!state.rateLimitWait) {\n consola.warn(\n `Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`,\n )\n throw new HTTPError(\n \"Rate limit exceeded\",\n Response.json({ message: \"Rate limit exceeded\" }, { status: 429 }),\n )\n }\n\n const waitTimeMs = waitTimeSeconds * 1000\n consola.warn(\n `Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`,\n )\n await sleep(waitTimeMs)\n // eslint-disable-next-line require-atomic-updates -- serialized by rateLimitLock\n state.lastRequestTimestamp = Date.now()\n consola.info(\"Rate limit wait completed, proceeding with request\")\n } finally {\n resolve()\n }\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport { accountManager } from \"~/lib/account-manager\"\nimport {\n copilotHeaders,\n copilotBaseUrl,\n type TokenSource,\n} from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { modelRouter } from \"~/lib/model-router\"\nimport { resetConnections } from \"~/lib/proxy\"\nimport { state } from \"~/lib/state\"\nimport { refreshCopilotToken } from \"~/lib/token\"\nimport { findModel, rootCause } from \"~/lib/utils\"\n\n// ---------------------------------------------------------------------------\n// Fetch with timeout helper\n// ---------------------------------------------------------------------------\n\n/**\n * Timeout for the initial HTTP connection + headers (not the body/stream).\n * Copilot's slow models (e.g. claude-opus) can take up to ~60s to start\n * streaming, so we give 120s for the connection phase.\n */\nconst FETCH_TIMEOUT_MS = 120_000\n\n/**\n * Retry delays in ms. After the first failure the connection pool is reset\n * (see `resetConnections`), so a single retry with a fresh socket is usually\n * enough. Keeping retries minimal avoids wasting Copilot request credits\n * (billed per request).\n */\nconst RETRY_DELAYS = [2_000]\n\n/**\n * Shorter timeout for retry attempts. The first request uses the full\n * FETCH_TIMEOUT_MS (120 s) to accommodate slow models. Retries happen\n * after a connection-pool reset, so a fresh socket should connect quickly —\n * if it doesn't respond within 20 s, the upstream is genuinely down and\n * waiting longer just burns time (and possibly credits).\n */\nconst RETRY_TIMEOUT_MS = 20_000\n\n/**\n * Wrapper around `fetch()` that aborts if the server doesn't respond within\n * `timeoutMs`. The timeout only covers the period until the response headers\n * arrive – once the body starts streaming, the timeout is cleared so that\n * long SSE responses are not interrupted.\n */\nasync function fetchWithTimeout(\n url: string,\n init: RequestInit,\n timeoutMs: number = FETCH_TIMEOUT_MS,\n): Promise<Response> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n })\n return response\n } catch (error: unknown) {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new Error(`Request timed out after ${timeoutMs}ms`)\n }\n throw error\n } finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * Retry loop for fetch: retries on network errors with exponential back-off.\n *\n * Returns `{ response }` on success.\n * Throws the last network error if all retries are exhausted.\n */\nasync function fetchWithRetry(\n url: string,\n buildInit: () => RequestInit,\n): Promise<Response> {\n let lastError: unknown\n const maxAttempts = RETRY_DELAYS.length + 1 // 1 initial + retries\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n // First attempt: full timeout (slow models may need up to 120 s).\n // Retries: short timeout — after pool reset a fresh socket should\n // connect in seconds; if it doesn't, the network is truly down.\n const timeout = attempt === 0 ? FETCH_TIMEOUT_MS : RETRY_TIMEOUT_MS\n return await fetchWithTimeout(url, buildInit(), timeout)\n } catch (error: unknown) {\n lastError = error\n\n // After the first network failure, destroy all pooled connections so\n // that retries use fresh sockets instead of hitting the same stale\n // ones (which would each wait ~60 s before timing out).\n if (attempt === 0) {\n resetConnections()\n }\n\n if (attempt < maxAttempts - 1) {\n const delay = RETRY_DELAYS[attempt]\n consola.warn(\n `Network error on attempt ${attempt + 1}/${maxAttempts}, retrying in ${delay}ms:`,\n error instanceof Error ? error.message : error,\n )\n await new Promise((r) => setTimeout(r, delay))\n }\n }\n }\n\n throw lastError instanceof Error ? lastError : (\n new Error(\"Network request failed\")\n )\n}\n\n// ---------------------------------------------------------------------------\n// Streaming slot release wrapper\n// ---------------------------------------------------------------------------\n\n/**\n * Wraps an AsyncGenerator so that `releaseSlot` is called when the generator\n * finishes (return or throw), not when the outer function returns.\n */\nasync function* wrapGeneratorWithRelease(\n gen: AsyncGenerator,\n releaseSlot: () => void,\n): AsyncGenerator {\n try {\n yield* gen\n } finally {\n releaseSlot()\n }\n}\n\n// ---------------------------------------------------------------------------\n// Reasoning-effort auto-detection cache\n// ---------------------------------------------------------------------------\n\n/**\n * Models that are known NOT to support the `reasoning_effort` parameter.\n * Populated at runtime: the first time a model returns 400 with\n * \"Unrecognized request argument\", it is added here and all future\n * requests to that model skip the injection automatically.\n */\nconst reasoningUnsupportedModels = new Set<string>()\n\n/**\n * Compute an appropriate thinking_budget from model capabilities.\n * Returns undefined if the model does not support thinking.\n */\nfunction getThinkingBudget(\n model: import(\"~/services/copilot/get-models\").Model | undefined,\n): number | undefined {\n if (!model) return undefined\n const { supports, limits } = model.capabilities\n const maxBudget = supports.max_thinking_budget\n if (!maxBudget || maxBudget <= 0) return undefined\n const maxOutput = limits.max_output_tokens ?? 0\n const upperBound = Math.min(maxBudget, Math.max(maxOutput - 1, 0))\n const lowerBound = supports.min_thinking_budget ?? 1024\n return Math.max(upperBound, lowerBound)\n}\n\n/**\n * Inject thinking parameters into the payload based on model capabilities.\n *\n * Strategy (in priority order):\n * 1. If the client already set reasoning_effort or thinking_budget → keep as-is\n * 2. If model capabilities declare max_thinking_budget → inject thinking_budget\n * 3. Otherwise → inject reasoning_effort=\"high\" (works on claude-*-4.6)\n *\n * The fallback to reasoning_effort ensures thinking works even when the\n * /models endpoint doesn't expose thinking budget fields.\n */\nfunction injectThinking(\n payload: ChatCompletionsPayload,\n resolvedModel: string,\n): ChatCompletionsPayload {\n // Client already specified thinking params — respect them\n if (payload.reasoning_effort || payload.thinking_budget) {\n return payload\n }\n\n // Try model-capability-based injection (thinking_budget)\n const model = findModel(resolvedModel)\n const budget = getThinkingBudget(model)\n if (budget) {\n return { ...payload, thinking_budget: budget }\n }\n\n // Fallback: inject reasoning_effort=\"high\" (auto-detected at runtime)\n if (!reasoningUnsupportedModels.has(resolvedModel)) {\n return { ...payload, reasoning_effort: \"high\" as const }\n }\n\n return payload\n}\n\n// ---------------------------------------------------------------------------\n// Thinking injection logging (debug level)\n// ---------------------------------------------------------------------------\n\nfunction logThinkingInjection(\n original: ChatCompletionsPayload,\n injected: ChatCompletionsPayload,\n resolvedModel: string,\n) {\n if (original.reasoning_effort || original.thinking_budget) {\n consola.debug(\n `Thinking: client-specified (reasoning_effort=${original.reasoning_effort ?? \"none\"} / thinking_budget=${original.thinking_budget ?? \"none\"})`,\n )\n } else if (\n injected.thinking_budget\n && injected.thinking_budget !== original.thinking_budget\n ) {\n consola.debug(\n `Thinking: injected thinking_budget=${injected.thinking_budget} for \"${resolvedModel}\"`,\n )\n } else if (injected.reasoning_effort === \"high\") {\n consola.debug(\n `Thinking: injected reasoning_effort=high for \"${resolvedModel}\"`,\n )\n } else if (reasoningUnsupportedModels.has(resolvedModel)) {\n consola.debug(\n `Thinking: skipped — \"${resolvedModel}\" does not support reasoning`,\n )\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public entry point\n// ---------------------------------------------------------------------------\n\nexport const createChatCompletions = async (\n payload: ChatCompletionsPayload,\n) => {\n // Apply model routing\n const resolvedModel = modelRouter.resolveModel(payload.model)\n const routedPayload =\n resolvedModel !== payload.model ?\n { ...payload, model: resolvedModel }\n : payload\n if (resolvedModel !== payload.model) {\n consola.debug(`Model routed: ${payload.model} → ${resolvedModel}`)\n }\n\n // ---------------------------------------------------------------------------\n // Thinking injection: use model capabilities to decide strategy\n // ---------------------------------------------------------------------------\n const thinkingPayload = injectThinking(routedPayload, resolvedModel)\n const wasInjected =\n thinkingPayload.reasoning_effort !== routedPayload.reasoning_effort\n || thinkingPayload.thinking_budget !== routedPayload.thinking_budget\n\n logThinkingInjection(routedPayload, thinkingPayload, resolvedModel)\n\n // Acquire concurrency slot\n const releaseSlot = await modelRouter.acquireSlot(resolvedModel)\n\n try {\n const result = await dispatchRequest(thinkingPayload)\n\n // For streaming responses, wrap the generator so the slot is released\n // when the stream ends (not when this function returns).\n if (Symbol.asyncIterator in result) {\n return wrapGeneratorWithRelease(result, releaseSlot)\n }\n\n // Non-streaming: release immediately\n releaseSlot()\n return result\n } catch (error) {\n // Auto-detect models that don't support reasoning_effort:\n // On 400 \"Unrecognized request argument\", strip the parameter and retry.\n const isReasoningRejected =\n wasInjected\n && error instanceof HTTPError\n && error.response.status === 400\n && error.message.includes(\"Unrecognized request argument\")\n\n if (isReasoningRejected) {\n reasoningUnsupportedModels.add(resolvedModel)\n consola.info(\n `Model \"${resolvedModel}\" does not support reasoning_effort — disabled for future requests`,\n )\n return retryWithoutReasoning(routedPayload, releaseSlot)\n }\n\n releaseSlot()\n throw error\n }\n}\n\n/**\n * Retry a request without reasoning_effort after the model rejected it.\n * Handles slot release for both streaming and non-streaming responses.\n */\nasync function retryWithoutReasoning(\n payload: ChatCompletionsPayload,\n releaseSlot: () => void,\n) {\n try {\n const result = await dispatchRequest(payload)\n if (Symbol.asyncIterator in result) {\n return wrapGeneratorWithRelease(result, releaseSlot)\n }\n releaseSlot()\n return result\n } catch (retryError) {\n releaseSlot()\n throw retryError\n }\n}\n\n/**\n * Dispatch request to either single-account or multi-account path.\n */\nfunction dispatchRequest(payload: ChatCompletionsPayload) {\n return state.multiAccountEnabled && accountManager.hasAccounts() ?\n createWithMultiAccount(payload)\n : createWithSingleAccount(payload)\n}\n\n// ---------------------------------------------------------------------------\n// Single-account path (original behaviour, unchanged)\n// ---------------------------------------------------------------------------\n\nasync function createWithSingleAccount(payload: ChatCompletionsPayload) {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const enableVision = payload.messages.some(\n (x) =>\n typeof x.content !== \"string\"\n && x.content?.some((x) => x.type === \"image_url\"),\n )\n\n // Agent/user check for X-Initiator header\n // Determine if any message is from an agent (\"assistant\" or \"tool\")\n const isAgentCall = payload.messages.some((msg) =>\n [\"assistant\", \"tool\"].includes(msg.role),\n )\n\n // Build headers fresh each call (token may be refreshed between attempts)\n const buildHeaders = (): Record<string, string> => ({\n ...copilotHeaders(state, enableVision),\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n })\n\n consola.debug(\"Sending request to Copilot:\", {\n model: payload.model,\n endpoint: `${copilotBaseUrl(state)}/chat/completions`,\n })\n\n const url = `${copilotBaseUrl(state)}/chat/completions`\n\n // Request usage stats in the final stream chunk\n const body =\n payload.stream ?\n { ...payload, stream_options: { include_usage: true } }\n : payload\n\n const bodyString = JSON.stringify(body)\n\n // Fetch with timeout + exponential back-off retries\n let response = await fetchWithRetry(url, () => ({\n method: \"POST\",\n headers: buildHeaders(),\n body: bodyString,\n }))\n\n // On 401 (token expired), refresh the Copilot token and retry once\n if (response.status === 401) {\n consola.warn(\"Copilot token expired, refreshing and retrying...\")\n try {\n await refreshCopilotToken()\n response = await fetchWithTimeout(url, {\n method: \"POST\",\n headers: buildHeaders(),\n body: bodyString,\n })\n } catch (refreshError) {\n consola.warn(`Failed to refresh token: ${rootCause(refreshError)}`)\n consola.debug(\"Failed to refresh token:\", refreshError)\n // Fall through to the error handling below\n }\n }\n\n if (!response.ok) {\n const errorBody = await response.text()\n\n if (response.status === 400) {\n consola.warn(`400: ${errorBody}`)\n } else {\n consola.error(\"Failed to create chat completions\", {\n status: response.status,\n statusText: response.statusText,\n body: errorBody,\n })\n }\n\n throw new HTTPError(\n `Failed to create chat completions: ${response.status} ${errorBody}`,\n response,\n )\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n}\n\n// ---------------------------------------------------------------------------\n// Multi-account path (failover across accounts)\n// ---------------------------------------------------------------------------\n\n/**\n * Attempt to refresh an account's token and retry the request.\n * Returns the result on success, or null if the refresh/retry failed.\n */\nasync function tryRefreshAndRetry(\n account: import(\"~/lib/account-manager\").Account,\n payload: ChatCompletionsPayload,\n tokenSource: TokenSource,\n): Promise<AsyncGenerator | ChatCompletionResponse | null> {\n try {\n await accountManager.refreshAccountToken(account)\n // Update tokenSource with the refreshed token\n tokenSource.copilotToken = account.copilotToken\n const result = await doFetch(payload, tokenSource)\n accountManager.markAccountSuccess(account.id)\n return result\n } catch {\n accountManager.markAccountStatus(\n account.id,\n \"error\",\n \"Token refresh failed\",\n )\n return null\n }\n}\n\n/**\n * Handle an HTTP error from a multi-account request attempt.\n *\n * For 401 errors, attempts token refresh and retry.\n * Returns the successful retry result, or null if the error was handled\n * without a successful retry.\n */\nasync function handleMultiAccountHttpError(\n error: HTTPError,\n account: import(\"~/lib/account-manager\").Account,\n retryContext: { payload: ChatCompletionsPayload; tokenSource: TokenSource },\n): Promise<AsyncGenerator | ChatCompletionResponse | null> {\n switch (error.response.status) {\n case 401: {\n consola.warn(`Account ${account.label}: 401, refreshing token...`)\n return tryRefreshAndRetry(\n account,\n retryContext.payload,\n retryContext.tokenSource,\n )\n }\n case 403: {\n accountManager.markAccountStatus(account.id, \"banned\", \"403 Forbidden\")\n return null\n }\n case 429: {\n accountManager.markAccountStatus(\n account.id,\n \"rate_limited\",\n \"429 Rate limited\",\n )\n return null\n }\n default: {\n // 5xx: upstream error — don't retry to avoid wasting request credits.\n // doFetch already retried once via fetchWithRetry; a second round\n // is unlikely to help and doubles the credit cost.\n if (error.response.status >= 500) {\n accountManager.markAccountStatus(\n account.id,\n \"error\",\n `HTTP ${error.response.status}`,\n )\n return null\n }\n accountManager.markAccountStatus(\n account.id,\n \"error\",\n `HTTP ${error.response.status}`,\n )\n return null\n }\n }\n}\n\nasync function createWithMultiAccount(payload: ChatCompletionsPayload) {\n const triedAccountIds = new Set<string>()\n let lastError: unknown\n\n // Try up to 3 different accounts\n for (let attempt = 0; attempt < 3; attempt++) {\n const account = accountManager.getActiveAccount()\n if (!account || triedAccountIds.has(account.id)) {\n // No more untried accounts available\n break\n }\n triedAccountIds.add(account.id)\n\n if (!account.copilotToken) {\n // Token may be missing after restart — try to refresh before giving up\n consola.info(\n `Account ${account.label} has no copilot token, refreshing...`,\n )\n await accountManager.refreshAccountToken(account)\n\n if (!account.copilotToken) {\n consola.warn(`Account ${account.label}: token refresh failed, skipping`)\n accountManager.markAccountStatus(\n account.id,\n \"error\",\n \"No copilot token\",\n )\n continue\n }\n }\n\n // Build a TokenSource from the account\n const tokenSource: TokenSource = {\n copilotToken: account.copilotToken,\n copilotApiEndpoint: account.copilotApiEndpoint,\n accountType: account.accountType,\n githubToken: account.githubToken,\n vsCodeVersion: state.vsCodeVersion,\n }\n\n try {\n const result = await doFetch(payload, tokenSource)\n accountManager.markAccountSuccess(account.id)\n return result\n } catch (error) {\n lastError = error\n\n if (error instanceof HTTPError) {\n const retryResult = await handleMultiAccountHttpError(error, account, {\n payload,\n tokenSource,\n })\n if (retryResult) return retryResult\n } else {\n // Network error or other\n accountManager.markAccountStatus(\n account.id,\n \"error\",\n (error as Error).message,\n )\n }\n\n consola.warn(\n `Account ${account.label} failed (attempt ${attempt + 1}), trying next...`,\n )\n }\n }\n\n // All accounts exhausted\n if (lastError)\n throw lastError instanceof Error ? lastError : (\n new Error(\"Network request failed\")\n )\n throw new Error(\"No available accounts\")\n}\n\n// ---------------------------------------------------------------------------\n// Shared fetch helper (used by multi-account path)\n// ---------------------------------------------------------------------------\n\n/**\n * Execute the actual HTTP request to the Copilot chat/completions endpoint.\n *\n * This is intentionally a thin wrapper so that `createWithMultiAccount` can\n * call it with different `TokenSource` objects while keeping all the header\n * construction / retry / error‐surfacing logic in one place.\n */\nasync function doFetch(\n payload: ChatCompletionsPayload,\n source: TokenSource,\n): Promise<AsyncGenerator | ChatCompletionResponse> {\n const enableVision = payload.messages.some(\n (x) =>\n typeof x.content !== \"string\"\n && x.content?.some((x) => x.type === \"image_url\"),\n )\n\n const isAgentCall = payload.messages.some((msg) =>\n [\"assistant\", \"tool\"].includes(msg.role),\n )\n\n const buildHeaders = (): Record<string, string> => ({\n ...copilotHeaders(source, enableVision),\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n })\n\n const url = `${copilotBaseUrl(source)}/chat/completions`\n\n consola.debug(\"Sending request to Copilot (multi-account):\", {\n model: payload.model,\n endpoint: url,\n })\n\n const body =\n payload.stream ?\n { ...payload, stream_options: { include_usage: true } }\n : payload\n\n const bodyString = JSON.stringify(body)\n\n // Fetch with timeout + exponential back-off retries\n const response = await fetchWithRetry(url, () => ({\n method: \"POST\",\n headers: buildHeaders(),\n body: bodyString,\n }))\n\n if (!response.ok) {\n const errorBody = await response.text()\n\n if (response.status === 400) {\n consola.warn(`400: ${errorBody}`)\n } else {\n consola.error(\"Failed to create chat completions\", {\n status: response.status,\n statusText: response.statusText,\n body: errorBody,\n })\n }\n\n throw new HTTPError(\n `Failed to create chat completions: ${response.status} ${errorBody}`,\n response,\n )\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n}\n\n// ===========================================================================\n// Types (unchanged)\n// ===========================================================================\n\n// Streaming types\n\nexport interface ChatCompletionChunk {\n id: string\n object: \"chat.completion.chunk\"\n created: number\n model: string\n choices: Array<Choice>\n system_fingerprint?: string\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n prompt_tokens_details?: {\n cached_tokens: number\n }\n completion_tokens_details?: {\n accepted_prediction_tokens: number\n rejected_prediction_tokens: number\n }\n }\n}\n\ninterface Delta {\n content?: string | null\n reasoning_content?: string | null\n reasoning_text?: string | null\n role?: \"user\" | \"assistant\" | \"system\" | \"tool\"\n tool_calls?: Array<{\n index: number\n id?: string\n type?: \"function\"\n function?: {\n name?: string\n arguments?: string\n }\n }>\n}\n\ninterface Choice {\n index: number\n delta: Delta\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null\n logprobs: object | null\n}\n\n// Non-streaming types\n\nexport interface ChatCompletionResponse {\n id: string\n object: \"chat.completion\"\n created: number\n model: string\n choices: Array<ChoiceNonStreaming>\n system_fingerprint?: string\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n prompt_tokens_details?: {\n cached_tokens: number\n }\n }\n}\n\ninterface ResponseMessage {\n role: \"assistant\"\n content: string | null\n reasoning_content?: string | null\n reasoning_text?: string | null\n tool_calls?: Array<ToolCall>\n}\n\ninterface ChoiceNonStreaming {\n index: number\n message: ResponseMessage\n logprobs: object | null\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\"\n}\n\n// Payload types\n\nexport interface ChatCompletionsPayload {\n messages: Array<Message>\n model: string\n temperature?: number | null\n top_p?: number | null\n max_tokens?: number | null\n stop?: string | Array<string> | null\n n?: number | null\n stream?: boolean | null\n\n frequency_penalty?: number | null\n presence_penalty?: number | null\n logit_bias?: Record<string, number> | null\n logprobs?: boolean | null\n response_format?: { type: \"json_object\" } | null\n seed?: number | null\n tools?: Array<Tool> | null\n tool_choice?:\n | \"none\"\n | \"auto\"\n | \"required\"\n | { type: \"function\"; function: { name: string } }\n | null\n user?: string | null\n\n // Anthropic thinking parameter — passed through transparently to Copilot\n thinking?: {\n type: \"enabled\"\n budget_tokens?: number\n }\n\n // OpenAI reasoning_effort parameter — triggers Copilot thinking mode\n reasoning_effort?: \"low\" | \"medium\" | \"high\" | null\n\n // Copilot thinking budget — number of tokens allocated for thinking\n thinking_budget?: number | null\n}\n\nexport interface Tool {\n type: \"function\"\n function: {\n name: string\n description?: string\n parameters: Record<string, unknown>\n }\n}\n\nexport interface Message {\n role: \"user\" | \"assistant\" | \"system\" | \"tool\" | \"developer\"\n content: string | Array<ContentPart> | null\n\n name?: string\n tool_calls?: Array<ToolCall>\n tool_call_id?: string\n}\n\nexport interface ToolCall {\n id: string\n type: \"function\"\n function: {\n name: string\n arguments: string\n }\n}\n\nexport type ContentPart = TextPart | ImagePart\n\nexport interface TextPart {\n type: \"text\"\n text: string\n}\n\nexport interface ImagePart {\n type: \"image_url\"\n image_url: {\n url: string\n detail?: \"low\" | \"high\" | \"auto\"\n }\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\nimport { streamSSE, type SSEMessage } from \"hono/streaming\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { state } from \"~/lib/state\"\nimport { findModel, isNullish } from \"~/lib/utils\"\nimport {\n createChatCompletions,\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n} from \"~/services/copilot/create-chat-completions\"\n\n/**\n * Set max_tokens from model limits if not already provided in the payload.\n */\nfunction applyMaxTokens(\n payload: ChatCompletionsPayload,\n): ChatCompletionsPayload {\n if (!isNullish(payload.max_tokens)) {\n return payload\n }\n\n const selectedModel = findModel(payload.model)\n if (!selectedModel) {\n return payload\n }\n\n const maxTokens = selectedModel.capabilities.limits.max_output_tokens\n if (maxTokens) {\n consola.debug(\"Set max_tokens to:\", maxTokens)\n return { ...payload, max_tokens: maxTokens }\n }\n\n return payload\n}\n\nexport async function handleCompletion(c: Context) {\n await checkRateLimit(state)\n\n const rawPayload = await c.req.json<ChatCompletionsPayload>()\n consola.debug(\"Request payload:\", JSON.stringify(rawPayload).slice(-400))\n\n const payload = applyMaxTokens(rawPayload)\n\n if (state.manualApprove) await awaitApproval()\n\n const response = await createChatCompletions(payload)\n\n if (isNonStreaming(response)) {\n // Map reasoning_text to reasoning_content for OpenAI-compatible clients\n const mappedResponse = mapReasoningFields(response)\n consola.debug(\"Non-streaming response:\", JSON.stringify(mappedResponse))\n return c.json(mappedResponse)\n }\n\n consola.debug(\"Streaming response\")\n return streamSSE(c, async (stream) => {\n try {\n for await (const chunk of response) {\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\n await stream.writeSSE(chunk as SSEMessage)\n }\n } catch (error) {\n const message = (error as Error).message || String(error)\n consola.warn(`SSE stream interrupted: ${message}`)\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n\n/**\n * Map `reasoning_text` (Copilot-specific) to `reasoning_content` (OpenAI-compatible)\n * so that downstream OpenAI-compatible clients can consume the reasoning output.\n */\nfunction mapReasoningFields(\n response: ChatCompletionResponse,\n): ChatCompletionResponse {\n const hasReasoningText = response.choices.some(\n (c) => (c.message as Record<string, unknown>).reasoning_text,\n )\n if (!hasReasoningText) return response\n\n return {\n ...response,\n choices: response.choices.map((choice) => {\n const msg = choice.message as Record<string, unknown>\n if (!msg.reasoning_text) return choice\n return {\n ...choice,\n message: {\n ...choice.message,\n reasoning_content:\n (msg.reasoning_text as string) || choice.message.reasoning_content,\n },\n }\n }),\n }\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCompletion } from \"./handler\"\n\nexport const completionRoutes = new Hono()\n\ncompletionRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { accountManager } from \"~/lib/account-manager\"\nimport {\n copilotHeaders,\n copilotBaseUrl,\n type TokenSource,\n} from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const createEmbeddings = async (payload: EmbeddingRequest) => {\n // In multi-account mode, use the active account's token\n let source: TokenSource = state\n if (state.multiAccountEnabled && accountManager.hasAccounts()) {\n const account = accountManager.getActiveAccount()\n if (account?.copilotToken) {\n source = {\n copilotToken: account.copilotToken,\n copilotApiEndpoint: account.copilotApiEndpoint,\n accountType: account.accountType,\n githubToken: account.githubToken,\n vsCodeVersion: state.vsCodeVersion,\n }\n }\n }\n\n if (!source.copilotToken) throw new Error(\"Copilot token not found\")\n\n const response = await fetch(`${copilotBaseUrl(source)}/embeddings`, {\n method: \"POST\",\n headers: copilotHeaders(source),\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to create embeddings\", response)\n\n return (await response.json()) as EmbeddingResponse\n}\n\nexport interface EmbeddingRequest {\n input: string | Array<string>\n model: string\n}\n\nexport interface Embedding {\n object: string\n embedding: Array<number>\n index: number\n}\n\nexport interface EmbeddingResponse {\n object: string\n data: Array<Embedding>\n model: string\n usage: {\n prompt_tokens: number\n total_tokens: number\n }\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport {\n createEmbeddings,\n type EmbeddingRequest,\n} from \"~/services/copilot/create-embeddings\"\n\nexport const embeddingRoutes = new Hono()\n\nembeddingRoutes.post(\"/\", async (c) => {\n try {\n const paylod = await c.req.json<EmbeddingRequest>()\n const response = await createEmbeddings(paylod)\n\n return c.json(response)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import type {\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\nimport type { Model } from \"~/services/copilot/get-models\"\n\n// Encoder type mapping\nconst ENCODING_MAP = {\n o200k_base: () => import(\"gpt-tokenizer/encoding/o200k_base\"),\n cl100k_base: () => import(\"gpt-tokenizer/encoding/cl100k_base\"),\n p50k_base: () => import(\"gpt-tokenizer/encoding/p50k_base\"),\n p50k_edit: () => import(\"gpt-tokenizer/encoding/p50k_edit\"),\n r50k_base: () => import(\"gpt-tokenizer/encoding/r50k_base\"),\n} as const\n\ntype SupportedEncoding = keyof typeof ENCODING_MAP\n\n// Define encoder interface\ninterface Encoder {\n encode: (text: string) => Array<number>\n}\n\n// Cache loaded encoders to avoid repeated imports\nconst encodingCache = new Map<string, Encoder>()\n\n/**\n * Calculate tokens for tool calls\n */\nconst calculateToolCallsTokens = (\n toolCalls: Array<ToolCall>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = 0\n for (const toolCall of toolCalls) {\n tokens += constants.funcInit\n tokens += encoder.encode(JSON.stringify(toolCall)).length\n }\n tokens += constants.funcEnd\n return tokens\n}\n\n/**\n * Calculate tokens for content parts\n */\nconst calculateContentPartsTokens = (\n contentParts: Array<ContentPart>,\n encoder: Encoder,\n): number => {\n let tokens = 0\n for (const part of contentParts) {\n if (part.type === \"image_url\") {\n tokens += encoder.encode(part.image_url.url).length + 85\n } else if (part.text) {\n tokens += encoder.encode(part.text).length\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens for a single message\n */\nconst calculateMessageTokens = (\n message: Message,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n const tokensPerMessage = 3\n const tokensPerName = 1\n let tokens = tokensPerMessage\n for (const [key, value] of Object.entries(message)) {\n if (typeof value === \"string\") {\n tokens += encoder.encode(value).length\n }\n if (key === \"name\") {\n tokens += tokensPerName\n }\n if (key === \"tool_calls\") {\n tokens += calculateToolCallsTokens(\n value as Array<ToolCall>,\n encoder,\n constants,\n )\n }\n if (key === \"content\" && Array.isArray(value)) {\n tokens += calculateContentPartsTokens(\n value as Array<ContentPart>,\n encoder,\n )\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens using custom algorithm\n */\nconst calculateTokens = (\n messages: Array<Message>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (messages.length === 0) {\n return 0\n }\n let numTokens = 0\n for (const message of messages) {\n numTokens += calculateMessageTokens(message, encoder, constants)\n }\n // every reply is primed with <|start|>assistant<|message|>\n numTokens += 3\n return numTokens\n}\n\n/**\n * Get the corresponding encoder module based on encoding type\n */\nconst getEncodeChatFunction = async (encoding: string): Promise<Encoder> => {\n if (encodingCache.has(encoding)) {\n const cached = encodingCache.get(encoding)\n if (cached) {\n return cached\n }\n }\n\n const supportedEncoding = encoding as SupportedEncoding\n if (!(supportedEncoding in ENCODING_MAP)) {\n const fallbackModule = (await ENCODING_MAP.o200k_base()) as Encoder\n encodingCache.set(encoding, fallbackModule)\n return fallbackModule\n }\n\n const encodingModule = (await ENCODING_MAP[supportedEncoding]()) as Encoder\n encodingCache.set(encoding, encodingModule)\n return encodingModule\n}\n\n/**\n * Get tokenizer type from model information\n */\nexport const getTokenizerFromModel = (model: Model): string => {\n return model.capabilities.tokenizer || \"o200k_base\"\n}\n\n/**\n * Get model-specific constants for token calculation\n */\nconst getModelConstants = (model: Model) => {\n return model.id === \"gpt-3.5-turbo\" || model.id === \"gpt-4\" ?\n {\n funcInit: 10,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n : {\n funcInit: 7,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n}\n\n/**\n * Calculate tokens for a single parameter\n */\nconst calculateParameterTokens = (\n key: string,\n prop: unknown,\n context: {\n encoder: Encoder\n constants: ReturnType<typeof getModelConstants>\n },\n): number => {\n const { encoder, constants } = context\n let tokens = constants.propKey\n\n // Early return if prop is not an object\n if (typeof prop !== \"object\" || prop === null) {\n return tokens\n }\n\n // Type assertion for parameter properties\n const param = prop as {\n type?: string\n description?: string\n enum?: Array<unknown>\n [key: string]: unknown\n }\n\n const paramName = key\n const paramType = param.type || \"string\"\n let paramDesc = param.description || \"\"\n\n // Handle enum values\n if (param.enum && Array.isArray(param.enum)) {\n tokens += constants.enumInit\n for (const item of param.enum) {\n tokens += constants.enumItem\n tokens += encoder.encode(String(item)).length\n }\n }\n\n // Clean up description\n if (paramDesc.endsWith(\".\")) {\n paramDesc = paramDesc.slice(0, -1)\n }\n\n // Encode the main parameter line\n const line = `${paramName}:${paramType}:${paramDesc}`\n tokens += encoder.encode(line).length\n\n // Handle additional properties (excluding standard ones)\n const excludedKeys = new Set([\"type\", \"description\", \"enum\"])\n for (const propertyName of Object.keys(param)) {\n if (!excludedKeys.has(propertyName)) {\n const propertyValue = param[propertyName]\n const propertyText =\n typeof propertyValue === \"string\" ? propertyValue : (\n JSON.stringify(propertyValue)\n )\n tokens += encoder.encode(`${propertyName}:${propertyText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for function parameters\n */\nconst calculateParametersTokens = (\n parameters: unknown,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (!parameters || typeof parameters !== \"object\") {\n return 0\n }\n\n const params = parameters as Record<string, unknown>\n let tokens = 0\n\n for (const [key, value] of Object.entries(params)) {\n if (key === \"properties\") {\n const properties = value as Record<string, unknown>\n if (Object.keys(properties).length > 0) {\n tokens += constants.propInit\n for (const propKey of Object.keys(properties)) {\n tokens += calculateParameterTokens(propKey, properties[propKey], {\n encoder,\n constants,\n })\n }\n }\n } else {\n const paramText =\n typeof value === \"string\" ? value : JSON.stringify(value)\n tokens += encoder.encode(`${key}:${paramText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for a single tool\n */\nconst calculateToolTokens = (\n tool: Tool,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = constants.funcInit\n const func = tool.function\n const fName = func.name\n let fDesc = func.description || \"\"\n if (fDesc.endsWith(\".\")) {\n fDesc = fDesc.slice(0, -1)\n }\n const line = fName + \":\" + fDesc\n tokens += encoder.encode(line).length\n if (\n typeof func.parameters === \"object\" // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n && func.parameters !== null\n ) {\n tokens += calculateParametersTokens(func.parameters, encoder, constants)\n }\n return tokens\n}\n\n/**\n * Calculate token count for tools based on model\n */\nexport const numTokensForTools = (\n tools: Array<Tool>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let funcTokenCount = 0\n for (const tool of tools) {\n funcTokenCount += calculateToolTokens(tool, encoder, constants)\n }\n funcTokenCount += constants.funcEnd\n return funcTokenCount\n}\n\n/**\n * Calculate the token count of messages, supporting multiple GPT encoders\n */\nexport const getTokenCount = async (\n payload: ChatCompletionsPayload,\n model: Model,\n): Promise<{ input: number; output: number }> => {\n // Get tokenizer string\n const tokenizer = getTokenizerFromModel(model)\n\n // Get corresponding encoder module\n const encoder = await getEncodeChatFunction(tokenizer)\n\n const constants = getModelConstants(model)\n\n // All messages in the payload are prompt tokens (the full conversation context).\n // \"Output\" tokens are only the NEW response from the model, not historical assistant turns.\n let inputTokens = calculateTokens(payload.messages, encoder, constants)\n if (payload.tools && payload.tools.length > 0) {\n inputTokens += numTokensForTools(payload.tools, encoder, constants)\n }\n\n return {\n input: inputTokens,\n output: 0,\n }\n}\n","import { type AnthropicResponse } from \"./anthropic-types\"\n\nexport function mapOpenAIStopReasonToAnthropic(\n finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null,\n): AnthropicResponse[\"stop_reason\"] {\n if (finishReason === null) {\n return null\n }\n const stopReasonMap = {\n stop: \"end_turn\",\n length: \"max_tokens\",\n tool_calls: \"tool_use\",\n content_filter: \"end_turn\",\n } as const\n return stopReasonMap[finishReason]\n}\n","import { state } from \"~/lib/state\"\nimport {\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n type ContentPart,\n type Message,\n type TextPart,\n type Tool,\n type ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicAssistantContentBlock,\n type AnthropicAssistantMessage,\n type AnthropicMessage,\n type AnthropicMessagesPayload,\n type AnthropicResponse,\n type AnthropicTextBlock,\n type AnthropicThinkingBlock,\n type AnthropicTool,\n type AnthropicToolResultBlock,\n type AnthropicToolUseBlock,\n type AnthropicUserContentBlock,\n type AnthropicUserMessage,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\n// Payload translation\n\nexport function translateToOpenAI(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload {\n return {\n model: translateModelName(payload.model),\n messages: translateAnthropicMessagesToOpenAI(\n payload.messages,\n payload.system,\n ),\n max_tokens: payload.max_tokens,\n stop: payload.stop_sequences,\n stream: payload.stream,\n temperature: payload.temperature,\n top_p: payload.top_p,\n user: payload.metadata?.user_id,\n tools: translateAnthropicToolsToOpenAI(payload.tools),\n tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),\n // Pass through thinking parameter as-is to Copilot\n ...(payload.thinking && { thinking: payload.thinking }),\n // Convert Anthropic thinking to reasoning_effort=high for Copilot\n ...(payload.thinking?.type === \"enabled\" && {\n reasoning_effort: \"high\" as const,\n }),\n // Convert Anthropic thinking budget_tokens to Copilot thinking_budget\n ...(payload.thinking?.budget_tokens && {\n thinking_budget: payload.thinking.budget_tokens,\n }),\n }\n}\n\nexport function translateModelName(model: string): string {\n // Claude Code 发送的模型名称可能与 GitHub Copilot 支持的不一致\n // 需要智能匹配到 Copilot 实际支持的模型\n\n const supportedModels = state.models?.data.map((m) => m.id) ?? []\n\n // 1. 直接匹配\n if (supportedModels.includes(model)) {\n return model\n }\n\n // 2. 移除日期后缀后匹配 (claude-opus-4-5-20251101 -> claude-opus-4-5)\n const modelBase = model.replace(/-\\d{8}$/, \"\")\n if (supportedModels.includes(modelBase)) {\n return modelBase\n }\n\n // 3. 尝试 4-5 -> 4.5 格式转换 (claude-opus-4-5 -> claude-opus-4.5)\n const modelWithDot = modelBase.replace(/-(\\d+)-(\\d+)$/, \"-$1.$2\")\n if (supportedModels.includes(modelWithDot)) {\n return modelWithDot\n }\n\n // 4. 尝试 4.5 -> 4-5 格式转换 (claude-opus-4.5 -> claude-opus-4-5)\n const modelWithDash = model.replace(/(\\d+)\\.(\\d+)/, \"$1-$2\")\n if (supportedModels.includes(modelWithDash)) {\n return modelWithDash\n }\n\n // 5. Anthropic 旧格式到 Copilot 新格式映射\n // claude-3-5-sonnet-xxx -> claude-sonnet-4.5\n // claude-3-opus-xxx -> claude-opus-4.5\n // claude-3-5-haiku-xxx -> claude-haiku-4.5\n const oldFormatMapping: Record<string, string> = {\n \"claude-3-5-sonnet\": \"claude-sonnet-4.5\",\n \"claude-3-sonnet\": \"claude-sonnet-4\",\n \"claude-3-5-opus\": \"claude-opus-4.5\",\n \"claude-3-opus\": \"claude-opus-4.5\",\n \"claude-3-5-haiku\": \"claude-haiku-4.5\",\n \"claude-3-haiku\": \"claude-haiku-4.5\",\n }\n\n for (const [oldFormat, newFormat] of Object.entries(oldFormatMapping)) {\n if (\n modelBase.startsWith(oldFormat)\n && supportedModels.includes(newFormat)\n ) {\n return newFormat\n }\n }\n\n // 6. 如果都找不到,返回原始模型名\n return model\n}\n\nfunction translateAnthropicMessagesToOpenAI(\n anthropicMessages: Array<AnthropicMessage>,\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n const systemMessages = handleSystemPrompt(system)\n\n const otherMessages = anthropicMessages.flatMap((message) =>\n message.role === \"user\" ?\n handleUserMessage(message)\n : handleAssistantMessage(message),\n )\n\n return [...systemMessages, ...otherMessages]\n}\n\nfunction handleSystemPrompt(\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n if (!system) {\n return []\n }\n\n if (typeof system === \"string\") {\n return [{ role: \"system\", content: system }]\n } else {\n const systemText = system.map((block) => block.text).join(\"\\n\\n\")\n return [{ role: \"system\", content: systemText }]\n }\n}\n\nfunction handleUserMessage(message: AnthropicUserMessage): Array<Message> {\n const newMessages: Array<Message> = []\n\n if (Array.isArray(message.content)) {\n const toolResultBlocks = message.content.filter(\n (block): block is AnthropicToolResultBlock =>\n block.type === \"tool_result\",\n )\n const otherBlocks = message.content.filter(\n (block) => block.type !== \"tool_result\",\n )\n\n // Tool results must come first to maintain protocol: tool_use -> tool_result -> user\n for (const block of toolResultBlocks) {\n newMessages.push({\n role: \"tool\",\n tool_call_id: block.tool_use_id,\n content: mapContent(block.content),\n })\n }\n\n if (otherBlocks.length > 0) {\n newMessages.push({\n role: \"user\",\n content: mapContent(otherBlocks),\n })\n }\n } else {\n newMessages.push({\n role: \"user\",\n content: mapContent(message.content),\n })\n }\n\n return newMessages\n}\n\nfunction handleAssistantMessage(\n message: AnthropicAssistantMessage,\n): Array<Message> {\n if (!Array.isArray(message.content)) {\n return [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n }\n\n const toolUseBlocks = message.content.filter(\n (block): block is AnthropicToolUseBlock => block.type === \"tool_use\",\n )\n\n const textBlocks = message.content.filter(\n (block): block is AnthropicTextBlock => block.type === \"text\",\n )\n\n const thinkingBlocks = message.content.filter(\n (block): block is AnthropicThinkingBlock => block.type === \"thinking\",\n )\n\n // Combine text and thinking blocks, as OpenAI doesn't have separate thinking blocks\n const allTextContent = [\n ...textBlocks.map((b) => b.text),\n ...thinkingBlocks.map((b) => b.thinking),\n ].join(\"\\n\\n\")\n\n return toolUseBlocks.length > 0 ?\n [\n {\n role: \"assistant\",\n content: allTextContent || null,\n tool_calls: toolUseBlocks.map((toolUse) => ({\n id: toolUse.id,\n type: \"function\",\n function: {\n name: toolUse.name,\n arguments: JSON.stringify(toolUse.input),\n },\n })),\n },\n ]\n : [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n}\n\nfunction mapContent(\n content:\n | string\n | Array<AnthropicUserContentBlock | AnthropicAssistantContentBlock>,\n): string | Array<ContentPart> | null {\n if (typeof content === \"string\") {\n return content\n }\n if (!Array.isArray(content)) {\n return null\n }\n\n const hasImage = content.some((block) => block.type === \"image\")\n if (!hasImage) {\n return content\n .filter(\n (block): block is AnthropicTextBlock | AnthropicThinkingBlock =>\n block.type === \"text\" || block.type === \"thinking\",\n )\n .map((block) => (block.type === \"text\" ? block.text : block.thinking))\n .join(\"\\n\\n\")\n }\n\n const contentParts: Array<ContentPart> = []\n for (const block of content) {\n switch (block.type) {\n case \"text\": {\n contentParts.push({ type: \"text\", text: block.text })\n\n break\n }\n case \"thinking\": {\n contentParts.push({ type: \"text\", text: block.thinking })\n\n break\n }\n case \"image\": {\n contentParts.push({\n type: \"image_url\",\n image_url: {\n url: `data:${block.source.media_type};base64,${block.source.data}`,\n },\n })\n\n break\n }\n // No default\n }\n }\n return contentParts\n}\n\nfunction translateAnthropicToolsToOpenAI(\n anthropicTools: Array<AnthropicTool> | undefined,\n): Array<Tool> | undefined {\n if (!anthropicTools) {\n return undefined\n }\n return anthropicTools.map((tool) => ({\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.input_schema,\n },\n }))\n}\n\nfunction translateAnthropicToolChoiceToOpenAI(\n anthropicToolChoice: AnthropicMessagesPayload[\"tool_choice\"],\n): ChatCompletionsPayload[\"tool_choice\"] {\n if (!anthropicToolChoice) {\n return undefined\n }\n\n switch (anthropicToolChoice.type) {\n case \"auto\": {\n return \"auto\"\n }\n case \"any\": {\n return \"required\"\n }\n case \"tool\": {\n if (anthropicToolChoice.name) {\n return {\n type: \"function\",\n function: { name: anthropicToolChoice.name },\n }\n }\n return undefined\n }\n case \"none\": {\n return \"none\"\n }\n default: {\n return undefined\n }\n }\n}\n\n// Response translation\n\n// eslint-disable-next-line complexity\nexport function translateToAnthropic(\n response: ChatCompletionResponse,\n): AnthropicResponse {\n // Merge content from all choices\n const allThinkingBlocks: Array<AnthropicThinkingBlock> = []\n const allTextBlocks: Array<AnthropicTextBlock> = []\n const allToolUseBlocks: Array<AnthropicToolUseBlock> = []\n let stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null =\n null // default\n stopReason = response.choices[0]?.finish_reason ?? stopReason\n\n // Process all choices to extract thinking, text and tool use blocks\n for (const choice of response.choices) {\n const thinkingBlocks = getAnthropicThinkingBlocks(\n choice.message.reasoning_content ?? choice.message.reasoning_text,\n )\n const textBlocks = getAnthropicTextBlocks(choice.message.content)\n const toolUseBlocks = getAnthropicToolUseBlocks(choice.message.tool_calls)\n\n allThinkingBlocks.push(...thinkingBlocks)\n allTextBlocks.push(...textBlocks)\n allToolUseBlocks.push(...toolUseBlocks)\n\n // Use the finish_reason from the first choice, or prioritize tool_calls\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\n stopReason = choice.finish_reason\n }\n }\n\n return {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n model: response.model,\n // Anthropic convention: thinking blocks come first, then text, then tool_use\n content: [...allThinkingBlocks, ...allTextBlocks, ...allToolUseBlocks],\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\n stop_sequence: null,\n usage: {\n input_tokens:\n (response.usage?.prompt_tokens ?? 0)\n - (response.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: response.usage?.completion_tokens ?? 0,\n ...(response.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n response.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n }\n}\n\nfunction getAnthropicThinkingBlocks(\n reasoningContent: string | null | undefined,\n): Array<AnthropicThinkingBlock> {\n if (!reasoningContent) {\n return []\n }\n return [{ type: \"thinking\", thinking: reasoningContent }]\n}\n\nfunction getAnthropicTextBlocks(\n messageContent: Message[\"content\"],\n): Array<AnthropicTextBlock> {\n if (typeof messageContent === \"string\") {\n return [{ type: \"text\", text: messageContent }]\n }\n\n if (Array.isArray(messageContent)) {\n return messageContent\n .filter((part): part is TextPart => part.type === \"text\")\n .map((part) => ({ type: \"text\", text: part.text }))\n }\n\n return []\n}\n\nfunction getAnthropicToolUseBlocks(\n toolCalls: Array<ToolCall> | undefined,\n): Array<AnthropicToolUseBlock> {\n if (!toolCalls) {\n return []\n }\n return toolCalls.map((toolCall) => ({\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: (() => {\n try {\n return JSON.parse(toolCall.function.arguments) as Record<\n string,\n unknown\n >\n } catch {\n return {}\n }\n })(),\n }))\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport { getTokenCount } from \"~/lib/tokenizer\"\nimport { findModel, rootCause } from \"~/lib/utils\"\n\nimport { type AnthropicMessagesPayload } from \"./anthropic-types\"\nimport { translateModelName, translateToOpenAI } from \"./non-stream-translation\"\n\n/**\n * Handles token counting for Anthropic messages.\n *\n * Uses multi-strategy model matching:\n * 1. findModel(translatedName) — translated Copilot name with format variants\n * 2. findModel(originalName) — original Anthropic name with format variants\n */\nexport async function handleCountTokens(c: Context) {\n try {\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n // Multi-strategy model matching:\n // Try translated name first (most likely to match Copilot model IDs),\n // then fall back to original Anthropic name with format variants\n const translatedModelName = translateModelName(anthropicPayload.model)\n const selectedModel =\n findModel(translatedModelName) ?? findModel(anthropicPayload.model)\n\n if (!selectedModel) {\n consola.warn(\n `Model not found for \"${anthropicPayload.model}\" (translated: \"${translatedModelName}\"), returning default token count`,\n )\n return c.json({\n input_tokens: 1,\n })\n }\n\n const tokenCount = await getTokenCount(openAIPayload, selectedModel)\n\n if (anthropicPayload.tools && anthropicPayload.tools.length > 0) {\n let mcpToolExist = false\n if (anthropicBeta?.startsWith(\"claude-code\")) {\n mcpToolExist = anthropicPayload.tools.some((tool) =>\n tool.name.startsWith(\"mcp__\"),\n )\n }\n if (!mcpToolExist) {\n if (anthropicPayload.model.startsWith(\"claude\")) {\n // https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview#pricing\n tokenCount.input = tokenCount.input + 346\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n tokenCount.input = tokenCount.input + 480\n }\n }\n }\n\n let finalTokenCount = tokenCount.input + tokenCount.output\n if (anthropicPayload.model.startsWith(\"claude\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.15)\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.03)\n }\n\n console.log(\"Token count:\", finalTokenCount)\n\n return c.json({\n input_tokens: finalTokenCount,\n })\n } catch (error) {\n consola.warn(`Error counting tokens: ${rootCause(error)}`)\n consola.debug(\"Error counting tokens:\", error)\n return c.json({\n input_tokens: 1,\n })\n }\n}\n","import { type ChatCompletionChunk } from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicStreamEventData,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\nfunction isToolBlockOpen(state: AnthropicStreamState): boolean {\n if (!state.contentBlockOpen) {\n return false\n }\n // Check if the current block index corresponds to any known tool call\n return Object.values(state.toolCalls).some(\n (tc) => tc.anthropicBlockIndex === state.contentBlockIndex,\n )\n}\n\n// eslint-disable-next-line max-lines-per-function, complexity\nexport function translateChunkToAnthropicEvents(\n chunk: ChatCompletionChunk,\n state: AnthropicStreamState,\n): Array<AnthropicStreamEventData> {\n const events: Array<AnthropicStreamEventData> = []\n\n if (chunk.choices.length === 0) {\n return events\n }\n\n const choice = chunk.choices[0]\n const { delta } = choice\n\n if (!state.messageStartSent) {\n events.push({\n type: \"message_start\",\n message: {\n id: chunk.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: chunk.model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens:\n (chunk.usage?.prompt_tokens ?? 0)\n - (chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: 0, // Will be updated in message_delta when finished\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n })\n state.messageStartSent = true\n }\n\n const reasoningContent = delta.reasoning_content ?? delta.reasoning_text\n if (reasoningContent) {\n // Close any non-thinking block that might be open\n if (state.contentBlockOpen && !state.thinkingBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n if (!state.thinkingBlockOpen) {\n // Start a new thinking block\n events.push({\n type: \"content_block_start\",\n index: state.contentBlockIndex,\n content_block: {\n type: \"thinking\",\n thinking: \"\",\n },\n })\n state.contentBlockOpen = true\n state.thinkingBlockOpen = true\n }\n\n events.push({\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"thinking_delta\",\n thinking: reasoningContent,\n },\n })\n }\n\n if (delta.content) {\n // Close thinking block if transitioning from thinking to text\n if (state.thinkingBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n state.thinkingBlockOpen = false\n }\n\n if (isToolBlockOpen(state)) {\n // A tool block was open, so close it before starting a text block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n if (!state.contentBlockOpen) {\n events.push({\n type: \"content_block_start\",\n index: state.contentBlockIndex,\n content_block: {\n type: \"text\",\n text: \"\",\n },\n })\n state.contentBlockOpen = true\n }\n\n events.push({\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"text_delta\",\n text: delta.content,\n },\n })\n }\n\n if (delta.tool_calls) {\n // Close thinking block if transitioning from thinking to tool calls\n if (state.thinkingBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n state.thinkingBlockOpen = false\n }\n\n for (const toolCall of delta.tool_calls) {\n if (toolCall.id && toolCall.function?.name) {\n // New tool call starting.\n if (state.contentBlockOpen) {\n // Close any previously open block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n const anthropicBlockIndex = state.contentBlockIndex\n state.toolCalls[toolCall.index] = {\n id: toolCall.id,\n name: toolCall.function.name,\n anthropicBlockIndex,\n }\n\n events.push({\n type: \"content_block_start\",\n index: anthropicBlockIndex,\n content_block: {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: {},\n },\n })\n state.contentBlockOpen = true\n }\n\n if (toolCall.function?.arguments) {\n const toolCallInfo = state.toolCalls[toolCall.index]\n // Tool call can still be empty\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (toolCallInfo) {\n events.push({\n type: \"content_block_delta\",\n index: toolCallInfo.anthropicBlockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: toolCall.function.arguments,\n },\n })\n }\n }\n }\n }\n\n if (choice.finish_reason) {\n if (state.contentBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockOpen = false\n }\n\n events.push(\n {\n type: \"message_delta\",\n delta: {\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\n stop_sequence: null,\n },\n usage: {\n input_tokens:\n (chunk.usage?.prompt_tokens ?? 0)\n - (chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: chunk.usage?.completion_tokens ?? 0,\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n {\n type: \"message_stop\",\n },\n )\n }\n\n return events\n}\n\nexport function translateErrorToAnthropicErrorEvent(): AnthropicStreamEventData {\n return {\n type: \"error\",\n error: {\n type: \"api_error\",\n message: \"An unexpected error occurred during streaming.\",\n },\n }\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\nimport { streamSSE } from \"hono/streaming\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { state } from \"~/lib/state\"\nimport {\n createChatCompletions,\n type ChatCompletionChunk,\n type ChatCompletionResponse,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicMessagesPayload,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport {\n translateToAnthropic,\n translateToOpenAI,\n} from \"./non-stream-translation\"\nimport {\n translateChunkToAnthropicEvents,\n translateErrorToAnthropicErrorEvent,\n} from \"./stream-translation\"\n\nexport async function handleCompletion(c: Context) {\n await checkRateLimit(state)\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n if (state.manualApprove) {\n await awaitApproval()\n }\n\n const response = await createChatCompletions(openAIPayload)\n\n if (isNonStreaming(response)) {\n const anthropicResponse = translateToAnthropic(response)\n return c.json(anthropicResponse)\n }\n\n return streamSSE(c, async (stream) => {\n const streamState: AnthropicStreamState = {\n messageStartSent: false,\n contentBlockIndex: 0,\n contentBlockOpen: false,\n toolCalls: {},\n thinkingBlockOpen: false,\n thinkingRequested: Boolean(anthropicPayload.thinking),\n }\n\n try {\n for await (const rawEvent of response) {\n const event = rawEvent as { data?: string }\n if (event.data === \"[DONE]\") {\n break\n }\n\n if (!event.data) {\n continue\n }\n\n let chunk: ChatCompletionChunk\n try {\n chunk = JSON.parse(event.data) as ChatCompletionChunk\n } catch {\n consola.debug(\"Skipping malformed SSE chunk\")\n continue\n }\n const events = translateChunkToAnthropicEvents(chunk, streamState)\n\n for (const event of events) {\n await stream.writeSSE({\n event: event.type,\n data: JSON.stringify(event),\n })\n }\n }\n } catch (error) {\n const message = (error as Error).message || String(error)\n consola.warn(`SSE stream interrupted: ${message}`)\n try {\n const errorEvent = translateErrorToAnthropicErrorEvent()\n await stream.writeSSE({\n event: errorEvent.type,\n data: JSON.stringify(errorEvent),\n })\n } catch {\n // Client already disconnected — nothing we can do\n }\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCountTokens } from \"./count-tokens-handler\"\nimport { handleCompletion } from \"./handler\"\n\nexport const messageRoutes = new Hono()\n\nmessageRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n return await handleCountTokens(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\nimport { cacheModels } from \"~/lib/utils\"\n\nexport const modelRoutes = new Hono()\n\nmodelRoutes.get(\"/\", async (c) => {\n try {\n if (!state.models) {\n // This should be handled by startup logic, but as a fallback.\n await cacheModels()\n }\n\n const models = state.models?.data.map((model) => ({\n id: model.id,\n object: \"model\",\n type: \"model\",\n created: 0, // No date available from source\n created_at: new Date(0).toISOString(), // No date available from source\n owned_by: model.vendor,\n display_name: model.name,\n }))\n\n return c.json({\n object: \"list\",\n data: models,\n has_more: false,\n })\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import consola from \"consola\"\nimport { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\nimport { rootCause } from \"~/lib/utils\"\n\nexport const tokenRoute = new Hono()\n\ntokenRoute.get(\"/\", (c) => {\n try {\n return c.json({\n token: state.copilotToken,\n })\n } catch (error) {\n consola.warn(`Error fetching token: ${rootCause(error)}`)\n consola.debug(\"Error fetching token:\", error)\n return c.json({ error: \"Failed to fetch token\", token: null }, 500)\n }\n})\n","import consola from \"consola\"\nimport { Hono } from \"hono\"\n\nimport { accountManager } from \"~/lib/account-manager\"\nimport { state } from \"~/lib/state\"\nimport { rootCause } from \"~/lib/utils\"\nimport { getCopilotUsage } from \"~/services/github/get-copilot-usage\"\n\nexport const usageRoute = new Hono()\n\nusageRoute.get(\"/\", async (c) => {\n try {\n // In multi-account mode, use the active account's GitHub token\n if (state.multiAccountEnabled && accountManager.hasAccounts()) {\n const account = accountManager.getActiveAccount()\n if (account) {\n const usage = await getCopilotUsage(account.githubToken)\n return c.json(usage)\n }\n }\n const usage = await getCopilotUsage()\n return c.json(usage)\n } catch (error) {\n consola.warn(`Error fetching usage: ${rootCause(error)}`)\n consola.debug(\"Error fetching usage:\", error)\n return c.json({ error: \"Failed to fetch Copilot usage\" }, 500)\n }\n})\n","import { Hono } from \"hono\"\nimport { cors } from \"hono/cors\"\n\nimport { apiKeyAuthMiddleware } from \"./lib/api-key-auth\"\nimport { modelLogger } from \"./lib/model-logger\"\nimport { adminRoutes } from \"./routes/admin/route\"\nimport { completionRoutes } from \"./routes/chat-completions/route\"\nimport { embeddingRoutes } from \"./routes/embeddings/route\"\nimport { messageRoutes } from \"./routes/messages/route\"\nimport { modelRoutes } from \"./routes/models/route\"\nimport { tokenRoute } from \"./routes/token/route\"\nimport { usageRoute } from \"./routes/usage/route\"\n\nexport const server = new Hono()\n\nserver.use(modelLogger())\nserver.use(cors())\nserver.use(apiKeyAuthMiddleware)\n\nserver.get(\"/\", (c) => c.text(\"Server running\"))\n\n// Chat completions\nserver.route(\"/chat/completions\", completionRoutes)\n\n// Models\nserver.route(\"/models\", modelRoutes)\n\nserver.route(\"/embeddings\", embeddingRoutes)\nserver.route(\"/usage\", usageRoute)\nserver.route(\"/token\", tokenRoute)\n\n// Compatibility with tools that expect v1/ prefix\nserver.route(\"/v1/chat/completions\", completionRoutes)\nserver.route(\"/v1/models\", modelRoutes)\nserver.route(\"/v1/embeddings\", embeddingRoutes)\n\n// Anthropic compatible endpoints\nserver.route(\"/v1/messages\", messageRoutes)\n\n// Admin API (Usage Viewer UI)\nserver.route(\"/api\", adminRoutes)\n","#!/usr/bin/env node\n\n// Load environment variables from .env file\nimport \"dotenv/config\"\n/* eslint-disable require-atomic-updates */\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 { accountManager } from \"./lib/account-manager\"\nimport { applyProxyConfig, getModelMappingConfig } from \"./lib/config\"\nimport { modelRouter } from \"./lib/model-router\"\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport {\n setupCopilotToken,\n setupGitHubToken,\n stopCopilotTokenRefresh,\n} from \"./lib/token\"\nimport { cacheModels, cacheVSCodeVersion } from \"./lib/utils\"\nimport { server } from \"./server\"\n\ninterface RunServerOptions {\n port: number\n verbose: boolean\n accountType: string\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n proxyEnv: boolean\n apiKeys?: Array<string>\n}\n\n/**\n * Initialize multi-account mode: load accounts from disk, optionally migrate\n * the legacy single-account, and start background token/usage refresh.\n */\nasync function initMultiAccount(): Promise<void> {\n try {\n await accountManager.loadAccounts()\n\n if (accountManager.hasAccounts()) {\n // Multi-account mode: accounts.json exists with accounts\n state.multiAccountEnabled = true\n consola.info(\n `Multi-account mode enabled with ${accountManager.accountCount} account(s)`,\n )\n\n // Stop single-account token refresh — multi-account has its own\n stopCopilotTokenRefresh()\n\n // Start background token/usage refresh\n await accountManager.startBackgroundRefresh()\n } else if (state.githubToken) {\n // No accounts in file — migrate current single account if we have a token\n try {\n const account = await accountManager.migrateFromLegacy(\n state.githubToken,\n state.accountType,\n )\n state.multiAccountEnabled = true\n consola.info(\n `Migrated current account (${account.githubLogin ?? account.label}) to multi-account mode`,\n )\n\n // Stop single-account token refresh — multi-account has its own\n stopCopilotTokenRefresh()\n\n await accountManager.startBackgroundRefresh()\n } catch (migrationError) {\n consola.warn(\n \"Could not migrate to multi-account, staying in single-account mode:\",\n migrationError,\n )\n }\n }\n } catch (error) {\n consola.debug(\"Multi-account init skipped:\", error)\n // Non-fatal — single account mode continues to work\n }\n}\n\n/**\n * Load model mapping and concurrency configuration from the config file and\n * apply it to the model router.\n */\nasync function initModelRouting(): Promise<void> {\n try {\n const modelMappingConfig = await getModelMappingConfig()\n if (modelMappingConfig) {\n if (modelMappingConfig.mapping) {\n modelRouter.updateMapping(modelMappingConfig.mapping)\n consola.info(\n `Model mapping loaded: ${Object.keys(modelMappingConfig.mapping).length} rule(s)`,\n )\n }\n if (modelMappingConfig.concurrency) {\n modelRouter.updateConcurrency(modelMappingConfig.concurrency)\n consola.info(\n `Model concurrency loaded: ${Object.keys(modelMappingConfig.concurrency).length} rule(s)`,\n )\n }\n }\n } catch (error) {\n consola.debug(\"Model routing config not loaded:\", error)\n }\n}\n\n/**\n * Interactively select models and generate a Claude Code environment script.\n */\nasync function setupClaudeCodeEnv(serverUrl: string): Promise<void> {\n const modelList = state.models?.data\n invariant(modelList, \"Models should be loaded by now\")\n\n const selectedModel = await consola.prompt(\n \"Select a model to use with Claude Code\",\n {\n type: \"select\",\n options: modelList.map((model) => model.id),\n },\n )\n\n if (typeof selectedModel === \"symbol\") {\n consola.info(\"Model selection cancelled\")\n return\n }\n\n const selectedSmallModel = await consola.prompt(\n \"Select a small model to use with Claude Code\",\n {\n type: \"select\",\n options: modelList.map((model) => model.id),\n },\n )\n\n if (typeof selectedSmallModel === \"symbol\") {\n consola.info(\"Model selection cancelled\")\n return\n }\n\n // Save selections to state for API access\n state.selectedModel = selectedModel\n state.selectedSmallModel = selectedSmallModel\n\n const command = generateEnvScript(\n {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: state.apiKeys?.[0] ?? \"dummy\",\n ANTHROPIC_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_OPUS_MODEL: selectedModel,\n ANTHROPIC_REASONING_MODEL: selectedModel,\n ANTHROPIC_SMALL_FAST_MODEL: selectedSmallModel,\n ANTHROPIC_DEFAULT_HAIKU_MODEL: selectedSmallModel,\n DISABLE_NON_ESSENTIAL_MODEL_CALLS: \"1\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\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}\nasync function validateGitHubToken(token: string): Promise<void> {\n state.githubToken = token\n consola.info(\"Using provided GitHub token\")\n try {\n const { getGitHubUser } = await import(\"~/services/github/get-user\")\n const user = await getGitHubUser()\n consola.info(`Logged in as ${user.login}`)\n } catch (error) {\n consola.error(\"Provided GitHub token is invalid\")\n throw error\n }\n}\n\n/**\n * Start and configure the Copilot API server according to the provided options.\n *\n * @param options - Server startup options:\n * - port: Port number to listen on\n * - verbose: Enable verbose logging\n * - accountType: Account plan to use (\"individual\", \"business\", \"enterprise\")\n * - manual: Require manual approval for requests\n * - rateLimit: Seconds to wait between requests (optional)\n * - rateLimitWait: Wait instead of erroring when rate limit is hit\n * - githubToken: GitHub token to use (optional; if omitted a token setup prompt may run)\n * - claudeCode: Generate a Claude Code environment launch command\n * - showToken: Expose GitHub/Copilot tokens in responses for debugging\n * - proxyEnv: Initialize proxy settings from environment variables\n * - apiKeys: Optional list of API keys to enable API key authentication\n */\nexport async function runServer(options: RunServerOptions): Promise<void> {\n // Apply saved proxy configuration first (if any)\n const savedProxyApplied = await applyProxyConfig()\n\n // Then apply --proxy-env if specified (overrides saved config)\n if (options.proxyEnv) {\n initProxyFromEnv()\n } else if (savedProxyApplied) {\n // If saved proxy was applied, initialize the proxy dispatcher\n initProxyFromEnv()\n }\n\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 state.apiKeys = options.apiKeys\n\n if (state.apiKeys && state.apiKeys.length > 0) {\n consola.info(\n `API key authentication enabled with ${state.apiKeys.length} key(s)`,\n )\n }\n\n await ensurePaths()\n\n // Standard Copilot mode\n await cacheVSCodeVersion()\n\n await (options.githubToken ?\n validateGitHubToken(options.githubToken)\n : setupGitHubToken())\n\n try {\n await setupCopilotToken()\n } catch (error) {\n // If getting Copilot token fails with 401, the GitHub token might be invalid\n const { HTTPError } = await import(\"~/lib/error\")\n if (error instanceof HTTPError && error.response.status === 401) {\n consola.error(\n \"Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked\",\n )\n const { clearGithubToken } = await import(\"~/lib/token\")\n await clearGithubToken()\n consola.info(\"Please restart to re-authenticate\")\n }\n throw error\n }\n\n await cacheModels()\n\n // Initialize multi-account mode\n await initMultiAccount()\n\n // Initialize model routing from config\n await initModelRouting()\n\n consola.info(\n `Available models: \\n${state.models?.data.map((model) => `- ${model.id}`).join(\"\\n\")}`,\n )\n\n const serverUrl = `http://localhost:${options.port}`\n\n if (options.claudeCode) {\n await setupClaudeCodeEnv(serverUrl)\n }\n\n const multiAccountInfo =\n state.multiAccountEnabled ?\n `\\n👥 Multi-account: ${accountManager.activeAccountCount}/${accountManager.accountCount} active`\n : \"\"\n\n consola.box(\n `🌐 Usage Viewer: https://imbuxiangnan-cyber.github.io/copilot-api-plus?endpoint=${serverUrl}/usage${multiAccountInfo}`,\n )\n\n serve({\n fetch: server.fetch as ServerHandler,\n port: options.port,\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 \"api-key\": {\n type: \"string\",\n description: \"API keys for authentication\",\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 // Handle multiple API keys - citty may pass a string or array\n const apiKeyRaw = args[\"api-key\"]\n let apiKeys: Array<string> | undefined\n if (apiKeyRaw) {\n apiKeys = Array.isArray(apiKeyRaw) ? apiKeyRaw : [apiKeyRaw]\n }\n\n return runServer({\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n accountType: args[\"account-type\"],\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 apiKeys,\n })\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand, runMain } from \"citty\"\n\nimport { addAccount, listAccounts, removeAccount } from \"./account\"\nimport { auth } from \"./auth\"\nimport { checkUsage } from \"./check-usage\"\nimport { debug } from \"./debug\"\nimport { logout } from \"./logout\"\nimport { proxy } from \"./proxy-config\"\nimport { start } from \"./start\"\n\nconst main = defineCommand({\n meta: {\n name: \"copilot-api-plus\",\n description:\n \"A wrapper around GitHub Copilot API to make it OpenAI/Anthropic compatible. Fork with bug fixes and improvements.\",\n },\n subCommands: {\n auth,\n start,\n \"check-usage\": checkUsage,\n \"add-account\": addAccount,\n \"list-accounts\": listAccounts,\n \"remove-account\": removeAccount,\n debug,\n logout,\n proxy,\n },\n})\n\nawait runMain(main)\n"],"x_google_ignoreList":[8,9,10,11,12],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"main.js","names":["fs","path","os","process","handleCompletion","isNonStreaming","handleCompletion"],"sources":["../src/lib/config.ts","../src/lib/proxy.ts","../src/account.ts","../src/auth.ts","../src/check-usage.ts","../src/debug.ts","../src/logout.ts","../src/proxy-config.ts","../node_modules/dotenv/package.json","../node_modules/dotenv/lib/main.js","../node_modules/dotenv/lib/env-options.js","../node_modules/dotenv/lib/cli-options.js","../node_modules/dotenv/config.js","../src/lib/model-router.ts","../src/lib/shell.ts","../src/lib/api-key-auth.ts","../src/lib/model-logger.ts","../src/routes/admin/accounts.ts","../src/routes/admin/models.ts","../src/routes/admin/stats.ts","../src/routes/admin/route.ts","../src/lib/approval.ts","../src/lib/rate-limit.ts","../src/services/copilot/create-chat-completions.ts","../src/routes/chat-completions/handler.ts","../src/routes/chat-completions/route.ts","../src/services/copilot/create-embeddings.ts","../src/routes/embeddings/route.ts","../src/lib/tokenizer.ts","../src/routes/messages/utils.ts","../src/routes/messages/non-stream-translation.ts","../src/routes/messages/count-tokens-handler.ts","../src/routes/messages/stream-translation.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["/**\n * Configuration file management\n * Handles persistent configuration storage for proxy settings and other options\n */\n\nimport consola from \"consola\"\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport { PATHS } from \"./paths\"\n\nconst CONFIG_FILENAME = \"config.json\"\n\nexport interface ProxyConfig {\n enabled: boolean\n httpProxy?: string\n httpsProxy?: string\n noProxy?: string\n}\n\nexport interface ModelMappingConfig {\n mapping?: Record<string, string>\n concurrency?: Record<string, number>\n}\n\nexport interface AppConfig {\n proxy?: ProxyConfig\n modelMapping?: ModelMappingConfig\n}\n\n/**\n * Get the path to the config file\n */\nexport function getConfigPath(): string {\n return path.join(PATHS.DATA_DIR, CONFIG_FILENAME)\n}\n\n/**\n * Load configuration from file\n */\nexport async function loadConfig(): Promise<AppConfig> {\n try {\n const configPath = getConfigPath()\n // eslint-disable-next-line unicorn/prefer-json-parse-buffer\n const content = await fs.readFile(configPath, \"utf8\")\n return JSON.parse(content) as AppConfig\n } catch {\n return {}\n }\n}\n\n/**\n * Save configuration to file\n */\nexport async function saveConfig(config: AppConfig): Promise<void> {\n const configPath = getConfigPath()\n await fs.writeFile(configPath, JSON.stringify(config, null, 2), \"utf8\")\n consola.debug(`Configuration saved to ${configPath}`)\n}\n\n/**\n * Get proxy configuration\n */\nexport async function getProxyConfig(): Promise<ProxyConfig | undefined> {\n const config = await loadConfig()\n return config.proxy\n}\n\n/**\n * Save proxy configuration\n */\nexport async function saveProxyConfig(proxyConfig: ProxyConfig): Promise<void> {\n const config = await loadConfig()\n config.proxy = proxyConfig\n await saveConfig(config)\n}\n\n/**\n * Clear proxy configuration\n */\nexport async function clearProxyConfig(): Promise<void> {\n const config = await loadConfig()\n delete config.proxy\n await saveConfig(config)\n}\n\n/**\n * Get model mapping configuration\n */\nexport async function getModelMappingConfig(): Promise<\n ModelMappingConfig | undefined\n> {\n const config = await loadConfig()\n return config.modelMapping\n}\n\n/**\n * Save model mapping configuration\n */\nexport async function saveModelMappingConfig(\n modelMapping: ModelMappingConfig,\n): Promise<void> {\n const config = await loadConfig()\n config.modelMapping = modelMapping\n await saveConfig(config)\n}\n\n/**\n * Apply saved proxy configuration to environment variables\n * This should be called at startup to restore proxy settings\n */\nexport async function applyProxyConfig(): Promise<boolean> {\n const proxyConfig = await getProxyConfig()\n\n if (!proxyConfig || !proxyConfig.enabled) {\n return false\n }\n\n if (proxyConfig.httpProxy) {\n process.env.HTTP_PROXY = proxyConfig.httpProxy\n process.env.http_proxy = proxyConfig.httpProxy\n }\n\n if (proxyConfig.httpsProxy) {\n process.env.HTTPS_PROXY = proxyConfig.httpsProxy\n process.env.https_proxy = proxyConfig.httpsProxy\n }\n\n if (proxyConfig.noProxy) {\n process.env.NO_PROXY = proxyConfig.noProxy\n process.env.no_proxy = proxyConfig.noProxy\n }\n\n consola.info(\"Proxy configuration loaded from saved settings\")\n if (proxyConfig.httpProxy) {\n consola.info(` HTTP_PROXY: ${proxyConfig.httpProxy}`)\n }\n if (proxyConfig.httpsProxy) {\n consola.info(` HTTPS_PROXY: ${proxyConfig.httpsProxy}`)\n }\n if (proxyConfig.noProxy) {\n consola.info(` NO_PROXY: ${proxyConfig.noProxy}`)\n }\n\n return true\n}\n","import consola from \"consola\"\nimport { getProxyForUrl } from \"proxy-from-env\"\nimport { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from \"undici\"\n\n// Module-level references so that `resetConnections` can swap them out.\n// Initialised by `initProxyFromEnv`; the dispatcher closure captures the\n// *variables* (not their values), so replacing them is enough.\nconst agentOptions = {\n keepAliveTimeout: 60_000,\n keepAliveMaxTimeout: 300_000,\n connect: {\n timeout: 15_000,\n // Send TCP keep-alive probes every 15 s to prevent HTTP proxies\n // (e.g. Clash) from killing idle SSE connections during long model\n // thinking phases where no HTTP-level data flows for 60+ seconds.\n keepAlive: true,\n keepAliveInitialDelay: 15_000,\n },\n}\nlet direct: Agent | undefined\nlet proxies = new Map<string, ProxyAgent>()\n\nexport function initProxyFromEnv(): void {\n if (typeof Bun !== \"undefined\") return\n\n try {\n direct = new Agent(agentOptions)\n 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({ uri: proxyUrl, ...agentOptions })\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 for (const agent of proxies.values()) {\n void (agent as unknown as Dispatcher).close()\n }\n // `direct` is always set before the dispatcher is installed.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return direct!.close()\n },\n destroy() {\n for (const agent of proxies.values()) {\n void (agent as unknown as Dispatcher).destroy()\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return direct!.destroy()\n },\n }\n\n setGlobalDispatcher(dispatcher as unknown as Dispatcher)\n consola.debug(\"HTTP proxy configured from environment (per-URL)\")\n } catch (err) {\n consola.debug(\"Proxy setup skipped:\", err)\n }\n}\n\n/**\n * Destroy all pooled connections (direct + proxy agents) and replace them\n * with fresh instances. The global dispatcher's `dispatch` method captures\n * `direct` and `proxies` by reference, so subsequent requests automatically\n * use the new agents — no need to call `setGlobalDispatcher` again.\n *\n * Call this after a network error to discard stale/half-closed sockets that\n * would otherwise cause every retry to wait ~60 s before timing out.\n *\n * Under the Bun runtime (which doesn't use undici) this is a no-op.\n */\nexport function resetConnections(): void {\n if (typeof Bun !== \"undefined\") return\n if (!direct) return\n\n const oldDirect = direct\n const oldProxies = proxies\n\n direct = new Agent(agentOptions)\n proxies = new Map<string, ProxyAgent>()\n\n // Tear down old agents in the background — errors are non-fatal.\n void (oldDirect as unknown as Dispatcher).close().catch(() => {})\n for (const agent of oldProxies.values()) {\n void (agent as unknown as Dispatcher).close().catch(() => {})\n }\n\n consola.debug(\"Connection pool reset — stale sockets cleared\")\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { accountManager } from \"./lib/account-manager\"\nimport { applyProxyConfig } from \"./lib/config\"\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { state } from \"./lib/state\"\nimport { cacheVSCodeVersion, rootCause } from \"./lib/utils\"\nimport { getDeviceCode } from \"./services/github/get-device-code\"\nimport { pollAccessToken } from \"./services/github/poll-access-token\"\n\n// ---------------------------------------------------------------------------\n// copilot-api-plus add-account\n// ---------------------------------------------------------------------------\n\nexport const addAccount = defineCommand({\n meta: {\n name: \"add-account\",\n description: \"Add a new GitHub account via Device Code auth\",\n },\n args: {\n label: {\n alias: \"l\",\n type: \"string\",\n description: \"Label for the account\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type (individual/business/enterprise)\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n },\n async run({ args }) {\n if (args.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n try {\n await ensurePaths()\n await applyProxyConfig()\n initProxyFromEnv()\n state.accountType = args[\"account-type\"]\n await cacheVSCodeVersion()\n\n // Device Code flow\n consola.info(\"Starting GitHub Device Code authentication...\")\n const deviceCode = await getDeviceCode()\n\n consola.box(\n `Please visit: ${deviceCode.verification_uri}\\nand enter code: ${deviceCode.user_code}`,\n )\n\n const githubToken = await pollAccessToken(deviceCode)\n consola.success(\"GitHub token obtained\")\n\n // Add account\n await accountManager.loadAccounts()\n\n const label = args.label || `Account ${accountManager.accountCount + 1}`\n const accountType = args[\"account-type\"]\n\n const account = await accountManager.addAccount(\n githubToken,\n label,\n accountType,\n )\n\n consola.success(\n `Account added: ${account.githubLogin} (${account.label})`,\n )\n consola.info(`Total accounts: ${accountManager.accountCount}`)\n } catch (err) {\n consola.warn(`Failed to add account: ${rootCause(err)}`)\n consola.debug(\"Failed to add account:\", err)\n process.exitCode = 1\n }\n },\n})\n\n// ---------------------------------------------------------------------------\n// copilot-api-plus list-accounts\n// ---------------------------------------------------------------------------\n\nexport const listAccounts = defineCommand({\n meta: {\n name: \"list-accounts\",\n description: \"List all configured accounts\",\n },\n args: {\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n },\n async run({ args }) {\n if (args.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n try {\n await ensurePaths()\n await accountManager.loadAccounts()\n\n const accounts = accountManager.getAccounts()\n\n if (accounts.length === 0) {\n consola.info(\"No accounts configured. Use `add-account` to add one.\")\n return\n }\n\n // Calculate column widths\n const rows = accounts.map((a, i) => ({\n num: String(i + 1),\n label: a.label || \"-\",\n login: a.githubLogin || \"unknown\",\n status: a.status,\n premium:\n a.usage ?\n `${a.usage.premium_remaining}/${a.usage.premium_total}`\n : \"-\",\n }))\n\n const cols = {\n num: Math.max(1, ...rows.map((r) => r.num.length)),\n label: Math.max(5, ...rows.map((r) => r.label.length)),\n login: Math.max(5, ...rows.map((r) => r.login.length)),\n status: Math.max(6, ...rows.map((r) => r.status.length)),\n premium: Math.max(17, ...rows.map((r) => r.premium.length)),\n }\n\n const pad = (s: string, w: number) => s.padEnd(w)\n const sep = (w: number) => \"─\".repeat(w)\n\n const header = `│ ${pad(\"#\", cols.num)} │ ${pad(\"Label\", cols.label)} │ ${pad(\"Login\", cols.login)} │ ${pad(\"Status\", cols.status)} │ ${pad(\"Premium Remaining\", cols.premium)} │`\n const topBorder = `┌─${sep(cols.num)}─┬─${sep(cols.label)}─┬─${sep(cols.login)}─┬─${sep(cols.status)}─┬─${sep(cols.premium)}─┐`\n const midBorder = `├─${sep(cols.num)}─┼─${sep(cols.label)}─┼─${sep(cols.login)}─┼─${sep(cols.status)}─┼─${sep(cols.premium)}─┤`\n const botBorder = `└─${sep(cols.num)}─┴─${sep(cols.label)}─┴─${sep(cols.login)}─┴─${sep(cols.status)}─┴─${sep(cols.premium)}─┘`\n\n consola.log(\"\")\n consola.log(topBorder)\n consola.log(header)\n consola.log(midBorder)\n\n for (const row of rows) {\n consola.log(\n `│ ${pad(row.num, cols.num)} │ ${pad(row.label, cols.label)} │ ${pad(row.login, cols.login)} │ ${pad(row.status, cols.status)} │ ${pad(row.premium, cols.premium)} │`,\n )\n }\n\n consola.log(botBorder)\n consola.log(\"\")\n } catch (err) {\n consola.warn(`Failed to list accounts: ${rootCause(err)}`)\n consola.debug(\"Failed to list accounts:\", err)\n process.exitCode = 1\n }\n },\n})\n\n// ---------------------------------------------------------------------------\n// copilot-api-plus remove-account\n// ---------------------------------------------------------------------------\n\nexport const removeAccount = defineCommand({\n meta: {\n name: \"remove-account\",\n description: \"Remove an account by label or index\",\n },\n args: {\n id: {\n type: \"positional\",\n description: \"Label or index (1-based) of the account to remove\",\n required: false,\n },\n label: {\n alias: \"l\",\n type: \"string\",\n description: \"Label of the account to remove\",\n },\n force: {\n alias: \"f\",\n type: \"boolean\",\n default: false,\n description: \"Skip confirmation prompt\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n },\n async run({ args }) {\n if (args.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n try {\n await ensurePaths()\n await accountManager.loadAccounts()\n\n const accounts = accountManager.getAccounts()\n\n if (accounts.length === 0) {\n consola.warn(\"No accounts configured.\")\n return\n }\n\n // Resolve which account to remove\n const identifier = args.id || args.label\n if (!identifier) {\n consola.error(\n \"Please specify an account to remove (by label or index).\",\n )\n consola.info(\"Usage: remove-account <label-or-index>\")\n process.exitCode = 1\n return\n }\n\n let account: (typeof accounts)[0] | undefined\n\n // Try numeric index first (1-based)\n const idx = Number.parseInt(identifier, 10)\n if (!Number.isNaN(idx) && idx >= 1 && idx <= accounts.length) {\n account = accounts[idx - 1]\n }\n\n // Try label match\n if (!account) {\n account = accounts.find(\n (a) => a.label.toLowerCase() === identifier.toLowerCase(),\n )\n }\n\n if (!account) {\n consola.error(`Account not found: ${identifier}`)\n process.exitCode = 1\n return\n }\n\n // Confirmation\n if (!args.force) {\n const confirmed = await consola.prompt(\n `Remove account \"${account.label}\" (${account.githubLogin || \"unknown\"})? [y/N]`,\n { type: \"confirm\" },\n )\n if (!confirmed) {\n consola.info(\"Cancelled.\")\n return\n }\n }\n\n const removed = await accountManager.removeAccount(account.id)\n if (removed) {\n consola.success(\n `Account removed: ${account.label} (${account.githubLogin || \"unknown\"})`,\n )\n } else {\n consola.error(\"Failed to remove account.\")\n process.exitCode = 1\n }\n } catch (err) {\n consola.warn(`Failed to remove account: ${rootCause(err)}`)\n consola.debug(\"Failed to remove account:\", err)\n process.exitCode = 1\n }\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { PATHS, ensurePaths } from \"./lib/paths\"\nimport { state } from \"./lib/state\"\nimport { setupGitHubToken } from \"./lib/token\"\n\ninterface RunAuthOptions {\n verbose: boolean\n showToken: boolean\n}\n\nexport async function runAuth(options: RunAuthOptions): Promise<void> {\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 await setupGitHubToken({ force: true })\n consola.success(\"GitHub token written to\", PATHS.GITHUB_TOKEN_PATH)\n}\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run GitHub auth flow without running the server\",\n },\n args: {\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub token on auth\",\n },\n },\n run({ args }) {\n return runAuth({\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { setupGitHubToken } from \"./lib/token\"\nimport { rootCause } from \"./lib/utils\"\nimport {\n getCopilotUsage,\n type QuotaDetail,\n} from \"./services/github/get-copilot-usage\"\n\nexport const checkUsage = defineCommand({\n meta: {\n name: \"check-usage\",\n description: \"Show current GitHub Copilot usage/quota information\",\n },\n async run() {\n await ensurePaths()\n await setupGitHubToken()\n try {\n const usage = await getCopilotUsage()\n const premium = usage.quota_snapshots.premium_interactions\n const premiumTotal = premium.entitlement\n const premiumUsed = premiumTotal - premium.remaining\n const premiumPercentUsed =\n premiumTotal > 0 ? (premiumUsed / premiumTotal) * 100 : 0\n const premiumPercentRemaining = premium.percent_remaining\n\n // Helper to summarize a quota snapshot\n function summarizeQuota(name: string, snap: QuotaDetail | undefined) {\n if (!snap) return `${name}: N/A`\n const total = snap.entitlement\n const used = total - snap.remaining\n const percentUsed = total > 0 ? (used / total) * 100 : 0\n const percentRemaining = snap.percent_remaining\n return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`\n }\n\n const premiumLine = `Premium: ${premiumUsed}/${premiumTotal} used (${premiumPercentUsed.toFixed(1)}% used, ${premiumPercentRemaining.toFixed(1)}% remaining)`\n const chatLine = summarizeQuota(\"Chat\", usage.quota_snapshots.chat)\n const completionsLine = summarizeQuota(\n \"Completions\",\n usage.quota_snapshots.completions,\n )\n\n consola.box(\n `Copilot Usage (plan: ${usage.copilot_plan})\\n`\n + `Quota resets: ${usage.quota_reset_date}\\n`\n + `\\nQuotas:\\n`\n + ` ${premiumLine}\\n`\n + ` ${chatLine}\\n`\n + ` ${completionsLine}`,\n )\n } catch (err) {\n consola.warn(`Failed to fetch Copilot usage: ${rootCause(err)}`)\n consola.debug(\"Failed to fetch Copilot usage:\", err)\n process.exit(1)\n }\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\nimport fs from \"node:fs/promises\"\nimport os from \"node:os\"\n\nimport { getProxyConfig, type ProxyConfig } from \"./lib/config\"\nimport { PATHS } from \"./lib/paths\"\n\ninterface DebugInfo {\n version: string\n runtime: {\n name: string\n version: string\n platform: string\n arch: string\n }\n paths: {\n APP_DIR: string\n GITHUB_TOKEN_PATH: string\n }\n credentials: {\n github: boolean\n }\n proxy?: ProxyConfig\n}\n\ninterface RunDebugOptions {\n json: boolean\n}\n\nasync function getPackageVersion(): Promise<string> {\n try {\n const packageJsonPath = new URL(\"../package.json\", import.meta.url).pathname\n // @ts-expect-error https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v59.0.1/docs/rules/prefer-json-parse-buffer.md\n // JSON.parse() can actually parse buffers\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath)) as {\n version: string\n }\n return packageJson.version\n } catch {\n return \"unknown\"\n }\n}\n\nfunction getRuntimeInfo() {\n const isBun = typeof Bun !== \"undefined\"\n\n return {\n name: isBun ? \"bun\" : \"node\",\n version: isBun ? Bun.version : process.version.slice(1),\n platform: os.platform(),\n arch: os.arch(),\n }\n}\n\nasync function checkTokenExists(): Promise<boolean> {\n try {\n const stats = await fs.stat(PATHS.GITHUB_TOKEN_PATH)\n if (!stats.isFile()) return false\n\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim().length > 0\n } catch {\n return false\n }\n}\n\nasync function getDebugInfo(): Promise<DebugInfo> {\n const [version, githubExists, proxyConfig] = await Promise.all([\n getPackageVersion(),\n checkTokenExists(),\n getProxyConfig(),\n ])\n\n return {\n version,\n runtime: getRuntimeInfo(),\n paths: {\n APP_DIR: PATHS.APP_DIR,\n GITHUB_TOKEN_PATH: PATHS.GITHUB_TOKEN_PATH,\n },\n credentials: {\n github: githubExists,\n },\n proxy: proxyConfig,\n }\n}\n\nfunction printDebugInfoPlain(info: DebugInfo): void {\n let proxyStatus = \"Not configured\"\n if (info.proxy) {\n proxyStatus =\n info.proxy.enabled ?\n `Enabled (${info.proxy.httpProxy || info.proxy.httpsProxy})`\n : \"Disabled\"\n }\n\n consola.info(`copilot-api-plus debug\n\nVersion: ${info.version}\nRuntime: ${info.runtime.name} ${info.runtime.version} (${info.runtime.platform} ${info.runtime.arch})\n\nPaths:\n APP_DIR: ${info.paths.APP_DIR}\n GITHUB_TOKEN_PATH: ${info.paths.GITHUB_TOKEN_PATH}\n\nCredentials:\n GitHub Copilot: ${info.credentials.github ? \"✅ Configured\" : \"❌ Not configured\"}\n\nProxy: ${proxyStatus}`)\n}\n\nfunction printDebugInfoJson(info: DebugInfo): void {\n console.log(JSON.stringify(info, null, 2))\n}\n\nexport async function runDebug(options: RunDebugOptions): Promise<void> {\n const debugInfo = await getDebugInfo()\n\n if (options.json) {\n printDebugInfoJson(debugInfo)\n } else {\n printDebugInfoPlain(debugInfo)\n }\n}\n\nexport const debug = defineCommand({\n meta: {\n name: \"debug\",\n description: \"Print debug information about the application\",\n },\n args: {\n json: {\n type: \"boolean\",\n default: false,\n description: \"Output debug information as JSON\",\n },\n },\n run({ args }) {\n return runDebug({\n json: args.json,\n })\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths, PATHS } from \"./lib/paths\"\nimport { clearGithubToken } from \"./lib/token\"\n\nexport async function runLogout(options: {\n github?: boolean\n all?: boolean\n}): Promise<void> {\n await ensurePaths()\n\n if (options.all || options.github) {\n await clearGithubToken()\n consola.success(\"Logged out from GitHub Copilot\")\n consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`)\n return\n }\n\n // Default: clear GitHub token\n await clearGithubToken()\n consola.success(\"Logged out from GitHub Copilot\")\n consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`)\n}\n\nexport const logout = defineCommand({\n meta: {\n name: \"logout\",\n description: \"Clear stored credentials and logout\",\n },\n args: {\n github: {\n alias: \"g\",\n type: \"boolean\",\n default: false,\n description: \"Clear GitHub Copilot token\",\n },\n all: {\n alias: \"a\",\n type: \"boolean\",\n default: false,\n description: \"Clear all credentials\",\n },\n },\n run({ args }) {\n return runLogout({\n github: args.github,\n all: args.all,\n })\n },\n})\n","/**\n * Proxy configuration command\n * Allows users to configure, enable, disable, and view proxy settings\n */\n\n/* eslint-disable max-lines-per-function */\n/* eslint-disable complexity */\n\nimport * as p from \"@clack/prompts\"\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport {\n clearProxyConfig,\n getProxyConfig,\n saveProxyConfig,\n type ProxyConfig,\n} from \"./lib/config\"\nimport { ensurePaths } from \"./lib/paths\"\n\nexport const proxy = defineCommand({\n meta: {\n name: \"proxy\",\n description: \"Configure proxy settings (persistent)\",\n },\n args: {\n set: {\n type: \"boolean\",\n default: false,\n description: \"Set proxy configuration interactively\",\n },\n enable: {\n type: \"boolean\",\n default: false,\n description: \"Enable saved proxy configuration\",\n },\n disable: {\n type: \"boolean\",\n default: false,\n description: \"Disable proxy (keep settings)\",\n },\n clear: {\n type: \"boolean\",\n default: false,\n description: \"Clear all proxy settings\",\n },\n show: {\n type: \"boolean\",\n default: false,\n description: \"Show current proxy configuration\",\n },\n \"http-proxy\": {\n type: \"string\",\n description: \"HTTP proxy URL (e.g., http://proxy:8080)\",\n },\n \"https-proxy\": {\n type: \"string\",\n description: \"HTTPS proxy URL (e.g., http://proxy:8080)\",\n },\n \"no-proxy\": {\n type: \"string\",\n description: \"Comma-separated list of hosts to bypass proxy\",\n },\n },\n async run({ args }) {\n await ensurePaths()\n\n // Show current configuration\n if (\n args.show\n || (!args.set\n && !args.enable\n && !args.disable\n && !args.clear\n && !args[\"http-proxy\"]\n && !args[\"https-proxy\"])\n ) {\n const config = await getProxyConfig()\n if (!config) {\n consola.info(\"No proxy configuration saved.\")\n consola.info(\"\")\n consola.info(\"To configure proxy, use one of:\")\n consola.info(\n \" copilot-api-plus proxy --set # Interactive setup\",\n )\n consola.info(\n \" copilot-api-plus proxy --http-proxy http://proxy:8080 # Direct set\",\n )\n return\n }\n\n consola.info(\"Current proxy configuration:\")\n consola.info(` Status: ${config.enabled ? \"✅ Enabled\" : \"❌ Disabled\"}`)\n if (config.httpProxy) {\n consola.info(` HTTP_PROXY: ${config.httpProxy}`)\n }\n if (config.httpsProxy) {\n consola.info(` HTTPS_PROXY: ${config.httpsProxy}`)\n }\n if (config.noProxy) {\n consola.info(` NO_PROXY: ${config.noProxy}`)\n }\n return\n }\n\n // Clear proxy settings\n if (args.clear) {\n await clearProxyConfig()\n consola.success(\"Proxy configuration cleared.\")\n return\n }\n\n // Enable proxy\n if (args.enable) {\n const config = await getProxyConfig()\n if (!config) {\n consola.error(\n \"No proxy configuration saved. Use --set to configure first.\",\n )\n return\n }\n config.enabled = true\n await saveProxyConfig(config)\n consola.success(\"Proxy enabled. It will be used on next server start.\")\n return\n }\n\n // Disable proxy\n if (args.disable) {\n const config = await getProxyConfig()\n if (!config) {\n consola.info(\"No proxy configuration to disable.\")\n return\n }\n config.enabled = false\n await saveProxyConfig(config)\n consola.success(\"Proxy disabled. Settings are preserved.\")\n return\n }\n\n // Direct set via command line args\n if (args[\"http-proxy\"] || args[\"https-proxy\"]) {\n const newConfig: ProxyConfig = {\n enabled: true,\n httpProxy: args[\"http-proxy\"],\n httpsProxy: args[\"https-proxy\"] || args[\"http-proxy\"], // Use HTTP proxy for HTTPS if not specified\n noProxy: args[\"no-proxy\"],\n }\n await saveProxyConfig(newConfig)\n consola.success(\"Proxy configuration saved and enabled.\")\n consola.info(` HTTP_PROXY: ${newConfig.httpProxy || \"(not set)\"}`)\n consola.info(` HTTPS_PROXY: ${newConfig.httpsProxy || \"(not set)\"}`)\n if (newConfig.noProxy) {\n consola.info(` NO_PROXY: ${newConfig.noProxy}`)\n }\n return\n }\n\n // Interactive setup\n if (args.set) {\n p.intro(\"Proxy Configuration\")\n\n const existingConfig = await getProxyConfig()\n\n const httpProxy = await p.text({\n message: \"HTTP Proxy URL\",\n placeholder: \"http://proxy:8080\",\n initialValue: existingConfig?.httpProxy || \"\",\n })\n\n if (p.isCancel(httpProxy)) {\n p.cancel(\"Configuration cancelled.\")\n return\n }\n\n const httpsProxy = await p.text({\n message: \"HTTPS Proxy URL (leave empty to use HTTP proxy)\",\n placeholder: \"http://proxy:8080\",\n initialValue: existingConfig?.httpsProxy || \"\",\n })\n\n if (p.isCancel(httpsProxy)) {\n p.cancel(\"Configuration cancelled.\")\n return\n }\n\n const noProxy = await p.text({\n message: \"No Proxy (comma-separated hosts to bypass)\",\n placeholder: \"localhost,127.0.0.1,.local\",\n initialValue: existingConfig?.noProxy || \"\",\n })\n\n if (p.isCancel(noProxy)) {\n p.cancel(\"Configuration cancelled.\")\n return\n }\n\n const enable = await p.confirm({\n message: \"Enable proxy now?\",\n initialValue: true,\n })\n\n if (p.isCancel(enable)) {\n p.cancel(\"Configuration cancelled.\")\n return\n }\n\n const newConfig: ProxyConfig = {\n enabled: enable,\n httpProxy: httpProxy || undefined,\n httpsProxy: httpsProxy || httpProxy || undefined,\n noProxy: noProxy || undefined,\n }\n\n await saveProxyConfig(newConfig)\n\n p.outro(`Proxy configuration saved${enable ? \" and enabled\" : \"\"}.`)\n }\n },\n})\n","","const fs = require('fs')\nconst path = require('path')\nconst os = require('os')\nconst crypto = require('crypto')\nconst packageJson = require('../package.json')\n\nconst version = packageJson.version\n\n// Array of tips to display randomly\nconst TIPS = [\n '🔐 encrypt with Dotenvx: https://dotenvx.com',\n '🔐 prevent committing .env to code: https://dotenvx.com/precommit',\n '🔐 prevent building .env in docker: https://dotenvx.com/prebuild',\n '📡 add observability to secrets: https://dotenvx.com/ops',\n '👥 sync secrets across teammates & machines: https://dotenvx.com/ops',\n '🗂️ backup and recover secrets: https://dotenvx.com/ops',\n '✅ audit secrets and track compliance: https://dotenvx.com/ops',\n '🔄 add secrets lifecycle management: https://dotenvx.com/ops',\n '🔑 add access controls to secrets: https://dotenvx.com/ops',\n '🛠️ run anywhere with `dotenvx run -- yourcommand`',\n '⚙️ specify custom .env file path with { path: \\'/custom/path/.env\\' }',\n '⚙️ enable debug logging with { debug: true }',\n '⚙️ override existing env vars with { override: true }',\n '⚙️ suppress all logs with { quiet: true }',\n '⚙️ write to custom object with { processEnv: myObject }',\n '⚙️ load multiple .env files with { path: [\\'.env.local\\', \\'.env\\'] }'\n]\n\n// Get a random tip from the tips array\nfunction _getRandomTip () {\n return TIPS[Math.floor(Math.random() * TIPS.length)]\n}\n\nfunction parseBoolean (value) {\n if (typeof value === 'string') {\n return !['false', '0', 'no', 'off', ''].includes(value.toLowerCase())\n }\n return Boolean(value)\n}\n\nfunction supportsAnsi () {\n return process.stdout.isTTY // && process.env.TERM !== 'dumb'\n}\n\nfunction dim (text) {\n return supportsAnsi() ? `\\x1b[2m${text}\\x1b[0m` : text\n}\n\nconst LINE = /(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg\n\n// Parse src into an Object\nfunction parse (src) {\n const obj = {}\n\n // Convert buffer to string\n let lines = src.toString()\n\n // Convert line breaks to same format\n lines = lines.replace(/\\r\\n?/mg, '\\n')\n\n let match\n while ((match = LINE.exec(lines)) != null) {\n const key = match[1]\n\n // Default undefined or null to empty string\n let value = (match[2] || '')\n\n // Remove whitespace\n value = value.trim()\n\n // Check if double quoted\n const maybeQuote = value[0]\n\n // Remove surrounding quotes\n value = value.replace(/^(['\"`])([\\s\\S]*)\\1$/mg, '$2')\n\n // Expand newlines if double quoted\n if (maybeQuote === '\"') {\n value = value.replace(/\\\\n/g, '\\n')\n value = value.replace(/\\\\r/g, '\\r')\n }\n\n // Add to object\n obj[key] = value\n }\n\n return obj\n}\n\nfunction _parseVault (options) {\n options = options || {}\n\n const vaultPath = _vaultPath(options)\n options.path = vaultPath // parse .env.vault\n const result = DotenvModule.configDotenv(options)\n if (!result.parsed) {\n const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`)\n err.code = 'MISSING_DATA'\n throw err\n }\n\n // handle scenario for comma separated keys - for use with key rotation\n // example: DOTENV_KEY=\"dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenvx.com/vault/.env.vault?environment=prod\"\n const keys = _dotenvKey(options).split(',')\n const length = keys.length\n\n let decrypted\n for (let i = 0; i < length; i++) {\n try {\n // Get full key\n const key = keys[i].trim()\n\n // Get instructions for decrypt\n const attrs = _instructions(result, key)\n\n // Decrypt\n decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key)\n\n break\n } catch (error) {\n // last key\n if (i + 1 >= length) {\n throw error\n }\n // try next key\n }\n }\n\n // Parse decrypted .env string\n return DotenvModule.parse(decrypted)\n}\n\nfunction _warn (message) {\n console.error(`[dotenv@${version}][WARN] ${message}`)\n}\n\nfunction _debug (message) {\n console.log(`[dotenv@${version}][DEBUG] ${message}`)\n}\n\nfunction _log (message) {\n console.log(`[dotenv@${version}] ${message}`)\n}\n\nfunction _dotenvKey (options) {\n // prioritize developer directly setting options.DOTENV_KEY\n if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {\n return options.DOTENV_KEY\n }\n\n // secondary infra already contains a DOTENV_KEY environment variable\n if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {\n return process.env.DOTENV_KEY\n }\n\n // fallback to empty string\n return ''\n}\n\nfunction _instructions (result, dotenvKey) {\n // Parse DOTENV_KEY. Format is a URI\n let uri\n try {\n uri = new URL(dotenvKey)\n } catch (error) {\n if (error.code === 'ERR_INVALID_URL') {\n const err = new Error('INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n throw error\n }\n\n // Get decrypt key\n const key = uri.password\n if (!key) {\n const err = new Error('INVALID_DOTENV_KEY: Missing key part')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n // Get environment\n const environment = uri.searchParams.get('environment')\n if (!environment) {\n const err = new Error('INVALID_DOTENV_KEY: Missing environment part')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n // Get ciphertext payload\n const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`\n const ciphertext = result.parsed[environmentKey] // DOTENV_VAULT_PRODUCTION\n if (!ciphertext) {\n const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`)\n err.code = 'NOT_FOUND_DOTENV_ENVIRONMENT'\n throw err\n }\n\n return { ciphertext, key }\n}\n\nfunction _vaultPath (options) {\n let possibleVaultPath = null\n\n if (options && options.path && options.path.length > 0) {\n if (Array.isArray(options.path)) {\n for (const filepath of options.path) {\n if (fs.existsSync(filepath)) {\n possibleVaultPath = filepath.endsWith('.vault') ? filepath : `${filepath}.vault`\n }\n }\n } else {\n possibleVaultPath = options.path.endsWith('.vault') ? options.path : `${options.path}.vault`\n }\n } else {\n possibleVaultPath = path.resolve(process.cwd(), '.env.vault')\n }\n\n if (fs.existsSync(possibleVaultPath)) {\n return possibleVaultPath\n }\n\n return null\n}\n\nfunction _resolveHome (envPath) {\n return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath\n}\n\nfunction _configVault (options) {\n const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || (options && options.debug))\n const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || (options && options.quiet))\n\n if (debug || !quiet) {\n _log('Loading env from encrypted .env.vault')\n }\n\n const parsed = DotenvModule._parseVault(options)\n\n let processEnv = process.env\n if (options && options.processEnv != null) {\n processEnv = options.processEnv\n }\n\n DotenvModule.populate(processEnv, parsed, options)\n\n return { parsed }\n}\n\nfunction configDotenv (options) {\n const dotenvPath = path.resolve(process.cwd(), '.env')\n let encoding = 'utf8'\n let processEnv = process.env\n if (options && options.processEnv != null) {\n processEnv = options.processEnv\n }\n let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || (options && options.debug))\n let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || (options && options.quiet))\n\n if (options && options.encoding) {\n encoding = options.encoding\n } else {\n if (debug) {\n _debug('No encoding is specified. UTF-8 is used by default')\n }\n }\n\n let optionPaths = [dotenvPath] // default, look for .env\n if (options && options.path) {\n if (!Array.isArray(options.path)) {\n optionPaths = [_resolveHome(options.path)]\n } else {\n optionPaths = [] // reset default\n for (const filepath of options.path) {\n optionPaths.push(_resolveHome(filepath))\n }\n }\n }\n\n // Build the parsed data in a temporary object (because we need to return it). Once we have the final\n // parsed data, we will combine it with process.env (or options.processEnv if provided).\n let lastError\n const parsedAll = {}\n for (const path of optionPaths) {\n try {\n // Specifying an encoding returns a string instead of a buffer\n const parsed = DotenvModule.parse(fs.readFileSync(path, { encoding }))\n\n DotenvModule.populate(parsedAll, parsed, options)\n } catch (e) {\n if (debug) {\n _debug(`Failed to load ${path} ${e.message}`)\n }\n lastError = e\n }\n }\n\n const populated = DotenvModule.populate(processEnv, parsedAll, options)\n\n // handle user settings DOTENV_CONFIG_ options inside .env file(s)\n debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug)\n quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet)\n\n if (debug || !quiet) {\n const keysCount = Object.keys(populated).length\n const shortPaths = []\n for (const filePath of optionPaths) {\n try {\n const relative = path.relative(process.cwd(), filePath)\n shortPaths.push(relative)\n } catch (e) {\n if (debug) {\n _debug(`Failed to load ${filePath} ${e.message}`)\n }\n lastError = e\n }\n }\n\n _log(`injecting env (${keysCount}) from ${shortPaths.join(',')} ${dim(`-- tip: ${_getRandomTip()}`)}`)\n }\n\n if (lastError) {\n return { parsed: parsedAll, error: lastError }\n } else {\n return { parsed: parsedAll }\n }\n}\n\n// Populates process.env from .env file\nfunction config (options) {\n // fallback to original dotenv if DOTENV_KEY is not set\n if (_dotenvKey(options).length === 0) {\n return DotenvModule.configDotenv(options)\n }\n\n const vaultPath = _vaultPath(options)\n\n // dotenvKey exists but .env.vault file does not exist\n if (!vaultPath) {\n _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`)\n\n return DotenvModule.configDotenv(options)\n }\n\n return DotenvModule._configVault(options)\n}\n\nfunction decrypt (encrypted, keyStr) {\n const key = Buffer.from(keyStr.slice(-64), 'hex')\n let ciphertext = Buffer.from(encrypted, 'base64')\n\n const nonce = ciphertext.subarray(0, 12)\n const authTag = ciphertext.subarray(-16)\n ciphertext = ciphertext.subarray(12, -16)\n\n try {\n const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce)\n aesgcm.setAuthTag(authTag)\n return `${aesgcm.update(ciphertext)}${aesgcm.final()}`\n } catch (error) {\n const isRange = error instanceof RangeError\n const invalidKeyLength = error.message === 'Invalid key length'\n const decryptionFailed = error.message === 'Unsupported state or unable to authenticate data'\n\n if (isRange || invalidKeyLength) {\n const err = new Error('INVALID_DOTENV_KEY: It must be 64 characters long (or more)')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n } else if (decryptionFailed) {\n const err = new Error('DECRYPTION_FAILED: Please check your DOTENV_KEY')\n err.code = 'DECRYPTION_FAILED'\n throw err\n } else {\n throw error\n }\n }\n}\n\n// Populate process.env with parsed values\nfunction populate (processEnv, parsed, options = {}) {\n const debug = Boolean(options && options.debug)\n const override = Boolean(options && options.override)\n const populated = {}\n\n if (typeof parsed !== 'object') {\n const err = new Error('OBJECT_REQUIRED: Please check the processEnv argument being passed to populate')\n err.code = 'OBJECT_REQUIRED'\n throw err\n }\n\n // Set process.env\n for (const key of Object.keys(parsed)) {\n if (Object.prototype.hasOwnProperty.call(processEnv, key)) {\n if (override === true) {\n processEnv[key] = parsed[key]\n populated[key] = parsed[key]\n }\n\n if (debug) {\n if (override === true) {\n _debug(`\"${key}\" is already defined and WAS overwritten`)\n } else {\n _debug(`\"${key}\" is already defined and was NOT overwritten`)\n }\n }\n } else {\n processEnv[key] = parsed[key]\n populated[key] = parsed[key]\n }\n }\n\n return populated\n}\n\nconst DotenvModule = {\n configDotenv,\n _configVault,\n _parseVault,\n config,\n decrypt,\n parse,\n populate\n}\n\nmodule.exports.configDotenv = DotenvModule.configDotenv\nmodule.exports._configVault = DotenvModule._configVault\nmodule.exports._parseVault = DotenvModule._parseVault\nmodule.exports.config = DotenvModule.config\nmodule.exports.decrypt = DotenvModule.decrypt\nmodule.exports.parse = DotenvModule.parse\nmodule.exports.populate = DotenvModule.populate\n\nmodule.exports = DotenvModule\n","// ../config.js accepts options via environment variables\nconst options = {}\n\nif (process.env.DOTENV_CONFIG_ENCODING != null) {\n options.encoding = process.env.DOTENV_CONFIG_ENCODING\n}\n\nif (process.env.DOTENV_CONFIG_PATH != null) {\n options.path = process.env.DOTENV_CONFIG_PATH\n}\n\nif (process.env.DOTENV_CONFIG_QUIET != null) {\n options.quiet = process.env.DOTENV_CONFIG_QUIET\n}\n\nif (process.env.DOTENV_CONFIG_DEBUG != null) {\n options.debug = process.env.DOTENV_CONFIG_DEBUG\n}\n\nif (process.env.DOTENV_CONFIG_OVERRIDE != null) {\n options.override = process.env.DOTENV_CONFIG_OVERRIDE\n}\n\nif (process.env.DOTENV_CONFIG_DOTENV_KEY != null) {\n options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY\n}\n\nmodule.exports = options\n","const re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/\n\nmodule.exports = function optionMatcher (args) {\n const options = args.reduce(function (acc, cur) {\n const matches = cur.match(re)\n if (matches) {\n acc[matches[1]] = matches[2]\n }\n return acc\n }, {})\n\n if (!('quiet' in options)) {\n options.quiet = 'true'\n }\n\n return options\n}\n","(function () {\n require('./lib/main').config(\n Object.assign(\n {},\n require('./lib/env-options'),\n require('./lib/cli-options')(process.argv)\n )\n )\n})()\n","/**\n * Model Router - Model mapping and per-model concurrency control\n *\n * Provides flexible model name mapping (requested → actual) and\n * per-model concurrency limits using a semaphore pattern.\n */\n\nimport consola from \"consola\"\n\nexport interface ModelMappingConfig {\n /** Map from requested model name → actual model name sent to Copilot. Special key \"*\" is the default/fallback. */\n mapping: Record<string, string>\n /** Per-model max concurrent requests. Special key \"default\" is the fallback. */\n concurrency: Record<string, number>\n}\n\nconst DEFAULT_CONFIG: ModelMappingConfig = {\n mapping: {},\n concurrency: {\n default: 10,\n },\n}\n\nconst DEFAULT_MAX_CONCURRENCY = 10\n\nexport class ModelRouter {\n private config: ModelMappingConfig\n private queues: Map<string, { active: number; waiters: Array<() => void> }> =\n new Map()\n\n constructor(config?: ModelMappingConfig) {\n this.config =\n config ?\n { ...config }\n : { ...DEFAULT_CONFIG, mapping: {}, concurrency: { default: 10 } }\n }\n\n /**\n * Resolve a requested model name to the actual model name.\n *\n * Resolution order:\n * 1. Exact match in config.mapping\n * 2. Wildcard \"*\" in config.mapping\n * 3. Passthrough (return requestedModel as-is)\n */\n resolveModel(requestedModel: string): string {\n // 1. Exact match\n if (requestedModel in this.config.mapping) {\n const resolved = this.config.mapping[requestedModel]\n consola.debug(`Model mapping: \"${requestedModel}\" → \"${resolved}\"`)\n return resolved\n }\n\n // 2. Wildcard fallback\n if (\"*\" in this.config.mapping) {\n const resolved = this.config.mapping[\"*\"]\n consola.debug(\n `Model mapping (wildcard): \"${requestedModel}\" → \"${resolved}\"`,\n )\n return resolved\n }\n\n // 3. Passthrough\n return requestedModel\n }\n\n /**\n * Acquire a concurrency slot for the given model.\n *\n * The caller should pass the **already-resolved** model name (i.e. the\n * value returned by `resolveModel()`). This method does NOT re-resolve\n * the name so that concurrency limits are keyed by the actual model sent\n * to the backend, not the user-facing alias.\n *\n * Returns a release function that must be called when the request completes.\n * If the concurrency limit is reached, the returned promise will wait until\n * a slot becomes available.\n */\n async acquireSlot(resolvedModel: string): Promise<() => void> {\n const maxConcurrency =\n (this.config.concurrency as Partial<Record<string, number>>)[\n resolvedModel\n ]\n ?? (this.config.concurrency as Partial<Record<string, number>>)[\"default\"]\n ?? DEFAULT_MAX_CONCURRENCY\n\n let queue = this.queues.get(resolvedModel)\n if (!queue) {\n queue = { active: 0, waiters: [] }\n this.queues.set(resolvedModel, queue)\n }\n\n if (queue.active < maxConcurrency) {\n queue.active++\n consola.debug(\n `Slot acquired for \"${resolvedModel}\": ${queue.active}/${maxConcurrency} active`,\n )\n return () => this.releaseSlot(resolvedModel)\n }\n\n // Wait for a slot to open\n const currentQueue = queue\n consola.debug(\n `Concurrency limit reached for \"${resolvedModel}\" (${maxConcurrency}), queuing request`,\n )\n return new Promise<() => void>((resolve) => {\n currentQueue.waiters.push(() => {\n currentQueue.active++\n consola.debug(\n `Queued slot acquired for \"${resolvedModel}\": ${currentQueue.active}/${maxConcurrency} active`,\n )\n resolve(() => this.releaseSlot(resolvedModel))\n })\n })\n }\n\n private releaseSlot(model: string): void {\n const queue = this.queues.get(model)\n if (!queue) return\n\n queue.active--\n\n if (queue.waiters.length > 0) {\n const next = queue.waiters.shift()\n if (next) next()\n }\n\n consola.debug(\n `Slot released for \"${model}\": ${queue.active} active, ${queue.waiters.length} queued`,\n )\n }\n\n /**\n * Get current concurrency stats for all tracked models.\n */\n getStats(): Record<\n string,\n { active: number; queued: number; maxConcurrency: number }\n > {\n const stats: Record<\n string,\n { active: number; queued: number; maxConcurrency: number }\n > = {}\n\n for (const [model, queue] of this.queues) {\n const maxConcurrency =\n (this.config.concurrency as Partial<Record<string, number>>)[model]\n ?? (this.config.concurrency as Partial<Record<string, number>>)[\n \"default\"\n ]\n ?? DEFAULT_MAX_CONCURRENCY\n\n stats[model] = {\n active: queue.active,\n queued: queue.waiters.length,\n maxConcurrency,\n }\n }\n\n return stats\n }\n\n /**\n * Update the model name mapping configuration.\n */\n updateMapping(mapping: Record<string, string>): void {\n this.config.mapping = { ...mapping }\n consola.info(\"Model mapping updated:\", Object.keys(mapping).length, \"rules\")\n }\n\n /**\n * Update the per-model concurrency configuration.\n */\n updateConcurrency(concurrency: Record<string, number>): void {\n this.config.concurrency = { ...concurrency }\n consola.info(\n \"Model concurrency updated:\",\n Object.keys(concurrency).length,\n \"rules\",\n )\n }\n\n /**\n * Get the current configuration (returns a copy).\n */\n getConfig(): ModelMappingConfig {\n return {\n mapping: { ...this.config.mapping },\n concurrency: { ...this.config.concurrency },\n }\n }\n}\n\nexport const modelRouter = new ModelRouter()\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\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(\n ([key, value]) =>\n `set -gx ${key} '${value.replaceAll(\"'\", String.raw`\\'`)}'`,\n )\n .join(\"; \")\n break\n }\n default: {\n // bash, zsh, sh\n const assignments = filteredEnvVars\n .map(\n ([key, value]) =>\n `${key}='${value.replaceAll(\"'\", String.raw`'\\''`)}'`,\n )\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 type { Context, MiddlewareHandler } from \"hono\"\n\nimport { HTTPException } from \"hono/http-exception\"\nimport { timingSafeEqual } from \"node:crypto\"\n\nimport { state } from \"./state\"\n\n/**\n * Retrieve an API key from the incoming request.\n *\n * Checks common locations where clients supply keys (Authorization Bearer header, `x-api-key` header, or `apiKey` query parameter) and returns the first one found.\n *\n * @returns The extracted API key, or `undefined` if no key is present.\n */\nfunction extractApiKey(c: Context): string | undefined {\n // OpenAI format: Authorization header with Bearer prefix\n const authHeader = c.req.header(\"authorization\")\n if (authHeader?.startsWith(\"Bearer \")) {\n return authHeader.slice(7) // Remove 'Bearer ' prefix\n }\n\n // Anthropic format: x-api-key header\n const anthropicKey = c.req.header(\"x-api-key\")\n if (anthropicKey) {\n return anthropicKey\n }\n\n // Fallback: query parameter, for extra compatibility of `/usage` or `/token` route\n const queryKey = c.req.query(\"apiKey\")\n if (queryKey) {\n return queryKey\n }\n\n return undefined\n}\n\n/**\n * API key authentication middleware\n * Validates that the request contains a valid API key if API keys are configured\n */\nexport const apiKeyAuthMiddleware: MiddlewareHandler = async (c, next) => {\n // If no API keys are configured, skip authentication\n if (!state.apiKeys || state.apiKeys.length === 0) {\n await next()\n return\n }\n\n const providedKey = extractApiKey(c)\n\n // If no API key is provided, return 401\n if (!providedKey) {\n throw new HTTPException(401, {\n message:\n \"API key required. Please provide a valid API key in the Authorization header (Bearer token) or x-api-key header.\",\n })\n }\n\n // Check if the provided key matches any of the configured keys (timing-safe)\n const isValidKey = state.apiKeys.some((key) => {\n if (key.length !== providedKey.length) return false\n try {\n return timingSafeEqual(Buffer.from(key), Buffer.from(providedKey))\n } catch {\n return false\n }\n })\n\n if (!isValidKey) {\n throw new HTTPException(401, {\n message: \"Invalid API key. Please provide a valid API key.\",\n })\n }\n\n // Key is valid, continue with the request\n await next()\n}\n","/**\n * Custom logger middleware that displays model name + thinking status before timestamp\n */\n\nimport type { Context, MiddlewareHandler, Next } from \"hono\"\n\n/**\n * Get timestamp string in format HH:mm:ss\n */\nfunction getTime(): string {\n return new Date().toLocaleTimeString(\"en-US\", { hour12: false })\n}\n\n/**\n * Format duration in human readable format\n */\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`\n return `${(ms / 1000).toFixed(1)}s`\n}\n\n/**\n * Extract model name and thinking status from request body.\n *\n * Thinking is considered active when:\n * - The client explicitly passes reasoning_effort / thinking_budget / thinking\n * - OR the backend will auto-inject thinking (default for all supported models)\n *\n * Since the proxy injects thinking for every model except those known to reject\n * it, we always mark thinking=true here. The `create-chat-completions` layer\n * will log the precise injection path separately.\n */\nasync function extractModelInfo(\n c: Context,\n): Promise<{ model?: string; thinking?: boolean }> {\n try {\n // Clone the request to avoid consuming the body\n const clonedReq = c.req.raw.clone()\n const body = (await clonedReq.json()) as {\n model?: string\n // OpenAI-style thinking params\n reasoning_effort?: string\n thinking_budget?: number\n // Anthropic-style thinking params\n thinking?: { type?: string; budget_tokens?: number }\n }\n // Client-explicit thinking check\n const clientThinking =\n Boolean(body.reasoning_effort)\n || Boolean(body.thinking_budget)\n || body.thinking?.type === \"enabled\"\n\n // The proxy injects thinking by default, so mark true regardless\n // (the actual injection + fallback is logged in create-chat-completions)\n return { model: body.model, thinking: clientThinking || true }\n } catch {\n return {}\n }\n}\n\n/**\n * Custom logger middleware that shows model name + thinking before timestamp\n *\n * Output format:\n * [model thinking] HH:mm:ss <-- METHOD /path\n * [model thinking] HH:mm:ss --> METHOD /path STATUS DURATION\n */\nexport function modelLogger(): MiddlewareHandler {\n return async (c: Context, next: Next) => {\n const method = c.req.method\n const path = c.req.path\n const queryString =\n c.req.raw.url.includes(\"?\") ? `?${c.req.raw.url.split(\"?\")[1]}` : \"\"\n const fullPath = `${path}${queryString}`\n\n // Extract model and thinking status for POST requests with JSON body\n let model: string | undefined\n let thinking = false\n if (method === \"POST\" && c.req.header(\"content-type\")?.includes(\"json\")) {\n const info = await extractModelInfo(c)\n model = info.model\n thinking = info.thinking ?? false\n }\n\n const thinkingTag = thinking ? \" thinking\" : \"\"\n const modelPrefix = model ? `[${model}${thinkingTag}] ` : \"\"\n const startTime = getTime()\n\n // Log incoming request\n console.log(`${modelPrefix}${startTime} <-- ${method} ${fullPath}`)\n\n const start = Date.now()\n await next()\n\n const duration = Date.now() - start\n const endTime = getTime()\n\n // Log outgoing response\n console.log(\n `${modelPrefix}${endTime} --> ${method} ${fullPath} ${c.res.status} ${formatDuration(duration)}`,\n )\n }\n}\n","import consola from \"consola\"\nimport { Hono } from \"hono\"\n\nimport type { Account } from \"~/lib/account-manager\"\n\nimport { accountManager } from \"~/lib/account-manager\"\nimport {\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { rootCause } from \"~/lib/utils\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\n\nexport const accountRoutes = new Hono()\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction maskToken(token: string): string {\n if (token.length <= 8) return \"****\"\n return `${token.slice(0, 4)}...${token.slice(-4)}`\n}\n\n/**\n * Return a sanitised copy of an account safe for API responses.\n * - `githubToken` is masked.\n * - `copilotToken` is fully excluded.\n */\nfunction sanitiseAccount(account: Account) {\n const { copilotToken: _dropped, githubToken, ...rest } = account\n return {\n ...rest,\n githubToken: maskToken(githubToken),\n }\n}\n\n// ---------------------------------------------------------------------------\n// GET / — List all accounts (token masked)\n// ---------------------------------------------------------------------------\n\naccountRoutes.get(\"/\", (c) => {\n try {\n const accounts = accountManager.getAccounts().map((a) => sanitiseAccount(a))\n return c.json({ accounts })\n } catch (error) {\n consola.warn(`Error listing accounts: ${rootCause(error)}`)\n consola.debug(\"Error listing accounts:\", error)\n return c.json({ error: \"Failed to list accounts\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// POST / — Add account\n// ---------------------------------------------------------------------------\n\naccountRoutes.post(\"/\", async (c) => {\n try {\n const body = await c.req.json<{\n githubToken: string\n label: string\n accountType?: string\n }>()\n\n if (!body.githubToken || !body.label) {\n return c.json({ error: \"githubToken and label are required\" }, 400)\n }\n\n const account = await accountManager.addAccount(\n body.githubToken,\n body.label,\n body.accountType,\n )\n\n return c.json({ account: sanitiseAccount(account) }, 201)\n } catch (error) {\n consola.warn(`Error adding account: ${rootCause(error)}`)\n consola.debug(\"Error adding account:\", error)\n return c.json({ error: \"Failed to add account\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// DELETE /:id — Remove account\n// ---------------------------------------------------------------------------\n\naccountRoutes.delete(\"/:id\", async (c) => {\n try {\n const id = c.req.param(\"id\")\n const removed = await accountManager.removeAccount(id)\n\n if (!removed) {\n return c.json({ error: \"Account not found\" }, 404)\n }\n\n return c.json({ success: true })\n } catch (error) {\n consola.warn(`Error removing account: ${rootCause(error)}`)\n consola.debug(\"Error removing account:\", error)\n return c.json({ error: \"Failed to remove account\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// PUT /:id/status — Update account status (enable / disable)\n// ---------------------------------------------------------------------------\n\naccountRoutes.put(\"/:id/status\", async (c) => {\n try {\n const id = c.req.param(\"id\")\n const body = await c.req.json<{ status: string }>()\n\n if (body.status !== \"active\" && body.status !== \"disabled\") {\n return c.json({ error: 'status must be \"active\" or \"disabled\"' }, 400)\n }\n\n const account = accountManager.getAccountById(id)\n if (!account) {\n return c.json({ error: \"Account not found\" }, 404)\n }\n\n account.status = body.status\n account.statusMessage = undefined\n\n // When manually activating, also clear cooldown and failure counters\n if (body.status === \"active\") {\n account.cooldownUntil = undefined\n account.consecutiveFailures = 0\n }\n\n await accountManager.saveAccounts()\n\n return c.json({ account: sanitiseAccount(account) })\n } catch (error) {\n consola.warn(`Error updating account status: ${rootCause(error)}`)\n consola.debug(\"Error updating account status:\", error)\n return c.json({ error: \"Failed to update account status\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// POST /:id/refresh — Force refresh token + usage for one account\n// ---------------------------------------------------------------------------\n\naccountRoutes.post(\"/:id/refresh\", async (c) => {\n try {\n const id = c.req.param(\"id\")\n const account = accountManager.getAccountById(id)\n\n if (!account) {\n return c.json({ error: \"Account not found\" }, 404)\n }\n\n await accountManager.refreshAccountToken(account)\n await accountManager.refreshAccountUsage(account)\n\n return c.json({ account: sanitiseAccount(account) })\n } catch (error) {\n consola.warn(`Error refreshing account: ${rootCause(error)}`)\n consola.debug(\"Error refreshing account:\", error)\n return c.json({ error: \"Failed to refresh account\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// POST /auth/start — Initiate GitHub Device Code flow\n// ---------------------------------------------------------------------------\n\naccountRoutes.post(\"/auth/start\", async (c) => {\n try {\n const deviceCode = await getDeviceCode()\n return c.json(deviceCode)\n } catch (error) {\n consola.warn(`Error starting device code flow: ${rootCause(error)}`)\n consola.debug(\"Error starting device code flow:\", error)\n return c.json({ error: \"Failed to start device code authorization\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// POST /auth/poll — Poll for Device Code authorization completion\n// ---------------------------------------------------------------------------\n\naccountRoutes.post(\"/auth/poll\", async (c) => {\n try {\n const { device_code, label, account_type } = await c.req.json<{\n device_code: string\n label?: string\n account_type?: string\n }>()\n\n if (!device_code) {\n return c.json({ error: \"device_code is required\" }, 400)\n }\n\n // Single poll attempt to GitHub's token endpoint\n const response = await fetch(\n `${GITHUB_BASE_URL}/login/oauth/access_token`,\n {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n device_code,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n },\n )\n\n if (!response.ok) {\n return c.json({ status: \"pending\" })\n }\n\n const json = (await response.json()) as\n | { access_token: string; token_type: string; scope: string }\n | { error: string; error_description?: string }\n\n // Handle error responses from GitHub\n if (\"error\" in json) {\n switch (json.error) {\n case \"authorization_pending\": {\n return c.json({ status: \"pending\" })\n }\n case \"slow_down\": {\n return c.json({ status: \"pending\", interval: 10 })\n }\n case \"expired_token\": {\n return c.json({ status: \"expired\" })\n }\n case \"access_denied\": {\n return c.json({ status: \"denied\" })\n }\n default: {\n return c.json({\n status: \"error\",\n message: json.error_description || json.error,\n })\n }\n }\n }\n\n // Success — we have an access token\n if (\"access_token\" in json && json.access_token) {\n const accountLabel = label || `Account ${accountManager.accountCount + 1}`\n const account = await accountManager.addAccount(\n json.access_token,\n accountLabel,\n account_type || \"individual\",\n )\n return c.json({ status: \"complete\", account: sanitiseAccount(account) })\n }\n\n // Unexpected response shape\n return c.json({ status: \"pending\" })\n } catch (error) {\n consola.warn(`Error polling device code: ${rootCause(error)}`)\n consola.debug(\"Error polling device code:\", error)\n return c.json({ error: \"Failed to poll device code authorization\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// GET /usage — Aggregated usage across all accounts\n// ---------------------------------------------------------------------------\n\naccountRoutes.get(\"/usage\", (c) => {\n try {\n const accounts = accountManager.getAccounts()\n\n const aggregatedUsage = {\n premium_remaining: 0,\n premium_total: 0,\n chat_remaining: 0,\n chat_total: 0,\n }\n\n const accountSummaries = accounts.map((a) => {\n if (a.usage) {\n aggregatedUsage.premium_remaining += a.usage.premium_remaining\n aggregatedUsage.premium_total += a.usage.premium_total\n aggregatedUsage.chat_remaining += a.usage.chat_remaining\n aggregatedUsage.chat_total += a.usage.chat_total\n }\n\n return {\n id: a.id,\n label: a.label,\n status: a.status,\n usage: a.usage ?? null,\n }\n })\n\n return c.json({\n totalAccounts: accounts.length,\n activeAccounts: accounts.filter((a) => a.status === \"active\").length,\n aggregatedUsage,\n accounts: accountSummaries,\n })\n } catch (error) {\n consola.warn(`Error fetching aggregated usage: ${rootCause(error)}`)\n consola.debug(\"Error fetching aggregated usage:\", error)\n return c.json({ error: \"Failed to fetch aggregated usage\" }, 500)\n }\n})\n","import consola from \"consola\"\nimport { Hono } from \"hono\"\n\nimport { saveModelMappingConfig } from \"~/lib/config\"\nimport { modelRouter } from \"~/lib/model-router\"\nimport { state } from \"~/lib/state\"\nimport { rootCause } from \"~/lib/utils\"\n\nexport const modelAdminRoutes = new Hono()\n\n// ---------------------------------------------------------------------------\n// GET /available — List all models from Copilot\n// ---------------------------------------------------------------------------\n\nmodelAdminRoutes.get(\"/available\", (c) => {\n try {\n const models = state.models?.data ?? []\n return c.json(models)\n } catch (error) {\n consola.warn(`Error fetching available models: ${rootCause(error)}`)\n consola.debug(\"Error fetching available models:\", error)\n return c.json({ error: \"Failed to fetch available models\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// GET /mapping — Get current model mapping config\n// ---------------------------------------------------------------------------\n\nmodelAdminRoutes.get(\"/mapping\", (c) => {\n try {\n return c.json(modelRouter.getConfig())\n } catch (error) {\n consola.warn(`Error fetching model mapping: ${rootCause(error)}`)\n consola.debug(\"Error fetching model mapping:\", error)\n return c.json({ error: \"Failed to fetch model mapping\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// PUT /mapping — Update model mapping\n// ---------------------------------------------------------------------------\n\nmodelAdminRoutes.put(\"/mapping\", async (c) => {\n try {\n const body = await c.req.json<{ mapping?: Record<string, string> }>()\n\n if (!body.mapping || typeof body.mapping !== \"object\") {\n return c.json({ error: \"mapping object is required\" }, 400)\n }\n\n // Validate that all mapping values are non-empty strings\n for (const [key, value] of Object.entries(body.mapping)) {\n if (typeof value !== \"string\" || value.trim() === \"\") {\n return c.json(\n {\n error: `Invalid mapping value for \"${key}\": must be a non-empty string`,\n },\n 400,\n )\n }\n }\n\n modelRouter.updateMapping(body.mapping)\n await saveModelMappingConfig(modelRouter.getConfig())\n\n return c.json(modelRouter.getConfig())\n } catch (error) {\n consola.warn(`Error updating model mapping: ${rootCause(error)}`)\n consola.debug(\"Error updating model mapping:\", error)\n return c.json({ error: \"Failed to update model mapping\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// GET /concurrency — Get concurrency config\n// ---------------------------------------------------------------------------\n\nmodelAdminRoutes.get(\"/concurrency\", (c) => {\n try {\n return c.json({ concurrency: modelRouter.getConfig().concurrency })\n } catch (error) {\n consola.warn(`Error fetching concurrency config: ${rootCause(error)}`)\n consola.debug(\"Error fetching concurrency config:\", error)\n return c.json({ error: \"Failed to fetch concurrency config\" }, 500)\n }\n})\n\n// ---------------------------------------------------------------------------\n// PUT /concurrency — Update concurrency config\n// ---------------------------------------------------------------------------\n\nmodelAdminRoutes.put(\"/concurrency\", async (c) => {\n try {\n const body = await c.req.json<{ concurrency?: Record<string, number> }>()\n\n if (!body.concurrency || typeof body.concurrency !== \"object\") {\n return c.json({ error: \"concurrency object is required\" }, 400)\n }\n\n // Validate that all concurrency values are positive integers\n for (const [key, value] of Object.entries(body.concurrency)) {\n if (typeof value !== \"number\" || value < 1 || !Number.isInteger(value)) {\n return c.json(\n {\n error: `Invalid concurrency value for \"${key}\": must be a positive integer`,\n },\n 400,\n )\n }\n }\n\n modelRouter.updateConcurrency(body.concurrency)\n await saveModelMappingConfig(modelRouter.getConfig())\n\n return c.json({ concurrency: modelRouter.getConfig().concurrency })\n } catch (error) {\n consola.warn(`Error updating concurrency config: ${rootCause(error)}`)\n consola.debug(\"Error updating concurrency config:\", error)\n return c.json({ error: \"Failed to update concurrency config\" }, 500)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { accountManager } from \"~/lib/account-manager\"\nimport { modelRouter } from \"~/lib/model-router\"\n\nexport const statsRoute = new Hono()\n\nstatsRoute.get(\"/\", (c) => {\n return c.json({\n accounts: {\n total: accountManager.accountCount,\n active: accountManager.activeAccountCount,\n },\n models: modelRouter.getStats(),\n uptime: process.uptime(),\n })\n})\n","import { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\n\nimport { accountRoutes } from \"./accounts\"\nimport { modelAdminRoutes } from \"./models\"\nimport { statsRoute } from \"./stats\"\n\nexport const adminRoutes = new Hono()\n\nadminRoutes.route(\"/accounts\", accountRoutes)\nadminRoutes.route(\"/models\", modelAdminRoutes)\nadminRoutes.route(\"/stats\", statsRoute)\n\n// ---------------------------------------------------------------------------\n// GET /config — Export-ready config with selected models and API key\n// ---------------------------------------------------------------------------\n\nadminRoutes.get(\"/config\", (c) => {\n return c.json({\n selectedModel: state.selectedModel,\n selectedSmallModel: state.selectedSmallModel,\n apiKey: state.apiKeys?.[0] ?? \"dummy\",\n })\n})\n","import consola from \"consola\"\n\nimport { HTTPError } from \"./error\"\n\nexport const awaitApproval = async () => {\n const response = await consola.prompt(`Accept incoming request?`, {\n type: \"confirm\",\n })\n\n if (!response)\n throw new HTTPError(\n \"Request rejected\",\n Response.json({ message: \"Request rejected\" }, { status: 403 }),\n )\n}\n","import consola from \"consola\"\n\nimport type { State } from \"./state\"\n\nimport { HTTPError } from \"./error\"\nimport { sleep } from \"./utils\"\n\n/** Serialize concurrent rate-limit checks so only one request passes at a time. */\nlet rateLimitLock: Promise<void> = Promise.resolve()\n\nexport async function checkRateLimit(state: State) {\n if (state.rateLimitSeconds === undefined) return\n\n // Chain on the previous check so concurrent requests are serialized\n const previous = rateLimitLock\n let resolve!: () => void\n rateLimitLock = new Promise<void>((r) => {\n resolve = r\n })\n\n try {\n await previous\n\n const now = Date.now()\n\n if (!state.lastRequestTimestamp) {\n state.lastRequestTimestamp = now\n return\n }\n\n const elapsedSeconds = (now - state.lastRequestTimestamp) / 1000\n\n if (elapsedSeconds > state.rateLimitSeconds) {\n state.lastRequestTimestamp = now\n return\n }\n\n const waitTimeSeconds = Math.ceil(state.rateLimitSeconds - elapsedSeconds)\n\n if (!state.rateLimitWait) {\n consola.warn(\n `Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`,\n )\n throw new HTTPError(\n \"Rate limit exceeded\",\n Response.json({ message: \"Rate limit exceeded\" }, { status: 429 }),\n )\n }\n\n const waitTimeMs = waitTimeSeconds * 1000\n consola.warn(\n `Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`,\n )\n await sleep(waitTimeMs)\n // eslint-disable-next-line require-atomic-updates -- serialized by rateLimitLock\n state.lastRequestTimestamp = Date.now()\n consola.info(\"Rate limit wait completed, proceeding with request\")\n } finally {\n resolve()\n }\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport { accountManager } from \"~/lib/account-manager\"\nimport {\n copilotHeaders,\n copilotBaseUrl,\n type TokenSource,\n} from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { modelRouter } from \"~/lib/model-router\"\nimport { resetConnections } from \"~/lib/proxy\"\nimport { state } from \"~/lib/state\"\nimport { refreshCopilotToken } from \"~/lib/token\"\nimport { findModel, rootCause } from \"~/lib/utils\"\n\n// ---------------------------------------------------------------------------\n// Fetch with timeout helper\n// ---------------------------------------------------------------------------\n\n/**\n * Timeout for the initial HTTP connection + headers (not the body/stream).\n * Copilot's slow models (e.g. claude-opus) can take up to ~60s to start\n * streaming, so we give 120s for the connection phase.\n */\nconst FETCH_TIMEOUT_MS = 120_000\n\n/**\n * Retry delays in ms. After the first failure the connection pool is reset\n * (see `resetConnections`), so a single retry with a fresh socket is usually\n * enough. Keeping retries minimal avoids wasting Copilot request credits\n * (billed per request).\n */\nconst RETRY_DELAYS = [2_000]\n\n/**\n * Shorter timeout for retry attempts. The first request uses the full\n * FETCH_TIMEOUT_MS (120 s) to accommodate slow models. Retries happen\n * after a connection-pool reset, so a fresh socket should connect quickly —\n * if it doesn't respond within 20 s, the upstream is genuinely down and\n * waiting longer just burns time (and possibly credits).\n */\nconst RETRY_TIMEOUT_MS = 20_000\n\n/**\n * Wrapper around `fetch()` that aborts if the server doesn't respond within\n * `timeoutMs`. The timeout only covers the period until the response headers\n * arrive – once the body starts streaming, the timeout is cleared so that\n * long SSE responses are not interrupted.\n */\nasync function fetchWithTimeout(\n url: string,\n init: RequestInit,\n timeoutMs: number = FETCH_TIMEOUT_MS,\n): Promise<Response> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n })\n return response\n } catch (error: unknown) {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new Error(`Request timed out after ${timeoutMs}ms`)\n }\n throw error\n } finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * Retry loop for fetch: retries on network errors with exponential back-off.\n *\n * Returns `{ response }` on success.\n * Throws the last network error if all retries are exhausted.\n */\nasync function fetchWithRetry(\n url: string,\n buildInit: () => RequestInit,\n): Promise<Response> {\n let lastError: unknown\n const maxAttempts = RETRY_DELAYS.length + 1 // 1 initial + retries\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n // First attempt: full timeout (slow models may need up to 120 s).\n // Retries: short timeout — after pool reset a fresh socket should\n // connect in seconds; if it doesn't, the network is truly down.\n const timeout = attempt === 0 ? FETCH_TIMEOUT_MS : RETRY_TIMEOUT_MS\n return await fetchWithTimeout(url, buildInit(), timeout)\n } catch (error: unknown) {\n lastError = error\n\n // After the first network failure, destroy all pooled connections so\n // that retries use fresh sockets instead of hitting the same stale\n // ones (which would each wait ~60 s before timing out).\n if (attempt === 0) {\n resetConnections()\n }\n\n if (attempt < maxAttempts - 1) {\n const delay = RETRY_DELAYS[attempt]\n consola.warn(\n `Network error on attempt ${attempt + 1}/${maxAttempts}, retrying in ${delay}ms:`,\n error instanceof Error ? error.message : error,\n )\n await new Promise((r) => setTimeout(r, delay))\n }\n }\n }\n\n throw lastError instanceof Error ? lastError : (\n new Error(\"Network request failed\")\n )\n}\n\n// ---------------------------------------------------------------------------\n// Streaming slot release wrapper\n// ---------------------------------------------------------------------------\n\n/**\n * Wraps an AsyncGenerator so that `releaseSlot` is called when the generator\n * finishes (return or throw), not when the outer function returns.\n */\nasync function* wrapGeneratorWithRelease(\n gen: AsyncGenerator,\n releaseSlot: () => void,\n): AsyncGenerator {\n try {\n yield* gen\n } finally {\n releaseSlot()\n }\n}\n\n// ---------------------------------------------------------------------------\n// Reasoning-effort auto-detection cache\n// ---------------------------------------------------------------------------\n\n/**\n * Models that are known NOT to support the `reasoning_effort` parameter.\n * Populated at runtime: the first time a model returns 400 with\n * \"Unrecognized request argument\", it is added here and all future\n * requests to that model skip the injection automatically.\n */\nconst reasoningUnsupportedModels = new Set<string>()\n\n/**\n * Compute an appropriate thinking_budget from model capabilities.\n * Returns undefined if the model does not support thinking.\n */\nfunction getThinkingBudget(\n model: import(\"~/services/copilot/get-models\").Model | undefined,\n): number | undefined {\n if (!model) return undefined\n const { supports, limits } = model.capabilities\n const maxBudget = supports.max_thinking_budget\n if (!maxBudget || maxBudget <= 0) return undefined\n const maxOutput = limits.max_output_tokens ?? 0\n const upperBound = Math.min(maxBudget, Math.max(maxOutput - 1, 0))\n const lowerBound = supports.min_thinking_budget ?? 1024\n return Math.max(upperBound, lowerBound)\n}\n\n/**\n * Inject thinking parameters into the payload based on model capabilities.\n *\n * Strategy (in priority order):\n * 1. If the client already set reasoning_effort or thinking_budget → keep as-is\n * 2. If model capabilities declare max_thinking_budget → inject thinking_budget\n * 3. Otherwise → inject reasoning_effort=\"high\" (works on claude-*-4.6)\n *\n * The fallback to reasoning_effort ensures thinking works even when the\n * /models endpoint doesn't expose thinking budget fields.\n */\nfunction injectThinking(\n payload: ChatCompletionsPayload,\n resolvedModel: string,\n): ChatCompletionsPayload {\n // Client already specified thinking params — respect them\n if (payload.reasoning_effort || payload.thinking_budget) {\n return payload\n }\n\n // Try model-capability-based injection (thinking_budget)\n const model = findModel(resolvedModel)\n const budget = getThinkingBudget(model)\n if (budget) {\n return { ...payload, thinking_budget: budget }\n }\n\n // Fallback: inject reasoning_effort=\"high\" (auto-detected at runtime)\n if (!reasoningUnsupportedModels.has(resolvedModel)) {\n return { ...payload, reasoning_effort: \"high\" as const }\n }\n\n return payload\n}\n\n// ---------------------------------------------------------------------------\n// Thinking injection logging (debug level)\n// ---------------------------------------------------------------------------\n\nfunction logThinkingInjection(\n original: ChatCompletionsPayload,\n injected: ChatCompletionsPayload,\n resolvedModel: string,\n) {\n if (original.reasoning_effort || original.thinking_budget) {\n consola.debug(\n `Thinking: client-specified (reasoning_effort=${original.reasoning_effort ?? \"none\"} / thinking_budget=${original.thinking_budget ?? \"none\"})`,\n )\n } else if (\n injected.thinking_budget\n && injected.thinking_budget !== original.thinking_budget\n ) {\n consola.debug(\n `Thinking: injected thinking_budget=${injected.thinking_budget} for \"${resolvedModel}\"`,\n )\n } else if (injected.reasoning_effort === \"high\") {\n consola.debug(\n `Thinking: injected reasoning_effort=high for \"${resolvedModel}\"`,\n )\n } else if (reasoningUnsupportedModels.has(resolvedModel)) {\n consola.debug(\n `Thinking: skipped — \"${resolvedModel}\" does not support reasoning`,\n )\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public entry point\n// ---------------------------------------------------------------------------\n\nexport const createChatCompletions = async (\n payload: ChatCompletionsPayload,\n) => {\n // Apply model routing\n const resolvedModel = modelRouter.resolveModel(payload.model)\n const routedPayload =\n resolvedModel !== payload.model ?\n { ...payload, model: resolvedModel }\n : payload\n if (resolvedModel !== payload.model) {\n consola.debug(`Model routed: ${payload.model} → ${resolvedModel}`)\n }\n\n // ---------------------------------------------------------------------------\n // Thinking injection: use model capabilities to decide strategy\n // ---------------------------------------------------------------------------\n const thinkingPayload = injectThinking(routedPayload, resolvedModel)\n const wasInjected =\n thinkingPayload.reasoning_effort !== routedPayload.reasoning_effort\n || thinkingPayload.thinking_budget !== routedPayload.thinking_budget\n\n logThinkingInjection(routedPayload, thinkingPayload, resolvedModel)\n\n // Acquire concurrency slot\n const releaseSlot = await modelRouter.acquireSlot(resolvedModel)\n\n try {\n const result = await dispatchRequest(thinkingPayload)\n\n // For streaming responses, wrap the generator so the slot is released\n // when the stream ends (not when this function returns).\n if (Symbol.asyncIterator in result) {\n return wrapGeneratorWithRelease(result, releaseSlot)\n }\n\n // Non-streaming: release immediately\n releaseSlot()\n return result\n } catch (error) {\n // Auto-detect models that don't support reasoning_effort:\n // On 400 \"Unrecognized request argument\", strip the parameter and retry.\n const isReasoningRejected =\n wasInjected\n && error instanceof HTTPError\n && error.response.status === 400\n && error.message.includes(\"Unrecognized request argument\")\n\n if (isReasoningRejected) {\n reasoningUnsupportedModels.add(resolvedModel)\n consola.info(\n `Model \"${resolvedModel}\" does not support reasoning_effort — disabled for future requests`,\n )\n return retryWithoutReasoning(routedPayload, releaseSlot)\n }\n\n releaseSlot()\n throw error\n }\n}\n\n/**\n * Retry a request without reasoning_effort after the model rejected it.\n * Handles slot release for both streaming and non-streaming responses.\n */\nasync function retryWithoutReasoning(\n payload: ChatCompletionsPayload,\n releaseSlot: () => void,\n) {\n try {\n const result = await dispatchRequest(payload)\n if (Symbol.asyncIterator in result) {\n return wrapGeneratorWithRelease(result, releaseSlot)\n }\n releaseSlot()\n return result\n } catch (retryError) {\n releaseSlot()\n throw retryError\n }\n}\n\n/**\n * Dispatch request to either single-account or multi-account path.\n */\nfunction dispatchRequest(payload: ChatCompletionsPayload) {\n return state.multiAccountEnabled && accountManager.hasAccounts() ?\n createWithMultiAccount(payload)\n : createWithSingleAccount(payload)\n}\n\n// ---------------------------------------------------------------------------\n// Single-account path (original behaviour, unchanged)\n// ---------------------------------------------------------------------------\n\nasync function createWithSingleAccount(payload: ChatCompletionsPayload) {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const enableVision = payload.messages.some(\n (x) =>\n typeof x.content !== \"string\"\n && x.content?.some((x) => x.type === \"image_url\"),\n )\n\n // Agent/user check for X-Initiator header\n // Determine if any message is from an agent (\"assistant\" or \"tool\")\n const isAgentCall = payload.messages.some((msg) =>\n [\"assistant\", \"tool\"].includes(msg.role),\n )\n\n // Build headers fresh each call (token may be refreshed between attempts)\n const buildHeaders = (): Record<string, string> => ({\n ...copilotHeaders(state, enableVision),\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n })\n\n consola.debug(\"Sending request to Copilot:\", {\n model: payload.model,\n endpoint: `${copilotBaseUrl(state)}/chat/completions`,\n })\n\n const url = `${copilotBaseUrl(state)}/chat/completions`\n\n // Request usage stats in the final stream chunk\n const body =\n payload.stream ?\n { ...payload, stream_options: { include_usage: true } }\n : payload\n\n const bodyString = JSON.stringify(body)\n\n // Fetch with timeout + exponential back-off retries\n let response = await fetchWithRetry(url, () => ({\n method: \"POST\",\n headers: buildHeaders(),\n body: bodyString,\n }))\n\n // On 401 (token expired), refresh the Copilot token and retry once\n if (response.status === 401) {\n consola.warn(\"Copilot token expired, refreshing and retrying...\")\n try {\n await refreshCopilotToken()\n response = await fetchWithTimeout(url, {\n method: \"POST\",\n headers: buildHeaders(),\n body: bodyString,\n })\n } catch (refreshError) {\n consola.warn(`Failed to refresh token: ${rootCause(refreshError)}`)\n consola.debug(\"Failed to refresh token:\", refreshError)\n // Fall through to the error handling below\n }\n }\n\n if (!response.ok) {\n const errorBody = await response.text()\n\n if (response.status === 400) {\n consola.warn(`400: ${errorBody}`)\n } else {\n consola.error(\"Failed to create chat completions\", {\n status: response.status,\n statusText: response.statusText,\n body: errorBody,\n })\n }\n\n throw new HTTPError(\n `Failed to create chat completions: ${response.status} ${errorBody}`,\n response,\n )\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n}\n\n// ---------------------------------------------------------------------------\n// Multi-account path (failover across accounts)\n// ---------------------------------------------------------------------------\n\n/**\n * Attempt to refresh an account's token and retry the request.\n * Returns the result on success, or null if the refresh/retry failed.\n */\nasync function tryRefreshAndRetry(\n account: import(\"~/lib/account-manager\").Account,\n payload: ChatCompletionsPayload,\n tokenSource: TokenSource,\n): Promise<AsyncGenerator | ChatCompletionResponse | null> {\n try {\n await accountManager.refreshAccountToken(account)\n // Update tokenSource with the refreshed token\n tokenSource.copilotToken = account.copilotToken\n const result = await doFetch(payload, tokenSource)\n accountManager.markAccountSuccess(account.id)\n return result\n } catch {\n accountManager.markAccountStatus(\n account.id,\n \"error\",\n \"Token refresh failed\",\n )\n return null\n }\n}\n\n/**\n * Handle an HTTP error from a multi-account request attempt.\n *\n * For 401 errors, attempts token refresh and retry.\n * Returns the successful retry result, or null if the error was handled\n * without a successful retry.\n */\nasync function handleMultiAccountHttpError(\n error: HTTPError,\n account: import(\"~/lib/account-manager\").Account,\n retryContext: { payload: ChatCompletionsPayload; tokenSource: TokenSource },\n): Promise<AsyncGenerator | ChatCompletionResponse | null> {\n switch (error.response.status) {\n case 401: {\n consola.warn(`Account ${account.label}: 401, refreshing token...`)\n return tryRefreshAndRetry(\n account,\n retryContext.payload,\n retryContext.tokenSource,\n )\n }\n case 403: {\n accountManager.markAccountStatus(account.id, \"banned\", \"403 Forbidden\")\n return null\n }\n case 429: {\n accountManager.markAccountStatus(\n account.id,\n \"rate_limited\",\n \"429 Rate limited\",\n )\n return null\n }\n default: {\n // 5xx: upstream error — don't retry to avoid wasting request credits.\n // doFetch already retried once via fetchWithRetry; a second round\n // is unlikely to help and doubles the credit cost.\n if (error.response.status >= 500) {\n accountManager.markAccountStatus(\n account.id,\n \"error\",\n `HTTP ${error.response.status}`,\n )\n return null\n }\n accountManager.markAccountStatus(\n account.id,\n \"error\",\n `HTTP ${error.response.status}`,\n )\n return null\n }\n }\n}\n\nasync function createWithMultiAccount(payload: ChatCompletionsPayload) {\n const triedAccountIds = new Set<string>()\n let lastError: unknown\n\n // Try up to 3 different accounts\n for (let attempt = 0; attempt < 3; attempt++) {\n const account = accountManager.getActiveAccount()\n if (!account || triedAccountIds.has(account.id)) {\n // No more untried accounts available\n break\n }\n triedAccountIds.add(account.id)\n\n if (!account.copilotToken) {\n // Token may be missing after restart — try to refresh before giving up\n consola.info(\n `Account ${account.label} has no copilot token, refreshing...`,\n )\n await accountManager.refreshAccountToken(account)\n\n if (!account.copilotToken) {\n consola.warn(`Account ${account.label}: token refresh failed, skipping`)\n accountManager.markAccountStatus(\n account.id,\n \"error\",\n \"No copilot token\",\n )\n continue\n }\n }\n\n // Build a TokenSource from the account\n const tokenSource: TokenSource = {\n copilotToken: account.copilotToken,\n copilotApiEndpoint: account.copilotApiEndpoint,\n accountType: account.accountType,\n githubToken: account.githubToken,\n vsCodeVersion: state.vsCodeVersion,\n }\n\n try {\n const result = await doFetch(payload, tokenSource)\n accountManager.markAccountSuccess(account.id)\n return result\n } catch (error) {\n lastError = error\n\n if (error instanceof HTTPError) {\n const retryResult = await handleMultiAccountHttpError(error, account, {\n payload,\n tokenSource,\n })\n if (retryResult) return retryResult\n } else {\n // Network error or other\n accountManager.markAccountStatus(\n account.id,\n \"error\",\n (error as Error).message,\n )\n }\n\n consola.warn(\n `Account ${account.label} failed (attempt ${attempt + 1}), trying next...`,\n )\n }\n }\n\n // All accounts exhausted\n if (lastError)\n throw lastError instanceof Error ? lastError : (\n new Error(\"Network request failed\")\n )\n throw new Error(\"No available accounts\")\n}\n\n// ---------------------------------------------------------------------------\n// Shared fetch helper (used by multi-account path)\n// ---------------------------------------------------------------------------\n\n/**\n * Execute the actual HTTP request to the Copilot chat/completions endpoint.\n *\n * This is intentionally a thin wrapper so that `createWithMultiAccount` can\n * call it with different `TokenSource` objects while keeping all the header\n * construction / retry / error‐surfacing logic in one place.\n */\nasync function doFetch(\n payload: ChatCompletionsPayload,\n source: TokenSource,\n): Promise<AsyncGenerator | ChatCompletionResponse> {\n const enableVision = payload.messages.some(\n (x) =>\n typeof x.content !== \"string\"\n && x.content?.some((x) => x.type === \"image_url\"),\n )\n\n const isAgentCall = payload.messages.some((msg) =>\n [\"assistant\", \"tool\"].includes(msg.role),\n )\n\n const buildHeaders = (): Record<string, string> => ({\n ...copilotHeaders(source, enableVision),\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n })\n\n const url = `${copilotBaseUrl(source)}/chat/completions`\n\n consola.debug(\"Sending request to Copilot (multi-account):\", {\n model: payload.model,\n endpoint: url,\n })\n\n const body =\n payload.stream ?\n { ...payload, stream_options: { include_usage: true } }\n : payload\n\n const bodyString = JSON.stringify(body)\n\n // Fetch with timeout + exponential back-off retries\n const response = await fetchWithRetry(url, () => ({\n method: \"POST\",\n headers: buildHeaders(),\n body: bodyString,\n }))\n\n if (!response.ok) {\n const errorBody = await response.text()\n\n if (response.status === 400) {\n consola.warn(`400: ${errorBody}`)\n } else {\n consola.error(\"Failed to create chat completions\", {\n status: response.status,\n statusText: response.statusText,\n body: errorBody,\n })\n }\n\n throw new HTTPError(\n `Failed to create chat completions: ${response.status} ${errorBody}`,\n response,\n )\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n}\n\n// ===========================================================================\n// Types (unchanged)\n// ===========================================================================\n\n// Streaming types\n\nexport interface ChatCompletionChunk {\n id: string\n object: \"chat.completion.chunk\"\n created: number\n model: string\n choices: Array<Choice>\n system_fingerprint?: string\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n prompt_tokens_details?: {\n cached_tokens: number\n }\n completion_tokens_details?: {\n accepted_prediction_tokens: number\n rejected_prediction_tokens: number\n }\n }\n}\n\ninterface Delta {\n content?: string | null\n reasoning_content?: string | null\n reasoning_text?: string | null\n role?: \"user\" | \"assistant\" | \"system\" | \"tool\"\n tool_calls?: Array<{\n index: number\n id?: string\n type?: \"function\"\n function?: {\n name?: string\n arguments?: string\n }\n }>\n}\n\ninterface Choice {\n index: number\n delta: Delta\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null\n logprobs: object | null\n}\n\n// Non-streaming types\n\nexport interface ChatCompletionResponse {\n id: string\n object: \"chat.completion\"\n created: number\n model: string\n choices: Array<ChoiceNonStreaming>\n system_fingerprint?: string\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n prompt_tokens_details?: {\n cached_tokens: number\n }\n }\n}\n\ninterface ResponseMessage {\n role: \"assistant\"\n content: string | null\n reasoning_content?: string | null\n reasoning_text?: string | null\n tool_calls?: Array<ToolCall>\n}\n\ninterface ChoiceNonStreaming {\n index: number\n message: ResponseMessage\n logprobs: object | null\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\"\n}\n\n// Payload types\n\nexport interface ChatCompletionsPayload {\n messages: Array<Message>\n model: string\n temperature?: number | null\n top_p?: number | null\n max_tokens?: number | null\n stop?: string | Array<string> | null\n n?: number | null\n stream?: boolean | null\n\n frequency_penalty?: number | null\n presence_penalty?: number | null\n logit_bias?: Record<string, number> | null\n logprobs?: boolean | null\n response_format?: { type: \"json_object\" } | null\n seed?: number | null\n tools?: Array<Tool> | null\n tool_choice?:\n | \"none\"\n | \"auto\"\n | \"required\"\n | { type: \"function\"; function: { name: string } }\n | null\n user?: string | null\n\n // Anthropic thinking parameter — passed through transparently to Copilot\n thinking?: {\n type: \"enabled\"\n budget_tokens?: number\n }\n\n // OpenAI reasoning_effort parameter — triggers Copilot thinking mode\n reasoning_effort?: \"low\" | \"medium\" | \"high\" | null\n\n // Copilot thinking budget — number of tokens allocated for thinking\n thinking_budget?: number | null\n}\n\nexport interface Tool {\n type: \"function\"\n function: {\n name: string\n description?: string\n parameters: Record<string, unknown>\n }\n}\n\nexport interface Message {\n role: \"user\" | \"assistant\" | \"system\" | \"tool\" | \"developer\"\n content: string | Array<ContentPart> | null\n\n name?: string\n tool_calls?: Array<ToolCall>\n tool_call_id?: string\n}\n\nexport interface ToolCall {\n id: string\n type: \"function\"\n function: {\n name: string\n arguments: string\n }\n}\n\nexport type ContentPart = TextPart | ImagePart\n\nexport interface TextPart {\n type: \"text\"\n text: string\n}\n\nexport interface ImagePart {\n type: \"image_url\"\n image_url: {\n url: string\n detail?: \"low\" | \"high\" | \"auto\"\n }\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\nimport { streamSSE, type SSEMessage } from \"hono/streaming\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { state } from \"~/lib/state\"\nimport { findModel, isNullish } from \"~/lib/utils\"\nimport {\n createChatCompletions,\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n} from \"~/services/copilot/create-chat-completions\"\n\n/**\n * Set max_tokens from model limits if not already provided in the payload.\n */\nfunction applyMaxTokens(\n payload: ChatCompletionsPayload,\n): ChatCompletionsPayload {\n if (!isNullish(payload.max_tokens)) {\n return payload\n }\n\n const selectedModel = findModel(payload.model)\n if (!selectedModel) {\n return payload\n }\n\n const maxTokens = selectedModel.capabilities.limits.max_output_tokens\n if (maxTokens) {\n consola.debug(\"Set max_tokens to:\", maxTokens)\n return { ...payload, max_tokens: maxTokens }\n }\n\n return payload\n}\n\nexport async function handleCompletion(c: Context) {\n await checkRateLimit(state)\n\n const rawPayload = await c.req.json<ChatCompletionsPayload>()\n consola.debug(\"Request payload:\", JSON.stringify(rawPayload).slice(-400))\n\n const payload = applyMaxTokens(rawPayload)\n\n if (state.manualApprove) await awaitApproval()\n\n const response = await createChatCompletions(payload)\n\n if (isNonStreaming(response)) {\n // Map reasoning_text to reasoning_content for OpenAI-compatible clients\n const mappedResponse = mapReasoningFields(response)\n consola.debug(\"Non-streaming response:\", JSON.stringify(mappedResponse))\n return c.json(mappedResponse)\n }\n\n consola.debug(\"Streaming response\")\n return streamSSE(c, async (stream) => {\n try {\n for await (const chunk of response) {\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\n await stream.writeSSE(chunk as SSEMessage)\n }\n } catch (error) {\n const message = (error as Error).message || String(error)\n consola.warn(`SSE stream interrupted: ${message}`)\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n\n/**\n * Map `reasoning_text` (Copilot-specific) to `reasoning_content` (OpenAI-compatible)\n * so that downstream OpenAI-compatible clients can consume the reasoning output.\n */\nfunction mapReasoningFields(\n response: ChatCompletionResponse,\n): ChatCompletionResponse {\n const hasReasoningText = response.choices.some(\n (c) => (c.message as Record<string, unknown>).reasoning_text,\n )\n if (!hasReasoningText) return response\n\n return {\n ...response,\n choices: response.choices.map((choice) => {\n const msg = choice.message as Record<string, unknown>\n if (!msg.reasoning_text) return choice\n return {\n ...choice,\n message: {\n ...choice.message,\n reasoning_content:\n (msg.reasoning_text as string) || choice.message.reasoning_content,\n },\n }\n }),\n }\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCompletion } from \"./handler\"\n\nexport const completionRoutes = new Hono()\n\ncompletionRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { accountManager } from \"~/lib/account-manager\"\nimport {\n copilotHeaders,\n copilotBaseUrl,\n type TokenSource,\n} from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const createEmbeddings = async (payload: EmbeddingRequest) => {\n // In multi-account mode, use the active account's token\n let source: TokenSource = state\n if (state.multiAccountEnabled && accountManager.hasAccounts()) {\n const account = accountManager.getActiveAccount()\n if (account?.copilotToken) {\n source = {\n copilotToken: account.copilotToken,\n copilotApiEndpoint: account.copilotApiEndpoint,\n accountType: account.accountType,\n githubToken: account.githubToken,\n vsCodeVersion: state.vsCodeVersion,\n }\n }\n }\n\n if (!source.copilotToken) throw new Error(\"Copilot token not found\")\n\n const response = await fetch(`${copilotBaseUrl(source)}/embeddings`, {\n method: \"POST\",\n headers: copilotHeaders(source),\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to create embeddings\", response)\n\n return (await response.json()) as EmbeddingResponse\n}\n\nexport interface EmbeddingRequest {\n input: string | Array<string>\n model: string\n}\n\nexport interface Embedding {\n object: string\n embedding: Array<number>\n index: number\n}\n\nexport interface EmbeddingResponse {\n object: string\n data: Array<Embedding>\n model: string\n usage: {\n prompt_tokens: number\n total_tokens: number\n }\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport {\n createEmbeddings,\n type EmbeddingRequest,\n} from \"~/services/copilot/create-embeddings\"\n\nexport const embeddingRoutes = new Hono()\n\nembeddingRoutes.post(\"/\", async (c) => {\n try {\n const paylod = await c.req.json<EmbeddingRequest>()\n const response = await createEmbeddings(paylod)\n\n return c.json(response)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import type {\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\nimport type { Model } from \"~/services/copilot/get-models\"\n\n// Encoder type mapping\nconst ENCODING_MAP = {\n o200k_base: () => import(\"gpt-tokenizer/encoding/o200k_base\"),\n cl100k_base: () => import(\"gpt-tokenizer/encoding/cl100k_base\"),\n p50k_base: () => import(\"gpt-tokenizer/encoding/p50k_base\"),\n p50k_edit: () => import(\"gpt-tokenizer/encoding/p50k_edit\"),\n r50k_base: () => import(\"gpt-tokenizer/encoding/r50k_base\"),\n} as const\n\ntype SupportedEncoding = keyof typeof ENCODING_MAP\n\n// Define encoder interface\ninterface Encoder {\n encode: (text: string) => Array<number>\n}\n\n// Cache loaded encoders to avoid repeated imports\nconst encodingCache = new Map<string, Encoder>()\n\n/**\n * Calculate tokens for tool calls\n */\nconst calculateToolCallsTokens = (\n toolCalls: Array<ToolCall>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = 0\n for (const toolCall of toolCalls) {\n tokens += constants.funcInit\n tokens += encoder.encode(JSON.stringify(toolCall)).length\n }\n tokens += constants.funcEnd\n return tokens\n}\n\n/**\n * Calculate tokens for content parts\n */\nconst calculateContentPartsTokens = (\n contentParts: Array<ContentPart>,\n encoder: Encoder,\n): number => {\n let tokens = 0\n for (const part of contentParts) {\n if (part.type === \"image_url\") {\n tokens += encoder.encode(part.image_url.url).length + 85\n } else if (part.text) {\n tokens += encoder.encode(part.text).length\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens for a single message\n */\nconst calculateMessageTokens = (\n message: Message,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n const tokensPerMessage = 3\n const tokensPerName = 1\n let tokens = tokensPerMessage\n for (const [key, value] of Object.entries(message)) {\n if (typeof value === \"string\") {\n tokens += encoder.encode(value).length\n }\n if (key === \"name\") {\n tokens += tokensPerName\n }\n if (key === \"tool_calls\") {\n tokens += calculateToolCallsTokens(\n value as Array<ToolCall>,\n encoder,\n constants,\n )\n }\n if (key === \"content\" && Array.isArray(value)) {\n tokens += calculateContentPartsTokens(\n value as Array<ContentPart>,\n encoder,\n )\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens using custom algorithm\n */\nconst calculateTokens = (\n messages: Array<Message>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (messages.length === 0) {\n return 0\n }\n let numTokens = 0\n for (const message of messages) {\n numTokens += calculateMessageTokens(message, encoder, constants)\n }\n // every reply is primed with <|start|>assistant<|message|>\n numTokens += 3\n return numTokens\n}\n\n/**\n * Get the corresponding encoder module based on encoding type\n */\nconst getEncodeChatFunction = async (encoding: string): Promise<Encoder> => {\n if (encodingCache.has(encoding)) {\n const cached = encodingCache.get(encoding)\n if (cached) {\n return cached\n }\n }\n\n const supportedEncoding = encoding as SupportedEncoding\n if (!(supportedEncoding in ENCODING_MAP)) {\n const fallbackModule = (await ENCODING_MAP.o200k_base()) as Encoder\n encodingCache.set(encoding, fallbackModule)\n return fallbackModule\n }\n\n const encodingModule = (await ENCODING_MAP[supportedEncoding]()) as Encoder\n encodingCache.set(encoding, encodingModule)\n return encodingModule\n}\n\n/**\n * Get tokenizer type from model information\n */\nexport const getTokenizerFromModel = (model: Model): string => {\n return model.capabilities.tokenizer || \"o200k_base\"\n}\n\n/**\n * Get model-specific constants for token calculation\n */\nconst getModelConstants = (model: Model) => {\n return model.id === \"gpt-3.5-turbo\" || model.id === \"gpt-4\" ?\n {\n funcInit: 10,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n : {\n funcInit: 7,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n}\n\n/**\n * Calculate tokens for a single parameter\n */\nconst calculateParameterTokens = (\n key: string,\n prop: unknown,\n context: {\n encoder: Encoder\n constants: ReturnType<typeof getModelConstants>\n },\n): number => {\n const { encoder, constants } = context\n let tokens = constants.propKey\n\n // Early return if prop is not an object\n if (typeof prop !== \"object\" || prop === null) {\n return tokens\n }\n\n // Type assertion for parameter properties\n const param = prop as {\n type?: string\n description?: string\n enum?: Array<unknown>\n [key: string]: unknown\n }\n\n const paramName = key\n const paramType = param.type || \"string\"\n let paramDesc = param.description || \"\"\n\n // Handle enum values\n if (param.enum && Array.isArray(param.enum)) {\n tokens += constants.enumInit\n for (const item of param.enum) {\n tokens += constants.enumItem\n tokens += encoder.encode(String(item)).length\n }\n }\n\n // Clean up description\n if (paramDesc.endsWith(\".\")) {\n paramDesc = paramDesc.slice(0, -1)\n }\n\n // Encode the main parameter line\n const line = `${paramName}:${paramType}:${paramDesc}`\n tokens += encoder.encode(line).length\n\n // Handle additional properties (excluding standard ones)\n const excludedKeys = new Set([\"type\", \"description\", \"enum\"])\n for (const propertyName of Object.keys(param)) {\n if (!excludedKeys.has(propertyName)) {\n const propertyValue = param[propertyName]\n const propertyText =\n typeof propertyValue === \"string\" ? propertyValue : (\n JSON.stringify(propertyValue)\n )\n tokens += encoder.encode(`${propertyName}:${propertyText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for function parameters\n */\nconst calculateParametersTokens = (\n parameters: unknown,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (!parameters || typeof parameters !== \"object\") {\n return 0\n }\n\n const params = parameters as Record<string, unknown>\n let tokens = 0\n\n for (const [key, value] of Object.entries(params)) {\n if (key === \"properties\") {\n const properties = value as Record<string, unknown>\n if (Object.keys(properties).length > 0) {\n tokens += constants.propInit\n for (const propKey of Object.keys(properties)) {\n tokens += calculateParameterTokens(propKey, properties[propKey], {\n encoder,\n constants,\n })\n }\n }\n } else {\n const paramText =\n typeof value === \"string\" ? value : JSON.stringify(value)\n tokens += encoder.encode(`${key}:${paramText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for a single tool\n */\nconst calculateToolTokens = (\n tool: Tool,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = constants.funcInit\n const func = tool.function\n const fName = func.name\n let fDesc = func.description || \"\"\n if (fDesc.endsWith(\".\")) {\n fDesc = fDesc.slice(0, -1)\n }\n const line = fName + \":\" + fDesc\n tokens += encoder.encode(line).length\n if (\n typeof func.parameters === \"object\" // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n && func.parameters !== null\n ) {\n tokens += calculateParametersTokens(func.parameters, encoder, constants)\n }\n return tokens\n}\n\n/**\n * Calculate token count for tools based on model\n */\nexport const numTokensForTools = (\n tools: Array<Tool>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let funcTokenCount = 0\n for (const tool of tools) {\n funcTokenCount += calculateToolTokens(tool, encoder, constants)\n }\n funcTokenCount += constants.funcEnd\n return funcTokenCount\n}\n\n/**\n * Calculate the token count of messages, supporting multiple GPT encoders\n */\nexport const getTokenCount = async (\n payload: ChatCompletionsPayload,\n model: Model,\n): Promise<{ input: number; output: number }> => {\n // Get tokenizer string\n const tokenizer = getTokenizerFromModel(model)\n\n // Get corresponding encoder module\n const encoder = await getEncodeChatFunction(tokenizer)\n\n const constants = getModelConstants(model)\n\n // All messages in the payload are prompt tokens (the full conversation context).\n // \"Output\" tokens are only the NEW response from the model, not historical assistant turns.\n let inputTokens = calculateTokens(payload.messages, encoder, constants)\n if (payload.tools && payload.tools.length > 0) {\n inputTokens += numTokensForTools(payload.tools, encoder, constants)\n }\n\n return {\n input: inputTokens,\n output: 0,\n }\n}\n","import { type AnthropicResponse } from \"./anthropic-types\"\n\nexport function mapOpenAIStopReasonToAnthropic(\n finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null,\n): AnthropicResponse[\"stop_reason\"] {\n if (finishReason === null) {\n return null\n }\n const stopReasonMap = {\n stop: \"end_turn\",\n length: \"max_tokens\",\n tool_calls: \"tool_use\",\n content_filter: \"end_turn\",\n } as const\n return stopReasonMap[finishReason]\n}\n","import { state } from \"~/lib/state\"\nimport {\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n type ContentPart,\n type Message,\n type TextPart,\n type Tool,\n type ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicAssistantContentBlock,\n type AnthropicAssistantMessage,\n type AnthropicMessage,\n type AnthropicMessagesPayload,\n type AnthropicResponse,\n type AnthropicTextBlock,\n type AnthropicThinkingBlock,\n type AnthropicTool,\n type AnthropicToolResultBlock,\n type AnthropicToolUseBlock,\n type AnthropicUserContentBlock,\n type AnthropicUserMessage,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\n// Payload translation\n\nexport function translateToOpenAI(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload {\n return {\n model: translateModelName(payload.model),\n messages: translateAnthropicMessagesToOpenAI(\n payload.messages,\n payload.system,\n ),\n max_tokens: payload.max_tokens,\n stop: payload.stop_sequences,\n stream: payload.stream,\n temperature: payload.temperature,\n top_p: payload.top_p,\n user: payload.metadata?.user_id,\n tools: translateAnthropicToolsToOpenAI(payload.tools),\n tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),\n // Pass through thinking parameter as-is to Copilot\n ...(payload.thinking && { thinking: payload.thinking }),\n // Convert Anthropic thinking to reasoning_effort=high for Copilot\n ...(payload.thinking?.type === \"enabled\" && {\n reasoning_effort: \"high\" as const,\n }),\n // Convert Anthropic thinking budget_tokens to Copilot thinking_budget\n ...(payload.thinking?.budget_tokens && {\n thinking_budget: payload.thinking.budget_tokens,\n }),\n }\n}\n\nexport function translateModelName(model: string): string {\n // Claude Code 发送的模型名称可能与 GitHub Copilot 支持的不一致\n // 需要智能匹配到 Copilot 实际支持的模型\n\n const supportedModels = state.models?.data.map((m) => m.id) ?? []\n\n // 1. 直接匹配\n if (supportedModels.includes(model)) {\n return model\n }\n\n // 2. 移除日期后缀后匹配 (claude-opus-4-5-20251101 -> claude-opus-4-5)\n const modelBase = model.replace(/-\\d{8}$/, \"\")\n if (supportedModels.includes(modelBase)) {\n return modelBase\n }\n\n // 3. 尝试 4-5 -> 4.5 格式转换 (claude-opus-4-5 -> claude-opus-4.5)\n const modelWithDot = modelBase.replace(/-(\\d+)-(\\d+)$/, \"-$1.$2\")\n if (supportedModels.includes(modelWithDot)) {\n return modelWithDot\n }\n\n // 4. 尝试 4.5 -> 4-5 格式转换 (claude-opus-4.5 -> claude-opus-4-5)\n const modelWithDash = model.replace(/(\\d+)\\.(\\d+)/, \"$1-$2\")\n if (supportedModels.includes(modelWithDash)) {\n return modelWithDash\n }\n\n // 5. Anthropic 旧格式到 Copilot 新格式映射\n // claude-3-5-sonnet-xxx -> claude-sonnet-4.5\n // claude-3-opus-xxx -> claude-opus-4.5\n // claude-3-5-haiku-xxx -> claude-haiku-4.5\n const oldFormatMapping: Record<string, string> = {\n \"claude-3-5-sonnet\": \"claude-sonnet-4.5\",\n \"claude-3-sonnet\": \"claude-sonnet-4\",\n \"claude-3-5-opus\": \"claude-opus-4.5\",\n \"claude-3-opus\": \"claude-opus-4.5\",\n \"claude-3-5-haiku\": \"claude-haiku-4.5\",\n \"claude-3-haiku\": \"claude-haiku-4.5\",\n }\n\n for (const [oldFormat, newFormat] of Object.entries(oldFormatMapping)) {\n if (\n modelBase.startsWith(oldFormat)\n && supportedModels.includes(newFormat)\n ) {\n return newFormat\n }\n }\n\n // 6. 如果都找不到,返回原始模型名\n return model\n}\n\nfunction translateAnthropicMessagesToOpenAI(\n anthropicMessages: Array<AnthropicMessage>,\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n const systemMessages = handleSystemPrompt(system)\n\n const otherMessages = anthropicMessages.flatMap((message) =>\n message.role === \"user\" ?\n handleUserMessage(message)\n : handleAssistantMessage(message),\n )\n\n return [...systemMessages, ...otherMessages]\n}\n\nfunction handleSystemPrompt(\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n if (!system) {\n return []\n }\n\n if (typeof system === \"string\") {\n return [{ role: \"system\", content: system }]\n } else {\n const systemText = system.map((block) => block.text).join(\"\\n\\n\")\n return [{ role: \"system\", content: systemText }]\n }\n}\n\nfunction handleUserMessage(message: AnthropicUserMessage): Array<Message> {\n const newMessages: Array<Message> = []\n\n if (Array.isArray(message.content)) {\n const toolResultBlocks = message.content.filter(\n (block): block is AnthropicToolResultBlock =>\n block.type === \"tool_result\",\n )\n const otherBlocks = message.content.filter(\n (block) => block.type !== \"tool_result\",\n )\n\n // Tool results must come first to maintain protocol: tool_use -> tool_result -> user\n for (const block of toolResultBlocks) {\n newMessages.push({\n role: \"tool\",\n tool_call_id: block.tool_use_id,\n content: mapContent(block.content),\n })\n }\n\n if (otherBlocks.length > 0) {\n newMessages.push({\n role: \"user\",\n content: mapContent(otherBlocks),\n })\n }\n } else {\n newMessages.push({\n role: \"user\",\n content: mapContent(message.content),\n })\n }\n\n return newMessages\n}\n\nfunction handleAssistantMessage(\n message: AnthropicAssistantMessage,\n): Array<Message> {\n if (!Array.isArray(message.content)) {\n return [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n }\n\n const toolUseBlocks = message.content.filter(\n (block): block is AnthropicToolUseBlock => block.type === \"tool_use\",\n )\n\n const textBlocks = message.content.filter(\n (block): block is AnthropicTextBlock => block.type === \"text\",\n )\n\n const thinkingBlocks = message.content.filter(\n (block): block is AnthropicThinkingBlock => block.type === \"thinking\",\n )\n\n // Combine text and thinking blocks, as OpenAI doesn't have separate thinking blocks\n const allTextContent = [\n ...textBlocks.map((b) => b.text),\n ...thinkingBlocks.map((b) => b.thinking),\n ].join(\"\\n\\n\")\n\n return toolUseBlocks.length > 0 ?\n [\n {\n role: \"assistant\",\n content: allTextContent || null,\n tool_calls: toolUseBlocks.map((toolUse) => ({\n id: toolUse.id,\n type: \"function\",\n function: {\n name: toolUse.name,\n arguments: JSON.stringify(toolUse.input),\n },\n })),\n },\n ]\n : [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n}\n\nfunction mapContent(\n content:\n | string\n | Array<AnthropicUserContentBlock | AnthropicAssistantContentBlock>,\n): string | Array<ContentPart> | null {\n if (typeof content === \"string\") {\n return content\n }\n if (!Array.isArray(content)) {\n return null\n }\n\n const hasImage = content.some((block) => block.type === \"image\")\n if (!hasImage) {\n return content\n .filter(\n (block): block is AnthropicTextBlock | AnthropicThinkingBlock =>\n block.type === \"text\" || block.type === \"thinking\",\n )\n .map((block) => (block.type === \"text\" ? block.text : block.thinking))\n .join(\"\\n\\n\")\n }\n\n const contentParts: Array<ContentPart> = []\n for (const block of content) {\n switch (block.type) {\n case \"text\": {\n contentParts.push({ type: \"text\", text: block.text })\n\n break\n }\n case \"thinking\": {\n contentParts.push({ type: \"text\", text: block.thinking })\n\n break\n }\n case \"image\": {\n contentParts.push({\n type: \"image_url\",\n image_url: {\n url: `data:${block.source.media_type};base64,${block.source.data}`,\n },\n })\n\n break\n }\n // No default\n }\n }\n return contentParts\n}\n\nfunction translateAnthropicToolsToOpenAI(\n anthropicTools: Array<AnthropicTool> | undefined,\n): Array<Tool> | undefined {\n if (!anthropicTools) {\n return undefined\n }\n return anthropicTools.map((tool) => ({\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.input_schema,\n },\n }))\n}\n\nfunction translateAnthropicToolChoiceToOpenAI(\n anthropicToolChoice: AnthropicMessagesPayload[\"tool_choice\"],\n): ChatCompletionsPayload[\"tool_choice\"] {\n if (!anthropicToolChoice) {\n return undefined\n }\n\n switch (anthropicToolChoice.type) {\n case \"auto\": {\n return \"auto\"\n }\n case \"any\": {\n return \"required\"\n }\n case \"tool\": {\n if (anthropicToolChoice.name) {\n return {\n type: \"function\",\n function: { name: anthropicToolChoice.name },\n }\n }\n return undefined\n }\n case \"none\": {\n return \"none\"\n }\n default: {\n return undefined\n }\n }\n}\n\n// Response translation\n\n// eslint-disable-next-line complexity\nexport function translateToAnthropic(\n response: ChatCompletionResponse,\n): AnthropicResponse {\n // Merge content from all choices\n const allThinkingBlocks: Array<AnthropicThinkingBlock> = []\n const allTextBlocks: Array<AnthropicTextBlock> = []\n const allToolUseBlocks: Array<AnthropicToolUseBlock> = []\n let stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null =\n null // default\n stopReason = response.choices[0]?.finish_reason ?? stopReason\n\n // Process all choices to extract thinking, text and tool use blocks\n for (const choice of response.choices) {\n const thinkingBlocks = getAnthropicThinkingBlocks(\n choice.message.reasoning_content ?? choice.message.reasoning_text,\n )\n const textBlocks = getAnthropicTextBlocks(choice.message.content)\n const toolUseBlocks = getAnthropicToolUseBlocks(choice.message.tool_calls)\n\n allThinkingBlocks.push(...thinkingBlocks)\n allTextBlocks.push(...textBlocks)\n allToolUseBlocks.push(...toolUseBlocks)\n\n // Use the finish_reason from the first choice, or prioritize tool_calls\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\n stopReason = choice.finish_reason\n }\n }\n\n return {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n model: response.model,\n // Anthropic convention: thinking blocks come first, then text, then tool_use\n content: [...allThinkingBlocks, ...allTextBlocks, ...allToolUseBlocks],\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\n stop_sequence: null,\n usage: {\n input_tokens:\n (response.usage?.prompt_tokens ?? 0)\n - (response.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: response.usage?.completion_tokens ?? 0,\n ...(response.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n response.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n }\n}\n\nfunction getAnthropicThinkingBlocks(\n reasoningContent: string | null | undefined,\n): Array<AnthropicThinkingBlock> {\n if (!reasoningContent) {\n return []\n }\n return [{ type: \"thinking\", thinking: reasoningContent }]\n}\n\nfunction getAnthropicTextBlocks(\n messageContent: Message[\"content\"],\n): Array<AnthropicTextBlock> {\n if (typeof messageContent === \"string\") {\n return [{ type: \"text\", text: messageContent }]\n }\n\n if (Array.isArray(messageContent)) {\n return messageContent\n .filter((part): part is TextPart => part.type === \"text\")\n .map((part) => ({ type: \"text\", text: part.text }))\n }\n\n return []\n}\n\nfunction getAnthropicToolUseBlocks(\n toolCalls: Array<ToolCall> | undefined,\n): Array<AnthropicToolUseBlock> {\n if (!toolCalls) {\n return []\n }\n return toolCalls.map((toolCall) => ({\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: (() => {\n try {\n return JSON.parse(toolCall.function.arguments) as Record<\n string,\n unknown\n >\n } catch {\n return {}\n }\n })(),\n }))\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport { getTokenCount } from \"~/lib/tokenizer\"\nimport { findModel, rootCause } from \"~/lib/utils\"\n\nimport { type AnthropicMessagesPayload } from \"./anthropic-types\"\nimport { translateModelName, translateToOpenAI } from \"./non-stream-translation\"\n\n/**\n * Handles token counting for Anthropic messages.\n *\n * Uses multi-strategy model matching:\n * 1. findModel(translatedName) — translated Copilot name with format variants\n * 2. findModel(originalName) — original Anthropic name with format variants\n */\nexport async function handleCountTokens(c: Context) {\n try {\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n // Multi-strategy model matching:\n // Try translated name first (most likely to match Copilot model IDs),\n // then fall back to original Anthropic name with format variants\n const translatedModelName = translateModelName(anthropicPayload.model)\n const selectedModel =\n findModel(translatedModelName) ?? findModel(anthropicPayload.model)\n\n if (!selectedModel) {\n consola.warn(\n `Model not found for \"${anthropicPayload.model}\" (translated: \"${translatedModelName}\"), returning default token count`,\n )\n return c.json({\n input_tokens: 1,\n })\n }\n\n const tokenCount = await getTokenCount(openAIPayload, selectedModel)\n\n if (anthropicPayload.tools && anthropicPayload.tools.length > 0) {\n let mcpToolExist = false\n if (anthropicBeta?.startsWith(\"claude-code\")) {\n mcpToolExist = anthropicPayload.tools.some((tool) =>\n tool.name.startsWith(\"mcp__\"),\n )\n }\n if (!mcpToolExist) {\n if (anthropicPayload.model.startsWith(\"claude\")) {\n // https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview#pricing\n tokenCount.input = tokenCount.input + 346\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n tokenCount.input = tokenCount.input + 480\n }\n }\n }\n\n let finalTokenCount = tokenCount.input + tokenCount.output\n if (anthropicPayload.model.startsWith(\"claude\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.15)\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.03)\n }\n\n console.log(\"Token count:\", finalTokenCount)\n\n return c.json({\n input_tokens: finalTokenCount,\n })\n } catch (error) {\n consola.warn(`Error counting tokens: ${rootCause(error)}`)\n consola.debug(\"Error counting tokens:\", error)\n return c.json({\n input_tokens: 1,\n })\n }\n}\n","import { type ChatCompletionChunk } from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicStreamEventData,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\nfunction isToolBlockOpen(state: AnthropicStreamState): boolean {\n if (!state.contentBlockOpen) {\n return false\n }\n // Check if the current block index corresponds to any known tool call\n return Object.values(state.toolCalls).some(\n (tc) => tc.anthropicBlockIndex === state.contentBlockIndex,\n )\n}\n\n// eslint-disable-next-line max-lines-per-function, complexity\nexport function translateChunkToAnthropicEvents(\n chunk: ChatCompletionChunk,\n state: AnthropicStreamState,\n): Array<AnthropicStreamEventData> {\n const events: Array<AnthropicStreamEventData> = []\n\n if (chunk.choices.length === 0) {\n return events\n }\n\n const choice = chunk.choices[0]\n const { delta } = choice\n\n if (!state.messageStartSent) {\n events.push({\n type: \"message_start\",\n message: {\n id: chunk.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: chunk.model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens:\n (chunk.usage?.prompt_tokens ?? 0)\n - (chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: 0, // Will be updated in message_delta when finished\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n })\n state.messageStartSent = true\n }\n\n const reasoningContent = delta.reasoning_content ?? delta.reasoning_text\n if (reasoningContent) {\n // Close any non-thinking block that might be open\n if (state.contentBlockOpen && !state.thinkingBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n if (!state.thinkingBlockOpen) {\n // Start a new thinking block\n events.push({\n type: \"content_block_start\",\n index: state.contentBlockIndex,\n content_block: {\n type: \"thinking\",\n thinking: \"\",\n },\n })\n state.contentBlockOpen = true\n state.thinkingBlockOpen = true\n }\n\n events.push({\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"thinking_delta\",\n thinking: reasoningContent,\n },\n })\n }\n\n if (delta.content) {\n // Close thinking block if transitioning from thinking to text\n if (state.thinkingBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n state.thinkingBlockOpen = false\n }\n\n if (isToolBlockOpen(state)) {\n // A tool block was open, so close it before starting a text block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n if (!state.contentBlockOpen) {\n events.push({\n type: \"content_block_start\",\n index: state.contentBlockIndex,\n content_block: {\n type: \"text\",\n text: \"\",\n },\n })\n state.contentBlockOpen = true\n }\n\n events.push({\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"text_delta\",\n text: delta.content,\n },\n })\n }\n\n if (delta.tool_calls) {\n // Close thinking block if transitioning from thinking to tool calls\n if (state.thinkingBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n state.thinkingBlockOpen = false\n }\n\n for (const toolCall of delta.tool_calls) {\n if (toolCall.id && toolCall.function?.name) {\n // New tool call starting.\n if (state.contentBlockOpen) {\n // Close any previously open block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n const anthropicBlockIndex = state.contentBlockIndex\n state.toolCalls[toolCall.index] = {\n id: toolCall.id,\n name: toolCall.function.name,\n anthropicBlockIndex,\n }\n\n events.push({\n type: \"content_block_start\",\n index: anthropicBlockIndex,\n content_block: {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: {},\n },\n })\n state.contentBlockOpen = true\n }\n\n if (toolCall.function?.arguments) {\n const toolCallInfo = state.toolCalls[toolCall.index]\n // Tool call can still be empty\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (toolCallInfo) {\n events.push({\n type: \"content_block_delta\",\n index: toolCallInfo.anthropicBlockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: toolCall.function.arguments,\n },\n })\n }\n }\n }\n }\n\n if (choice.finish_reason) {\n if (state.contentBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockOpen = false\n }\n\n events.push(\n {\n type: \"message_delta\",\n delta: {\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\n stop_sequence: null,\n },\n usage: {\n input_tokens:\n (chunk.usage?.prompt_tokens ?? 0)\n - (chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: chunk.usage?.completion_tokens ?? 0,\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n {\n type: \"message_stop\",\n },\n )\n }\n\n return events\n}\n\nexport function translateErrorToAnthropicErrorEvent(): AnthropicStreamEventData {\n return {\n type: \"error\",\n error: {\n type: \"api_error\",\n message: \"An unexpected error occurred during streaming.\",\n },\n }\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\nimport { streamSSE } from \"hono/streaming\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { state } from \"~/lib/state\"\nimport {\n createChatCompletions,\n type ChatCompletionChunk,\n type ChatCompletionResponse,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicMessagesPayload,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport {\n translateToAnthropic,\n translateToOpenAI,\n} from \"./non-stream-translation\"\nimport {\n translateChunkToAnthropicEvents,\n translateErrorToAnthropicErrorEvent,\n} from \"./stream-translation\"\n\nexport async function handleCompletion(c: Context) {\n await checkRateLimit(state)\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n if (state.manualApprove) {\n await awaitApproval()\n }\n\n const response = await createChatCompletions(openAIPayload)\n\n if (isNonStreaming(response)) {\n const anthropicResponse = translateToAnthropic(response)\n return c.json(anthropicResponse)\n }\n\n return streamSSE(c, async (stream) => {\n const streamState: AnthropicStreamState = {\n messageStartSent: false,\n contentBlockIndex: 0,\n contentBlockOpen: false,\n toolCalls: {},\n thinkingBlockOpen: false,\n thinkingRequested: Boolean(anthropicPayload.thinking),\n }\n\n try {\n for await (const rawEvent of response) {\n const event = rawEvent as { data?: string }\n if (event.data === \"[DONE]\") {\n break\n }\n\n if (!event.data) {\n continue\n }\n\n let chunk: ChatCompletionChunk\n try {\n chunk = JSON.parse(event.data) as ChatCompletionChunk\n } catch {\n consola.debug(\"Skipping malformed SSE chunk\")\n continue\n }\n const events = translateChunkToAnthropicEvents(chunk, streamState)\n\n for (const event of events) {\n await stream.writeSSE({\n event: event.type,\n data: JSON.stringify(event),\n })\n }\n }\n } catch (error) {\n const message = (error as Error).message || String(error)\n consola.warn(`SSE stream interrupted: ${message}`)\n try {\n const errorEvent = translateErrorToAnthropicErrorEvent()\n await stream.writeSSE({\n event: errorEvent.type,\n data: JSON.stringify(errorEvent),\n })\n } catch {\n // Client already disconnected — nothing we can do\n }\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCountTokens } from \"./count-tokens-handler\"\nimport { handleCompletion } from \"./handler\"\n\nexport const messageRoutes = new Hono()\n\nmessageRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n return await handleCountTokens(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\nimport { cacheModels } from \"~/lib/utils\"\n\nexport const modelRoutes = new Hono()\n\nmodelRoutes.get(\"/\", async (c) => {\n try {\n if (!state.models) {\n // This should be handled by startup logic, but as a fallback.\n await cacheModels()\n }\n\n const models = state.models?.data.map((model) => ({\n id: model.id,\n object: \"model\",\n type: \"model\",\n created: 0, // No date available from source\n created_at: new Date(0).toISOString(), // No date available from source\n owned_by: model.vendor,\n display_name: model.name,\n }))\n\n return c.json({\n object: \"list\",\n data: models,\n has_more: false,\n })\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import consola from \"consola\"\nimport { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\nimport { rootCause } from \"~/lib/utils\"\n\nexport const tokenRoute = new Hono()\n\ntokenRoute.get(\"/\", (c) => {\n try {\n return c.json({\n token: state.copilotToken,\n })\n } catch (error) {\n consola.warn(`Error fetching token: ${rootCause(error)}`)\n consola.debug(\"Error fetching token:\", error)\n return c.json({ error: \"Failed to fetch token\", token: null }, 500)\n }\n})\n","import consola from \"consola\"\nimport { Hono } from \"hono\"\n\nimport { accountManager } from \"~/lib/account-manager\"\nimport { state } from \"~/lib/state\"\nimport { rootCause } from \"~/lib/utils\"\nimport { getCopilotUsage } from \"~/services/github/get-copilot-usage\"\n\nexport const usageRoute = new Hono()\n\nusageRoute.get(\"/\", async (c) => {\n try {\n // In multi-account mode, use the active account's GitHub token\n if (state.multiAccountEnabled && accountManager.hasAccounts()) {\n const account = accountManager.getActiveAccount()\n if (account) {\n const usage = await getCopilotUsage(account.githubToken)\n return c.json(usage)\n }\n }\n const usage = await getCopilotUsage()\n return c.json(usage)\n } catch (error) {\n consola.warn(`Error fetching usage: ${rootCause(error)}`)\n consola.debug(\"Error fetching usage:\", error)\n return c.json({ error: \"Failed to fetch Copilot usage\" }, 500)\n }\n})\n","import { Hono } from \"hono\"\nimport { cors } from \"hono/cors\"\n\nimport { apiKeyAuthMiddleware } from \"./lib/api-key-auth\"\nimport { modelLogger } from \"./lib/model-logger\"\nimport { adminRoutes } from \"./routes/admin/route\"\nimport { completionRoutes } from \"./routes/chat-completions/route\"\nimport { embeddingRoutes } from \"./routes/embeddings/route\"\nimport { messageRoutes } from \"./routes/messages/route\"\nimport { modelRoutes } from \"./routes/models/route\"\nimport { tokenRoute } from \"./routes/token/route\"\nimport { usageRoute } from \"./routes/usage/route\"\n\nexport const server = new Hono()\n\nserver.use(modelLogger())\nserver.use(cors())\nserver.use(apiKeyAuthMiddleware)\n\nserver.get(\"/\", (c) => c.text(\"Server running\"))\n\n// Chat completions\nserver.route(\"/chat/completions\", completionRoutes)\n\n// Models\nserver.route(\"/models\", modelRoutes)\n\nserver.route(\"/embeddings\", embeddingRoutes)\nserver.route(\"/usage\", usageRoute)\nserver.route(\"/token\", tokenRoute)\n\n// Compatibility with tools that expect v1/ prefix\nserver.route(\"/v1/chat/completions\", completionRoutes)\nserver.route(\"/v1/models\", modelRoutes)\nserver.route(\"/v1/embeddings\", embeddingRoutes)\n\n// Anthropic compatible endpoints\nserver.route(\"/v1/messages\", messageRoutes)\n\n// Admin API (Usage Viewer UI)\nserver.route(\"/api\", adminRoutes)\n","#!/usr/bin/env node\n\n// Load environment variables from .env file\nimport \"dotenv/config\"\n/* eslint-disable require-atomic-updates */\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 { accountManager } from \"./lib/account-manager\"\nimport { applyProxyConfig, getModelMappingConfig } from \"./lib/config\"\nimport { modelRouter } from \"./lib/model-router\"\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport {\n setupCopilotToken,\n setupGitHubToken,\n stopCopilotTokenRefresh,\n} from \"./lib/token\"\nimport { cacheModels, cacheVSCodeVersion } from \"./lib/utils\"\nimport { server } from \"./server\"\n\ninterface RunServerOptions {\n port: number\n verbose: boolean\n accountType: string\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n proxyEnv: boolean\n apiKeys?: Array<string>\n}\n\n/**\n * Initialize multi-account mode: load accounts from disk, optionally migrate\n * the legacy single-account, and start background token/usage refresh.\n */\nasync function initMultiAccount(): Promise<void> {\n try {\n await accountManager.loadAccounts()\n\n if (accountManager.hasAccounts()) {\n // Multi-account mode: accounts.json exists with accounts\n state.multiAccountEnabled = true\n consola.info(\n `Multi-account mode enabled with ${accountManager.accountCount} account(s)`,\n )\n\n // Stop single-account token refresh — multi-account has its own\n stopCopilotTokenRefresh()\n\n // Start background token/usage refresh\n await accountManager.startBackgroundRefresh()\n } else if (state.githubToken) {\n // No accounts in file — migrate current single account if we have a token\n try {\n const account = await accountManager.migrateFromLegacy(\n state.githubToken,\n state.accountType,\n )\n state.multiAccountEnabled = true\n consola.info(\n `Migrated current account (${account.githubLogin ?? account.label}) to multi-account mode`,\n )\n\n // Stop single-account token refresh — multi-account has its own\n stopCopilotTokenRefresh()\n\n await accountManager.startBackgroundRefresh()\n } catch (migrationError) {\n consola.warn(\n \"Could not migrate to multi-account, staying in single-account mode:\",\n migrationError,\n )\n }\n }\n } catch (error) {\n consola.debug(\"Multi-account init skipped:\", error)\n // Non-fatal — single account mode continues to work\n }\n}\n\n/**\n * Load model mapping and concurrency configuration from the config file and\n * apply it to the model router.\n */\nasync function initModelRouting(): Promise<void> {\n try {\n const modelMappingConfig = await getModelMappingConfig()\n if (modelMappingConfig) {\n if (modelMappingConfig.mapping) {\n modelRouter.updateMapping(modelMappingConfig.mapping)\n consola.info(\n `Model mapping loaded: ${Object.keys(modelMappingConfig.mapping).length} rule(s)`,\n )\n }\n if (modelMappingConfig.concurrency) {\n modelRouter.updateConcurrency(modelMappingConfig.concurrency)\n consola.info(\n `Model concurrency loaded: ${Object.keys(modelMappingConfig.concurrency).length} rule(s)`,\n )\n }\n }\n } catch (error) {\n consola.debug(\"Model routing config not loaded:\", error)\n }\n}\n\n/**\n * Interactively select models and generate a Claude Code environment script.\n */\nasync function setupClaudeCodeEnv(serverUrl: string): Promise<void> {\n const modelList = state.models?.data\n invariant(modelList, \"Models should be loaded by now\")\n\n const selectedModel = await consola.prompt(\n \"Select a model to use with Claude Code\",\n {\n type: \"select\",\n options: modelList.map((model) => model.id),\n },\n )\n\n if (typeof selectedModel === \"symbol\") {\n consola.info(\"Model selection cancelled\")\n return\n }\n\n const selectedSmallModel = await consola.prompt(\n \"Select a small model to use with Claude Code\",\n {\n type: \"select\",\n options: modelList.map((model) => model.id),\n },\n )\n\n if (typeof selectedSmallModel === \"symbol\") {\n consola.info(\"Model selection cancelled\")\n return\n }\n\n // Save selections to state for API access\n state.selectedModel = selectedModel\n state.selectedSmallModel = selectedSmallModel\n\n const command = generateEnvScript(\n {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: state.apiKeys?.[0] ?? \"dummy\",\n ANTHROPIC_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_OPUS_MODEL: selectedModel,\n ANTHROPIC_REASONING_MODEL: selectedModel,\n ANTHROPIC_SMALL_FAST_MODEL: selectedSmallModel,\n ANTHROPIC_DEFAULT_HAIKU_MODEL: selectedSmallModel,\n DISABLE_NON_ESSENTIAL_MODEL_CALLS: \"1\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\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}\nasync function validateGitHubToken(token: string): Promise<void> {\n state.githubToken = token\n consola.info(\"Using provided GitHub token\")\n try {\n const { getGitHubUser } = await import(\"~/services/github/get-user\")\n const user = await getGitHubUser()\n consola.info(`Logged in as ${user.login}`)\n } catch (error) {\n consola.error(\"Provided GitHub token is invalid\")\n throw error\n }\n}\n\n/**\n * Start and configure the Copilot API server according to the provided options.\n *\n * @param options - Server startup options:\n * - port: Port number to listen on\n * - verbose: Enable verbose logging\n * - accountType: Account plan to use (\"individual\", \"business\", \"enterprise\")\n * - manual: Require manual approval for requests\n * - rateLimit: Seconds to wait between requests (optional)\n * - rateLimitWait: Wait instead of erroring when rate limit is hit\n * - githubToken: GitHub token to use (optional; if omitted a token setup prompt may run)\n * - claudeCode: Generate a Claude Code environment launch command\n * - showToken: Expose GitHub/Copilot tokens in responses for debugging\n * - proxyEnv: Initialize proxy settings from environment variables\n * - apiKeys: Optional list of API keys to enable API key authentication\n */\nexport async function runServer(options: RunServerOptions): Promise<void> {\n // Apply saved proxy configuration first (if any)\n const savedProxyApplied = await applyProxyConfig()\n\n // Then apply --proxy-env if specified (overrides saved config)\n if (options.proxyEnv) {\n initProxyFromEnv()\n } else if (savedProxyApplied) {\n // If saved proxy was applied, initialize the proxy dispatcher\n initProxyFromEnv()\n }\n\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 state.apiKeys = options.apiKeys\n\n if (state.apiKeys && state.apiKeys.length > 0) {\n consola.info(\n `API key authentication enabled with ${state.apiKeys.length} key(s)`,\n )\n }\n\n await ensurePaths()\n\n // Standard Copilot mode\n await cacheVSCodeVersion()\n\n await (options.githubToken ?\n validateGitHubToken(options.githubToken)\n : setupGitHubToken())\n\n try {\n await setupCopilotToken()\n } catch (error) {\n // If getting Copilot token fails with 401, the GitHub token might be invalid\n const { HTTPError } = await import(\"~/lib/error\")\n if (error instanceof HTTPError && error.response.status === 401) {\n consola.error(\n \"Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked\",\n )\n const { clearGithubToken } = await import(\"~/lib/token\")\n await clearGithubToken()\n consola.info(\"Please restart to re-authenticate\")\n }\n throw error\n }\n\n await cacheModels()\n\n // Initialize multi-account mode\n await initMultiAccount()\n\n // Initialize model routing from config\n await initModelRouting()\n\n consola.info(\n `Available models: \\n${state.models?.data.map((model) => `- ${model.id}`).join(\"\\n\")}`,\n )\n\n const serverUrl = `http://localhost:${options.port}`\n\n if (options.claudeCode) {\n await setupClaudeCodeEnv(serverUrl)\n }\n\n const multiAccountInfo =\n state.multiAccountEnabled ?\n `\\n👥 Multi-account: ${accountManager.activeAccountCount}/${accountManager.accountCount} active`\n : \"\"\n\n consola.box(\n `🌐 Usage Viewer: https://imbuxiangnan-cyber.github.io/copilot-api-plus?endpoint=${serverUrl}/usage${multiAccountInfo}`,\n )\n\n serve({\n fetch: server.fetch as ServerHandler,\n port: options.port,\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 \"api-key\": {\n type: \"string\",\n description: \"API keys for authentication\",\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 // Handle multiple API keys - citty may pass a string or array\n const apiKeyRaw = args[\"api-key\"]\n let apiKeys: Array<string> | undefined\n if (apiKeyRaw) {\n apiKeys = Array.isArray(apiKeyRaw) ? apiKeyRaw : [apiKeyRaw]\n }\n\n return runServer({\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n accountType: args[\"account-type\"],\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 apiKeys,\n })\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand, runMain } from \"citty\"\n\nimport { addAccount, listAccounts, removeAccount } from \"./account\"\nimport { auth } from \"./auth\"\nimport { checkUsage } from \"./check-usage\"\nimport { debug } from \"./debug\"\nimport { logout } from \"./logout\"\nimport { proxy } from \"./proxy-config\"\nimport { start } from \"./start\"\n\nconst main = defineCommand({\n meta: {\n name: \"copilot-api-plus\",\n description:\n \"A wrapper around GitHub Copilot API to make it OpenAI/Anthropic compatible. Fork with bug fixes and improvements.\",\n },\n subCommands: {\n auth,\n start,\n \"check-usage\": checkUsage,\n \"add-account\": addAccount,\n \"list-accounts\": listAccounts,\n \"remove-account\": removeAccount,\n debug,\n logout,\n proxy,\n },\n})\n\nawait runMain(main)\n"],"x_google_ignoreList":[8,9,10,11,12],"mappings":"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"}
|
package/package.json
CHANGED