github-router 0.3.7 → 0.3.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/dist/main.js +576 -300
- package/dist/main.js.map +1 -1
- package/package.json +1 -2
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","names":["state: State","state","headers: Record<string, string>","errorJson: unknown","token","process","commandBlock: string","state","parts: Array<string>","x","headers: Record<string, string>","searchTimestamps: Array<number>","references: Array<{ title: string; url: string }>","handleCompletion","injectWebSearchIfNeeded","inputTokens: number | undefined","isNonStreaming","extractUserQuery","handleCompletion","isWebSearchTool","body: AnyRecord","resolveModelInBody","extraHeaders: Record<string, string>","parsed: AnyRecord","headers: Record<string, string>","extractUserQuery","body: AnyRecord","parsed: AnyRecord","headers: Record<string, string>","rateLimit: number | undefined"],"sources":["../src/lib/paths.ts","../src/lib/state.ts","../src/lib/api-config.ts","../src/lib/error.ts","../src/services/github/get-copilot-token.ts","../src/services/github/get-device-code.ts","../src/services/github/get-user.ts","../src/services/copilot/get-models.ts","../src/services/get-vscode-version.ts","../src/lib/utils.ts","../src/services/github/poll-access-token.ts","../src/lib/token.ts","../src/auth.ts","../src/services/github/get-copilot-usage.ts","../src/check-usage.ts","../src/debug.ts","../src/lib/proxy.ts","../src/lib/shell.ts","../src/lib/approval.ts","../src/lib/rate-limit.ts","../src/lib/request-log.ts","../src/lib/tokenizer.ts","../src/services/copilot/create-chat-completions.ts","../src/services/copilot/web-search.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/services/copilot/create-messages.ts","../src/routes/messages/count-tokens-handler.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/services/copilot/create-responses.ts","../src/routes/responses/handler.ts","../src/routes/responses/route.ts","../src/routes/search/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport os from \"node:os\"\nimport path from \"node:path\"\n\nconst APP_DIR = path.join(os.homedir(), \".local\", \"share\", \"github-router\")\n\nconst GITHUB_TOKEN_PATH = path.join(APP_DIR, \"github_token\")\n\nexport const PATHS = {\n APP_DIR,\n GITHUB_TOKEN_PATH,\n}\n\nexport async function ensurePaths(): Promise<void> {\n await fs.mkdir(PATHS.APP_DIR, { recursive: true })\n await ensureFile(PATHS.GITHUB_TOKEN_PATH)\n}\n\nasync function ensureFile(filePath: string): Promise<void> {\n try {\n await fs.access(filePath, fs.constants.W_OK)\n } catch {\n await fs.writeFile(filePath, \"\")\n await fs.chmod(filePath, 0o600)\n }\n}\n","import { randomBytes, randomUUID } from \"node:crypto\"\n\nimport type { ModelsResponse } from \"~/services/copilot/get-models\"\n\nexport interface State {\n githubToken?: string\n copilotToken?: string\n\n accountType: string\n copilotApiUrl?: string\n models?: ModelsResponse\n vsCodeVersion?: string\n\n manualApprove: boolean\n rateLimitWait: boolean\n showToken: boolean\n\n // Rate limiting configuration\n rateLimitSeconds?: number\n lastRequestTimestamp?: number\n\n // Persistent session identifiers to match VS Code fingerprint\n sessionId: string\n machineId: string\n}\n\nexport const state: State = {\n accountType: \"enterprise\",\n manualApprove: false,\n rateLimitWait: false,\n showToken: false,\n sessionId: randomUUID(),\n machineId: randomBytes(32).toString(\"hex\"),\n}\n","import { randomUUID } from \"node:crypto\"\n\nimport type { State } from \"./state\"\n\nexport const standardHeaders = () => ({\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n})\n\nconst COPILOT_VERSION = \"0.38.2026021302\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\nconst API_VERSION = \"2025-10-01\"\n\nexport const copilotBaseUrl = (state: State) =>\n state.copilotApiUrl ?? \"https://api.githubcopilot.com\"\nexport const copilotHeaders = (\n state: State,\n vision: boolean = false,\n integrationId: string = \"vscode-chat\",\n) => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${state.copilotToken}`,\n \"content-type\": standardHeaders()[\"content-type\"],\n \"copilot-integration-id\": integrationId,\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"openai-intent\": \"conversation-panel\",\n \"x-interaction-type\": \"conversation-panel\",\n \"x-github-api-version\": API_VERSION,\n \"x-request-id\": randomUUID(),\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n \"VScode-SessionId\": state.sessionId,\n \"VScode-MachineId\": state.machineId,\n }\n\n if (vision) headers[\"copilot-vision-request\"] = \"true\"\n\n return headers\n}\n\nexport const GITHUB_API_BASE_URL = \"https://api.github.com\"\nexport const githubHeaders = (state: State) => ({\n ...standardHeaders(),\n authorization: `token ${state.githubToken}`,\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": API_VERSION,\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n})\n\nexport const GITHUB_BASE_URL = \"https://github.com\"\nexport const GITHUB_CLIENT_ID = \"Iv1.b507a08c87ecfe98\"\nexport const GITHUB_APP_SCOPES = [\"read:user\"].join(\" \")\n","import type { Context } from \"hono\"\nimport type { ContentfulStatusCode } from \"hono/utils/http-status\"\n\nimport consola from \"consola\"\n\nexport class HTTPError extends Error {\n response: Response\n\n constructor(message: string, response: Response) {\n super(message)\n this.response = response\n }\n}\n\nexport async function forwardError(c: Context, error: unknown) {\n consola.error(\"Error occurred:\", error)\n\n if (error instanceof HTTPError) {\n const errorText = await error.response.text()\n let errorJson: unknown\n try {\n errorJson = JSON.parse(errorText)\n } catch {\n errorJson = undefined\n }\n const message = resolveErrorMessage(errorJson, errorText)\n consola.error(\"HTTP error:\", errorJson ?? errorText)\n return c.json(\n {\n error: {\n message,\n type: \"error\",\n },\n },\n error.response.status as ContentfulStatusCode,\n )\n }\n\n return c.json(\n {\n error: {\n message: error instanceof Error ? error.message : String(error),\n type: \"error\",\n },\n },\n 500,\n )\n}\n\n// Extracts error message from { message } or { error: { message } } payloads.\nfunction resolveErrorMessage(errorJson: unknown, fallback: string): string {\n if (typeof errorJson !== \"object\" || errorJson === null) return fallback\n\n const errorRecord = errorJson as Record<string, unknown>\n if (errorRecord.message !== undefined) return String(errorRecord.message)\n\n if (typeof errorRecord.error === \"object\" && errorRecord.error !== null) {\n const nestedRecord = errorRecord.error as Record<string, unknown>\n if (nestedRecord.message !== undefined) return String(nestedRecord.message)\n }\n\n return fallback\n}\n","import { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotToken = async () => {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(state),\n },\n )\n\n if (!response.ok) throw new HTTPError(\"Failed to get Copilot token\", response)\n\n const data = (await response.json()) as GetCopilotTokenResponse\n\n // Use the API base URL from the token response if available,\n // matching how VS Code determines the CAPI endpoint dynamically.\n if (data.endpoints?.api) {\n state.copilotApiUrl = data.endpoints.api\n }\n\n return data\n}\n\ninterface GetCopilotTokenResponse {\n expires_at: number\n refresh_in: number\n token: string\n endpoints?: {\n api?: string\n proxy?: string\n telemetry?: string\n \"origin-tracker\"?: string\n }\n}\n","import {\n GITHUB_APP_SCOPES,\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\n\nexport async function getDeviceCode(): Promise<DeviceCodeResponse> {\n const response = await fetch(`${GITHUB_BASE_URL}/login/device/code`, {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n scope: GITHUB_APP_SCOPES,\n }),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get device code\", response)\n\n return (await response.json()) as DeviceCodeResponse\n}\n\nexport interface DeviceCodeResponse {\n device_code: string\n user_code: string\n verification_uri: string\n expires_in: number\n interval: number\n}\n","import { GITHUB_API_BASE_URL, standardHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport async function getGitHubUser() {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\n ...standardHeaders(),\n },\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get GitHub user\", response)\n\n return (await response.json()) as GithubUserResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GithubUserResponse {\n login: string\n}\n","import { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getModels = async () => {\n const response = await fetch(`${copilotBaseUrl(state)}/models`, {\n headers: copilotHeaders(state),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get models\", response)\n\n return (await response.json()) as ModelsResponse\n}\n\nexport interface ModelsResponse {\n data: Array<Model>\n object: string\n}\n\ninterface ModelLimits {\n max_context_window_tokens?: number\n max_output_tokens?: number\n max_prompt_tokens?: number\n max_inputs?: number\n}\n\ninterface ModelSupports {\n tool_calls?: boolean\n parallel_tool_calls?: boolean\n dimensions?: boolean\n}\n\ninterface ModelCapabilities {\n family: string\n limits: ModelLimits\n object: string\n supports: ModelSupports\n tokenizer: string\n type: string\n}\n\nexport interface Model {\n capabilities: ModelCapabilities\n id: string\n model_picker_enabled: boolean\n name: string\n object: string\n preview: boolean\n vendor: string\n version: string\n supported_endpoints?: Array<string>\n policy?: {\n state: string\n terms: string\n }\n}\n","const FALLBACK = \"1.104.3\"\n\nexport async function getVSCodeVersion() {\n const controller = new AbortController()\n const timeout = setTimeout(() => {\n controller.abort()\n }, 5000)\n\n try {\n const response = await fetch(\n \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=visual-studio-code-bin\",\n {\n signal: controller.signal,\n },\n )\n\n const pkgbuild = await response.text()\n const pkgverRegex = /pkgver=([0-9.]+)/\n const match = pkgbuild.match(pkgverRegex)\n\n if (match) {\n return match[1]\n }\n\n return FALLBACK\n } catch {\n return FALLBACK\n } finally {\n clearTimeout(timeout)\n }\n}\n\nawait getVSCodeVersion()\n","import consola from \"consola\"\n\nimport { getModels } from \"~/services/copilot/get-models\"\nimport { getVSCodeVersion } from \"~/services/get-vscode-version\"\n\nimport { state } from \"./state\"\n\nexport const sleep = (ms: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, ms)\n })\n\nexport const isNullish = (value: unknown): value is null | undefined =>\n value === null || value === undefined\n\n/**\n * Beta values that VS Code Copilot Chat actually sends to the Copilot API.\n * Only these are forwarded; everything else (e.g. context-1m-*) is stripped\n * so our requests match what VS Code produces.\n */\nconst ALLOWED_BETA_PREFIXES = [\n \"interleaved-thinking-\",\n \"context-management-\",\n \"advanced-tool-use-\",\n \"token-counting-\",\n]\n\n/**\n * Filter an `anthropic-beta` header value, keeping only beta flags that\n * VS Code Copilot is known to send. Returns the filtered comma-separated\n * string, or undefined if nothing remains.\n */\nexport function filterBetaHeader(value: string): string | undefined {\n const filtered = value\n .split(\",\")\n .map((v) => v.trim())\n .filter(\n (v) =>\n v && ALLOWED_BETA_PREFIXES.some((prefix) => v.startsWith(prefix)),\n )\n .join(\",\")\n return filtered || undefined\n}\n\n/**\n * Resolve a model name to the best available variant in the Copilot model list.\n * Prefers the 1M context variant for opus models.\n */\nexport function resolveModel(modelId: string): string {\n const models = state.models?.data\n if (!models) return modelId\n\n // Exact match — no remapping needed\n if (models.some((m) => m.id === modelId)) return modelId\n\n // For opus models, prefer the 1m variant\n if (modelId.toLowerCase().includes(\"opus\")) {\n const oneM = models.find((m) => m.id.includes(\"opus\") && m.id.endsWith(\"-1m\"))\n if (oneM) return oneM.id\n }\n\n return modelId\n}\n\nexport async function cacheModels(): Promise<void> {\n const models = await getModels()\n state.models = models\n}\n\nexport const cacheVSCodeVersion = async () => {\n const response = await getVSCodeVersion()\n state.vsCodeVersion = response\n\n consola.info(`Using VSCode version: ${response}`)\n}\n","import consola from \"consola\"\n\nimport {\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { sleep } from \"~/lib/utils\"\n\nimport type { DeviceCodeResponse } from \"./get-device-code\"\n\nexport async function pollAccessToken(\n deviceCode: DeviceCodeResponse,\n): Promise<string> {\n // Interval is in seconds, we need to multiply by 1000 to get milliseconds\n // I'm also adding another second, just to be safe\n const sleepDuration = (deviceCode.interval + 1) * 1000\n consola.debug(`Polling access token with interval of ${sleepDuration}ms`)\n const expiresAt = Date.now() + deviceCode.expires_in * 1000\n\n while (Date.now() < expiresAt) {\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: deviceCode.device_code,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n },\n )\n\n if (!response.ok) {\n consola.error(\"Failed to poll access token:\", await response.text())\n if (Date.now() >= expiresAt) break\n await sleep(sleepDuration)\n continue\n }\n\n const json = await response.json()\n consola.debug(\"Polling access token response:\", json)\n\n const { access_token } = json as AccessTokenResponse\n\n if (access_token) {\n return access_token\n }\n\n if (Date.now() >= expiresAt) break\n await sleep(sleepDuration)\n }\n\n throw new Error(\"Device code expired. Please run auth again.\")\n}\n\ninterface AccessTokenResponse {\n access_token: string\n token_type: string\n scope: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\nimport { getCopilotToken } from \"~/services/github/get-copilot-token\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\nimport { getGitHubUser } from \"~/services/github/get-user\"\nimport { pollAccessToken } from \"~/services/github/poll-access-token\"\n\nimport { HTTPError } from \"./error\"\nimport { state } from \"./state\"\n\nconst readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n\nconst writeGithubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)\n\nexport const setupCopilotToken = async () => {\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n\n // Display the Copilot token to the screen\n consola.debug(\"GitHub Copilot Token fetched successfully!\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n const refreshInterval = Math.max((refresh_in - 60) * 1000, 1000)\n setInterval(async () => {\n consola.debug(\"Refreshing Copilot token\")\n try {\n const { token } = await getCopilotToken()\n state.copilotToken = token\n consola.debug(\"Copilot token refreshed\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n }\n }, refreshInterval)\n}\n\ninterface SetupGitHubTokenOptions {\n force?: boolean\n}\n\nexport async function setupGitHubToken(\n options?: SetupGitHubTokenOptions,\n): Promise<void> {\n try {\n const githubToken = await readGithubToken()\n\n if (githubToken && !options?.force) {\n state.githubToken = githubToken\n if (state.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n await logUser()\n\n return\n }\n\n consola.info(\"Not logged in, getting new access token\")\n const response = await getDeviceCode()\n consola.debug(\"Device code response:\", response)\n\n consola.info(\n `Please enter the code \"${response.user_code}\" in ${response.verification_uri}`,\n )\n\n const token = await pollAccessToken(response)\n await writeGithubToken(token)\n state.githubToken = token\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n await logUser()\n } catch (error) {\n if (error instanceof HTTPError) {\n consola.error(\"Failed to get GitHub token:\", await error.response.json())\n throw error\n }\n\n consola.error(\"Failed to get GitHub token:\", error)\n throw error\n }\n}\n\nasync function logUser() {\n const user = await getGitHubUser()\n consola.info(`Logged in as ${user.login}`)\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 { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotUsage = async (): Promise<CopilotUsageResponse> => {\n const response = await fetch(`${GITHUB_API_BASE_URL}/copilot_internal/user`, {\n headers: githubHeaders(state),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get Copilot usage\", response)\n }\n\n return (await response.json()) as CopilotUsageResponse\n}\n\nexport interface QuotaDetail {\n entitlement: number\n overage_count: number\n overage_permitted: boolean\n percent_remaining: number\n quota_id: string\n quota_remaining: number\n remaining: number\n unlimited: boolean\n}\n\ninterface QuotaSnapshots {\n chat: QuotaDetail\n completions: QuotaDetail\n premium_interactions: QuotaDetail\n}\n\ninterface CopilotUsageResponse {\n access_type_sku: string\n analytics_tracking_id: string\n assigned_date: string\n can_signup_for_limited: boolean\n chat_enabled: boolean\n copilot_plan: string\n organization_login_list: Array<unknown>\n organization_list: Array<unknown>\n quota_reset_date: string\n quota_snapshots: QuotaSnapshots\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { setupGitHubToken } from \"./lib/token\"\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.error(\"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 { 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 tokenExists: boolean\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, tokenExists] = await Promise.all([\n getPackageVersion(),\n checkTokenExists(),\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 tokenExists,\n }\n}\n\nfunction printDebugInfoPlain(info: DebugInfo): void {\n consola.info(`github-router 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\nToken exists: ${info.tokenExists ? \"Yes\" : \"No\"}`)\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","import consola from \"consola\"\nimport { getProxyForUrl } from \"proxy-from-env\"\nimport { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from \"undici\"\n\nexport function initProxyFromEnv(): void {\n if (typeof Bun !== \"undefined\") return\n\n try {\n const direct = new Agent()\n const proxies = new Map<string, ProxyAgent>()\n\n // We only need a minimal dispatcher that implements `dispatch` at runtime.\n // Typing the object as `Dispatcher` forces TypeScript to require many\n // additional methods. Instead, keep a plain object and cast when passing\n // to `setGlobalDispatcher`.\n const dispatcher = {\n dispatch(\n options: Dispatcher.DispatchOptions,\n handler: Dispatcher.DispatchHandler,\n ) {\n try {\n const origin =\n typeof options.origin === \"string\" ?\n new URL(options.origin)\n : (options.origin as URL)\n const get = getProxyForUrl as unknown as (\n u: string,\n ) => string | undefined\n const raw = get(origin.toString())\n const proxyUrl = raw && raw.length > 0 ? raw : undefined\n if (!proxyUrl) {\n consola.debug(`HTTP proxy bypass: ${origin.hostname}`)\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n let agent = proxies.get(proxyUrl)\n if (!agent) {\n agent = new ProxyAgent(proxyUrl)\n proxies.set(proxyUrl, agent)\n }\n let label = proxyUrl\n try {\n const u = new URL(proxyUrl)\n label = `${u.protocol}//${u.host}`\n } catch {\n /* noop */\n }\n consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`)\n return (agent as unknown as Dispatcher).dispatch(options, handler)\n } catch {\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n },\n close() {\n return direct.close()\n },\n destroy() {\n return direct.destroy()\n },\n }\n\n 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","import 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, env } = process\n\n if (platform === \"win32\") {\n // Git Bash / MSYS2 / Cygwin set SHELL even on Windows\n if (env.SHELL) {\n if (env.SHELL.endsWith(\"zsh\")) return \"zsh\"\n if (env.SHELL.endsWith(\"fish\")) return \"fish\"\n if (env.SHELL.endsWith(\"bash\")) return \"bash\"\n return \"sh\"\n }\n\n // Windows PowerShell 5.x sets this\n if (env.POWERSHELL_DISTRIBUTION_CHANNEL) return \"powershell\"\n\n // PowerShell (both 5.x and 7+/pwsh) adds user-scoped module paths\n // at runtime. The system-level PSModulePath in CMD lacks these paths.\n if (env.PSModulePath) {\n const lower = env.PSModulePath.toLowerCase()\n if (\n lower.includes(\"documents\\\\powershell\")\n || lower.includes(\"documents\\\\windowspowershell\")\n ) {\n return \"powershell\"\n }\n }\n\n return \"cmd\"\n }\n\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\nfunction quotePosixValue(value: string): string {\n return `'${value.replace(/'/g, \"'\\\\''\")}'`\n}\n\nfunction quotePowerShellValue(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`\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} = ${quotePowerShellValue(value)}`)\n .join(\"; \")\n break\n }\n case \"cmd\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set \"${key}=${value}\"`)\n .join(\" & \")\n break\n }\n case \"fish\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set -gx ${key} ${quotePosixValue(value)}`)\n .join(\"; \")\n break\n }\n default: {\n // bash, zsh, sh\n const assignments = filteredEnvVars\n .map(([key, value]) => `${key}=${quotePosixValue(value)}`)\n .join(\" \")\n commandBlock = filteredEnvVars.length > 0 ? `export ${assignments}` : \"\"\n break\n }\n }\n\n if (commandBlock && commandToRun) {\n const separator =\n shell === \"cmd\" ? \" & \" : shell === \"powershell\" ? \"; \" : \" && \"\n return `${commandBlock}${separator}${commandToRun}`\n }\n\n return commandBlock || commandToRun\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 by user\",\n Response.json({ message: \"Request rejected by user\" }, { 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\nexport async function checkRateLimit(state: State) {\n if (state.rateLimitSeconds === undefined) return\n\n const now = Date.now()\n\n if (!state.lastRequestTimestamp) {\n state.lastRequestTimestamp = now\n return\n }\n\n const elapsedSeconds = (now - state.lastRequestTimestamp) / 1000\n\n if (elapsedSeconds > state.rateLimitSeconds) {\n state.lastRequestTimestamp = now\n return\n }\n\n const waitTimeSeconds = Math.ceil(state.rateLimitSeconds - elapsedSeconds)\n\n if (!state.rateLimitWait) {\n consola.warn(\n `Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`,\n )\n throw new HTTPError(\n \"Rate limit exceeded\",\n Response.json({ message: \"Rate limit exceeded\" }, { status: 429 }),\n )\n }\n\n const waitTimeMs = waitTimeSeconds * 1000\n consola.warn(\n `Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`,\n )\n await sleep(waitTimeMs)\n state.lastRequestTimestamp = Date.now()\n consola.info(\"Rate limit wait completed, proceeding with request\")\n return\n}\n","import consola from \"consola\"\n\nimport type { Model } from \"~/services/copilot/get-models\"\n\nexport interface RequestLogInfo {\n method: string\n path: string\n model?: string\n resolvedModel?: string\n inputTokens?: number\n outputTokens?: number\n status?: number\n streaming?: boolean\n}\n\n/**\n * Format a number with K/M suffix for compact display.\n */\nfunction formatTokens(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`\n return String(n)\n}\n\n/**\n * Build a context window summary: \"in:1.2K out:50 ctx:1.2K/1M (0.1%)\"\n */\nfunction formatTokenInfo(\n inputTokens: number | undefined,\n outputTokens: number | undefined,\n model: Model | undefined,\n): string | undefined {\n if (inputTokens === undefined) return undefined\n\n const parts: Array<string> = []\n const maxPrompt = model?.capabilities.limits.max_prompt_tokens\n\n if (maxPrompt) {\n const pct = ((inputTokens / maxPrompt) * 100).toFixed(1)\n parts.push(`in:${formatTokens(inputTokens)}/${formatTokens(maxPrompt)} (${pct}%)`)\n } else {\n parts.push(`in:${formatTokens(inputTokens)}`)\n }\n\n if (outputTokens !== undefined) {\n parts.push(`out:${formatTokens(outputTokens)}`)\n }\n\n return parts.join(\" \")\n}\n\n/**\n * Print a single summary line for a completed request.\n *\n * Examples:\n * POST /v1/messages claude-opus-4.6-1m in:1.2K/1M (0.1%) out:50 200 2.3s\n * POST /v1/messages claude-opus-4-6→claude-opus-4.6-1m in:743/1M (0.1%) 200 198ms\n * POST /v1/chat/completions claude-sonnet-4 in:15 out:16 200 2.1s stream\n */\nexport function logRequest(\n info: RequestLogInfo,\n model: Model | undefined,\n startTime: number,\n): void {\n const parts: Array<string> = []\n\n parts.push(`${info.method} ${info.path}`)\n\n // Model (show resolution arrow if remapped)\n if (info.resolvedModel && info.resolvedModel !== info.model) {\n parts.push(`${info.model}→${info.resolvedModel}`)\n } else if (info.resolvedModel ?? info.model) {\n parts.push((info.resolvedModel ?? info.model)!)\n }\n\n // Token info with context window fill\n const tokenInfo = formatTokenInfo(info.inputTokens, info.outputTokens, model)\n if (tokenInfo) {\n parts.push(tokenInfo)\n }\n\n // Status\n if (info.status !== undefined) {\n parts.push(String(info.status))\n }\n\n // Duration + streaming flag\n const elapsed = Date.now() - startTime\n const duration =\n elapsed >= 1000 ? `${(elapsed / 1000).toFixed(1)}s` : `${elapsed}ms`\n parts.push(info.streaming ? `${duration} stream` : duration)\n\n consola.info(parts.join(\" \"))\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\" \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 simplifiedMessages = payload.messages\n const inputMessages = simplifiedMessages.filter(\n (msg) => msg.role !== \"assistant\",\n )\n const outputMessages = simplifiedMessages.filter(\n (msg) => msg.role === \"assistant\",\n )\n\n const constants = getModelConstants(model)\n let inputTokens = calculateTokens(inputMessages, encoder, constants)\n if (payload.tools && payload.tools.length > 0) {\n inputTokens += numTokensForTools(payload.tools, encoder, constants)\n }\n const outputTokens = calculateTokens(outputMessages, encoder, constants)\n\n return {\n input: inputTokens,\n output: outputTokens,\n }\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const createChatCompletions = async (\n payload: ChatCompletionsPayload,\n) => {\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 and add X-Initiator\n const headers: Record<string, string> = {\n ...copilotHeaders(state, enableVision),\n \"Openai-Organization\": \"github-copilot\",\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n }\n\n const response = await fetch(`${copilotBaseUrl(state)}/chat/completions`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n let errorBody = \"\"\n try {\n errorBody = await response.text()\n } catch {\n errorBody = \"(could not read error body)\"\n }\n const claudeModels = state.models?.data\n .filter((m) => m.id.startsWith(\"claude\"))\n .map((m) => m.id)\n .join(\", \") ?? \"(models not loaded)\"\n consola.error(\n `Copilot rejected model \"${payload.model}\": ${response.status} ${errorBody} (available Claude models: ${claudeModels})`,\n )\n // Re-create the response so downstream error handlers can still read the body\n const reconstructed = new Response(errorBody, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n throw new HTTPError(\"Failed to create chat completions\", reconstructed)\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n}\n\n// Streaming types\n\nexport interface ChatCompletionChunk {\n id: string\n object: \"chat.completion.chunk\"\n created: number\n model: string\n choices: Array<Choice>\n system_fingerprint?: string\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n prompt_tokens_details?: {\n cached_tokens: number\n }\n completion_tokens_details?: {\n accepted_prediction_tokens: number\n rejected_prediction_tokens: number\n }\n }\n}\n\ninterface Delta {\n content?: string | null\n role?: \"user\" | \"assistant\" | \"system\" | \"tool\"\n tool_calls?: Array<{\n index: number\n id?: string\n type?: \"function\"\n function?: {\n name?: string\n arguments?: string\n }\n }>\n}\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 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\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 consola from \"consola\"\n\nimport { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { state } from \"~/lib/state\"\nimport { sleep } from \"~/lib/utils\"\n\nexport interface WebSearchResult {\n content: string\n references: Array<{ title: string; url: string }>\n}\n\ninterface ThreadsResponse {\n thread_id: string\n}\n\ninterface ThreadsMessageResponse {\n message: {\n content: string\n references: Array<{\n query?: string\n results?: Array<{\n title: string\n url: string\n reference_type: string\n }>\n }>\n }\n}\n\nconst MAX_SEARCHES_PER_SECOND = 3\nlet searchTimestamps: Array<number> = []\n\nasync function throttleSearch(): Promise<void> {\n const now = Date.now()\n searchTimestamps = searchTimestamps.filter((t) => now - t < 1000)\n if (searchTimestamps.length >= MAX_SEARCHES_PER_SECOND) {\n const waitMs = 1000 - (now - searchTimestamps[0])\n if (waitMs > 0) {\n consola.debug(`Web search rate limited, waiting ${waitMs}ms`)\n await sleep(waitMs)\n }\n }\n searchTimestamps.push(Date.now())\n}\n\nfunction threadsHeaders(): Record<string, string> {\n return copilotHeaders(state, false, \"copilot-chat\")\n}\n\nasync function createThread(): Promise<string> {\n const response = await fetch(`${copilotBaseUrl(state)}/github/chat/threads`, {\n method: \"POST\",\n headers: threadsHeaders(),\n body: JSON.stringify({}),\n })\n\n if (!response.ok) {\n consola.error(\"Failed to create chat thread\", response.status)\n throw new Error(`Failed to create chat thread: ${response.status}`)\n }\n\n const data = (await response.json()) as ThreadsResponse\n return data.thread_id\n}\n\nasync function sendThreadMessage(\n threadId: string,\n query: string,\n): Promise<ThreadsMessageResponse> {\n const response = await fetch(\n `${copilotBaseUrl(state)}/github/chat/threads/${threadId}/messages`,\n {\n method: \"POST\",\n headers: threadsHeaders(),\n body: JSON.stringify({\n content: query,\n intent: \"conversation\",\n skills: [\"web-search\"],\n references: [],\n }),\n },\n )\n\n if (!response.ok) {\n consola.error(\"Failed to send thread message\", response.status)\n throw new Error(`Failed to send thread message: ${response.status}`)\n }\n\n return (await response.json()) as ThreadsMessageResponse\n}\n\nexport async function searchWeb(query: string): Promise<WebSearchResult> {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n await throttleSearch()\n\n consola.info(`Web search: \"${query.slice(0, 80)}\"`)\n\n const threadId = await createThread()\n const response = await sendThreadMessage(threadId, query)\n\n const references: Array<{ title: string; url: string }> = []\n for (const ref of response.message.references ?? []) {\n if (ref.results) {\n for (const result of ref.results) {\n if (result.url && result.reference_type !== \"bing_search\") {\n references.push({ title: result.title, url: result.url })\n }\n }\n }\n }\n\n consola.debug(`Web search returned ${references.length} references`)\n\n return {\n content: response.message.content,\n references,\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 { logRequest } from \"~/lib/request-log\"\nimport { state } from \"~/lib/state\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\nimport { isNullish, resolveModel } from \"~/lib/utils\"\nimport {\n createChatCompletions,\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n type Message,\n} from \"~/services/copilot/create-chat-completions\"\nimport { searchWeb } from \"~/services/copilot/web-search\"\n\nexport async function handleCompletion(c: Context) {\n const startTime = Date.now()\n await checkRateLimit(state)\n\n let payload = await c.req.json<ChatCompletionsPayload>()\n const debugEnabled = consola.level >= 4\n if (debugEnabled) {\n consola.debug(\"Request payload:\", JSON.stringify(payload).slice(-400))\n }\n\n if (state.manualApprove) await awaitApproval()\n\n await injectWebSearchIfNeeded(payload)\n\n // Resolve model name (e.g. opus → opus-1m variant)\n const originalModel = payload.model\n const resolvedModel = resolveModel(payload.model)\n if (resolvedModel !== payload.model) {\n payload.model = resolvedModel\n }\n\n // Find the selected model\n const selectedModel = state.models?.data.find(\n (model) => model.id === payload.model,\n )\n\n // Calculate token count\n let inputTokens: number | undefined\n try {\n if (selectedModel) {\n const tokenCount = await getTokenCount(payload, selectedModel)\n inputTokens = tokenCount.input\n }\n } catch {\n // Token counting is best-effort\n }\n\n if (isNullish(payload.max_tokens)) {\n payload = {\n ...payload,\n max_tokens: selectedModel?.capabilities.limits.max_output_tokens,\n }\n if (debugEnabled) {\n consola.debug(\"Set max_tokens to:\", JSON.stringify(payload.max_tokens))\n }\n }\n\n const response = await createChatCompletions(payload)\n const isStreaming = !isNonStreaming(response)\n\n // Extract output tokens from non-streaming response (no extra call)\n const outputTokens = !isStreaming\n ? (response as ChatCompletionResponse).usage?.completion_tokens\n : undefined\n\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n inputTokens,\n outputTokens,\n status: 200,\n streaming: isStreaming,\n },\n selectedModel,\n startTime,\n )\n\n if (!isStreaming) {\n if (debugEnabled) {\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\n }\n return c.json(response)\n }\n\n return streamSSE(c, async (stream) => {\n for await (const chunk of response) {\n if (debugEnabled) {\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\n }\n await stream.writeSSE(chunk as SSEMessage)\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n\nasync function injectWebSearchIfNeeded(\n payload: ChatCompletionsPayload,\n): Promise<void> {\n const hasWebSearch = payload.tools?.some(\n (t) =>\n (\"type\" in t && (t as unknown as Record<string, unknown>).type === \"web_search\")\n || t.function?.name === \"web_search\",\n )\n if (!hasWebSearch) return\n\n // Skip search on follow-up messages (tool call results)\n const hasToolResult = payload.messages.some((msg) => msg.role === \"tool\")\n const query = hasToolResult ? undefined : extractUserQuery(payload.messages)\n\n if (query) {\n try {\n const results = await searchWeb(query)\n const searchContext = [\n \"[Web Search Results]\",\n results.content,\n \"\",\n results.references.map((r) => `- [${r.title}](${r.url})`).join(\"\\n\"),\n \"[End Web Search Results]\",\n ].join(\"\\n\")\n\n // Prepend to existing system message or inject a new one\n const systemMsg = payload.messages.find((msg) => msg.role === \"system\")\n if (systemMsg) {\n const existingContent =\n typeof systemMsg.content === \"string\" ? systemMsg.content\n : Array.isArray(systemMsg.content) ?\n systemMsg.content\n .filter((p) => p.type === \"text\")\n .map((p) => (\"text\" in p ? p.text : \"\"))\n .join(\"\\n\")\n : \"\"\n systemMsg.content = `${searchContext}\\n\\n${existingContent}`\n } else {\n payload.messages.unshift({\n role: \"system\",\n content: searchContext,\n })\n }\n } catch (error) {\n consola.warn(\"Web search failed, continuing without results:\", error)\n }\n }\n\n // Remove web_search from tools before forwarding\n payload.tools = payload.tools?.filter(\n (t) =>\n !(\n (\"type\" in t && (t as unknown as Record<string, unknown>).type === \"web_search\")\n || t.function?.name === \"web_search\"\n ),\n ) as typeof payload.tools\n if (payload.tools?.length === 0) {\n payload.tools = undefined\n }\n if (!payload.tools) {\n payload.tool_choice = undefined\n } else if (\n payload.tool_choice\n && typeof payload.tool_choice === \"object\"\n && \"type\" in payload.tool_choice\n && payload.tool_choice.type === \"function\"\n ) {\n const toolChoiceName = payload.tool_choice.function?.name\n if (\n toolChoiceName\n && !payload.tools.some((tool) => tool.function.name === toolChoiceName)\n ) {\n payload.tool_choice = undefined\n }\n }\n}\n\nfunction extractUserQuery(messages: Array<Message>): string | undefined {\n // Find the last user message\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") return msg.content\n if (Array.isArray(msg.content)) {\n const text = msg.content.find((p) => p.type === \"text\")\n if (text && \"text\" in text) return text.text as string\n }\n }\n }\n return undefined\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 { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const createEmbeddings = async (payload: EmbeddingRequest) => {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const response = await fetch(`${copilotBaseUrl(state)}/embeddings`, {\n method: \"POST\",\n headers: copilotHeaders(state),\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 payload = await c.req.json<EmbeddingRequest>()\n const response = await createEmbeddings(payload)\n\n return c.json(response)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { randomUUID } from \"node:crypto\"\n\nimport consola from \"consola\"\n\nimport { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\n/**\n * Build headers that match what VS Code Copilot Chat sends to the Copilot API.\n *\n * copilotHeaders() provides: Authorization, content-type, copilot-integration-id,\n * editor-version, editor-plugin-version, user-agent, openai-intent,\n * x-github-api-version, x-request-id, x-vscode-user-agent-library-version.\n *\n * We add the remaining headers VS Code sends for /v1/messages:\n * - X-Initiator (VS Code sets dynamically; \"agent\" is safe for CLI use)\n * - anthropic-version (VS Code's Anthropic SDK sends this)\n * - X-Interaction-Id (VS Code sends a session-scoped UUID)\n *\n * We intentionally omit copilot-vision-request — VS Code only sends it when\n * images are present, and the native /v1/messages endpoint handles vision\n * without requiring the header.\n *\n * extraHeaders allows callers to forward client-supplied beta headers\n * (anthropic-beta) so Copilot enables extended features.\n */\nfunction buildHeaders(\n extraHeaders?: Record<string, string>,\n): Record<string, string> {\n return {\n ...copilotHeaders(state),\n accept: \"application/json\",\n \"X-Initiator\": \"agent\",\n \"anthropic-version\": \"2023-06-01\",\n \"X-Interaction-Id\": randomUUID(),\n ...extraHeaders,\n }\n}\n\n/**\n * Forward an Anthropic Messages API request to Copilot's native /v1/messages endpoint.\n * Returns the raw Response so callers can handle streaming vs non-streaming.\n */\nexport async function createMessages(\n body: string,\n extraHeaders?: Record<string, string>,\n): Promise<Response> {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const headers = buildHeaders(extraHeaders)\n const url = `${copilotBaseUrl(state)}/v1/messages?beta=true`\n consola.debug(`Forwarding to ${url}`)\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n })\n\n if (!response.ok) {\n let errorBody = \"\"\n try {\n errorBody = await response.text()\n } catch {\n errorBody = \"(could not read error body)\"\n }\n consola.error(\n `Copilot /v1/messages error: ${response.status} ${errorBody}`,\n )\n const reconstructed = new Response(errorBody, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n throw new HTTPError(\"Copilot messages request failed\", reconstructed)\n }\n\n return response\n}\n\n/**\n * Forward an Anthropic count_tokens request to Copilot's native endpoint.\n * Returns the raw Response.\n */\nexport async function countTokens(\n body: string,\n extraHeaders?: Record<string, string>,\n): Promise<Response> {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const headers = buildHeaders(extraHeaders)\n const url = `${copilotBaseUrl(state)}/v1/messages/count_tokens?beta=true`\n consola.debug(`Forwarding to ${url}`)\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n })\n\n if (!response.ok) {\n let errorBody = \"\"\n try {\n errorBody = await response.text()\n } catch {\n errorBody = \"(could not read error body)\"\n }\n consola.error(\n `Copilot count_tokens error: ${response.status} ${errorBody}`,\n )\n const reconstructed = new Response(errorBody, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n throw new HTTPError(\"Copilot count_tokens request failed\", reconstructed)\n }\n\n return response\n}\n","import type { Context } from \"hono\"\n\nimport { logRequest } from \"~/lib/request-log\"\nimport { filterBetaHeader, resolveModel } from \"~/lib/utils\"\nimport { state } from \"~/lib/state\"\nimport { countTokens } from \"~/services/copilot/create-messages\"\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyRecord = Record<string, any>\n\nconst isWebSearchTool = (tool: AnyRecord): boolean =>\n (typeof tool.type === \"string\" && tool.type.startsWith(\"web_search\")) ||\n tool.name === \"web_search\"\n\n/**\n * Strip web_search tools from the request body before forwarding\n * to Copilot's count_tokens endpoint, which rejects unknown tool types.\n * Returns the original raw body if no web_search tools are present.\n */\nfunction stripWebSearchFromBody(rawBody: string): string {\n if (!rawBody.includes(\"web_search\")) return rawBody\n\n let body: AnyRecord\n try {\n body = JSON.parse(rawBody)\n } catch {\n return rawBody\n }\n\n const hasWebSearch = body.tools?.some(\n (tool: AnyRecord) => isWebSearchTool(tool),\n )\n if (!hasWebSearch) return rawBody\n\n body.tools = body.tools.filter(\n (tool: AnyRecord) => !isWebSearchTool(tool),\n )\n\n if (body.tools.length === 0) {\n body.tools = undefined\n body.tool_choice = undefined\n } else if (\n body.tool_choice &&\n typeof body.tool_choice === \"object\" &&\n body.tool_choice.type === \"tool\"\n ) {\n const choiceName = body.tool_choice.name\n if (\n choiceName &&\n !body.tools.some((tool: AnyRecord) => tool.name === choiceName)\n ) {\n body.tool_choice = { type: \"auto\" }\n }\n }\n\n return JSON.stringify(body)\n}\n\n/**\n * Passthrough handler for Anthropic token counting.\n * Strips web_search tools and forwards beta headers to Copilot's\n * native /v1/messages/count_tokens endpoint.\n */\nexport async function handleCountTokens(c: Context) {\n const startTime = Date.now()\n const rawBody = await c.req.text()\n const strippedBody = stripWebSearchFromBody(rawBody)\n const { body: finalBody, originalModel, resolvedModel } = resolveModelInBody(strippedBody)\n\n const extraHeaders: Record<string, string> = {}\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n if (anthropicBeta) {\n const filtered = filterBetaHeader(anthropicBeta)\n if (filtered) extraHeaders[\"anthropic-beta\"] = filtered\n }\n\n const response = await countTokens(finalBody, extraHeaders)\n const responseBody = (await response.json()) as { input_tokens?: number }\n\n const modelId = resolvedModel ?? originalModel\n const selectedModel = state.models?.data.find((m) => m.id === modelId)\n\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n inputTokens: responseBody.input_tokens,\n status: response.status,\n },\n selectedModel,\n startTime,\n )\n\n return c.json(responseBody)\n}\n\n/**\n * Parse the JSON body, resolve the model name, and re-serialize.\n */\nfunction resolveModelInBody(rawBody: string): {\n body: string\n originalModel?: string\n resolvedModel?: string\n} {\n let parsed: AnyRecord\n try {\n parsed = JSON.parse(rawBody)\n } catch {\n return { body: rawBody }\n }\n\n const originalModel =\n typeof parsed.model === \"string\" ? parsed.model : undefined\n if (!originalModel) return { body: rawBody, originalModel }\n\n const resolved = resolveModel(originalModel)\n if (resolved === originalModel)\n return { body: rawBody, originalModel, resolvedModel: originalModel }\n\n parsed.model = resolved\n return {\n body: JSON.stringify(parsed),\n originalModel,\n resolvedModel: resolved,\n }\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { logRequest } from \"~/lib/request-log\"\nimport { state } from \"~/lib/state\"\nimport { filterBetaHeader, resolveModel } from \"~/lib/utils\"\nimport { createMessages } from \"~/services/copilot/create-messages\"\nimport { searchWeb } from \"~/services/copilot/web-search\"\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyRecord = Record<string, any>\n\nconst isWebSearchTool = (tool: AnyRecord): boolean =>\n (typeof tool.type === \"string\" && tool.type.startsWith(\"web_search\")) ||\n tool.name === \"web_search\"\n\n/**\n * Extract whitelisted beta headers from the incoming request to forward\n * to the Copilot API. VS Code sends these to enable extended features\n * like thinking, context management, and advanced tool use.\n */\nfunction extractBetaHeaders(c: Context): Record<string, string> {\n const headers: Record<string, string> = {}\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n if (anthropicBeta) {\n const filtered = filterBetaHeader(anthropicBeta)\n if (filtered) headers[\"anthropic-beta\"] = filtered\n }\n return headers\n}\n\n/**\n * Extract the text content from the last user message for web search.\n * Handles both string content and content block arrays (multimodal).\n */\nfunction extractUserQuery(\n messages: Array<AnyRecord>,\n): string | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") return msg.content\n if (Array.isArray(msg.content)) {\n const textBlock = msg.content.find(\n (block: AnyRecord) => block.type === \"text\",\n )\n if (textBlock?.text) return textBlock.text as string\n }\n }\n }\n return undefined\n}\n\n/**\n * Check if any user message contains tool_result content blocks,\n * indicating a follow-up turn where we should skip web search.\n * In Anthropic format, tool results are content blocks inside user messages,\n * NOT separate role: \"tool\" messages like in OpenAI format.\n */\nfunction hasToolResultContent(messages: Array<AnyRecord>): boolean {\n return messages.some(\n (msg) =>\n Array.isArray(msg.content) &&\n msg.content.some(\n (block: AnyRecord) => block.type === \"tool_result\",\n ),\n )\n}\n\n/**\n * Inject web search results into the Anthropic system field.\n * Handles three cases: absent, string, or array of content blocks.\n * When array, prepends without cache_control to preserve existing directives.\n */\nfunction injectSearchResults(\n body: AnyRecord,\n searchContext: string,\n): void {\n if (body.system === undefined || body.system === null) {\n body.system = searchContext\n } else if (typeof body.system === \"string\") {\n body.system = `${searchContext}\\n\\n${body.system}`\n } else if (Array.isArray(body.system)) {\n body.system = [\n { type: \"text\", text: searchContext },\n ...body.system,\n ]\n }\n}\n\n/**\n * Strip web_search tools from the request and clean up tool_choice.\n * Returns the modified body object.\n */\nfunction stripWebSearchTool(body: AnyRecord): void {\n if (!body.tools) return\n\n body.tools = body.tools.filter(\n (tool: AnyRecord) => !isWebSearchTool(tool),\n )\n\n if (body.tools.length === 0) {\n body.tools = undefined\n body.tool_choice = undefined\n } else if (\n body.tool_choice &&\n typeof body.tool_choice === \"object\" &&\n body.tool_choice.type === \"tool\"\n ) {\n // If tool_choice forced the removed web_search tool, fall back to auto\n const choiceName = body.tool_choice.name\n if (\n choiceName &&\n !body.tools.some((tool: AnyRecord) => tool.name === choiceName)\n ) {\n body.tool_choice = { type: \"auto\" }\n }\n }\n}\n\n/**\n * Process web search if the request contains a web_search tool.\n * Performs the search, injects results into system, and strips the tool.\n * Returns the (possibly modified) body string to forward.\n */\nasync function processWebSearch(rawBody: string): Promise<string> {\n // Fast path: skip parsing if no web_search tool present\n if (!rawBody.includes(\"web_search\")) return rawBody\n\n let body: AnyRecord\n try {\n body = JSON.parse(rawBody)\n } catch {\n return rawBody\n }\n\n const hasWebSearch = body.tools?.some(\n (tool: AnyRecord) => isWebSearchTool(tool),\n )\n if (!hasWebSearch) return rawBody\n\n // Skip search on follow-up messages (tool call results)\n const hasToolResult = hasToolResultContent(body.messages ?? [])\n const query = hasToolResult ? undefined : extractUserQuery(body.messages ?? [])\n\n if (query) {\n try {\n const results = await searchWeb(query)\n const searchContext = [\n \"[Web Search Results]\",\n results.content,\n \"\",\n results.references.map((r) => `- [${r.title}](${r.url})`).join(\"\\n\"),\n \"[End Web Search Results]\",\n ].join(\"\\n\")\n\n injectSearchResults(body, searchContext)\n } catch (error) {\n consola.warn(\"Web search failed, continuing without results:\", error)\n }\n }\n\n // Always strip web_search tool regardless of whether search succeeded\n stripWebSearchTool(body)\n\n return JSON.stringify(body)\n}\n\nexport async function handleCompletion(c: Context) {\n const startTime = Date.now()\n await checkRateLimit(state)\n\n const rawBody = await c.req.text()\n\n const debugEnabled = consola.level >= 4\n if (debugEnabled) {\n consola.debug(\"Anthropic request body:\", rawBody.slice(0, 2000))\n }\n\n if (state.manualApprove) {\n await awaitApproval()\n }\n\n const betaHeaders = extractBetaHeaders(c)\n const finalBody = await processWebSearch(rawBody)\n\n // Resolve model name (e.g. opus → opus-1m variant)\n const { body: resolvedBody, originalModel, resolvedModel } = resolveModelInBody(finalBody)\n\n // Look up model metadata for context window info\n const selectedModel = state.models?.data.find(\n (m) => m.id === (resolvedModel ?? originalModel),\n )\n\n const response = await createMessages(resolvedBody, betaHeaders)\n\n const contentType = response.headers.get(\"content-type\") ?? \"\"\n const isStreaming = contentType.includes(\"text/event-stream\")\n\n // Streaming: pipe the upstream SSE response body directly\n if (isStreaming) {\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n status: response.status,\n streaming: true,\n },\n selectedModel,\n startTime,\n )\n\n if (debugEnabled) {\n consola.debug(\"Streaming response from Copilot /v1/messages\")\n }\n return new Response(response.body, {\n status: response.status,\n headers: {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n },\n })\n }\n\n // Non-streaming: extract usage from response body\n const responseBody = (await response.json()) as AnyRecord\n\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n inputTokens: responseBody.usage?.input_tokens,\n outputTokens: responseBody.usage?.output_tokens,\n status: response.status,\n },\n selectedModel,\n startTime,\n )\n\n if (debugEnabled) {\n consola.debug(\n \"Non-streaming response from Copilot /v1/messages:\",\n JSON.stringify(responseBody).slice(0, 2000),\n )\n }\n return c.json(responseBody, response.status as 200)\n}\n\n/**\n * Parse the JSON body, resolve the model name, and re-serialize.\n * Returns the body string plus the original and resolved model names.\n */\nfunction resolveModelInBody(rawBody: string): {\n body: string\n originalModel?: string\n resolvedModel?: string\n} {\n let parsed: AnyRecord\n try {\n parsed = JSON.parse(rawBody)\n } catch {\n return { body: rawBody }\n }\n\n const originalModel =\n typeof parsed.model === \"string\" ? parsed.model : undefined\n if (!originalModel) return { body: rawBody, originalModel }\n\n const resolved = resolveModel(originalModel)\n if (resolved === originalModel)\n return { body: rawBody, originalModel, resolvedModel: originalModel }\n\n parsed.model = resolved\n return {\n body: JSON.stringify(parsed),\n originalModel,\n resolvedModel: resolved,\n }\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCountTokens } from \"./count-tokens-handler\"\nimport { handleCompletion } from \"./handler\"\n\nexport const messageRoutes = new Hono()\n\nmessageRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n return await handleCountTokens(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { 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 { events } from \"fetch-event-stream\"\n\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const createResponses = async (payload: ResponsesPayload) => {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const enableVision = detectVision(payload.input)\n\n const isAgentCall = detectAgentCall(payload.input)\n\n const headers: Record<string, string> = {\n ...copilotHeaders(state, enableVision),\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n }\n\n const filteredPayload = filterUnsupportedTools(payload)\n\n const response = await fetch(`${copilotBaseUrl(state)}/responses`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(filteredPayload),\n })\n\n if (!response.ok) {\n consola.error(\"Failed to create responses\", response)\n throw new HTTPError(\"Failed to create responses\", response)\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ResponsesApiResponse\n}\n\nfunction detectVision(input: ResponsesPayload[\"input\"]): boolean {\n if (typeof input === \"string\") return false\n if (!Array.isArray(input)) return false\n\n return input.some((item) => {\n if (\"content\" in item && Array.isArray(item.content)) {\n return item.content.some(\n (part: Record<string, unknown>) => part.type === \"input_image\",\n )\n }\n return false\n })\n}\n\nfunction detectAgentCall(input: ResponsesPayload[\"input\"]): boolean {\n if (typeof input === \"string\") return false\n if (!Array.isArray(input)) return false\n\n return input.some((item) => {\n if (\"role\" in item && item.role === \"assistant\") return true\n if (\n \"type\" in item\n && (item.type === \"function_call\" || item.type === \"function_call_output\")\n ) {\n return true\n }\n return false\n })\n}\n\nfunction filterUnsupportedTools(payload: ResponsesPayload): ResponsesPayload {\n if (!payload.tools || !Array.isArray(payload.tools)) return payload\n\n const supported = payload.tools.filter((tool) => {\n const isSupported = tool.type === \"function\"\n if (!isSupported) {\n consola.debug(`Stripping unsupported tool type: ${tool.type}`)\n }\n return isSupported\n })\n\n let toolChoice = payload.tool_choice\n if (supported.length === 0) {\n toolChoice = undefined\n } else if (\n toolChoice\n && typeof toolChoice === \"object\"\n ) {\n const supportedNames = new Set(\n supported.map((tool) => tool.name).filter(Boolean),\n )\n const toolChoiceName = getToolChoiceName(toolChoice)\n if (toolChoiceName && !supportedNames.has(toolChoiceName)) {\n toolChoice = undefined\n }\n }\n\n return {\n ...payload,\n tools: supported.length > 0 ? supported : undefined,\n tool_choice: toolChoice,\n }\n}\n\nfunction getToolChoiceName(\n toolChoice: NonNullable<ResponsesPayload[\"tool_choice\"]>,\n): string | undefined {\n if (typeof toolChoice !== \"object\") return undefined\n if (\n \"function\" in toolChoice\n && toolChoice.function\n && typeof toolChoice.function === \"object\"\n ) {\n return (toolChoice.function as { name?: string }).name\n }\n if (\"name\" in toolChoice) {\n return toolChoice.name\n }\n return undefined\n}\n\n// Types\n\nexport interface ResponsesInputItem {\n role?: \"user\" | \"assistant\" | \"system\"\n type?: \"message\" | \"function_call\" | \"function_call_output\"\n content?: string | Array<Record<string, unknown>>\n name?: string\n call_id?: string\n arguments?: string\n output?: string\n [key: string]: unknown\n}\n\nexport interface ResponsesTool {\n type: string\n name?: string\n description?: string\n parameters?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport interface ResponsesPayload {\n model: string\n input: string | Array<ResponsesInputItem>\n instructions?: string\n tools?: Array<ResponsesTool>\n tool_choice?:\n | string\n | { type: string; name?: string; function?: { name?: string } }\n max_output_tokens?: number\n temperature?: number\n top_p?: number\n stream?: boolean\n store?: boolean\n metadata?: Record<string, string>\n previous_response_id?: string\n reasoning?: { effort?: string; summary?: string }\n [key: string]: unknown\n}\n\nexport interface ResponsesApiResponse {\n id: string\n object: \"response\"\n status: string\n output: Array<unknown>\n [key: string]: unknown\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 { logRequest } from \"~/lib/request-log\"\nimport { state } from \"~/lib/state\"\nimport { isNullish, resolveModel } from \"~/lib/utils\"\nimport {\n createResponses,\n type ResponsesApiResponse,\n type ResponsesInputItem,\n type ResponsesPayload,\n} from \"~/services/copilot/create-responses\"\nimport { searchWeb } from \"~/services/copilot/web-search\"\n\nexport async function handleResponses(c: Context) {\n const startTime = Date.now()\n await checkRateLimit(state)\n\n const payload = await c.req.json<ResponsesPayload>()\n const debugEnabled = consola.level >= 4\n if (debugEnabled) {\n consola.debug(\n \"Responses request payload:\",\n JSON.stringify(payload).slice(-400),\n )\n }\n\n // Resolve model name (e.g. opus → opus-1m variant)\n const originalModel = payload.model\n const resolvedModel = resolveModel(payload.model)\n if (resolvedModel !== payload.model) {\n payload.model = resolvedModel\n }\n\n const selectedModel = state.models?.data.find(\n (model) => model.id === payload.model,\n )\n\n if (state.manualApprove) await awaitApproval()\n\n await injectWebSearchIfNeeded(payload)\n\n if (isNullish(payload.max_output_tokens)) {\n payload.max_output_tokens =\n selectedModel?.capabilities.limits.max_output_tokens\n if (debugEnabled) {\n consola.debug(\n \"Set max_output_tokens to:\",\n JSON.stringify(payload.max_output_tokens),\n )\n }\n }\n\n const response = await createResponses(payload)\n const isStreaming = !isNonStreaming(response)\n\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n status: 200,\n streaming: isStreaming,\n },\n selectedModel,\n startTime,\n )\n\n if (!isStreaming) {\n if (debugEnabled) {\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\n }\n return c.json(response)\n }\n\n return streamSSE(c, async (stream) => {\n for await (const chunk of response) {\n if (debugEnabled) {\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\n }\n\n if (chunk.data === \"[DONE]\") {\n break\n }\n\n if (!chunk.data) {\n continue\n }\n\n await stream.writeSSE({\n data: chunk.data,\n event: chunk.event,\n id: chunk.id?.toString(),\n })\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createResponses>>,\n): response is ResponsesApiResponse => Object.hasOwn(response, \"output\")\n\nasync function injectWebSearchIfNeeded(\n payload: ResponsesPayload,\n): Promise<void> {\n const hasWebSearch = payload.tools?.some((t) => t.type === \"web_search\")\n if (!hasWebSearch) return\n\n // Skip search on follow-up messages (function call results)\n if (Array.isArray(payload.input)) {\n const hasFollowUp = payload.input.some(\n (item: ResponsesInputItem) => item.type === \"function_call_output\",\n )\n if (hasFollowUp) return\n }\n\n const query = extractUserQuery(payload.input)\n if (!query) return\n\n try {\n const results = await searchWeb(query)\n const searchContext = [\n \"[Web Search Results]\",\n results.content,\n \"\",\n results.references.map((r) => `- [${r.title}](${r.url})`).join(\"\\n\"),\n \"[End Web Search Results]\",\n ].join(\"\\n\")\n\n payload.instructions =\n payload.instructions ?\n `${searchContext}\\n\\n${payload.instructions}`\n : searchContext\n } catch (error) {\n consola.warn(\"Web search failed, continuing without results:\", error)\n }\n}\n\nfunction extractUserQuery(\n input: ResponsesPayload[\"input\"],\n): string | undefined {\n if (typeof input === \"string\") return input\n if (!Array.isArray(input)) return undefined\n\n // Find the last user message\n for (let i = input.length - 1; i >= 0; i--) {\n const item = input[i]\n if (\"role\" in item && item.role === \"user\") {\n if (typeof item.content === \"string\") return item.content\n if (Array.isArray(item.content)) {\n const text = item.content.find(\n (p: Record<string, unknown>) => p.type === \"input_text\",\n )\n if (text && \"text\" in text) return text.text as string\n }\n }\n }\n return undefined\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleResponses } from \"./handler\"\n\nexport const responsesRoutes = new Hono()\n\nresponsesRoutes.post(\"/\", async (c) => {\n try {\n return await handleResponses(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport { searchWeb } from \"~/services/copilot/web-search\"\n\nexport const searchRoutes = new Hono()\n\nsearchRoutes.post(\"/\", async (c) => {\n try {\n const { query } = await c.req.json<{ query: string }>()\n\n if (!query || typeof query !== \"string\") {\n return c.json(\n { error: { message: \"Missing required field: query\" } },\n 400,\n )\n }\n\n const results = await searchWeb(query)\n return c.json({ results })\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\n\nexport const tokenRoute = new Hono()\n\ntokenRoute.get(\"/\", (c) => {\n if (!state.showToken) {\n return c.json(\n { error: { message: \"Token endpoint disabled\", type: \"error\" } },\n 403,\n )\n }\n\n return c.json({\n token: state.copilotToken,\n })\n})\n","import { Hono } from \"hono\"\nimport consola from \"consola\"\n\nimport { forwardError } from \"~/lib/error\"\nimport { getCopilotUsage } from \"~/services/github/get-copilot-usage\"\n\nexport const usageRoute = new Hono()\n\nusageRoute.get(\"/\", async (c) => {\n try {\n const usage = await getCopilotUsage()\n return c.json(usage)\n } catch (error) {\n consola.error(\"Error fetching Copilot usage:\", error)\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\nimport { cors } from \"hono/cors\"\n\nimport { completionRoutes } from \"./routes/chat-completions/route\"\nimport { embeddingRoutes } from \"./routes/embeddings/route\"\nimport { messageRoutes } from \"./routes/messages/route\"\nimport { modelRoutes } from \"./routes/models/route\"\nimport { responsesRoutes } from \"./routes/responses/route\"\nimport { searchRoutes } from \"./routes/search/route\"\nimport { tokenRoute } from \"./routes/token/route\"\nimport { usageRoute } from \"./routes/usage/route\"\n\nexport const server = new Hono()\n\nserver.use(cors())\n\nserver.get(\"/\", (c) => c.text(\"Server running\"))\n\nserver.route(\"/chat/completions\", completionRoutes)\nserver.route(\"/responses\", responsesRoutes)\nserver.route(\"/models\", modelRoutes)\nserver.route(\"/embeddings\", embeddingRoutes)\nserver.route(\"/search\", searchRoutes)\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/responses\", responsesRoutes)\nserver.route(\"/v1/models\", modelRoutes)\nserver.route(\"/v1/embeddings\", embeddingRoutes)\nserver.route(\"/v1/search\", searchRoutes)\n\n// Anthropic compatible endpoints\nserver.route(\"/v1/messages\", messageRoutes)\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\nimport { serve, type ServerHandler } from \"srvx\"\nimport invariant from \"tiny-invariant\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport { setupCopilotToken, setupGitHubToken } from \"./lib/token\"\nimport { cacheModels, cacheVSCodeVersion } from \"./lib/utils\"\nimport type { Model } from \"./services/copilot/get-models\"\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 codex: boolean\n showToken: boolean\n proxyEnv: boolean\n}\n\nconst allowedAccountTypes = new Set([\"individual\", \"business\", \"enterprise\"])\n\nfunction printAndCopyCommand(command: string, label: string): void {\n consola.box(`${label}\\n\\n${command}`)\n try {\n clipboard.writeSync(command)\n consola.success(`Copied ${label} command to clipboard!`)\n } catch {\n consola.warn(\"Failed to copy to clipboard. Copy the command above manually.\")\n }\n}\n\nfunction filterModelsByEndpoint(\n models: Array<Model>,\n endpoint: string,\n): Array<Model> {\n const filtered = models.filter((model) => {\n const endpoints = model.supported_endpoints\n // Some deployments omit supported_endpoints; keep those models visible.\n if (!endpoints || endpoints.length === 0) return true\n return endpoints.some((entry) => {\n const normalized = entry.replace(/^\\/?v1\\//, \"\").replace(/^\\//, \"\")\n return normalized === endpoint\n })\n })\n\n return filtered.length > 0 ? filtered : models\n}\n\nasync function generateClaudeCodeCommand(serverUrl: string) {\n invariant(state.models, \"Models should be loaded by now\")\n\n const claudeModels = state.models.data.filter((model) =>\n model.id.toLowerCase().startsWith(\"claude\"),\n )\n\n if (claudeModels.length === 0) {\n consola.error(\"No Claude models available from Copilot API\")\n return\n }\n\n // Pick the best main model: prefer opus, then sonnet, then first available\n const mainModel =\n claudeModels.find((m) => m.id.includes(\"opus\")) ??\n claudeModels.find((m) => m.id.includes(\"sonnet\")) ??\n claudeModels[0]\n\n // Pick the best small model: prefer haiku, then sonnet, then first available\n const smallModel =\n claudeModels.find((m) => m.id.includes(\"haiku\")) ??\n claudeModels.find((m) => m.id.includes(\"sonnet\")) ??\n claudeModels[0]\n\n // Only prompt if there are multiple options and the user might want to override\n let selectedModel = mainModel.id\n let selectedSmallModel = smallModel.id\n\n if (claudeModels.length > 1) {\n consola.info(\n `Using ${mainModel.id} as main model and ${smallModel.id} as small model`,\n )\n const override = await consola.prompt(\"Override model selection?\", {\n type: \"confirm\",\n initial: false,\n })\n\n if (override) {\n selectedModel = await consola.prompt(\n \"Select a main model for Claude Code\",\n {\n type: \"select\",\n options: claudeModels.map((model) => model.id),\n },\n )\n selectedSmallModel = await consola.prompt(\n \"Select a small/fast model for Claude Code\",\n {\n type: \"select\",\n options: claudeModels.map((model) => model.id),\n },\n )\n }\n }\n\n const command = generateEnvScript(\n {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: \"dummy\",\n ANTHROPIC_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel,\n ANTHROPIC_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 --dangerously-skip-permissions\",\n )\n\n printAndCopyCommand(command, \"Claude Code\")\n}\n\nasync function generateCodexCommand(serverUrl: string) {\n invariant(state.models, \"Models should be loaded by now\")\n\n const supportedModels = filterModelsByEndpoint(\n state.models.data,\n \"responses\",\n )\n\n const defaultCodexModel = supportedModels.find(\n (model) => model.id === \"gpt5.2-codex\",\n )\n\n const selectedModel =\n defaultCodexModel ?\n defaultCodexModel.id\n : await consola.prompt(\"Select a model to use with Codex CLI\", {\n type: \"select\",\n options: supportedModels.map((model) => model.id),\n })\n\n const quotedModel = JSON.stringify(selectedModel)\n const command = generateEnvScript(\n {\n OPENAI_BASE_URL: `${serverUrl}/v1`,\n OPENAI_API_KEY: \"dummy\",\n },\n `codex -m ${quotedModel}`,\n )\n\n printAndCopyCommand(command, \"Codex CLI\")\n}\n\nexport async function runServer(options: RunServerOptions): Promise<void> {\n if (options.proxyEnv) {\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\n await ensurePaths()\n await cacheVSCodeVersion()\n\n if (options.githubToken) {\n state.githubToken = options.githubToken\n consola.info(\"Using provided GitHub token\")\n } else {\n await setupGitHubToken()\n }\n\n await setupCopilotToken()\n await cacheModels()\n\n consola.info(\n `Available models: \\n${state.models?.data.map((model) => `- ${model.id}`).join(\"\\n\")}`,\n )\n\n const serverUrl = `http://localhost:${options.port}`\n\n if (options.claudeCode) await generateClaudeCodeCommand(serverUrl)\n if (options.codex) await generateCodexCommand(serverUrl)\n\n consola.box(\n `🌐 Usage Viewer: https://animeshkundu.github.io/github-router/dashboard.html?endpoint=${serverUrl}/usage`,\n )\n\n serve({\n fetch: server.fetch as ServerHandler,\n hostname: \"127.0.0.1\",\n port: options.port,\n })\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the github-router server\",\n },\n args: {\n port: {\n alias: \"p\",\n type: \"string\",\n default: \"8787\",\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: \"enterprise\",\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 codex: {\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Codex CLI with Copilot API config\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub and Copilot tokens on fetch and refresh\",\n },\n \"proxy-env\": {\n type: \"boolean\",\n default: false,\n description: \"Initialize proxy from environment variables\",\n },\n },\n run({ args }) {\n const rateLimitRaw = args[\"rate-limit\"]\n let rateLimit: number | undefined\n if (rateLimitRaw !== undefined) {\n rateLimit = Number.parseInt(rateLimitRaw, 10)\n if (Number.isNaN(rateLimit) || rateLimit <= 0) {\n throw new Error(\"Invalid rate limit. Must be a positive integer.\")\n }\n }\n\n const port = Number.parseInt(args.port, 10)\n if (Number.isNaN(port) || port <= 0 || port > 65535) {\n throw new Error(\"Invalid port. Must be between 1 and 65535.\")\n }\n\n const accountType = args[\"account-type\"]\n if (!allowedAccountTypes.has(accountType)) {\n throw new Error(\n \"Invalid account type. Must be individual, business, or enterprise.\",\n )\n }\n\n const rateLimitWait = args.wait && rateLimit !== undefined\n if (args.wait && rateLimit === undefined) {\n consola.warn(\"Rate limit wait ignored because no rate limit was set.\")\n }\n\n const githubToken = args[\"github-token\"] ?? process.env.GH_TOKEN\n\n return runServer({\n port,\n verbose: args.verbose,\n accountType,\n manual: args.manual,\n rateLimit,\n rateLimitWait,\n githubToken,\n claudeCode: args[\"claude-code\"],\n codex: args.codex,\n showToken: args[\"show-token\"],\n proxyEnv: args[\"proxy-env\"],\n })\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand, runMain } from \"citty\"\n\nimport { auth } from \"./auth\"\nimport { checkUsage } from \"./check-usage\"\nimport { debug } from \"./debug\"\nimport { start } from \"./start\"\n\nconst main = defineCommand({\n meta: {\n name: \"github-router\",\n description:\n \"A reverse proxy that exposes GitHub Copilot as OpenAI and Anthropic compatible API endpoints.\",\n },\n subCommands: { auth, start, \"check-usage\": checkUsage, debug },\n})\n\nawait runMain(main)\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"main.js","names":["state: State","state","headers: Record<string, string>","errorJson: unknown","token","process","child: ReturnType<typeof Bun.spawn>","server","state","parts: Array<string>","x","headers: Record<string, string>","searchTimestamps: Array<number>","references: Array<{ title: string; url: string }>","handleCompletion","injectWebSearchIfNeeded","inputTokens: number | undefined","isNonStreaming","extractUserQuery","handleCompletion","isWebSearchTool","body: AnyRecord","resolveModelInBody","extraHeaders: Record<string, string>","parsed: AnyRecord","headers: Record<string, string>","extractUserQuery","body: AnyRecord","response: Response","parsed: AnyRecord","headers: Record<string, string>","app","srvxServer: ReturnType<typeof serve> | undefined","lastError: unknown","port: number | undefined","rateLimit: number | undefined","vars: Record<string, string>","process","server: Awaited<ReturnType<typeof setupAndServe>>[\"server\"]","serverUrl: string","server","process","server: Awaited<ReturnType<typeof setupAndServe>>[\"server\"]","serverUrl: string","server","process","commandBlock: string"],"sources":["../src/lib/paths.ts","../src/lib/state.ts","../src/lib/api-config.ts","../src/lib/error.ts","../src/services/github/get-copilot-token.ts","../src/services/github/get-device-code.ts","../src/services/github/get-user.ts","../src/services/copilot/get-models.ts","../src/services/get-vscode-version.ts","../src/lib/utils.ts","../src/services/github/poll-access-token.ts","../src/lib/token.ts","../src/auth.ts","../src/services/github/get-copilot-usage.ts","../src/check-usage.ts","../src/lib/port.ts","../src/lib/launch.ts","../src/lib/proxy.ts","../src/lib/approval.ts","../src/lib/rate-limit.ts","../src/lib/request-log.ts","../src/lib/tokenizer.ts","../src/services/copilot/create-chat-completions.ts","../src/services/copilot/web-search.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/services/copilot/create-messages.ts","../src/routes/messages/count-tokens-handler.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/services/copilot/create-responses.ts","../src/routes/responses/handler.ts","../src/routes/responses/route.ts","../src/routes/search/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts","../src/lib/server-setup.ts","../src/claude.ts","../src/codex.ts","../src/debug.ts","../src/lib/shell.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport os from \"node:os\"\nimport path from \"node:path\"\n\nconst APP_DIR = path.join(os.homedir(), \".local\", \"share\", \"github-router\")\n\nconst GITHUB_TOKEN_PATH = path.join(APP_DIR, \"github_token\")\n\nexport const PATHS = {\n APP_DIR,\n GITHUB_TOKEN_PATH,\n}\n\nexport async function ensurePaths(): Promise<void> {\n await fs.mkdir(PATHS.APP_DIR, { recursive: true })\n await ensureFile(PATHS.GITHUB_TOKEN_PATH)\n}\n\nasync function ensureFile(filePath: string): Promise<void> {\n try {\n await fs.access(filePath, fs.constants.W_OK)\n } catch {\n await fs.writeFile(filePath, \"\")\n await fs.chmod(filePath, 0o600)\n }\n}\n","import { randomBytes, randomUUID } from \"node:crypto\"\n\nimport type { ModelsResponse } from \"~/services/copilot/get-models\"\n\nexport interface State {\n githubToken?: string\n copilotToken?: string\n\n accountType: string\n copilotApiUrl?: string\n models?: ModelsResponse\n vsCodeVersion?: string\n\n manualApprove: boolean\n rateLimitWait: boolean\n showToken: boolean\n\n // Rate limiting configuration\n rateLimitSeconds?: number\n lastRequestTimestamp?: number\n\n // Persistent session identifiers to match VS Code fingerprint\n sessionId: string\n machineId: string\n}\n\nexport const state: State = {\n accountType: \"enterprise\",\n manualApprove: false,\n rateLimitWait: false,\n showToken: false,\n sessionId: randomUUID(),\n machineId: randomBytes(32).toString(\"hex\"),\n}\n","import { randomUUID } from \"node:crypto\"\n\nimport type { State } from \"./state\"\n\nexport const standardHeaders = () => ({\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n})\n\nconst COPILOT_VERSION = \"0.38.2026021302\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\nconst API_VERSION = \"2025-10-01\"\n\nexport const copilotBaseUrl = (state: State) =>\n state.copilotApiUrl ?? \"https://api.githubcopilot.com\"\nexport const copilotHeaders = (\n state: State,\n vision: boolean = false,\n integrationId: string = \"vscode-chat\",\n) => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${state.copilotToken}`,\n \"content-type\": standardHeaders()[\"content-type\"],\n \"copilot-integration-id\": integrationId,\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"openai-intent\": \"conversation-panel\",\n \"x-interaction-type\": \"conversation-panel\",\n \"x-github-api-version\": API_VERSION,\n \"x-request-id\": randomUUID(),\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n \"VScode-SessionId\": state.sessionId,\n \"VScode-MachineId\": state.machineId,\n }\n\n if (vision) headers[\"copilot-vision-request\"] = \"true\"\n\n return headers\n}\n\nexport const GITHUB_API_BASE_URL = \"https://api.github.com\"\nexport const githubHeaders = (state: State) => ({\n ...standardHeaders(),\n authorization: `token ${state.githubToken}`,\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": API_VERSION,\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n})\n\nexport const GITHUB_BASE_URL = \"https://github.com\"\nexport const GITHUB_CLIENT_ID = \"Iv1.b507a08c87ecfe98\"\nexport const GITHUB_APP_SCOPES = [\"read:user\"].join(\" \")\n","import type { Context } from \"hono\"\nimport type { ContentfulStatusCode } from \"hono/utils/http-status\"\n\nimport consola from \"consola\"\n\nexport class HTTPError extends Error {\n response: Response\n\n constructor(message: string, response: Response) {\n super(message)\n this.response = response\n }\n}\n\nexport async function forwardError(c: Context, error: unknown) {\n consola.error(\"Error occurred:\", error)\n\n if (error instanceof HTTPError) {\n const errorText = await error.response.text().catch(() => \"\")\n let errorJson: unknown\n try {\n errorJson = JSON.parse(errorText)\n } catch {\n errorJson = undefined\n }\n const message = resolveErrorMessage(errorJson, errorText)\n consola.error(\"HTTP error:\", errorJson ?? errorText)\n return c.json(\n {\n error: {\n message,\n type: \"error\",\n },\n },\n error.response.status as ContentfulStatusCode,\n )\n }\n\n return c.json(\n {\n error: {\n message: error instanceof Error ? error.message : String(error),\n type: \"error\",\n },\n },\n 500,\n )\n}\n\n// Extracts error message from { message } or { error: { message } } payloads.\nfunction resolveErrorMessage(errorJson: unknown, fallback: string): string {\n if (typeof errorJson !== \"object\" || errorJson === null) return fallback\n\n const errorRecord = errorJson as Record<string, unknown>\n if (errorRecord.message !== undefined) return String(errorRecord.message)\n\n if (typeof errorRecord.error === \"object\" && errorRecord.error !== null) {\n const nestedRecord = errorRecord.error as Record<string, unknown>\n if (nestedRecord.message !== undefined) return String(nestedRecord.message)\n }\n\n return fallback\n}\n","import { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotToken = async () => {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(state),\n },\n )\n\n if (!response.ok) throw new HTTPError(\"Failed to get Copilot token\", response)\n\n const data = (await response.json()) as GetCopilotTokenResponse\n\n // Use the API base URL from the token response if available,\n // matching how VS Code determines the CAPI endpoint dynamically.\n if (data.endpoints?.api) {\n state.copilotApiUrl = data.endpoints.api\n }\n\n return data\n}\n\ninterface GetCopilotTokenResponse {\n expires_at: number\n refresh_in: number\n token: string\n endpoints?: {\n api?: string\n proxy?: string\n telemetry?: string\n \"origin-tracker\"?: string\n }\n}\n","import {\n GITHUB_APP_SCOPES,\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\n\nexport async function getDeviceCode(): Promise<DeviceCodeResponse> {\n const response = await fetch(`${GITHUB_BASE_URL}/login/device/code`, {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n scope: GITHUB_APP_SCOPES,\n }),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get device code\", response)\n\n return (await response.json()) as DeviceCodeResponse\n}\n\nexport interface DeviceCodeResponse {\n device_code: string\n user_code: string\n verification_uri: string\n expires_in: number\n interval: number\n}\n","import { GITHUB_API_BASE_URL, standardHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport async function getGitHubUser() {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\n ...standardHeaders(),\n },\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get GitHub user\", response)\n\n return (await response.json()) as GithubUserResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GithubUserResponse {\n login: string\n}\n","import { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getModels = async () => {\n const response = await fetch(`${copilotBaseUrl(state)}/models`, {\n headers: copilotHeaders(state),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get models\", response)\n\n return (await response.json()) as ModelsResponse\n}\n\nexport interface ModelsResponse {\n data: Array<Model>\n object: string\n}\n\ninterface ModelLimits {\n max_context_window_tokens?: number\n max_output_tokens?: number\n max_prompt_tokens?: number\n max_inputs?: number\n}\n\ninterface ModelSupports {\n tool_calls?: boolean\n parallel_tool_calls?: boolean\n dimensions?: boolean\n}\n\ninterface ModelCapabilities {\n family: string\n limits: ModelLimits\n object: string\n supports: ModelSupports\n tokenizer: string\n type: string\n}\n\nexport interface Model {\n capabilities: ModelCapabilities\n id: string\n model_picker_enabled: boolean\n name: string\n object: string\n preview: boolean\n vendor: string\n version: string\n supported_endpoints?: Array<string>\n requestHeaders?: Record<string, string>\n policy?: {\n state: string\n terms: string\n }\n}\n","const FALLBACK = \"1.104.3\"\n\nexport async function getVSCodeVersion() {\n const controller = new AbortController()\n const timeout = setTimeout(() => {\n controller.abort()\n }, 5000)\n\n try {\n const response = await fetch(\n \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=visual-studio-code-bin\",\n {\n signal: controller.signal,\n },\n )\n\n const pkgbuild = await response.text()\n const pkgverRegex = /pkgver=([0-9.]+)/\n const match = pkgbuild.match(pkgverRegex)\n\n if (match) {\n return match[1]\n }\n\n return FALLBACK\n } catch {\n return FALLBACK\n } finally {\n clearTimeout(timeout)\n }\n}\n\nawait getVSCodeVersion()\n","import consola from \"consola\"\n\nimport { getModels } from \"~/services/copilot/get-models\"\nimport { getVSCodeVersion } from \"~/services/get-vscode-version\"\n\nimport { state } from \"./state\"\n\nexport const sleep = (ms: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, ms)\n })\n\nexport const isNullish = (value: unknown): value is null | undefined =>\n value === null || value === undefined\n\n/**\n * Beta values that VS Code Copilot Chat actually sends to the Copilot API.\n * Only these are forwarded; everything else (e.g. context-1m-*) is stripped\n * so our requests match what VS Code produces.\n */\nconst ALLOWED_BETA_PREFIXES = [\n \"interleaved-thinking-\",\n \"context-management-\",\n \"advanced-tool-use-\",\n \"token-counting-\",\n]\n\n/**\n * Filter an `anthropic-beta` header value, keeping only beta flags that\n * VS Code Copilot is known to send. Returns the filtered comma-separated\n * string, or undefined if nothing remains.\n */\nexport function filterBetaHeader(value: string): string | undefined {\n const filtered = value\n .split(\",\")\n .map((v) => v.trim())\n .filter(\n (v) =>\n v && ALLOWED_BETA_PREFIXES.some((prefix) => v.startsWith(prefix)),\n )\n .join(\",\")\n return filtered || undefined\n}\n\n/**\n * Resolve a model name to the best available variant in the Copilot model list.\n * Prefers the 1M context variant for opus models.\n */\nexport function resolveModel(modelId: string): string {\n const models = state.models?.data\n if (!models) return modelId\n\n // Exact match — no remapping needed\n if (models.some((m) => m.id === modelId)) return modelId\n\n // For opus models, prefer the 1m variant\n if (modelId.toLowerCase().includes(\"opus\")) {\n const oneM = models.find((m) => m.id.includes(\"opus\") && m.id.endsWith(\"-1m\"))\n if (oneM) return oneM.id\n }\n\n return modelId\n}\n\nexport async function cacheModels(): Promise<void> {\n const models = await getModels()\n state.models = models\n}\n\nexport const cacheVSCodeVersion = async () => {\n const response = await getVSCodeVersion()\n state.vsCodeVersion = response\n\n consola.info(`Using VSCode version: ${response}`)\n}\n","import consola from \"consola\"\n\nimport {\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { sleep } from \"~/lib/utils\"\n\nimport type { DeviceCodeResponse } from \"./get-device-code\"\n\nexport async function pollAccessToken(\n deviceCode: DeviceCodeResponse,\n): Promise<string> {\n // Interval is in seconds, we need to multiply by 1000 to get milliseconds\n // I'm also adding another second, just to be safe\n const sleepDuration = (deviceCode.interval + 1) * 1000\n consola.debug(`Polling access token with interval of ${sleepDuration}ms`)\n const expiresAt = Date.now() + deviceCode.expires_in * 1000\n\n while (Date.now() < expiresAt) {\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: deviceCode.device_code,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n },\n )\n\n if (!response.ok) {\n consola.error(\"Failed to poll access token:\", await response.text())\n if (Date.now() >= expiresAt) break\n await sleep(sleepDuration)\n continue\n }\n\n const json = await response.json()\n consola.debug(\"Polling access token response:\", json)\n\n const { access_token } = json as AccessTokenResponse\n\n if (access_token) {\n return access_token\n }\n\n if (Date.now() >= expiresAt) break\n await sleep(sleepDuration)\n }\n\n throw new Error(\"Device code expired. Please run auth again.\")\n}\n\ninterface AccessTokenResponse {\n access_token: string\n token_type: string\n scope: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\nimport { getCopilotToken } from \"~/services/github/get-copilot-token\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\nimport { getGitHubUser } from \"~/services/github/get-user\"\nimport { pollAccessToken } from \"~/services/github/poll-access-token\"\n\nimport { HTTPError } from \"./error\"\nimport { state } from \"./state\"\n\nconst readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n\nconst writeGithubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)\n\nexport const setupCopilotToken = async () => {\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n\n // Display the Copilot token to the screen\n consola.debug(\"GitHub Copilot Token fetched successfully!\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n const refreshInterval = Math.max((refresh_in - 60) * 1000, 1000)\n setInterval(async () => {\n consola.debug(\"Refreshing Copilot token\")\n try {\n const { token } = await getCopilotToken()\n state.copilotToken = token\n consola.debug(\"Copilot token refreshed\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n }\n }, refreshInterval)\n}\n\ninterface SetupGitHubTokenOptions {\n force?: boolean\n}\n\nexport async function setupGitHubToken(\n options?: SetupGitHubTokenOptions,\n): Promise<void> {\n try {\n const githubToken = await readGithubToken()\n\n if (githubToken && !options?.force) {\n state.githubToken = githubToken\n if (state.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n await logUser()\n\n return\n }\n\n consola.info(\"Not logged in, getting new access token\")\n const response = await getDeviceCode()\n consola.debug(\"Device code response:\", response)\n\n consola.info(\n `Please enter the code \"${response.user_code}\" in ${response.verification_uri}`,\n )\n\n const token = await pollAccessToken(response)\n await writeGithubToken(token)\n state.githubToken = token\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n await logUser()\n } catch (error) {\n if (error instanceof HTTPError) {\n consola.error(\"Failed to get GitHub token:\", await error.response.json())\n throw error\n }\n\n consola.error(\"Failed to get GitHub token:\", error)\n throw error\n }\n}\n\nasync function logUser() {\n const user = await getGitHubUser()\n consola.info(`Logged in as ${user.login}`)\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 { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotUsage = async (): Promise<CopilotUsageResponse> => {\n const response = await fetch(`${GITHUB_API_BASE_URL}/copilot_internal/user`, {\n headers: githubHeaders(state),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get Copilot usage\", response)\n }\n\n return (await response.json()) as CopilotUsageResponse\n}\n\nexport interface QuotaDetail {\n entitlement: number\n overage_count: number\n overage_permitted: boolean\n percent_remaining: number\n quota_id: string\n quota_remaining: number\n remaining: number\n unlimited: boolean\n}\n\ninterface QuotaSnapshots {\n chat: QuotaDetail\n completions: QuotaDetail\n premium_interactions: QuotaDetail\n}\n\ninterface CopilotUsageResponse {\n access_type_sku: string\n analytics_tracking_id: string\n assigned_date: string\n can_signup_for_limited: boolean\n chat_enabled: boolean\n copilot_plan: string\n organization_login_list: Array<unknown>\n organization_list: Array<unknown>\n quota_reset_date: string\n quota_snapshots: QuotaSnapshots\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { setupGitHubToken } from \"./lib/token\"\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.error(\"Failed to fetch Copilot usage:\", err)\n process.exit(1)\n }\n },\n})\n","export const DEFAULT_PORT = 8787\nexport const DEFAULT_CODEX_MODEL = \"gpt5.3-codex\"\n\nconst PORT_RANGE_MIN = 11000\nconst PORT_RANGE_MAX = 65535\n\n/** Generate a random port number in the range [11000, 65535]. */\nexport function generateRandomPort(): number {\n return (\n Math.floor(Math.random() * (PORT_RANGE_MAX - PORT_RANGE_MIN + 1))\n + PORT_RANGE_MIN\n )\n}\n","import process from \"node:process\"\n\nimport consola from \"consola\"\n\nimport type { Server } from \"srvx\"\n\nimport { DEFAULT_CODEX_MODEL } from \"./port\"\n\nexport interface LaunchTarget {\n kind: \"claude-code\" | \"codex\"\n envVars: Record<string, string>\n extraArgs: string[]\n model?: string\n}\n\nexport function buildLaunchCommand(target: LaunchTarget): {\n cmd: string[]\n env: Record<string, string | undefined>\n} {\n const cmd: string[] =\n target.kind === \"claude-code\"\n ? [\"claude\", \"--dangerously-skip-permissions\", ...target.extraArgs]\n : [\"codex\", \"-m\", target.model ?? DEFAULT_CODEX_MODEL, ...target.extraArgs]\n\n return {\n cmd,\n env: { ...process.env, ...target.envVars },\n }\n}\n\nexport function launchChild(target: LaunchTarget, server: Server): void {\n const { cmd, env } = buildLaunchCommand(target)\n\n const executable = cmd[0]\n if (!Bun.which(executable)) {\n consola.error(\n `\"${executable}\" not found on PATH. Install it first, then try again.`,\n )\n process.exit(1)\n }\n\n let child: ReturnType<typeof Bun.spawn>\n try {\n child = Bun.spawn({\n cmd,\n env,\n stdin: \"inherit\",\n stdout: \"inherit\",\n stderr: \"inherit\",\n })\n } catch (error) {\n consola.error(\n `Failed to launch ${executable}:`,\n error instanceof Error ? error.message : String(error),\n )\n server.close(true).catch(() => {})\n process.exit(1)\n }\n\n let cleaned = false\n let exiting = false\n async function cleanup(): Promise<void> {\n if (cleaned) return\n cleaned = true\n\n try {\n child.kill()\n } catch {\n // Already exited\n }\n\n const timeout = setTimeout(() => process.exit(1), 5000)\n try {\n await server.close(true)\n } catch {\n // Server already closed\n }\n clearTimeout(timeout)\n }\n\n function exit(code: number): void {\n if (exiting) return\n exiting = true\n process.exit(code)\n }\n\n const onSignal = () => {\n cleanup().then(() => exit(130)).catch(() => exit(1))\n }\n process.on(\"SIGINT\", onSignal)\n process.on(\"SIGTERM\", onSignal)\n\n child.exited.then(async (exitCode) => {\n await cleanup()\n exit(exitCode ?? 0)\n }).catch(() => exit(1))\n}\n","import consola from \"consola\"\nimport { getProxyForUrl } from \"proxy-from-env\"\nimport { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from \"undici\"\n\nexport function initProxyFromEnv(): void {\n if (typeof Bun !== \"undefined\") return\n\n try {\n const direct = new Agent()\n const proxies = new Map<string, ProxyAgent>()\n\n // We only need a minimal dispatcher that implements `dispatch` at runtime.\n // Typing the object as `Dispatcher` forces TypeScript to require many\n // additional methods. Instead, keep a plain object and cast when passing\n // to `setGlobalDispatcher`.\n const dispatcher = {\n dispatch(\n options: Dispatcher.DispatchOptions,\n handler: Dispatcher.DispatchHandler,\n ) {\n try {\n const origin =\n typeof options.origin === \"string\" ?\n new URL(options.origin)\n : (options.origin as URL)\n const get = getProxyForUrl as unknown as (\n u: string,\n ) => string | undefined\n const raw = get(origin.toString())\n const proxyUrl = raw && raw.length > 0 ? raw : undefined\n if (!proxyUrl) {\n consola.debug(`HTTP proxy bypass: ${origin.hostname}`)\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n let agent = proxies.get(proxyUrl)\n if (!agent) {\n agent = new ProxyAgent(proxyUrl)\n proxies.set(proxyUrl, agent)\n }\n let label = proxyUrl\n try {\n const u = new URL(proxyUrl)\n label = `${u.protocol}//${u.host}`\n } catch {\n /* noop */\n }\n consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`)\n return (agent as unknown as Dispatcher).dispatch(options, handler)\n } catch {\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n },\n close() {\n return direct.close()\n },\n destroy() {\n return direct.destroy()\n },\n }\n\n 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","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 by user\",\n Response.json({ message: \"Request rejected by user\" }, { 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\nexport async function checkRateLimit(state: State) {\n if (state.rateLimitSeconds === undefined) return\n\n const now = Date.now()\n\n if (!state.lastRequestTimestamp) {\n state.lastRequestTimestamp = now\n return\n }\n\n const elapsedSeconds = (now - state.lastRequestTimestamp) / 1000\n\n if (elapsedSeconds > state.rateLimitSeconds) {\n state.lastRequestTimestamp = now\n return\n }\n\n const waitTimeSeconds = Math.ceil(state.rateLimitSeconds - elapsedSeconds)\n\n if (!state.rateLimitWait) {\n consola.warn(\n `Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`,\n )\n throw new HTTPError(\n \"Rate limit exceeded\",\n Response.json({ message: \"Rate limit exceeded\" }, { status: 429 }),\n )\n }\n\n const waitTimeMs = waitTimeSeconds * 1000\n consola.warn(\n `Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`,\n )\n await sleep(waitTimeMs)\n state.lastRequestTimestamp = Date.now()\n consola.info(\"Rate limit wait completed, proceeding with request\")\n return\n}\n","import consola from \"consola\"\n\nimport type { Model } from \"~/services/copilot/get-models\"\n\nexport interface RequestLogInfo {\n method: string\n path: string\n model?: string\n resolvedModel?: string\n inputTokens?: number\n outputTokens?: number\n status?: number\n streaming?: boolean\n errorBody?: string\n}\n\n/**\n * Format a number with K/M suffix for compact display.\n */\nfunction formatTokens(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`\n return String(n)\n}\n\n/**\n * Build a context window summary: \"in:1.2K out:50 ctx:1.2K/1M (0.1%)\"\n */\nfunction formatTokenInfo(\n inputTokens: number | undefined,\n outputTokens: number | undefined,\n model: Model | undefined,\n): string | undefined {\n if (inputTokens === undefined) return undefined\n\n const parts: Array<string> = []\n const maxPrompt = model?.capabilities.limits.max_prompt_tokens\n\n if (maxPrompt) {\n const pct = ((inputTokens / maxPrompt) * 100).toFixed(1)\n parts.push(`in:${formatTokens(inputTokens)}/${formatTokens(maxPrompt)} (${pct}%)`)\n } else {\n parts.push(`in:${formatTokens(inputTokens)}`)\n }\n\n if (outputTokens !== undefined) {\n parts.push(`out:${formatTokens(outputTokens)}`)\n }\n\n return parts.join(\" \")\n}\n\n/**\n * Print a single summary line for a completed request.\n *\n * Examples:\n * POST /v1/messages claude-opus-4.6-1m in:1.2K/1M (0.1%) out:50 200 2.3s\n * POST /v1/messages claude-opus-4-6→claude-opus-4.6-1m in:743/1M (0.1%) 200 198ms\n * POST /v1/chat/completions claude-sonnet-4 in:15 out:16 200 2.1s stream\n */\nexport function logRequest(\n info: RequestLogInfo,\n model: Model | undefined,\n startTime: number,\n): void {\n const parts: Array<string> = []\n\n parts.push(`${info.method} ${info.path}`)\n\n // Model (show resolution arrow if remapped)\n if (info.resolvedModel && info.resolvedModel !== info.model) {\n parts.push(`${info.model}→${info.resolvedModel}`)\n } else if (info.resolvedModel ?? info.model) {\n parts.push((info.resolvedModel ?? info.model)!)\n }\n\n // Token info with context window fill\n const tokenInfo = formatTokenInfo(info.inputTokens, info.outputTokens, model)\n if (tokenInfo) {\n parts.push(tokenInfo)\n }\n\n // Status\n if (info.status !== undefined) {\n parts.push(String(info.status))\n }\n\n // Duration + streaming flag\n const elapsed = Date.now() - startTime\n const duration =\n elapsed >= 1000 ? `${(elapsed / 1000).toFixed(1)}s` : `${elapsed}ms`\n parts.push(info.streaming ? `${duration} stream` : duration)\n\n const line = parts.join(\" \")\n\n if (detectCapabilityMismatch(info, model)) {\n consola.error(`[MISMATCH] ${line}`)\n } else {\n consola.info(line)\n }\n}\n\n/**\n * Detect when the API rejects a request for token/context reasons\n * that contradict what the /models endpoint reported.\n */\nfunction detectCapabilityMismatch(\n info: RequestLogInfo,\n model: Model | undefined,\n): boolean {\n if (!info.errorBody || !model) return false\n if (!info.status || info.status < 400) return false\n\n const err = info.errorBody.toLowerCase()\n return (\n err.includes(\"token\") ||\n err.includes(\"context\") ||\n err.includes(\"too long\") ||\n err.includes(\"max_tokens\") ||\n err.includes(\"prompt is too long\")\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\" \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 simplifiedMessages = payload.messages\n const inputMessages = simplifiedMessages.filter(\n (msg) => msg.role !== \"assistant\",\n )\n const outputMessages = simplifiedMessages.filter(\n (msg) => msg.role === \"assistant\",\n )\n\n const constants = getModelConstants(model)\n let inputTokens = calculateTokens(inputMessages, encoder, constants)\n if (payload.tools && payload.tools.length > 0) {\n inputTokens += numTokensForTools(payload.tools, encoder, constants)\n }\n const outputTokens = calculateTokens(outputMessages, encoder, constants)\n\n return {\n input: inputTokens,\n output: outputTokens,\n }\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const createChatCompletions = async (\n payload: ChatCompletionsPayload,\n modelHeaders?: Record<string, string>,\n) => {\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 and add X-Initiator\n const headers: Record<string, string> = {\n ...copilotHeaders(state, enableVision),\n ...modelHeaders,\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n }\n\n const response = await fetch(`${copilotBaseUrl(state)}/chat/completions`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n let errorBody = \"\"\n try {\n errorBody = await response.text()\n } catch {\n errorBody = \"(could not read error body)\"\n }\n const claudeModels = state.models?.data\n .filter((m) => m.id.startsWith(\"claude\"))\n .map((m) => m.id)\n .join(\", \") ?? \"(models not loaded)\"\n consola.error(\n `Copilot rejected model \"${payload.model}\": ${response.status} ${errorBody} (available Claude models: ${claudeModels})`,\n )\n // Re-create the response so downstream error handlers can still read the body\n const reconstructed = new Response(errorBody, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n throw new HTTPError(\"Failed to create chat completions\", reconstructed)\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n}\n\n// Streaming types\n\nexport interface ChatCompletionChunk {\n id: string\n object: \"chat.completion.chunk\"\n created: number\n model: string\n choices: Array<Choice>\n system_fingerprint?: string\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n prompt_tokens_details?: {\n cached_tokens: number\n }\n completion_tokens_details?: {\n accepted_prediction_tokens: number\n rejected_prediction_tokens: number\n }\n }\n}\n\ninterface Delta {\n content?: string | null\n role?: \"user\" | \"assistant\" | \"system\" | \"tool\"\n tool_calls?: Array<{\n index: number\n id?: string\n type?: \"function\"\n function?: {\n name?: string\n arguments?: string\n }\n }>\n}\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 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\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 consola from \"consola\"\n\nimport { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { state } from \"~/lib/state\"\nimport { sleep } from \"~/lib/utils\"\n\nexport interface WebSearchResult {\n content: string\n references: Array<{ title: string; url: string }>\n}\n\ninterface ThreadsResponse {\n thread_id: string\n}\n\ninterface ThreadsMessageResponse {\n message: {\n content: string\n references: Array<{\n query?: string\n results?: Array<{\n title: string\n url: string\n reference_type: string\n }>\n }>\n }\n}\n\nconst MAX_SEARCHES_PER_SECOND = 3\nlet searchTimestamps: Array<number> = []\n\nasync function throttleSearch(): Promise<void> {\n const now = Date.now()\n searchTimestamps = searchTimestamps.filter((t) => now - t < 1000)\n if (searchTimestamps.length >= MAX_SEARCHES_PER_SECOND) {\n const waitMs = 1000 - (now - searchTimestamps[0])\n if (waitMs > 0) {\n consola.debug(`Web search rate limited, waiting ${waitMs}ms`)\n await sleep(waitMs)\n }\n }\n searchTimestamps.push(Date.now())\n}\n\nfunction threadsHeaders(): Record<string, string> {\n return copilotHeaders(state, false, \"copilot-chat\")\n}\n\nasync function createThread(): Promise<string> {\n const response = await fetch(`${copilotBaseUrl(state)}/github/chat/threads`, {\n method: \"POST\",\n headers: threadsHeaders(),\n body: JSON.stringify({}),\n })\n\n if (!response.ok) {\n consola.error(\"Failed to create chat thread\", response.status)\n throw new Error(`Failed to create chat thread: ${response.status}`)\n }\n\n const data = (await response.json()) as ThreadsResponse\n return data.thread_id\n}\n\nasync function sendThreadMessage(\n threadId: string,\n query: string,\n): Promise<ThreadsMessageResponse> {\n const response = await fetch(\n `${copilotBaseUrl(state)}/github/chat/threads/${threadId}/messages`,\n {\n method: \"POST\",\n headers: threadsHeaders(),\n body: JSON.stringify({\n content: query,\n intent: \"conversation\",\n skills: [\"web-search\"],\n references: [],\n }),\n },\n )\n\n if (!response.ok) {\n consola.error(\"Failed to send thread message\", response.status)\n throw new Error(`Failed to send thread message: ${response.status}`)\n }\n\n return (await response.json()) as ThreadsMessageResponse\n}\n\nexport async function searchWeb(query: string): Promise<WebSearchResult> {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n await throttleSearch()\n\n consola.info(`Web search: \"${query.slice(0, 80)}\"`)\n\n const threadId = await createThread()\n const response = await sendThreadMessage(threadId, query)\n\n const references: Array<{ title: string; url: string }> = []\n for (const ref of response.message.references ?? []) {\n if (ref.results) {\n for (const result of ref.results) {\n if (result.url && result.reference_type !== \"bing_search\") {\n references.push({ title: result.title, url: result.url })\n }\n }\n }\n }\n\n consola.debug(`Web search returned ${references.length} references`)\n\n return {\n content: response.message.content,\n references,\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 { HTTPError } from \"~/lib/error\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { logRequest } from \"~/lib/request-log\"\nimport { state } from \"~/lib/state\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\nimport { isNullish, resolveModel } from \"~/lib/utils\"\nimport {\n createChatCompletions,\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n type Message,\n} from \"~/services/copilot/create-chat-completions\"\nimport { searchWeb } from \"~/services/copilot/web-search\"\n\nexport async function handleCompletion(c: Context) {\n const startTime = Date.now()\n await checkRateLimit(state)\n\n let payload = await c.req.json<ChatCompletionsPayload>()\n const debugEnabled = consola.level >= 4\n if (debugEnabled) {\n consola.debug(\"Request payload:\", JSON.stringify(payload).slice(-400))\n }\n\n if (state.manualApprove) await awaitApproval()\n\n await injectWebSearchIfNeeded(payload)\n\n // Resolve model name (e.g. opus → opus-1m variant)\n const originalModel = payload.model\n const resolvedModel = resolveModel(payload.model)\n if (resolvedModel !== payload.model) {\n payload.model = resolvedModel\n }\n\n // Find the selected model\n const selectedModel = state.models?.data.find(\n (model) => model.id === payload.model,\n )\n\n // Calculate token count\n let inputTokens: number | undefined\n try {\n if (selectedModel) {\n const tokenCount = await getTokenCount(payload, selectedModel)\n inputTokens = tokenCount.input\n }\n } catch {\n // Token counting is best-effort\n }\n\n if (isNullish(payload.max_tokens)) {\n payload = {\n ...payload,\n max_tokens: selectedModel?.capabilities.limits.max_output_tokens,\n }\n if (debugEnabled) {\n consola.debug(\"Set max_tokens to:\", JSON.stringify(payload.max_tokens))\n }\n }\n\n const response = await createChatCompletions(payload, selectedModel?.requestHeaders).catch(\n async (error: unknown) => {\n if (error instanceof HTTPError) {\n const errorBody = await error.response.clone().text().catch(() => \"\")\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n status: error.response.status,\n errorBody,\n },\n selectedModel,\n startTime,\n )\n }\n throw error\n },\n )\n const isStreaming = !isNonStreaming(response)\n\n // Extract output tokens from non-streaming response (no extra call)\n const outputTokens = !isStreaming\n ? (response as ChatCompletionResponse).usage?.completion_tokens\n : undefined\n\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n inputTokens,\n outputTokens,\n status: 200,\n streaming: isStreaming,\n },\n selectedModel,\n startTime,\n )\n\n if (!isStreaming) {\n if (debugEnabled) {\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\n }\n return c.json(response)\n }\n\n return streamSSE(c, async (stream) => {\n for await (const chunk of response) {\n if (debugEnabled) {\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\n }\n await stream.writeSSE(chunk as SSEMessage)\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n\nasync function injectWebSearchIfNeeded(\n payload: ChatCompletionsPayload,\n): Promise<void> {\n const hasWebSearch = payload.tools?.some(\n (t) =>\n (\"type\" in t && (t as unknown as Record<string, unknown>).type === \"web_search\")\n || t.function?.name === \"web_search\",\n )\n if (!hasWebSearch) return\n\n // Skip search on follow-up messages (tool call results)\n const hasToolResult = payload.messages.some((msg) => msg.role === \"tool\")\n const query = hasToolResult ? undefined : extractUserQuery(payload.messages)\n\n if (query) {\n try {\n const results = await searchWeb(query)\n const searchContext = [\n \"[Web Search Results]\",\n results.content,\n \"\",\n results.references.map((r) => `- [${r.title}](${r.url})`).join(\"\\n\"),\n \"[End Web Search Results]\",\n ].join(\"\\n\")\n\n // Prepend to existing system message or inject a new one\n const systemMsg = payload.messages.find((msg) => msg.role === \"system\")\n if (systemMsg) {\n const existingContent =\n typeof systemMsg.content === \"string\" ? systemMsg.content\n : Array.isArray(systemMsg.content) ?\n systemMsg.content\n .filter((p) => p.type === \"text\")\n .map((p) => (\"text\" in p ? p.text : \"\"))\n .join(\"\\n\")\n : \"\"\n systemMsg.content = `${searchContext}\\n\\n${existingContent}`\n } else {\n payload.messages.unshift({\n role: \"system\",\n content: searchContext,\n })\n }\n } catch (error) {\n consola.warn(\"Web search failed, continuing without results:\", error)\n }\n }\n\n // Remove web_search from tools before forwarding\n payload.tools = payload.tools?.filter(\n (t) =>\n !(\n (\"type\" in t && (t as unknown as Record<string, unknown>).type === \"web_search\")\n || t.function?.name === \"web_search\"\n ),\n ) as typeof payload.tools\n if (payload.tools?.length === 0) {\n payload.tools = undefined\n }\n if (!payload.tools) {\n payload.tool_choice = undefined\n } else if (\n payload.tool_choice\n && typeof payload.tool_choice === \"object\"\n && \"type\" in payload.tool_choice\n && payload.tool_choice.type === \"function\"\n ) {\n const toolChoiceName = payload.tool_choice.function?.name\n if (\n toolChoiceName\n && !payload.tools.some((tool) => tool.function.name === toolChoiceName)\n ) {\n payload.tool_choice = undefined\n }\n }\n}\n\nfunction extractUserQuery(messages: Array<Message>): string | undefined {\n // Find the last user message\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") return msg.content\n if (Array.isArray(msg.content)) {\n const text = msg.content.find((p) => p.type === \"text\")\n if (text && \"text\" in text) return text.text as string\n }\n }\n }\n return undefined\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 { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const createEmbeddings = async (payload: EmbeddingRequest) => {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const response = await fetch(`${copilotBaseUrl(state)}/embeddings`, {\n method: \"POST\",\n headers: copilotHeaders(state),\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 payload = await c.req.json<EmbeddingRequest>()\n const response = await createEmbeddings(payload)\n\n return c.json(response)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { randomUUID } from \"node:crypto\"\n\nimport consola from \"consola\"\n\nimport { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\n/**\n * Build headers that match what VS Code Copilot Chat sends to the Copilot API.\n *\n * copilotHeaders() provides: Authorization, content-type, copilot-integration-id,\n * editor-version, editor-plugin-version, user-agent, openai-intent,\n * x-github-api-version, x-request-id, x-vscode-user-agent-library-version.\n *\n * We add the remaining headers VS Code sends for /v1/messages:\n * - X-Initiator (VS Code sets dynamically; \"agent\" is safe for CLI use)\n * - anthropic-version (VS Code's Anthropic SDK sends this)\n * - X-Interaction-Id (VS Code sends a session-scoped UUID)\n *\n * We intentionally omit copilot-vision-request — VS Code only sends it when\n * images are present, and the native /v1/messages endpoint handles vision\n * without requiring the header.\n *\n * extraHeaders allows callers to forward client-supplied beta headers\n * (anthropic-beta) so Copilot enables extended features.\n */\nfunction buildHeaders(\n extraHeaders?: Record<string, string>,\n): Record<string, string> {\n return {\n ...copilotHeaders(state),\n accept: \"application/json\",\n \"openai-intent\": \"conversation-agent\",\n \"x-interaction-type\": \"conversation-agent\",\n \"X-Initiator\": \"agent\",\n \"anthropic-version\": \"2023-06-01\",\n \"X-Interaction-Id\": randomUUID(),\n ...extraHeaders,\n }\n}\n\n/**\n * Forward an Anthropic Messages API request to Copilot's native /v1/messages endpoint.\n * Returns the raw Response so callers can handle streaming vs non-streaming.\n */\nexport async function createMessages(\n body: string,\n extraHeaders?: Record<string, string>,\n): Promise<Response> {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const headers = buildHeaders(extraHeaders)\n const url = `${copilotBaseUrl(state)}/v1/messages?beta=true`\n consola.debug(`Forwarding to ${url}`)\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n })\n\n if (!response.ok) {\n let errorBody = \"\"\n try {\n errorBody = await response.text()\n } catch {\n errorBody = \"(could not read error body)\"\n }\n consola.error(\n `Copilot /v1/messages error: ${response.status} ${errorBody}`,\n )\n const reconstructed = new Response(errorBody, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n throw new HTTPError(\"Copilot messages request failed\", reconstructed)\n }\n\n return response\n}\n\n/**\n * Forward an Anthropic count_tokens request to Copilot's native endpoint.\n * Returns the raw Response.\n */\nexport async function countTokens(\n body: string,\n extraHeaders?: Record<string, string>,\n): Promise<Response> {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const headers = buildHeaders(extraHeaders)\n const url = `${copilotBaseUrl(state)}/v1/messages/count_tokens?beta=true`\n consola.debug(`Forwarding to ${url}`)\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n })\n\n if (!response.ok) {\n let errorBody = \"\"\n try {\n errorBody = await response.text()\n } catch {\n errorBody = \"(could not read error body)\"\n }\n consola.error(\n `Copilot count_tokens error: ${response.status} ${errorBody}`,\n )\n const reconstructed = new Response(errorBody, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n throw new HTTPError(\"Copilot count_tokens request failed\", reconstructed)\n }\n\n return response\n}\n","import type { Context } from \"hono\"\n\nimport { logRequest } from \"~/lib/request-log\"\nimport { filterBetaHeader, resolveModel } from \"~/lib/utils\"\nimport { state } from \"~/lib/state\"\nimport { countTokens } from \"~/services/copilot/create-messages\"\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyRecord = Record<string, any>\n\nconst isWebSearchTool = (tool: AnyRecord): boolean =>\n (typeof tool.type === \"string\" && tool.type.startsWith(\"web_search\")) ||\n tool.name === \"web_search\"\n\n/**\n * Strip web_search tools from the request body before forwarding\n * to Copilot's count_tokens endpoint, which rejects unknown tool types.\n * Returns the original raw body if no web_search tools are present.\n */\nfunction stripWebSearchFromBody(rawBody: string): string {\n if (!rawBody.includes(\"web_search\")) return rawBody\n\n let body: AnyRecord\n try {\n body = JSON.parse(rawBody)\n } catch {\n return rawBody\n }\n\n const hasWebSearch = body.tools?.some(\n (tool: AnyRecord) => isWebSearchTool(tool),\n )\n if (!hasWebSearch) return rawBody\n\n body.tools = body.tools.filter(\n (tool: AnyRecord) => !isWebSearchTool(tool),\n )\n\n if (body.tools.length === 0) {\n body.tools = undefined\n body.tool_choice = undefined\n } else if (\n body.tool_choice &&\n typeof body.tool_choice === \"object\" &&\n body.tool_choice.type === \"tool\"\n ) {\n const choiceName = body.tool_choice.name\n if (\n choiceName &&\n !body.tools.some((tool: AnyRecord) => tool.name === choiceName)\n ) {\n body.tool_choice = { type: \"auto\" }\n }\n }\n\n return JSON.stringify(body)\n}\n\n/**\n * Passthrough handler for Anthropic token counting.\n * Strips web_search tools and forwards beta headers to Copilot's\n * native /v1/messages/count_tokens endpoint.\n */\nexport async function handleCountTokens(c: Context) {\n const startTime = Date.now()\n const rawBody = await c.req.text()\n const strippedBody = stripWebSearchFromBody(rawBody)\n const { body: finalBody, originalModel, resolvedModel } = resolveModelInBody(strippedBody)\n\n const extraHeaders: Record<string, string> = {}\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n if (anthropicBeta) {\n const filtered = filterBetaHeader(anthropicBeta)\n if (filtered) extraHeaders[\"anthropic-beta\"] = filtered\n }\n\n const modelId = resolvedModel ?? originalModel\n const selectedModel = state.models?.data.find((m) => m.id === modelId)\n\n const response = await countTokens(finalBody, {\n ...selectedModel?.requestHeaders,\n ...extraHeaders,\n })\n const responseBody = (await response.json()) as { input_tokens?: number }\n\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n inputTokens: responseBody.input_tokens,\n status: response.status,\n },\n selectedModel,\n startTime,\n )\n\n return c.json(responseBody)\n}\n\n/**\n * Parse the JSON body, resolve the model name, and re-serialize.\n */\nfunction resolveModelInBody(rawBody: string): {\n body: string\n originalModel?: string\n resolvedModel?: string\n} {\n let parsed: AnyRecord\n try {\n parsed = JSON.parse(rawBody)\n } catch {\n return { body: rawBody }\n }\n\n const originalModel =\n typeof parsed.model === \"string\" ? parsed.model : undefined\n if (!originalModel) return { body: rawBody, originalModel }\n\n const resolved = resolveModel(originalModel)\n if (resolved === originalModel)\n return { body: rawBody, originalModel, resolvedModel: originalModel }\n\n parsed.model = resolved\n return {\n body: JSON.stringify(parsed),\n originalModel,\n resolvedModel: resolved,\n }\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { HTTPError } from \"~/lib/error\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { logRequest } from \"~/lib/request-log\"\nimport { state } from \"~/lib/state\"\nimport { filterBetaHeader, resolveModel } from \"~/lib/utils\"\nimport { createMessages } from \"~/services/copilot/create-messages\"\nimport { searchWeb } from \"~/services/copilot/web-search\"\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyRecord = Record<string, any>\n\nconst isWebSearchTool = (tool: AnyRecord): boolean =>\n (typeof tool.type === \"string\" && tool.type.startsWith(\"web_search\")) ||\n tool.name === \"web_search\"\n\n/**\n * Extract whitelisted beta headers from the incoming request to forward\n * to the Copilot API. VS Code sends these to enable extended features\n * like thinking, context management, and advanced tool use.\n */\nfunction extractBetaHeaders(c: Context): Record<string, string> {\n const headers: Record<string, string> = {}\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n if (anthropicBeta) {\n const filtered = filterBetaHeader(anthropicBeta)\n if (filtered) headers[\"anthropic-beta\"] = filtered\n }\n return headers\n}\n\n/**\n * Extract the text content from the last user message for web search.\n * Handles both string content and content block arrays (multimodal).\n */\nfunction extractUserQuery(\n messages: Array<AnyRecord>,\n): string | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") return msg.content\n if (Array.isArray(msg.content)) {\n const textBlock = msg.content.find(\n (block: AnyRecord) => block.type === \"text\",\n )\n if (textBlock?.text) return textBlock.text as string\n }\n }\n }\n return undefined\n}\n\n/**\n * Check if any user message contains tool_result content blocks,\n * indicating a follow-up turn where we should skip web search.\n * In Anthropic format, tool results are content blocks inside user messages,\n * NOT separate role: \"tool\" messages like in OpenAI format.\n */\nfunction hasToolResultContent(messages: Array<AnyRecord>): boolean {\n return messages.some(\n (msg) =>\n Array.isArray(msg.content) &&\n msg.content.some(\n (block: AnyRecord) => block.type === \"tool_result\",\n ),\n )\n}\n\n/**\n * Inject web search results into the Anthropic system field.\n * Handles three cases: absent, string, or array of content blocks.\n * When array, prepends without cache_control to preserve existing directives.\n */\nfunction injectSearchResults(\n body: AnyRecord,\n searchContext: string,\n): void {\n if (body.system === undefined || body.system === null) {\n body.system = searchContext\n } else if (typeof body.system === \"string\") {\n body.system = `${searchContext}\\n\\n${body.system}`\n } else if (Array.isArray(body.system)) {\n body.system = [\n { type: \"text\", text: searchContext },\n ...body.system,\n ]\n }\n}\n\n/**\n * Strip web_search tools from the request and clean up tool_choice.\n * Returns the modified body object.\n */\nfunction stripWebSearchTool(body: AnyRecord): void {\n if (!body.tools) return\n\n body.tools = body.tools.filter(\n (tool: AnyRecord) => !isWebSearchTool(tool),\n )\n\n if (body.tools.length === 0) {\n body.tools = undefined\n body.tool_choice = undefined\n } else if (\n body.tool_choice &&\n typeof body.tool_choice === \"object\" &&\n body.tool_choice.type === \"tool\"\n ) {\n // If tool_choice forced the removed web_search tool, fall back to auto\n const choiceName = body.tool_choice.name\n if (\n choiceName &&\n !body.tools.some((tool: AnyRecord) => tool.name === choiceName)\n ) {\n body.tool_choice = { type: \"auto\" }\n }\n }\n}\n\n/**\n * Process web search if the request contains a web_search tool.\n * Performs the search, injects results into system, and strips the tool.\n * Returns the (possibly modified) body string to forward.\n */\nasync function processWebSearch(rawBody: string): Promise<string> {\n // Fast path: skip parsing if no web_search tool present\n if (!rawBody.includes(\"web_search\")) return rawBody\n\n let body: AnyRecord\n try {\n body = JSON.parse(rawBody)\n } catch {\n return rawBody\n }\n\n const hasWebSearch = body.tools?.some(\n (tool: AnyRecord) => isWebSearchTool(tool),\n )\n if (!hasWebSearch) return rawBody\n\n // Skip search on follow-up messages (tool call results)\n const hasToolResult = hasToolResultContent(body.messages ?? [])\n const query = hasToolResult ? undefined : extractUserQuery(body.messages ?? [])\n\n if (query) {\n try {\n const results = await searchWeb(query)\n const searchContext = [\n \"[Web Search Results]\",\n results.content,\n \"\",\n results.references.map((r) => `- [${r.title}](${r.url})`).join(\"\\n\"),\n \"[End Web Search Results]\",\n ].join(\"\\n\")\n\n injectSearchResults(body, searchContext)\n } catch (error) {\n consola.warn(\"Web search failed, continuing without results:\", error)\n }\n }\n\n // Always strip web_search tool regardless of whether search succeeded\n stripWebSearchTool(body)\n\n return JSON.stringify(body)\n}\n\nexport async function handleCompletion(c: Context) {\n const startTime = Date.now()\n await checkRateLimit(state)\n\n const rawBody = await c.req.text()\n\n const debugEnabled = consola.level >= 4\n if (debugEnabled) {\n consola.debug(\"Anthropic request body:\", rawBody.slice(0, 2000))\n }\n\n if (state.manualApprove) {\n await awaitApproval()\n }\n\n const betaHeaders = extractBetaHeaders(c)\n const finalBody = await processWebSearch(rawBody)\n\n // Resolve model name (e.g. opus → opus-1m variant)\n const { body: resolvedBody, originalModel, resolvedModel } = resolveModelInBody(finalBody)\n\n // Look up model metadata for context window info\n const selectedModel = state.models?.data.find(\n (m) => m.id === (resolvedModel ?? originalModel),\n )\n\n // Apply default anthropic-beta for Claude models when client sends none\n const effectiveBetas = applyDefaultBetas(betaHeaders, resolvedModel ?? originalModel)\n\n let response: Response\n try {\n response = await createMessages(resolvedBody, {\n ...selectedModel?.requestHeaders,\n ...effectiveBetas,\n })\n } catch (error) {\n if (error instanceof HTTPError) {\n const errorBody = await error.response.clone().text().catch(() => \"\")\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n status: error.response.status,\n errorBody,\n },\n selectedModel,\n startTime,\n )\n }\n throw error\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"\"\n const isStreaming = contentType.includes(\"text/event-stream\")\n\n // Streaming: pipe the upstream SSE response body directly\n if (isStreaming) {\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n status: response.status,\n streaming: true,\n },\n selectedModel,\n startTime,\n )\n\n if (debugEnabled) {\n consola.debug(\"Streaming response from Copilot /v1/messages\")\n }\n return new Response(response.body, {\n status: response.status,\n headers: {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n },\n })\n }\n\n // Non-streaming: extract usage from response body\n const responseBody = (await response.json()) as AnyRecord\n\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n inputTokens: responseBody.usage?.input_tokens,\n outputTokens: responseBody.usage?.output_tokens,\n status: response.status,\n },\n selectedModel,\n startTime,\n )\n\n if (debugEnabled) {\n consola.debug(\n \"Non-streaming response from Copilot /v1/messages:\",\n JSON.stringify(responseBody).slice(0, 2000),\n )\n }\n return c.json(responseBody, response.status as 200)\n}\n\n/**\n * Parse the JSON body, resolve the model name, and re-serialize.\n * Returns the body string plus the original and resolved model names.\n */\nfunction resolveModelInBody(rawBody: string): {\n body: string\n originalModel?: string\n resolvedModel?: string\n} {\n let parsed: AnyRecord\n try {\n parsed = JSON.parse(rawBody)\n } catch {\n return { body: rawBody }\n }\n\n const originalModel =\n typeof parsed.model === \"string\" ? parsed.model : undefined\n if (!originalModel) return { body: rawBody, originalModel }\n\n const resolved = resolveModel(originalModel)\n if (resolved === originalModel)\n return { body: rawBody, originalModel, resolvedModel: originalModel }\n\n parsed.model = resolved\n return {\n body: JSON.stringify(parsed),\n originalModel,\n resolvedModel: resolved,\n }\n}\n\n/**\n * Apply default anthropic-beta values for Claude models when the client\n * (e.g. curl) sends no beta headers. Claude CLI sends its own betas,\n * so this only fires as a safety net for bare clients.\n */\nfunction applyDefaultBetas(\n betaHeaders: Record<string, string>,\n modelId?: string,\n): Record<string, string> {\n if (betaHeaders[\"anthropic-beta\"]) return betaHeaders\n if (!modelId || !modelId.startsWith(\"claude-\")) return betaHeaders\n\n return {\n ...betaHeaders,\n \"anthropic-beta\": [\n \"interleaved-thinking-2025-05-14\",\n \"token-counting-2024-11-01\",\n ].join(\",\"),\n }\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCountTokens } from \"./count-tokens-handler\"\nimport { handleCompletion } from \"./handler\"\n\nexport const messageRoutes = new Hono()\n\nmessageRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n return await handleCountTokens(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { 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 { events } from \"fetch-event-stream\"\n\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const createResponses = async (\n payload: ResponsesPayload,\n modelHeaders?: Record<string, string>,\n) => {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const enableVision = detectVision(payload.input)\n\n const isAgentCall = detectAgentCall(payload.input)\n\n const headers: Record<string, string> = {\n ...copilotHeaders(state, enableVision),\n ...modelHeaders,\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n }\n\n const filteredPayload = filterUnsupportedTools(payload)\n\n const response = await fetch(`${copilotBaseUrl(state)}/responses`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(filteredPayload),\n })\n\n if (!response.ok) {\n consola.error(\"Failed to create responses\", response)\n throw new HTTPError(\"Failed to create responses\", response)\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ResponsesApiResponse\n}\n\nfunction detectVision(input: ResponsesPayload[\"input\"]): boolean {\n if (typeof input === \"string\") return false\n if (!Array.isArray(input)) return false\n\n return input.some((item) => {\n if (\"content\" in item && Array.isArray(item.content)) {\n return item.content.some(\n (part: Record<string, unknown>) => part.type === \"input_image\",\n )\n }\n return false\n })\n}\n\nfunction detectAgentCall(input: ResponsesPayload[\"input\"]): boolean {\n if (typeof input === \"string\") return false\n if (!Array.isArray(input)) return false\n\n return input.some((item) => {\n if (\"role\" in item && item.role === \"assistant\") return true\n if (\n \"type\" in item\n && (item.type === \"function_call\" || item.type === \"function_call_output\")\n ) {\n return true\n }\n return false\n })\n}\n\nfunction filterUnsupportedTools(payload: ResponsesPayload): ResponsesPayload {\n if (!payload.tools || !Array.isArray(payload.tools)) return payload\n\n const supported = payload.tools.filter((tool) => {\n const isSupported = tool.type === \"function\"\n if (!isSupported) {\n consola.debug(`Stripping unsupported tool type: ${tool.type}`)\n }\n return isSupported\n })\n\n let toolChoice = payload.tool_choice\n if (supported.length === 0) {\n toolChoice = undefined\n } else if (\n toolChoice\n && typeof toolChoice === \"object\"\n ) {\n const supportedNames = new Set(\n supported.map((tool) => tool.name).filter(Boolean),\n )\n const toolChoiceName = getToolChoiceName(toolChoice)\n if (toolChoiceName && !supportedNames.has(toolChoiceName)) {\n toolChoice = undefined\n }\n }\n\n return {\n ...payload,\n tools: supported.length > 0 ? supported : undefined,\n tool_choice: toolChoice,\n }\n}\n\nfunction getToolChoiceName(\n toolChoice: NonNullable<ResponsesPayload[\"tool_choice\"]>,\n): string | undefined {\n if (typeof toolChoice !== \"object\") return undefined\n if (\n \"function\" in toolChoice\n && toolChoice.function\n && typeof toolChoice.function === \"object\"\n ) {\n return (toolChoice.function as { name?: string }).name\n }\n if (\"name\" in toolChoice) {\n return toolChoice.name\n }\n return undefined\n}\n\n// Types\n\nexport interface ResponsesInputItem {\n role?: \"user\" | \"assistant\" | \"system\"\n type?: \"message\" | \"function_call\" | \"function_call_output\"\n content?: string | Array<Record<string, unknown>>\n name?: string\n call_id?: string\n arguments?: string\n output?: string\n [key: string]: unknown\n}\n\nexport interface ResponsesTool {\n type: string\n name?: string\n description?: string\n parameters?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport interface ResponsesPayload {\n model: string\n input: string | Array<ResponsesInputItem>\n instructions?: string\n tools?: Array<ResponsesTool>\n tool_choice?:\n | string\n | { type: string; name?: string; function?: { name?: string } }\n max_output_tokens?: number\n temperature?: number\n top_p?: number\n stream?: boolean\n store?: boolean\n metadata?: Record<string, string>\n previous_response_id?: string\n reasoning?: { effort?: string; summary?: string }\n [key: string]: unknown\n}\n\nexport interface ResponsesApiResponse {\n id: string\n object: \"response\"\n status: string\n output: Array<unknown>\n [key: string]: unknown\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\nimport { streamSSE } from \"hono/streaming\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { HTTPError } from \"~/lib/error\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { logRequest } from \"~/lib/request-log\"\nimport { state } from \"~/lib/state\"\nimport { isNullish, resolveModel } from \"~/lib/utils\"\nimport {\n createResponses,\n type ResponsesApiResponse,\n type ResponsesInputItem,\n type ResponsesPayload,\n} from \"~/services/copilot/create-responses\"\nimport { searchWeb } from \"~/services/copilot/web-search\"\n\nexport async function handleResponses(c: Context) {\n const startTime = Date.now()\n await checkRateLimit(state)\n\n const payload = await c.req.json<ResponsesPayload>()\n const debugEnabled = consola.level >= 4\n if (debugEnabled) {\n consola.debug(\n \"Responses request payload:\",\n JSON.stringify(payload).slice(-400),\n )\n }\n\n // Resolve model name (e.g. opus → opus-1m variant)\n const originalModel = payload.model\n const resolvedModel = resolveModel(payload.model)\n if (resolvedModel !== payload.model) {\n payload.model = resolvedModel\n }\n\n const selectedModel = state.models?.data.find(\n (model) => model.id === payload.model,\n )\n\n if (state.manualApprove) await awaitApproval()\n\n await injectWebSearchIfNeeded(payload)\n\n if (isNullish(payload.max_output_tokens)) {\n payload.max_output_tokens =\n selectedModel?.capabilities.limits.max_output_tokens\n if (debugEnabled) {\n consola.debug(\n \"Set max_output_tokens to:\",\n JSON.stringify(payload.max_output_tokens),\n )\n }\n }\n\n const response = await createResponses(payload, selectedModel?.requestHeaders).catch(\n async (error: unknown) => {\n if (error instanceof HTTPError) {\n const errorBody = await error.response.clone().text().catch(() => \"\")\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n status: error.response.status,\n errorBody,\n },\n selectedModel,\n startTime,\n )\n }\n throw error\n },\n )\n const isStreaming = !isNonStreaming(response)\n\n logRequest(\n {\n method: \"POST\",\n path: c.req.path,\n model: originalModel,\n resolvedModel,\n status: 200,\n streaming: isStreaming,\n },\n selectedModel,\n startTime,\n )\n\n if (!isStreaming) {\n if (debugEnabled) {\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\n }\n return c.json(response)\n }\n\n return streamSSE(c, async (stream) => {\n for await (const chunk of response) {\n if (debugEnabled) {\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\n }\n\n if (chunk.data === \"[DONE]\") {\n break\n }\n\n if (!chunk.data) {\n continue\n }\n\n await stream.writeSSE({\n data: chunk.data,\n event: chunk.event,\n id: chunk.id?.toString(),\n })\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createResponses>>,\n): response is ResponsesApiResponse => Object.hasOwn(response, \"output\")\n\nasync function injectWebSearchIfNeeded(\n payload: ResponsesPayload,\n): Promise<void> {\n const hasWebSearch = payload.tools?.some((t) => t.type === \"web_search\")\n if (!hasWebSearch) return\n\n // Skip search on follow-up messages (function call results)\n if (Array.isArray(payload.input)) {\n const hasFollowUp = payload.input.some(\n (item: ResponsesInputItem) => item.type === \"function_call_output\",\n )\n if (hasFollowUp) return\n }\n\n const query = extractUserQuery(payload.input)\n if (!query) return\n\n try {\n const results = await searchWeb(query)\n const searchContext = [\n \"[Web Search Results]\",\n results.content,\n \"\",\n results.references.map((r) => `- [${r.title}](${r.url})`).join(\"\\n\"),\n \"[End Web Search Results]\",\n ].join(\"\\n\")\n\n payload.instructions =\n payload.instructions ?\n `${searchContext}\\n\\n${payload.instructions}`\n : searchContext\n } catch (error) {\n consola.warn(\"Web search failed, continuing without results:\", error)\n }\n}\n\nfunction extractUserQuery(\n input: ResponsesPayload[\"input\"],\n): string | undefined {\n if (typeof input === \"string\") return input\n if (!Array.isArray(input)) return undefined\n\n // Find the last user message\n for (let i = input.length - 1; i >= 0; i--) {\n const item = input[i]\n if (\"role\" in item && item.role === \"user\") {\n if (typeof item.content === \"string\") return item.content\n if (Array.isArray(item.content)) {\n const text = item.content.find(\n (p: Record<string, unknown>) => p.type === \"input_text\",\n )\n if (text && \"text\" in text) return text.text as string\n }\n }\n }\n return undefined\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleResponses } from \"./handler\"\n\nexport const responsesRoutes = new Hono()\n\nresponsesRoutes.post(\"/\", async (c) => {\n try {\n return await handleResponses(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport { searchWeb } from \"~/services/copilot/web-search\"\n\nexport const searchRoutes = new Hono()\n\nsearchRoutes.post(\"/\", async (c) => {\n try {\n const { query } = await c.req.json<{ query: string }>()\n\n if (!query || typeof query !== \"string\") {\n return c.json(\n { error: { message: \"Missing required field: query\" } },\n 400,\n )\n }\n\n const results = await searchWeb(query)\n return c.json({ results })\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\n\nexport const tokenRoute = new Hono()\n\ntokenRoute.get(\"/\", (c) => {\n if (!state.showToken) {\n return c.json(\n { error: { message: \"Token endpoint disabled\", type: \"error\" } },\n 403,\n )\n }\n\n return c.json({\n token: state.copilotToken,\n })\n})\n","import { Hono } from \"hono\"\nimport consola from \"consola\"\n\nimport { forwardError } from \"~/lib/error\"\nimport { getCopilotUsage } from \"~/services/github/get-copilot-usage\"\n\nexport const usageRoute = new Hono()\n\nusageRoute.get(\"/\", async (c) => {\n try {\n const usage = await getCopilotUsage()\n return c.json(usage)\n } catch (error) {\n consola.error(\"Error fetching Copilot usage:\", error)\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\nimport { cors } from \"hono/cors\"\n\nimport { completionRoutes } from \"./routes/chat-completions/route\"\nimport { embeddingRoutes } from \"./routes/embeddings/route\"\nimport { messageRoutes } from \"./routes/messages/route\"\nimport { modelRoutes } from \"./routes/models/route\"\nimport { responsesRoutes } from \"./routes/responses/route\"\nimport { searchRoutes } from \"./routes/search/route\"\nimport { tokenRoute } from \"./routes/token/route\"\nimport { usageRoute } from \"./routes/usage/route\"\n\nexport const server = new Hono()\n\nserver.use(cors())\n\nserver.get(\"/\", (c) => c.text(\"Server running\"))\n\nserver.route(\"/chat/completions\", completionRoutes)\nserver.route(\"/responses\", responsesRoutes)\nserver.route(\"/models\", modelRoutes)\nserver.route(\"/embeddings\", embeddingRoutes)\nserver.route(\"/search\", searchRoutes)\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/responses\", responsesRoutes)\nserver.route(\"/v1/models\", modelRoutes)\nserver.route(\"/v1/embeddings\", embeddingRoutes)\nserver.route(\"/v1/search\", searchRoutes)\n\n// Anthropic compatible endpoints\nserver.route(\"/v1/messages\", messageRoutes)\n","import consola from \"consola\"\nimport { serve, type ServerHandler } from \"srvx\"\n\nimport { ensurePaths } from \"./paths\"\nimport { generateRandomPort } from \"./port\"\nimport { initProxyFromEnv } from \"./proxy\"\nimport { state } from \"./state\"\nimport { setupCopilotToken, setupGitHubToken } from \"./token\"\nimport { cacheModels, cacheVSCodeVersion } from \"./utils\"\nimport { server as app } from \"../server\"\n\nconst MAX_PORT_RETRIES = 10\n\nexport interface ServerSetupOptions {\n port?: number\n verbose: boolean\n accountType: string\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n showToken: boolean\n proxyEnv: boolean\n silent: boolean\n}\n\nexport async function setupAndServe(\n options: ServerSetupOptions,\n): Promise<{ server: ReturnType<typeof serve>; serverUrl: string }> {\n if (options.proxyEnv) {\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\n await ensurePaths()\n await cacheVSCodeVersion()\n\n if (options.githubToken) {\n state.githubToken = options.githubToken\n consola.info(\"Using provided GitHub token\")\n } else {\n await setupGitHubToken()\n }\n\n await setupCopilotToken()\n await cacheModels()\n\n consola.info(\n `Available models: \\n${state.models?.data.map((model) => `- ${model.id}`).join(\"\\n\")}`,\n )\n\n const serveOptions = {\n fetch: app.fetch as ServerHandler,\n hostname: \"127.0.0.1\",\n silent: options.silent,\n }\n\n let srvxServer: ReturnType<typeof serve> | undefined\n\n if (options.port !== undefined) {\n // Explicit port — no retry\n srvxServer = serve({ ...serveOptions, port: options.port })\n } else {\n // Random available port with retry\n let lastError: unknown\n for (let attempt = 0; attempt < MAX_PORT_RETRIES; attempt++) {\n const candidatePort = generateRandomPort()\n try {\n srvxServer = serve({ ...serveOptions, port: candidatePort })\n break\n } catch (error) {\n lastError = error\n const isAddrInUse =\n error instanceof Error\n && (error.message.includes(\"EADDRINUSE\")\n || error.message.includes(\"address already in use\")\n || (\"code\" in error\n && (error as NodeJS.ErrnoException).code === \"EADDRINUSE\"))\n if (!isAddrInUse) throw error\n consola.debug(`Port ${candidatePort} in use, trying another...`)\n }\n }\n\n if (srvxServer === undefined) {\n throw new Error(\n `Failed to find an available port after ${MAX_PORT_RETRIES} attempts. `\n + `Specify a port with --port or free some ports. Last error: ${lastError}`,\n )\n }\n }\n\n // Read actual port from the server URL\n const url = srvxServer.url\n if (!url) {\n throw new Error(\"Server started but URL is not available\")\n }\n const serverUrl = url.replace(/\\/$/, \"\")\n\n return { server: srvxServer, serverUrl }\n}\n\n/** Shared CLI arg definitions for all server commands. */\nexport const sharedServerArgs = {\n port: {\n alias: \"p\",\n type: \"string\" as const,\n description: \"Port to listen on\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\" as const,\n default: false,\n description: \"Enable verbose logging\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\" as const,\n default: \"enterprise\",\n description: \"Account type to use (individual, business, enterprise)\",\n },\n manual: {\n type: \"boolean\" as const,\n default: false,\n description: \"Enable manual request approval\",\n },\n \"rate-limit\": {\n alias: \"r\",\n type: \"string\" as const,\n description: \"Rate limit in seconds between requests\",\n },\n wait: {\n alias: \"w\",\n type: \"boolean\" as const,\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\" as const,\n description:\n \"Provide GitHub token directly (must be generated using the `auth` subcommand)\",\n },\n \"show-token\": {\n type: \"boolean\" as const,\n default: false,\n description: \"Show GitHub and Copilot tokens on fetch and refresh\",\n },\n \"proxy-env\": {\n type: \"boolean\" as const,\n default: false,\n description: \"Initialize proxy from environment variables\",\n },\n} as const\n\nconst allowedAccountTypes = new Set([\"individual\", \"business\", \"enterprise\"])\n\n/** Parse shared server args into ServerSetupOptions fields. */\nexport function parseSharedArgs(args: Record<string, unknown>): {\n port?: number\n verbose: boolean\n accountType: string\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n showToken: boolean\n proxyEnv: boolean\n} {\n const portRaw = args.port as string | undefined\n let port: number | undefined\n if (portRaw !== undefined) {\n port = Number.parseInt(portRaw, 10)\n if (Number.isNaN(port) || port <= 0 || port > 65535) {\n throw new Error(\"Invalid port. Must be between 1 and 65535.\")\n }\n }\n\n const accountType = (args[\"account-type\"] as string) ?? \"enterprise\"\n if (!allowedAccountTypes.has(accountType)) {\n throw new Error(\n \"Invalid account type. Must be individual, business, or enterprise.\",\n )\n }\n\n const rateLimitRaw = args[\"rate-limit\"] as string | undefined\n let rateLimit: number | undefined\n if (rateLimitRaw !== undefined) {\n rateLimit = Number.parseInt(rateLimitRaw, 10)\n if (Number.isNaN(rateLimit) || rateLimit <= 0) {\n throw new Error(\"Invalid rate limit. Must be a positive integer.\")\n }\n }\n\n const rateLimitWait = (args.wait as boolean) && rateLimit !== undefined\n if ((args.wait as boolean) && rateLimit === undefined) {\n consola.warn(\"Rate limit wait ignored because no rate limit was set.\")\n }\n\n const githubToken =\n (args[\"github-token\"] as string | undefined) ?? process.env.GH_TOKEN\n\n return {\n port,\n verbose: args.verbose as boolean,\n accountType,\n manual: args.manual as boolean,\n rateLimit,\n rateLimitWait,\n githubToken,\n showToken: args[\"show-token\"] as boolean,\n proxyEnv: args[\"proxy-env\"] as boolean,\n }\n}\n\n/** Build environment variables for Claude Code. */\nexport function getClaudeCodeEnvVars(\n serverUrl: string,\n model?: string,\n): Record<string, string> {\n const vars: Record<string, string> = {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: \"dummy\",\n DISABLE_NON_ESSENTIAL_MODEL_CALLS: \"1\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\n }\n if (model) vars.ANTHROPIC_MODEL = model\n return vars\n}\n\n/** Build environment variables for Codex CLI. */\nexport function getCodexEnvVars(serverUrl: string): Record<string, string> {\n return {\n OPENAI_BASE_URL: `${serverUrl}/v1`,\n OPENAI_API_KEY: \"dummy\",\n }\n}\n","import process from \"node:process\"\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { launchChild } from \"./lib/launch\"\nimport {\n getClaudeCodeEnvVars,\n parseSharedArgs,\n setupAndServe,\n sharedServerArgs,\n} from \"./lib/server-setup\"\n\nexport const claude = defineCommand({\n meta: {\n name: \"claude\",\n description: \"Start the proxy server and launch Claude Code\",\n },\n args: {\n ...sharedServerArgs,\n model: {\n alias: \"m\",\n type: \"string\",\n description: \"Override the default model for Claude Code\",\n },\n },\n async run({ args }) {\n if (!process.stdout.isTTY) {\n consola.error(\"The claude subcommand requires a TTY (interactive terminal).\")\n process.exit(1)\n }\n\n const parsed = parseSharedArgs(args as unknown as Record<string, unknown>)\n\n let server: Awaited<ReturnType<typeof setupAndServe>>[\"server\"]\n let serverUrl: string\n try {\n const result = await setupAndServe({\n ...parsed,\n port: parsed.port, // undefined = random port\n silent: true,\n })\n server = result.server\n serverUrl = result.serverUrl\n await server.ready()\n } catch (error) {\n consola.error(\"Failed to start server:\", error instanceof Error ? error.message : error)\n process.exit(1)\n }\n\n consola.success(`Server ready on ${serverUrl}, launching Claude Code...`)\n consola.level = 1 // errors and warnings only — prevent TUI corruption\n\n const envVars = getClaudeCodeEnvVars(serverUrl, args.model)\n const extraArgs = ((args as unknown as Record<string, unknown>)._ as string[]) ?? []\n\n launchChild(\n { kind: \"claude-code\", envVars, extraArgs, model: args.model },\n server,\n )\n },\n})\n","import process from \"node:process\"\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { launchChild } from \"./lib/launch\"\nimport { DEFAULT_CODEX_MODEL } from \"./lib/port\"\nimport {\n getCodexEnvVars,\n parseSharedArgs,\n setupAndServe,\n sharedServerArgs,\n} from \"./lib/server-setup\"\n\nexport const codex = defineCommand({\n meta: {\n name: \"codex\",\n description: \"Start the proxy server and launch Codex CLI\",\n },\n args: {\n ...sharedServerArgs,\n model: {\n alias: \"m\",\n type: \"string\",\n description: \"Override the default model for Codex CLI\",\n },\n },\n async run({ args }) {\n if (!process.stdout.isTTY) {\n consola.error(\"The codex subcommand requires a TTY (interactive terminal).\")\n process.exit(1)\n }\n\n const parsed = parseSharedArgs(args as unknown as Record<string, unknown>)\n\n let server: Awaited<ReturnType<typeof setupAndServe>>[\"server\"]\n let serverUrl: string\n try {\n const result = await setupAndServe({\n ...parsed,\n port: parsed.port, // undefined = random port\n silent: true,\n })\n server = result.server\n serverUrl = result.serverUrl\n await server.ready()\n } catch (error) {\n consola.error(\"Failed to start server:\", error instanceof Error ? error.message : error)\n process.exit(1)\n }\n\n const codexModel = args.model ?? DEFAULT_CODEX_MODEL\n consola.success(`Server ready on ${serverUrl}, launching Codex CLI (${codexModel})...`)\n consola.level = 1 // errors and warnings only — prevent TUI corruption\n\n const envVars = getCodexEnvVars(serverUrl)\n const extraArgs = ((args as unknown as Record<string, unknown>)._ as string[]) ?? []\n\n launchChild(\n { kind: \"codex\", envVars, extraArgs, model: args.model },\n server,\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 { 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 tokenExists: boolean\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, tokenExists] = await Promise.all([\n getPackageVersion(),\n checkTokenExists(),\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 tokenExists,\n }\n}\n\nfunction printDebugInfoPlain(info: DebugInfo): void {\n consola.info(`github-router 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\nToken exists: ${info.tokenExists ? \"Yes\" : \"No\"}`)\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","import 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, env } = process\n\n if (platform === \"win32\") {\n // Git Bash / MSYS2 / Cygwin set SHELL even on Windows\n if (env.SHELL) {\n if (env.SHELL.endsWith(\"zsh\")) return \"zsh\"\n if (env.SHELL.endsWith(\"fish\")) return \"fish\"\n if (env.SHELL.endsWith(\"bash\")) return \"bash\"\n return \"sh\"\n }\n\n // Windows PowerShell 5.x sets this\n if (env.POWERSHELL_DISTRIBUTION_CHANNEL) return \"powershell\"\n\n // PowerShell (both 5.x and 7+/pwsh) adds user-scoped module paths\n // at runtime. The system-level PSModulePath in CMD lacks these paths.\n if (env.PSModulePath) {\n const lower = env.PSModulePath.toLowerCase()\n if (\n lower.includes(\"documents\\\\powershell\")\n || lower.includes(\"documents\\\\windowspowershell\")\n ) {\n return \"powershell\"\n }\n }\n\n return \"cmd\"\n }\n\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\nfunction quotePosixValue(value: string): string {\n return `'${value.replace(/'/g, \"'\\\\''\")}'`\n}\n\nfunction quotePowerShellValue(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`\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} = ${quotePowerShellValue(value)}`)\n .join(\"; \")\n break\n }\n case \"cmd\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set \"${key}=${value}\"`)\n .join(\" & \")\n break\n }\n case \"fish\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set -gx ${key} ${quotePosixValue(value)}`)\n .join(\"; \")\n break\n }\n default: {\n // bash, zsh, sh\n const assignments = filteredEnvVars\n .map(([key, value]) => `${key}=${quotePosixValue(value)}`)\n .join(\" \")\n commandBlock = filteredEnvVars.length > 0 ? `export ${assignments}` : \"\"\n break\n }\n }\n\n if (commandBlock && commandToRun) {\n const separator =\n shell === \"cmd\" ? \" & \" : shell === \"powershell\" ? \"; \" : \" && \"\n return `${commandBlock}${separator}${commandToRun}`\n }\n\n return commandBlock || commandToRun\n}\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\n\nimport { generateEnvScript } from \"./lib/shell\"\nimport { DEFAULT_CODEX_MODEL, DEFAULT_PORT } from \"./lib/port\"\nimport {\n getClaudeCodeEnvVars,\n getCodexEnvVars,\n parseSharedArgs,\n setupAndServe,\n sharedServerArgs,\n} from \"./lib/server-setup\"\n\nfunction printAndCopyCommand(command: string, label: string): void {\n consola.box(`${label}\\n\\n${command}`)\n try {\n clipboard.writeSync(command)\n consola.success(`Copied ${label} command to clipboard!`)\n } catch {\n consola.warn(\"Failed to copy to clipboard. Copy the command above manually.\")\n }\n}\n\nfunction generateClaudeCodeCommand(serverUrl: string, model?: string) {\n const envVars = getClaudeCodeEnvVars(serverUrl, model)\n const command = generateEnvScript(envVars, \"claude --dangerously-skip-permissions\")\n printAndCopyCommand(command, \"Claude Code\")\n}\n\nfunction generateCodexCommand(serverUrl: string, model?: string) {\n const codexModel = model ?? DEFAULT_CODEX_MODEL\n const envVars = getCodexEnvVars(serverUrl)\n const command = generateEnvScript(envVars, `codex -m ${codexModel}`)\n printAndCopyCommand(command, \"Codex CLI\")\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the github-router server\",\n },\n args: {\n ...sharedServerArgs,\n cc: {\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Claude Code with Copilot API config\",\n },\n cx: {\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Codex CLI with Copilot API config\",\n },\n model: {\n alias: \"m\",\n type: \"string\",\n description: \"Override the default model (used with --cc or --cx)\",\n },\n },\n async run({ args }) {\n const parsed = parseSharedArgs(args as unknown as Record<string, unknown>)\n\n const { serverUrl } = await setupAndServe({\n ...parsed,\n port: parsed.port ?? DEFAULT_PORT,\n silent: false,\n })\n\n if (args.cc) generateClaudeCodeCommand(serverUrl, args.model)\n if (args.cx) generateCodexCommand(serverUrl, args.model)\n\n consola.box(\n `🌐 Usage Viewer: https://animeshkundu.github.io/github-router/dashboard.html?endpoint=${serverUrl}/usage`,\n )\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand, runMain } from \"citty\"\nimport consola from \"consola\"\n\nimport { auth } from \"./auth\"\nimport { checkUsage } from \"./check-usage\"\nimport { claude } from \"./claude\"\nimport { codex } from \"./codex\"\nimport { debug } from \"./debug\"\nimport { start } from \"./start\"\n\nprocess.on(\"unhandledRejection\", (error) => {\n consola.error(\"Unhandled rejection:\", error)\n})\n\nprocess.on(\"uncaughtException\", (error) => {\n consola.error(\"Uncaught exception:\", error)\n process.exit(1)\n})\n\nconst main = defineCommand({\n meta: {\n name: \"github-router\",\n description:\n \"A reverse proxy that exposes GitHub Copilot as OpenAI and Anthropic compatible API endpoints.\",\n },\n subCommands: { auth, start, claude, codex, \"check-usage\": checkUsage, debug },\n})\n\nawait runMain(main)\n"],"mappings":"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"}
|