copilot-api-node20 0.6.0 → 0.7.0

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.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","names":["state: State","state","headers: Record<string, string>","errorJson: unknown","tokenRefreshInterval: NodeJS.Timeout | undefined","onlineHandler: (() => void) | undefined","offlineHandler: (() => void) | undefined","token","process","commandBlock: string","state","outputMessages: typeof simplifiedMessages","x","headers: Record<string, string>","handleCompletion","isNonStreaming","handleCompletion","newMessages: Array<Message>","contentParts: Array<ContentPart>","allTextBlocks: Array<AnthropicTextBlock>","allToolUseBlocks: Array<AnthropicToolUseBlock>","stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null","state","events: Array<AnthropicStreamEventData>","events","streamState: AnthropicStreamState","events","cleanupFunctions: Array<() => void | Promise<void>>","process","selectedModel: string","selectedSmallModel: string"],"sources":["../src/lib/paths.ts","../src/lib/state.ts","../src/lib/connectivity.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/shell.ts","../src/lib/approval.ts","../src/lib/rate-limit.ts","../src/lib/tokenizer.ts","../src/lib/sanitize.ts","../src/services/copilot/create-chat-completions.ts","../src/routes/chat-completions/handler.ts","../src/routes/chat-completions/route.ts","../src/services/copilot/create-embeddings.ts","../src/routes/embeddings/route.ts","../src/routes/messages/utils.ts","../src/routes/messages/non-stream-translation.ts","../src/routes/messages/stream-translation.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["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\", \"copilot-api\")\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 type { ModelsResponse } from \"~/services/copilot/get-models\"\n\nexport interface ConnectivityConfig {\n enabled: boolean\n probeEndpoints: Array<string>\n fastProbeInterval: number\n slowProbeInterval: number\n timeoutMs: number\n jitterMaxMs: number\n connectionPooling: boolean\n dnsCache: boolean\n}\n\nexport interface State {\n githubToken?: string\n copilotToken?: string\n\n accountType: 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 // API timeout configuration\n timeoutMs?: number\n\n // Connectivity monitoring configuration\n connectivity: ConnectivityConfig\n}\n\nexport const state: State = {\n accountType: \"individual\",\n manualApprove: false,\n rateLimitWait: false,\n showToken: false,\n connectivity: {\n enabled: true,\n probeEndpoints: [\n \"https://api.github.com\",\n \"https://www.google.com\",\n \"https://1.1.1.1\",\n ],\n fastProbeInterval: 5000, // 5 seconds when offline\n slowProbeInterval: 60000, // 1 minute when online\n timeoutMs: 5000,\n jitterMaxMs: 1000, // 0-1 second random jitter\n connectionPooling: true, // Enable HTTP/2 connection pooling\n dnsCache: true, // Enable DNS caching headers\n },\n}\n","import { EventEmitter } from \"node:events\"\n\nimport consola from \"consola\"\n\nimport { state } from \"./state\"\n\ninterface ConnectivityStats {\n isOnline: boolean\n lastChecked: string\n consecutiveFailures: number\n lastErrorType?: string\n lastErrorMessage?: string\n}\n\ninterface PerformanceStats {\n currentInterval: number\n nextCheckEstimate: string\n lastSuccessfulEndpoint?: string\n endpointFailureStats: Record<string, number>\n jitterEnabled: boolean\n connectionPooling: boolean\n dnsCache: boolean\n}\n\nclass ConnectivityMonitor extends EventEmitter {\n private isOnline = true\n private lastChecked = new Date().toISOString()\n private consecutiveFailures = 0\n private lastErrorType?: string\n private lastErrorMessage?: string\n private lastSuccessfulEndpoint?: string\n private endpointFailureStats: Record<string, number> = {}\n private checkInterval?: NodeJS.Timeout\n private abortController?: AbortController\n\n start(): void {\n if (!state.connectivity.enabled) {\n consola.debug(\"Connectivity monitoring disabled\")\n return\n }\n\n consola.info(\"Starting connectivity monitor\", {\n probeEndpoints: state.connectivity.probeEndpoints,\n fastInterval: state.connectivity.fastProbeInterval,\n })\n\n this.scheduleNextCheck()\n\n // Cleanup on process termination\n const cleanup = () => {\n this.stop()\n process.exit(0)\n }\n\n process.on(\"SIGINT\", cleanup)\n process.on(\"SIGTERM\", cleanup)\n }\n\n stop(): void {\n consola.debug(\"Stopping connectivity monitor\")\n\n if (this.checkInterval) {\n clearTimeout(this.checkInterval)\n this.checkInterval = undefined\n }\n\n if (this.abortController) {\n this.abortController.abort()\n this.abortController = undefined\n }\n }\n\n private scheduleNextCheck(): void {\n if (this.checkInterval) {\n clearTimeout(this.checkInterval)\n }\n\n const baseInterval = this.isOnline\n ? state.connectivity.slowProbeInterval\n : state.connectivity.fastProbeInterval\n\n // Add jitter to prevent thundering herd\n const jitter = Math.random() * state.connectivity.jitterMaxMs\n const interval = baseInterval + jitter\n\n this.checkInterval = setTimeout(() => {\n this.performConnectivityCheck()\n }, interval)\n }\n\n private async performConnectivityCheck(): Promise<void> {\n this.abortController = new AbortController()\n const timeoutId = setTimeout(\n () => this.abortController?.abort(),\n state.connectivity.timeoutMs,\n )\n\n try {\n let success = false\n\n for (const endpoint of state.connectivity.probeEndpoints) {\n try {\n const response = await fetch(endpoint, {\n method: \"HEAD\",\n signal: this.abortController.signal,\n headers: {\n \"User-Agent\": \"copilot-api-connectivity-monitor/1.0\",\n ...(state.connectivity.dnsCache && {\n \"Cache-Control\": \"max-age=300\",\n }),\n },\n })\n\n if (response.ok) {\n success = true\n this.lastSuccessfulEndpoint = endpoint\n break\n }\n } catch (error) {\n this.endpointFailureStats[endpoint] =\n (this.endpointFailureStats[endpoint] || 0) + 1\n\n consola.debug(`Probe failed for ${endpoint}:`, error)\n }\n }\n\n this.updateConnectivityState(success)\n } catch (error) {\n this.handleConnectivityError(error as Error)\n } finally {\n clearTimeout(timeoutId)\n this.scheduleNextCheck()\n }\n }\n\n private updateConnectivityState(isOnline: boolean): void {\n const wasOnline = this.isOnline\n this.isOnline = isOnline\n this.lastChecked = new Date().toISOString()\n\n if (isOnline) {\n if (this.consecutiveFailures > 0) {\n consola.info(`Connectivity restored after ${this.consecutiveFailures} failures`)\n }\n this.consecutiveFailures = 0\n this.lastErrorType = undefined\n this.lastErrorMessage = undefined\n\n if (!wasOnline) {\n this.emit(\"online\")\n }\n } else {\n this.consecutiveFailures++\n\n if (wasOnline) {\n consola.warn(\"Connectivity lost\")\n this.emit(\"offline\")\n }\n }\n }\n\n private handleConnectivityError(error: Error): void {\n this.lastErrorType = error.name\n this.lastErrorMessage = error.message\n\n consola.error(\"Connectivity check failed:\", error)\n this.updateConnectivityState(false)\n }\n\n getConnectivityStats(): ConnectivityStats {\n return {\n isOnline: this.isOnline,\n lastChecked: this.lastChecked,\n consecutiveFailures: this.consecutiveFailures,\n lastErrorType: this.lastErrorType,\n lastErrorMessage: this.lastErrorMessage,\n }\n }\n\n getPerformanceStats(): PerformanceStats {\n const currentInterval = this.isOnline\n ? state.connectivity.slowProbeInterval\n : state.connectivity.fastProbeInterval\n\n const nextCheckEstimate = new Date(\n Date.now() + currentInterval + Math.random() * state.connectivity.jitterMaxMs,\n ).toISOString()\n\n return {\n currentInterval,\n nextCheckEstimate,\n lastSuccessfulEndpoint: this.lastSuccessfulEndpoint,\n endpointFailureStats: { ...this.endpointFailureStats },\n jitterEnabled: state.connectivity.jitterMaxMs > 0,\n connectionPooling: state.connectivity.connectionPooling,\n dnsCache: state.connectivity.dnsCache,\n }\n }\n}\n\nexport const connectivityMonitor = new ConnectivityMonitor()\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.32.2025093001\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\nconst API_VERSION = \"2025-08-20\"\n\nexport const copilotBaseUrl = (state: State) =>\n state.accountType === \"individual\" ?\n \"https://api.githubcopilot.com\"\n : `https://api.${state.accountType}.githubcopilot.com`\nexport const copilotHeaders = (state: State, vision: boolean = false) => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${state.copilotToken}`,\n \"content-type\": standardHeaders()[\"content-type\"],\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"openai-intent\": \"model-access\",\n \"x-github-api-version\": API_VERSION,\n \"x-interaction-type\": \"model-access\",\n \"x-request-id\": randomUUID(),\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\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 = errorText\n }\n consola.error(\"HTTP error:\", errorJson)\n return c.json(\n {\n error: {\n message: errorText,\n type: \"error\",\n },\n },\n error.response.status as ContentfulStatusCode,\n )\n }\n\n return c.json(\n {\n error: {\n message: (error as Error).message,\n type: \"error\",\n },\n },\n 500,\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 getCopilotToken = async () => {\n // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(state),\n signal: controller.signal,\n },\n )\n\n if (!response.ok)\n throw new HTTPError(\"Failed to get Copilot token\", response)\n\n return (await response.json()) as GetCopilotTokenResponse\n } finally {\n clearTimeout(timeout)\n }\n}\n\n// Trimmed for the sake of simplicity\ninterface GetCopilotTokenResponse {\n expires_at: number\n refresh_in: number\n token: string\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\"\nimport { state } from \"~/lib/state\"\n\nexport async function getDeviceCode(): Promise<DeviceCodeResponse> {\n // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\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 signal: controller.signal,\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get device code\", response)\n\n return (await response.json()) as DeviceCodeResponse\n } finally {\n clearTimeout(timeout)\n }\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 // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\n ...standardHeaders(),\n },\n signal: controller.signal,\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get GitHub user\", response)\n\n return (await response.json()) as GithubUserResponse\n } finally {\n clearTimeout(timeout)\n }\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 // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const response = await fetch(`${copilotBaseUrl(state)}/models`, {\n headers: copilotHeaders(state),\n signal: controller.signal,\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get models\", response)\n\n return (await response.json()) as ModelsResponse\n } finally {\n clearTimeout(timeout)\n }\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\ninterface 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 policy?: {\n state: string\n terms: string\n }\n}\n","export function getVSCodeVersion() {\n return \"1.105.0-insider\"\n}\n\ngetVSCodeVersion()\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\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 { state } from \"~/lib/state\"\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\n while (true) {\n // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\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 signal: controller.signal,\n },\n )\n\n if (!response.ok) {\n await sleep(sleepDuration)\n consola.error(\"Failed to poll access token:\", await response.text())\n\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 } else {\n await sleep(sleepDuration)\n }\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n consola.error(\"Access token polling timed out\")\n await sleep(sleepDuration)\n continue\n }\n throw error\n } finally {\n clearTimeout(timeout)\n }\n }\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 { connectivityMonitor } from \"~/lib/connectivity\"\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\n// Track cleanup resources for token management\nlet tokenRefreshInterval: NodeJS.Timeout | undefined\nlet isRefreshPending = false\n\n// Event listener functions that can be removed\nlet onlineHandler: (() => void) | undefined\nlet offlineHandler: (() => void) | undefined\n\n// Cleanup function to be called on shutdown\nexport function cleanupTokenManagement() {\n consola.debug(\"Cleaning up token management\")\n\n // Clear the refresh interval\n if (tokenRefreshInterval) {\n clearInterval(tokenRefreshInterval)\n tokenRefreshInterval = undefined\n }\n\n // Remove event listeners\n if (onlineHandler) {\n connectivityMonitor.off(\"online\", onlineHandler)\n onlineHandler = undefined\n }\n\n if (offlineHandler) {\n connectivityMonitor.off(\"offline\", offlineHandler)\n offlineHandler = undefined\n }\n}\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 = (refresh_in - 60) * 1000\n\n const refreshTokenWithRetry = async (\n maxRetries = 5,\n baseDelay = 1000,\n reason = \"scheduled\",\n ) => {\n if (isRefreshPending) {\n consola.debug(\"Token refresh already in progress, skipping\")\n return\n }\n\n isRefreshPending = true\n try {\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n consola.debug(\n `Refreshing Copilot token (${reason}, attempt ${attempt}/${maxRetries})`,\n )\n const { token } = await getCopilotToken()\n state.copilotToken = token\n consola.debug(\"Copilot token refreshed successfully\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n return // Success - exit retry loop\n } catch (error) {\n const isLastAttempt = attempt === maxRetries\n consola.error(\n `Failed to refresh Copilot token (attempt ${attempt}/${maxRetries}):`,\n error,\n )\n\n if (isLastAttempt) {\n consola.error(\n \"All token refresh attempts failed. Service may be unavailable until next scheduled refresh.\",\n )\n return // Give up after max retries\n }\n\n // Exponential backoff: wait 1s, 2s, 4s, 8s, 16s\n const delay = baseDelay * Math.pow(2, attempt - 1)\n consola.debug(`Retrying token refresh in ${delay}ms...`)\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n }\n } finally {\n isRefreshPending = false\n }\n }\n\n // Set up scheduled token refresh\n tokenRefreshInterval = setInterval(() => {\n // Don't await to prevent blocking the interval timer\n refreshTokenWithRetry(5, 1000, \"scheduled\").catch((error) => {\n consola.error(\"Unexpected error in scheduled token refresh:\", error)\n })\n }, refreshInterval)\n\n // Start connectivity monitoring\n connectivityMonitor.start()\n\n // Create event handler functions that can be properly removed\n onlineHandler = () => {\n consola.debug(\n \"Network connectivity restored, attempting immediate token refresh\",\n )\n // Attempt immediate refresh when network comes back\n refreshTokenWithRetry(3, 500, \"network-restored\").catch((error) => {\n consola.error(\n \"Unexpected error in network-restored token refresh:\",\n error,\n )\n })\n }\n\n offlineHandler = () => {\n consola.debug(\"Network connectivity lost\")\n }\n\n // Listen for network restoration events\n connectivityMonitor.on(\"online\", onlineHandler)\n connectivityMonitor.on(\"offline\", offlineHandler)\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 // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/user`,\n {\n headers: githubHeaders(state),\n signal: controller.signal,\n },\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 } finally {\n clearTimeout(timeout)\n }\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 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(`copilot-api 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 { execSync } from \"node:child_process\"\nimport process from \"node:process\"\n\ntype ShellName = \"bash\" | \"zsh\" | \"fish\" | \"powershell\" | \"cmd\" | \"sh\"\ntype EnvVars = Record<string, string | undefined>\n\nfunction getShell(): ShellName {\n const { platform, ppid, env } = process\n\n if (platform === \"win32\") {\n try {\n const command = `wmic process get ParentProcessId,Name | findstr \"${ppid}\"`\n const parentProcess = execSync(command, { stdio: \"pipe\" }).toString()\n\n if (parentProcess.toLowerCase().includes(\"powershell.exe\")) {\n return \"powershell\"\n }\n } catch {\n return \"cmd\"\n }\n\n return \"cmd\"\n } else {\n const shellPath = env.SHELL\n if (shellPath) {\n if (shellPath.endsWith(\"zsh\")) return \"zsh\"\n if (shellPath.endsWith(\"fish\")) return \"fish\"\n if (shellPath.endsWith(\"bash\")) return \"bash\"\n }\n\n return \"sh\"\n }\n}\n\n/**\n * Generates a copy-pasteable script to set multiple environment variables\n * and run a subsequent command.\n * @param {EnvVars} envVars - An object of environment variables to set.\n * @param {string} commandToRun - The command to run after setting the variables.\n * @returns {string} The formatted script string.\n */\nexport function generateEnvScript(\n envVars: EnvVars,\n commandToRun: string = \"\",\n): string {\n const shell = getShell()\n const filteredEnvVars = Object.entries(envVars).filter(\n ([, value]) => value !== undefined,\n ) as Array<[string, string]>\n\n let commandBlock: string\n\n switch (shell) {\n case \"powershell\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `$env:${key} = ${value}`)\n .join(\"; \")\n break\n }\n case \"cmd\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set ${key}=${value}`)\n .join(\" & \")\n break\n }\n case \"fish\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set -gx ${key} ${value}`)\n .join(\"; \")\n break\n }\n default: {\n // bash, zsh, sh\n const assignments = filteredEnvVars\n .map(([key, value]) => `${key}=${value}`)\n .join(\" \")\n commandBlock = filteredEnvVars.length > 0 ? `export ${assignments}` : \"\"\n break\n }\n }\n\n if (commandBlock && commandToRun) {\n const separator = shell === \"cmd\" ? \" & \" : \" && \"\n return `${commandBlock}${separator}${commandToRun}`\n }\n\n return commandBlock || commandToRun\n}\n","import consola from \"consola\"\n\nimport { HTTPError } from \"./error\"\n\nexport const awaitApproval = async () => {\n const response = await consola.prompt(`Accept incoming request?`, {\n type: \"confirm\",\n })\n\n if (!response)\n throw new HTTPError(\n \"Request rejected\",\n Response.json({ message: \"Request rejected\" }, { status: 403 }),\n )\n}\n","import consola from \"consola\"\n\nimport type { State } from \"./state\"\n\nimport { HTTPError } from \"./error\"\nimport { sleep } from \"./utils\"\n\nexport async function checkRateLimit(state: State) {\n if (state.rateLimitSeconds === undefined) return\n\n const now = Date.now()\n\n if (!state.lastRequestTimestamp) {\n state.lastRequestTimestamp = now\n return\n }\n\n const elapsedSeconds = (now - state.lastRequestTimestamp) / 1000\n\n if (elapsedSeconds > state.rateLimitSeconds) {\n state.lastRequestTimestamp = now\n return\n }\n\n const waitTimeSeconds = Math.ceil(state.rateLimitSeconds - elapsedSeconds)\n\n if (!state.rateLimitWait) {\n consola.warn(\n `Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`,\n )\n throw new HTTPError(\n \"Rate limit exceeded\",\n Response.json({ message: \"Rate limit exceeded\" }, { status: 429 }),\n )\n }\n\n const waitTimeMs = waitTimeSeconds * 1000\n consola.warn(\n `Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`,\n )\n await sleep(waitTimeMs)\n // eslint-disable-next-line require-atomic-updates\n state.lastRequestTimestamp = now\n consola.info(\"Rate limit wait completed, proceeding with request\")\n return\n}\n","import { countTokens } from \"gpt-tokenizer/model/gpt-4o\"\n\nimport type { Message } from \"~/services/copilot/create-chat-completions\"\n\nexport const getTokenCount = (messages: Array<Message>) => {\n const simplifiedMessages = messages.map((message) => {\n let content = \"\"\n if (typeof message.content === \"string\") {\n content = message.content\n } else if (Array.isArray(message.content)) {\n content = message.content\n .filter((part) => part.type === \"text\")\n .map((part) => (part as { text: string }).text)\n .join(\"\")\n }\n return { ...message, content }\n })\n\n let inputMessages = simplifiedMessages.filter((message) => {\n return message.role !== \"tool\"\n })\n let outputMessages: typeof simplifiedMessages = []\n\n const lastMessage = simplifiedMessages.at(-1)\n\n if (lastMessage?.role === \"assistant\") {\n inputMessages = simplifiedMessages.slice(0, -1)\n outputMessages = [lastMessage]\n }\n\n // @ts-expect-error TS can't infer from arr.filter()\n const inputTokens = countTokens(inputMessages)\n // @ts-expect-error TS can't infer from arr.filter()\n const outputTokens = countTokens(outputMessages)\n\n return {\n input: inputTokens,\n output: outputTokens,\n }\n}\n","/**\n * Sanitizes JSON payloads by removing ANSI escape sequences and invisible Unicode characters\n * that can cause GitHub Copilot API to return 400 Bad Request errors.\n */\n\n/**\n * Removes ANSI escape sequences and problematic Unicode characters from a string\n */\nexport function sanitizeString(str: string): string {\n return (\n str\n // Remove ANSI escape sequences (e.g., \\x1b[31m, \\x1b[0m, etc.)\n .replaceAll(/\\x1b\\[[0-9;]*[a-z]/gi, \"\")\n // Remove other ANSI sequences that might use different patterns\n .replaceAll(/\\x1b\\[[0-9;]*m/g, \"\")\n .replaceAll(/\\x1b\\[[\\d;]*[HfA-DsuJKmhlp]/g, \"\")\n // Remove other control characters except newlines (\\n), tabs (\\t), and carriage returns (\\r)\n .replaceAll(/[\\x00-\\x08\\v\\f\\x0E-\\x1F\\x7F]/g, \"\")\n // Remove invisible Unicode characters\n .replaceAll(/[\\u200B-\\u200D\\uFEFF]/g, \"\") // Zero-width spaces, BOM\n .replaceAll(/[\\u2060-\\u2064]/g, \"\") // Word joiner, invisible separator\n .replaceAll(/[\\u206A-\\u206F]/g, \"\") // Various invisible formatting characters\n // Remove other problematic invisible characters\n .replaceAll(/[\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]/g, \"\") // Various space characters\n // Remove any remaining non-printable characters that might cause JSON parsing issues\n .replaceAll(/[\\uFFF0-\\uFFFF]/g, \"\")\n ) // Specials block\n}\n\n/**\n * Recursively sanitizes all string values in an object or array\n */\nexport function sanitizePayload<T>(payload: T): T {\n if (typeof payload === \"string\") {\n return sanitizeString(payload) as T\n }\n\n if (Array.isArray(payload)) {\n return payload.map((item) => sanitizePayload(item)) as T\n }\n\n if (payload && typeof payload === \"object\") {\n const sanitized = {} as T\n for (const [key, value] of Object.entries(payload)) {\n ;(sanitized as any)[key] = sanitizePayload(value)\n }\n return sanitized\n }\n\n return payload\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\nimport { request } from \"undici\"\n\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { sanitizePayload } from \"~/lib/sanitize\"\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 // Sanitize payload to remove ANSI escape sequences and problematic Unicode characters\n const sanitizedPayload = sanitizePayload(payload)\n\n const enableVision = sanitizedPayload.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 = sanitizedPayload.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 \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n }\n\n // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const { statusCode, headers: responseHeaders, body } = await request(`${copilotBaseUrl(state)}/chat/completions`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(sanitizedPayload),\n signal: controller.signal,\n // Set undici-specific timeouts\n headersTimeout: timeoutMs,\n bodyTimeout: timeoutMs * 3, // Triple the body timeout for streaming\n connectTimeout: timeoutMs,\n })\n\n // Create a Response-like object for compatibility\n const response = new Response(body, {\n status: statusCode,\n headers: responseHeaders as HeadersInit,\n })\n\n if (!response.ok) {\n consola.error(\"Failed to create chat completions\", response)\n throw new HTTPError(\"Failed to create chat completions\", response)\n }\n\n if (sanitizedPayload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n } finally {\n clearTimeout(timeout)\n }\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 }\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 type { Context } from \"hono\"\n\nimport consola from \"consola\"\nimport { streamSSE, type SSEMessage } from \"hono/streaming\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { state } from \"~/lib/state\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\nimport { isNullish } from \"~/lib/utils\"\nimport {\n createChatCompletions,\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n} from \"~/services/copilot/create-chat-completions\"\n\nexport async function handleCompletion(c: Context) {\n await checkRateLimit(state)\n\n let payload = await c.req.json<ChatCompletionsPayload>()\n consola.debug(\"Request payload:\", JSON.stringify(payload).slice(-400))\n\n consola.info(\"Current token count:\", getTokenCount(payload.messages))\n\n if (state.manualApprove) await awaitApproval()\n\n if (isNullish(payload.max_tokens)) {\n const selectedModel = state.models?.data.find(\n (model) => model.id === payload.model,\n )\n\n payload = {\n ...payload,\n max_tokens: selectedModel?.capabilities.limits.max_output_tokens,\n }\n consola.debug(\"Set max_tokens to:\", JSON.stringify(payload.max_tokens))\n }\n\n const response = await createChatCompletions(payload)\n\n if (isNonStreaming(response)) {\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\n return c.json(response)\n }\n\n consola.debug(\"Streaming response\")\n return streamSSE(c, async (stream) => {\n for await (const chunk of response) {\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\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","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 // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const response = await fetch(`${copilotBaseUrl(state)}/embeddings`, {\n method: \"POST\",\n headers: copilotHeaders(state),\n body: JSON.stringify(payload),\n signal: controller.signal,\n })\n\n if (!response.ok)\n throw new HTTPError(\"Failed to create embeddings\", response)\n\n return (await response.json()) as EmbeddingResponse\n } finally {\n clearTimeout(timeout)\n }\n}\n\nexport interface EmbeddingRequest {\n input: string | Array<string>\n model: string\n}\n\nexport interface Embedding {\n object: string\n embedding: Array<number>\n index: number\n}\n\nexport interface EmbeddingResponse {\n object: string\n data: Array<Embedding>\n model: string\n usage: {\n prompt_tokens: number\n total_tokens: number\n }\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport {\n createEmbeddings,\n type EmbeddingRequest,\n} from \"~/services/copilot/create-embeddings\"\n\nexport const embeddingRoutes = new Hono()\n\nembeddingRoutes.post(\"/\", async (c) => {\n try {\n const paylod = await c.req.json<EmbeddingRequest>()\n const response = await createEmbeddings(paylod)\n\n return c.json(response)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { type AnthropicResponse } from \"./anthropic-types\"\n\nexport function mapOpenAIStopReasonToAnthropic(\n finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null,\n): AnthropicResponse[\"stop_reason\"] {\n if (finishReason === null) {\n return null\n }\n const stopReasonMap = {\n stop: \"end_turn\",\n length: \"max_tokens\",\n tool_calls: \"tool_use\",\n content_filter: \"end_turn\",\n } as const\n return stopReasonMap[finishReason]\n}\n","import {\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n type ContentPart,\n type Message,\n type TextPart,\n type Tool,\n type ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicAssistantContentBlock,\n type AnthropicAssistantMessage,\n type AnthropicMessage,\n type AnthropicMessagesPayload,\n type AnthropicResponse,\n type AnthropicTextBlock,\n type AnthropicThinkingBlock,\n type AnthropicTool,\n type AnthropicToolResultBlock,\n type AnthropicToolUseBlock,\n type AnthropicUserContentBlock,\n type AnthropicUserMessage,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\n// Payload translation\n\nexport function translateToOpenAI(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload {\n return {\n model: translateModelName(payload.model),\n messages: translateAnthropicMessagesToOpenAI(\n payload.messages,\n payload.system,\n ),\n max_tokens: payload.max_tokens,\n stop: payload.stop_sequences,\n stream: payload.stream,\n temperature: payload.temperature,\n top_p: payload.top_p,\n user: payload.metadata?.user_id,\n tools: translateAnthropicToolsToOpenAI(payload.tools),\n tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),\n }\n}\n\nfunction translateModelName(model: string): string {\n // Subagent requests use a specific model number which Copilot doesn't support\n if (model.startsWith(\"claude-sonnet-4-\")) {\n return model.replace(/^claude-sonnet-4-.*/, \"claude-sonnet-4\")\n } else if (model.startsWith(\"claude-opus-\")) {\n return model.replace(/^claude-opus-4-.*/, \"claude-opus-4\")\n }\n return model\n}\n\nfunction translateAnthropicMessagesToOpenAI(\n anthropicMessages: Array<AnthropicMessage>,\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n const systemMessages = handleSystemPrompt(system)\n\n const otherMessages = anthropicMessages.flatMap((message) =>\n message.role === \"user\" ?\n handleUserMessage(message)\n : handleAssistantMessage(message),\n )\n\n return [...systemMessages, ...otherMessages]\n}\n\nfunction handleSystemPrompt(\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n if (!system) {\n return []\n }\n\n if (typeof system === \"string\") {\n return [{ role: \"system\", content: system }]\n } else {\n const systemText = system.map((block) => block.text).join(\"\\n\\n\")\n return [{ role: \"system\", content: systemText }]\n }\n}\n\nfunction handleUserMessage(message: AnthropicUserMessage): Array<Message> {\n const newMessages: Array<Message> = []\n\n if (Array.isArray(message.content)) {\n const toolResultBlocks = message.content.filter(\n (block): block is AnthropicToolResultBlock =>\n block.type === \"tool_result\",\n )\n const otherBlocks = message.content.filter(\n (block) => block.type !== \"tool_result\",\n )\n\n // Tool results must come first to maintain protocol: tool_use -> tool_result -> user\n for (const block of toolResultBlocks) {\n newMessages.push({\n role: \"tool\",\n tool_call_id: block.tool_use_id,\n content: mapContent(block.content),\n })\n }\n\n if (otherBlocks.length > 0) {\n newMessages.push({\n role: \"user\",\n content: mapContent(otherBlocks),\n })\n }\n } else {\n newMessages.push({\n role: \"user\",\n content: mapContent(message.content),\n })\n }\n\n return newMessages\n}\n\nfunction handleAssistantMessage(\n message: AnthropicAssistantMessage,\n): Array<Message> {\n if (!Array.isArray(message.content)) {\n return [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n }\n\n const toolUseBlocks = message.content.filter(\n (block): block is AnthropicToolUseBlock => block.type === \"tool_use\",\n )\n\n const textBlocks = message.content.filter(\n (block): block is AnthropicTextBlock => block.type === \"text\",\n )\n\n const thinkingBlocks = message.content.filter(\n (block): block is AnthropicThinkingBlock => block.type === \"thinking\",\n )\n\n // Combine text and thinking blocks, as OpenAI doesn't have separate thinking blocks\n const allTextContent = [\n ...textBlocks.map((b) => b.text),\n ...thinkingBlocks.map((b) => b.thinking),\n ].join(\"\\n\\n\")\n\n return toolUseBlocks.length > 0 ?\n [\n {\n role: \"assistant\",\n content: allTextContent || null,\n tool_calls: toolUseBlocks.map((toolUse) => ({\n id: toolUse.id,\n type: \"function\",\n function: {\n name: toolUse.name,\n arguments: JSON.stringify(toolUse.input),\n },\n })),\n },\n ]\n : [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n}\n\nfunction mapContent(\n content:\n | string\n | Array<AnthropicUserContentBlock | AnthropicAssistantContentBlock>,\n): string | Array<ContentPart> | null {\n if (typeof content === \"string\") {\n return content\n }\n if (!Array.isArray(content)) {\n return null\n }\n\n const hasImage = content.some((block) => block.type === \"image\")\n if (!hasImage) {\n return content\n .filter(\n (block): block is AnthropicTextBlock | AnthropicThinkingBlock =>\n block.type === \"text\" || block.type === \"thinking\",\n )\n .map((block) => (block.type === \"text\" ? block.text : block.thinking))\n .join(\"\\n\\n\")\n }\n\n const contentParts: Array<ContentPart> = []\n for (const block of content) {\n switch (block.type) {\n case \"text\": {\n contentParts.push({ type: \"text\", text: block.text })\n\n break\n }\n case \"thinking\": {\n contentParts.push({ type: \"text\", text: block.thinking })\n\n break\n }\n case \"image\": {\n contentParts.push({\n type: \"image_url\",\n image_url: {\n url: `data:${block.source.media_type};base64,${block.source.data}`,\n },\n })\n\n break\n }\n // No default\n }\n }\n return contentParts\n}\n\nfunction translateAnthropicToolsToOpenAI(\n anthropicTools: Array<AnthropicTool> | undefined,\n): Array<Tool> | undefined {\n if (!anthropicTools) {\n return undefined\n }\n return anthropicTools.map((tool) => ({\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.input_schema,\n },\n }))\n}\n\nfunction translateAnthropicToolChoiceToOpenAI(\n anthropicToolChoice: AnthropicMessagesPayload[\"tool_choice\"],\n): ChatCompletionsPayload[\"tool_choice\"] {\n if (!anthropicToolChoice) {\n return undefined\n }\n\n switch (anthropicToolChoice.type) {\n case \"auto\": {\n return \"auto\"\n }\n case \"any\": {\n return \"required\"\n }\n case \"tool\": {\n if (anthropicToolChoice.name) {\n return {\n type: \"function\",\n function: { name: anthropicToolChoice.name },\n }\n }\n return undefined\n }\n case \"none\": {\n return \"none\"\n }\n default: {\n return undefined\n }\n }\n}\n\n// Response translation\n\nexport function translateToAnthropic(\n response: ChatCompletionResponse,\n): AnthropicResponse {\n // Merge content from all choices\n const allTextBlocks: Array<AnthropicTextBlock> = []\n const allToolUseBlocks: Array<AnthropicToolUseBlock> = []\n let stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null =\n null // default\n stopReason = response.choices[0]?.finish_reason ?? stopReason\n\n // Process all choices to extract text and tool use blocks\n for (const choice of response.choices) {\n const textBlocks = getAnthropicTextBlocks(choice.message.content)\n const toolUseBlocks = getAnthropicToolUseBlocks(choice.message.tool_calls)\n\n allTextBlocks.push(...textBlocks)\n allToolUseBlocks.push(...toolUseBlocks)\n\n // Use the finish_reason from the first choice, or prioritize tool_calls\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\n stopReason = choice.finish_reason\n }\n }\n\n // Note: GitHub Copilot doesn't generate thinking blocks, so we don't include them in responses\n\n return {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n model: response.model,\n content: [...allTextBlocks, ...allToolUseBlocks],\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\n stop_sequence: null,\n usage: {\n input_tokens: response.usage?.prompt_tokens ?? 0,\n output_tokens: response.usage?.completion_tokens ?? 0,\n },\n }\n}\n\nfunction getAnthropicTextBlocks(\n messageContent: Message[\"content\"],\n): Array<AnthropicTextBlock> {\n if (typeof messageContent === \"string\") {\n return [{ type: \"text\", text: messageContent }]\n }\n\n if (Array.isArray(messageContent)) {\n return messageContent\n .filter((part): part is TextPart => part.type === \"text\")\n .map((part) => ({ type: \"text\", text: part.text }))\n }\n\n return []\n}\n\nfunction getAnthropicToolUseBlocks(\n toolCalls: Array<ToolCall> | undefined,\n): Array<AnthropicToolUseBlock> {\n if (!toolCalls) {\n return []\n }\n return toolCalls.map((toolCall) => ({\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: JSON.parse(toolCall.function.arguments) as Record<string, unknown>,\n }))\n}\n","import { type ChatCompletionChunk } from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicStreamEventData,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\nfunction isToolBlockOpen(state: AnthropicStreamState): boolean {\n if (!state.contentBlockOpen) {\n return false\n }\n // Check if the current block index corresponds to any known tool call\n return Object.values(state.toolCalls).some(\n (tc) => tc.anthropicBlockIndex === state.contentBlockIndex,\n )\n}\n\n// eslint-disable-next-line max-lines-per-function, complexity\nexport function translateChunkToAnthropicEvents(\n chunk: ChatCompletionChunk,\n state: AnthropicStreamState,\n): Array<AnthropicStreamEventData> {\n const events: Array<AnthropicStreamEventData> = []\n\n if (chunk.choices.length === 0) {\n return events\n }\n\n const choice = chunk.choices[0]\n const { delta } = choice\n\n if (!state.messageStartSent) {\n events.push({\n type: \"message_start\",\n message: {\n id: chunk.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: chunk.model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens: chunk.usage?.prompt_tokens ?? 0,\n output_tokens: 0, // Will be updated in message_delta when finished\n },\n },\n })\n state.messageStartSent = true\n }\n\n if (delta.content) {\n if (isToolBlockOpen(state)) {\n // A tool block was open, so close it before starting a text block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n if (!state.contentBlockOpen) {\n events.push({\n type: \"content_block_start\",\n index: state.contentBlockIndex,\n content_block: {\n type: \"text\",\n text: \"\",\n },\n })\n state.contentBlockOpen = true\n }\n\n events.push({\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"text_delta\",\n text: delta.content,\n },\n })\n }\n\n if (delta.tool_calls) {\n for (const toolCall of delta.tool_calls) {\n if (toolCall.id && toolCall.function?.name) {\n // New tool call starting.\n if (state.contentBlockOpen) {\n // Close any previously open block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n const anthropicBlockIndex = state.contentBlockIndex\n state.toolCalls[toolCall.index] = {\n id: toolCall.id,\n name: toolCall.function.name,\n anthropicBlockIndex,\n }\n\n events.push({\n type: \"content_block_start\",\n index: anthropicBlockIndex,\n content_block: {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: {},\n },\n })\n state.contentBlockOpen = true\n }\n\n if (toolCall.function?.arguments) {\n const toolCallInfo = state.toolCalls[toolCall.index]\n // Tool call can still be empty\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (toolCallInfo) {\n events.push({\n type: \"content_block_delta\",\n index: toolCallInfo.anthropicBlockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: toolCall.function.arguments,\n },\n })\n }\n }\n }\n }\n\n if (choice.finish_reason) {\n if (state.contentBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockOpen = false\n }\n\n events.push(\n {\n type: \"message_delta\",\n delta: {\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\n stop_sequence: null,\n },\n usage: {\n input_tokens: chunk.usage?.prompt_tokens ?? 0,\n output_tokens: chunk.usage?.completion_tokens ?? 0,\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n {\n type: \"message_stop\",\n },\n )\n }\n\n return events\n}\n\nexport function translateErrorToAnthropicErrorEvent(): AnthropicStreamEventData {\n return {\n type: \"error\",\n error: {\n type: \"api_error\",\n message: \"An unexpected error occurred during streaming.\",\n },\n }\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\nimport { streamSSE } from \"hono/streaming\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { state } from \"~/lib/state\"\nimport {\n createChatCompletions,\n type ChatCompletionChunk,\n type ChatCompletionResponse,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicMessagesPayload,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport {\n translateToAnthropic,\n translateToOpenAI,\n} from \"./non-stream-translation\"\nimport { translateChunkToAnthropicEvents } from \"./stream-translation\"\n\nexport async function handleCompletion(c: Context) {\n await checkRateLimit(state)\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n consola.debug(\"Anthropic request payload:\", JSON.stringify(anthropicPayload))\n\n const openAIPayload = translateToOpenAI(anthropicPayload)\n consola.debug(\n \"Translated OpenAI request payload:\",\n JSON.stringify(openAIPayload),\n )\n\n if (state.manualApprove) {\n await awaitApproval()\n }\n\n const response = await createChatCompletions(openAIPayload)\n\n if (isNonStreaming(response)) {\n consola.debug(\n \"Non-streaming response from Copilot:\",\n JSON.stringify(response).slice(-400),\n )\n const anthropicResponse = translateToAnthropic(response)\n consola.debug(\n \"Translated Anthropic response:\",\n JSON.stringify(anthropicResponse),\n )\n return c.json(anthropicResponse)\n }\n\n consola.debug(\"Streaming response from Copilot\")\n return streamSSE(c, async (stream) => {\n const streamState: AnthropicStreamState = {\n messageStartSent: false,\n contentBlockIndex: 0,\n contentBlockOpen: false,\n toolCalls: {},\n }\n\n for await (const rawEvent of response) {\n consola.debug(\"Copilot raw stream event:\", JSON.stringify(rawEvent))\n if (rawEvent.data === \"[DONE]\") {\n break\n }\n\n if (!rawEvent.data) {\n continue\n }\n\n const chunk = JSON.parse(rawEvent.data) as ChatCompletionChunk\n const events = translateChunkToAnthropicEvents(chunk, streamState)\n\n for (const event of events) {\n consola.debug(\"Translated Anthropic event:\", JSON.stringify(event))\n await stream.writeSSE({\n event: event.type,\n data: JSON.stringify(event),\n })\n }\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { 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","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 { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\n\nexport const tokenRoute = new Hono()\n\ntokenRoute.get(\"/\", (c) => {\n try {\n return c.json({\n token: state.copilotToken,\n })\n } catch (error) {\n console.error(\"Error fetching token:\", error)\n return c.json({ error: \"Failed to fetch token\", token: null }, 500)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { 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 console.error(\"Error fetching Copilot usage:\", error)\n return c.json({ error: \"Failed to fetch Copilot usage\" }, 500)\n }\n})\n","import { Hono } from \"hono\"\nimport { cors } from \"hono/cors\"\nimport { logger } from \"hono/logger\"\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 { tokenRoute } from \"./routes/token/route\"\nimport { usageRoute } from \"./routes/usage/route\"\n\nexport const server = new Hono()\n\nserver.use(logger())\nserver.use(cors())\n\nserver.get(\"/\", (c) => c.text(\"Server running\"))\n\nserver.route(\"/chat/completions\", completionRoutes)\nserver.route(\"/models\", modelRoutes)\nserver.route(\"/embeddings\", embeddingRoutes)\nserver.route(\"/usage\", usageRoute)\nserver.route(\"/token\", tokenRoute)\n\n// Compatibility with tools that expect v1/ prefix\nserver.route(\"/v1/chat/completions\", completionRoutes)\nserver.route(\"/v1/models\", modelRoutes)\nserver.route(\"/v1/embeddings\", embeddingRoutes)\n\n// Anthropic compatible endpoints\nserver.route(\"/v1/messages\", messageRoutes)\nserver.post(\"/v1/messages/count_tokens\", (c) => c.json({ input_tokens: 1 }))\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\nimport process from \"node:process\"\nimport { serve, type ServerHandler } from \"srvx\"\nimport invariant from \"tiny-invariant\"\n\nimport { connectivityMonitor } from \"./lib/connectivity\"\nimport { ensurePaths } from \"./lib/paths\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport {\n setupCopilotToken,\n setupGitHubToken,\n cleanupTokenManagement,\n} from \"./lib/token\"\nimport { cacheModels, cacheVSCodeVersion } from \"./lib/utils\"\nimport { server } from \"./server\"\n\n// Track cleanup functions to call on exit\nconst cleanupFunctions: Array<() => void | Promise<void>> = []\n\n// Setup process signal handlers for graceful shutdown\nfunction setupGracefulShutdown() {\n const cleanup = async () => {\n consola.info(\"Gracefully shutting down...\")\n\n // Run all cleanup functions\n for (const cleanupFn of cleanupFunctions) {\n try {\n await cleanupFn()\n } catch (error) {\n consola.error(\"Error during cleanup:\", error)\n }\n }\n\n consola.info(\"Shutdown complete\")\n process.exit(0)\n }\n\n // Handle SIGINT (Ctrl+C) and SIGTERM\n process.on(\"SIGINT\", cleanup)\n process.on(\"SIGTERM\", cleanup)\n\n // Handle uncaught exceptions and unhandled promise rejections\n process.on(\"uncaughtException\", (error) => {\n consola.error(\"Uncaught exception:\", error)\n cleanup().finally(() => process.exit(1))\n })\n\n process.on(\"unhandledRejection\", (reason, promise) => {\n consola.error(\"Unhandled promise rejection at:\", promise, \"reason:\", reason)\n cleanup().finally(() => process.exit(1))\n })\n}\n\ninterface RunServerOptions {\n port: number\n verbose: boolean\n accountType: string\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n model?: string\n smallModel?: string\n timeout?: number\n disableConnectivityMonitoring: boolean\n}\n\nexport async function runServer(options: RunServerOptions): Promise<void> {\n // Setup graceful shutdown handlers early\n setupGracefulShutdown()\n\n // Register connectivity monitor cleanup\n cleanupFunctions.push(\n () => {\n consola.debug(\"Cleaning up connectivity monitor\")\n connectivityMonitor.stop()\n },\n () => {\n consola.debug(\"Cleaning up token management\")\n cleanupTokenManagement()\n },\n )\n\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.accountType = options.accountType\n if (options.accountType !== \"individual\") {\n consola.info(`Using ${options.accountType} plan GitHub account`)\n }\n\n state.manualApprove = options.manual\n state.rateLimitSeconds = options.rateLimit\n state.rateLimitWait = options.rateLimitWait\n state.showToken = options.showToken\n state.timeoutMs = options.timeout\n state.connectivity.enabled = !options.disableConnectivityMonitoring\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) {\n invariant(state.models, \"Models should be loaded by now\")\n\n let selectedModel: string\n let selectedSmallModel: string\n\n // Check if models are provided via command line\n if (options.model && options.smallModel) {\n // Validate provided models\n const availableModelIds = state.models.data.map((model) => model.id)\n\n if (!availableModelIds.includes(options.model)) {\n consola.error(`Invalid model: ${options.model}`)\n consola.info(`Available models: \\n${availableModelIds.join(\"\\n\")}`)\n process.exit(1)\n }\n\n if (!availableModelIds.includes(options.smallModel)) {\n consola.error(`Invalid small model: ${options.smallModel}`)\n consola.info(`Available models: \\n${availableModelIds.join(\"\\n\")}`)\n process.exit(1)\n }\n\n selectedModel = options.model\n selectedSmallModel = options.smallModel\n consola.info(`Using model: ${selectedModel}`)\n consola.info(`Using small model: ${selectedSmallModel}`)\n } else if (options.model || options.smallModel) {\n // If only one model is provided, show error\n consola.error(\n \"Both --model and --small-model must be specified when using command-line model selection\",\n )\n process.exit(1)\n } else {\n // Fall back to interactive selection\n selectedModel = await consola.prompt(\n \"Select a model to use with Claude Code\",\n {\n type: \"select\",\n options: state.models.data.map((model) => model.id),\n },\n )\n\n selectedSmallModel = await consola.prompt(\n \"Select a small model to use with Claude Code\",\n {\n type: \"select\",\n options: state.models.data.map((model) => model.id),\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_SMALL_FAST_MODEL: selectedSmallModel,\n },\n \"claude\",\n )\n\n try {\n clipboard.writeSync(command)\n consola.success(\"Copied Claude Code command to clipboard!\")\n } catch {\n consola.warn(\n \"Failed to copy to clipboard. Here is the Claude Code command:\",\n )\n consola.log(command)\n }\n }\n\n consola.box(\n `🌐 Usage Viewer: https://ericc-ch.github.io/copilot-api?endpoint=${serverUrl}/usage`,\n )\n\n serve({\n fetch: server.fetch as ServerHandler,\n port: options.port,\n })\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the Copilot API server\",\n },\n args: {\n port: {\n alias: \"p\",\n type: \"string\",\n default: \"4141\",\n description: \"Port to listen on\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type to use (individual, business, enterprise)\",\n },\n manual: {\n type: \"boolean\",\n default: false,\n description: \"Enable manual request approval\",\n },\n \"rate-limit\": {\n alias: \"r\",\n type: \"string\",\n description: \"Rate limit in seconds between requests\",\n },\n wait: {\n alias: \"w\",\n type: \"boolean\",\n default: false,\n description:\n \"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set\",\n },\n \"github-token\": {\n alias: \"g\",\n type: \"string\",\n description:\n \"Provide GitHub token directly (must be generated using the `auth` subcommand)\",\n },\n \"claude-code\": {\n alias: \"c\",\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Claude Code with Copilot API config\",\n },\n model: {\n alias: \"m\",\n type: \"string\",\n description: \"Model to use with Claude Code (requires --claude-code)\",\n },\n \"small-model\": {\n alias: \"s\",\n type: \"string\",\n description:\n \"Small/fast model to use with Claude Code (requires --claude-code)\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub and Copilot tokens on fetch and refresh\",\n },\n timeout: {\n alias: \"t\",\n type: \"string\",\n description: \"API timeout in milliseconds (default: 120000)\",\n },\n \"disable-connectivity-monitoring\": {\n type: \"boolean\",\n default: false,\n description:\n \"Disable automatic network connectivity monitoring for token refresh\",\n },\n },\n run({ args }) {\n const rateLimitRaw = args[\"rate-limit\"]\n const rateLimit =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n rateLimitRaw === undefined ? undefined : Number.parseInt(rateLimitRaw, 10)\n\n const timeoutRaw = args.timeout\n const timeout =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n timeoutRaw === undefined ? 120000 : Number.parseInt(timeoutRaw, 10)\n\n return runServer({\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n accountType: args[\"account-type\"],\n manual: args.manual,\n rateLimit,\n rateLimitWait: args.wait,\n githubToken: args[\"github-token\"],\n claudeCode: args[\"claude-code\"],\n model: args.model,\n smallModel: args[\"small-model\"],\n showToken: args[\"show-token\"],\n timeout,\n disableConnectivityMonitoring: args[\"disable-connectivity-monitoring\"],\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: \"copilot-api\",\n description:\n \"A wrapper around GitHub Copilot API to make it OpenAI compatible, making it usable for other tools.\",\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>","parts: Array<string>","path","errorJson: Record<string, unknown>","errorJson: unknown","json: unknown","tokenRefreshInterval: NodeJS.Timeout | undefined","onlineHandler: (() => void) | undefined","offlineHandler: (() => void) | undefined","token","error: unknown","process","commandBlock: string","start","state","sanitizedArray: Array<unknown>","x","headers: Record<string, string>","handleCompletion","isNonStreaming","finalUsage: GitHubCopilotUsage | null","handleCompletion","newMessages: Array<Message>","contentParts: Array<ContentPart>","allTextBlocks: Array<AnthropicTextBlock>","allToolUseBlocks: Array<AnthropicToolUseBlock>","stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null","state","events: Array<AnthropicStreamEventData>","events","finalUsage: GitHubCopilotUsage | null","streamState: AnthropicStreamState","events","cleanupFunctions: Array<() => void | Promise<void>>","process","selectedModel: string","selectedSmallModel: string"],"sources":["../src/lib/paths.ts","../src/lib/state.ts","../src/lib/connectivity.ts","../src/lib/api-config.ts","../src/lib/logger/completion-logger.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/shell.ts","../src/lib/logger/enhanced-hono-logger.ts","../src/lib/approval.ts","../src/lib/logger/token-tracker.ts","../src/lib/rate-limit.ts","../src/lib/sanitize.ts","../src/services/copilot/create-chat-completions.ts","../src/routes/chat-completions/handler.ts","../src/routes/chat-completions/route.ts","../src/services/copilot/create-embeddings.ts","../src/routes/embeddings/route.ts","../src/routes/messages/utils.ts","../src/routes/messages/non-stream-translation.ts","../src/routes/messages/stream-translation.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["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\", \"copilot-api\")\n\nconst GITHUB_TOKEN_PATH = path.join(APP_DIR, \"github_token\")\nconst MACHINE_ID_PATH = path.join(APP_DIR, \"machine_id\")\nconst SESSION_ID_PATH = path.join(APP_DIR, \"session_id\")\n\nexport const PATHS = {\n APP_DIR,\n GITHUB_TOKEN_PATH,\n MACHINE_ID_PATH,\n SESSION_ID_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 await ensureFile(PATHS.MACHINE_ID_PATH)\n await ensureFile(PATHS.SESSION_ID_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 type { ModelsResponse } from \"~/services/copilot/get-models\"\n\nexport interface ConnectivityConfig {\n enabled: boolean\n probeEndpoints: Array<string>\n fastProbeInterval: number\n slowProbeInterval: number\n timeoutMs: number\n jitterMaxMs: number\n connectionPooling: boolean\n dnsCache: boolean\n}\n\nexport interface State {\n githubToken?: string\n copilotToken?: string\n\n accountType: 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 // API timeout configuration\n timeoutMs?: number\n\n // Connectivity monitoring configuration\n connectivity: ConnectivityConfig\n\n // VSCode Insiders header fields\n machineId?: string // Persistent across restarts\n sessionId?: string // Persistent for session\n}\n\nexport const state: State = {\n accountType: \"individual\",\n manualApprove: false,\n rateLimitWait: false,\n showToken: false,\n connectivity: {\n enabled: true,\n probeEndpoints: [\n \"https://api.github.com\",\n \"https://www.google.com\",\n \"https://1.1.1.1\",\n ],\n fastProbeInterval: 5000, // 5 seconds when offline\n slowProbeInterval: 60000, // 1 minute when online\n timeoutMs: 5000,\n jitterMaxMs: 1000, // 0-1 second random jitter\n connectionPooling: true, // Enable HTTP/2 connection pooling\n dnsCache: true, // Enable DNS caching headers\n },\n}\n","import consola from \"consola\"\n\nimport { state } from \"./state\"\n\ninterface ConnectivityStats {\n isOnline: boolean\n lastChecked: string\n consecutiveFailures: number\n lastErrorType?: string\n lastErrorMessage?: string\n}\n\ninterface PerformanceStats {\n currentInterval: number\n nextCheckEstimate: string\n lastSuccessfulEndpoint?: string\n endpointFailureStats: Record<string, number>\n jitterEnabled: boolean\n connectionPooling: boolean\n dnsCache: boolean\n}\n\nclass ConnectivityMonitor extends EventTarget {\n private isOnline = true\n private lastChecked = new Date().toISOString()\n private consecutiveFailures = 0\n private lastErrorType?: string\n private lastErrorMessage?: string\n private lastSuccessfulEndpoint?: string\n private endpointFailureStats: Record<string, number> = {}\n private checkInterval?: NodeJS.Timeout\n private abortController?: AbortController\n\n // EventEmitter compatibility methods\n on(event: string, listener: () => void): this {\n this.addEventListener(event, listener)\n return this\n }\n\n off(event: string, listener: () => void): this {\n this.removeEventListener(event, listener)\n return this\n }\n\n start(): void {\n if (!state.connectivity.enabled) {\n consola.debug(\"Connectivity monitoring disabled\")\n return\n }\n\n consola.info(\"Starting connectivity monitor\", {\n probeEndpoints: state.connectivity.probeEndpoints,\n fastInterval: state.connectivity.fastProbeInterval,\n })\n\n this.scheduleNextCheck()\n\n // Cleanup on process termination\n const cleanup = () => {\n this.stop()\n process.exit(0)\n }\n\n process.on(\"SIGINT\", cleanup)\n process.on(\"SIGTERM\", cleanup)\n }\n\n stop(): void {\n consola.debug(\"Stopping connectivity monitor\")\n\n if (this.checkInterval) {\n clearTimeout(this.checkInterval)\n this.checkInterval = undefined\n }\n\n if (this.abortController) {\n this.abortController.abort()\n this.abortController = undefined\n }\n }\n\n private scheduleNextCheck(): void {\n if (this.checkInterval) {\n clearTimeout(this.checkInterval)\n }\n\n const baseInterval =\n this.isOnline ?\n state.connectivity.slowProbeInterval\n : state.connectivity.fastProbeInterval\n\n // Add jitter to prevent thundering herd\n const jitter = Math.random() * state.connectivity.jitterMaxMs\n const interval = baseInterval + jitter\n\n this.checkInterval = setTimeout(() => {\n this.performConnectivityCheck().catch((error: unknown) => {\n consola.error(\"Connectivity check failed:\", error)\n })\n }, interval)\n }\n\n private async performConnectivityCheck(): Promise<void> {\n this.abortController = new AbortController()\n const timeoutId = setTimeout(\n () => this.abortController?.abort(),\n state.connectivity.timeoutMs,\n )\n\n try {\n let success = false\n\n for (const endpoint of state.connectivity.probeEndpoints) {\n try {\n const response = await fetch(endpoint, {\n method: \"HEAD\",\n signal: this.abortController.signal,\n headers: {\n \"User-Agent\": \"copilot-api-connectivity-monitor/1.0\",\n ...(state.connectivity.dnsCache && {\n \"Cache-Control\": \"max-age=300\",\n }),\n },\n })\n\n if (response.ok) {\n success = true\n this.lastSuccessfulEndpoint = endpoint\n break\n }\n } catch (error) {\n this.endpointFailureStats[endpoint] =\n (this.endpointFailureStats[endpoint] || 0) + 1\n\n consola.debug(`Probe failed for ${endpoint}:`, error)\n }\n }\n\n this.updateConnectivityState(success)\n } catch (error) {\n this.handleConnectivityError(error as Error)\n } finally {\n clearTimeout(timeoutId)\n this.scheduleNextCheck()\n }\n }\n\n private updateConnectivityState(isOnline: boolean): void {\n const wasOnline = this.isOnline\n this.isOnline = isOnline\n this.lastChecked = new Date().toISOString()\n\n if (isOnline) {\n if (this.consecutiveFailures > 0) {\n consola.info(\n `Connectivity restored after ${this.consecutiveFailures} failures`,\n )\n }\n this.consecutiveFailures = 0\n this.lastErrorType = undefined\n this.lastErrorMessage = undefined\n\n if (!wasOnline) {\n this.dispatchEvent(new CustomEvent(\"online\"))\n }\n } else {\n this.consecutiveFailures++\n\n if (wasOnline) {\n consola.warn(\"Connectivity lost\")\n this.dispatchEvent(new CustomEvent(\"offline\"))\n }\n }\n }\n\n private handleConnectivityError(error: Error): void {\n this.lastErrorType = error.name\n this.lastErrorMessage = error.message\n\n consola.error(\"Connectivity check failed:\", error)\n this.updateConnectivityState(false)\n }\n\n getConnectivityStats(): ConnectivityStats {\n return {\n isOnline: this.isOnline,\n lastChecked: this.lastChecked,\n consecutiveFailures: this.consecutiveFailures,\n lastErrorType: this.lastErrorType,\n lastErrorMessage: this.lastErrorMessage,\n }\n }\n\n getPerformanceStats(): PerformanceStats {\n const currentInterval =\n this.isOnline ?\n state.connectivity.slowProbeInterval\n : state.connectivity.fastProbeInterval\n\n const nextCheckEstimate = new Date(\n Date.now()\n + currentInterval\n + Math.random() * state.connectivity.jitterMaxMs,\n ).toISOString()\n\n return {\n currentInterval,\n nextCheckEstimate,\n lastSuccessfulEndpoint: this.lastSuccessfulEndpoint,\n endpointFailureStats: { ...this.endpointFailureStats },\n jitterEnabled: state.connectivity.jitterMaxMs > 0,\n connectionPooling: state.connectivity.connectionPooling,\n dnsCache: state.connectivity.dnsCache,\n }\n }\n}\n\nexport const connectivityMonitor = new ConnectivityMonitor()\n","import { randomUUID, createHash, randomBytes } from \"node:crypto\"\nimport fs from \"node:fs/promises\"\nimport os from \"node:os\"\n\nimport type { State } from \"./state\"\n\nimport { PATHS } from \"./paths\"\n\nexport const standardHeaders = () => ({\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n})\n\nconst COPILOT_VERSION = \"0.32.2025100203\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\nconst API_VERSION = \"2025-08-20\"\n\n// Generate stable machine ID based on system characteristics + entropy\nconst generateMachineId = (): string => {\n const hash = createHash(\"sha256\")\n hash.update(process.platform)\n hash.update(process.arch)\n hash.update(process.env.USER || process.env.USERNAME || \"anonymous\")\n hash.update(os.hostname())\n hash.update(Date.now().toString()) // Installation timestamp\n // Add entropy to prevent predictable IDs\n hash.update(randomBytes(16))\n return hash.digest(\"hex\")\n}\n\n// Read machine ID from disk, generate if missing\nconst readMachineId = async (): Promise<string> => {\n try {\n const machineId = await fs.readFile(PATHS.MACHINE_ID_PATH, \"utf8\")\n if (machineId.trim()) return machineId.trim()\n } catch {\n // File doesn't exist or is empty\n }\n\n const newMachineId = generateMachineId()\n await fs.writeFile(PATHS.MACHINE_ID_PATH, newMachineId)\n await fs.chmod(PATHS.MACHINE_ID_PATH, 0o600)\n return newMachineId\n}\n\n// Read session ID from disk, generate if missing\nconst readSessionId = async (): Promise<string> => {\n try {\n const sessionId = await fs.readFile(PATHS.SESSION_ID_PATH, \"utf8\")\n if (sessionId.trim()) return sessionId.trim()\n } catch {\n // File doesn't exist or is empty\n }\n\n const newSessionId = randomUUID()\n await fs.writeFile(PATHS.SESSION_ID_PATH, newSessionId)\n await fs.chmod(PATHS.SESSION_ID_PATH, 0o600)\n return newSessionId\n}\n\n// Initialize machine and session IDs (call during app startup)\nexport const initializeVSCodeIdentifiers = async (\n state: State,\n): Promise<void> => {\n if (!state.machineId) {\n // eslint-disable-next-line require-atomic-updates\n state.machineId = await readMachineId()\n }\n if (!state.sessionId) {\n // eslint-disable-next-line require-atomic-updates\n state.sessionId = await readSessionId()\n }\n}\n\nexport const copilotBaseUrl = (state: State) =>\n state.accountType === \"individual\" ?\n \"https://api.githubcopilot.com\"\n : `https://api.${state.accountType}.githubcopilot.com`\nexport const copilotHeaders = (state: State, vision: boolean = false) => {\n // Validate required IDs exist (should be initialized at startup)\n if (!state.machineId || !state.sessionId) {\n throw new Error(\n \"VSCode identifiers not initialized. Call initializeVSCodeIdentifiers() during startup.\",\n )\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${state.copilotToken}`,\n \"Content-Type\": \"application/json\",\n\n // Updated to match VSCode Insiders exact casing\n accept: \"*/*\",\n \"accept-encoding\": \"br, gzip, deflate\",\n \"accept-language\": \"*\",\n \"sec-fetch-mode\": \"cors\",\n\n // VSCode identification - exact casing from VSCode Insiders\n \"Copilot-Integration-Id\": \"vscode-chat\",\n \"Editor-Version\": `vscode/${state.vsCodeVersion}`,\n \"Editor-Plugin-Version\": EDITOR_PLUGIN_VERSION,\n \"User-Agent\": USER_AGENT,\n \"VScode-MachineId\": state.machineId,\n \"VScode-SessionId\": state.sessionId,\n\n // Updated intent and interaction type - exact casing\n \"OpenAI-Intent\": \"conversation-agent\",\n \"X-Interaction-Type\": \"conversation-agent\",\n\n // Updated user agent library - exact casing\n \"X-VSCode-User-Agent-Library-Version\": \"node-fetch\",\n\n // Request tracking - exact casing\n \"X-GitHub-Api-Version\": API_VERSION,\n \"X-Interaction-Id\": randomUUID(), // New - unique per request\n \"X-Request-Id\": randomUUID(),\n\n // Lowercase duplicates as they appear in VSCode Insiders\n \"openai-intent\": \"conversation-agent\",\n \"x-interaction-type\": \"conversation-agent\",\n }\n\n if (vision) headers[\"copilot-vision-request\"] = \"true\"\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\": \"node-fetch\",\n})\n\nexport const GITHUB_BASE_URL = \"https://github.com\"\nexport const GITHUB_CLIENT_ID = \"01ab8ac9400c4e429b23\"\nexport const GITHUB_APP_SCOPES = [\"user:email\"].join(\" \")\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport { state } from \"~/lib/state\"\n\ninterface CompletionData {\n context: Context\n startTime: number\n requestId: string\n}\n\ninterface TokenUsage {\n inputTokens?: number\n outputTokens?: number\n}\n\ninterface RequestData {\n model?: string\n tokenUsage?: TokenUsage\n copilotDuration?: number\n}\n\n// Helper function to humanize large numbers\nconst humanize = (num: number): string => {\n if (num >= 100000) return `${Math.round(num / 1000)}K`\n if (num >= 10000) return `${Math.round(num / 1000)}K`\n if (num >= 1000) return `${(num / 1000).toFixed(1)}K`\n return num.toString()\n}\n\n// Helper function to pad strings for alignment\nconst pad = (str: string, length: number) => str.padEnd(length)\n\n// Calculate context window percentage\nconst getContextPercentage = (contextWindow: number, model: string): string => {\n if (!state.models) return \"\"\n\n const selectedModel = state.models.data.find((m) => m.id === model)\n if (!selectedModel) return \"\"\n\n const maxContextTokens =\n selectedModel.capabilities.limits.max_context_window_tokens\n\n if (!maxContextTokens) return \"\"\n\n const percentage = ((contextWindow / maxContextTokens) * 100).toFixed(1)\n return ` (${percentage}%)`\n}\n\n// Format token usage information\nconst formatTokenUsage = (requestData: RequestData): string => {\n const parts: Array<string> = []\n\n if (requestData.model) {\n const model = pad(requestData.model, 18)\n parts.push(model)\n }\n\n if (requestData.tokenUsage) {\n const usage = requestData.tokenUsage\n const contextWindow = (usage.inputTokens || 0) + (usage.outputTokens || 0)\n\n const contextPercentage =\n requestData.model ?\n getContextPercentage(contextWindow, requestData.model)\n : \"\"\n\n const input = humanize(usage.inputTokens || 0).padStart(5)\n const output = humanize(usage.outputTokens || 0).padStart(5)\n const tokenPart = `↑${input} │ ↓${output}`\n const tokens = pad(tokenPart, 18)\n\n // Format context with number left-aligned and percentage right-aligned\n const contextNum = contextWindow.toString()\n const contextFormatted =\n contextPercentage ?\n `${contextNum}${contextPercentage.padStart(15 - contextNum.length)}`\n : contextNum.padEnd(15)\n\n parts.push(`Tokens: ${tokens} | Context: ${contextFormatted}`)\n } else if (requestData.model) {\n // Show when token data is missing for requests that should have it\n const tokens = pad(\"N/A\", 18)\n const context = \"N/A\".padEnd(15)\n parts.push(`Tokens: ${tokens} | Context: ${context}`)\n }\n\n if (requestData.copilotDuration) {\n const apiDuration = pad(`${Math.round(requestData.copilotDuration)}ms`, 8)\n parts.push(`API: ${apiDuration}`)\n }\n\n return parts.length > 0 ? ` | ${parts.join(\" | \")}` : \"\"\n}\n\nexport const CompletionLogger = {\n completionCallbacks: new Map<string, CompletionData>(),\n\n registerCompletion(requestId: string, context: Context, startTime: number) {\n this.completionCallbacks.set(requestId, { context, startTime, requestId })\n },\n\n executeCompletion(requestId: string) {\n const data = this.completionCallbacks.get(requestId)\n if (data) {\n this.logCompletion(data)\n this.completionCallbacks.delete(requestId)\n }\n },\n\n logCompletion(data: CompletionData) {\n const { context: c, startTime } = data\n const end = Date.now()\n const duration = end - startTime\n const requestData = c.get(\"requestData\") as RequestData | undefined\n\n // Build the enhanced log line with fixed-width columns\n const method = pad(c.req.method, 4)\n const path = pad(c.req.path, 18)\n const status = pad(c.res.status.toString(), 3)\n const durationStr = pad(`${duration}ms`, 8)\n\n let logLine = ` --> ${method}${path}${status} ${durationStr}`\n\n // Add token usage and performance info if available\n if (requestData) {\n logLine += formatTokenUsage(requestData)\n }\n\n consola.info(logLine)\n },\n\n logRateLimit(data: CompletionData, response: Response) {\n const { context: c, startTime } = data\n const end = Date.now()\n const duration = end - startTime\n\n // Extract rate limit info from headers\n const rateLimitExceeded = response.headers.get(\"x-ratelimit-exceeded\") || \"\"\n const rateLimitType = rateLimitExceeded.split(\":\")[1] || \"unknown\"\n const retry =\n response.headers.get(\"retry-after\")\n || response.headers.get(\"x-ratelimit-user-retry-after\")\n || \"?\"\n\n // Build the log line with same format as successful requests\n const method = pad(c.req.method, 4)\n const path = pad(c.req.path, 18)\n const status = pad(\"429\", 3)\n const durationStr = pad(`${duration}ms`, 8)\n\n let logLine = `⚠ --> ${method}${path}${status} ${durationStr}`\n logLine += ` | Rate limited (${retry}s retry) | ${rateLimitType}`\n\n // Add API timing if available\n const requestData = c.get(\"requestData\") as RequestData | undefined\n if (requestData?.copilotDuration) {\n const apiDuration = pad(`${Math.round(requestData.copilotDuration)}ms`, 8)\n logLine += ` | API: ${apiDuration}`\n }\n\n consola.info(logLine)\n },\n\n // Cleanup method to prevent memory leaks\n cleanup() {\n const MAX_CALLBACKS = 1000 // Prevent unbounded growth\n const fiveMinutesAgo = Date.now() - 5 * 60 * 1000\n\n // Remove callbacks older than 5 minutes\n for (const [requestId, data] of this.completionCallbacks) {\n if (data.startTime < fiveMinutesAgo) {\n this.completionCallbacks.delete(requestId)\n }\n }\n\n // If still too many callbacks, remove oldest ones\n if (this.completionCallbacks.size > MAX_CALLBACKS) {\n const entries = Array.from(this.completionCallbacks.entries()).sort(\n ([, a], [, b]) => a.startTime - b.startTime,\n )\n\n const toRemove = entries.slice(0, entries.length - MAX_CALLBACKS)\n for (const [requestId] of toRemove) {\n this.completionCallbacks.delete(requestId)\n }\n }\n },\n}\n\n// Cleanup old callbacks every minute\nsetInterval(() => CompletionLogger.cleanup(), 60 * 1000)\n","import type { Context } from \"hono\"\nimport type { ContentfulStatusCode } from \"hono/utils/http-status\"\n\nimport consola from \"consola\"\n\nimport { CompletionLogger } from \"~/lib/logger/completion-logger\"\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 if (error instanceof HTTPError && error.response.status === 429) {\n // Handle 429 errors with clean logging\n const requestId = c.get(\"requestId\")\n const completionData = CompletionLogger.completionCallbacks.get(requestId)\n\n if (completionData) {\n CompletionLogger.logRateLimit(completionData, error.response)\n CompletionLogger.completionCallbacks.delete(requestId)\n }\n\n // Return the error response without verbose logging\n const errorText = await error.response.text()\n let errorJson: Record<string, unknown>\n try {\n errorJson = JSON.parse(errorText) as Record<string, unknown>\n } catch {\n errorJson = { error: { message: errorText, type: \"error\" } }\n }\n\n return c.json(errorJson, 429)\n }\n\n // Existing error handling for non-429 errors\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 = errorText\n }\n consola.error(\"HTTP error:\", errorJson)\n return c.json(\n {\n error: {\n message: errorText,\n type: \"error\",\n },\n },\n error.response.status as ContentfulStatusCode,\n )\n }\n\n return c.json(\n {\n error: {\n message: (error as Error).message,\n type: \"error\",\n },\n },\n 500,\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 getCopilotToken = async () => {\n // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(state),\n signal: controller.signal,\n },\n )\n\n if (!response.ok)\n throw new HTTPError(\"Failed to get Copilot token\", response)\n\n return (await response.json()) as GetCopilotTokenResponse\n } finally {\n clearTimeout(timeout)\n }\n}\n\n// Trimmed for the sake of simplicity\ninterface GetCopilotTokenResponse {\n expires_at: number\n refresh_in: number\n token: string\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\"\nimport { state } from \"~/lib/state\"\n\nexport async function getDeviceCode(): Promise<DeviceCodeResponse> {\n // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\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 signal: controller.signal,\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get device code\", response)\n\n return (await response.json()) as DeviceCodeResponse\n } finally {\n clearTimeout(timeout)\n }\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 // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\n ...standardHeaders(),\n },\n signal: controller.signal,\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get GitHub user\", response)\n\n return (await response.json()) as GithubUserResponse\n } finally {\n clearTimeout(timeout)\n }\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 // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const response = await fetch(`${copilotBaseUrl(state)}/models`, {\n headers: copilotHeaders(state),\n signal: controller.signal,\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get models\", response)\n\n return (await response.json()) as ModelsResponse\n } finally {\n clearTimeout(timeout)\n }\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\ninterface 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 policy?: {\n state: string\n terms: string\n }\n}\n","export function getVSCodeVersion() {\n return \"1.105.0-insider\"\n}\n\ngetVSCodeVersion()\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\nexport async function cacheModels(): Promise<void> {\n const models = await getModels()\n state.models = models\n}\n\nexport const cacheVSCodeVersion = () => {\n const response = 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 { state } from \"~/lib/state\"\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\n while (true) {\n // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\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 signal: controller.signal,\n },\n )\n\n if (!response.ok) {\n await sleep(sleepDuration)\n consola.error(\"Failed to poll access token:\", await response.text())\n\n continue\n }\n\n const json: unknown = 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 } else {\n await sleep(sleepDuration)\n }\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n consola.error(\"Access token polling timed out\")\n await sleep(sleepDuration)\n continue\n }\n throw error\n } finally {\n clearTimeout(timeout)\n }\n }\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 { connectivityMonitor } from \"~/lib/connectivity\"\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\n// Track cleanup resources for token management\nlet tokenRefreshInterval: NodeJS.Timeout | undefined\nlet isRefreshPending = false\n\n// Event listener functions that can be removed\nlet onlineHandler: (() => void) | undefined\nlet offlineHandler: (() => void) | undefined\n\n// Cleanup function to be called on shutdown\nexport function cleanupTokenManagement() {\n consola.debug(\"Cleaning up token management\")\n\n // Clear the refresh interval\n if (tokenRefreshInterval) {\n clearInterval(tokenRefreshInterval)\n tokenRefreshInterval = undefined\n }\n\n // Remove event listeners\n if (onlineHandler) {\n connectivityMonitor.off(\"online\", onlineHandler)\n onlineHandler = undefined\n }\n\n if (offlineHandler) {\n connectivityMonitor.off(\"offline\", offlineHandler)\n offlineHandler = undefined\n }\n}\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 = (refresh_in - 60) * 1000\n\n const refreshTokenWithRetry = async (\n maxRetries = 5,\n baseDelay = 1000,\n reason = \"scheduled\",\n ) => {\n if (isRefreshPending) {\n consola.debug(\"Token refresh already in progress, skipping\")\n return\n }\n\n isRefreshPending = true\n try {\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n consola.debug(\n `Refreshing Copilot token (${reason}, attempt ${attempt}/${maxRetries})`,\n )\n const { token } = await getCopilotToken()\n state.copilotToken = token\n consola.debug(\"Copilot token refreshed successfully\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n return // Success - exit retry loop\n } catch (error: unknown) {\n const isLastAttempt = attempt === maxRetries\n consola.error(\n `Failed to refresh Copilot token (attempt ${attempt}/${maxRetries}):`,\n error,\n )\n\n if (isLastAttempt) {\n consola.error(\n \"All token refresh attempts failed. Service may be unavailable until next scheduled refresh.\",\n )\n return // Give up after max retries\n }\n\n // Exponential backoff: wait 1s, 2s, 4s, 8s, 16s\n const delay = baseDelay * Math.pow(2, attempt - 1)\n consola.debug(`Retrying token refresh in ${delay}ms...`)\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n }\n } finally {\n // Reset the pending flag - this is intentionally done in finally block\n // eslint-disable-next-line require-atomic-updates\n isRefreshPending = false\n }\n }\n\n // Set up scheduled token refresh\n tokenRefreshInterval = setInterval(() => {\n // Don't await to prevent blocking the interval timer\n refreshTokenWithRetry(5, 1000, \"scheduled\").catch((error: unknown) => {\n consola.error(\"Unexpected error in scheduled token refresh:\", error)\n })\n }, refreshInterval)\n\n // Start connectivity monitoring\n connectivityMonitor.start()\n\n // Create event handler functions that can be properly removed\n onlineHandler = () => {\n consola.debug(\n \"Network connectivity restored, attempting immediate token refresh\",\n )\n // Attempt immediate refresh when network comes back\n refreshTokenWithRetry(3, 500, \"network-restored\").catch(\n (error: unknown) => {\n consola.error(\n \"Unexpected error in network-restored token refresh:\",\n error,\n )\n },\n )\n }\n\n offlineHandler = () => {\n consola.debug(\"Network connectivity lost\")\n }\n\n // Listen for network restoration events\n connectivityMonitor.on(\"online\", onlineHandler)\n connectivityMonitor.on(\"offline\", offlineHandler)\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 // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/user`,\n {\n headers: githubHeaders(state),\n signal: controller.signal,\n },\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 } finally {\n clearTimeout(timeout)\n }\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 const packageJsonBuffer = await fs.readFile(packageJsonPath)\n const packageJson = JSON.parse(packageJsonBuffer.toString()) 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(`copilot-api 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 { execSync } from \"node:child_process\"\nimport process from \"node:process\"\n\ntype ShellName = \"bash\" | \"zsh\" | \"fish\" | \"powershell\" | \"cmd\" | \"sh\"\ntype EnvVars = Record<string, string | undefined>\n\nfunction getShell(): ShellName {\n const { platform, ppid, env } = process\n\n if (platform === \"win32\") {\n try {\n const command = `wmic process get ParentProcessId,Name | findstr \"${ppid}\"`\n const parentProcess = execSync(command, { stdio: \"pipe\" }).toString()\n\n if (parentProcess.toLowerCase().includes(\"powershell.exe\")) {\n return \"powershell\"\n }\n } catch {\n return \"cmd\"\n }\n\n return \"cmd\"\n } else {\n const shellPath = env.SHELL\n if (shellPath) {\n if (shellPath.endsWith(\"zsh\")) return \"zsh\"\n if (shellPath.endsWith(\"fish\")) return \"fish\"\n if (shellPath.endsWith(\"bash\")) return \"bash\"\n }\n\n return \"sh\"\n }\n}\n\n/**\n * Generates a copy-pasteable script to set multiple environment variables\n * and run a subsequent command.\n * @param {EnvVars} envVars - An object of environment variables to set.\n * @param {string} commandToRun - The command to run after setting the variables.\n * @returns {string} The formatted script string.\n */\nexport function generateEnvScript(\n envVars: EnvVars,\n commandToRun: string = \"\",\n): string {\n const shell = getShell()\n const filteredEnvVars = Object.entries(envVars).filter(\n ([, value]) => value !== undefined,\n ) as Array<[string, string]>\n\n let commandBlock: string\n\n switch (shell) {\n case \"powershell\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `$env:${key} = ${value}`)\n .join(\"; \")\n break\n }\n case \"cmd\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set ${key}=${value}`)\n .join(\" & \")\n break\n }\n case \"fish\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set -gx ${key} ${value}`)\n .join(\"; \")\n break\n }\n default: {\n // bash, zsh, sh\n const assignments = filteredEnvVars\n .map(([key, value]) => `${key}=${value}`)\n .join(\" \")\n commandBlock = filteredEnvVars.length > 0 ? `export ${assignments}` : \"\"\n break\n }\n }\n\n if (commandBlock && commandToRun) {\n const separator = shell === \"cmd\" ? \" & \" : \" && \"\n return `${commandBlock}${separator}${commandToRun}`\n }\n\n return commandBlock || commandToRun\n}\n","import type { Context, Next } from \"hono\"\n\nimport type { TokenUsage } from \"./token-tracker\"\n\nimport { CompletionLogger } from \"./completion-logger\"\n\n// Store request data for use in completion log\ndeclare module \"hono\" {\n interface ContextVariableMap {\n requestId: string\n requestData?: {\n model?: string\n tokenUsage?: TokenUsage\n copilotDuration?: number\n }\n }\n}\n\n// Generate unique request ID\nfunction generateRequestId(): string {\n return `req_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`\n}\n\nexport function enhancedLogger() {\n return async (c: Context, next: Next) => {\n const start = Date.now()\n const requestId = generateRequestId()\n\n // Store request ID\n c.set(\"requestId\", requestId)\n\n // Add request ID to response headers\n c.header(\"x-request-id\", requestId)\n\n // Register for post-completion logging\n CompletionLogger.registerCompletion(requestId, c, start)\n\n await next()\n\n // Check if we have complete token data immediately (non-streaming)\n const requestData = c.get(\"requestData\")\n if (requestData?.tokenUsage) {\n // Complete data available, log now and skip completion callback\n CompletionLogger.executeCompletion(requestId)\n }\n // For streaming responses, detailed log will happen after stream completes via CompletionLogger\n }\n}\n","import consola from \"consola\"\n\nimport { HTTPError } from \"./error\"\n\nexport const awaitApproval = async () => {\n const response = await consola.prompt(`Accept incoming request?`, {\n type: \"confirm\",\n })\n\n if (!response)\n throw new HTTPError(\n \"Request rejected\",\n Response.json({ message: \"Request rejected\" }, { status: 403 }),\n )\n}\n","export interface TokenUsage {\n inputTokens: number\n outputTokens: number\n totalTokens: number\n estimatedCost?: number\n // GitHub Copilot specific fields\n cachedTokens?: number\n acceptedPredictionTokens?: number\n rejectedPredictionTokens?: number\n}\n\n// Pricing data (update as needed) - example rates\nconst TOKEN_PRICING = {\n input: 0.000003, // $0.003 per 1K tokens\n output: 0.000015, // $0.015 per 1K tokens\n} as const\n\nexport interface GitHubCopilotUsage {\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// Parse GitHub Copilot usage data from streaming response\nexport function parseGitHubCopilotUsage(\n usageData: GitHubCopilotUsage,\n): TokenUsage {\n const inputTokens = usageData.prompt_tokens || 0\n const outputTokens = usageData.completion_tokens || 0\n const totalTokens = usageData.total_tokens || inputTokens + outputTokens\n\n const estimatedCost =\n inputTokens * TOKEN_PRICING.input + outputTokens * TOKEN_PRICING.output\n\n return {\n inputTokens,\n outputTokens,\n totalTokens,\n estimatedCost,\n cachedTokens: usageData.prompt_tokens_details?.cached_tokens,\n acceptedPredictionTokens:\n usageData.completion_tokens_details?.accepted_prediction_tokens,\n rejectedPredictionTokens:\n usageData.completion_tokens_details?.rejected_prediction_tokens,\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 // eslint-disable-next-line require-atomic-updates\n state.lastRequestTimestamp = now\n consola.info(\"Rate limit wait completed, proceeding with request\")\n return\n}\n","/**\n * Sanitizes JSON payloads by removing ANSI escape sequences and invisible Unicode characters\n * that can cause GitHub Copilot API to return 400 Bad Request errors.\n */\n\n/**\n * Removes ANSI escape sequences and problematic Unicode characters from a string\n */\nexport function sanitizeString(str: string): string {\n let result = str\n\n // Remove ANSI escape sequences without using control regex\n // ESC sequence starts with \\x1b (character code 27)\n const escChar = String.fromCodePoint(27)\n\n // Simple approach: split on ESC and filter out ANSI sequences\n const parts = result.split(escChar)\n if (parts.length > 1) {\n // Keep first part, then process remaining parts\n result = parts[0]\n for (let i = 1; i < parts.length; i++) {\n const part = parts[i]\n // Find end of ANSI sequence - match [, optional params (digits/semicolons), and end letter\n const match = part.match(/^\\[[0-9;]*[a-z]/i)\n // Remove the ANSI sequence if found, otherwise add ESC back and keep the part\n result += match ? part.slice(match[0].length) : escChar + part\n }\n }\n\n return (\n result\n // Remove invisible Unicode characters\n .replaceAll(/[\\u200B-\\u200D\\uFEFF]/g, \"\") // Zero-width spaces, BOM\n .replaceAll(/[\\u2060-\\u2064]/g, \"\") // Word joiner, invisible separator\n .replaceAll(/[\\u206A-\\u206F]/g, \"\") // Various invisible formatting characters\n // Remove other problematic invisible characters\n .replaceAll(/[\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]/g, \"\") // Various space characters\n // Remove any remaining non-printable characters that might cause JSON parsing issues\n .replaceAll(/[\\uFFF0-\\uFFFF]/g, \"\")\n // Remove control characters (0x00-0x1F) except for newline (0x0A) and tab (0x09)\n // eslint-disable-next-line no-control-regex\n .replaceAll(/[\\x00-\\x08\\v\\f\\x0E-\\x1F]/g, \"\")\n )\n}\n\n/**\n * Recursively sanitizes all string values in an object or array\n */\nexport function sanitizePayload<T>(payload: T): T {\n if (typeof payload === \"string\") {\n return sanitizeString(payload) as T\n }\n\n if (Array.isArray(payload)) {\n // Type-safe array handling with explicit typing\n const sanitizedArray: Array<unknown> = payload.map((item: unknown) =>\n sanitizePayload(item),\n )\n return sanitizedArray as T\n }\n\n if (payload && typeof payload === \"object\") {\n const sanitized = {} as Record<string, unknown>\n for (const [key, value] of Object.entries(payload)) {\n sanitized[key] = sanitizePayload(value)\n }\n return sanitized as T\n }\n\n return payload\n}\n","import { events } from \"fetch-event-stream\"\nimport { request } from \"undici\"\n\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { sanitizePayload } from \"~/lib/sanitize\"\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 // Sanitize payload to remove ANSI escape sequences and problematic Unicode characters\n const sanitizedPayload = sanitizePayload(payload)\n\n const enableVision = sanitizedPayload.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 = sanitizedPayload.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 \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n }\n\n // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const {\n statusCode,\n headers: responseHeaders,\n body,\n } = await request(`${copilotBaseUrl(state)}/chat/completions`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(sanitizedPayload),\n signal: controller.signal,\n // Set undici-specific timeouts\n headersTimeout: timeoutMs,\n bodyTimeout: timeoutMs * 3, // Triple the body timeout for streaming\n })\n\n // Create a Response-like object for compatibility\n const response = new Response(body as unknown as ReadableStream, {\n status: statusCode,\n headers: responseHeaders as HeadersInit,\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to create chat completions\", response)\n }\n\n if (sanitizedPayload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n } finally {\n clearTimeout(timeout)\n }\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 }\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 type { Context } from \"hono\"\n\nimport consola from \"consola\"\nimport { streamSSE, type SSEMessage } from \"hono/streaming\"\n\nimport type { GitHubCopilotUsage } from \"~/lib/logger/token-tracker\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { CompletionLogger } from \"~/lib/logger/completion-logger\"\nimport { parseGitHubCopilotUsage } from \"~/lib/logger/token-tracker\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { state } from \"~/lib/state\"\nimport { isNullish } from \"~/lib/utils\"\nimport {\n createChatCompletions,\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n} from \"~/services/copilot/create-chat-completions\"\n\nexport async function handleCompletion(c: Context) {\n await checkRateLimit(state)\n\n let payload = await c.req.json<ChatCompletionsPayload>()\n consola.debug(\"Request payload:\", JSON.stringify(payload).slice(-400))\n\n // Store initial request data for completion log\n c.set(\"requestData\", {\n model: payload.model,\n })\n\n if (state.manualApprove) {\n await awaitApproval()\n }\n\n if (isNullish(payload.max_tokens)) {\n const selectedModel = state.models?.data.find(\n (model) => model.id === payload.model,\n )\n\n payload = {\n ...payload,\n max_tokens: selectedModel?.capabilities.limits.max_output_tokens,\n }\n consola.debug(\"Set max_tokens to:\", JSON.stringify(payload.max_tokens))\n }\n\n const copilotStart = performance.now()\n const response = await createChatCompletions(payload)\n const copilotDuration = performance.now() - copilotStart\n\n if (isNonStreaming(response)) {\n // Store data for completion log\n const requestData = c.get(\"requestData\") || {}\n if (response.usage) {\n requestData.tokenUsage = parseGitHubCopilotUsage(response.usage)\n }\n requestData.copilotDuration = copilotDuration\n c.set(\"requestData\", requestData)\n\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\n return c.json(response)\n }\n\n return streamSSE(c, async (stream) => {\n let finalUsage: GitHubCopilotUsage | null = null\n\n for await (const chunk of response) {\n if (chunk.data && chunk.data !== \"[DONE]\") {\n try {\n const parsed = JSON.parse(chunk.data) as {\n usage?: GitHubCopilotUsage\n }\n // Check for usage data in streaming response (usually in final chunk)\n if (parsed.usage) {\n finalUsage = parsed.usage\n // Store the data immediately when we find it\n const requestData = c.get(\"requestData\") || {}\n requestData.tokenUsage = parseGitHubCopilotUsage(finalUsage)\n requestData.copilotDuration = copilotDuration\n c.set(\"requestData\", requestData)\n }\n } catch {\n // Ignore parse errors for chunks\n }\n }\n\n await stream.writeSSE(chunk as SSEMessage)\n }\n\n // Ensure we have the data stored even if we didn't catch it in the loop\n if (finalUsage) {\n const requestData = c.get(\"requestData\") || {}\n if (!requestData.tokenUsage) {\n requestData.tokenUsage = parseGitHubCopilotUsage(finalUsage)\n requestData.copilotDuration = copilotDuration\n c.set(\"requestData\", requestData)\n }\n }\n\n // Trigger completion logging now that streaming is done\n const requestId = c.get(\"requestId\")\n if (requestId) {\n CompletionLogger.executeCompletion(requestId)\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCompletion } from \"./handler\"\n\nexport const completionRoutes = new Hono()\n\ncompletionRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { 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 // Setup timeout with AbortController\n const controller = new AbortController()\n const timeoutMs = state.timeoutMs ?? 120000 // Default to 2 minutes\n const timeout = setTimeout(() => {\n controller.abort()\n }, timeoutMs)\n\n try {\n const response = await fetch(`${copilotBaseUrl(state)}/embeddings`, {\n method: \"POST\",\n headers: copilotHeaders(state),\n body: JSON.stringify(payload),\n signal: controller.signal,\n })\n\n if (!response.ok)\n throw new HTTPError(\"Failed to create embeddings\", response)\n\n return (await response.json()) as EmbeddingResponse\n } finally {\n clearTimeout(timeout)\n }\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 { parseGitHubCopilotUsage } from \"~/lib/logger/token-tracker\"\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\n // Store initial request data for completion log\n c.set(\"requestData\", {\n model: payload.model,\n })\n\n const copilotStart = performance.now()\n const response = await createEmbeddings(payload)\n const copilotDuration = performance.now() - copilotStart\n\n // Store data for completion log\n const requestData = c.get(\"requestData\") || {}\n requestData.tokenUsage = parseGitHubCopilotUsage(response.usage)\n requestData.copilotDuration = copilotDuration\n c.set(\"requestData\", requestData)\n\n return c.json(response)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { type AnthropicResponse } from \"./anthropic-types\"\n\nexport function mapOpenAIStopReasonToAnthropic(\n finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null,\n): AnthropicResponse[\"stop_reason\"] {\n if (finishReason === null) {\n return null\n }\n const stopReasonMap = {\n stop: \"end_turn\",\n length: \"max_tokens\",\n tool_calls: \"tool_use\",\n content_filter: \"end_turn\",\n } as const\n return stopReasonMap[finishReason]\n}\n","import {\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n type ContentPart,\n type Message,\n type TextPart,\n type Tool,\n type ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicAssistantContentBlock,\n type AnthropicAssistantMessage,\n type AnthropicMessage,\n type AnthropicMessagesPayload,\n type AnthropicResponse,\n type AnthropicTextBlock,\n type AnthropicThinkingBlock,\n type AnthropicTool,\n type AnthropicToolResultBlock,\n type AnthropicToolUseBlock,\n type AnthropicUserContentBlock,\n type AnthropicUserMessage,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\n// Payload translation\n\nexport function translateToOpenAI(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload {\n return {\n model: translateModelName(payload.model),\n messages: translateAnthropicMessagesToOpenAI(\n payload.messages,\n payload.system,\n ),\n max_tokens: payload.max_tokens,\n stop: payload.stop_sequences,\n stream: payload.stream,\n temperature: payload.temperature,\n top_p: payload.top_p,\n user: payload.metadata?.user_id,\n tools: translateAnthropicToolsToOpenAI(payload.tools),\n tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),\n }\n}\n\nfunction translateModelName(model: string): string {\n // Subagent requests use a specific model number which Copilot doesn't support\n if (model.startsWith(\"claude-sonnet-4-\")) {\n return model.replace(/^claude-sonnet-4-.*/, \"claude-sonnet-4\")\n } else if (model.startsWith(\"claude-opus-\")) {\n return model.replace(/^claude-opus-4-.*/, \"claude-opus-4\")\n }\n return model\n}\n\nfunction translateAnthropicMessagesToOpenAI(\n anthropicMessages: Array<AnthropicMessage>,\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n const systemMessages = handleSystemPrompt(system)\n\n const otherMessages = anthropicMessages.flatMap((message) =>\n message.role === \"user\" ?\n handleUserMessage(message)\n : handleAssistantMessage(message),\n )\n\n return [...systemMessages, ...otherMessages]\n}\n\nfunction handleSystemPrompt(\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n if (!system) {\n return []\n }\n\n if (typeof system === \"string\") {\n return [{ role: \"system\", content: system }]\n } else {\n const systemText = system.map((block) => block.text).join(\"\\n\\n\")\n return [{ role: \"system\", content: systemText }]\n }\n}\n\nfunction handleUserMessage(message: AnthropicUserMessage): Array<Message> {\n const newMessages: Array<Message> = []\n\n if (Array.isArray(message.content)) {\n const toolResultBlocks = message.content.filter(\n (block): block is AnthropicToolResultBlock =>\n block.type === \"tool_result\",\n )\n const otherBlocks = message.content.filter(\n (block) => block.type !== \"tool_result\",\n )\n\n // Tool results must come first to maintain protocol: tool_use -> tool_result -> user\n for (const block of toolResultBlocks) {\n newMessages.push({\n role: \"tool\",\n tool_call_id: block.tool_use_id,\n content: mapContent(block.content),\n })\n }\n\n if (otherBlocks.length > 0) {\n newMessages.push({\n role: \"user\",\n content: mapContent(otherBlocks),\n })\n }\n } else {\n newMessages.push({\n role: \"user\",\n content: mapContent(message.content),\n })\n }\n\n return newMessages\n}\n\nfunction handleAssistantMessage(\n message: AnthropicAssistantMessage,\n): Array<Message> {\n if (!Array.isArray(message.content)) {\n return [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n }\n\n const toolUseBlocks = message.content.filter(\n (block): block is AnthropicToolUseBlock => block.type === \"tool_use\",\n )\n\n const textBlocks = message.content.filter(\n (block): block is AnthropicTextBlock => block.type === \"text\",\n )\n\n const thinkingBlocks = message.content.filter(\n (block): block is AnthropicThinkingBlock => block.type === \"thinking\",\n )\n\n // Combine text and thinking blocks, as OpenAI doesn't have separate thinking blocks\n const allTextContent = [\n ...textBlocks.map((b) => b.text),\n ...thinkingBlocks.map((b) => b.thinking),\n ].join(\"\\n\\n\")\n\n return toolUseBlocks.length > 0 ?\n [\n {\n role: \"assistant\",\n content: allTextContent || null,\n tool_calls: toolUseBlocks.map((toolUse) => ({\n id: toolUse.id,\n type: \"function\",\n function: {\n name: toolUse.name,\n arguments: JSON.stringify(toolUse.input),\n },\n })),\n },\n ]\n : [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n}\n\nfunction mapContent(\n content:\n | string\n | Array<AnthropicUserContentBlock | AnthropicAssistantContentBlock>,\n): string | Array<ContentPart> | null {\n if (typeof content === \"string\") {\n return content\n }\n if (!Array.isArray(content)) {\n return null\n }\n\n const hasImage = content.some((block) => block.type === \"image\")\n if (!hasImage) {\n return content\n .filter(\n (block): block is AnthropicTextBlock | AnthropicThinkingBlock =>\n block.type === \"text\" || block.type === \"thinking\",\n )\n .map((block) => (block.type === \"text\" ? block.text : block.thinking))\n .join(\"\\n\\n\")\n }\n\n const contentParts: Array<ContentPart> = []\n for (const block of content) {\n switch (block.type) {\n case \"text\": {\n contentParts.push({ type: \"text\", text: block.text })\n\n break\n }\n case \"thinking\": {\n contentParts.push({ type: \"text\", text: block.thinking })\n\n break\n }\n case \"image\": {\n contentParts.push({\n type: \"image_url\",\n image_url: {\n url: `data:${block.source.media_type};base64,${block.source.data}`,\n },\n })\n\n break\n }\n // No default\n }\n }\n return contentParts\n}\n\nfunction translateAnthropicToolsToOpenAI(\n anthropicTools: Array<AnthropicTool> | undefined,\n): Array<Tool> | undefined {\n if (!anthropicTools) {\n return undefined\n }\n return anthropicTools.map((tool) => ({\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.input_schema,\n },\n }))\n}\n\nfunction translateAnthropicToolChoiceToOpenAI(\n anthropicToolChoice: AnthropicMessagesPayload[\"tool_choice\"],\n): ChatCompletionsPayload[\"tool_choice\"] {\n if (!anthropicToolChoice) {\n return undefined\n }\n\n switch (anthropicToolChoice.type) {\n case \"auto\": {\n return \"auto\"\n }\n case \"any\": {\n return \"required\"\n }\n case \"tool\": {\n if (anthropicToolChoice.name) {\n return {\n type: \"function\",\n function: { name: anthropicToolChoice.name },\n }\n }\n return undefined\n }\n case \"none\": {\n return \"none\"\n }\n default: {\n return undefined\n }\n }\n}\n\n// Response translation\n\nexport function translateToAnthropic(\n response: ChatCompletionResponse,\n): AnthropicResponse {\n // Merge content from all choices\n const allTextBlocks: Array<AnthropicTextBlock> = []\n const allToolUseBlocks: Array<AnthropicToolUseBlock> = []\n let stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null =\n null // default\n stopReason = response.choices[0]?.finish_reason ?? stopReason\n\n // Process all choices to extract text and tool use blocks\n for (const choice of response.choices) {\n const textBlocks = getAnthropicTextBlocks(choice.message.content)\n const toolUseBlocks = getAnthropicToolUseBlocks(choice.message.tool_calls)\n\n allTextBlocks.push(...textBlocks)\n allToolUseBlocks.push(...toolUseBlocks)\n\n // Use the finish_reason from the first choice, or prioritize tool_calls\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\n stopReason = choice.finish_reason\n }\n }\n\n // Note: GitHub Copilot doesn't generate thinking blocks, so we don't include them in responses\n\n return {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n model: response.model,\n content: [...allTextBlocks, ...allToolUseBlocks],\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\n stop_sequence: null,\n usage: {\n input_tokens: response.usage?.prompt_tokens ?? 0,\n output_tokens: response.usage?.completion_tokens ?? 0,\n },\n }\n}\n\nfunction getAnthropicTextBlocks(\n messageContent: Message[\"content\"],\n): Array<AnthropicTextBlock> {\n if (typeof messageContent === \"string\") {\n return [{ type: \"text\", text: messageContent }]\n }\n\n if (Array.isArray(messageContent)) {\n return messageContent\n .filter((part): part is TextPart => part.type === \"text\")\n .map((part) => ({ type: \"text\", text: part.text }))\n }\n\n return []\n}\n\nfunction getAnthropicToolUseBlocks(\n toolCalls: Array<ToolCall> | undefined,\n): Array<AnthropicToolUseBlock> {\n if (!toolCalls) {\n return []\n }\n return toolCalls.map((toolCall) => ({\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: JSON.parse(toolCall.function.arguments) as Record<string, unknown>,\n }))\n}\n","import { type ChatCompletionChunk } from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicStreamEventData,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\nfunction isToolBlockOpen(state: AnthropicStreamState): boolean {\n if (!state.contentBlockOpen) {\n return false\n }\n // Check if the current block index corresponds to any known tool call\n return Object.values(state.toolCalls).some(\n (tc) => tc.anthropicBlockIndex === state.contentBlockIndex,\n )\n}\n\n// eslint-disable-next-line max-lines-per-function, complexity\nexport function translateChunkToAnthropicEvents(\n chunk: ChatCompletionChunk,\n state: AnthropicStreamState,\n): Array<AnthropicStreamEventData> {\n const events: Array<AnthropicStreamEventData> = []\n\n if (chunk.choices.length === 0) {\n return events\n }\n\n const choice = chunk.choices[0]\n const { delta } = choice\n\n if (!state.messageStartSent) {\n events.push({\n type: \"message_start\",\n message: {\n id: chunk.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: chunk.model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens: chunk.usage?.prompt_tokens ?? 0,\n output_tokens: 0, // Will be updated in message_delta when finished\n },\n },\n })\n state.messageStartSent = true\n }\n\n if (delta.content) {\n if (isToolBlockOpen(state)) {\n // A tool block was open, so close it before starting a text block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n if (!state.contentBlockOpen) {\n events.push({\n type: \"content_block_start\",\n index: state.contentBlockIndex,\n content_block: {\n type: \"text\",\n text: \"\",\n },\n })\n state.contentBlockOpen = true\n }\n\n events.push({\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"text_delta\",\n text: delta.content,\n },\n })\n }\n\n if (delta.tool_calls) {\n for (const toolCall of delta.tool_calls) {\n if (toolCall.id && toolCall.function?.name) {\n // New tool call starting.\n if (state.contentBlockOpen) {\n // Close any previously open block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n const anthropicBlockIndex = state.contentBlockIndex\n state.toolCalls[toolCall.index] = {\n id: toolCall.id,\n name: toolCall.function.name,\n anthropicBlockIndex,\n }\n\n events.push({\n type: \"content_block_start\",\n index: anthropicBlockIndex,\n content_block: {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: {},\n },\n })\n state.contentBlockOpen = true\n }\n\n if (toolCall.function?.arguments) {\n const toolCallInfo = state.toolCalls[toolCall.index]\n // Tool call can still be empty\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (toolCallInfo) {\n events.push({\n type: \"content_block_delta\",\n index: toolCallInfo.anthropicBlockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: toolCall.function.arguments,\n },\n })\n }\n }\n }\n }\n\n if (choice.finish_reason) {\n if (state.contentBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockOpen = false\n }\n\n events.push(\n {\n type: \"message_delta\",\n delta: {\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\n stop_sequence: null,\n },\n usage: {\n input_tokens: chunk.usage?.prompt_tokens ?? 0,\n output_tokens: chunk.usage?.completion_tokens ?? 0,\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n {\n type: \"message_stop\",\n },\n )\n }\n\n return events\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\nimport { streamSSE } from \"hono/streaming\"\n\nimport { awaitApproval } from \"~/lib/approval\"\nimport { CompletionLogger } from \"~/lib/logger/completion-logger\"\nimport {\n parseGitHubCopilotUsage,\n type GitHubCopilotUsage,\n} from \"~/lib/logger/token-tracker\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { state } from \"~/lib/state\"\nimport {\n createChatCompletions,\n type ChatCompletionChunk,\n type ChatCompletionResponse,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicMessagesPayload,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport {\n translateToAnthropic,\n translateToOpenAI,\n} from \"./non-stream-translation\"\nimport { translateChunkToAnthropicEvents } from \"./stream-translation\"\n\nexport async function handleCompletion(c: Context) {\n await checkRateLimit(state)\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n consola.debug(\"Anthropic request payload:\", JSON.stringify(anthropicPayload))\n\n const openAIPayload = translateToOpenAI(anthropicPayload)\n consola.debug(\n \"Translated OpenAI request payload:\",\n JSON.stringify(openAIPayload),\n )\n\n // Store initial request data for completion log\n c.set(\"requestData\", {\n model: openAIPayload.model,\n })\n\n const copilotStart = performance.now()\n\n if (state.manualApprove) {\n await awaitApproval()\n }\n\n const response = await createChatCompletions(openAIPayload)\n const copilotDuration = performance.now() - copilotStart\n\n if (isNonStreaming(response)) {\n // Store data for completion log\n const requestData = c.get(\"requestData\") || {}\n if (response.usage) {\n requestData.tokenUsage = parseGitHubCopilotUsage(response.usage)\n }\n requestData.copilotDuration = copilotDuration\n c.set(\"requestData\", requestData)\n\n consola.debug(\n \"Non-streaming response from Copilot:\",\n JSON.stringify(response).slice(-400),\n )\n const anthropicResponse = translateToAnthropic(response)\n consola.debug(\n \"Translated Anthropic response:\",\n JSON.stringify(anthropicResponse),\n )\n return c.json(anthropicResponse)\n }\n\n consola.debug(\"Streaming response from Copilot\")\n return streamSSE(c, async (stream) => {\n let finalUsage: GitHubCopilotUsage | null = null\n\n const streamState: AnthropicStreamState = {\n messageStartSent: false,\n contentBlockIndex: 0,\n contentBlockOpen: false,\n toolCalls: {},\n }\n\n for await (const rawEvent of response) {\n consola.debug(\"Copilot raw stream event:\", JSON.stringify(rawEvent))\n if (rawEvent.data === \"[DONE]\") {\n break\n }\n\n if (!rawEvent.data) {\n continue\n }\n\n const chunk = JSON.parse(rawEvent.data) as ChatCompletionChunk\n\n // Check for usage data in streaming response (usually in final chunk)\n if (chunk.usage) {\n finalUsage = chunk.usage\n // Store the data immediately when we find it\n const requestData = c.get(\"requestData\") || {}\n requestData.tokenUsage = parseGitHubCopilotUsage(finalUsage)\n requestData.copilotDuration = copilotDuration\n c.set(\"requestData\", requestData)\n }\n\n const events = translateChunkToAnthropicEvents(chunk, streamState)\n\n for (const event of events) {\n consola.debug(\"Translated Anthropic event:\", JSON.stringify(event))\n await stream.writeSSE({\n event: event.type,\n data: JSON.stringify(event),\n })\n }\n }\n\n // Ensure we have the data stored even if we didn't catch it in the loop\n if (finalUsage) {\n const requestData = c.get(\"requestData\") || {}\n if (!requestData.tokenUsage) {\n requestData.tokenUsage = parseGitHubCopilotUsage(finalUsage)\n requestData.copilotDuration = copilotDuration\n c.set(\"requestData\", requestData)\n }\n }\n\n // Trigger completion logging now that streaming is done\n const requestId = c.get(\"requestId\")\n if (requestId) {\n CompletionLogger.executeCompletion(requestId)\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCompletion } from \"./handler\"\n\nexport const 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","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 { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\n\nexport const tokenRoute = new Hono()\n\ntokenRoute.get(\"/\", (c) => {\n try {\n return c.json({\n token: state.copilotToken,\n })\n } catch (error) {\n console.error(\"Error fetching token:\", error)\n return c.json({ error: \"Failed to fetch token\", token: null }, 500)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { 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 console.error(\"Error fetching Copilot usage:\", error)\n return c.json({ error: \"Failed to fetch Copilot usage\" }, 500)\n }\n})\n","import { Hono } from \"hono\"\nimport { cors } from \"hono/cors\"\n\nimport { enhancedLogger } from \"./lib/logger/enhanced-hono-logger\"\nimport { completionRoutes } from \"./routes/chat-completions/route\"\nimport { embeddingRoutes } from \"./routes/embeddings/route\"\nimport { messageRoutes } from \"./routes/messages/route\"\nimport { modelRoutes } from \"./routes/models/route\"\nimport { tokenRoute } from \"./routes/token/route\"\nimport { usageRoute } from \"./routes/usage/route\"\n\nexport const server = new Hono()\n\n// Core middleware - order matters\nserver.use(enhancedLogger()) // Use our enhanced logger instead of default\nserver.use(cors())\n\nserver.get(\"/\", (c) => c.text(\"Server running\"))\n\nserver.route(\"/chat/completions\", completionRoutes)\nserver.route(\"/models\", modelRoutes)\nserver.route(\"/embeddings\", embeddingRoutes)\nserver.route(\"/usage\", usageRoute)\nserver.route(\"/token\", tokenRoute)\n\n// Compatibility with tools that expect v1/ prefix\nserver.route(\"/v1/chat/completions\", completionRoutes)\nserver.route(\"/v1/models\", modelRoutes)\nserver.route(\"/v1/embeddings\", embeddingRoutes)\n\n// Anthropic compatible endpoints\nserver.route(\"/v1/messages\", messageRoutes)\nserver.post(\"/v1/messages/count_tokens\", (c) => c.json({ input_tokens: 1 }))\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\nimport process from \"node:process\"\nimport { serve, type ServerHandler } from \"srvx\"\nimport invariant from \"tiny-invariant\"\n\nimport { initializeVSCodeIdentifiers } from \"./lib/api-config\"\nimport { connectivityMonitor } from \"./lib/connectivity\"\nimport { ensurePaths } from \"./lib/paths\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport {\n setupCopilotToken,\n setupGitHubToken,\n cleanupTokenManagement,\n} from \"./lib/token\"\nimport { cacheModels, cacheVSCodeVersion } from \"./lib/utils\"\nimport { server } from \"./server\"\n\n// Track cleanup functions to call on exit\nconst cleanupFunctions: Array<() => void | Promise<void>> = []\n\n// Setup process signal handlers for graceful shutdown\nfunction setupGracefulShutdown() {\n const cleanup = async () => {\n consola.info(\"Gracefully shutting down...\")\n\n // Run all cleanup functions\n for (const cleanupFn of cleanupFunctions) {\n try {\n await cleanupFn()\n } catch (error) {\n consola.error(\"Error during cleanup:\", error)\n }\n }\n\n consola.info(\"Shutdown complete\")\n process.exit(0)\n }\n\n // Handle SIGINT (Ctrl+C) and SIGTERM\n process.on(\"SIGINT\", cleanup)\n process.on(\"SIGTERM\", cleanup)\n\n // Handle uncaught exceptions and unhandled promise rejections\n process.on(\"uncaughtException\", (error) => {\n consola.error(\"Uncaught exception:\", error)\n void cleanup().finally(() => process.exit(1))\n })\n\n process.on(\"unhandledRejection\", (reason, promise) => {\n consola.error(\"Unhandled promise rejection at:\", promise, \"reason:\", reason)\n void cleanup().finally(() => process.exit(1))\n })\n}\n\ninterface RunServerOptions {\n port: number\n verbose: boolean\n accountType: string\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n model?: string\n smallModel?: string\n timeout?: number\n disableConnectivityMonitoring: boolean\n}\n\nasync function setupClaudeCodeConfiguration(\n options: RunServerOptions,\n serverUrl: string,\n): Promise<void> {\n if (!options.claudeCode) return\n\n invariant(state.models, \"Models should be loaded by now\")\n\n let selectedModel: string\n let selectedSmallModel: string\n\n // Check if models are provided via command line\n if (options.model && options.smallModel) {\n // Validate provided models\n const availableModelIds = state.models.data.map((model) => model.id)\n\n if (!availableModelIds.includes(options.model)) {\n consola.error(`Invalid model: ${options.model}`)\n consola.info(`Available models: \\n${availableModelIds.join(\"\\n\")}`)\n process.exit(1)\n }\n\n if (!availableModelIds.includes(options.smallModel)) {\n consola.error(`Invalid small model: ${options.smallModel}`)\n consola.info(`Available models: \\n${availableModelIds.join(\"\\n\")}`)\n process.exit(1)\n }\n\n selectedModel = options.model\n selectedSmallModel = options.smallModel\n consola.info(`Using model: ${selectedModel}`)\n consola.info(`Using small model: ${selectedSmallModel}`)\n } else if (options.model || options.smallModel) {\n // If only one model is provided, show error\n consola.error(\n \"Both --model and --small-model must be specified when using command-line model selection\",\n )\n process.exit(1)\n } else {\n // Fall back to interactive selection\n selectedModel = await consola.prompt(\n \"Select a model to use with Claude Code\",\n {\n type: \"select\",\n options: state.models.data.map((model) => model.id),\n },\n )\n\n selectedSmallModel = await consola.prompt(\n \"Select a small model to use with Claude Code\",\n {\n type: \"select\",\n options: state.models.data.map((model) => model.id),\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_SMALL_FAST_MODEL: selectedSmallModel,\n },\n \"claude\",\n )\n\n try {\n clipboard.writeSync(command)\n consola.success(\"Copied Claude Code command to clipboard!\")\n } catch {\n consola.warn(\n \"Failed to copy to clipboard. Here is the Claude Code command:\",\n )\n consola.log(command)\n }\n}\n\nexport async function runServer(options: RunServerOptions): Promise<void> {\n // Setup graceful shutdown handlers early\n setupGracefulShutdown()\n\n // Register connectivity monitor cleanup\n cleanupFunctions.push(\n () => {\n consola.debug(\"Cleaning up connectivity monitor\")\n connectivityMonitor.stop()\n },\n () => {\n consola.debug(\"Cleaning up token management\")\n cleanupTokenManagement()\n },\n )\n\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.accountType = options.accountType\n if (options.accountType !== \"individual\") {\n consola.info(`Using ${options.accountType} plan GitHub account`)\n }\n\n state.manualApprove = options.manual\n state.rateLimitSeconds = options.rateLimit\n state.rateLimitWait = options.rateLimitWait\n state.showToken = options.showToken\n state.timeoutMs = options.timeout\n state.connectivity.enabled = !options.disableConnectivityMonitoring\n\n await ensurePaths()\n cacheVSCodeVersion()\n\n // Initialize VSCode identifiers for header matching\n await initializeVSCodeIdentifiers(state)\n\n if (options.githubToken) {\n // eslint-disable-next-line require-atomic-updates\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 await setupClaudeCodeConfiguration(options, serverUrl)\n\n consola.box(\n `🌐 Usage Viewer: https://ericc-ch.github.io/copilot-api?endpoint=${serverUrl}/usage`,\n )\n\n serve({\n fetch: server.fetch as ServerHandler,\n port: options.port,\n })\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the Copilot API server\",\n },\n args: {\n port: {\n alias: \"p\",\n type: \"string\",\n default: \"4141\",\n description: \"Port to listen on\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type to use (individual, business, enterprise)\",\n },\n manual: {\n type: \"boolean\",\n default: false,\n description: \"Enable manual request approval\",\n },\n \"rate-limit\": {\n alias: \"r\",\n type: \"string\",\n description: \"Rate limit in seconds between requests\",\n },\n wait: {\n alias: \"w\",\n type: \"boolean\",\n default: false,\n description:\n \"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set\",\n },\n \"github-token\": {\n alias: \"g\",\n type: \"string\",\n description:\n \"Provide GitHub token directly (must be generated using the `auth` subcommand)\",\n },\n \"claude-code\": {\n alias: \"c\",\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Claude Code with Copilot API config\",\n },\n model: {\n alias: \"m\",\n type: \"string\",\n description: \"Model to use with Claude Code (requires --claude-code)\",\n },\n \"small-model\": {\n alias: \"s\",\n type: \"string\",\n description:\n \"Small/fast model to use with Claude Code (requires --claude-code)\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub and Copilot tokens on fetch and refresh\",\n },\n timeout: {\n alias: \"t\",\n type: \"string\",\n description: \"API timeout in milliseconds (default: 120000)\",\n },\n \"disable-connectivity-monitoring\": {\n type: \"boolean\",\n default: false,\n description:\n \"Disable automatic network connectivity monitoring for token refresh\",\n },\n },\n run({ args }) {\n const rateLimitRaw = args[\"rate-limit\"]\n const rateLimit =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n rateLimitRaw === undefined ? undefined : Number.parseInt(rateLimitRaw, 10)\n\n const timeoutRaw = args.timeout\n const timeout =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n timeoutRaw === undefined ? 120000 : Number.parseInt(timeoutRaw, 10)\n\n return runServer({\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n accountType: args[\"account-type\"],\n manual: args.manual,\n rateLimit,\n rateLimitWait: args.wait,\n githubToken: args[\"github-token\"],\n claudeCode: args[\"claude-code\"],\n model: args.model,\n smallModel: args[\"small-model\"],\n showToken: args[\"show-token\"],\n timeout,\n disableConnectivityMonitoring: args[\"disable-connectivity-monitoring\"],\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: \"copilot-api\",\n description:\n \"A wrapper around GitHub Copilot API to make it OpenAI compatible, making it usable for other tools.\",\n },\n subCommands: { auth, start, \"check-usage\": checkUsage, debug },\n})\n\nawait runMain(main)\n"],"mappings":"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"}