@ashsec/copilot-api 0.7.10 → 0.7.11
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 +45 -27
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -19,7 +19,7 @@ import { streamSSE } from "hono/streaming";
|
|
|
19
19
|
|
|
20
20
|
//#region package.json
|
|
21
21
|
var name = "@ashsec/copilot-api";
|
|
22
|
-
var version = "0.7.
|
|
22
|
+
var version = "0.7.11";
|
|
23
23
|
var description = "Turn GitHub Copilot into OpenAI/Anthropic API compatible server. Usable with Claude Code!";
|
|
24
24
|
var keywords = [
|
|
25
25
|
"proxy",
|
|
@@ -184,7 +184,7 @@ var HTTPError = class extends Error {
|
|
|
184
184
|
}
|
|
185
185
|
};
|
|
186
186
|
function isContentFilterError(obj) {
|
|
187
|
-
return typeof obj === "object" && obj !== null && "error" in obj && typeof obj.error === "object" && obj.error
|
|
187
|
+
return typeof obj === "object" && obj !== null && "error" in obj && typeof obj.error === "object" && obj.error.code === "content_filter";
|
|
188
188
|
}
|
|
189
189
|
async function forwardError(c, error) {
|
|
190
190
|
consola.error("Error occurred:", error);
|
|
@@ -678,7 +678,7 @@ const checkUsage = defineCommand({
|
|
|
678
678
|
const SYSTEM_REPLACEMENTS = [{
|
|
679
679
|
id: "system-anthropic-billing",
|
|
680
680
|
name: "Remove Anthropic billing header",
|
|
681
|
-
pattern:
|
|
681
|
+
pattern: String.raw`x-anthropic-billing-header:[^\n]*\n?`,
|
|
682
682
|
replacement: "",
|
|
683
683
|
isRegex: true,
|
|
684
684
|
enabled: true,
|
|
@@ -735,7 +735,8 @@ async function getUserReplacements() {
|
|
|
735
735
|
/**
|
|
736
736
|
* Add a new user replacement rule
|
|
737
737
|
*/
|
|
738
|
-
async function addReplacement(pattern, replacement,
|
|
738
|
+
async function addReplacement(pattern, replacement, options) {
|
|
739
|
+
const { isRegex = false, name: name$1 } = options ?? {};
|
|
739
740
|
await ensureLoaded();
|
|
740
741
|
const rule = {
|
|
741
742
|
id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
@@ -1389,6 +1390,14 @@ function getStatusColor(status) {
|
|
|
1389
1390
|
return colors.green;
|
|
1390
1391
|
}
|
|
1391
1392
|
/**
|
|
1393
|
+
* Sanitize request body by omitting large message/prompt arrays
|
|
1394
|
+
*/
|
|
1395
|
+
function sanitizeRequestBody(parsed) {
|
|
1396
|
+
const sanitized = {};
|
|
1397
|
+
for (const [key, value] of Object.entries(parsed)) sanitized[key] = key === "messages" || key === "prompt" ? `[${Array.isArray(value) ? value.length : 1} items omitted]` : value;
|
|
1398
|
+
return sanitized;
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1392
1401
|
* Log raw HTTP request details (for debug mode)
|
|
1393
1402
|
*/
|
|
1394
1403
|
async function logRawRequest(c) {
|
|
@@ -1396,9 +1405,7 @@ async function logRawRequest(c) {
|
|
|
1396
1405
|
const url = c.req.url;
|
|
1397
1406
|
const headers = Object.fromEntries(c.req.raw.headers.entries());
|
|
1398
1407
|
const lines = [];
|
|
1399
|
-
lines.push(`${colors.magenta}${colors.bold}[DEBUG] Incoming Request${colors.reset}`);
|
|
1400
|
-
lines.push(`${colors.cyan}${method}${colors.reset} ${url}`);
|
|
1401
|
-
lines.push(`${colors.dim}Headers:${colors.reset}`);
|
|
1408
|
+
lines.push(`${colors.magenta}${colors.bold}[DEBUG] Incoming Request${colors.reset}`, `${colors.cyan}${method}${colors.reset} ${url}`, `${colors.dim}Headers:${colors.reset}`);
|
|
1402
1409
|
for (const [key, value] of Object.entries(headers)) {
|
|
1403
1410
|
const displayValue = key.toLowerCase().includes("authorization") ? `${value.slice(0, 20)}...` : value;
|
|
1404
1411
|
lines.push(` ${colors.gray}${key}:${colors.reset} ${displayValue}`);
|
|
@@ -1407,11 +1414,8 @@ async function logRawRequest(c) {
|
|
|
1407
1414
|
const body = await c.req.raw.clone().text();
|
|
1408
1415
|
if (body) try {
|
|
1409
1416
|
const parsed = JSON.parse(body);
|
|
1410
|
-
const sanitized =
|
|
1411
|
-
|
|
1412
|
-
else sanitized[key] = value;
|
|
1413
|
-
lines.push(`${colors.dim}Body (sanitized):${colors.reset}`);
|
|
1414
|
-
lines.push(` ${JSON.stringify(sanitized, null, 2).split("\n").join("\n ")}`);
|
|
1417
|
+
const sanitized = sanitizeRequestBody(parsed);
|
|
1418
|
+
lines.push(`${colors.dim}Body (sanitized):${colors.reset}`, ` ${JSON.stringify(sanitized, null, 2).split("\n").join("\n ")}`);
|
|
1415
1419
|
} catch {
|
|
1416
1420
|
lines.push(`${colors.dim}Body:${colors.reset} [${body.length} bytes]`);
|
|
1417
1421
|
}
|
|
@@ -1450,7 +1454,7 @@ async function requestLogger(c, next) {
|
|
|
1450
1454
|
const statusBadge = `${statusColor}${status}${colors.reset}`;
|
|
1451
1455
|
const durationStr = `${colors.cyan}${duration}s${colors.reset}`;
|
|
1452
1456
|
lines.push(`${colors.bold}${method}${colors.reset} ${path$1} ${statusBadge} ${durationStr}`);
|
|
1453
|
-
if (ctx?.provider && ctx
|
|
1457
|
+
if (ctx?.provider && ctx.model) {
|
|
1454
1458
|
const providerColor = ctx.provider === "Azure OpenAI" ? colors.blue : colors.magenta;
|
|
1455
1459
|
lines.push(` ${colors.gray}Provider:${colors.reset} ${providerColor}${ctx.provider}${colors.reset} ${colors.gray}->${colors.reset} ${colors.white}${ctx.model}${colors.reset}`);
|
|
1456
1460
|
}
|
|
@@ -1479,7 +1483,7 @@ const awaitApproval = async () => {
|
|
|
1479
1483
|
* "gpt-5-1-codex" -> "gpt-5.1-codex"
|
|
1480
1484
|
*/
|
|
1481
1485
|
function normalizeModelName(model) {
|
|
1482
|
-
return model.
|
|
1486
|
+
return model.replaceAll(/(\d)-(\d)/g, (_, p1, p2) => `${p1}.${p2}`);
|
|
1483
1487
|
}
|
|
1484
1488
|
|
|
1485
1489
|
//#endregion
|
|
@@ -1883,8 +1887,8 @@ function translateToOpenAI(payload) {
|
|
|
1883
1887
|
};
|
|
1884
1888
|
}
|
|
1885
1889
|
function translateModelName(model) {
|
|
1886
|
-
if (
|
|
1887
|
-
else if (
|
|
1890
|
+
if (/^claude-sonnet-4-\d{8}/.test(model)) return "claude-sonnet-4";
|
|
1891
|
+
else if (/^claude-opus-4-\d{8}/.test(model)) return "claude-opus-4";
|
|
1888
1892
|
return model;
|
|
1889
1893
|
}
|
|
1890
1894
|
function translateAnthropicMessagesToOpenAI(anthropicMessages, system) {
|
|
@@ -2002,23 +2006,35 @@ function translateAnthropicToolChoiceToOpenAI(anthropicToolChoice) {
|
|
|
2002
2006
|
}
|
|
2003
2007
|
}
|
|
2004
2008
|
function translateToAnthropic(response, originalModel) {
|
|
2009
|
+
const { contentBlocks, stopReason } = extractContentFromChoices(response);
|
|
2010
|
+
return buildAnthropicResponse(response, {
|
|
2011
|
+
contentBlocks,
|
|
2012
|
+
stopReason,
|
|
2013
|
+
originalModel
|
|
2014
|
+
});
|
|
2015
|
+
}
|
|
2016
|
+
function extractContentFromChoices(response) {
|
|
2005
2017
|
const allTextBlocks = [];
|
|
2006
2018
|
const allToolUseBlocks = [];
|
|
2007
|
-
let stopReason = null;
|
|
2008
|
-
stopReason = response.choices[0]?.finish_reason ?? stopReason;
|
|
2019
|
+
let stopReason = response.choices[0]?.finish_reason ?? null;
|
|
2009
2020
|
for (const choice of response.choices) {
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
allTextBlocks.push(...textBlocks);
|
|
2013
|
-
allToolUseBlocks.push(...toolUseBlocks);
|
|
2021
|
+
allTextBlocks.push(...getAnthropicTextBlocks(choice.message.content));
|
|
2022
|
+
allToolUseBlocks.push(...getAnthropicToolUseBlocks(choice.message.tool_calls));
|
|
2014
2023
|
if (choice.finish_reason === "tool_calls" || stopReason === "stop") stopReason = choice.finish_reason;
|
|
2015
2024
|
}
|
|
2025
|
+
return {
|
|
2026
|
+
contentBlocks: [...allTextBlocks, ...allToolUseBlocks],
|
|
2027
|
+
stopReason
|
|
2028
|
+
};
|
|
2029
|
+
}
|
|
2030
|
+
function buildAnthropicResponse(response, options) {
|
|
2031
|
+
const { contentBlocks, stopReason, originalModel } = options;
|
|
2016
2032
|
return {
|
|
2017
2033
|
id: response.id,
|
|
2018
2034
|
type: "message",
|
|
2019
2035
|
role: "assistant",
|
|
2020
2036
|
model: originalModel ?? response.model,
|
|
2021
|
-
content:
|
|
2037
|
+
content: contentBlocks,
|
|
2022
2038
|
stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),
|
|
2023
2039
|
stop_sequence: null,
|
|
2024
2040
|
usage: {
|
|
@@ -2124,8 +2140,8 @@ function translateChunkToAnthropicEvents(chunk, state$1, originalModel) {
|
|
|
2124
2140
|
const events$1 = [];
|
|
2125
2141
|
if (chunk.usage) {
|
|
2126
2142
|
state$1.pendingUsage = {
|
|
2127
|
-
prompt_tokens: chunk.usage.prompt_tokens
|
|
2128
|
-
completion_tokens: chunk.usage.completion_tokens
|
|
2143
|
+
prompt_tokens: chunk.usage.prompt_tokens,
|
|
2144
|
+
completion_tokens: chunk.usage.completion_tokens,
|
|
2129
2145
|
cached_tokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
|
|
2130
2146
|
};
|
|
2131
2147
|
if (state$1.pendingFinishReason && !state$1.messageDeltaSent) {
|
|
@@ -2305,7 +2321,8 @@ async function handleCompletion(c) {
|
|
|
2305
2321
|
stream: true,
|
|
2306
2322
|
stream_options: { include_usage: true }
|
|
2307
2323
|
};
|
|
2308
|
-
const
|
|
2324
|
+
const azureConfig = state.azureOpenAIConfig;
|
|
2325
|
+
const eventStream = isAzureModel && azureConfig ? await createAzureOpenAIChatCompletions(azureConfig, streamPayload) : await createChatCompletions(streamPayload);
|
|
2309
2326
|
return streamSSE(c, async (stream) => {
|
|
2310
2327
|
const { chunks, usage } = await collectChunksWithUsage(eventStream);
|
|
2311
2328
|
consola.debug(`[stream] Collected ${chunks.length} chunks, usage:`, usage);
|
|
@@ -2345,7 +2362,8 @@ async function handleCompletion(c) {
|
|
|
2345
2362
|
...openAIPayload,
|
|
2346
2363
|
stream: false
|
|
2347
2364
|
};
|
|
2348
|
-
const
|
|
2365
|
+
const azureConfigNonStream = state.azureOpenAIConfig;
|
|
2366
|
+
const response = isAzureModel && azureConfigNonStream ? await createAzureOpenAIChatCompletions(azureConfigNonStream, nonStreamPayload) : await createChatCompletions(nonStreamPayload);
|
|
2349
2367
|
if (response.usage) setRequestContext(c, {
|
|
2350
2368
|
inputTokens: response.usage.prompt_tokens,
|
|
2351
2369
|
outputTokens: response.usage.completion_tokens
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","names":["state: State","state","headers: Record<string, string>","errorJson: unknown","config","config: AzureOpenAIConfig","lastError: Error | undefined","lastResponse: Response | undefined","config","config","errorDetails: string","parsed: unknown","config","token","name","SYSTEM_REPLACEMENTS: Array<ReplacementRule>","userReplacements: Array<ReplacementRule>","rule: ReplacementRule","result","appliedRules: string[]","type","name","rule","version","process","commandBlock: string","lines: string[]","sanitized: Record<string, unknown>","path","tokenParts: string[]","state","x","headers: Record<string, string>","handleCompletion","response","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","chunks: Array<ChatCompletionChunk>","usage: UsageData | null","streamState: AnthropicStreamState","events","packageJson","packageJson"],"sources":["../package.json","../src/lib/paths.ts","../src/lib/state.ts","../src/lib/api-config.ts","../src/lib/error.ts","../src/services/github/get-copilot-token.ts","../src/services/github/get-device-code.ts","../src/services/github/get-user.ts","../src/services/azure-openai/config.ts","../src/lib/retry-fetch.ts","../src/services/azure-openai/create-chat-completions.ts","../src/services/azure-openai/get-models.ts","../src/services/copilot/get-models.ts","../src/services/get-vscode-version.ts","../src/lib/utils.ts","../src/services/github/poll-access-token.ts","../src/lib/token.ts","../src/auth.ts","../src/services/github/get-copilot-usage.ts","../src/check-usage.ts","../src/lib/auto-replace.ts","../src/config.ts","../src/debug.ts","../src/lib/proxy.ts","../src/lib/shell.ts","../src/lib/request-logger.ts","../src/lib/approval.ts","../src/lib/model-resolver.ts","../src/lib/rate-limit.ts","../src/lib/tokenizer.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/count-tokens-handler.ts","../src/routes/messages/stream-translation.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/routes/replacements/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["{\n \"name\": \"@ashsec/copilot-api\",\n \"version\": \"0.7.10\",\n \"description\": \"Turn GitHub Copilot into OpenAI/Anthropic API compatible server. Usable with Claude Code!\",\n \"keywords\": [\n \"proxy\",\n \"github-copilot\",\n \"openai-compatible\"\n ],\n \"homepage\": \"https://github.com/ericc-ch/copilot-api\",\n \"bugs\": \"https://github.com/ericc-ch/copilot-api/issues\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/ericc-ch/copilot-api.git\"\n },\n \"author\": \"Erick Christian <erickchristian48@gmail.com>\",\n \"type\": \"module\",\n \"bin\": {\n \"copilot-api\": \"./dist/main.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsdown\",\n \"dev\": \"bun run --watch ./src/main.ts\",\n \"knip\": \"knip-bun\",\n \"lint\": \"eslint --cache\",\n \"lint:all\": \"eslint --cache .\",\n \"prepack\": \"bun run build\",\n \"prepare\": \"simple-git-hooks\",\n \"release\": \"bumpp && bun publish --access public\",\n \"start\": \"NODE_ENV=production bun run ./src/main.ts\",\n \"typecheck\": \"tsc\"\n },\n \"simple-git-hooks\": {\n \"pre-commit\": \"bunx lint-staged\"\n },\n \"lint-staged\": {\n \"*\": \"bun run lint --fix\"\n },\n \"dependencies\": {\n \"citty\": \"^0.1.6\",\n \"clipboardy\": \"^5.0.0\",\n \"consola\": \"^3.4.2\",\n \"fetch-event-stream\": \"^0.1.5\",\n \"gpt-tokenizer\": \"^3.0.1\",\n \"hono\": \"^4.9.9\",\n \"proxy-from-env\": \"^1.1.0\",\n \"srvx\": \"^0.8.9\",\n \"tiny-invariant\": \"^1.3.3\",\n \"undici\": \"^7.16.0\",\n \"zod\": \"^4.1.11\"\n },\n \"devDependencies\": {\n \"@echristian/eslint-config\": \"^0.0.54\",\n \"@types/bun\": \"^1.2.23\",\n \"@types/proxy-from-env\": \"^1.0.4\",\n \"bumpp\": \"^10.2.3\",\n \"eslint\": \"^9.37.0\",\n \"knip\": \"^5.64.1\",\n \"lint-staged\": \"^16.2.3\",\n \"prettier-plugin-packagejson\": \"^2.5.19\",\n \"simple-git-hooks\": \"^2.13.1\",\n \"tsdown\": \"^0.15.6\",\n \"typescript\": \"^5.9.3\"\n }\n}\n","import fs from \"node:fs/promises\"\r\nimport os from \"node:os\"\r\nimport path from \"node:path\"\r\n\r\nconst APP_DIR = path.join(os.homedir(), \".local\", \"share\", \"copilot-api\")\r\n\r\nconst GITHUB_TOKEN_PATH = path.join(APP_DIR, \"github_token\")\r\nconst AZURE_OPENAI_CONFIG_PATH = path.join(APP_DIR, \"azure_openai_config\")\r\nconst REPLACEMENTS_CONFIG_PATH = path.join(APP_DIR, \"replacements.json\")\r\n\r\nexport const PATHS = {\r\n APP_DIR,\r\n GITHUB_TOKEN_PATH,\r\n AZURE_OPENAI_CONFIG_PATH,\r\n REPLACEMENTS_CONFIG_PATH,\r\n}\r\n\r\nexport async function ensurePaths(): Promise<void> {\r\n await fs.mkdir(PATHS.APP_DIR, { recursive: true })\r\n await ensureFile(PATHS.GITHUB_TOKEN_PATH)\r\n await ensureFile(PATHS.AZURE_OPENAI_CONFIG_PATH)\r\n}\r\n\r\nasync function ensureFile(filePath: string): Promise<void> {\r\n try {\r\n await fs.access(filePath, fs.constants.W_OK)\r\n } catch {\r\n await fs.writeFile(filePath, \"\")\r\n await fs.chmod(filePath, 0o600)\r\n }\r\n}\r\n","import type {\r\n AzureOpenAIConfig,\r\n AzureOpenAIDeploymentInfo,\r\n} from \"~/services/azure-openai/types\"\r\nimport type { ModelsResponse } from \"~/services/copilot/get-models\"\r\n\r\nexport interface State {\r\n githubToken?: string\r\n copilotToken?: string\r\n\r\n accountType: string\r\n models?: ModelsResponse\r\n vsCodeVersion?: string\r\n\r\n manualApprove: boolean\r\n rateLimitWait: boolean\r\n showToken: boolean\r\n debug: boolean\r\n\r\n // Rate limiting configuration\r\n rateLimitSeconds?: number\r\n lastRequestTimestamp?: number\r\n\r\n // Azure OpenAI configuration\r\n azureOpenAIConfig?: AzureOpenAIConfig\r\n azureOpenAIDeployments?: Array<AzureOpenAIDeploymentInfo>\r\n}\r\n\r\nexport const state: State = {\r\n accountType: \"individual\",\r\n manualApprove: false,\r\n rateLimitWait: false,\r\n showToken: false,\r\n debug: false,\r\n}\r\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.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\nconst API_VERSION = \"2025-04-01\"\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\": \"conversation-panel\",\n \"x-github-api-version\": API_VERSION,\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 requestPayload?: unknown\n\n constructor(message: string, response: Response, requestPayload?: unknown) {\n super(message)\n this.response = response\n this.requestPayload = requestPayload\n }\n}\n\ninterface ContentFilterError {\n error: {\n code: string\n innererror?: {\n code: string\n content_filter_result?: unknown\n }\n }\n}\n\nfunction isContentFilterError(obj: unknown): obj is ContentFilterError {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"error\" in obj &&\n typeof (obj as ContentFilterError).error === \"object\" &&\n (obj as ContentFilterError).error?.code === \"content_filter\"\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\n // Check for content filter error and log full details\n if (isContentFilterError(errorJson)) {\n consola.box(\"CONTENT FILTER TRIGGERED\")\n consola.error(\"Full error response:\")\n console.log(JSON.stringify(errorJson, null, 2))\n\n if (error.requestPayload) {\n consola.error(\"Request payload that triggered the filter:\")\n console.log(JSON.stringify(error.requestPayload, null, 2))\n }\n }\n\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 const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(state),\n },\n )\n\n if (!response.ok) throw new HTTPError(\"Failed to get Copilot token\", response)\n\n return (await response.json()) as GetCopilotTokenResponse\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\"\n\nexport async function getDeviceCode(): Promise<DeviceCodeResponse> {\n const response = await fetch(`${GITHUB_BASE_URL}/login/device/code`, {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n scope: GITHUB_APP_SCOPES,\n }),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get device code\", response)\n\n return (await response.json()) as DeviceCodeResponse\n}\n\nexport interface DeviceCodeResponse {\n device_code: string\n user_code: string\n verification_uri: string\n expires_in: number\n interval: number\n}\n","import { GITHUB_API_BASE_URL, standardHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport async function getGitHubUser() {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\n ...standardHeaders(),\n },\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get GitHub user\", response)\n\n return (await response.json()) as GithubUserResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GithubUserResponse {\n login: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\n\nimport type { AzureOpenAIConfig } from \"./types\"\n\nexport const AZURE_OPENAI_MODEL_PREFIX = \"azure_openai_\"\n\nexport async function loadAzureOpenAIConfig(): Promise<AzureOpenAIConfig | null> {\n try {\n const content = await fs.readFile(PATHS.AZURE_OPENAI_CONFIG_PATH, \"utf8\")\n if (!content.trim()) {\n return null\n }\n\n const decoded = Buffer.from(content.trim(), \"base64\").toString(\"utf8\")\n const config = JSON.parse(decoded) as AzureOpenAIConfig\n\n if (!config.endpoint || !config.apiKey) {\n return null\n }\n\n return config\n } catch {\n return null\n }\n}\n\nexport async function saveAzureOpenAIConfig(\n config: AzureOpenAIConfig,\n): Promise<void> {\n const encoded = Buffer.from(JSON.stringify(config)).toString(\"base64\")\n await fs.writeFile(PATHS.AZURE_OPENAI_CONFIG_PATH, encoded, \"utf8\")\n await fs.chmod(PATHS.AZURE_OPENAI_CONFIG_PATH, 0o600)\n consola.success(\"Azure OpenAI configuration saved\")\n}\n\nexport async function promptAzureOpenAISetup(): Promise<AzureOpenAIConfig | null> {\n const wantToAdd = await consola.prompt(\n \"Would you like to add a custom Azure OpenAI endpoint?\",\n {\n type: \"confirm\",\n initial: false,\n },\n )\n\n if (!wantToAdd) {\n return null\n }\n\n const endpoint = await consola.prompt(\n \"Enter your Azure OpenAI endpoint URL (e.g., https://your-resource.openai.azure.com):\",\n {\n type: \"text\",\n },\n )\n\n if (!endpoint || typeof endpoint !== \"string\" || !endpoint.trim()) {\n consola.warn(\"No endpoint provided, skipping Azure OpenAI setup\")\n return null\n }\n\n const apiKey = await consola.prompt(\"Enter your Azure OpenAI API key:\", {\n type: \"text\",\n })\n\n if (!apiKey || typeof apiKey !== \"string\" || !apiKey.trim()) {\n consola.warn(\"No API key provided, skipping Azure OpenAI setup\")\n return null\n }\n\n const config: AzureOpenAIConfig = {\n endpoint: endpoint.trim().replace(/\\/$/, \"\"), // Remove trailing slash\n apiKey: apiKey.trim(),\n }\n\n await saveAzureOpenAIConfig(config)\n return config\n}\n\nexport function isAzureOpenAIModel(modelId: string): boolean {\n return modelId.startsWith(AZURE_OPENAI_MODEL_PREFIX)\n}\n\nexport function getAzureDeploymentName(modelId: string): string {\n return modelId.slice(AZURE_OPENAI_MODEL_PREFIX.length)\n}\n","import consola from \"consola\"\r\n\r\nimport { sleep } from \"./utils\"\r\n\r\n// Fast retry: 100ms, 200ms, 300ms, then stop (max ~600ms total wait)\r\nconst RETRY_DELAYS_MS = [100, 200, 300]\r\n\r\n/**\r\n * Check if an error is retryable (transient network error)\r\n */\r\nfunction isRetryableError(error: unknown): boolean {\r\n if (!(error instanceof Error)) return false\r\n\r\n const message = error.message.toLowerCase()\r\n const causeMessage =\r\n error.cause instanceof Error ? error.cause.message.toLowerCase() : \"\"\r\n\r\n // Common transient error patterns\r\n const retryablePatterns = [\r\n \"fetch failed\",\r\n \"other side closed\",\r\n \"connection reset\",\r\n \"econnreset\",\r\n \"socket hang up\",\r\n \"socket connection was closed unexpectedly\",\r\n \"etimedout\",\r\n \"econnrefused\",\r\n \"network error\",\r\n \"aborted\",\r\n \"timeout\",\r\n ]\r\n\r\n return retryablePatterns.some(\r\n (pattern) => message.includes(pattern) || causeMessage.includes(pattern),\r\n )\r\n}\r\n\r\n/**\r\n * Check if an HTTP response status is retryable\r\n */\r\nfunction isRetryableStatus(status: number): boolean {\r\n // 4xx client errors (except 400, 401, 403, 404) and 5xx server errors\r\n // Retry: 408 Timeout, 429 Rate Limit, and all 5xx\r\n return status === 408 || status === 429 || (status >= 500 && status <= 599)\r\n}\r\n\r\n/**\r\n * Fetch with automatic fast retry on transient failures\r\n * Retries with delays: 100ms, 200ms, 300ms (max ~600ms total wait)\r\n */\r\nexport async function fetchWithRetry(\r\n input: string | URL | Request,\r\n init?: RequestInit,\r\n): Promise<Response> {\r\n const maxAttempts = RETRY_DELAYS_MS.length + 1 // 4 total attempts\r\n\r\n let lastError: Error | undefined\r\n let lastResponse: Response | undefined\r\n\r\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\r\n try {\r\n // Force a new connection by adding cache-busting and connection headers\r\n const headers = new Headers(init?.headers)\r\n\r\n // Ensure we're not reusing potentially stale connections\r\n headers.set(\"Connection\", \"close\")\r\n\r\n const response = await fetch(input, {\r\n ...init,\r\n headers,\r\n // Disable keep-alive to force fresh connections on each attempt\r\n keepalive: false,\r\n })\r\n\r\n // Check for retryable HTTP status codes\r\n if (isRetryableStatus(response.status) && attempt < maxAttempts - 1) {\r\n lastResponse = response\r\n const delayMs = RETRY_DELAYS_MS[attempt]\r\n consola.warn(\r\n `HTTP ${response.status} (attempt ${attempt + 1}/${maxAttempts}), retrying in ${delayMs}ms`,\r\n )\r\n await sleep(delayMs)\r\n continue\r\n }\r\n\r\n return response\r\n } catch (error) {\r\n lastError = error as Error\r\n\r\n if (!isRetryableError(error) || attempt === maxAttempts - 1) {\r\n throw error\r\n }\r\n\r\n const delayMs = RETRY_DELAYS_MS[attempt]\r\n consola.warn(\r\n `Fetch failed (attempt ${attempt + 1}/${maxAttempts}), retrying in ${delayMs}ms:`,\r\n lastError.message,\r\n )\r\n await sleep(delayMs)\r\n }\r\n }\r\n\r\n // If we exhausted retries due to HTTP status, return the last response\r\n if (lastResponse) {\r\n return lastResponse\r\n }\r\n\r\n throw lastError\r\n}\r\n","import consola from \"consola\"\r\nimport { events } from \"fetch-event-stream\"\r\n\r\nimport type {\r\n ChatCompletionResponse,\r\n ChatCompletionsPayload,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\n\r\nimport type { AzureOpenAIConfig } from \"./types\"\r\n\r\nimport { getAzureDeploymentName } from \"./config\"\r\n\r\nconst AZURE_API_VERSION = \"2024-10-21\"\r\n\r\nexport async function createAzureOpenAIChatCompletions(\r\n config: AzureOpenAIConfig,\r\n payload: ChatCompletionsPayload,\r\n) {\r\n // Extract the actual deployment name from the prefixed model ID\r\n const deploymentName = getAzureDeploymentName(payload.model)\r\n\r\n // Convert max_tokens to max_completion_tokens for newer models (GPT-4o, GPT-5, etc.)\r\n // Azure OpenAI newer models require max_completion_tokens instead of max_tokens\r\n const { max_tokens, ...restPayload } = payload\r\n const azurePayload = {\r\n ...restPayload,\r\n model: deploymentName,\r\n ...(max_tokens != null && { max_completion_tokens: max_tokens }),\r\n }\r\n\r\n const response = await fetchWithRetry(\r\n `${config.endpoint}/openai/deployments/${deploymentName}/chat/completions?api-version=${AZURE_API_VERSION}`,\r\n {\r\n method: \"POST\",\r\n headers: {\r\n \"api-key\": config.apiKey,\r\n \"Content-Type\": \"application/json\",\r\n },\r\n body: JSON.stringify(azurePayload),\r\n },\r\n )\r\n\r\n if (!response.ok) {\r\n consola.error(\"Failed to create Azure OpenAI chat completions:\", response)\r\n throw new HTTPError(\r\n \"Failed to create Azure OpenAI chat completions\",\r\n response,\r\n payload,\r\n )\r\n }\r\n\r\n if (payload.stream) {\r\n return events(response)\r\n }\r\n\r\n return (await response.json()) as ChatCompletionResponse\r\n}\r\n","import consola from \"consola\"\r\n\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\n\r\nimport type {\r\n AzureOpenAIConfig,\r\n AzureOpenAIDeploymentInfo,\r\n AzureOpenAIDeploymentsResponse,\r\n} from \"./types\"\r\n\r\nimport { AZURE_OPENAI_MODEL_PREFIX } from \"./config\"\r\n\r\n// Different API versions for different endpoints\r\nconst AZURE_DEPLOYMENTS_API_VERSION = \"2022-12-01\"\r\n\r\nexport async function getAzureOpenAIDeployments(\r\n config: AzureOpenAIConfig,\r\n): Promise<Array<AzureOpenAIDeploymentInfo>> {\r\n try {\r\n const response = await fetchWithRetry(\r\n `${config.endpoint}/openai/deployments?api-version=${AZURE_DEPLOYMENTS_API_VERSION}`,\r\n {\r\n headers: {\r\n \"api-key\": config.apiKey,\r\n \"Content-Type\": \"application/json\",\r\n },\r\n },\r\n )\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => \"\")\r\n consola.error(\r\n `Failed to fetch Azure OpenAI deployments: ${response.status}`,\r\n errorText,\r\n )\r\n throw new HTTPError(\"Failed to fetch Azure OpenAI deployments\", response)\r\n }\r\n\r\n const data = (await response.json()) as AzureOpenAIDeploymentsResponse\r\n\r\n // Only include deployments that are successfully deployed\r\n return data.data\r\n .filter((deployment) => deployment.status === \"succeeded\")\r\n .map((deployment) => ({\r\n id: `${AZURE_OPENAI_MODEL_PREFIX}${deployment.id}`,\r\n deploymentName: deployment.id,\r\n model: deployment.model,\r\n created: deployment.created_at,\r\n object: \"deployment\",\r\n owned_by: deployment.owner || \"azure-openai\",\r\n }))\r\n } catch (error) {\r\n if (error instanceof HTTPError) {\r\n throw error\r\n }\r\n consola.error(\"Failed to fetch Azure OpenAI deployments:\", error)\r\n return []\r\n }\r\n}\r\n","import consola from \"consola\"\r\n\r\nimport { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\nimport { state } from \"~/lib/state\"\r\n\r\nexport const getModels = async () => {\r\n const url = `${copilotBaseUrl(state)}/models`\r\n const response = await fetchWithRetry(url, {\r\n headers: copilotHeaders(state),\r\n })\r\n\r\n if (!response.ok) {\r\n const errorBody = await response.text()\r\n let errorDetails: string\r\n try {\r\n const parsed: unknown = JSON.parse(errorBody)\r\n errorDetails = JSON.stringify(parsed, null, 2)\r\n } catch {\r\n errorDetails = errorBody || \"(empty response)\"\r\n }\r\n consola.error(\r\n `Failed to get models from ${url}\\n`\r\n + `Status: ${response.status} ${response.statusText}\\n`\r\n + `Response: ${errorDetails}`,\r\n )\r\n throw new HTTPError(\r\n `Failed to get models: ${response.status} ${response.statusText}`,\r\n response,\r\n )\r\n }\r\n\r\n return (await response.json()) as ModelsResponse\r\n}\r\n\r\nexport interface ModelsResponse {\r\n data: Array<Model>\r\n object: string\r\n}\r\n\r\ninterface ModelLimits {\r\n max_context_window_tokens?: number\r\n max_output_tokens?: number\r\n max_prompt_tokens?: number\r\n max_inputs?: number\r\n}\r\n\r\ninterface ModelSupports {\r\n tool_calls?: boolean\r\n parallel_tool_calls?: boolean\r\n dimensions?: boolean\r\n}\r\n\r\ninterface ModelCapabilities {\r\n family: string\r\n limits: ModelLimits\r\n object: string\r\n supports: ModelSupports\r\n tokenizer: string\r\n type: string\r\n}\r\n\r\nexport interface Model {\r\n capabilities: ModelCapabilities\r\n id: string\r\n model_picker_enabled: boolean\r\n name: string\r\n object: string\r\n preview: boolean\r\n vendor: string\r\n version: string\r\n policy?: {\r\n state: string\r\n terms: string\r\n }\r\n}\r\n","const FALLBACK = \"1.104.3\"\n\nexport async function getVSCodeVersion() {\n const controller = new AbortController()\n const timeout = setTimeout(() => {\n controller.abort()\n }, 5000)\n\n try {\n const response = await fetch(\n \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=visual-studio-code-bin\",\n {\n signal: controller.signal,\n },\n )\n\n const pkgbuild = await response.text()\n const pkgverRegex = /pkgver=([0-9.]+)/\n const match = pkgbuild.match(pkgverRegex)\n\n if (match) {\n return match[1]\n }\n\n return FALLBACK\n } catch {\n return FALLBACK\n } finally {\n clearTimeout(timeout)\n }\n}\n\nawait getVSCodeVersion()\n","import consola from \"consola\"\r\n\r\nimport {\r\n getAzureOpenAIDeployments,\r\n loadAzureOpenAIConfig,\r\n promptAzureOpenAISetup,\r\n} from \"~/services/azure-openai\"\r\nimport { getModels } from \"~/services/copilot/get-models\"\r\nimport { getVSCodeVersion } from \"~/services/get-vscode-version\"\r\n\r\nimport { state } from \"./state\"\r\n\r\nexport const sleep = (ms: number) =>\r\n new Promise((resolve) => {\r\n setTimeout(resolve, ms)\r\n })\r\n\r\nexport const isNullish = (value: unknown): value is null | undefined =>\r\n value === null || value === undefined\r\n\r\nexport async function cacheModels(): Promise<void> {\r\n try {\r\n const models = await getModels()\r\n state.models = models\r\n } catch (error) {\r\n consola.error(\"Failed to fetch and cache models. This could be due to:\")\r\n consola.error(\" - Invalid or expired Copilot token\")\r\n consola.error(\" - Network connectivity issues\")\r\n consola.error(\" - GitHub Copilot service unavailable\")\r\n consola.error(\r\n \" - Account type mismatch (try --account-type=individual or --account-type=business)\",\r\n )\r\n throw error\r\n }\r\n}\r\n\r\nexport const cacheVSCodeVersion = async () => {\r\n const response = await getVSCodeVersion()\r\n state.vsCodeVersion = response\r\n\r\n consola.info(`Using VSCode version: ${response}`)\r\n}\r\n\r\nexport async function setupAzureOpenAI(): Promise<void> {\r\n // Try to load existing config\r\n let config = await loadAzureOpenAIConfig()\r\n\r\n // If no config exists, prompt user on first run\r\n if (!config) {\r\n config = await promptAzureOpenAISetup()\r\n }\r\n\r\n if (!config) {\r\n consola.info(\"Azure OpenAI not configured\")\r\n return\r\n }\r\n\r\n state.azureOpenAIConfig = config\r\n consola.info(\"Azure OpenAI configuration loaded\")\r\n\r\n // Fetch and cache Azure OpenAI deployments\r\n try {\r\n const deployments = await getAzureOpenAIDeployments(config)\r\n state.azureOpenAIDeployments = deployments\r\n if (deployments.length > 0) {\r\n consola.info(\r\n `Loaded ${deployments.length} Azure OpenAI deployment(s):\\n${deployments.map((d) => `- ${d.id} (${d.model})`).join(\"\\n\")}`,\r\n )\r\n } else {\r\n consola.warn(\"No Azure OpenAI deployments found\")\r\n }\r\n } catch (error) {\r\n consola.warn(\"Failed to fetch Azure OpenAI deployments:\", error)\r\n }\r\n}\r\n","import consola from \"consola\"\n\nimport {\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { sleep } from \"~/lib/utils\"\n\nimport type { DeviceCodeResponse } from \"./get-device-code\"\n\nexport async function pollAccessToken(\n deviceCode: DeviceCodeResponse,\n): Promise<string> {\n // Interval is in seconds, we need to multiply by 1000 to get milliseconds\n // I'm also adding another second, just to be safe\n const sleepDuration = (deviceCode.interval + 1) * 1000\n consola.debug(`Polling access token with interval of ${sleepDuration}ms`)\n\n while (true) {\n const response = await fetch(\n `${GITHUB_BASE_URL}/login/oauth/access_token`,\n {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n device_code: deviceCode.device_code,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n },\n )\n\n if (!response.ok) {\n 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 }\n}\n\ninterface AccessTokenResponse {\n access_token: string\n token_type: string\n scope: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\nimport { getCopilotToken } from \"~/services/github/get-copilot-token\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\nimport { getGitHubUser } from \"~/services/github/get-user\"\nimport { pollAccessToken } from \"~/services/github/poll-access-token\"\n\nimport { HTTPError } from \"./error\"\nimport { state } from \"./state\"\n\nconst readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n\nconst writeGithubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)\n\nexport const setupCopilotToken = async () => {\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n\n // Display the Copilot token to the screen\n consola.debug(\"GitHub Copilot Token fetched successfully!\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n const refreshInterval = (refresh_in - 60) * 1000\n setInterval(async () => {\n consola.debug(\"Refreshing Copilot token\")\n try {\n const { token } = await getCopilotToken()\n state.copilotToken = token\n consola.debug(\"Copilot token refreshed\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n throw error\n }\n }, refreshInterval)\n}\n\ninterface SetupGitHubTokenOptions {\n force?: boolean\n}\n\nexport async function setupGitHubToken(\n options?: SetupGitHubTokenOptions,\n): Promise<void> {\n try {\n const githubToken = await readGithubToken()\n\n if (githubToken && !options?.force) {\n state.githubToken = githubToken\n if (state.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n await logUser()\n\n return\n }\n\n consola.info(\"Not logged in, getting new access token\")\n const response = await getDeviceCode()\n consola.debug(\"Device code response:\", response)\n\n consola.info(\n `Please enter the code \"${response.user_code}\" in ${response.verification_uri}`,\n )\n\n const token = await pollAccessToken(response)\n await writeGithubToken(token)\n state.githubToken = token\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n await logUser()\n } catch (error) {\n if (error instanceof HTTPError) {\n consola.error(\"Failed to get GitHub token:\", await error.response.json())\n throw error\n }\n\n consola.error(\"Failed to get GitHub token:\", error)\n throw error\n }\n}\n\nasync function logUser() {\n const user = await getGitHubUser()\n consola.info(`Logged in as ${user.login}`)\n}\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { PATHS, ensurePaths } from \"./lib/paths\"\nimport { state } from \"./lib/state\"\nimport { setupGitHubToken } from \"./lib/token\"\n\ninterface RunAuthOptions {\n verbose: boolean\n showToken: boolean\n}\n\nexport async function runAuth(options: RunAuthOptions): Promise<void> {\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.showToken = options.showToken\n\n await ensurePaths()\n await setupGitHubToken({ force: true })\n consola.success(\"GitHub token written to\", PATHS.GITHUB_TOKEN_PATH)\n}\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run GitHub auth flow without running the server\",\n },\n args: {\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub token on auth\",\n },\n },\n run({ args }) {\n return runAuth({\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n","import { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotUsage = async (): Promise<CopilotUsageResponse> => {\n const response = await fetch(`${GITHUB_API_BASE_URL}/copilot_internal/user`, {\n headers: githubHeaders(state),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get Copilot usage\", response)\n }\n\n return (await response.json()) as CopilotUsageResponse\n}\n\nexport interface QuotaDetail {\n entitlement: number\n overage_count: number\n overage_permitted: boolean\n percent_remaining: number\n quota_id: string\n quota_remaining: number\n remaining: number\n unlimited: boolean\n}\n\ninterface QuotaSnapshots {\n chat: QuotaDetail\n completions: QuotaDetail\n premium_interactions: QuotaDetail\n}\n\ninterface CopilotUsageResponse {\n access_type_sku: string\n analytics_tracking_id: string\n assigned_date: string\n can_signup_for_limited: boolean\n chat_enabled: boolean\n copilot_plan: string\n organization_login_list: Array<unknown>\n organization_list: Array<unknown>\n quota_reset_date: string\n quota_snapshots: QuotaSnapshots\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { setupGitHubToken } from \"./lib/token\"\nimport {\n getCopilotUsage,\n type QuotaDetail,\n} from \"./services/github/get-copilot-usage\"\n\nexport const checkUsage = defineCommand({\n meta: {\n name: \"check-usage\",\n description: \"Show current GitHub Copilot usage/quota information\",\n },\n async run() {\n await ensurePaths()\n await setupGitHubToken()\n try {\n const usage = await getCopilotUsage()\n const premium = usage.quota_snapshots.premium_interactions\n const premiumTotal = premium.entitlement\n const premiumUsed = premiumTotal - premium.remaining\n const premiumPercentUsed =\n premiumTotal > 0 ? (premiumUsed / premiumTotal) * 100 : 0\n const premiumPercentRemaining = premium.percent_remaining\n\n // Helper to summarize a quota snapshot\n function summarizeQuota(name: string, snap: QuotaDetail | undefined) {\n if (!snap) return `${name}: N/A`\n const total = snap.entitlement\n const used = total - snap.remaining\n const percentUsed = total > 0 ? (used / total) * 100 : 0\n const percentRemaining = snap.percent_remaining\n return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`\n }\n\n const premiumLine = `Premium: ${premiumUsed}/${premiumTotal} used (${premiumPercentUsed.toFixed(1)}% used, ${premiumPercentRemaining.toFixed(1)}% remaining)`\n const chatLine = summarizeQuota(\"Chat\", usage.quota_snapshots.chat)\n const completionsLine = summarizeQuota(\n \"Completions\",\n usage.quota_snapshots.completions,\n )\n\n consola.box(\n `Copilot Usage (plan: ${usage.copilot_plan})\\n`\n + `Quota resets: ${usage.quota_reset_date}\\n`\n + `\\nQuotas:\\n`\n + ` ${premiumLine}\\n`\n + ` ${chatLine}\\n`\n + ` ${completionsLine}`,\n )\n } catch (err) {\n consola.error(\"Failed to fetch Copilot usage:\", err)\n process.exit(1)\n }\n },\n})\n","import consola from \"consola\"\r\nimport fs from \"node:fs/promises\"\r\n\r\nimport type { ChatCompletionsPayload } from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport { PATHS } from \"./paths\"\r\n\r\nexport interface ReplacementRule {\r\n id: string\r\n name?: string // Human-readable name/description\r\n pattern: string\r\n replacement: string\r\n isRegex: boolean\r\n enabled: boolean\r\n isSystem?: boolean // System rules cannot be deleted by user\r\n}\r\n\r\n// Built-in system replacement that cannot be removed\r\nconst SYSTEM_REPLACEMENTS: Array<ReplacementRule> = [\r\n {\r\n id: \"system-anthropic-billing\",\r\n name: \"Remove Anthropic billing header\",\r\n pattern: \"x-anthropic-billing-header:[^\\\\n]*\\\\n?\",\r\n replacement: \"\",\r\n isRegex: true,\r\n enabled: true,\r\n isSystem: true,\r\n },\r\n]\r\n\r\n// User-configured replacements (loaded from disk)\r\nlet userReplacements: Array<ReplacementRule> = []\r\nlet isLoaded = false\r\n\r\n/**\r\n * Load user replacements from disk\r\n */\r\nexport async function loadReplacements(): Promise<void> {\r\n try {\r\n const data = await fs.readFile(PATHS.REPLACEMENTS_CONFIG_PATH)\r\n const parsed = JSON.parse(data.toString()) as Array<ReplacementRule>\r\n userReplacements = parsed.filter((r) => !r.isSystem)\r\n isLoaded = true\r\n consola.debug(`Loaded ${userReplacements.length} user replacement rules`)\r\n } catch {\r\n // File doesn't exist or is invalid - start with empty array\r\n userReplacements = []\r\n isLoaded = true\r\n }\r\n}\r\n\r\n/**\r\n * Save user replacements to disk\r\n */\r\nexport async function saveReplacements(): Promise<void> {\r\n try {\r\n await fs.writeFile(\r\n PATHS.REPLACEMENTS_CONFIG_PATH,\r\n JSON.stringify(userReplacements, null, 2),\r\n \"utf8\",\r\n )\r\n consola.debug(`Saved ${userReplacements.length} user replacement rules`)\r\n } catch (error) {\r\n consola.error(\"Failed to save replacement rules:\", error)\r\n throw error\r\n }\r\n}\r\n\r\n/**\r\n * Ensure replacements are loaded before accessing\r\n */\r\nexport async function ensureLoaded(): Promise<void> {\r\n if (!isLoaded) {\r\n await loadReplacements()\r\n }\r\n}\r\n\r\n/**\r\n * Get all replacement rules (system + user)\r\n */\r\nexport async function getAllReplacements(): Promise<Array<ReplacementRule>> {\r\n await ensureLoaded()\r\n return [...SYSTEM_REPLACEMENTS, ...userReplacements]\r\n}\r\n\r\n/**\r\n * Get only user-configurable replacements\r\n */\r\nexport async function getUserReplacements(): Promise<Array<ReplacementRule>> {\r\n await ensureLoaded()\r\n return userReplacements\r\n}\r\n\r\n/**\r\n * Add a new user replacement rule\r\n */\r\nexport async function addReplacement(\r\n pattern: string,\r\n replacement: string,\r\n isRegex = false,\r\n name?: string,\r\n): Promise<ReplacementRule> {\r\n await ensureLoaded()\r\n const rule: ReplacementRule = {\r\n id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,\r\n name,\r\n pattern,\r\n replacement,\r\n isRegex,\r\n enabled: true,\r\n isSystem: false,\r\n }\r\n userReplacements.push(rule)\r\n await saveReplacements()\r\n consola.info(`Added replacement rule: \"${pattern}\" -> \"${replacement}\"`)\r\n return rule\r\n}\r\n\r\n/**\r\n * Remove a user replacement rule by ID\r\n */\r\nexport async function removeReplacement(id: string): Promise<boolean> {\r\n await ensureLoaded()\r\n const rule = userReplacements.find((r) => r.id === id)\r\n if (!rule) {\r\n return false\r\n }\r\n if (rule.isSystem) {\r\n consola.warn(\"Cannot remove system replacement rule\")\r\n return false\r\n }\r\n userReplacements = userReplacements.filter((r) => r.id !== id)\r\n await saveReplacements()\r\n consola.info(`Removed replacement rule: ${id}`)\r\n return true\r\n}\r\n\r\n/**\r\n * Update an existing user replacement rule\r\n */\r\nexport async function updateReplacement(\r\n id: string,\r\n updates: {\r\n name?: string\r\n pattern?: string\r\n replacement?: string\r\n isRegex?: boolean\r\n enabled?: boolean\r\n },\r\n): Promise<ReplacementRule | null> {\r\n await ensureLoaded()\r\n\r\n const rule = userReplacements.find((r) => r.id === id)\r\n if (!rule) {\r\n return null\r\n }\r\n\r\n if (rule.isSystem) {\r\n consola.warn(\"Cannot update system replacement rule\")\r\n return null\r\n }\r\n\r\n if (updates.name !== undefined) rule.name = updates.name\r\n if (updates.pattern !== undefined) rule.pattern = updates.pattern\r\n if (updates.replacement !== undefined) rule.replacement = updates.replacement\r\n if (updates.isRegex !== undefined) rule.isRegex = updates.isRegex\r\n if (updates.enabled !== undefined) rule.enabled = updates.enabled\r\n\r\n await saveReplacements()\r\n consola.info(`Updated replacement rule: ${rule.name || rule.id}`)\r\n return rule\r\n}\r\n\r\n/**\r\n * Toggle a replacement rule on/off\r\n */\r\nexport async function toggleReplacement(\r\n id: string,\r\n): Promise<ReplacementRule | null> {\r\n await ensureLoaded()\r\n // Check user replacements first\r\n const userRule = userReplacements.find((r) => r.id === id)\r\n if (userRule) {\r\n userRule.enabled = !userRule.enabled\r\n await saveReplacements()\r\n consola.info(\r\n `Toggled replacement rule ${id}: ${userRule.enabled ? \"enabled\" : \"disabled\"}`,\r\n )\r\n return userRule\r\n }\r\n\r\n // System rules cannot be toggled\r\n const systemRule = SYSTEM_REPLACEMENTS.find((r) => r.id === id)\r\n if (systemRule) {\r\n consola.warn(\"Cannot toggle system replacement rule\")\r\n return null\r\n }\r\n\r\n return null\r\n}\r\n\r\n/**\r\n * Clear all user replacements\r\n */\r\nexport async function clearUserReplacements(): Promise<void> {\r\n userReplacements = []\r\n await saveReplacements()\r\n consola.info(\"Cleared all user replacement rules\")\r\n}\r\n\r\n/**\r\n * Apply a single replacement rule to text and return info about whether it matched\r\n */\r\nfunction applyRule(\r\n text: string,\r\n rule: ReplacementRule,\r\n): { result: string; matched: boolean } {\r\n if (!rule.enabled) return { result: text, matched: false }\r\n\r\n if (rule.isRegex) {\r\n try {\r\n const regex = new RegExp(rule.pattern, \"g\")\r\n const result = text.replace(regex, rule.replacement)\r\n return { result, matched: result !== text }\r\n } catch {\r\n consola.warn(`Invalid regex pattern in rule ${rule.id}: ${rule.pattern}`)\r\n return { result: text, matched: false }\r\n }\r\n }\r\n\r\n const result = text.split(rule.pattern).join(rule.replacement)\r\n return { result, matched: result !== text }\r\n}\r\n\r\n/**\r\n * Apply all replacement rules to text\r\n */\r\nexport async function applyReplacements(text: string): Promise<string> {\r\n let result = text\r\n const allRules = await getAllReplacements()\r\n const appliedRules: string[] = []\r\n\r\n for (const rule of allRules) {\r\n const { result: newResult, matched } = applyRule(result, rule)\r\n if (matched) {\r\n result = newResult\r\n appliedRules.push(rule.name || rule.id)\r\n }\r\n }\r\n\r\n if (appliedRules.length > 0) {\r\n consola.info(`Replacements applied: ${appliedRules.join(\", \")}`)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Apply replacements to a chat completions payload\r\n * This modifies message content in place\r\n */\r\nexport async function applyReplacementsToPayload(\r\n payload: ChatCompletionsPayload,\r\n): Promise<ChatCompletionsPayload> {\r\n const processedMessages = await Promise.all(\r\n payload.messages.map(async (message) => {\r\n if (typeof message.content === \"string\") {\r\n return {\r\n ...message,\r\n content: await applyReplacements(message.content),\r\n }\r\n }\r\n\r\n // Handle array content (multimodal)\r\n if (Array.isArray(message.content)) {\r\n return {\r\n ...message,\r\n content: await Promise.all(\r\n message.content.map(async (part) => {\r\n if (\r\n typeof part === \"object\"\r\n && part.type === \"text\"\r\n && part.text\r\n ) {\r\n return {\r\n ...part,\r\n text: await applyReplacements(part.text),\r\n }\r\n }\r\n return part\r\n }),\r\n ),\r\n }\r\n }\r\n\r\n return message\r\n }),\r\n )\r\n\r\n return {\r\n ...payload,\r\n messages: processedMessages,\r\n }\r\n}\r\n","import { defineCommand } from \"citty\"\r\nimport consola from \"consola\"\r\n\r\nimport {\r\n addReplacement,\r\n applyReplacements,\r\n clearUserReplacements,\r\n getAllReplacements,\r\n getUserReplacements,\r\n removeReplacement,\r\n toggleReplacement,\r\n updateReplacement,\r\n type ReplacementRule,\r\n} from \"~/lib/auto-replace\"\r\nimport { ensurePaths, PATHS } from \"~/lib/paths\"\r\n\r\ntype MenuAction =\r\n | \"list\"\r\n | \"add\"\r\n | \"edit\"\r\n | \"remove\"\r\n | \"toggle\"\r\n | \"test\"\r\n | \"clear\"\r\n | \"exit\"\r\n\r\nfunction formatRule(rule: ReplacementRule, index: number): string {\r\n const status = rule.enabled ? \"✓\" : \"✗\"\r\n const type = rule.isRegex ? \"regex\" : \"string\"\r\n const system = rule.isSystem ? \" [system]\" : \"\"\r\n const name = rule.name ? ` \"${rule.name}\"` : \"\"\r\n const replacement = rule.replacement || \"(empty)\"\r\n return `${index + 1}. [${status}] (${type})${system}${name} \"${rule.pattern}\" → \"${replacement}\"`\r\n}\r\n\r\nasync function listReplacements(): Promise<void> {\r\n const all = await getAllReplacements()\r\n\r\n if (all.length === 0) {\r\n consola.info(\"No replacement rules configured.\")\r\n return\r\n }\r\n\r\n consola.info(\"\\n📋 Replacement Rules:\\n\")\r\n for (const [i, element] of all.entries()) {\r\n console.log(formatRule(element, i))\r\n }\r\n console.log()\r\n}\r\n\r\nasync function addNewReplacement(): Promise<void> {\r\n const name = await consola.prompt(\"Name (optional, short description):\", {\r\n type: \"text\",\r\n default: \"\",\r\n })\r\n\r\n if (typeof name === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const matchType = await consola.prompt(\"Match type:\", {\r\n type: \"select\",\r\n options: [\r\n { label: \"String (exact match)\", value: \"string\" },\r\n { label: \"Regex (regular expression)\", value: \"regex\" },\r\n ],\r\n })\r\n\r\n if (typeof matchType === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const pattern = await consola.prompt(\"Pattern to match:\", {\r\n type: \"text\",\r\n })\r\n\r\n if (typeof pattern === \"symbol\" || !pattern) {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n // Validate regex if needed\r\n if (matchType === \"regex\") {\r\n try {\r\n new RegExp(pattern)\r\n } catch {\r\n consola.error(`Invalid regex pattern: ${pattern}`)\r\n return\r\n }\r\n }\r\n\r\n const replacement = await consola.prompt(\r\n \"Replacement text (leave empty to delete matches):\",\r\n {\r\n type: \"text\",\r\n default: \"\",\r\n },\r\n )\r\n\r\n if (typeof replacement === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const rule = await addReplacement(\r\n pattern,\r\n replacement,\r\n matchType === \"regex\",\r\n name || undefined,\r\n )\r\n\r\n consola.success(`Added rule: ${rule.name || rule.id}`)\r\n}\r\n\r\nasync function editExistingReplacement(): Promise<void> {\r\n const userRules = await getUserReplacements()\r\n\r\n if (userRules.length === 0) {\r\n consola.info(\"No user rules to edit.\")\r\n return\r\n }\r\n\r\n const options = userRules.map((rule, i) => ({\r\n label: formatRule(rule, i),\r\n value: rule.id,\r\n }))\r\n\r\n const selected = await consola.prompt(\"Select rule to edit:\", {\r\n type: \"select\",\r\n options,\r\n })\r\n\r\n if (typeof selected === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const rule = userRules.find((r) => r.id === selected)\r\n if (!rule) {\r\n consola.error(\"Rule not found.\")\r\n return\r\n }\r\n\r\n consola.info(`\\nEditing rule: ${rule.name || rule.id}`)\r\n consola.info(\"Press Enter to keep current value.\\n\")\r\n\r\n const name = await consola.prompt(\"Name:\", {\r\n type: \"text\",\r\n default: rule.name || \"\",\r\n })\r\n\r\n if (typeof name === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const matchType = await consola.prompt(\"Match type:\", {\r\n type: \"select\",\r\n options: [\r\n { label: \"String (exact match)\", value: \"string\" },\r\n { label: \"Regex (regular expression)\", value: \"regex\" },\r\n ],\r\n initial: rule.isRegex ? \"regex\" : \"string\",\r\n })\r\n\r\n if (typeof matchType === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const pattern = await consola.prompt(\"Pattern to match:\", {\r\n type: \"text\",\r\n default: rule.pattern,\r\n })\r\n\r\n if (typeof pattern === \"symbol\" || !pattern) {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n // Validate regex if needed\r\n if (matchType === \"regex\") {\r\n try {\r\n new RegExp(pattern)\r\n } catch {\r\n consola.error(`Invalid regex pattern: ${pattern}`)\r\n return\r\n }\r\n }\r\n\r\n const replacement = await consola.prompt(\"Replacement text:\", {\r\n type: \"text\",\r\n default: rule.replacement,\r\n })\r\n\r\n if (typeof replacement === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const updated = await updateReplacement(selected, {\r\n name: name || undefined,\r\n pattern,\r\n replacement,\r\n isRegex: matchType === \"regex\",\r\n })\r\n\r\n if (updated) {\r\n consola.success(`Updated rule: ${updated.name || updated.id}`)\r\n } else {\r\n consola.error(\"Failed to update rule.\")\r\n }\r\n}\r\n\r\nasync function removeExistingReplacement(): Promise<void> {\r\n const userRules = await getUserReplacements()\r\n\r\n if (userRules.length === 0) {\r\n consola.info(\"No user rules to remove.\")\r\n return\r\n }\r\n\r\n const options = userRules.map((rule, i) => ({\r\n label: formatRule(rule, i),\r\n value: rule.id,\r\n }))\r\n\r\n const selected = await consola.prompt(\"Select rule to remove:\", {\r\n type: \"select\",\r\n options,\r\n })\r\n\r\n if (typeof selected === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const success = await removeReplacement(selected)\r\n if (success) {\r\n consola.success(\"Rule removed.\")\r\n } else {\r\n consola.error(\"Failed to remove rule.\")\r\n }\r\n}\r\n\r\nasync function toggleExistingReplacement(): Promise<void> {\r\n const userRules = await getUserReplacements()\r\n\r\n if (userRules.length === 0) {\r\n consola.info(\"No user rules to toggle.\")\r\n return\r\n }\r\n\r\n const options = userRules.map((rule, i) => ({\r\n label: formatRule(rule, i),\r\n value: rule.id,\r\n }))\r\n\r\n const selected = await consola.prompt(\"Select rule to toggle:\", {\r\n type: \"select\",\r\n options,\r\n })\r\n\r\n if (typeof selected === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const rule = await toggleReplacement(selected)\r\n if (rule) {\r\n consola.success(`Rule ${rule.enabled ? \"enabled\" : \"disabled\"}.`)\r\n } else {\r\n consola.error(\"Failed to toggle rule.\")\r\n }\r\n}\r\n\r\nasync function testReplacements(): Promise<void> {\r\n const testText = await consola.prompt(\"Enter text to test replacements:\", {\r\n type: \"text\",\r\n })\r\n\r\n if (typeof testText === \"symbol\" || !testText) {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const result = await applyReplacements(testText)\r\n\r\n consola.info(\"\\n📝 Original:\")\r\n console.log(testText)\r\n consola.info(\"\\n✨ After replacements:\")\r\n console.log(result)\r\n console.log()\r\n}\r\n\r\nasync function clearAllReplacements(): Promise<void> {\r\n const confirm = await consola.prompt(\r\n \"Are you sure you want to clear all user replacements?\",\r\n {\r\n type: \"confirm\",\r\n initial: false,\r\n },\r\n )\r\n\r\n if (confirm) {\r\n await clearUserReplacements()\r\n consola.success(\"All user replacements cleared.\")\r\n } else {\r\n consola.info(\"Cancelled.\")\r\n }\r\n}\r\n\r\nasync function mainMenu(): Promise<void> {\r\n consola.info(`\\n🔧 Copilot API - Replacement Configuration`)\r\n consola.info(`Config file: ${PATHS.REPLACEMENTS_CONFIG_PATH}\\n`)\r\n\r\n let running = true\r\n\r\n while (running) {\r\n const action = await consola.prompt(\"What would you like to do?\", {\r\n type: \"select\",\r\n options: [\r\n { label: \"📋 List all rules\", value: \"list\" as MenuAction },\r\n { label: \"➕ Add new rule\", value: \"add\" as MenuAction },\r\n { label: \"✏️ Edit rule\", value: \"edit\" as MenuAction },\r\n { label: \"➖ Remove rule\", value: \"remove\" as MenuAction },\r\n { label: \"🔄 Toggle rule on/off\", value: \"toggle\" as MenuAction },\r\n { label: \"🧪 Test replacements\", value: \"test\" as MenuAction },\r\n { label: \"🗑️ Clear all user rules\", value: \"clear\" as MenuAction },\r\n { label: \"🚪 Exit\", value: \"exit\" as MenuAction },\r\n ],\r\n })\r\n\r\n if (typeof action === \"symbol\") {\r\n break\r\n }\r\n\r\n switch (action) {\r\n case \"list\": {\r\n await listReplacements()\r\n break\r\n }\r\n case \"add\": {\r\n await addNewReplacement()\r\n break\r\n }\r\n case \"edit\": {\r\n await editExistingReplacement()\r\n break\r\n }\r\n case \"remove\": {\r\n await removeExistingReplacement()\r\n break\r\n }\r\n case \"toggle\": {\r\n await toggleExistingReplacement()\r\n break\r\n }\r\n case \"test\": {\r\n await testReplacements()\r\n break\r\n }\r\n case \"clear\": {\r\n await clearAllReplacements()\r\n break\r\n }\r\n case \"exit\": {\r\n running = false\r\n break\r\n }\r\n default: {\r\n break\r\n }\r\n }\r\n }\r\n\r\n consola.info(\"Goodbye! 👋\")\r\n}\r\n\r\nexport const config = defineCommand({\r\n meta: {\r\n name: \"config\",\r\n description: \"Configure replacement rules interactively\",\r\n },\r\n run: async () => {\r\n await ensurePaths()\r\n await mainMenu()\r\n },\r\n})\r\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\nimport fs from \"node:fs/promises\"\nimport os from \"node:os\"\n\nimport { PATHS } from \"./lib/paths\"\n\ninterface DebugInfo {\n version: string\n runtime: {\n name: string\n version: string\n platform: string\n arch: string\n }\n paths: {\n APP_DIR: string\n GITHUB_TOKEN_PATH: string\n }\n tokenExists: boolean\n}\n\ninterface RunDebugOptions {\n json: boolean\n}\n\nasync function getPackageVersion(): Promise<string> {\n try {\n const packageJsonPath = new URL(\"../package.json\", import.meta.url).pathname\n // @ts-expect-error https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v59.0.1/docs/rules/prefer-json-parse-buffer.md\n // JSON.parse() can actually parse buffers\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath)) as {\n version: string\n }\n return packageJson.version\n } catch {\n return \"unknown\"\n }\n}\n\nfunction getRuntimeInfo() {\n const isBun = typeof Bun !== \"undefined\"\n\n return {\n name: isBun ? \"bun\" : \"node\",\n version: isBun ? Bun.version : process.version.slice(1),\n platform: os.platform(),\n arch: os.arch(),\n }\n}\n\nasync function checkTokenExists(): Promise<boolean> {\n try {\n const stats = await fs.stat(PATHS.GITHUB_TOKEN_PATH)\n if (!stats.isFile()) return false\n\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim().length > 0\n } catch {\n return false\n }\n}\n\nasync function getDebugInfo(): Promise<DebugInfo> {\n const [version, tokenExists] = await Promise.all([\n getPackageVersion(),\n checkTokenExists(),\n ])\n\n return {\n version,\n runtime: getRuntimeInfo(),\n paths: {\n APP_DIR: PATHS.APP_DIR,\n GITHUB_TOKEN_PATH: PATHS.GITHUB_TOKEN_PATH,\n },\n tokenExists,\n }\n}\n\nfunction printDebugInfoPlain(info: DebugInfo): void {\n consola.info(`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 consola from \"consola\"\nimport { getProxyForUrl } from \"proxy-from-env\"\nimport { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from \"undici\"\n\nexport function initProxyFromEnv(): void {\n if (typeof Bun !== \"undefined\") return\n\n try {\n const direct = new Agent()\n const proxies = new Map<string, ProxyAgent>()\n\n // We only need a minimal dispatcher that implements `dispatch` at runtime.\n // Typing the object as `Dispatcher` forces TypeScript to require many\n // additional methods. Instead, keep a plain object and cast when passing\n // to `setGlobalDispatcher`.\n const dispatcher = {\n dispatch(\n options: Dispatcher.DispatchOptions,\n handler: Dispatcher.DispatchHandler,\n ) {\n try {\n const origin =\n typeof options.origin === \"string\" ?\n new URL(options.origin)\n : (options.origin as URL)\n const get = getProxyForUrl as unknown as (\n u: string,\n ) => string | undefined\n const raw = get(origin.toString())\n const proxyUrl = raw && raw.length > 0 ? raw : undefined\n if (!proxyUrl) {\n consola.debug(`HTTP proxy bypass: ${origin.hostname}`)\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n let agent = proxies.get(proxyUrl)\n if (!agent) {\n agent = new ProxyAgent(proxyUrl)\n proxies.set(proxyUrl, agent)\n }\n let label = proxyUrl\n try {\n const u = new URL(proxyUrl)\n label = `${u.protocol}//${u.host}`\n } catch {\n /* noop */\n }\n consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`)\n return (agent as unknown as Dispatcher).dispatch(options, handler)\n } catch {\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n },\n close() {\n return direct.close()\n },\n destroy() {\n return direct.destroy()\n },\n }\n\n setGlobalDispatcher(dispatcher as unknown as Dispatcher)\n consola.debug(\"HTTP proxy configured from environment (per-URL)\")\n } catch (err) {\n consola.debug(\"Proxy setup skipped:\", err)\n }\n}\n","import { 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\"\r\n\r\nimport { state } from \"./state\"\r\n\r\n/**\r\n * Request context stored for logging on response\r\n */\r\nexport interface RequestContext {\r\n startTime: number\r\n model?: string\r\n inputTokens?: number\r\n outputTokens?: number\r\n provider?: \"Copilot\" | \"Azure OpenAI\"\r\n}\r\n\r\nconst REQUEST_CONTEXT_KEY = \"requestContext\"\r\n\r\n// ANSI color codes\r\nconst colors = {\r\n reset: \"\\x1b[0m\",\r\n dim: \"\\x1b[2m\",\r\n bold: \"\\x1b[1m\",\r\n cyan: \"\\x1b[36m\",\r\n green: \"\\x1b[32m\",\r\n yellow: \"\\x1b[33m\",\r\n red: \"\\x1b[31m\",\r\n magenta: \"\\x1b[35m\",\r\n blue: \"\\x1b[34m\",\r\n white: \"\\x1b[37m\",\r\n gray: \"\\x1b[90m\",\r\n}\r\n\r\n/**\r\n * Get the current time formatted as HH:MM:SS\r\n */\r\nfunction getTimeString(): string {\r\n return new Date().toLocaleTimeString(\"en-US\", {\r\n hour12: false,\r\n hour: \"2-digit\",\r\n minute: \"2-digit\",\r\n second: \"2-digit\",\r\n })\r\n}\r\n\r\n/**\r\n * Get status color based on HTTP status code\r\n */\r\nfunction getStatusColor(status: number): string {\r\n if (status >= 500) return colors.red\r\n if (status >= 400) return colors.yellow\r\n if (status >= 300) return colors.cyan\r\n return colors.green\r\n}\r\n\r\n/**\r\n * Log raw HTTP request details (for debug mode)\r\n */\r\nasync function logRawRequest(c: Context): Promise<void> {\r\n const method = c.req.method\r\n const url = c.req.url\r\n const headers = Object.fromEntries(c.req.raw.headers.entries())\r\n\r\n const lines: string[] = []\r\n lines.push(`${colors.magenta}${colors.bold}[DEBUG] Incoming Request${colors.reset}`)\r\n lines.push(`${colors.cyan}${method}${colors.reset} ${url}`)\r\n lines.push(`${colors.dim}Headers:${colors.reset}`)\r\n\r\n for (const [key, value] of Object.entries(headers)) {\r\n // Mask authorization headers\r\n const displayValue = key.toLowerCase().includes(\"authorization\")\r\n ? `${value.slice(0, 20)}...`\r\n : value\r\n lines.push(` ${colors.gray}${key}:${colors.reset} ${displayValue}`)\r\n }\r\n\r\n // Try to get body info without consuming it\r\n if (method !== \"GET\" && method !== \"HEAD\") {\r\n try {\r\n const clonedRequest = c.req.raw.clone()\r\n const body = await clonedRequest.text()\r\n if (body) {\r\n // Parse JSON to extract model, omit messages/prompt\r\n try {\r\n const parsed = JSON.parse(body)\r\n const sanitized: Record<string, unknown> = {}\r\n\r\n for (const [key, value] of Object.entries(parsed)) {\r\n if (key === \"messages\" || key === \"prompt\") {\r\n sanitized[key] = `[${Array.isArray(value) ? value.length : 1} items omitted]`\r\n } else {\r\n sanitized[key] = value\r\n }\r\n }\r\n\r\n lines.push(`${colors.dim}Body (sanitized):${colors.reset}`)\r\n lines.push(` ${JSON.stringify(sanitized, null, 2).split(\"\\n\").join(\"\\n \")}`)\r\n } catch {\r\n // Not JSON, show length\r\n lines.push(`${colors.dim}Body:${colors.reset} [${body.length} bytes]`)\r\n }\r\n }\r\n } catch {\r\n lines.push(`${colors.dim}Body:${colors.reset} [unable to read]`)\r\n }\r\n }\r\n\r\n lines.push(`${colors.dim}${\"─\".repeat(60)}${colors.reset}`)\r\n console.log(lines.join(\"\\n\"))\r\n}\r\n\r\n/**\r\n * Set request context for logging\r\n */\r\nexport function setRequestContext(\r\n c: Context,\r\n ctx: Partial<Omit<RequestContext, \"startTime\">>,\r\n): void {\r\n const existing = c.get(REQUEST_CONTEXT_KEY) as RequestContext | undefined\r\n if (existing) {\r\n c.set(REQUEST_CONTEXT_KEY, { ...existing, ...ctx })\r\n }\r\n}\r\n\r\n/**\r\n * Custom request logger middleware\r\n */\r\nexport async function requestLogger(c: Context, next: Next): Promise<void> {\r\n // Log raw request in debug mode\r\n if (state.debug) {\r\n await logRawRequest(c)\r\n }\r\n\r\n const startTime = Date.now()\r\n const method = c.req.method\r\n const path =\r\n c.req.path +\r\n (c.req.raw.url.includes(\"?\") ? \"?\" + c.req.raw.url.split(\"?\")[1] : \"\")\r\n\r\n // Initialize request context\r\n c.set(REQUEST_CONTEXT_KEY, { startTime } as RequestContext)\r\n\r\n await next()\r\n\r\n // Get context that may have been set during request handling\r\n const ctx = c.get(REQUEST_CONTEXT_KEY) as RequestContext | undefined\r\n const duration = ((Date.now() - startTime) / 1000).toFixed(1)\r\n const status = c.res.status\r\n const statusColor = getStatusColor(status)\r\n\r\n // Build the log block\r\n const lines: string[] = []\r\n\r\n // Separator\r\n lines.push(`${colors.dim}${\"─\".repeat(60)}${colors.reset}`)\r\n\r\n // Main request line: method, path, status, duration\r\n const statusBadge = `${statusColor}${status}${colors.reset}`\r\n const durationStr = `${colors.cyan}${duration}s${colors.reset}`\r\n lines.push(\r\n `${colors.bold}${method}${colors.reset} ${path} ${statusBadge} ${durationStr}`,\r\n )\r\n\r\n // Provider and model info\r\n if (ctx?.provider && ctx?.model) {\r\n const providerColor =\r\n ctx.provider === \"Azure OpenAI\" ? colors.blue : colors.magenta\r\n lines.push(\r\n ` ${colors.gray}Provider:${colors.reset} ${providerColor}${ctx.provider}${colors.reset} ${colors.gray}->${colors.reset} ${colors.white}${ctx.model}${colors.reset}`,\r\n )\r\n }\r\n\r\n // Token info\r\n if (ctx?.inputTokens !== undefined || ctx?.outputTokens !== undefined) {\r\n const tokenParts: string[] = []\r\n if (ctx.inputTokens !== undefined) {\r\n tokenParts.push(\r\n `${colors.gray}Input:${colors.reset} ${colors.yellow}${ctx.inputTokens.toLocaleString()}${colors.reset}`,\r\n )\r\n }\r\n if (ctx.outputTokens !== undefined) {\r\n tokenParts.push(\r\n `${colors.gray}Output:${colors.reset} ${colors.green}${ctx.outputTokens.toLocaleString()}${colors.reset}`,\r\n )\r\n }\r\n lines.push(` ${tokenParts.join(\" \")}`)\r\n }\r\n\r\n // Timestamp\r\n lines.push(` ${colors.dim}${getTimeString()}${colors.reset}`)\r\n\r\n // Print all lines\r\n console.log(lines.join(\"\\n\"))\r\n}\r\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","/**\r\n * Normalize a model name by converting dashes to dots between numbers.\r\n * e.g., \"claude-opus-4-5\" -> \"claude-opus-4.5\"\r\n * \"gpt-4-1\" -> \"gpt-4.1\"\r\n * \"gpt-5-1-codex\" -> \"gpt-5.1-codex\"\r\n */\r\nexport function normalizeModelName(model: string): string {\r\n // Replace dash with dot only between two digits: \"4-5\" -> \"4.5\"\r\n return model.replace(/(\\d)-(\\d)/g, (_, p1, p2) => `${p1}.${p2}`)\r\n}\r\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 type {\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\nimport type { Model } from \"~/services/copilot/get-models\"\n\n// Encoder type mapping\nconst ENCODING_MAP = {\n o200k_base: () => import(\"gpt-tokenizer/encoding/o200k_base\"),\n cl100k_base: () => import(\"gpt-tokenizer/encoding/cl100k_base\"),\n p50k_base: () => import(\"gpt-tokenizer/encoding/p50k_base\"),\n p50k_edit: () => import(\"gpt-tokenizer/encoding/p50k_edit\"),\n r50k_base: () => import(\"gpt-tokenizer/encoding/r50k_base\"),\n} as const\n\ntype SupportedEncoding = keyof typeof ENCODING_MAP\n\n// Define encoder interface\ninterface Encoder {\n encode: (text: string) => Array<number>\n}\n\n// Cache loaded encoders to avoid repeated imports\nconst encodingCache = new Map<string, Encoder>()\n\n/**\n * Calculate tokens for tool calls\n */\nconst calculateToolCallsTokens = (\n toolCalls: Array<ToolCall>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = 0\n for (const toolCall of toolCalls) {\n tokens += constants.funcInit\n tokens += encoder.encode(JSON.stringify(toolCall)).length\n }\n tokens += constants.funcEnd\n return tokens\n}\n\n/**\n * Calculate tokens for content parts\n */\nconst calculateContentPartsTokens = (\n contentParts: Array<ContentPart>,\n encoder: Encoder,\n): number => {\n let tokens = 0\n for (const part of contentParts) {\n if (part.type === \"image_url\") {\n tokens += encoder.encode(part.image_url.url).length + 85\n } else if (part.text) {\n tokens += encoder.encode(part.text).length\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens for a single message\n */\nconst calculateMessageTokens = (\n message: Message,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n const tokensPerMessage = 3\n const tokensPerName = 1\n let tokens = tokensPerMessage\n for (const [key, value] of Object.entries(message)) {\n if (typeof value === \"string\") {\n tokens += encoder.encode(value).length\n }\n if (key === \"name\") {\n tokens += tokensPerName\n }\n if (key === \"tool_calls\") {\n tokens += calculateToolCallsTokens(\n value as Array<ToolCall>,\n encoder,\n constants,\n )\n }\n if (key === \"content\" && Array.isArray(value)) {\n tokens += calculateContentPartsTokens(\n value as Array<ContentPart>,\n encoder,\n )\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens using custom algorithm\n */\nconst calculateTokens = (\n messages: Array<Message>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (messages.length === 0) {\n return 0\n }\n let numTokens = 0\n for (const message of messages) {\n numTokens += calculateMessageTokens(message, encoder, constants)\n }\n // every reply is primed with <|start|>assistant<|message|>\n numTokens += 3\n return numTokens\n}\n\n/**\n * Get the corresponding encoder module based on encoding type\n */\nconst getEncodeChatFunction = async (encoding: string): Promise<Encoder> => {\n if (encodingCache.has(encoding)) {\n const cached = encodingCache.get(encoding)\n if (cached) {\n return cached\n }\n }\n\n const supportedEncoding = encoding as SupportedEncoding\n if (!(supportedEncoding in ENCODING_MAP)) {\n const fallbackModule = (await ENCODING_MAP.o200k_base()) as Encoder\n encodingCache.set(encoding, fallbackModule)\n return fallbackModule\n }\n\n const encodingModule = (await ENCODING_MAP[supportedEncoding]()) as Encoder\n encodingCache.set(encoding, encodingModule)\n return encodingModule\n}\n\n/**\n * Get tokenizer type from model information\n */\nexport const getTokenizerFromModel = (model: Model): string => {\n return model.capabilities.tokenizer || \"o200k_base\"\n}\n\n/**\n * Get model-specific constants for token calculation\n */\nconst getModelConstants = (model: Model) => {\n return model.id === \"gpt-3.5-turbo\" || model.id === \"gpt-4\" ?\n {\n funcInit: 10,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n : {\n funcInit: 7,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n}\n\n/**\n * Calculate tokens for a single parameter\n */\nconst calculateParameterTokens = (\n key: string,\n prop: unknown,\n context: {\n encoder: Encoder\n constants: ReturnType<typeof getModelConstants>\n },\n): number => {\n const { encoder, constants } = context\n let tokens = constants.propKey\n\n // Early return if prop is not an object\n if (typeof prop !== \"object\" || prop === null) {\n return tokens\n }\n\n // Type assertion for parameter properties\n const param = prop as {\n type?: string\n description?: string\n enum?: Array<unknown>\n [key: string]: unknown\n }\n\n const paramName = key\n const paramType = param.type || \"string\"\n let paramDesc = param.description || \"\"\n\n // Handle enum values\n if (param.enum && Array.isArray(param.enum)) {\n tokens += constants.enumInit\n for (const item of param.enum) {\n tokens += constants.enumItem\n tokens += encoder.encode(String(item)).length\n }\n }\n\n // Clean up description\n if (paramDesc.endsWith(\".\")) {\n paramDesc = paramDesc.slice(0, -1)\n }\n\n // Encode the main parameter line\n const line = `${paramName}:${paramType}:${paramDesc}`\n tokens += encoder.encode(line).length\n\n // Handle additional properties (excluding standard ones)\n const excludedKeys = new Set([\"type\", \"description\", \"enum\"])\n for (const propertyName of Object.keys(param)) {\n if (!excludedKeys.has(propertyName)) {\n const propertyValue = param[propertyName]\n const propertyText =\n typeof propertyValue === \"string\" ? propertyValue : (\n JSON.stringify(propertyValue)\n )\n tokens += encoder.encode(`${propertyName}:${propertyText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for function parameters\n */\nconst calculateParametersTokens = (\n parameters: unknown,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (!parameters || typeof parameters !== \"object\") {\n return 0\n }\n\n const params = parameters as Record<string, unknown>\n let tokens = 0\n\n for (const [key, value] of Object.entries(params)) {\n if (key === \"properties\") {\n const properties = value as Record<string, unknown>\n if (Object.keys(properties).length > 0) {\n tokens += constants.propInit\n for (const propKey of Object.keys(properties)) {\n tokens += calculateParameterTokens(propKey, properties[propKey], {\n encoder,\n constants,\n })\n }\n }\n } else {\n const paramText =\n typeof value === \"string\" ? value : JSON.stringify(value)\n tokens += encoder.encode(`${key}:${paramText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for a single tool\n */\nconst calculateToolTokens = (\n tool: Tool,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = constants.funcInit\n const func = tool.function\n const fName = func.name\n let fDesc = func.description || \"\"\n if (fDesc.endsWith(\".\")) {\n fDesc = fDesc.slice(0, -1)\n }\n const line = fName + \":\" + fDesc\n tokens += encoder.encode(line).length\n if (\n typeof func.parameters === \"object\" // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n && func.parameters !== null\n ) {\n tokens += calculateParametersTokens(func.parameters, encoder, constants)\n }\n return tokens\n}\n\n/**\n * Calculate token count for tools based on model\n */\nexport const numTokensForTools = (\n tools: Array<Tool>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let funcTokenCount = 0\n for (const tool of tools) {\n funcTokenCount += calculateToolTokens(tool, encoder, constants)\n }\n funcTokenCount += constants.funcEnd\n return funcTokenCount\n}\n\n/**\n * Calculate the token count of messages, supporting multiple GPT encoders\n */\nexport const getTokenCount = async (\n payload: ChatCompletionsPayload,\n model: Model,\n): Promise<{ input: number; output: number }> => {\n // Get tokenizer string\n const tokenizer = getTokenizerFromModel(model)\n\n // Get corresponding encoder module\n const encoder = await getEncodeChatFunction(tokenizer)\n\n const simplifiedMessages = payload.messages\n const inputMessages = simplifiedMessages.filter(\n (msg) => msg.role !== \"assistant\",\n )\n const outputMessages = simplifiedMessages.filter(\n (msg) => msg.role === \"assistant\",\n )\n\n const constants = getModelConstants(model)\n let inputTokens = calculateTokens(inputMessages, encoder, constants)\n if (payload.tools && payload.tools.length > 0) {\n inputTokens += numTokensForTools(payload.tools, encoder, constants)\n }\n const outputTokens = calculateTokens(outputMessages, encoder, constants)\n\n return {\n input: inputTokens,\n output: outputTokens,\n }\n}\n\n/**\n * Estimate token count for a payload without model info (uses o200k_base encoding)\n * This is a rough estimate used when we don't have model-specific info\n */\nexport const estimateTokenCount = async (\n payload: ChatCompletionsPayload,\n): Promise<number> => {\n const encoder = await getEncodeChatFunction(\"o200k_base\")\n\n // Simple estimation: encode all message content\n let tokens = 0\n for (const message of payload.messages) {\n // 3 tokens per message overhead\n tokens += 3\n\n if (typeof message.content === \"string\") {\n tokens += encoder.encode(message.content).length\n } else if (Array.isArray(message.content)) {\n for (const part of message.content) {\n if (part.type === \"text\" && part.text) {\n tokens += encoder.encode(part.text).length\n } else if (part.type === \"image_url\") {\n // Rough estimate for images\n tokens += 85\n }\n }\n }\n\n // Add role tokens\n if (message.role) {\n tokens += encoder.encode(message.role).length\n }\n\n // Tool calls in messages (assistant responses with tool use)\n if (message.tool_calls) {\n tokens += encoder.encode(JSON.stringify(message.tool_calls)).length\n }\n }\n\n // Add tool definitions if present (but don't double count - use simplified estimate)\n // Tool definitions add overhead but the full JSON stringify overcounts\n if (payload.tools && payload.tools.length > 0) {\n // Estimate ~50 tokens per tool on average for function name + description + params\n tokens += payload.tools.length * 50\n }\n\n // Priming tokens\n tokens += 3\n\n return tokens\n}\n","import consola from \"consola\"\r\nimport { events } from \"fetch-event-stream\"\r\n\r\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\nimport { state } from \"~/lib/state\"\r\n\r\nexport const createChatCompletions = async (\r\n payload: ChatCompletionsPayload,\r\n) => {\r\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\r\n\r\n const enableVision = payload.messages.some(\r\n (x) =>\r\n typeof x.content !== \"string\"\r\n && x.content?.some((x) => x.type === \"image_url\"),\r\n )\r\n\r\n // Agent/user check for X-Initiator header\r\n // Determine if any message is from an agent (\"assistant\" or \"tool\")\r\n const isAgentCall = payload.messages.some((msg) =>\r\n [\"assistant\", \"tool\"].includes(msg.role),\r\n )\r\n\r\n // Build headers and add X-Initiator\r\n const headers: Record<string, string> = {\r\n ...copilotHeaders(state, enableVision),\r\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\r\n }\r\n\r\n const response = await fetchWithRetry(`${copilotBaseUrl(state)}/chat/completions`, {\r\n method: \"POST\",\r\n headers,\r\n body: JSON.stringify(payload),\r\n })\r\n\r\n if (!response.ok) {\r\n consola.error(\"Failed to create chat completions\", response)\r\n throw new HTTPError(\"Failed to create chat completions\", response)\r\n }\r\n\r\n if (payload.stream) {\r\n return events(response)\r\n }\r\n\r\n return (await response.json()) as ChatCompletionResponse\r\n}\r\n\r\n// Streaming types\r\n\r\nexport interface ChatCompletionChunk {\r\n id: string\r\n object: \"chat.completion.chunk\"\r\n created: number\r\n model: string\r\n choices: Array<Choice>\r\n system_fingerprint?: string\r\n usage?: {\r\n prompt_tokens: number\r\n completion_tokens: number\r\n total_tokens: number\r\n prompt_tokens_details?: {\r\n cached_tokens: number\r\n }\r\n completion_tokens_details?: {\r\n accepted_prediction_tokens: number\r\n rejected_prediction_tokens: number\r\n }\r\n }\r\n}\r\n\r\ninterface Delta {\r\n content?: string | null\r\n role?: \"user\" | \"assistant\" | \"system\" | \"tool\"\r\n tool_calls?: Array<{\r\n index: number\r\n id?: string\r\n type?: \"function\"\r\n function?: {\r\n name?: string\r\n arguments?: string\r\n }\r\n }>\r\n}\r\n\r\ninterface Choice {\r\n index: number\r\n delta: Delta\r\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null\r\n logprobs: object | null\r\n}\r\n\r\n// Non-streaming types\r\n\r\nexport interface ChatCompletionResponse {\r\n id: string\r\n object: \"chat.completion\"\r\n created: number\r\n model: string\r\n choices: Array<ChoiceNonStreaming>\r\n system_fingerprint?: string\r\n usage?: {\r\n prompt_tokens: number\r\n completion_tokens: number\r\n total_tokens: number\r\n prompt_tokens_details?: {\r\n cached_tokens: number\r\n }\r\n }\r\n}\r\n\r\ninterface ResponseMessage {\r\n role: \"assistant\"\r\n content: string | null\r\n tool_calls?: Array<ToolCall>\r\n}\r\n\r\ninterface ChoiceNonStreaming {\r\n index: number\r\n message: ResponseMessage\r\n logprobs: object | null\r\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\"\r\n}\r\n\r\n// Payload types\r\n\r\nexport interface ChatCompletionsPayload {\r\n messages: Array<Message>\r\n model: string\r\n temperature?: number | null\r\n top_p?: number | null\r\n max_tokens?: number | null\r\n stop?: string | Array<string> | null\r\n n?: number | null\r\n stream?: boolean | null\r\n stream_options?: { include_usage?: boolean } | null\r\n\r\n frequency_penalty?: number | null\r\n presence_penalty?: number | null\r\n logit_bias?: Record<string, number> | null\r\n logprobs?: boolean | null\r\n response_format?: { type: \"json_object\" } | null\r\n seed?: number | null\r\n tools?: Array<Tool> | null\r\n tool_choice?:\r\n | \"none\"\r\n | \"auto\"\r\n | \"required\"\r\n | { type: \"function\"; function: { name: string } }\r\n | null\r\n user?: string | null\r\n}\r\n\r\nexport interface Tool {\r\n type: \"function\"\r\n function: {\r\n name: string\r\n description?: string\r\n parameters: Record<string, unknown>\r\n }\r\n}\r\n\r\nexport interface Message {\r\n role: \"user\" | \"assistant\" | \"system\" | \"tool\" | \"developer\"\r\n content: string | Array<ContentPart> | null\r\n\r\n name?: string\r\n tool_calls?: Array<ToolCall>\r\n tool_call_id?: string\r\n}\r\n\r\nexport interface ToolCall {\r\n id: string\r\n type: \"function\"\r\n function: {\r\n name: string\r\n arguments: string\r\n }\r\n}\r\n\r\nexport type ContentPart = TextPart | ImagePart\r\n\r\nexport interface TextPart {\r\n type: \"text\"\r\n text: string\r\n}\r\n\r\nexport interface ImagePart {\r\n type: \"image_url\"\r\n image_url: {\r\n url: string\r\n detail?: \"low\" | \"high\" | \"auto\"\r\n }\r\n}\r\n","import type { Context } from \"hono\"\r\n\r\nimport consola from \"consola\"\r\nimport { streamSSE, type SSEMessage } from \"hono/streaming\"\r\n\r\nimport { awaitApproval } from \"~/lib/approval\"\r\nimport { applyReplacementsToPayload } from \"~/lib/auto-replace\"\r\nimport { normalizeModelName } from \"~/lib/model-resolver\"\r\nimport { checkRateLimit } from \"~/lib/rate-limit\"\r\nimport { setRequestContext } from \"~/lib/request-logger\"\r\nimport { state } from \"~/lib/state\"\r\nimport { getTokenCount } from \"~/lib/tokenizer\"\r\nimport { isNullish } from \"~/lib/utils\"\r\nimport {\r\n createAzureOpenAIChatCompletions,\r\n isAzureOpenAIModel,\r\n} from \"~/services/azure-openai\"\r\nimport {\r\n createChatCompletions,\r\n type ChatCompletionChunk,\r\n type ChatCompletionResponse,\r\n type ChatCompletionsPayload,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nexport async function handleCompletion(c: Context) {\r\n await checkRateLimit(state)\r\n\r\n const rawPayload = await c.req.json<ChatCompletionsPayload>()\r\n\r\n // Apply auto-replacements to the payload\r\n // eslint-disable-next-line require-atomic-updates\r\n let payload = await applyReplacementsToPayload(rawPayload)\r\n\r\n // Normalize model name (e.g., claude-opus-4-5 -> claude-opus-4.5)\r\n payload = {\r\n ...payload,\r\n model: normalizeModelName(payload.model),\r\n }\r\n\r\n consola.debug(\"Request payload:\", JSON.stringify(payload).slice(-400))\r\n\r\n // Check if this is an Azure OpenAI model\r\n if (isAzureOpenAIModel(payload.model)) {\r\n if (!state.azureOpenAIConfig) {\r\n return c.json({ error: \"Azure OpenAI not configured\" }, 500)\r\n }\r\n\r\n setRequestContext(c, { provider: \"Azure OpenAI\", model: payload.model })\r\n\r\n if (state.manualApprove) await awaitApproval()\r\n\r\n const response = await createAzureOpenAIChatCompletions(\r\n state.azureOpenAIConfig,\r\n payload,\r\n )\r\n\r\n if (isNonStreaming(response)) {\r\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\r\n if (response.usage) {\r\n setRequestContext(c, {\r\n inputTokens: response.usage.prompt_tokens,\r\n outputTokens: response.usage.completion_tokens,\r\n })\r\n }\r\n return c.json(response)\r\n }\r\n\r\n consola.debug(\"Streaming response\")\r\n return streamSSE(c, async (stream) => {\r\n for await (const chunk of response) {\r\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\r\n // Capture usage from final chunk if available\r\n if (chunk.data && chunk.data !== \"[DONE]\") {\r\n const parsed = JSON.parse(chunk.data) as ChatCompletionChunk\r\n if (parsed.usage) {\r\n setRequestContext(c, {\r\n inputTokens: parsed.usage.prompt_tokens,\r\n outputTokens: parsed.usage.completion_tokens,\r\n })\r\n }\r\n }\r\n await stream.writeSSE(chunk as SSEMessage)\r\n }\r\n })\r\n }\r\n\r\n setRequestContext(c, { provider: \"Copilot\", model: payload.model })\r\n\r\n // Find the selected model\r\n const selectedModel = state.models?.data.find(\r\n (model) => model.id === payload.model,\r\n )\r\n\r\n // Calculate and display token count\r\n try {\r\n if (selectedModel) {\r\n const tokenCount = await getTokenCount(payload, selectedModel)\r\n setRequestContext(c, { inputTokens: tokenCount.input })\r\n }\r\n } catch (error) {\r\n consola.warn(\"Failed to calculate token count:\", error)\r\n }\r\n\r\n if (state.manualApprove) await awaitApproval()\r\n\r\n if (isNullish(payload.max_tokens)) {\r\n payload = {\r\n ...payload,\r\n max_tokens: selectedModel?.capabilities.limits.max_output_tokens,\r\n }\r\n consola.debug(\"Set max_tokens to:\", JSON.stringify(payload.max_tokens))\r\n }\r\n\r\n const response = await createChatCompletions(payload)\r\n\r\n if (isNonStreaming(response)) {\r\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\r\n if (response.usage) {\r\n setRequestContext(c, {\r\n inputTokens: response.usage.prompt_tokens,\r\n outputTokens: response.usage.completion_tokens,\r\n })\r\n }\r\n return c.json(response)\r\n }\r\n\r\n consola.debug(\"Streaming response\")\r\n return streamSSE(c, async (stream) => {\r\n for await (const chunk of response) {\r\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\r\n // Capture usage from final chunk if available\r\n if (chunk.data && chunk.data !== \"[DONE]\") {\r\n const parsed = JSON.parse(chunk.data) as ChatCompletionChunk\r\n if (parsed.usage) {\r\n setRequestContext(c, {\r\n inputTokens: parsed.usage.prompt_tokens,\r\n outputTokens: parsed.usage.completion_tokens,\r\n })\r\n }\r\n }\r\n await stream.writeSSE(chunk as SSEMessage)\r\n }\r\n })\r\n}\r\n\r\nconst isNonStreaming = (\r\n response: Awaited<ReturnType<typeof createChatCompletions>>,\r\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\r\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\"\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\nimport { state } from \"~/lib/state\"\r\n\r\nexport const createEmbeddings = async (payload: EmbeddingRequest) => {\r\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\r\n\r\n const response = await fetchWithRetry(`${copilotBaseUrl(state)}/embeddings`, {\r\n method: \"POST\",\r\n headers: copilotHeaders(state),\r\n body: JSON.stringify(payload),\r\n })\r\n\r\n if (!response.ok) throw new HTTPError(\"Failed to create embeddings\", response)\r\n\r\n return (await response.json()) as EmbeddingResponse\r\n}\r\n\r\nexport interface EmbeddingRequest {\r\n input: string | Array<string>\r\n model: string\r\n}\r\n\r\nexport interface Embedding {\r\n object: string\r\n embedding: Array<number>\r\n index: number\r\n}\r\n\r\nexport interface EmbeddingResponse {\r\n object: string\r\n data: Array<Embedding>\r\n model: string\r\n usage: {\r\n prompt_tokens: number\r\n total_tokens: number\r\n }\r\n}\r\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 {\r\n type ChatCompletionResponse,\r\n type ChatCompletionsPayload,\r\n type ContentPart,\r\n type Message,\r\n type TextPart,\r\n type Tool,\r\n type ToolCall,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport {\r\n type AnthropicAssistantContentBlock,\r\n type AnthropicAssistantMessage,\r\n type AnthropicMessage,\r\n type AnthropicMessagesPayload,\r\n type AnthropicResponse,\r\n type AnthropicTextBlock,\r\n type AnthropicThinkingBlock,\r\n type AnthropicTool,\r\n type AnthropicToolResultBlock,\r\n type AnthropicToolUseBlock,\r\n type AnthropicUserContentBlock,\r\n type AnthropicUserMessage,\r\n} from \"./anthropic-types\"\r\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\r\n\r\n// Payload translation\r\n\r\nexport function translateToOpenAI(\r\n payload: AnthropicMessagesPayload,\r\n): ChatCompletionsPayload {\r\n return {\r\n model: translateModelName(payload.model),\r\n messages: translateAnthropicMessagesToOpenAI(\r\n payload.messages,\r\n payload.system,\r\n ),\r\n max_tokens: payload.max_tokens,\r\n stop: payload.stop_sequences,\r\n stream: payload.stream,\r\n temperature: payload.temperature,\r\n top_p: payload.top_p,\r\n user: payload.metadata?.user_id,\r\n tools: translateAnthropicToolsToOpenAI(payload.tools),\r\n tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),\r\n }\r\n}\r\n\r\nfunction translateModelName(model: string): string {\r\n // Subagent requests use a specific dated model which Copilot doesn't support\r\n // e.g., claude-sonnet-4-20250514 -> claude-sonnet-4\r\n // But preserve version numbers like claude-opus-4-5 (normalized to claude-opus-4.5 later)\r\n if (model.match(/^claude-sonnet-4-\\d{8}/)) {\r\n return \"claude-sonnet-4\"\r\n } else if (model.match(/^claude-opus-4-\\d{8}/)) {\r\n return \"claude-opus-4\"\r\n }\r\n return model\r\n}\r\n\r\nfunction translateAnthropicMessagesToOpenAI(\r\n anthropicMessages: Array<AnthropicMessage>,\r\n system: string | Array<AnthropicTextBlock> | undefined,\r\n): Array<Message> {\r\n const systemMessages = handleSystemPrompt(system)\r\n\r\n const otherMessages = anthropicMessages.flatMap((message) =>\r\n message.role === \"user\" ?\r\n handleUserMessage(message)\r\n : handleAssistantMessage(message),\r\n )\r\n\r\n return [...systemMessages, ...otherMessages]\r\n}\r\n\r\nfunction handleSystemPrompt(\r\n system: string | Array<AnthropicTextBlock> | undefined,\r\n): Array<Message> {\r\n if (!system) {\r\n return []\r\n }\r\n\r\n if (typeof system === \"string\") {\r\n return [{ role: \"system\", content: system }]\r\n } else {\r\n const systemText = system.map((block) => block.text).join(\"\\n\\n\")\r\n return [{ role: \"system\", content: systemText }]\r\n }\r\n}\r\n\r\nfunction handleUserMessage(message: AnthropicUserMessage): Array<Message> {\r\n const newMessages: Array<Message> = []\r\n\r\n if (Array.isArray(message.content)) {\r\n const toolResultBlocks = message.content.filter(\r\n (block): block is AnthropicToolResultBlock =>\r\n block.type === \"tool_result\",\r\n )\r\n const otherBlocks = message.content.filter(\r\n (block) => block.type !== \"tool_result\",\r\n )\r\n\r\n // Tool results must come first to maintain protocol: tool_use -> tool_result -> user\r\n for (const block of toolResultBlocks) {\r\n newMessages.push({\r\n role: \"tool\",\r\n tool_call_id: block.tool_use_id,\r\n content: mapContent(block.content),\r\n })\r\n }\r\n\r\n if (otherBlocks.length > 0) {\r\n newMessages.push({\r\n role: \"user\",\r\n content: mapContent(otherBlocks),\r\n })\r\n }\r\n } else {\r\n newMessages.push({\r\n role: \"user\",\r\n content: mapContent(message.content),\r\n })\r\n }\r\n\r\n return newMessages\r\n}\r\n\r\nfunction handleAssistantMessage(\r\n message: AnthropicAssistantMessage,\r\n): Array<Message> {\r\n if (!Array.isArray(message.content)) {\r\n return [\r\n {\r\n role: \"assistant\",\r\n content: mapContent(message.content),\r\n },\r\n ]\r\n }\r\n\r\n const toolUseBlocks = message.content.filter(\r\n (block): block is AnthropicToolUseBlock => block.type === \"tool_use\",\r\n )\r\n\r\n const textBlocks = message.content.filter(\r\n (block): block is AnthropicTextBlock => block.type === \"text\",\r\n )\r\n\r\n const thinkingBlocks = message.content.filter(\r\n (block): block is AnthropicThinkingBlock => block.type === \"thinking\",\r\n )\r\n\r\n // Combine text and thinking blocks, as OpenAI doesn't have separate thinking blocks\r\n const allTextContent = [\r\n ...textBlocks.map((b) => b.text),\r\n ...thinkingBlocks.map((b) => b.thinking),\r\n ].join(\"\\n\\n\")\r\n\r\n return toolUseBlocks.length > 0 ?\r\n [\r\n {\r\n role: \"assistant\",\r\n content: allTextContent || null,\r\n tool_calls: toolUseBlocks.map((toolUse) => ({\r\n id: toolUse.id,\r\n type: \"function\",\r\n function: {\r\n name: toolUse.name,\r\n arguments: JSON.stringify(toolUse.input),\r\n },\r\n })),\r\n },\r\n ]\r\n : [\r\n {\r\n role: \"assistant\",\r\n content: mapContent(message.content),\r\n },\r\n ]\r\n}\r\n\r\nfunction mapContent(\r\n content:\r\n | string\r\n | Array<AnthropicUserContentBlock | AnthropicAssistantContentBlock>,\r\n): string | Array<ContentPart> | null {\r\n if (typeof content === \"string\") {\r\n return content\r\n }\r\n if (!Array.isArray(content)) {\r\n return null\r\n }\r\n\r\n const hasImage = content.some((block) => block.type === \"image\")\r\n if (!hasImage) {\r\n return content\r\n .filter(\r\n (block): block is AnthropicTextBlock | AnthropicThinkingBlock =>\r\n block.type === \"text\" || block.type === \"thinking\",\r\n )\r\n .map((block) => (block.type === \"text\" ? block.text : block.thinking))\r\n .join(\"\\n\\n\")\r\n }\r\n\r\n const contentParts: Array<ContentPart> = []\r\n for (const block of content) {\r\n switch (block.type) {\r\n case \"text\": {\r\n contentParts.push({ type: \"text\", text: block.text })\r\n\r\n break\r\n }\r\n case \"thinking\": {\r\n contentParts.push({ type: \"text\", text: block.thinking })\r\n\r\n break\r\n }\r\n case \"image\": {\r\n contentParts.push({\r\n type: \"image_url\",\r\n image_url: {\r\n url: `data:${block.source.media_type};base64,${block.source.data}`,\r\n },\r\n })\r\n\r\n break\r\n }\r\n // No default\r\n }\r\n }\r\n return contentParts\r\n}\r\n\r\nfunction translateAnthropicToolsToOpenAI(\r\n anthropicTools: Array<AnthropicTool> | undefined,\r\n): Array<Tool> | undefined {\r\n if (!anthropicTools) {\r\n return undefined\r\n }\r\n return anthropicTools.map((tool) => ({\r\n type: \"function\",\r\n function: {\r\n name: tool.name,\r\n description: tool.description,\r\n parameters: tool.input_schema,\r\n },\r\n }))\r\n}\r\n\r\nfunction translateAnthropicToolChoiceToOpenAI(\r\n anthropicToolChoice: AnthropicMessagesPayload[\"tool_choice\"],\r\n): ChatCompletionsPayload[\"tool_choice\"] {\r\n if (!anthropicToolChoice) {\r\n return undefined\r\n }\r\n\r\n switch (anthropicToolChoice.type) {\r\n case \"auto\": {\r\n return \"auto\"\r\n }\r\n case \"any\": {\r\n return \"required\"\r\n }\r\n case \"tool\": {\r\n if (anthropicToolChoice.name) {\r\n return {\r\n type: \"function\",\r\n function: { name: anthropicToolChoice.name },\r\n }\r\n }\r\n return undefined\r\n }\r\n case \"none\": {\r\n return \"none\"\r\n }\r\n default: {\r\n return undefined\r\n }\r\n }\r\n}\r\n\r\n// Response translation\r\n\r\nexport function translateToAnthropic(\r\n response: ChatCompletionResponse,\r\n originalModel?: string,\r\n): AnthropicResponse {\r\n // Merge content from all choices\r\n const allTextBlocks: Array<AnthropicTextBlock> = []\r\n const allToolUseBlocks: Array<AnthropicToolUseBlock> = []\r\n let stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null =\r\n null // default\r\n stopReason = response.choices[0]?.finish_reason ?? stopReason\r\n\r\n // Process all choices to extract text and tool use blocks\r\n for (const choice of response.choices) {\r\n const textBlocks = getAnthropicTextBlocks(choice.message.content)\r\n const toolUseBlocks = getAnthropicToolUseBlocks(choice.message.tool_calls)\r\n\r\n allTextBlocks.push(...textBlocks)\r\n allToolUseBlocks.push(...toolUseBlocks)\r\n\r\n // Use the finish_reason from the first choice, or prioritize tool_calls\r\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\r\n stopReason = choice.finish_reason\r\n }\r\n }\r\n\r\n // Note: GitHub Copilot doesn't generate thinking blocks, so we don't include them in responses\r\n\r\n return {\r\n id: response.id,\r\n type: \"message\",\r\n role: \"assistant\",\r\n // Use original requested model for cost calculation in Claude Code\r\n model: originalModel ?? response.model,\r\n content: [...allTextBlocks, ...allToolUseBlocks],\r\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\r\n stop_sequence: null,\r\n usage: {\r\n input_tokens:\r\n (response.usage?.prompt_tokens ?? 0)\r\n - (response.usage?.prompt_tokens_details?.cached_tokens ?? 0),\r\n output_tokens: response.usage?.completion_tokens ?? 0,\r\n ...(response.usage?.prompt_tokens_details?.cached_tokens\r\n !== undefined && {\r\n cache_read_input_tokens:\r\n response.usage.prompt_tokens_details.cached_tokens,\r\n }),\r\n },\r\n }\r\n}\r\n\r\nfunction getAnthropicTextBlocks(\r\n messageContent: Message[\"content\"],\r\n): Array<AnthropicTextBlock> {\r\n if (typeof messageContent === \"string\") {\r\n return [{ type: \"text\", text: messageContent }]\r\n }\r\n\r\n if (Array.isArray(messageContent)) {\r\n return messageContent\r\n .filter((part): part is TextPart => part.type === \"text\")\r\n .map((part) => ({ type: \"text\", text: part.text }))\r\n }\r\n\r\n return []\r\n}\r\n\r\nfunction getAnthropicToolUseBlocks(\r\n toolCalls: Array<ToolCall> | undefined,\r\n): Array<AnthropicToolUseBlock> {\r\n if (!toolCalls) {\r\n return []\r\n }\r\n return toolCalls.map((toolCall) => ({\r\n type: \"tool_use\",\r\n id: toolCall.id,\r\n name: toolCall.function.name,\r\n input: JSON.parse(toolCall.function.arguments) as Record<string, unknown>,\r\n }))\r\n}\r\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport { normalizeModelName } from \"~/lib/model-resolver\"\nimport { state } from \"~/lib/state\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\n\nimport { type AnthropicMessagesPayload } from \"./anthropic-types\"\nimport { translateToOpenAI } from \"./non-stream-translation\"\n\n/**\n * Handles token counting for Anthropic messages\n */\nexport async function handleCountTokens(c: Context) {\n try {\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n // Normalize model name (e.g., claude-opus-4-5 -> claude-opus-4.5) before lookup\n const normalizedModel = normalizeModelName(anthropicPayload.model)\n\n const selectedModel = state.models?.data.find(\n (model) => model.id === normalizedModel,\n )\n\n if (!selectedModel) {\n consola.warn(\"Model not found, returning default token count\")\n return c.json({\n input_tokens: 1,\n })\n }\n\n const tokenCount = await getTokenCount(openAIPayload, selectedModel)\n\n if (anthropicPayload.tools && anthropicPayload.tools.length > 0) {\n let mcpToolExist = false\n if (anthropicBeta?.startsWith(\"claude-code\")) {\n mcpToolExist = anthropicPayload.tools.some((tool) =>\n tool.name.startsWith(\"mcp__\"),\n )\n }\n if (!mcpToolExist) {\n if (anthropicPayload.model.startsWith(\"claude\")) {\n // https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview#pricing\n tokenCount.input = tokenCount.input + 346\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n tokenCount.input = tokenCount.input + 480\n }\n }\n }\n\n let finalTokenCount = tokenCount.input + tokenCount.output\n if (anthropicPayload.model.startsWith(\"claude\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.15)\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.03)\n }\n\n consola.info(\"Token count:\", finalTokenCount)\n\n return c.json({\n input_tokens: finalTokenCount,\n })\n } catch (error) {\n consola.error(\"Error counting tokens:\", error)\n return c.json({\n input_tokens: 1,\n })\n }\n}\n","import {\r\n type ChatCompletionChunk,\r\n type ChatCompletionResponse,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport {\r\n type AnthropicStreamEventData,\r\n type AnthropicStreamState,\r\n} from \"./anthropic-types\"\r\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\r\n\r\nfunction isToolBlockOpen(state: AnthropicStreamState): boolean {\r\n if (!state.contentBlockOpen) {\r\n return false\r\n }\r\n // Check if the current block index corresponds to any known tool call\r\n return Object.values(state.toolCalls).some(\r\n (tc) => tc.anthropicBlockIndex === state.contentBlockIndex,\r\n )\r\n}\r\n\r\n// Helper to create message_delta and message_stop events\r\nfunction createMessageDeltaEvents(\r\n finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\",\r\n usage: { prompt_tokens: number; completion_tokens: number; cached_tokens: number },\r\n): Array<AnthropicStreamEventData> {\r\n const stopReason = mapOpenAIStopReasonToAnthropic(finishReason)\r\n console.log(`[stream-translation] Creating message_delta with stop_reason: ${stopReason}, finishReason: ${finishReason}`)\r\n return [\r\n {\r\n type: \"message_delta\",\r\n delta: {\r\n stop_reason: stopReason,\r\n stop_sequence: null,\r\n },\r\n usage: {\r\n input_tokens: usage.prompt_tokens,\r\n output_tokens: usage.completion_tokens,\r\n cache_creation_input_tokens: 0,\r\n cache_read_input_tokens: usage.cached_tokens,\r\n },\r\n },\r\n {\r\n type: \"message_stop\",\r\n },\r\n ]\r\n}\r\n\r\n// Export for use in handler fallback\r\nexport function createFallbackMessageDeltaEvents(\r\n state: AnthropicStreamState,\r\n): Array<AnthropicStreamEventData> {\r\n // If message_delta was already sent, return empty\r\n if (state.messageDeltaSent) {\r\n return []\r\n }\r\n\r\n // If we have a pending finish_reason, send message_delta with whatever usage we have\r\n if (state.pendingFinishReason) {\r\n const usage = state.pendingUsage ?? { prompt_tokens: 0, completion_tokens: 0, cached_tokens: 0 }\r\n return createMessageDeltaEvents(state.pendingFinishReason, usage)\r\n }\r\n\r\n return []\r\n}\r\n\r\n// eslint-disable-next-line max-lines-per-function, complexity\r\nexport function translateChunkToAnthropicEvents(\r\n chunk: ChatCompletionChunk,\r\n state: AnthropicStreamState,\r\n originalModel?: string,\r\n): Array<AnthropicStreamEventData> {\r\n const events: Array<AnthropicStreamEventData> = []\r\n\r\n // Capture usage from any chunk that has it (may come before, with, or after finish_reason)\r\n if (chunk.usage) {\r\n state.pendingUsage = {\r\n prompt_tokens: chunk.usage.prompt_tokens ?? 0,\r\n completion_tokens: chunk.usage.completion_tokens ?? 0,\r\n cached_tokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0,\r\n }\r\n\r\n // If we already saw finish_reason but deferred message_delta, send it now\r\n if (state.pendingFinishReason && !state.messageDeltaSent) {\r\n events.push(\r\n ...createMessageDeltaEvents(state.pendingFinishReason, state.pendingUsage),\r\n )\r\n state.messageDeltaSent = true\r\n }\r\n }\r\n\r\n if (chunk.choices.length === 0) {\r\n // Empty choices chunk - usage already captured above\r\n return events\r\n }\r\n\r\n const choice = chunk.choices[0]\r\n const { delta } = choice\r\n\r\n if (!state.messageStartSent) {\r\n // Include usage in message_start for context window display\r\n // Use pending usage if available (captured from earlier chunks)\r\n const usage = state.pendingUsage ?? { prompt_tokens: 0, completion_tokens: 0, cached_tokens: 0 }\r\n events.push({\r\n type: \"message_start\",\r\n message: {\r\n id: chunk.id,\r\n type: \"message\",\r\n role: \"assistant\",\r\n content: [],\r\n // Use original requested model for cost calculation in Claude Code\r\n model: originalModel ?? chunk.model,\r\n stop_reason: null,\r\n stop_sequence: null,\r\n // Include usage for context window display\r\n usage: {\r\n input_tokens: usage.prompt_tokens,\r\n output_tokens: usage.completion_tokens,\r\n cache_creation_input_tokens: 0,\r\n cache_read_input_tokens: usage.cached_tokens,\r\n },\r\n },\r\n })\r\n state.messageStartSent = true\r\n }\r\n\r\n if (delta.content) {\r\n if (isToolBlockOpen(state)) {\r\n // A tool block was open, so close it before starting a text block.\r\n events.push({\r\n type: \"content_block_stop\",\r\n index: state.contentBlockIndex,\r\n })\r\n state.contentBlockIndex++\r\n state.contentBlockOpen = false\r\n }\r\n\r\n if (!state.contentBlockOpen) {\r\n events.push({\r\n type: \"content_block_start\",\r\n index: state.contentBlockIndex,\r\n content_block: {\r\n type: \"text\",\r\n text: \"\",\r\n },\r\n })\r\n state.contentBlockOpen = true\r\n }\r\n\r\n events.push({\r\n type: \"content_block_delta\",\r\n index: state.contentBlockIndex,\r\n delta: {\r\n type: \"text_delta\",\r\n text: delta.content,\r\n },\r\n })\r\n }\r\n\r\n if (delta.tool_calls) {\r\n for (const toolCall of delta.tool_calls) {\r\n if (toolCall.id && toolCall.function?.name) {\r\n // New tool call starting.\r\n if (state.contentBlockOpen) {\r\n // Close any previously open block.\r\n events.push({\r\n type: \"content_block_stop\",\r\n index: state.contentBlockIndex,\r\n })\r\n state.contentBlockIndex++\r\n state.contentBlockOpen = false\r\n }\r\n\r\n const anthropicBlockIndex = state.contentBlockIndex\r\n state.toolCalls[toolCall.index] = {\r\n id: toolCall.id,\r\n name: toolCall.function.name,\r\n anthropicBlockIndex,\r\n }\r\n\r\n events.push({\r\n type: \"content_block_start\",\r\n index: anthropicBlockIndex,\r\n content_block: {\r\n type: \"tool_use\",\r\n id: toolCall.id,\r\n name: toolCall.function.name,\r\n input: {},\r\n },\r\n })\r\n state.contentBlockOpen = true\r\n }\r\n\r\n if (toolCall.function?.arguments) {\r\n const toolCallInfo = state.toolCalls[toolCall.index]\r\n // Tool call can still be empty\r\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\r\n if (toolCallInfo) {\r\n events.push({\r\n type: \"content_block_delta\",\r\n index: toolCallInfo.anthropicBlockIndex,\r\n delta: {\r\n type: \"input_json_delta\",\r\n partial_json: toolCall.function.arguments,\r\n },\r\n })\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (choice.finish_reason) {\r\n if (state.contentBlockOpen) {\r\n events.push({\r\n type: \"content_block_stop\",\r\n index: state.contentBlockIndex,\r\n })\r\n state.contentBlockOpen = false\r\n }\r\n\r\n // Check if we have usage data (from this chunk or previously captured)\r\n const hasUsage = chunk.usage || state.pendingUsage\r\n\r\n if (hasUsage) {\r\n // We have usage - send message_delta immediately\r\n const usage = {\r\n prompt_tokens: chunk.usage?.prompt_tokens ?? state.pendingUsage?.prompt_tokens ?? 0,\r\n completion_tokens: chunk.usage?.completion_tokens ?? state.pendingUsage?.completion_tokens ?? 0,\r\n cached_tokens: chunk.usage?.prompt_tokens_details?.cached_tokens ?? state.pendingUsage?.cached_tokens ?? 0,\r\n }\r\n\r\n events.push(...createMessageDeltaEvents(choice.finish_reason, usage))\r\n state.messageDeltaSent = true\r\n } else {\r\n // No usage yet - defer message_delta until we receive usage in a later chunk\r\n state.pendingFinishReason = choice.finish_reason\r\n }\r\n }\r\n\r\n return events\r\n}\r\n\r\n/**\r\n * Convert a complete OpenAI ChatCompletionResponse to Anthropic streaming events.\r\n * This is used when we fetch non-streaming from upstream but need to simulate\r\n * streaming to the client with accurate token counts.\r\n */\r\nexport function translateResponseToAnthropicEvents(\r\n response: ChatCompletionResponse,\r\n originalModel?: string,\r\n): Array<AnthropicStreamEventData> {\r\n const events: Array<AnthropicStreamEventData> = []\r\n\r\n const choice = response.choices[0]\r\n if (!choice) {\r\n return events\r\n }\r\n\r\n const inputTokens = response.usage?.prompt_tokens ?? 0\r\n const outputTokens = response.usage?.completion_tokens ?? 0\r\n const cachedTokens =\r\n response.usage?.prompt_tokens_details?.cached_tokens ?? 0\r\n\r\n // 1. message_start - with actual token counts from response\r\n events.push({\r\n type: \"message_start\",\r\n message: {\r\n id: response.id,\r\n type: \"message\",\r\n role: \"assistant\",\r\n content: [],\r\n // Use original requested model for cost calculation in Claude Code\r\n model: originalModel ?? response.model,\r\n stop_reason: null,\r\n stop_sequence: null,\r\n usage: {\r\n input_tokens: inputTokens,\r\n output_tokens: 0,\r\n cache_creation_input_tokens: 0,\r\n cache_read_input_tokens: cachedTokens,\r\n },\r\n },\r\n })\r\n\r\n let contentBlockIndex = 0\r\n\r\n // Handle text content\r\n if (choice.message.content) {\r\n // 2. content_block_start for text\r\n events.push({\r\n type: \"content_block_start\",\r\n index: contentBlockIndex,\r\n content_block: {\r\n type: \"text\",\r\n text: \"\",\r\n },\r\n })\r\n\r\n // 3. content_block_delta with the full text\r\n events.push({\r\n type: \"content_block_delta\",\r\n index: contentBlockIndex,\r\n delta: {\r\n type: \"text_delta\",\r\n text: choice.message.content,\r\n },\r\n })\r\n\r\n // 4. content_block_stop\r\n events.push({\r\n type: \"content_block_stop\",\r\n index: contentBlockIndex,\r\n })\r\n\r\n contentBlockIndex++\r\n }\r\n\r\n // Handle tool calls\r\n if (choice.message.tool_calls) {\r\n for (const toolCall of choice.message.tool_calls) {\r\n // content_block_start for tool_use\r\n events.push({\r\n type: \"content_block_start\",\r\n index: contentBlockIndex,\r\n content_block: {\r\n type: \"tool_use\",\r\n id: toolCall.id,\r\n name: toolCall.function.name,\r\n input: {},\r\n },\r\n })\r\n\r\n // content_block_delta with tool arguments\r\n events.push({\r\n type: \"content_block_delta\",\r\n index: contentBlockIndex,\r\n delta: {\r\n type: \"input_json_delta\",\r\n partial_json: toolCall.function.arguments,\r\n },\r\n })\r\n\r\n // content_block_stop\r\n events.push({\r\n type: \"content_block_stop\",\r\n index: contentBlockIndex,\r\n })\r\n\r\n contentBlockIndex++\r\n }\r\n }\r\n\r\n // 5. message_delta with final usage\r\n events.push({\r\n type: \"message_delta\",\r\n delta: {\r\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\r\n stop_sequence: null,\r\n },\r\n usage: {\r\n input_tokens: inputTokens,\r\n output_tokens: outputTokens,\r\n cache_creation_input_tokens: 0,\r\n cache_read_input_tokens: cachedTokens,\r\n },\r\n })\r\n\r\n // 6. message_stop\r\n events.push({\r\n type: \"message_stop\",\r\n })\r\n\r\n return events\r\n}\r\n\r\nexport function translateErrorToAnthropicErrorEvent(): AnthropicStreamEventData {\r\n return {\r\n type: \"error\",\r\n error: {\r\n type: \"api_error\",\r\n message: \"An unexpected error occurred during streaming.\",\r\n },\r\n }\r\n}\r\n","import type { Context } from \"hono\"\r\n\r\nimport consola from \"consola\"\r\nimport { streamSSE } from \"hono/streaming\"\r\n\r\nimport { awaitApproval } from \"~/lib/approval\"\r\nimport { applyReplacementsToPayload } from \"~/lib/auto-replace\"\r\nimport { normalizeModelName } from \"~/lib/model-resolver\"\r\nimport { checkRateLimit } from \"~/lib/rate-limit\"\r\nimport { setRequestContext } from \"~/lib/request-logger\"\r\nimport { state } from \"~/lib/state\"\r\nimport {\r\n createAzureOpenAIChatCompletions,\r\n isAzureOpenAIModel,\r\n} from \"~/services/azure-openai\"\r\nimport {\r\n createChatCompletions,\r\n type ChatCompletionChunk,\r\n type ChatCompletionResponse,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport {\r\n type AnthropicMessagesPayload,\r\n type AnthropicStreamState,\r\n} from \"./anthropic-types\"\r\nimport {\r\n translateToAnthropic,\r\n translateToOpenAI,\r\n} from \"./non-stream-translation\"\r\nimport {\r\n createFallbackMessageDeltaEvents,\r\n translateChunkToAnthropicEvents,\r\n} from \"./stream-translation\"\r\n\r\ninterface UsageData {\r\n prompt_tokens: number\r\n completion_tokens: number\r\n cached_tokens: number\r\n}\r\n\r\n/** Collect all chunks and extract usage data */\r\nasync function collectChunksWithUsage(\r\n eventStream: AsyncIterable<{ event?: string; data?: string }>,\r\n): Promise<{ chunks: Array<ChatCompletionChunk>; usage: UsageData | null }> {\r\n const chunks: Array<ChatCompletionChunk> = []\r\n let usage: UsageData | null = null\r\n\r\n for await (const event of eventStream) {\r\n if (!event.data || event.data === \"[DONE]\") continue\r\n try {\r\n const chunk = JSON.parse(event.data) as ChatCompletionChunk\r\n chunks.push(chunk)\r\n if (chunk.usage) {\r\n usage = {\r\n prompt_tokens: chunk.usage.prompt_tokens,\r\n completion_tokens: chunk.usage.completion_tokens,\r\n cached_tokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0,\r\n }\r\n }\r\n } catch (error) {\r\n consola.error(\"Failed to parse chunk:\", error, event.data)\r\n }\r\n }\r\n return { chunks, usage }\r\n}\r\n\r\nexport async function handleCompletion(c: Context) {\r\n await checkRateLimit(state)\r\n\r\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\r\n consola.debug(\"Anthropic request payload:\", JSON.stringify(anthropicPayload))\r\n\r\n const translatedPayload = translateToOpenAI(anthropicPayload)\r\n let openAIPayload = await applyReplacementsToPayload(translatedPayload)\r\n openAIPayload = { ...openAIPayload, model: normalizeModelName(openAIPayload.model) }\r\n\r\n if (state.manualApprove) await awaitApproval()\r\n\r\n const isAzureModel = isAzureOpenAIModel(openAIPayload.model)\r\n\r\n if (isAzureModel) {\r\n if (!state.azureOpenAIConfig) {\r\n return c.json({ error: \"Azure OpenAI not configured\" }, 500)\r\n }\r\n setRequestContext(c, { provider: \"Azure OpenAI\", model: openAIPayload.model })\r\n } else {\r\n setRequestContext(c, { provider: \"Copilot\", model: openAIPayload.model })\r\n }\r\n\r\n if (anthropicPayload.stream) {\r\n const streamPayload = {\r\n ...openAIPayload,\r\n stream: true,\r\n stream_options: { include_usage: true },\r\n }\r\n\r\n const response = isAzureModel\r\n ? await createAzureOpenAIChatCompletions(state.azureOpenAIConfig!, streamPayload)\r\n : await createChatCompletions(streamPayload)\r\n\r\n const eventStream = response as AsyncIterable<{ event?: string; data?: string }>\r\n\r\n return streamSSE(c, async (stream) => {\r\n // Buffer all chunks first to get usage before emitting message_start\r\n const { chunks, usage } = await collectChunksWithUsage(eventStream)\r\n\r\n consola.debug(`[stream] Collected ${chunks.length} chunks, usage:`, usage)\r\n\r\n if (usage) {\r\n setRequestContext(c, {\r\n inputTokens: usage.prompt_tokens,\r\n outputTokens: usage.completion_tokens,\r\n })\r\n }\r\n\r\n const streamState: AnthropicStreamState = {\r\n messageStartSent: false,\r\n contentBlockOpen: false,\r\n contentBlockIndex: 0,\r\n toolCalls: {},\r\n pendingUsage: usage ?? undefined,\r\n }\r\n\r\n // Emit all events with correct usage in message_start\r\n for (const chunk of chunks) {\r\n const events = translateChunkToAnthropicEvents(chunk, streamState, anthropicPayload.model)\r\n for (const evt of events) {\r\n consola.debug(`[stream] Emitting event: ${evt.type}`)\r\n await stream.writeSSE({ event: evt.type, data: JSON.stringify(evt) })\r\n }\r\n }\r\n\r\n const fallbackEvents = createFallbackMessageDeltaEvents(streamState)\r\n consola.debug(`[stream] Fallback events: ${fallbackEvents.length}, messageDeltaSent: ${streamState.messageDeltaSent}`)\r\n for (const evt of fallbackEvents) {\r\n consola.debug(`[stream] Emitting fallback event: ${evt.type}`)\r\n await stream.writeSSE({ event: evt.type, data: JSON.stringify(evt) })\r\n }\r\n })\r\n }\r\n\r\n // Non-streaming response\r\n const nonStreamPayload = { ...openAIPayload, stream: false }\r\n\r\n const response = isAzureModel\r\n ? ((await createAzureOpenAIChatCompletions(\r\n state.azureOpenAIConfig!,\r\n nonStreamPayload,\r\n )) as ChatCompletionResponse)\r\n : ((await createChatCompletions(nonStreamPayload)) as ChatCompletionResponse)\r\n\r\n if (response.usage) {\r\n setRequestContext(c, {\r\n inputTokens: response.usage.prompt_tokens,\r\n outputTokens: response.usage.completion_tokens,\r\n })\r\n }\r\n\r\n const anthropicResponse = translateToAnthropic(response, anthropicPayload.model)\r\n return c.json(anthropicResponse)\r\n}\r\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCountTokens } from \"./count-tokens-handler\"\nimport { handleCompletion } from \"./handler\"\n\nexport const messageRoutes = new Hono()\n\nmessageRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n return await handleCountTokens(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\nimport { cacheModels } from \"~/lib/utils\"\n\nexport const modelRoutes = new Hono()\n\nmodelRoutes.get(\"/\", async (c) => {\n try {\n if (!state.models) {\n // This should be handled by startup logic, but as a fallback.\n await cacheModels()\n }\n\n // Copilot models\n const copilotModels =\n 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 // Azure OpenAI deployments\n const azureModels =\n state.azureOpenAIDeployments?.map((deployment) => ({\n id: deployment.id,\n object: \"model\",\n type: \"model\",\n created: deployment.created,\n created_at: new Date(deployment.created * 1000).toISOString(),\n owned_by: deployment.owned_by,\n display_name: `${deployment.deploymentName} (${deployment.model})`,\n })) ?? []\n\n const allModels = [...copilotModels, ...azureModels]\n\n return c.json({\n object: \"list\",\n data: allModels,\n has_more: false,\n })\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\r\n\r\nimport {\r\n addReplacement,\r\n clearUserReplacements,\r\n getAllReplacements,\r\n getUserReplacements,\r\n removeReplacement,\r\n toggleReplacement,\r\n updateReplacement,\r\n} from \"~/lib/auto-replace\"\r\n\r\nexport const replacementsRoute = new Hono()\r\n\r\n// Get all replacement rules\r\nreplacementsRoute.get(\"/\", async (c) => {\r\n return c.json({\r\n all: await getAllReplacements(),\r\n user: await getUserReplacements(),\r\n })\r\n})\r\n\r\n// Add a new replacement rule\r\nreplacementsRoute.post(\"/\", async (c) => {\r\n const body = await c.req.json<{\r\n pattern: string\r\n replacement?: string\r\n isRegex?: boolean\r\n name?: string\r\n }>()\r\n\r\n if (!body.pattern) {\r\n return c.json({ error: \"Pattern is required\" }, 400)\r\n }\r\n\r\n const rule = await addReplacement(\r\n body.pattern,\r\n body.replacement ?? \"\",\r\n body.isRegex ?? false,\r\n body.name,\r\n )\r\n\r\n return c.json(rule, 201)\r\n})\r\n\r\n// Delete a replacement rule\r\nreplacementsRoute.delete(\"/:id\", async (c) => {\r\n const id = c.req.param(\"id\")\r\n const success = await removeReplacement(id)\r\n\r\n if (!success) {\r\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\r\n }\r\n\r\n return c.json({ success: true })\r\n})\r\n\r\n// Update a replacement rule\r\nreplacementsRoute.patch(\"/:id\", async (c) => {\r\n const id = c.req.param(\"id\")\r\n const body = await c.req.json<{\r\n name?: string\r\n pattern?: string\r\n replacement?: string\r\n isRegex?: boolean\r\n enabled?: boolean\r\n }>()\r\n\r\n const rule = await updateReplacement(id, body)\r\n\r\n if (!rule) {\r\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\r\n }\r\n\r\n return c.json(rule)\r\n})\r\n\r\n// Toggle a replacement rule\r\nreplacementsRoute.patch(\"/:id/toggle\", async (c) => {\r\n const id = c.req.param(\"id\")\r\n const rule = await toggleReplacement(id)\r\n\r\n if (!rule) {\r\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\r\n }\r\n\r\n return c.json(rule)\r\n})\r\n\r\n// Clear all user replacements\r\nreplacementsRoute.delete(\"/\", async (c) => {\r\n await clearUserReplacements()\r\n return c.json({ success: true })\r\n})\r\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\"\r\nimport { cors } from \"hono/cors\"\r\n\r\nimport { requestLogger } from \"./lib/request-logger\"\r\nimport { completionRoutes } from \"./routes/chat-completions/route\"\r\nimport { embeddingRoutes } from \"./routes/embeddings/route\"\r\nimport { messageRoutes } from \"./routes/messages/route\"\r\nimport { modelRoutes } from \"./routes/models/route\"\r\nimport { replacementsRoute } from \"./routes/replacements/route\"\r\nimport { tokenRoute } from \"./routes/token/route\"\r\nimport { usageRoute } from \"./routes/usage/route\"\r\n\r\nexport const server = new Hono()\r\n\r\nserver.use(requestLogger)\r\nserver.use(cors())\r\n\r\nserver.get(\"/\", (c) => c.text(\"Server running\"))\r\n\r\nserver.route(\"/chat/completions\", completionRoutes)\r\nserver.route(\"/models\", modelRoutes)\r\nserver.route(\"/embeddings\", embeddingRoutes)\r\nserver.route(\"/usage\", usageRoute)\r\nserver.route(\"/token\", tokenRoute)\r\nserver.route(\"/replacements\", replacementsRoute)\r\n\r\n// Compatibility with tools that expect v1/ prefix\r\nserver.route(\"/v1/chat/completions\", completionRoutes)\r\nserver.route(\"/v1/models\", modelRoutes)\r\nserver.route(\"/v1/embeddings\", embeddingRoutes)\r\n\r\n// Anthropic compatible endpoints\r\nserver.route(\"/v1/messages\", messageRoutes)\r\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\nimport { serve, type ServerHandler } from \"srvx\"\nimport invariant from \"tiny-invariant\"\n\nimport packageJson from \"../package.json\" with { type: \"json\" }\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport { setupCopilotToken, setupGitHubToken } from \"./lib/token\"\nimport { cacheModels, cacheVSCodeVersion, setupAzureOpenAI } from \"./lib/utils\"\nimport { server } from \"./server\"\n\ninterface RunServerOptions {\n port: number\n verbose: boolean\n accountType: string\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n proxyEnv: boolean\n insecure: boolean\n debug: boolean\n}\n\nexport async function runServer(options: RunServerOptions): Promise<void> {\n consola.info(`copilot-api v${packageJson.version}`)\n\n if (options.insecure) {\n // Disable SSL certificate verification globally\n process.env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\"\n consola.warn(\"SSL certificate verification disabled (insecure mode)\")\n }\n\n if (options.proxyEnv) {\n initProxyFromEnv()\n }\n\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.accountType = options.accountType\n if (options.accountType !== \"individual\") {\n consola.info(`Using ${options.accountType} plan GitHub account`)\n }\n\n state.manualApprove = options.manual\n state.rateLimitSeconds = options.rateLimit\n state.rateLimitWait = options.rateLimitWait\n state.showToken = options.showToken\n state.debug = options.debug\n\n if (options.debug) {\n consola.info(\"Debug mode enabled - raw HTTP requests will be logged\")\n }\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 // Setup Azure OpenAI (prompt on first run, load from config thereafter)\n await setupAzureOpenAI()\n\n // Build combined model list for display\n const copilotModelIds = state.models?.data.map((model) => model.id) ?? []\n const azureModelIds =\n state.azureOpenAIDeployments?.map((deployment) => deployment.id) ?? []\n const allModelIds = [...copilotModelIds, ...azureModelIds]\n\n consola.info(\n `Available models: \\n${allModelIds.map((id) => `- ${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 const selectedModel = await consola.prompt(\n \"Select a model to use with Claude Code\",\n {\n type: \"select\",\n options: allModelIds,\n },\n )\n\n const selectedSmallModel = await consola.prompt(\n \"Select a small model to use with Claude Code\",\n {\n type: \"select\",\n options: allModelIds,\n },\n )\n\n const command = generateEnvScript(\n {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: \"dummy\",\n ANTHROPIC_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel,\n ANTHROPIC_SMALL_FAST_MODEL: selectedSmallModel,\n ANTHROPIC_DEFAULT_HAIKU_MODEL: selectedSmallModel,\n DISABLE_NON_ESSENTIAL_MODEL_CALLS: \"1\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\n },\n \"claude\",\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 // Increase idle timeout for long-running requests (e.g. Claude Code compact)\n // Bun default is 10s which is too short\n bun: {\n idleTimeout: 255, // max value in seconds (4m 15s)\n },\n })\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the Copilot API server\",\n },\n args: {\n port: {\n alias: \"p\",\n type: \"string\",\n default: \"4141\",\n description: \"Port to listen on\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type to use (individual, business, enterprise)\",\n },\n manual: {\n type: \"boolean\",\n default: false,\n description: \"Enable manual request approval\",\n },\n \"rate-limit\": {\n alias: \"r\",\n type: \"string\",\n description: \"Rate limit in seconds between requests\",\n },\n wait: {\n alias: \"w\",\n type: \"boolean\",\n default: false,\n description:\n \"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set\",\n },\n \"github-token\": {\n alias: \"g\",\n type: \"string\",\n description:\n \"Provide GitHub token directly (must be generated using the `auth` subcommand)\",\n },\n \"claude-code\": {\n alias: \"c\",\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Claude Code with Copilot API config\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub and Copilot tokens on fetch and refresh\",\n },\n \"proxy-env\": {\n type: \"boolean\",\n default: false,\n description: \"Initialize proxy from environment variables\",\n },\n insecure: {\n type: \"boolean\",\n default: false,\n description:\n \"Disable SSL certificate verification (for corporate proxies with self-signed certs)\",\n },\n debug: {\n alias: \"d\",\n type: \"boolean\",\n default: false,\n description: \"Log raw HTTP requests received by the server (headers, method, path)\",\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 return runServer({\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n accountType: args[\"account-type\"],\n manual: args.manual,\n rateLimit,\n rateLimitWait: args.wait,\n githubToken: args[\"github-token\"],\n claudeCode: args[\"claude-code\"],\n showToken: args[\"show-token\"],\n proxyEnv: args[\"proxy-env\"],\n insecure: args.insecure,\n debug: args.debug,\n })\n },\n})\n","#!/usr/bin/env node\r\n\r\nimport { defineCommand, runMain } from \"citty\"\r\n\r\nimport packageJson from \"../package.json\" with { type: \"json\" }\r\n\r\nimport { auth } from \"./auth\"\r\nimport { checkUsage } from \"./check-usage\"\r\nimport { config } from \"./config\"\r\nimport { debug } from \"./debug\"\r\nimport { start } from \"./start\"\r\n\r\nconst main = defineCommand({\r\n meta: {\r\n name: \"copilot-api\",\r\n version: packageJson.version,\r\n description:\r\n \"A wrapper around GitHub Copilot API to make it OpenAI compatible, making it usable for other tools.\",\r\n },\r\n subCommands: { auth, start, \"check-usage\": checkUsage, debug, config },\r\n})\r\n\r\nawait runMain(main)\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"main.js","names":["state: State","state","headers: Record<string, string>","errorJson: unknown","config","config: AzureOpenAIConfig","lastError: Error | undefined","lastResponse: Response | undefined","config","config","errorDetails: string","parsed: unknown","config","token","name","SYSTEM_REPLACEMENTS: Array<ReplacementRule>","userReplacements: Array<ReplacementRule>","rule: ReplacementRule","result","appliedRules: Array<string>","type","name","rule","version","process","commandBlock: string","sanitized: Record<string, unknown>","lines: Array<string>","path","tokenParts: Array<string>","state","x","headers: Record<string, string>","handleCompletion","response","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","chunks: Array<ChatCompletionChunk>","usage: UsageData | null","streamState: AnthropicStreamState","events","packageJson","packageJson"],"sources":["../package.json","../src/lib/paths.ts","../src/lib/state.ts","../src/lib/api-config.ts","../src/lib/error.ts","../src/services/github/get-copilot-token.ts","../src/services/github/get-device-code.ts","../src/services/github/get-user.ts","../src/services/azure-openai/config.ts","../src/lib/retry-fetch.ts","../src/services/azure-openai/create-chat-completions.ts","../src/services/azure-openai/get-models.ts","../src/services/copilot/get-models.ts","../src/services/get-vscode-version.ts","../src/lib/utils.ts","../src/services/github/poll-access-token.ts","../src/lib/token.ts","../src/auth.ts","../src/services/github/get-copilot-usage.ts","../src/check-usage.ts","../src/lib/auto-replace.ts","../src/config.ts","../src/debug.ts","../src/lib/proxy.ts","../src/lib/shell.ts","../src/lib/request-logger.ts","../src/lib/approval.ts","../src/lib/model-resolver.ts","../src/lib/rate-limit.ts","../src/lib/tokenizer.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/count-tokens-handler.ts","../src/routes/messages/stream-translation.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/routes/replacements/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["{\n \"name\": \"@ashsec/copilot-api\",\n \"version\": \"0.7.11\",\n \"description\": \"Turn GitHub Copilot into OpenAI/Anthropic API compatible server. Usable with Claude Code!\",\n \"keywords\": [\n \"proxy\",\n \"github-copilot\",\n \"openai-compatible\"\n ],\n \"homepage\": \"https://github.com/ericc-ch/copilot-api\",\n \"bugs\": \"https://github.com/ericc-ch/copilot-api/issues\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/ericc-ch/copilot-api.git\"\n },\n \"author\": \"Erick Christian <erickchristian48@gmail.com>\",\n \"type\": \"module\",\n \"bin\": {\n \"copilot-api\": \"./dist/main.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsdown\",\n \"dev\": \"bun run --watch ./src/main.ts\",\n \"knip\": \"knip-bun\",\n \"lint\": \"eslint --cache\",\n \"lint:all\": \"eslint --cache .\",\n \"prepack\": \"bun run build\",\n \"prepare\": \"simple-git-hooks\",\n \"release\": \"bumpp && bun publish --access public\",\n \"start\": \"NODE_ENV=production bun run ./src/main.ts\",\n \"typecheck\": \"tsc\"\n },\n \"simple-git-hooks\": {\n \"pre-commit\": \"bunx lint-staged\"\n },\n \"lint-staged\": {\n \"*\": \"bun run lint --fix\"\n },\n \"dependencies\": {\n \"citty\": \"^0.1.6\",\n \"clipboardy\": \"^5.0.0\",\n \"consola\": \"^3.4.2\",\n \"fetch-event-stream\": \"^0.1.5\",\n \"gpt-tokenizer\": \"^3.0.1\",\n \"hono\": \"^4.9.9\",\n \"proxy-from-env\": \"^1.1.0\",\n \"srvx\": \"^0.8.9\",\n \"tiny-invariant\": \"^1.3.3\",\n \"undici\": \"^7.16.0\",\n \"zod\": \"^4.1.11\"\n },\n \"devDependencies\": {\n \"@echristian/eslint-config\": \"^0.0.54\",\n \"@types/bun\": \"^1.2.23\",\n \"@types/proxy-from-env\": \"^1.0.4\",\n \"bumpp\": \"^10.2.3\",\n \"eslint\": \"^9.37.0\",\n \"knip\": \"^5.64.1\",\n \"lint-staged\": \"^16.2.3\",\n \"prettier-plugin-packagejson\": \"^2.5.19\",\n \"simple-git-hooks\": \"^2.13.1\",\n \"tsdown\": \"^0.15.6\",\n \"typescript\": \"^5.9.3\"\n }\n}\n","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 AZURE_OPENAI_CONFIG_PATH = path.join(APP_DIR, \"azure_openai_config\")\nconst REPLACEMENTS_CONFIG_PATH = path.join(APP_DIR, \"replacements.json\")\n\nexport const PATHS = {\n APP_DIR,\n GITHUB_TOKEN_PATH,\n AZURE_OPENAI_CONFIG_PATH,\n REPLACEMENTS_CONFIG_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.AZURE_OPENAI_CONFIG_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 {\n AzureOpenAIConfig,\n AzureOpenAIDeploymentInfo,\n} from \"~/services/azure-openai/types\"\nimport type { ModelsResponse } from \"~/services/copilot/get-models\"\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 debug: boolean\n\n // Rate limiting configuration\n rateLimitSeconds?: number\n lastRequestTimestamp?: number\n\n // Azure OpenAI configuration\n azureOpenAIConfig?: AzureOpenAIConfig\n azureOpenAIDeployments?: Array<AzureOpenAIDeploymentInfo>\n}\n\nexport const state: State = {\n accountType: \"individual\",\n manualApprove: false,\n rateLimitWait: false,\n showToken: false,\n debug: false,\n}\n","import { randomUUID } from \"node:crypto\"\n\nimport type { State } from \"./state\"\n\nexport const standardHeaders = () => ({\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n})\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\nconst API_VERSION = \"2025-04-01\"\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\": \"conversation-panel\",\n \"x-github-api-version\": API_VERSION,\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 requestPayload?: unknown\n\n constructor(message: string, response: Response, requestPayload?: unknown) {\n super(message)\n this.response = response\n this.requestPayload = requestPayload\n }\n}\n\ninterface ContentFilterError {\n error: {\n code: string\n innererror?: {\n code: string\n content_filter_result?: unknown\n }\n }\n}\n\nfunction isContentFilterError(obj: unknown): obj is ContentFilterError {\n return (\n typeof obj === \"object\"\n && obj !== null\n && \"error\" in obj\n && typeof (obj as ContentFilterError).error === \"object\"\n && (obj as ContentFilterError).error.code === \"content_filter\"\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\n // Check for content filter error and log full details\n if (isContentFilterError(errorJson)) {\n consola.box(\"CONTENT FILTER TRIGGERED\")\n consola.error(\"Full error response:\")\n console.log(JSON.stringify(errorJson, null, 2))\n\n if (error.requestPayload) {\n consola.error(\"Request payload that triggered the filter:\")\n console.log(JSON.stringify(error.requestPayload, null, 2))\n }\n }\n\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 const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(state),\n },\n )\n\n if (!response.ok) throw new HTTPError(\"Failed to get Copilot token\", response)\n\n return (await response.json()) as GetCopilotTokenResponse\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\"\n\nexport async function getDeviceCode(): Promise<DeviceCodeResponse> {\n const response = await fetch(`${GITHUB_BASE_URL}/login/device/code`, {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n scope: GITHUB_APP_SCOPES,\n }),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get device code\", response)\n\n return (await response.json()) as DeviceCodeResponse\n}\n\nexport interface DeviceCodeResponse {\n device_code: string\n user_code: string\n verification_uri: string\n expires_in: number\n interval: number\n}\n","import { GITHUB_API_BASE_URL, standardHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport async function getGitHubUser() {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\n ...standardHeaders(),\n },\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get GitHub user\", response)\n\n return (await response.json()) as GithubUserResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GithubUserResponse {\n login: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\n\nimport type { AzureOpenAIConfig } from \"./types\"\n\nexport const AZURE_OPENAI_MODEL_PREFIX = \"azure_openai_\"\n\nexport async function loadAzureOpenAIConfig(): Promise<AzureOpenAIConfig | null> {\n try {\n const content = await fs.readFile(PATHS.AZURE_OPENAI_CONFIG_PATH, \"utf8\")\n if (!content.trim()) {\n return null\n }\n\n const decoded = Buffer.from(content.trim(), \"base64\").toString(\"utf8\")\n const config = JSON.parse(decoded) as AzureOpenAIConfig\n\n if (!config.endpoint || !config.apiKey) {\n return null\n }\n\n return config\n } catch {\n return null\n }\n}\n\nexport async function saveAzureOpenAIConfig(\n config: AzureOpenAIConfig,\n): Promise<void> {\n const encoded = Buffer.from(JSON.stringify(config)).toString(\"base64\")\n await fs.writeFile(PATHS.AZURE_OPENAI_CONFIG_PATH, encoded, \"utf8\")\n await fs.chmod(PATHS.AZURE_OPENAI_CONFIG_PATH, 0o600)\n consola.success(\"Azure OpenAI configuration saved\")\n}\n\nexport async function promptAzureOpenAISetup(): Promise<AzureOpenAIConfig | null> {\n const wantToAdd = await consola.prompt(\n \"Would you like to add a custom Azure OpenAI endpoint?\",\n {\n type: \"confirm\",\n initial: false,\n },\n )\n\n if (!wantToAdd) {\n return null\n }\n\n const endpoint = await consola.prompt(\n \"Enter your Azure OpenAI endpoint URL (e.g., https://your-resource.openai.azure.com):\",\n {\n type: \"text\",\n },\n )\n\n if (!endpoint || typeof endpoint !== \"string\" || !endpoint.trim()) {\n consola.warn(\"No endpoint provided, skipping Azure OpenAI setup\")\n return null\n }\n\n const apiKey = await consola.prompt(\"Enter your Azure OpenAI API key:\", {\n type: \"text\",\n })\n\n if (!apiKey || typeof apiKey !== \"string\" || !apiKey.trim()) {\n consola.warn(\"No API key provided, skipping Azure OpenAI setup\")\n return null\n }\n\n const config: AzureOpenAIConfig = {\n endpoint: endpoint.trim().replace(/\\/$/, \"\"), // Remove trailing slash\n apiKey: apiKey.trim(),\n }\n\n await saveAzureOpenAIConfig(config)\n return config\n}\n\nexport function isAzureOpenAIModel(modelId: string): boolean {\n return modelId.startsWith(AZURE_OPENAI_MODEL_PREFIX)\n}\n\nexport function getAzureDeploymentName(modelId: string): string {\n return modelId.slice(AZURE_OPENAI_MODEL_PREFIX.length)\n}\n","import consola from \"consola\"\n\nimport { sleep } from \"./utils\"\n\n// Fast retry: 100ms, 200ms, 300ms, then stop (max ~600ms total wait)\nconst RETRY_DELAYS_MS = [100, 200, 300]\n\n/**\n * Check if an error is retryable (transient network error)\n */\nfunction isRetryableError(error: unknown): boolean {\n if (!(error instanceof Error)) return false\n\n const message = error.message.toLowerCase()\n const causeMessage =\n error.cause instanceof Error ? error.cause.message.toLowerCase() : \"\"\n\n // Common transient error patterns\n const retryablePatterns = [\n \"fetch failed\",\n \"other side closed\",\n \"connection reset\",\n \"econnreset\",\n \"socket hang up\",\n \"socket connection was closed unexpectedly\",\n \"etimedout\",\n \"econnrefused\",\n \"network error\",\n \"aborted\",\n \"timeout\",\n ]\n\n return retryablePatterns.some(\n (pattern) => message.includes(pattern) || causeMessage.includes(pattern),\n )\n}\n\n/**\n * Check if an HTTP response status is retryable\n */\nfunction isRetryableStatus(status: number): boolean {\n // 4xx client errors (except 400, 401, 403, 404) and 5xx server errors\n // Retry: 408 Timeout, 429 Rate Limit, and all 5xx\n return status === 408 || status === 429 || (status >= 500 && status <= 599)\n}\n\n/**\n * Fetch with automatic fast retry on transient failures\n * Retries with delays: 100ms, 200ms, 300ms (max ~600ms total wait)\n */\nexport async function fetchWithRetry(\n input: string | URL | Request,\n init?: RequestInit,\n): Promise<Response> {\n const maxAttempts = RETRY_DELAYS_MS.length + 1 // 4 total attempts\n\n let lastError: Error | undefined\n let lastResponse: Response | undefined\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n // Force a new connection by adding cache-busting and connection headers\n const headers = new Headers(init?.headers)\n\n // Ensure we're not reusing potentially stale connections\n headers.set(\"Connection\", \"close\")\n\n const response = await fetch(input, {\n ...init,\n headers,\n // Disable keep-alive to force fresh connections on each attempt\n keepalive: false,\n })\n\n // Check for retryable HTTP status codes\n if (isRetryableStatus(response.status) && attempt < maxAttempts - 1) {\n lastResponse = response\n const delayMs = RETRY_DELAYS_MS[attempt]\n consola.warn(\n `HTTP ${response.status} (attempt ${attempt + 1}/${maxAttempts}), retrying in ${delayMs}ms`,\n )\n await sleep(delayMs)\n continue\n }\n\n return response\n } catch (error) {\n lastError = error as Error\n\n if (!isRetryableError(error) || attempt === maxAttempts - 1) {\n throw error\n }\n\n const delayMs = RETRY_DELAYS_MS[attempt]\n consola.warn(\n `Fetch failed (attempt ${attempt + 1}/${maxAttempts}), retrying in ${delayMs}ms:`,\n lastError.message,\n )\n await sleep(delayMs)\n }\n }\n\n // If we exhausted retries due to HTTP status, return the last response\n if (lastResponse) {\n return lastResponse\n }\n\n throw lastError\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport type {\n ChatCompletionResponse,\n ChatCompletionsPayload,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport { HTTPError } from \"~/lib/error\"\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\n\nimport type { AzureOpenAIConfig } from \"./types\"\n\nimport { getAzureDeploymentName } from \"./config\"\n\nconst AZURE_API_VERSION = \"2024-10-21\"\n\nexport async function createAzureOpenAIChatCompletions(\n config: AzureOpenAIConfig,\n payload: ChatCompletionsPayload,\n) {\n // Extract the actual deployment name from the prefixed model ID\n const deploymentName = getAzureDeploymentName(payload.model)\n\n // Convert max_tokens to max_completion_tokens for newer models (GPT-4o, GPT-5, etc.)\n // Azure OpenAI newer models require max_completion_tokens instead of max_tokens\n const { max_tokens, ...restPayload } = payload\n const azurePayload = {\n ...restPayload,\n model: deploymentName,\n ...(max_tokens != null && { max_completion_tokens: max_tokens }),\n }\n\n const response = await fetchWithRetry(\n `${config.endpoint}/openai/deployments/${deploymentName}/chat/completions?api-version=${AZURE_API_VERSION}`,\n {\n method: \"POST\",\n headers: {\n \"api-key\": config.apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(azurePayload),\n },\n )\n\n if (!response.ok) {\n consola.error(\"Failed to create Azure OpenAI chat completions:\", response)\n throw new HTTPError(\n \"Failed to create Azure OpenAI chat completions\",\n response,\n payload,\n )\n }\n\n if (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n}\n","import consola from \"consola\"\n\nimport { HTTPError } from \"~/lib/error\"\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\n\nimport type {\n AzureOpenAIConfig,\n AzureOpenAIDeploymentInfo,\n AzureOpenAIDeploymentsResponse,\n} from \"./types\"\n\nimport { AZURE_OPENAI_MODEL_PREFIX } from \"./config\"\n\n// Different API versions for different endpoints\nconst AZURE_DEPLOYMENTS_API_VERSION = \"2022-12-01\"\n\nexport async function getAzureOpenAIDeployments(\n config: AzureOpenAIConfig,\n): Promise<Array<AzureOpenAIDeploymentInfo>> {\n try {\n const response = await fetchWithRetry(\n `${config.endpoint}/openai/deployments?api-version=${AZURE_DEPLOYMENTS_API_VERSION}`,\n {\n headers: {\n \"api-key\": config.apiKey,\n \"Content-Type\": \"application/json\",\n },\n },\n )\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"\")\n consola.error(\n `Failed to fetch Azure OpenAI deployments: ${response.status}`,\n errorText,\n )\n throw new HTTPError(\"Failed to fetch Azure OpenAI deployments\", response)\n }\n\n const data = (await response.json()) as AzureOpenAIDeploymentsResponse\n\n // Only include deployments that are successfully deployed\n return data.data\n .filter((deployment) => deployment.status === \"succeeded\")\n .map((deployment) => ({\n id: `${AZURE_OPENAI_MODEL_PREFIX}${deployment.id}`,\n deploymentName: deployment.id,\n model: deployment.model,\n created: deployment.created_at,\n object: \"deployment\",\n owned_by: deployment.owner || \"azure-openai\",\n }))\n } catch (error) {\n if (error instanceof HTTPError) {\n throw error\n }\n consola.error(\"Failed to fetch Azure OpenAI deployments:\", error)\n return []\n }\n}\n","import consola from \"consola\"\n\nimport { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\nimport { state } from \"~/lib/state\"\n\nexport const getModels = async () => {\n const url = `${copilotBaseUrl(state)}/models`\n const response = await fetchWithRetry(url, {\n headers: copilotHeaders(state),\n })\n\n if (!response.ok) {\n const errorBody = await response.text()\n let errorDetails: string\n try {\n const parsed: unknown = JSON.parse(errorBody)\n errorDetails = JSON.stringify(parsed, null, 2)\n } catch {\n errorDetails = errorBody || \"(empty response)\"\n }\n consola.error(\n `Failed to get models from ${url}\\n`\n + `Status: ${response.status} ${response.statusText}\\n`\n + `Response: ${errorDetails}`,\n )\n throw new HTTPError(\n `Failed to get models: ${response.status} ${response.statusText}`,\n response,\n )\n }\n\n return (await response.json()) as ModelsResponse\n}\n\nexport interface ModelsResponse {\n data: Array<Model>\n object: string\n}\n\ninterface ModelLimits {\n max_context_window_tokens?: number\n max_output_tokens?: number\n max_prompt_tokens?: number\n max_inputs?: number\n}\n\ninterface ModelSupports {\n tool_calls?: boolean\n parallel_tool_calls?: boolean\n dimensions?: boolean\n}\n\ninterface ModelCapabilities {\n family: string\n limits: ModelLimits\n object: string\n supports: ModelSupports\n tokenizer: string\n type: string\n}\n\nexport interface Model {\n capabilities: ModelCapabilities\n id: string\n model_picker_enabled: boolean\n name: string\n object: string\n preview: boolean\n vendor: string\n version: string\n policy?: {\n state: string\n terms: string\n }\n}\n","const FALLBACK = \"1.104.3\"\n\nexport async function getVSCodeVersion() {\n const controller = new AbortController()\n const timeout = setTimeout(() => {\n controller.abort()\n }, 5000)\n\n try {\n const response = await fetch(\n \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=visual-studio-code-bin\",\n {\n signal: controller.signal,\n },\n )\n\n const pkgbuild = await response.text()\n const pkgverRegex = /pkgver=([0-9.]+)/\n const match = pkgbuild.match(pkgverRegex)\n\n if (match) {\n return match[1]\n }\n\n return FALLBACK\n } catch {\n return FALLBACK\n } finally {\n clearTimeout(timeout)\n }\n}\n\nawait getVSCodeVersion()\n","import consola from \"consola\"\n\nimport {\n getAzureOpenAIDeployments,\n loadAzureOpenAIConfig,\n promptAzureOpenAISetup,\n} from \"~/services/azure-openai\"\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 try {\n const models = await getModels()\n state.models = models\n } catch (error) {\n consola.error(\"Failed to fetch and cache models. This could be due to:\")\n consola.error(\" - Invalid or expired Copilot token\")\n consola.error(\" - Network connectivity issues\")\n consola.error(\" - GitHub Copilot service unavailable\")\n consola.error(\n \" - Account type mismatch (try --account-type=individual or --account-type=business)\",\n )\n throw error\n }\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\nexport async function setupAzureOpenAI(): Promise<void> {\n // Try to load existing config\n let config = await loadAzureOpenAIConfig()\n\n // If no config exists, prompt user on first run\n if (!config) {\n config = await promptAzureOpenAISetup()\n }\n\n if (!config) {\n consola.info(\"Azure OpenAI not configured\")\n return\n }\n\n state.azureOpenAIConfig = config\n consola.info(\"Azure OpenAI configuration loaded\")\n\n // Fetch and cache Azure OpenAI deployments\n try {\n const deployments = await getAzureOpenAIDeployments(config)\n state.azureOpenAIDeployments = deployments\n if (deployments.length > 0) {\n consola.info(\n `Loaded ${deployments.length} Azure OpenAI deployment(s):\\n${deployments.map((d) => `- ${d.id} (${d.model})`).join(\"\\n\")}`,\n )\n } else {\n consola.warn(\"No Azure OpenAI deployments found\")\n }\n } catch (error) {\n consola.warn(\"Failed to fetch Azure OpenAI deployments:\", error)\n }\n}\n","import consola from \"consola\"\n\nimport {\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { sleep } from \"~/lib/utils\"\n\nimport type { DeviceCodeResponse } from \"./get-device-code\"\n\nexport async function pollAccessToken(\n deviceCode: DeviceCodeResponse,\n): Promise<string> {\n // Interval is in seconds, we need to multiply by 1000 to get milliseconds\n // I'm also adding another second, just to be safe\n const sleepDuration = (deviceCode.interval + 1) * 1000\n consola.debug(`Polling access token with interval of ${sleepDuration}ms`)\n\n while (true) {\n const response = await fetch(\n `${GITHUB_BASE_URL}/login/oauth/access_token`,\n {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n device_code: deviceCode.device_code,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n },\n )\n\n if (!response.ok) {\n 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 }\n}\n\ninterface AccessTokenResponse {\n access_token: string\n token_type: string\n scope: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\nimport { getCopilotToken } from \"~/services/github/get-copilot-token\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\nimport { getGitHubUser } from \"~/services/github/get-user\"\nimport { pollAccessToken } from \"~/services/github/poll-access-token\"\n\nimport { HTTPError } from \"./error\"\nimport { state } from \"./state\"\n\nconst readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n\nconst writeGithubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)\n\nexport const setupCopilotToken = async () => {\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n\n // Display the Copilot token to the screen\n consola.debug(\"GitHub Copilot Token fetched successfully!\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n const refreshInterval = (refresh_in - 60) * 1000\n setInterval(async () => {\n consola.debug(\"Refreshing Copilot token\")\n try {\n const { token } = await getCopilotToken()\n state.copilotToken = token\n consola.debug(\"Copilot token refreshed\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n throw error\n }\n }, refreshInterval)\n}\n\ninterface SetupGitHubTokenOptions {\n force?: boolean\n}\n\nexport async function setupGitHubToken(\n options?: SetupGitHubTokenOptions,\n): Promise<void> {\n try {\n const githubToken = await readGithubToken()\n\n if (githubToken && !options?.force) {\n state.githubToken = githubToken\n if (state.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n await logUser()\n\n return\n }\n\n consola.info(\"Not logged in, getting new access token\")\n const response = await getDeviceCode()\n consola.debug(\"Device code response:\", response)\n\n consola.info(\n `Please enter the code \"${response.user_code}\" in ${response.verification_uri}`,\n )\n\n const token = await pollAccessToken(response)\n await writeGithubToken(token)\n state.githubToken = token\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n await logUser()\n } catch (error) {\n if (error instanceof HTTPError) {\n consola.error(\"Failed to get GitHub token:\", await error.response.json())\n throw error\n }\n\n consola.error(\"Failed to get GitHub token:\", error)\n throw error\n }\n}\n\nasync function logUser() {\n const user = await getGitHubUser()\n consola.info(`Logged in as ${user.login}`)\n}\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { PATHS, ensurePaths } from \"./lib/paths\"\nimport { state } from \"./lib/state\"\nimport { setupGitHubToken } from \"./lib/token\"\n\ninterface RunAuthOptions {\n verbose: boolean\n showToken: boolean\n}\n\nexport async function runAuth(options: RunAuthOptions): Promise<void> {\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.showToken = options.showToken\n\n await ensurePaths()\n await setupGitHubToken({ force: true })\n consola.success(\"GitHub token written to\", PATHS.GITHUB_TOKEN_PATH)\n}\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run GitHub auth flow without running the server\",\n },\n args: {\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub token on auth\",\n },\n },\n run({ args }) {\n return runAuth({\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n","import { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotUsage = async (): Promise<CopilotUsageResponse> => {\n const response = await fetch(`${GITHUB_API_BASE_URL}/copilot_internal/user`, {\n headers: githubHeaders(state),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get Copilot usage\", response)\n }\n\n return (await response.json()) as CopilotUsageResponse\n}\n\nexport interface QuotaDetail {\n entitlement: number\n overage_count: number\n overage_permitted: boolean\n percent_remaining: number\n quota_id: string\n quota_remaining: number\n remaining: number\n unlimited: boolean\n}\n\ninterface QuotaSnapshots {\n chat: QuotaDetail\n completions: QuotaDetail\n premium_interactions: QuotaDetail\n}\n\ninterface CopilotUsageResponse {\n access_type_sku: string\n analytics_tracking_id: string\n assigned_date: string\n can_signup_for_limited: boolean\n chat_enabled: boolean\n copilot_plan: string\n organization_login_list: Array<unknown>\n organization_list: Array<unknown>\n quota_reset_date: string\n quota_snapshots: QuotaSnapshots\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { setupGitHubToken } from \"./lib/token\"\nimport {\n getCopilotUsage,\n type QuotaDetail,\n} from \"./services/github/get-copilot-usage\"\n\nexport const checkUsage = defineCommand({\n meta: {\n name: \"check-usage\",\n description: \"Show current GitHub Copilot usage/quota information\",\n },\n async run() {\n await ensurePaths()\n await setupGitHubToken()\n try {\n const usage = await getCopilotUsage()\n const premium = usage.quota_snapshots.premium_interactions\n const premiumTotal = premium.entitlement\n const premiumUsed = premiumTotal - premium.remaining\n const premiumPercentUsed =\n premiumTotal > 0 ? (premiumUsed / premiumTotal) * 100 : 0\n const premiumPercentRemaining = premium.percent_remaining\n\n // Helper to summarize a quota snapshot\n function summarizeQuota(name: string, snap: QuotaDetail | undefined) {\n if (!snap) return `${name}: N/A`\n const total = snap.entitlement\n const used = total - snap.remaining\n const percentUsed = total > 0 ? (used / total) * 100 : 0\n const percentRemaining = snap.percent_remaining\n return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`\n }\n\n const premiumLine = `Premium: ${premiumUsed}/${premiumTotal} used (${premiumPercentUsed.toFixed(1)}% used, ${premiumPercentRemaining.toFixed(1)}% remaining)`\n const chatLine = summarizeQuota(\"Chat\", usage.quota_snapshots.chat)\n const completionsLine = summarizeQuota(\n \"Completions\",\n usage.quota_snapshots.completions,\n )\n\n consola.box(\n `Copilot Usage (plan: ${usage.copilot_plan})\\n`\n + `Quota resets: ${usage.quota_reset_date}\\n`\n + `\\nQuotas:\\n`\n + ` ${premiumLine}\\n`\n + ` ${chatLine}\\n`\n + ` ${completionsLine}`,\n )\n } catch (err) {\n consola.error(\"Failed to fetch Copilot usage:\", err)\n process.exit(1)\n }\n },\n})\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport type { ChatCompletionsPayload } from \"~/services/copilot/create-chat-completions\"\n\nimport { PATHS } from \"./paths\"\n\nexport interface ReplacementRule {\n id: string\n name?: string // Human-readable name/description\n pattern: string\n replacement: string\n isRegex: boolean\n enabled: boolean\n isSystem?: boolean // System rules cannot be deleted by user\n}\n\n// Built-in system replacement that cannot be removed\nconst SYSTEM_REPLACEMENTS: Array<ReplacementRule> = [\n {\n id: \"system-anthropic-billing\",\n name: \"Remove Anthropic billing header\",\n pattern: String.raw`x-anthropic-billing-header:[^\\n]*\\n?`,\n replacement: \"\",\n isRegex: true,\n enabled: true,\n isSystem: true,\n },\n]\n\n// User-configured replacements (loaded from disk)\nlet userReplacements: Array<ReplacementRule> = []\nlet isLoaded = false\n\n/**\n * Load user replacements from disk\n */\nexport async function loadReplacements(): Promise<void> {\n try {\n const data = await fs.readFile(PATHS.REPLACEMENTS_CONFIG_PATH)\n const parsed = JSON.parse(data.toString()) as Array<ReplacementRule>\n userReplacements = parsed.filter((r) => !r.isSystem)\n isLoaded = true\n consola.debug(`Loaded ${userReplacements.length} user replacement rules`)\n } catch {\n // File doesn't exist or is invalid - start with empty array\n userReplacements = []\n isLoaded = true\n }\n}\n\n/**\n * Save user replacements to disk\n */\nexport async function saveReplacements(): Promise<void> {\n try {\n await fs.writeFile(\n PATHS.REPLACEMENTS_CONFIG_PATH,\n JSON.stringify(userReplacements, null, 2),\n \"utf8\",\n )\n consola.debug(`Saved ${userReplacements.length} user replacement rules`)\n } catch (error) {\n consola.error(\"Failed to save replacement rules:\", error)\n throw error\n }\n}\n\n/**\n * Ensure replacements are loaded before accessing\n */\nexport async function ensureLoaded(): Promise<void> {\n if (!isLoaded) {\n await loadReplacements()\n }\n}\n\n/**\n * Get all replacement rules (system + user)\n */\nexport async function getAllReplacements(): Promise<Array<ReplacementRule>> {\n await ensureLoaded()\n return [...SYSTEM_REPLACEMENTS, ...userReplacements]\n}\n\n/**\n * Get only user-configurable replacements\n */\nexport async function getUserReplacements(): Promise<Array<ReplacementRule>> {\n await ensureLoaded()\n return userReplacements\n}\n\n/**\n * Add a new user replacement rule\n */\nexport async function addReplacement(\n pattern: string,\n replacement: string,\n options?: { isRegex?: boolean; name?: string },\n): Promise<ReplacementRule> {\n const { isRegex = false, name } = options ?? {}\n await ensureLoaded()\n const rule: ReplacementRule = {\n id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,\n name,\n pattern,\n replacement,\n isRegex,\n enabled: true,\n isSystem: false,\n }\n userReplacements.push(rule)\n await saveReplacements()\n consola.info(`Added replacement rule: \"${pattern}\" -> \"${replacement}\"`)\n return rule\n}\n\n/**\n * Remove a user replacement rule by ID\n */\nexport async function removeReplacement(id: string): Promise<boolean> {\n await ensureLoaded()\n const rule = userReplacements.find((r) => r.id === id)\n if (!rule) {\n return false\n }\n if (rule.isSystem) {\n consola.warn(\"Cannot remove system replacement rule\")\n return false\n }\n userReplacements = userReplacements.filter((r) => r.id !== id)\n await saveReplacements()\n consola.info(`Removed replacement rule: ${id}`)\n return true\n}\n\n/**\n * Update an existing user replacement rule\n */\nexport async function updateReplacement(\n id: string,\n updates: {\n name?: string\n pattern?: string\n replacement?: string\n isRegex?: boolean\n enabled?: boolean\n },\n): Promise<ReplacementRule | null> {\n await ensureLoaded()\n\n const rule = userReplacements.find((r) => r.id === id)\n if (!rule) {\n return null\n }\n\n if (rule.isSystem) {\n consola.warn(\"Cannot update system replacement rule\")\n return null\n }\n\n if (updates.name !== undefined) rule.name = updates.name\n if (updates.pattern !== undefined) rule.pattern = updates.pattern\n if (updates.replacement !== undefined) rule.replacement = updates.replacement\n if (updates.isRegex !== undefined) rule.isRegex = updates.isRegex\n if (updates.enabled !== undefined) rule.enabled = updates.enabled\n\n await saveReplacements()\n consola.info(`Updated replacement rule: ${rule.name || rule.id}`)\n return rule\n}\n\n/**\n * Toggle a replacement rule on/off\n */\nexport async function toggleReplacement(\n id: string,\n): Promise<ReplacementRule | null> {\n await ensureLoaded()\n // Check user replacements first\n const userRule = userReplacements.find((r) => r.id === id)\n if (userRule) {\n userRule.enabled = !userRule.enabled\n await saveReplacements()\n consola.info(\n `Toggled replacement rule ${id}: ${userRule.enabled ? \"enabled\" : \"disabled\"}`,\n )\n return userRule\n }\n\n // System rules cannot be toggled\n const systemRule = SYSTEM_REPLACEMENTS.find((r) => r.id === id)\n if (systemRule) {\n consola.warn(\"Cannot toggle system replacement rule\")\n return null\n }\n\n return null\n}\n\n/**\n * Clear all user replacements\n */\nexport async function clearUserReplacements(): Promise<void> {\n userReplacements = []\n await saveReplacements()\n consola.info(\"Cleared all user replacement rules\")\n}\n\n/**\n * Apply a single replacement rule to text and return info about whether it matched\n */\nfunction applyRule(\n text: string,\n rule: ReplacementRule,\n): { result: string; matched: boolean } {\n if (!rule.enabled) return { result: text, matched: false }\n\n if (rule.isRegex) {\n try {\n const regex = new RegExp(rule.pattern, \"g\")\n const result = text.replace(regex, rule.replacement)\n return { result, matched: result !== text }\n } catch {\n consola.warn(`Invalid regex pattern in rule ${rule.id}: ${rule.pattern}`)\n return { result: text, matched: false }\n }\n }\n\n const result = text.split(rule.pattern).join(rule.replacement)\n return { result, matched: result !== text }\n}\n\n/**\n * Apply all replacement rules to text\n */\nexport async function applyReplacements(text: string): Promise<string> {\n let result = text\n const allRules = await getAllReplacements()\n const appliedRules: Array<string> = []\n\n for (const rule of allRules) {\n const { result: newResult, matched } = applyRule(result, rule)\n if (matched) {\n result = newResult\n appliedRules.push(rule.name || rule.id)\n }\n }\n\n if (appliedRules.length > 0) {\n consola.info(`Replacements applied: ${appliedRules.join(\", \")}`)\n }\n\n return result\n}\n\n/**\n * Apply replacements to a chat completions payload\n * This modifies message content in place\n */\nexport async function applyReplacementsToPayload(\n payload: ChatCompletionsPayload,\n): Promise<ChatCompletionsPayload> {\n const processedMessages = await Promise.all(\n payload.messages.map(async (message) => {\n if (typeof message.content === \"string\") {\n return {\n ...message,\n content: await applyReplacements(message.content),\n }\n }\n\n // Handle array content (multimodal)\n if (Array.isArray(message.content)) {\n return {\n ...message,\n content: await Promise.all(\n message.content.map(async (part) => {\n if (\n typeof part === \"object\"\n && part.type === \"text\"\n && part.text\n ) {\n return {\n ...part,\n text: await applyReplacements(part.text),\n }\n }\n return part\n }),\n ),\n }\n }\n\n return message\n }),\n )\n\n return {\n ...payload,\n messages: processedMessages,\n }\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport {\n addReplacement,\n applyReplacements,\n clearUserReplacements,\n getAllReplacements,\n getUserReplacements,\n removeReplacement,\n toggleReplacement,\n updateReplacement,\n type ReplacementRule,\n} from \"~/lib/auto-replace\"\nimport { ensurePaths, PATHS } from \"~/lib/paths\"\n\ntype MenuAction =\n | \"list\"\n | \"add\"\n | \"edit\"\n | \"remove\"\n | \"toggle\"\n | \"test\"\n | \"clear\"\n | \"exit\"\n\nfunction formatRule(rule: ReplacementRule, index: number): string {\n const status = rule.enabled ? \"✓\" : \"✗\"\n const type = rule.isRegex ? \"regex\" : \"string\"\n const system = rule.isSystem ? \" [system]\" : \"\"\n const name = rule.name ? ` \"${rule.name}\"` : \"\"\n const replacement = rule.replacement || \"(empty)\"\n return `${index + 1}. [${status}] (${type})${system}${name} \"${rule.pattern}\" → \"${replacement}\"`\n}\n\nasync function listReplacements(): Promise<void> {\n const all = await getAllReplacements()\n\n if (all.length === 0) {\n consola.info(\"No replacement rules configured.\")\n return\n }\n\n consola.info(\"\\n📋 Replacement Rules:\\n\")\n for (const [i, element] of all.entries()) {\n console.log(formatRule(element, i))\n }\n console.log()\n}\n\nasync function addNewReplacement(): Promise<void> {\n const name = await consola.prompt(\"Name (optional, short description):\", {\n type: \"text\",\n default: \"\",\n })\n\n if (typeof name === \"symbol\") {\n consola.info(\"Cancelled.\")\n return\n }\n\n const matchType = await consola.prompt(\"Match type:\", {\n type: \"select\",\n options: [\n { label: \"String (exact match)\", value: \"string\" },\n { label: \"Regex (regular expression)\", value: \"regex\" },\n ],\n })\n\n if (typeof matchType === \"symbol\") {\n consola.info(\"Cancelled.\")\n return\n }\n\n const pattern = await consola.prompt(\"Pattern to match:\", {\n type: \"text\",\n })\n\n if (typeof pattern === \"symbol\" || !pattern) {\n consola.info(\"Cancelled.\")\n return\n }\n\n // Validate regex if needed\n if (matchType === \"regex\") {\n try {\n new RegExp(pattern)\n } catch {\n consola.error(`Invalid regex pattern: ${pattern}`)\n return\n }\n }\n\n const replacement = await consola.prompt(\n \"Replacement text (leave empty to delete matches):\",\n {\n type: \"text\",\n default: \"\",\n },\n )\n\n if (typeof replacement === \"symbol\") {\n consola.info(\"Cancelled.\")\n return\n }\n\n const rule = await addReplacement(\n pattern,\n replacement,\n matchType === \"regex\",\n name || undefined,\n )\n\n consola.success(`Added rule: ${rule.name || rule.id}`)\n}\n\nasync function editExistingReplacement(): Promise<void> {\n const userRules = await getUserReplacements()\n\n if (userRules.length === 0) {\n consola.info(\"No user rules to edit.\")\n return\n }\n\n const options = userRules.map((rule, i) => ({\n label: formatRule(rule, i),\n value: rule.id,\n }))\n\n const selected = await consola.prompt(\"Select rule to edit:\", {\n type: \"select\",\n options,\n })\n\n if (typeof selected === \"symbol\") {\n consola.info(\"Cancelled.\")\n return\n }\n\n const rule = userRules.find((r) => r.id === selected)\n if (!rule) {\n consola.error(\"Rule not found.\")\n return\n }\n\n consola.info(`\\nEditing rule: ${rule.name || rule.id}`)\n consola.info(\"Press Enter to keep current value.\\n\")\n\n const name = await consola.prompt(\"Name:\", {\n type: \"text\",\n default: rule.name || \"\",\n })\n\n if (typeof name === \"symbol\") {\n consola.info(\"Cancelled.\")\n return\n }\n\n const matchType = await consola.prompt(\"Match type:\", {\n type: \"select\",\n options: [\n { label: \"String (exact match)\", value: \"string\" },\n { label: \"Regex (regular expression)\", value: \"regex\" },\n ],\n initial: rule.isRegex ? \"regex\" : \"string\",\n })\n\n if (typeof matchType === \"symbol\") {\n consola.info(\"Cancelled.\")\n return\n }\n\n const pattern = await consola.prompt(\"Pattern to match:\", {\n type: \"text\",\n default: rule.pattern,\n })\n\n if (typeof pattern === \"symbol\" || !pattern) {\n consola.info(\"Cancelled.\")\n return\n }\n\n // Validate regex if needed\n if (matchType === \"regex\") {\n try {\n new RegExp(pattern)\n } catch {\n consola.error(`Invalid regex pattern: ${pattern}`)\n return\n }\n }\n\n const replacement = await consola.prompt(\"Replacement text:\", {\n type: \"text\",\n default: rule.replacement,\n })\n\n if (typeof replacement === \"symbol\") {\n consola.info(\"Cancelled.\")\n return\n }\n\n const updated = await updateReplacement(selected, {\n name: name || undefined,\n pattern,\n replacement,\n isRegex: matchType === \"regex\",\n })\n\n if (updated) {\n consola.success(`Updated rule: ${updated.name || updated.id}`)\n } else {\n consola.error(\"Failed to update rule.\")\n }\n}\n\nasync function removeExistingReplacement(): Promise<void> {\n const userRules = await getUserReplacements()\n\n if (userRules.length === 0) {\n consola.info(\"No user rules to remove.\")\n return\n }\n\n const options = userRules.map((rule, i) => ({\n label: formatRule(rule, i),\n value: rule.id,\n }))\n\n const selected = await consola.prompt(\"Select rule to remove:\", {\n type: \"select\",\n options,\n })\n\n if (typeof selected === \"symbol\") {\n consola.info(\"Cancelled.\")\n return\n }\n\n const success = await removeReplacement(selected)\n if (success) {\n consola.success(\"Rule removed.\")\n } else {\n consola.error(\"Failed to remove rule.\")\n }\n}\n\nasync function toggleExistingReplacement(): Promise<void> {\n const userRules = await getUserReplacements()\n\n if (userRules.length === 0) {\n consola.info(\"No user rules to toggle.\")\n return\n }\n\n const options = userRules.map((rule, i) => ({\n label: formatRule(rule, i),\n value: rule.id,\n }))\n\n const selected = await consola.prompt(\"Select rule to toggle:\", {\n type: \"select\",\n options,\n })\n\n if (typeof selected === \"symbol\") {\n consola.info(\"Cancelled.\")\n return\n }\n\n const rule = await toggleReplacement(selected)\n if (rule) {\n consola.success(`Rule ${rule.enabled ? \"enabled\" : \"disabled\"}.`)\n } else {\n consola.error(\"Failed to toggle rule.\")\n }\n}\n\nasync function testReplacements(): Promise<void> {\n const testText = await consola.prompt(\"Enter text to test replacements:\", {\n type: \"text\",\n })\n\n if (typeof testText === \"symbol\" || !testText) {\n consola.info(\"Cancelled.\")\n return\n }\n\n const result = await applyReplacements(testText)\n\n consola.info(\"\\n📝 Original:\")\n console.log(testText)\n consola.info(\"\\n✨ After replacements:\")\n console.log(result)\n console.log()\n}\n\nasync function clearAllReplacements(): Promise<void> {\n const confirm = await consola.prompt(\n \"Are you sure you want to clear all user replacements?\",\n {\n type: \"confirm\",\n initial: false,\n },\n )\n\n if (confirm) {\n await clearUserReplacements()\n consola.success(\"All user replacements cleared.\")\n } else {\n consola.info(\"Cancelled.\")\n }\n}\n\nasync function mainMenu(): Promise<void> {\n consola.info(`\\n🔧 Copilot API - Replacement Configuration`)\n consola.info(`Config file: ${PATHS.REPLACEMENTS_CONFIG_PATH}\\n`)\n\n let running = true\n\n while (running) {\n const action = await consola.prompt(\"What would you like to do?\", {\n type: \"select\",\n options: [\n { label: \"📋 List all rules\", value: \"list\" as MenuAction },\n { label: \"➕ Add new rule\", value: \"add\" as MenuAction },\n { label: \"✏️ Edit rule\", value: \"edit\" as MenuAction },\n { label: \"➖ Remove rule\", value: \"remove\" as MenuAction },\n { label: \"🔄 Toggle rule on/off\", value: \"toggle\" as MenuAction },\n { label: \"🧪 Test replacements\", value: \"test\" as MenuAction },\n { label: \"🗑️ Clear all user rules\", value: \"clear\" as MenuAction },\n { label: \"🚪 Exit\", value: \"exit\" as MenuAction },\n ],\n })\n\n if (typeof action === \"symbol\") {\n break\n }\n\n switch (action) {\n case \"list\": {\n await listReplacements()\n break\n }\n case \"add\": {\n await addNewReplacement()\n break\n }\n case \"edit\": {\n await editExistingReplacement()\n break\n }\n case \"remove\": {\n await removeExistingReplacement()\n break\n }\n case \"toggle\": {\n await toggleExistingReplacement()\n break\n }\n case \"test\": {\n await testReplacements()\n break\n }\n case \"clear\": {\n await clearAllReplacements()\n break\n }\n case \"exit\": {\n running = false\n break\n }\n default: {\n break\n }\n }\n }\n\n consola.info(\"Goodbye! 👋\")\n}\n\nexport const config = defineCommand({\n meta: {\n name: \"config\",\n description: \"Configure replacement rules interactively\",\n },\n run: async () => {\n await ensurePaths()\n await mainMenu()\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\nimport fs from \"node:fs/promises\"\nimport os from \"node:os\"\n\nimport { PATHS } from \"./lib/paths\"\n\ninterface DebugInfo {\n version: string\n runtime: {\n name: string\n version: string\n platform: string\n arch: string\n }\n paths: {\n APP_DIR: string\n GITHUB_TOKEN_PATH: string\n }\n tokenExists: boolean\n}\n\ninterface RunDebugOptions {\n json: boolean\n}\n\nasync function getPackageVersion(): Promise<string> {\n try {\n const packageJsonPath = new URL(\"../package.json\", import.meta.url).pathname\n // @ts-expect-error https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v59.0.1/docs/rules/prefer-json-parse-buffer.md\n // JSON.parse() can actually parse buffers\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath)) as {\n version: string\n }\n return packageJson.version\n } catch {\n return \"unknown\"\n }\n}\n\nfunction getRuntimeInfo() {\n const isBun = typeof Bun !== \"undefined\"\n\n return {\n name: isBun ? \"bun\" : \"node\",\n version: isBun ? Bun.version : process.version.slice(1),\n platform: os.platform(),\n arch: os.arch(),\n }\n}\n\nasync function checkTokenExists(): Promise<boolean> {\n try {\n const stats = await fs.stat(PATHS.GITHUB_TOKEN_PATH)\n if (!stats.isFile()) return false\n\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim().length > 0\n } catch {\n return false\n }\n}\n\nasync function getDebugInfo(): Promise<DebugInfo> {\n const [version, tokenExists] = await Promise.all([\n getPackageVersion(),\n checkTokenExists(),\n ])\n\n return {\n version,\n runtime: getRuntimeInfo(),\n paths: {\n APP_DIR: PATHS.APP_DIR,\n GITHUB_TOKEN_PATH: PATHS.GITHUB_TOKEN_PATH,\n },\n tokenExists,\n }\n}\n\nfunction printDebugInfoPlain(info: DebugInfo): void {\n consola.info(`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 consola from \"consola\"\nimport { getProxyForUrl } from \"proxy-from-env\"\nimport { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from \"undici\"\n\nexport function initProxyFromEnv(): void {\n if (typeof Bun !== \"undefined\") return\n\n try {\n const direct = new Agent()\n const proxies = new Map<string, ProxyAgent>()\n\n // We only need a minimal dispatcher that implements `dispatch` at runtime.\n // Typing the object as `Dispatcher` forces TypeScript to require many\n // additional methods. Instead, keep a plain object and cast when passing\n // to `setGlobalDispatcher`.\n const dispatcher = {\n dispatch(\n options: Dispatcher.DispatchOptions,\n handler: Dispatcher.DispatchHandler,\n ) {\n try {\n const origin =\n typeof options.origin === \"string\" ?\n new URL(options.origin)\n : (options.origin as URL)\n const get = getProxyForUrl as unknown as (\n u: string,\n ) => string | undefined\n const raw = get(origin.toString())\n const proxyUrl = raw && raw.length > 0 ? raw : undefined\n if (!proxyUrl) {\n consola.debug(`HTTP proxy bypass: ${origin.hostname}`)\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n let agent = proxies.get(proxyUrl)\n if (!agent) {\n agent = new ProxyAgent(proxyUrl)\n proxies.set(proxyUrl, agent)\n }\n let label = proxyUrl\n try {\n const u = new URL(proxyUrl)\n label = `${u.protocol}//${u.host}`\n } catch {\n /* noop */\n }\n consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`)\n return (agent as unknown as Dispatcher).dispatch(options, handler)\n } catch {\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n },\n close() {\n return direct.close()\n },\n destroy() {\n return direct.destroy()\n },\n }\n\n setGlobalDispatcher(dispatcher as unknown as Dispatcher)\n consola.debug(\"HTTP proxy configured from environment (per-URL)\")\n } catch (err) {\n consola.debug(\"Proxy setup skipped:\", err)\n }\n}\n","import { 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 { state } from \"./state\"\n\n/**\n * Request context stored for logging on response\n */\nexport interface RequestContext {\n startTime: number\n model?: string\n inputTokens?: number\n outputTokens?: number\n provider?: \"Copilot\" | \"Azure OpenAI\"\n}\n\nconst REQUEST_CONTEXT_KEY = \"requestContext\"\n\n// ANSI color codes\nconst colors = {\n reset: \"\\x1b[0m\",\n dim: \"\\x1b[2m\",\n bold: \"\\x1b[1m\",\n cyan: \"\\x1b[36m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n red: \"\\x1b[31m\",\n magenta: \"\\x1b[35m\",\n blue: \"\\x1b[34m\",\n white: \"\\x1b[37m\",\n gray: \"\\x1b[90m\",\n}\n\n/**\n * Get the current time formatted as HH:MM:SS\n */\nfunction getTimeString(): string {\n return new Date().toLocaleTimeString(\"en-US\", {\n hour12: false,\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n })\n}\n\n/**\n * Get status color based on HTTP status code\n */\nfunction getStatusColor(status: number): string {\n if (status >= 500) return colors.red\n if (status >= 400) return colors.yellow\n if (status >= 300) return colors.cyan\n return colors.green\n}\n\n/**\n * Sanitize request body by omitting large message/prompt arrays\n */\nfunction sanitizeRequestBody(\n parsed: Record<string, unknown>,\n): Record<string, unknown> {\n const sanitized: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(parsed)) {\n sanitized[key] =\n key === \"messages\" || key === \"prompt\" ?\n `[${Array.isArray(value) ? value.length : 1} items omitted]`\n : value\n }\n return sanitized\n}\n\n/**\n * Log raw HTTP request details (for debug mode)\n */\nasync function logRawRequest(c: Context): Promise<void> {\n const method = c.req.method\n const url = c.req.url\n const headers = Object.fromEntries(c.req.raw.headers.entries())\n\n const lines: Array<string> = []\n lines.push(\n `${colors.magenta}${colors.bold}[DEBUG] Incoming Request${colors.reset}`,\n `${colors.cyan}${method}${colors.reset} ${url}`,\n `${colors.dim}Headers:${colors.reset}`,\n )\n\n for (const [key, value] of Object.entries(headers)) {\n // Mask authorization headers\n const displayValue =\n key.toLowerCase().includes(\"authorization\") ?\n `${value.slice(0, 20)}...`\n : value\n lines.push(` ${colors.gray}${key}:${colors.reset} ${displayValue}`)\n }\n\n // Try to get body info without consuming it\n if (method !== \"GET\" && method !== \"HEAD\") {\n try {\n const clonedRequest = c.req.raw.clone()\n const body = await clonedRequest.text()\n if (body) {\n // Parse JSON to extract model, omit messages/prompt\n try {\n const parsed = JSON.parse(body) as Record<string, unknown>\n const sanitized = sanitizeRequestBody(parsed)\n\n lines.push(\n `${colors.dim}Body (sanitized):${colors.reset}`,\n ` ${JSON.stringify(sanitized, null, 2).split(\"\\n\").join(\"\\n \")}`,\n )\n } catch {\n // Not JSON, show length\n lines.push(`${colors.dim}Body:${colors.reset} [${body.length} bytes]`)\n }\n }\n } catch {\n lines.push(`${colors.dim}Body:${colors.reset} [unable to read]`)\n }\n }\n\n lines.push(`${colors.dim}${\"─\".repeat(60)}${colors.reset}`)\n console.log(lines.join(\"\\n\"))\n}\n\n/**\n * Set request context for logging\n */\nexport function setRequestContext(\n c: Context,\n ctx: Partial<Omit<RequestContext, \"startTime\">>,\n): void {\n const existing = c.get(REQUEST_CONTEXT_KEY) as RequestContext | undefined\n if (existing) {\n c.set(REQUEST_CONTEXT_KEY, { ...existing, ...ctx })\n }\n}\n\n/**\n * Custom request logger middleware\n */\nexport async function requestLogger(c: Context, next: Next): Promise<void> {\n // Log raw request in debug mode\n if (state.debug) {\n await logRawRequest(c)\n }\n\n const startTime = Date.now()\n const method = c.req.method\n const path =\n c.req.path\n + (c.req.raw.url.includes(\"?\") ? \"?\" + c.req.raw.url.split(\"?\")[1] : \"\")\n\n // Initialize request context\n c.set(REQUEST_CONTEXT_KEY, { startTime } as RequestContext)\n\n await next()\n\n // Get context that may have been set during request handling\n const ctx = c.get(REQUEST_CONTEXT_KEY) as RequestContext | undefined\n const duration = ((Date.now() - startTime) / 1000).toFixed(1)\n const status = c.res.status\n const statusColor = getStatusColor(status)\n\n // Build the log block\n const lines: Array<string> = []\n\n // Separator\n lines.push(`${colors.dim}${\"─\".repeat(60)}${colors.reset}`)\n\n // Main request line: method, path, status, duration\n const statusBadge = `${statusColor}${status}${colors.reset}`\n const durationStr = `${colors.cyan}${duration}s${colors.reset}`\n lines.push(\n `${colors.bold}${method}${colors.reset} ${path} ${statusBadge} ${durationStr}`,\n )\n\n // Provider and model info\n if (ctx?.provider && ctx.model) {\n const providerColor =\n ctx.provider === \"Azure OpenAI\" ? colors.blue : colors.magenta\n lines.push(\n ` ${colors.gray}Provider:${colors.reset} ${providerColor}${ctx.provider}${colors.reset} ${colors.gray}->${colors.reset} ${colors.white}${ctx.model}${colors.reset}`,\n )\n }\n\n // Token info\n if (ctx?.inputTokens !== undefined || ctx?.outputTokens !== undefined) {\n const tokenParts: Array<string> = []\n if (ctx.inputTokens !== undefined) {\n tokenParts.push(\n `${colors.gray}Input:${colors.reset} ${colors.yellow}${ctx.inputTokens.toLocaleString()}${colors.reset}`,\n )\n }\n if (ctx.outputTokens !== undefined) {\n tokenParts.push(\n `${colors.gray}Output:${colors.reset} ${colors.green}${ctx.outputTokens.toLocaleString()}${colors.reset}`,\n )\n }\n lines.push(` ${tokenParts.join(\" \")}`)\n }\n\n // Timestamp\n lines.push(` ${colors.dim}${getTimeString()}${colors.reset}`)\n\n // Print all lines\n console.log(lines.join(\"\\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","/**\n * Normalize a model name by converting dashes to dots between numbers.\n * e.g., \"claude-opus-4-5\" -> \"claude-opus-4.5\"\n * \"gpt-4-1\" -> \"gpt-4.1\"\n * \"gpt-5-1-codex\" -> \"gpt-5.1-codex\"\n */\nexport function normalizeModelName(model: string): string {\n // Replace dash with dot only between two digits: \"4-5\" -> \"4.5\"\n return model.replaceAll(/(\\d)-(\\d)/g, (_, p1, p2) => `${p1}.${p2}`)\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 type {\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\nimport type { Model } from \"~/services/copilot/get-models\"\n\n// Encoder type mapping\nconst ENCODING_MAP = {\n o200k_base: () => import(\"gpt-tokenizer/encoding/o200k_base\"),\n cl100k_base: () => import(\"gpt-tokenizer/encoding/cl100k_base\"),\n p50k_base: () => import(\"gpt-tokenizer/encoding/p50k_base\"),\n p50k_edit: () => import(\"gpt-tokenizer/encoding/p50k_edit\"),\n r50k_base: () => import(\"gpt-tokenizer/encoding/r50k_base\"),\n} as const\n\ntype SupportedEncoding = keyof typeof ENCODING_MAP\n\n// Define encoder interface\ninterface Encoder {\n encode: (text: string) => Array<number>\n}\n\n// Cache loaded encoders to avoid repeated imports\nconst encodingCache = new Map<string, Encoder>()\n\n/**\n * Calculate tokens for tool calls\n */\nconst calculateToolCallsTokens = (\n toolCalls: Array<ToolCall>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = 0\n for (const toolCall of toolCalls) {\n tokens += constants.funcInit\n tokens += encoder.encode(JSON.stringify(toolCall)).length\n }\n tokens += constants.funcEnd\n return tokens\n}\n\n/**\n * Calculate tokens for content parts\n */\nconst calculateContentPartsTokens = (\n contentParts: Array<ContentPart>,\n encoder: Encoder,\n): number => {\n let tokens = 0\n for (const part of contentParts) {\n if (part.type === \"image_url\") {\n tokens += encoder.encode(part.image_url.url).length + 85\n } else if (part.text) {\n tokens += encoder.encode(part.text).length\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens for a single message\n */\nconst calculateMessageTokens = (\n message: Message,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n const tokensPerMessage = 3\n const tokensPerName = 1\n let tokens = tokensPerMessage\n for (const [key, value] of Object.entries(message)) {\n if (typeof value === \"string\") {\n tokens += encoder.encode(value).length\n }\n if (key === \"name\") {\n tokens += tokensPerName\n }\n if (key === \"tool_calls\") {\n tokens += calculateToolCallsTokens(\n value as Array<ToolCall>,\n encoder,\n constants,\n )\n }\n if (key === \"content\" && Array.isArray(value)) {\n tokens += calculateContentPartsTokens(\n value as Array<ContentPart>,\n encoder,\n )\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens using custom algorithm\n */\nconst calculateTokens = (\n messages: Array<Message>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (messages.length === 0) {\n return 0\n }\n let numTokens = 0\n for (const message of messages) {\n numTokens += calculateMessageTokens(message, encoder, constants)\n }\n // every reply is primed with <|start|>assistant<|message|>\n numTokens += 3\n return numTokens\n}\n\n/**\n * Get the corresponding encoder module based on encoding type\n */\nconst getEncodeChatFunction = async (encoding: string): Promise<Encoder> => {\n if (encodingCache.has(encoding)) {\n const cached = encodingCache.get(encoding)\n if (cached) {\n return cached\n }\n }\n\n const supportedEncoding = encoding as SupportedEncoding\n if (!(supportedEncoding in ENCODING_MAP)) {\n const fallbackModule = (await ENCODING_MAP.o200k_base()) as Encoder\n encodingCache.set(encoding, fallbackModule)\n return fallbackModule\n }\n\n const encodingModule = (await ENCODING_MAP[supportedEncoding]()) as Encoder\n encodingCache.set(encoding, encodingModule)\n return encodingModule\n}\n\n/**\n * Get tokenizer type from model information\n */\nexport const getTokenizerFromModel = (model: Model): string => {\n return model.capabilities.tokenizer || \"o200k_base\"\n}\n\n/**\n * Get model-specific constants for token calculation\n */\nconst getModelConstants = (model: Model) => {\n return model.id === \"gpt-3.5-turbo\" || model.id === \"gpt-4\" ?\n {\n funcInit: 10,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n : {\n funcInit: 7,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n}\n\n/**\n * Calculate tokens for a single parameter\n */\nconst calculateParameterTokens = (\n key: string,\n prop: unknown,\n context: {\n encoder: Encoder\n constants: ReturnType<typeof getModelConstants>\n },\n): number => {\n const { encoder, constants } = context\n let tokens = constants.propKey\n\n // Early return if prop is not an object\n if (typeof prop !== \"object\" || prop === null) {\n return tokens\n }\n\n // Type assertion for parameter properties\n const param = prop as {\n type?: string\n description?: string\n enum?: Array<unknown>\n [key: string]: unknown\n }\n\n const paramName = key\n const paramType = param.type || \"string\"\n let paramDesc = param.description || \"\"\n\n // Handle enum values\n if (param.enum && Array.isArray(param.enum)) {\n tokens += constants.enumInit\n for (const item of param.enum) {\n tokens += constants.enumItem\n tokens += encoder.encode(String(item)).length\n }\n }\n\n // Clean up description\n if (paramDesc.endsWith(\".\")) {\n paramDesc = paramDesc.slice(0, -1)\n }\n\n // Encode the main parameter line\n const line = `${paramName}:${paramType}:${paramDesc}`\n tokens += encoder.encode(line).length\n\n // Handle additional properties (excluding standard ones)\n const excludedKeys = new Set([\"type\", \"description\", \"enum\"])\n for (const propertyName of Object.keys(param)) {\n if (!excludedKeys.has(propertyName)) {\n const propertyValue = param[propertyName]\n const propertyText =\n typeof propertyValue === \"string\" ? propertyValue : (\n JSON.stringify(propertyValue)\n )\n tokens += encoder.encode(`${propertyName}:${propertyText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for function parameters\n */\nconst calculateParametersTokens = (\n parameters: unknown,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (!parameters || typeof parameters !== \"object\") {\n return 0\n }\n\n const params = parameters as Record<string, unknown>\n let tokens = 0\n\n for (const [key, value] of Object.entries(params)) {\n if (key === \"properties\") {\n const properties = value as Record<string, unknown>\n if (Object.keys(properties).length > 0) {\n tokens += constants.propInit\n for (const propKey of Object.keys(properties)) {\n tokens += calculateParameterTokens(propKey, properties[propKey], {\n encoder,\n constants,\n })\n }\n }\n } else {\n const paramText =\n typeof value === \"string\" ? value : JSON.stringify(value)\n tokens += encoder.encode(`${key}:${paramText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for a single tool\n */\nconst calculateToolTokens = (\n tool: Tool,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = constants.funcInit\n const func = tool.function\n const fName = func.name\n let fDesc = func.description || \"\"\n if (fDesc.endsWith(\".\")) {\n fDesc = fDesc.slice(0, -1)\n }\n const line = fName + \":\" + fDesc\n tokens += encoder.encode(line).length\n if (\n typeof func.parameters === \"object\" // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n && func.parameters !== null\n ) {\n tokens += calculateParametersTokens(func.parameters, encoder, constants)\n }\n return tokens\n}\n\n/**\n * Calculate token count for tools based on model\n */\nexport const numTokensForTools = (\n tools: Array<Tool>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let funcTokenCount = 0\n for (const tool of tools) {\n funcTokenCount += calculateToolTokens(tool, encoder, constants)\n }\n funcTokenCount += constants.funcEnd\n return funcTokenCount\n}\n\n/**\n * Calculate the token count of messages, supporting multiple GPT encoders\n */\nexport const getTokenCount = async (\n payload: ChatCompletionsPayload,\n model: Model,\n): Promise<{ input: number; output: number }> => {\n // Get tokenizer string\n const tokenizer = getTokenizerFromModel(model)\n\n // Get corresponding encoder module\n const encoder = await getEncodeChatFunction(tokenizer)\n\n const simplifiedMessages = payload.messages\n const inputMessages = simplifiedMessages.filter(\n (msg) => msg.role !== \"assistant\",\n )\n const outputMessages = simplifiedMessages.filter(\n (msg) => msg.role === \"assistant\",\n )\n\n const constants = getModelConstants(model)\n let inputTokens = calculateTokens(inputMessages, encoder, constants)\n if (payload.tools && payload.tools.length > 0) {\n inputTokens += numTokensForTools(payload.tools, encoder, constants)\n }\n const outputTokens = calculateTokens(outputMessages, encoder, constants)\n\n return {\n input: inputTokens,\n output: outputTokens,\n }\n}\n\n/**\n * Estimate token count for a payload without model info (uses o200k_base encoding)\n * This is a rough estimate used when we don't have model-specific info\n */\nexport const estimateTokenCount = async (\n payload: ChatCompletionsPayload,\n): Promise<number> => {\n const encoder = await getEncodeChatFunction(\"o200k_base\")\n\n // Simple estimation: encode all message content\n let tokens = 0\n for (const message of payload.messages) {\n // 3 tokens per message overhead\n tokens += 3\n\n if (typeof message.content === \"string\") {\n tokens += encoder.encode(message.content).length\n } else if (Array.isArray(message.content)) {\n for (const part of message.content) {\n if (part.type === \"text\" && part.text) {\n tokens += encoder.encode(part.text).length\n } else if (part.type === \"image_url\") {\n // Rough estimate for images\n tokens += 85\n }\n }\n }\n\n // Add role tokens\n if (message.role) {\n tokens += encoder.encode(message.role).length\n }\n\n // Tool calls in messages (assistant responses with tool use)\n if (message.tool_calls) {\n tokens += encoder.encode(JSON.stringify(message.tool_calls)).length\n }\n }\n\n // Add tool definitions if present (but don't double count - use simplified estimate)\n // Tool definitions add overhead but the full JSON stringify overcounts\n if (payload.tools && payload.tools.length > 0) {\n // Estimate ~50 tokens per tool on average for function name + description + params\n tokens += payload.tools.length * 50\n }\n\n // Priming tokens\n tokens += 3\n\n return tokens\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\nimport { state } from \"~/lib/state\"\n\nexport const createChatCompletions = async (\n payload: ChatCompletionsPayload,\n) => {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const enableVision = payload.messages.some(\n (x) =>\n typeof x.content !== \"string\"\n && x.content?.some((x) => x.type === \"image_url\"),\n )\n\n // Agent/user check for X-Initiator header\n // Determine if any message is from an agent (\"assistant\" or \"tool\")\n const isAgentCall = payload.messages.some((msg) =>\n [\"assistant\", \"tool\"].includes(msg.role),\n )\n\n // Build headers and add X-Initiator\n const headers: Record<string, string> = {\n ...copilotHeaders(state, enableVision),\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\n }\n\n const response = await fetchWithRetry(\n `${copilotBaseUrl(state)}/chat/completions`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n },\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 (payload.stream) {\n return events(response)\n }\n\n return (await response.json()) as ChatCompletionResponse\n}\n\n// Streaming types\n\nexport interface ChatCompletionChunk {\n id: string\n object: \"chat.completion.chunk\"\n created: number\n model: string\n choices: Array<Choice>\n system_fingerprint?: string\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n prompt_tokens_details?: {\n cached_tokens: number\n }\n completion_tokens_details?: {\n accepted_prediction_tokens: number\n rejected_prediction_tokens: number\n }\n }\n}\n\ninterface Delta {\n content?: string | null\n role?: \"user\" | \"assistant\" | \"system\" | \"tool\"\n tool_calls?: Array<{\n index: number\n id?: string\n type?: \"function\"\n function?: {\n name?: string\n arguments?: string\n }\n }>\n}\n\ninterface Choice {\n index: number\n delta: Delta\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null\n logprobs: object | null\n}\n\n// Non-streaming types\n\nexport interface ChatCompletionResponse {\n id: string\n object: \"chat.completion\"\n created: number\n model: string\n choices: Array<ChoiceNonStreaming>\n system_fingerprint?: string\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n prompt_tokens_details?: {\n cached_tokens: number\n }\n }\n}\n\ninterface ResponseMessage {\n role: \"assistant\"\n content: string | null\n tool_calls?: Array<ToolCall>\n}\n\ninterface ChoiceNonStreaming {\n index: number\n message: ResponseMessage\n logprobs: object | null\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\"\n}\n\n// Payload types\n\nexport interface ChatCompletionsPayload {\n messages: Array<Message>\n model: string\n temperature?: number | null\n top_p?: number | null\n max_tokens?: number | null\n stop?: string | Array<string> | null\n n?: number | null\n stream?: boolean | null\n stream_options?: { include_usage?: 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 { applyReplacementsToPayload } from \"~/lib/auto-replace\"\nimport { normalizeModelName } from \"~/lib/model-resolver\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { setRequestContext } from \"~/lib/request-logger\"\nimport { state } from \"~/lib/state\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\nimport { isNullish } from \"~/lib/utils\"\nimport {\n createAzureOpenAIChatCompletions,\n isAzureOpenAIModel,\n} from \"~/services/azure-openai\"\nimport {\n createChatCompletions,\n type ChatCompletionChunk,\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 const rawPayload = await c.req.json<ChatCompletionsPayload>()\n\n // Apply auto-replacements to the payload\n\n let payload = await applyReplacementsToPayload(rawPayload)\n\n // Normalize model name (e.g., claude-opus-4-5 -> claude-opus-4.5)\n payload = {\n ...payload,\n model: normalizeModelName(payload.model),\n }\n\n consola.debug(\"Request payload:\", JSON.stringify(payload).slice(-400))\n\n // Check if this is an Azure OpenAI model\n if (isAzureOpenAIModel(payload.model)) {\n if (!state.azureOpenAIConfig) {\n return c.json({ error: \"Azure OpenAI not configured\" }, 500)\n }\n\n setRequestContext(c, { provider: \"Azure OpenAI\", model: payload.model })\n\n if (state.manualApprove) await awaitApproval()\n\n const response = await createAzureOpenAIChatCompletions(\n state.azureOpenAIConfig,\n payload,\n )\n\n if (isNonStreaming(response)) {\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\n if (response.usage) {\n setRequestContext(c, {\n inputTokens: response.usage.prompt_tokens,\n outputTokens: response.usage.completion_tokens,\n })\n }\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 // Capture usage from final chunk if available\n if (chunk.data && chunk.data !== \"[DONE]\") {\n const parsed = JSON.parse(chunk.data) as ChatCompletionChunk\n if (parsed.usage) {\n setRequestContext(c, {\n inputTokens: parsed.usage.prompt_tokens,\n outputTokens: parsed.usage.completion_tokens,\n })\n }\n }\n await stream.writeSSE(chunk as SSEMessage)\n }\n })\n }\n\n setRequestContext(c, { provider: \"Copilot\", model: payload.model })\n\n // Find the selected model\n const selectedModel = state.models?.data.find(\n (model) => model.id === payload.model,\n )\n\n // Calculate and display token count\n try {\n if (selectedModel) {\n const tokenCount = await getTokenCount(payload, selectedModel)\n setRequestContext(c, { inputTokens: tokenCount.input })\n }\n } catch (error) {\n consola.warn(\"Failed to calculate token count:\", error)\n }\n\n if (state.manualApprove) await awaitApproval()\n\n if (isNullish(payload.max_tokens)) {\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 if (response.usage) {\n setRequestContext(c, {\n inputTokens: response.usage.prompt_tokens,\n outputTokens: response.usage.completion_tokens,\n })\n }\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 // Capture usage from final chunk if available\n if (chunk.data && chunk.data !== \"[DONE]\") {\n const parsed = JSON.parse(chunk.data) as ChatCompletionChunk\n if (parsed.usage) {\n setRequestContext(c, {\n inputTokens: parsed.usage.prompt_tokens,\n outputTokens: parsed.usage.completion_tokens,\n })\n }\n }\n await stream.writeSSE(chunk as SSEMessage)\n }\n })\n}\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\n","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 { fetchWithRetry } from \"~/lib/retry-fetch\"\nimport { state } from \"~/lib/state\"\n\nexport const createEmbeddings = async (payload: EmbeddingRequest) => {\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\n\n const response = await fetchWithRetry(`${copilotBaseUrl(state)}/embeddings`, {\n method: \"POST\",\n headers: copilotHeaders(state),\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to create embeddings\", response)\n\n return (await response.json()) as EmbeddingResponse\n}\n\nexport interface EmbeddingRequest {\n input: string | Array<string>\n model: string\n}\n\nexport interface Embedding {\n object: string\n embedding: Array<number>\n index: number\n}\n\nexport interface EmbeddingResponse {\n object: string\n data: Array<Embedding>\n model: string\n usage: {\n prompt_tokens: number\n total_tokens: number\n }\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport {\n createEmbeddings,\n type EmbeddingRequest,\n} from \"~/services/copilot/create-embeddings\"\n\nexport const embeddingRoutes = new Hono()\n\nembeddingRoutes.post(\"/\", async (c) => {\n try {\n const 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 dated model which Copilot doesn't support\n // e.g., claude-sonnet-4-20250514 -> claude-sonnet-4\n // But preserve version numbers like claude-opus-4-5 (normalized to claude-opus-4.5 later)\n if (/^claude-sonnet-4-\\d{8}/.test(model)) {\n return \"claude-sonnet-4\"\n } else if (/^claude-opus-4-\\d{8}/.test(model)) {\n return \"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 originalModel?: string,\n): AnthropicResponse {\n const { contentBlocks, stopReason } = extractContentFromChoices(response)\n return buildAnthropicResponse(response, {\n contentBlocks,\n stopReason,\n originalModel,\n })\n}\n\nfunction extractContentFromChoices(response: ChatCompletionResponse): {\n contentBlocks: Array<AnthropicTextBlock | AnthropicToolUseBlock>\n stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null\n} {\n const allTextBlocks: Array<AnthropicTextBlock> = []\n const allToolUseBlocks: Array<AnthropicToolUseBlock> = []\n let stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null =\n response.choices[0]?.finish_reason ?? null\n\n for (const choice of response.choices) {\n allTextBlocks.push(...getAnthropicTextBlocks(choice.message.content))\n allToolUseBlocks.push(\n ...getAnthropicToolUseBlocks(choice.message.tool_calls),\n )\n\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\n stopReason = choice.finish_reason\n }\n }\n\n return {\n contentBlocks: [...allTextBlocks, ...allToolUseBlocks],\n stopReason,\n }\n}\n\nfunction buildAnthropicResponse(\n response: ChatCompletionResponse,\n options: {\n contentBlocks: Array<AnthropicTextBlock | AnthropicToolUseBlock>\n stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null\n originalModel?: string\n },\n): AnthropicResponse {\n const { contentBlocks, stopReason, originalModel } = options\n return {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n model: originalModel ?? response.model,\n content: contentBlocks,\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\n stop_sequence: null,\n usage: {\n input_tokens:\n (response.usage?.prompt_tokens ?? 0)\n - (response.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: response.usage?.completion_tokens ?? 0,\n ...(response.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n response.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n }\n}\n\nfunction 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 { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport { normalizeModelName } from \"~/lib/model-resolver\"\nimport { state } from \"~/lib/state\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\n\nimport { type AnthropicMessagesPayload } from \"./anthropic-types\"\nimport { translateToOpenAI } from \"./non-stream-translation\"\n\n/**\n * Handles token counting for Anthropic messages\n */\nexport async function handleCountTokens(c: Context) {\n try {\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n // Normalize model name (e.g., claude-opus-4-5 -> claude-opus-4.5) before lookup\n const normalizedModel = normalizeModelName(anthropicPayload.model)\n\n const selectedModel = state.models?.data.find(\n (model) => model.id === normalizedModel,\n )\n\n if (!selectedModel) {\n consola.warn(\"Model not found, returning default token count\")\n return c.json({\n input_tokens: 1,\n })\n }\n\n const tokenCount = await getTokenCount(openAIPayload, selectedModel)\n\n if (anthropicPayload.tools && anthropicPayload.tools.length > 0) {\n let mcpToolExist = false\n if (anthropicBeta?.startsWith(\"claude-code\")) {\n mcpToolExist = anthropicPayload.tools.some((tool) =>\n tool.name.startsWith(\"mcp__\"),\n )\n }\n if (!mcpToolExist) {\n if (anthropicPayload.model.startsWith(\"claude\")) {\n // https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview#pricing\n tokenCount.input = tokenCount.input + 346\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n tokenCount.input = tokenCount.input + 480\n }\n }\n }\n\n let finalTokenCount = tokenCount.input + tokenCount.output\n if (anthropicPayload.model.startsWith(\"claude\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.15)\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.03)\n }\n\n consola.info(\"Token count:\", finalTokenCount)\n\n return c.json({\n input_tokens: finalTokenCount,\n })\n } catch (error) {\n consola.error(\"Error counting tokens:\", error)\n return c.json({\n input_tokens: 1,\n })\n }\n}\n","import {\n type ChatCompletionChunk,\n type ChatCompletionResponse,\n} 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// Helper to create message_delta and message_stop events\nfunction createMessageDeltaEvents(\n finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\",\n usage: {\n prompt_tokens: number\n completion_tokens: number\n cached_tokens: number\n },\n): Array<AnthropicStreamEventData> {\n const stopReason = mapOpenAIStopReasonToAnthropic(finishReason)\n console.log(\n `[stream-translation] Creating message_delta with stop_reason: ${stopReason}, finishReason: ${finishReason}`,\n )\n return [\n {\n type: \"message_delta\",\n delta: {\n stop_reason: stopReason,\n stop_sequence: null,\n },\n usage: {\n input_tokens: usage.prompt_tokens,\n output_tokens: usage.completion_tokens,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: usage.cached_tokens,\n },\n },\n {\n type: \"message_stop\",\n },\n ]\n}\n\n// Export for use in handler fallback\nexport function createFallbackMessageDeltaEvents(\n state: AnthropicStreamState,\n): Array<AnthropicStreamEventData> {\n // If message_delta was already sent, return empty\n if (state.messageDeltaSent) {\n return []\n }\n\n // If we have a pending finish_reason, send message_delta with whatever usage we have\n if (state.pendingFinishReason) {\n const usage = state.pendingUsage ?? {\n prompt_tokens: 0,\n completion_tokens: 0,\n cached_tokens: 0,\n }\n return createMessageDeltaEvents(state.pendingFinishReason, usage)\n }\n\n return []\n}\n\n// eslint-disable-next-line max-lines-per-function, complexity\nexport function translateChunkToAnthropicEvents(\n chunk: ChatCompletionChunk,\n state: AnthropicStreamState,\n originalModel?: string,\n): Array<AnthropicStreamEventData> {\n const events: Array<AnthropicStreamEventData> = []\n\n // Capture usage from any chunk that has it (may come before, with, or after finish_reason)\n if (chunk.usage) {\n state.pendingUsage = {\n prompt_tokens: chunk.usage.prompt_tokens,\n completion_tokens: chunk.usage.completion_tokens,\n cached_tokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0,\n }\n\n // If we already saw finish_reason but deferred message_delta, send it now\n if (state.pendingFinishReason && !state.messageDeltaSent) {\n events.push(\n ...createMessageDeltaEvents(\n state.pendingFinishReason,\n state.pendingUsage,\n ),\n )\n state.messageDeltaSent = true\n }\n }\n\n if (chunk.choices.length === 0) {\n // Empty choices chunk - usage already captured above\n return events\n }\n\n const choice = chunk.choices[0]\n const { delta } = choice\n\n if (!state.messageStartSent) {\n // Include usage in message_start for context window display\n // Use pending usage if available (captured from earlier chunks)\n const usage = state.pendingUsage ?? {\n prompt_tokens: 0,\n completion_tokens: 0,\n cached_tokens: 0,\n }\n events.push({\n type: \"message_start\",\n message: {\n id: chunk.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n // Use original requested model for cost calculation in Claude Code\n model: originalModel ?? chunk.model,\n stop_reason: null,\n stop_sequence: null,\n // Include usage for context window display\n usage: {\n input_tokens: usage.prompt_tokens,\n output_tokens: usage.completion_tokens,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: usage.cached_tokens,\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 // Check if we have usage data (from this chunk or previously captured)\n const hasUsage = chunk.usage || state.pendingUsage\n\n if (hasUsage) {\n // We have usage - send message_delta immediately\n const usage = {\n prompt_tokens:\n chunk.usage?.prompt_tokens ?? state.pendingUsage?.prompt_tokens ?? 0,\n completion_tokens:\n chunk.usage?.completion_tokens\n ?? state.pendingUsage?.completion_tokens\n ?? 0,\n cached_tokens:\n chunk.usage?.prompt_tokens_details?.cached_tokens\n ?? state.pendingUsage?.cached_tokens\n ?? 0,\n }\n\n events.push(...createMessageDeltaEvents(choice.finish_reason, usage))\n state.messageDeltaSent = true\n } else {\n // No usage yet - defer message_delta until we receive usage in a later chunk\n state.pendingFinishReason = choice.finish_reason\n }\n }\n\n return events\n}\n\n/**\n * Convert a complete OpenAI ChatCompletionResponse to Anthropic streaming events.\n * This is used when we fetch non-streaming from upstream but need to simulate\n * streaming to the client with accurate token counts.\n */\nexport function translateResponseToAnthropicEvents(\n response: ChatCompletionResponse,\n originalModel?: string,\n): Array<AnthropicStreamEventData> {\n const choice = response.choices[0]\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- defensive check for empty choices array\n if (!choice) {\n return []\n }\n\n const inputTokens = response.usage?.prompt_tokens ?? 0\n const outputTokens = response.usage?.completion_tokens ?? 0\n const cachedTokens = response.usage?.prompt_tokens_details?.cached_tokens ?? 0\n\n const events: Array<AnthropicStreamEventData> = [\n createMessageStartEvent(response, {\n originalModel,\n inputTokens,\n cachedTokens,\n }),\n ]\n\n let contentBlockIndex = 0\n contentBlockIndex = addTextContentEvents(events, choice, contentBlockIndex)\n addToolCallEvents(events, choice, contentBlockIndex)\n addMessageDeltaAndStopEvents(events, choice, {\n inputTokens,\n outputTokens,\n cachedTokens,\n })\n\n return events\n}\n\ninterface MessageStartEventOptions {\n originalModel: string | undefined\n inputTokens: number\n cachedTokens: number\n}\n\nfunction createMessageStartEvent(\n response: ChatCompletionResponse,\n options: MessageStartEventOptions,\n): AnthropicStreamEventData {\n const { originalModel, inputTokens, cachedTokens } = options\n return {\n type: \"message_start\",\n message: {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: originalModel ?? response.model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens: inputTokens,\n output_tokens: 0,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: cachedTokens,\n },\n },\n }\n}\n\nfunction addTextContentEvents(\n events: Array<AnthropicStreamEventData>,\n choice: ChatCompletionResponse[\"choices\"][0],\n contentBlockIndex: number,\n): number {\n if (choice.message.content) {\n events.push(\n {\n type: \"content_block_start\",\n index: contentBlockIndex,\n content_block: { type: \"text\", text: \"\" },\n },\n {\n type: \"content_block_delta\",\n index: contentBlockIndex,\n delta: { type: \"text_delta\", text: choice.message.content },\n },\n { type: \"content_block_stop\", index: contentBlockIndex },\n )\n return contentBlockIndex + 1\n }\n return contentBlockIndex\n}\n\nfunction addToolCallEvents(\n events: Array<AnthropicStreamEventData>,\n choice: ChatCompletionResponse[\"choices\"][0],\n startIndex: number,\n): void {\n if (!choice.message.tool_calls) return\n\n let idx = startIndex\n for (const toolCall of choice.message.tool_calls) {\n events.push(\n {\n type: \"content_block_start\",\n index: idx,\n content_block: {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: {},\n },\n },\n {\n type: \"content_block_delta\",\n index: idx,\n delta: {\n type: \"input_json_delta\",\n partial_json: toolCall.function.arguments,\n },\n },\n { type: \"content_block_stop\", index: idx },\n )\n idx++\n }\n}\n\ninterface UsageTokens {\n inputTokens: number\n outputTokens: number\n cachedTokens: number\n}\n\nfunction addMessageDeltaAndStopEvents(\n events: Array<AnthropicStreamEventData>,\n choice: ChatCompletionResponse[\"choices\"][0],\n usage: UsageTokens,\n): void {\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: usage.inputTokens,\n output_tokens: usage.outputTokens,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: usage.cachedTokens,\n },\n },\n { type: \"message_stop\" },\n )\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 { applyReplacementsToPayload } from \"~/lib/auto-replace\"\nimport { normalizeModelName } from \"~/lib/model-resolver\"\nimport { checkRateLimit } from \"~/lib/rate-limit\"\nimport { setRequestContext } from \"~/lib/request-logger\"\nimport { state } from \"~/lib/state\"\nimport {\n createAzureOpenAIChatCompletions,\n isAzureOpenAIModel,\n} from \"~/services/azure-openai\"\nimport {\n createChatCompletions,\n type ChatCompletionChunk,\n type ChatCompletionResponse,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicMessagesPayload,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport {\n translateToAnthropic,\n translateToOpenAI,\n} from \"./non-stream-translation\"\nimport {\n createFallbackMessageDeltaEvents,\n translateChunkToAnthropicEvents,\n} from \"./stream-translation\"\n\ninterface UsageData {\n prompt_tokens: number\n completion_tokens: number\n cached_tokens: number\n}\n\n/** Collect all chunks and extract usage data */\nasync function collectChunksWithUsage(\n eventStream: AsyncIterable<{ event?: string; data?: string }>,\n): Promise<{ chunks: Array<ChatCompletionChunk>; usage: UsageData | null }> {\n const chunks: Array<ChatCompletionChunk> = []\n let usage: UsageData | null = null\n\n for await (const event of eventStream) {\n if (!event.data || event.data === \"[DONE]\") continue\n try {\n const chunk = JSON.parse(event.data) as ChatCompletionChunk\n chunks.push(chunk)\n if (chunk.usage) {\n usage = {\n prompt_tokens: chunk.usage.prompt_tokens,\n completion_tokens: chunk.usage.completion_tokens,\n cached_tokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0,\n }\n }\n } catch (error) {\n consola.error(\"Failed to parse chunk:\", error, event.data)\n }\n }\n return { chunks, usage }\n}\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 translatedPayload = translateToOpenAI(anthropicPayload)\n let openAIPayload = await applyReplacementsToPayload(translatedPayload)\n openAIPayload = {\n ...openAIPayload,\n model: normalizeModelName(openAIPayload.model),\n }\n\n if (state.manualApprove) await awaitApproval()\n\n const isAzureModel = isAzureOpenAIModel(openAIPayload.model)\n\n if (isAzureModel) {\n if (!state.azureOpenAIConfig) {\n return c.json({ error: \"Azure OpenAI not configured\" }, 500)\n }\n setRequestContext(c, {\n provider: \"Azure OpenAI\",\n model: openAIPayload.model,\n })\n } else {\n setRequestContext(c, { provider: \"Copilot\", model: openAIPayload.model })\n }\n\n if (anthropicPayload.stream) {\n const streamPayload = {\n ...openAIPayload,\n stream: true,\n stream_options: { include_usage: true },\n }\n\n const azureConfig = state.azureOpenAIConfig\n const response =\n isAzureModel && azureConfig ?\n await createAzureOpenAIChatCompletions(azureConfig, streamPayload)\n : await createChatCompletions(streamPayload)\n\n const eventStream = response as AsyncIterable<{\n event?: string\n data?: string\n }>\n\n return streamSSE(c, async (stream) => {\n // Buffer all chunks first to get usage before emitting message_start\n const { chunks, usage } = await collectChunksWithUsage(eventStream)\n\n consola.debug(`[stream] Collected ${chunks.length} chunks, usage:`, usage)\n\n if (usage) {\n setRequestContext(c, {\n inputTokens: usage.prompt_tokens,\n outputTokens: usage.completion_tokens,\n })\n }\n\n const streamState: AnthropicStreamState = {\n messageStartSent: false,\n contentBlockOpen: false,\n contentBlockIndex: 0,\n toolCalls: {},\n pendingUsage: usage ?? undefined,\n }\n\n // Emit all events with correct usage in message_start\n for (const chunk of chunks) {\n const events = translateChunkToAnthropicEvents(\n chunk,\n streamState,\n anthropicPayload.model,\n )\n for (const evt of events) {\n consola.debug(`[stream] Emitting event: ${evt.type}`)\n await stream.writeSSE({ event: evt.type, data: JSON.stringify(evt) })\n }\n }\n\n const fallbackEvents = createFallbackMessageDeltaEvents(streamState)\n consola.debug(\n `[stream] Fallback events: ${fallbackEvents.length}, messageDeltaSent: ${streamState.messageDeltaSent}`,\n )\n for (const evt of fallbackEvents) {\n consola.debug(`[stream] Emitting fallback event: ${evt.type}`)\n await stream.writeSSE({ event: evt.type, data: JSON.stringify(evt) })\n }\n })\n }\n\n // Non-streaming response\n const nonStreamPayload = { ...openAIPayload, stream: false }\n\n const azureConfigNonStream = state.azureOpenAIConfig\n const response =\n isAzureModel && azureConfigNonStream ?\n ((await createAzureOpenAIChatCompletions(\n azureConfigNonStream,\n nonStreamPayload,\n )) as ChatCompletionResponse)\n : ((await createChatCompletions(\n nonStreamPayload,\n )) as ChatCompletionResponse)\n\n if (response.usage) {\n setRequestContext(c, {\n inputTokens: response.usage.prompt_tokens,\n outputTokens: response.usage.completion_tokens,\n })\n }\n\n const anthropicResponse = translateToAnthropic(\n response,\n anthropicPayload.model,\n )\n return c.json(anthropicResponse)\n}\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCountTokens } from \"./count-tokens-handler\"\nimport { handleCompletion } from \"./handler\"\n\nexport const messageRoutes = new Hono()\n\nmessageRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n return await handleCountTokens(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\nimport { cacheModels } from \"~/lib/utils\"\n\nexport const modelRoutes = new Hono()\n\nmodelRoutes.get(\"/\", async (c) => {\n try {\n if (!state.models) {\n // This should be handled by startup logic, but as a fallback.\n await cacheModels()\n }\n\n // Copilot models\n const copilotModels =\n 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 // Azure OpenAI deployments\n const azureModels =\n state.azureOpenAIDeployments?.map((deployment) => ({\n id: deployment.id,\n object: \"model\",\n type: \"model\",\n created: deployment.created,\n created_at: new Date(deployment.created * 1000).toISOString(),\n owned_by: deployment.owned_by,\n display_name: `${deployment.deploymentName} (${deployment.model})`,\n })) ?? []\n\n const allModels = [...copilotModels, ...azureModels]\n\n return c.json({\n object: \"list\",\n data: allModels,\n has_more: false,\n })\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport {\n addReplacement,\n clearUserReplacements,\n getAllReplacements,\n getUserReplacements,\n removeReplacement,\n toggleReplacement,\n updateReplacement,\n} from \"~/lib/auto-replace\"\n\nexport const replacementsRoute = new Hono()\n\n// Get all replacement rules\nreplacementsRoute.get(\"/\", async (c) => {\n return c.json({\n all: await getAllReplacements(),\n user: await getUserReplacements(),\n })\n})\n\n// Add a new replacement rule\nreplacementsRoute.post(\"/\", async (c) => {\n const body = await c.req.json<{\n pattern: string\n replacement?: string\n isRegex?: boolean\n name?: string\n }>()\n\n if (!body.pattern) {\n return c.json({ error: \"Pattern is required\" }, 400)\n }\n\n const rule = await addReplacement(\n body.pattern,\n body.replacement ?? \"\",\n body.isRegex ?? false,\n body.name,\n )\n\n return c.json(rule, 201)\n})\n\n// Delete a replacement rule\nreplacementsRoute.delete(\"/:id\", async (c) => {\n const id = c.req.param(\"id\")\n const success = await removeReplacement(id)\n\n if (!success) {\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\n }\n\n return c.json({ success: true })\n})\n\n// Update a replacement rule\nreplacementsRoute.patch(\"/:id\", async (c) => {\n const id = c.req.param(\"id\")\n const body = await c.req.json<{\n name?: string\n pattern?: string\n replacement?: string\n isRegex?: boolean\n enabled?: boolean\n }>()\n\n const rule = await updateReplacement(id, body)\n\n if (!rule) {\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\n }\n\n return c.json(rule)\n})\n\n// Toggle a replacement rule\nreplacementsRoute.patch(\"/:id/toggle\", async (c) => {\n const id = c.req.param(\"id\")\n const rule = await toggleReplacement(id)\n\n if (!rule) {\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\n }\n\n return c.json(rule)\n})\n\n// Clear all user replacements\nreplacementsRoute.delete(\"/\", async (c) => {\n await clearUserReplacements()\n return c.json({ success: true })\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 { requestLogger } from \"./lib/request-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 { replacementsRoute } from \"./routes/replacements/route\"\nimport { tokenRoute } from \"./routes/token/route\"\nimport { usageRoute } from \"./routes/usage/route\"\n\nexport const server = new Hono()\n\nserver.use(requestLogger)\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)\nserver.route(\"/replacements\", replacementsRoute)\n\n// Compatibility with tools that expect v1/ prefix\nserver.route(\"/v1/chat/completions\", completionRoutes)\nserver.route(\"/v1/models\", modelRoutes)\nserver.route(\"/v1/embeddings\", embeddingRoutes)\n\n// Anthropic compatible endpoints\nserver.route(\"/v1/messages\", messageRoutes)\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\nimport { serve, type ServerHandler } from \"srvx\"\nimport invariant from \"tiny-invariant\"\n\nimport packageJson from \"../package.json\" with { type: \"json\" }\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport { setupCopilotToken, setupGitHubToken } from \"./lib/token\"\nimport { cacheModels, cacheVSCodeVersion, setupAzureOpenAI } from \"./lib/utils\"\nimport { server } from \"./server\"\n\ninterface RunServerOptions {\n port: number\n verbose: boolean\n accountType: string\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n proxyEnv: boolean\n insecure: boolean\n debug: boolean\n}\n\nexport async function runServer(options: RunServerOptions): Promise<void> {\n consola.info(`copilot-api v${packageJson.version}`)\n\n if (options.insecure) {\n // Disable SSL certificate verification globally\n process.env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\"\n consola.warn(\"SSL certificate verification disabled (insecure mode)\")\n }\n\n if (options.proxyEnv) {\n initProxyFromEnv()\n }\n\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.accountType = options.accountType\n if (options.accountType !== \"individual\") {\n consola.info(`Using ${options.accountType} plan GitHub account`)\n }\n\n state.manualApprove = options.manual\n state.rateLimitSeconds = options.rateLimit\n state.rateLimitWait = options.rateLimitWait\n state.showToken = options.showToken\n state.debug = options.debug\n\n if (options.debug) {\n consola.info(\"Debug mode enabled - raw HTTP requests will be logged\")\n }\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 // Setup Azure OpenAI (prompt on first run, load from config thereafter)\n await setupAzureOpenAI()\n\n // Build combined model list for display\n const copilotModelIds = state.models?.data.map((model) => model.id) ?? []\n const azureModelIds =\n state.azureOpenAIDeployments?.map((deployment) => deployment.id) ?? []\n const allModelIds = [...copilotModelIds, ...azureModelIds]\n\n consola.info(\n `Available models: \\n${allModelIds.map((id) => `- ${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 const selectedModel = await consola.prompt(\n \"Select a model to use with Claude Code\",\n {\n type: \"select\",\n options: allModelIds,\n },\n )\n\n const selectedSmallModel = await consola.prompt(\n \"Select a small model to use with Claude Code\",\n {\n type: \"select\",\n options: allModelIds,\n },\n )\n\n const command = generateEnvScript(\n {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: \"dummy\",\n ANTHROPIC_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel,\n ANTHROPIC_SMALL_FAST_MODEL: selectedSmallModel,\n ANTHROPIC_DEFAULT_HAIKU_MODEL: selectedSmallModel,\n DISABLE_NON_ESSENTIAL_MODEL_CALLS: \"1\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\n },\n \"claude\",\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 // Increase idle timeout for long-running requests (e.g. Claude Code compact)\n // Bun default is 10s which is too short\n bun: {\n idleTimeout: 255, // max value in seconds (4m 15s)\n },\n })\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the Copilot API server\",\n },\n args: {\n port: {\n alias: \"p\",\n type: \"string\",\n default: \"4141\",\n description: \"Port to listen on\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type to use (individual, business, enterprise)\",\n },\n manual: {\n type: \"boolean\",\n default: false,\n description: \"Enable manual request approval\",\n },\n \"rate-limit\": {\n alias: \"r\",\n type: \"string\",\n description: \"Rate limit in seconds between requests\",\n },\n wait: {\n alias: \"w\",\n type: \"boolean\",\n default: false,\n description:\n \"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set\",\n },\n \"github-token\": {\n alias: \"g\",\n type: \"string\",\n description:\n \"Provide GitHub token directly (must be generated using the `auth` subcommand)\",\n },\n \"claude-code\": {\n alias: \"c\",\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Claude Code with Copilot API config\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub and Copilot tokens on fetch and refresh\",\n },\n \"proxy-env\": {\n type: \"boolean\",\n default: false,\n description: \"Initialize proxy from environment variables\",\n },\n insecure: {\n type: \"boolean\",\n default: false,\n description:\n \"Disable SSL certificate verification (for corporate proxies with self-signed certs)\",\n },\n debug: {\n alias: \"d\",\n type: \"boolean\",\n default: false,\n description:\n \"Log raw HTTP requests received by the server (headers, method, path)\",\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 return runServer({\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n accountType: args[\"account-type\"],\n manual: args.manual,\n rateLimit,\n rateLimitWait: args.wait,\n githubToken: args[\"github-token\"],\n claudeCode: args[\"claude-code\"],\n showToken: args[\"show-token\"],\n proxyEnv: args[\"proxy-env\"],\n insecure: args.insecure,\n debug: args.debug,\n })\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand, runMain } from \"citty\"\n\nimport packageJson from \"../package.json\" with { type: \"json\" }\nimport { auth } from \"./auth\"\nimport { checkUsage } from \"./check-usage\"\nimport { config } from \"./config\"\nimport { debug } from \"./debug\"\nimport { start } from \"./start\"\n\nconst main = defineCommand({\n meta: {\n name: \"copilot-api\",\n version: packageJson.version,\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, config },\n})\n\nawait runMain(main)\n"],"mappings":"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"}
|