betahi-copilot-bridge 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -7
- package/dist/main.js +36 -20
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ endpoint, so [Codex CLI](https://github.com/openai/codex) and
|
|
|
5
5
|
[Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) can
|
|
6
6
|
talk to Copilot transparently.
|
|
7
7
|
|
|
8
|
-
**Supports:** Codex CLI and Claude Code out of the box.
|
|
8
|
+
**Supports:** **Codex CLI** and **Claude Code** out of the box.
|
|
9
9
|
|
|
10
10
|
> [!WARNING]
|
|
11
11
|
> This is a reverse-engineered bridge for the GitHub Copilot API. It is not
|
|
@@ -95,6 +95,11 @@ model = "gpt-5.3-codex"
|
|
|
95
95
|
model_reasoning_effort = "high"
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
If `model_reasoning_effort` is omitted, the bridge leaves it unset and Codex
|
|
99
|
+
uses that model's default reasoning effort (a startup info log also reminds you).
|
|
100
|
+
|
|
101
|
+
`model_reasoning_effort` only affects Codex requests; it does not affect Claude.
|
|
102
|
+
|
|
98
103
|
That's it — `codex exec '...'` will now route through the bridge to Copilot.
|
|
99
104
|
|
|
100
105
|
Use `--no-codex-setup` to skip the managed-block writer entirely (e.g. if you
|
|
@@ -128,15 +133,20 @@ If you prefer to wire it yourself:
|
|
|
128
133
|
"ANTHROPIC_MODEL": "claude-opus-4.7",
|
|
129
134
|
"ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4.6",
|
|
130
135
|
"ANTHROPIC_SMALL_FAST_MODEL": "claude-haiku-4.5",
|
|
131
|
-
"
|
|
136
|
+
"MODEL_REASONING_EFFORT": "medium"
|
|
132
137
|
},
|
|
133
138
|
"model": "claude-opus-4.7"
|
|
134
139
|
}
|
|
135
140
|
```
|
|
136
141
|
|
|
137
|
-
`
|
|
138
|
-
`.claude/settings.json` and `.claude/settings.local.json` and
|
|
139
|
-
|
|
142
|
+
`MODEL_REASONING_EFFORT` (case-insensitive key lookup) is also read from the
|
|
143
|
+
project-local `.claude/settings.json` and `.claude/settings.local.json` and
|
|
144
|
+
applied to Claude requests only when the model supports reasoning.
|
|
145
|
+
|
|
146
|
+
For backward compatibility, `COPILOT_REASONING_EFFORT` is accepted as an alias.
|
|
147
|
+
|
|
148
|
+
If Claude-side reasoning is not configured, Claude requests fall back to
|
|
149
|
+
`medium` (when the target model supports reasoning).
|
|
140
150
|
|
|
141
151
|
## Environment overrides
|
|
142
152
|
|
|
@@ -146,7 +156,10 @@ upstream call when the model supports reasoning.
|
|
|
146
156
|
| `COPILOT_ACCOUNT_TYPE` | `individual` \| `business` \| `enterprise`. |
|
|
147
157
|
| `COPILOT_BASE_URL` | Override the upstream Copilot base URL. |
|
|
148
158
|
| `COPILOT_VSCODE_VERSION` | Override the VS Code version sent upstream. |
|
|
149
|
-
| `
|
|
159
|
+
| `MODEL_REASONING_EFFORT` | Claude-side default reasoning effort (preferred key). |
|
|
160
|
+
| `COPILOT_REASONING_EFFORT` | Alias of `MODEL_REASONING_EFFORT` (backward compatible). |
|
|
161
|
+
|
|
162
|
+
|
|
150
163
|
|
|
151
164
|
## Supported models
|
|
152
165
|
|
|
@@ -195,7 +208,8 @@ accepts upstream.
|
|
|
195
208
|
If an unsupported value is sent for a reasoning-capable model, the bridge
|
|
196
209
|
falls back to the model's default (`medium` for the GPT-5 / Claude Opus 4.7
|
|
197
210
|
families) instead of forwarding an invalid request upstream. Set the default
|
|
198
|
-
globally via `
|
|
211
|
+
globally via `MODEL_REASONING_EFFORT` (or `COPILOT_REASONING_EFFORT` alias)
|
|
212
|
+
(env, or `env` in
|
|
199
213
|
`~/.claude/settings.json`); per-request `reasoning_effort` (or Anthropic
|
|
200
214
|
`thinking.budget_tokens`) takes precedence.
|
|
201
215
|
|
|
@@ -217,3 +231,7 @@ bun run ./src/main.ts start --host 127.0.0.1 --port 4141 --no-prompt
|
|
|
217
231
|
Adding another CLI: drop a new translator under `src/bridges/<client>/`,
|
|
218
232
|
reuse `src/services/copilot/` for upstream calls, register routes in
|
|
219
233
|
`src/server.ts`, and add tests under `tests/`.
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT — see [LICENSE](./LICENSE).
|
package/dist/main.js
CHANGED
|
@@ -1059,33 +1059,47 @@ const normalizeClaudeOpus47Effort = (value) => {
|
|
|
1059
1059
|
default: return;
|
|
1060
1060
|
}
|
|
1061
1061
|
};
|
|
1062
|
-
const
|
|
1063
|
-
const
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1062
|
+
const getEnvValueCaseInsensitive = (env, key) => {
|
|
1063
|
+
const direct = env[key];
|
|
1064
|
+
if (typeof direct === "string") return direct;
|
|
1065
|
+
const lower = key.toLowerCase();
|
|
1066
|
+
return Object.entries(env).find(([k]) => k.toLowerCase() === lower)?.[1];
|
|
1067
|
+
};
|
|
1068
|
+
const getConfiguredReasoningEffort = (client, claudeSettingsEnv) => {
|
|
1069
|
+
if (client !== "claude") return;
|
|
1070
|
+
return process.env.MODEL_REASONING_EFFORT ?? process.env.COPILOT_REASONING_EFFORT ?? getEnvValueCaseInsensitive(claudeSettingsEnv, "MODEL_REASONING_EFFORT") ?? getEnvValueCaseInsensitive(claudeSettingsEnv, "COPILOT_REASONING_EFFORT");
|
|
1071
|
+
};
|
|
1072
|
+
const getRequestedReasoningEffort = (payload, claudeSettingsEnv, client) => {
|
|
1073
|
+
const configuredReasoningEffort = getConfiguredReasoningEffort(client, claudeSettingsEnv);
|
|
1074
|
+
const defaultEffort = client === "claude" ? "medium" : defaultReasoningEffort(payload.model);
|
|
1075
|
+
const requestedReasoningEffort = payload.reasoning_effort ?? normalizeReasoningEffort$1(configuredReasoningEffort);
|
|
1076
|
+
return sanitizeReasoningEffortForModel(payload.model, requestedReasoningEffort) ?? defaultEffort;
|
|
1077
|
+
};
|
|
1078
|
+
const getRequestedClaudeOpus47Effort = (payload, claudeSettingsEnv, client) => {
|
|
1067
1079
|
if (!isClaudeOpus47Model$1(payload.model)) return;
|
|
1068
|
-
|
|
1080
|
+
const configuredReasoningEffort = getConfiguredReasoningEffort(client, claudeSettingsEnv);
|
|
1081
|
+
return payload.output_config?.effort ?? normalizeClaudeOpus47Effort(payload.reasoning_effort) ?? normalizeClaudeOpus47Effort(configuredReasoningEffort) ?? (client === "claude" ? "medium" : void 0);
|
|
1069
1082
|
};
|
|
1070
1083
|
const sanitizeUserIdentifier = (user) => {
|
|
1071
1084
|
if (!user) return;
|
|
1072
1085
|
return user.slice(0, MAX_USER_LENGTH);
|
|
1073
1086
|
};
|
|
1074
|
-
const buildRequestPayload = (payload, claudeSettingsEnv) => {
|
|
1075
|
-
const requestedReasoningEffort = getRequestedReasoningEffort(payload, claudeSettingsEnv);
|
|
1076
|
-
const requestedClaudeOpus47Effort = getRequestedClaudeOpus47Effort(payload, claudeSettingsEnv);
|
|
1087
|
+
const buildRequestPayload = (payload, claudeSettingsEnv, client) => {
|
|
1088
|
+
const requestedReasoningEffort = getRequestedReasoningEffort(payload, claudeSettingsEnv, client);
|
|
1089
|
+
const requestedClaudeOpus47Effort = getRequestedClaudeOpus47Effort(payload, claudeSettingsEnv, client);
|
|
1077
1090
|
const reasoningEffort = usesMaxCompletionTokens(payload.model) && payload.tools !== null && payload.tools !== void 0 && payload.tools.length > 0 ? void 0 : requestedReasoningEffort;
|
|
1078
1091
|
if (!usesMaxCompletionTokens(payload.model) || payload.max_tokens === null || payload.max_tokens === void 0) {
|
|
1092
|
+
const shouldAttachReasoningEffort = !isClaudeOpus47Model$1(payload.model);
|
|
1079
1093
|
const sanitizedPayload = {
|
|
1080
1094
|
...payload,
|
|
1081
1095
|
output_config: requestedClaudeOpus47Effort ? {
|
|
1082
1096
|
...payload.output_config,
|
|
1083
1097
|
effort: requestedClaudeOpus47Effort
|
|
1084
1098
|
} : payload.output_config,
|
|
1085
|
-
reasoning_effort:
|
|
1099
|
+
reasoning_effort: shouldAttachReasoningEffort ? payload.reasoning_effort : void 0,
|
|
1086
1100
|
user: sanitizeUserIdentifier(payload.user)
|
|
1087
1101
|
};
|
|
1088
|
-
return reasoningEffort === null || reasoningEffort === void 0 ? sanitizedPayload : {
|
|
1102
|
+
return !shouldAttachReasoningEffort || reasoningEffort === null || reasoningEffort === void 0 ? sanitizedPayload : {
|
|
1089
1103
|
...sanitizedPayload,
|
|
1090
1104
|
reasoning_effort: reasoningEffort
|
|
1091
1105
|
};
|
|
@@ -1100,13 +1114,14 @@ const buildRequestPayload = (payload, claudeSettingsEnv) => {
|
|
|
1100
1114
|
};
|
|
1101
1115
|
const isAgentInitiator = (messages) => messages.some((msg) => msg.role === "assistant" || msg.role === "tool") ? "agent" : "user";
|
|
1102
1116
|
const messagesIncludeImage = (messages) => messages.some((msg) => typeof msg.content !== "string" && msg.content?.some((part) => part.type === "image_url"));
|
|
1103
|
-
const createChatCompletions = async (config, payload) => {
|
|
1117
|
+
const createChatCompletions = async (config, payload, options) => {
|
|
1104
1118
|
const provider = getCopilotProviderContext(config);
|
|
1105
1119
|
const enableVision = messagesIncludeImage(payload.messages);
|
|
1106
1120
|
const initiator = isAgentInitiator(payload.messages);
|
|
1107
|
-
const
|
|
1108
|
-
const
|
|
1109
|
-
|
|
1121
|
+
const client = options?.client ?? "generic";
|
|
1122
|
+
const claudeSettingsEnv = client === "claude" ? await getClaudeSettingsEnv() : {};
|
|
1123
|
+
const requestPayload = buildRequestPayload(payload, claudeSettingsEnv, client);
|
|
1124
|
+
if (shouldUseResponsesApiForModel(payload.model)) return createResponses(provider, payload, claudeSettingsEnv, client, {
|
|
1110
1125
|
vision: enableVision,
|
|
1111
1126
|
initiator
|
|
1112
1127
|
});
|
|
@@ -1122,7 +1137,7 @@ const createChatCompletions = async (config, payload) => {
|
|
|
1122
1137
|
initiator
|
|
1123
1138
|
});
|
|
1124
1139
|
if (!response.ok) {
|
|
1125
|
-
if (await shouldRetryWithResponses(response)) return createResponses(provider, payload, claudeSettingsEnv, {
|
|
1140
|
+
if (await shouldRetryWithResponses(response)) return createResponses(provider, payload, claudeSettingsEnv, client, {
|
|
1126
1141
|
vision: enableVision,
|
|
1127
1142
|
initiator
|
|
1128
1143
|
});
|
|
@@ -1132,8 +1147,8 @@ const createChatCompletions = async (config, payload) => {
|
|
|
1132
1147
|
if (payload.stream) return events(response);
|
|
1133
1148
|
return await response.json();
|
|
1134
1149
|
};
|
|
1135
|
-
async function createResponses(provider, payload, claudeSettingsEnv, options) {
|
|
1136
|
-
const reasoningEffort = getRequestedReasoningEffort(payload, claudeSettingsEnv);
|
|
1150
|
+
async function createResponses(provider, payload, claudeSettingsEnv, client, options) {
|
|
1151
|
+
const reasoningEffort = getRequestedReasoningEffort(payload, claudeSettingsEnv, client);
|
|
1137
1152
|
const response = await fetchCopilot(provider, "/responses", {
|
|
1138
1153
|
method: "POST",
|
|
1139
1154
|
headers: {
|
|
@@ -1168,7 +1183,7 @@ chatCompletionRoutes.post("/", async (c) => {
|
|
|
1168
1183
|
try {
|
|
1169
1184
|
await checkRateLimit();
|
|
1170
1185
|
const payload = await c.req.json();
|
|
1171
|
-
const response = await createChatCompletions(c.var.config, payload);
|
|
1186
|
+
const response = await createChatCompletions(c.var.config, payload, { client: "generic" });
|
|
1172
1187
|
if (isNonStreaming(response)) return c.json(response);
|
|
1173
1188
|
return streamSSE(c, async (stream) => {
|
|
1174
1189
|
for await (const chunk of response) await stream.writeSSE(chunk);
|
|
@@ -1857,7 +1872,7 @@ messageRoutes.post("/", async (c) => {
|
|
|
1857
1872
|
}
|
|
1858
1873
|
const openAIPayload = translateToOpenAI(await c.req.json());
|
|
1859
1874
|
try {
|
|
1860
|
-
const response = await createChatCompletions(config, openAIPayload);
|
|
1875
|
+
const response = await createChatCompletions(config, openAIPayload, { client: "claude" });
|
|
1861
1876
|
if (isNonStreamingResponse(response)) return c.json(translateToAnthropic(response));
|
|
1862
1877
|
return streamSSE(c, async (stream) => {
|
|
1863
1878
|
const streamState = {
|
|
@@ -2553,6 +2568,7 @@ const start = defineCommand({
|
|
|
2553
2568
|
const codexUserConfig = await readCodexUserConfigFromDisk(codexConfigPath);
|
|
2554
2569
|
let chosenModel = codexUserConfig.model;
|
|
2555
2570
|
let chosenEffort = codexUserConfig.modelReasoningEffort;
|
|
2571
|
+
if (chosenModel && !chosenEffort) consola.info(`codex model_reasoning_effort not set; using ${chosenModel}'s default reasoning effort`);
|
|
2556
2572
|
if (!args["no-codex-setup"]) try {
|
|
2557
2573
|
const result = await applyCodexConfig({
|
|
2558
2574
|
baseUrl: `${baseUrl}/v1`,
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","names":["runtimeState: RuntimeState","COPILOT_VERSION","EDITOR_PLUGIN_VERSION","USER_AGENT","path","COPILOT_VERSION","EDITOR_PLUGIN_VERSION","USER_AGENT","GITHUB_API_VERSION","GITHUB_API_BASE_URL","sleep","readGitHubToken","merged: Record<string, string>","parsed: Record<string, unknown>","env: Record<string, unknown>","next: Record<string, unknown>","lines: Array<string>","out: CodexUserConfig","CODEX_DEFAULTS: CodexDefaults","MODEL_CAPABILITIES: ReadonlyArray<ModelCapability>","entries: Array<readonly [string, ModelCapability]>","order: ReadonlyArray<ReasoningEffort>","state: ResponseTranslationState","translated: Array<ResponsesInputItem>","isClaudeOpus47Model","normalizeReasoningEffort","matches: Array<Model>","newMessages: Array<Message>","contentParts: Array<ContentPart>","allTextBlocks: Array<AnthropicTextBlock>","allToolUseBlocks: Array<AnthropicToolUseBlock>","stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null","events: Array<AnthropicStreamEventData>","events","streamState: AnthropicStreamState","chunk: ChatCompletionChunk","events","parts: Array<ChatContentPart>","messages: Array<ChatMessage>","inputItems: Array<ResponsesInputItem>","role: ChatRole","tools: Array<ChatTool> | undefined","payload: ChatRequestPayload","output: ResponsesApiResult[\"output\"]","event: ResponsesStreamEvent","stableResponse: StableResponseMetadata","incoming: ReasoningField | undefined","upstream","chosenModel: string | undefined","chosenEffort: string | undefined"],"sources":["../src/lib/error.ts","../src/lib/paths.ts","../src/lib/state.ts","../src/providers/copilot/client.ts","../src/providers/copilot/get-models.ts","../src/lib/auth.ts","../src/lib/config.ts","../src/auth.ts","../src/lib/claude-settings.ts","../src/lib/codex-config.ts","../src/lib/defaults.ts","../src/lib/model-capabilities.ts","../src/lib/rate-limit.ts","../src/services/copilot/responses.ts","../src/services/copilot/create-chat-completions.ts","../src/routes/chat-completions.ts","../src/providers/copilot/create-embeddings.ts","../src/routes/embeddings.ts","../src/lib/models-resolver.ts","../src/bridges/claude/utils.ts","../src/bridges/claude/non-stream-translation.ts","../src/bridges/claude/stream-translation.ts","../src/lib/tokenizer.ts","../src/routes/messages.ts","../src/routes/models.ts","../src/bridges/codex/chat-fallback.ts","../src/bridges/codex/normalize-stream.ts","../src/bridges/codex/responses.ts","../src/routes/responses.ts","../src/providers/github/get-copilot-usage.ts","../src/routes/usage.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["export class BridgeNotImplementedError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"BridgeNotImplementedError\"\n }\n}\n\nexport class HTTPError extends Error {\n response: Response\n\n constructor(message: string, response: Response) {\n super(message)\n this.name = \"HTTPError\"\n this.response = response\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-bridge\")\n\nconst GITHUB_TOKEN_PATH = path.join(APP_DIR, \"github_token\")\n\nexport const PATHS = {\n APP_DIR,\n GITHUB_TOKEN_PATH,\n}\n\nexport async function ensurePaths(): Promise<void> {\n await fs.mkdir(PATHS.APP_DIR, { recursive: true })\n await ensureFile(PATHS.GITHUB_TOKEN_PATH)\n}\n\nasync function ensureFile(filePath: string): Promise<void> {\n try {\n await fs.access(filePath, fs.constants.W_OK)\n } catch {\n await fs.writeFile(filePath, \"\")\n await fs.chmod(filePath, 0o600)\n }\n}","import type { ModelsResponse } from \"~/providers/copilot/get-models\"\n\nexport interface RuntimeState {\n models?: ModelsResponse\n rateLimitSeconds?: number\n rateLimitWait?: boolean\n lastRequestTimestamp?: number\n}\n\nexport const runtimeState: RuntimeState = {}\n","import { randomUUID } from \"node:crypto\"\n\nimport type { BridgeConfig } from \"~/lib/config\"\nimport { BridgeNotImplementedError } from \"~/lib/error\"\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\nconst API_VERSION = \"2025-04-01\"\n\nexport interface CopilotProviderContext {\n baseUrl: string\n token: string | undefined\n vsCodeVersion: string\n}\n\nexport const getCopilotProviderContext = (\n config: BridgeConfig,\n): CopilotProviderContext => ({\n baseUrl: config.copilotBaseUrl,\n token: config.copilotToken,\n vsCodeVersion: config.vsCodeVersion,\n})\n\nexport interface FetchCopilotOptions {\n vision?: boolean\n initiator?: \"agent\" | \"user\"\n}\n\nexport const fetchCopilot = async (\n provider: CopilotProviderContext,\n path: string,\n init: RequestInit,\n options: FetchCopilotOptions = {},\n) => {\n if (!provider.token) {\n throw new BridgeNotImplementedError(\n \"COPILOT_TOKEN is not configured for copilot-bridge.\",\n )\n }\n\n const headers = new Headers(init.headers)\n\n headers.set(\"authorization\", `Bearer ${provider.token}`)\n headers.set(\"copilot-integration-id\", \"vscode-chat\")\n headers.set(\"editor-version\", `vscode/${provider.vsCodeVersion}`)\n headers.set(\"editor-plugin-version\", EDITOR_PLUGIN_VERSION)\n headers.set(\"user-agent\", USER_AGENT)\n headers.set(\"openai-intent\", \"conversation-panel\")\n headers.set(\"x-github-api-version\", API_VERSION)\n headers.set(\"x-request-id\", randomUUID())\n headers.set(\"x-vscode-user-agent-library-version\", \"electron-fetch\")\n\n if (options.vision) {\n headers.set(\"copilot-vision-request\", \"true\")\n }\n\n if (options.initiator) {\n headers.set(\"x-initiator\", options.initiator)\n }\n\n if (!headers.has(\"content-type\") && init.body !== undefined) {\n headers.set(\"content-type\", \"application/json\")\n }\n\n if (!headers.has(\"accept\")) {\n headers.set(\"accept\", \"application/json\")\n }\n\n return fetch(`${provider.baseUrl}${path}`, {\n ...init,\n headers,\n })\n}\n","import type { BridgeConfig } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\n\nimport { fetchCopilot, getCopilotProviderContext } from \"./client\"\n\nexport const getModels = async (\n config: BridgeConfig,\n): Promise<ModelsResponse> => {\n const provider = getCopilotProviderContext(config)\n const response = await fetchCopilot(provider, \"/models\", {\n method: \"GET\",\n headers: { accept: \"application/json\" },\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get models\", response)\n\n return (await response.json()) as ModelsResponse\n}\n\nexport interface ModelsResponse {\n data: Array<Model>\n object: string\n}\n\ninterface ModelLimits {\n max_context_window_tokens?: number\n max_output_tokens?: number\n max_prompt_tokens?: number\n max_inputs?: number\n}\n\ninterface ModelSupports {\n tool_calls?: boolean\n parallel_tool_calls?: boolean\n dimensions?: boolean\n}\n\ninterface ModelCapabilities {\n family: string\n limits: ModelLimits\n object: string\n supports: ModelSupports\n tokenizer: string\n type: string\n}\n\nexport interface Model {\n capabilities: ModelCapabilities\n id: string\n model_picker_enabled: boolean\n name: string\n object: string\n preview: boolean\n vendor: string\n version: string\n policy?: {\n state: string\n terms: string\n }\n}\n","import fs from \"node:fs/promises\"\n\nimport consola from \"consola\"\n\nimport type { BridgeConfig } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { PATHS, ensurePaths } from \"~/lib/paths\"\nimport { runtimeState } from \"~/lib/state\"\nimport { getModels } from \"~/providers/copilot/get-models\"\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\nconst GITHUB_API_VERSION = \"2022-11-28\"\n\nconst GITHUB_API_BASE_URL = \"https://api.github.com\"\nconst GITHUB_BASE_URL = \"https://github.com\"\nconst GITHUB_CLIENT_ID = \"Iv1.b507a08c87ecfe98\"\nconst GITHUB_APP_SCOPES = [\"read:user\"].join(\" \")\n\ninterface DeviceCodeResponse {\n device_code: string\n expires_in: number\n interval: number\n user_code: string\n verification_uri: string\n}\n\ninterface AccessTokenResponse {\n access_token?: string\n}\n\ninterface CopilotTokenResponse {\n refresh_in: number\n token: string\n}\n\ninterface GitHubUserResponse {\n login: string\n}\n\ninterface AuthOptions {\n force?: boolean\n showToken?: boolean\n}\n\nconst standardHeaders = () => ({\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n})\n\nconst sleep = (ms: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, ms)\n })\n\nconst readGitHubToken = async () => {\n const token = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return token.trim()\n}\n\nconst writeGitHubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, `${token.trim()}\\n`, { mode: 0o600 })\n\nconst githubHeaders = (githubToken: string, vsCodeVersion: string) => ({\n ...standardHeaders(),\n authorization: `token ${githubToken}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"editor-version\": `vscode/${vsCodeVersion}`,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": GITHUB_API_VERSION,\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n})\n\nconst getDeviceCode = async (): 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) {\n throw new HTTPError(\"Failed to get device code\", response)\n }\n\n return (await response.json()) as DeviceCodeResponse\n}\n\nconst pollAccessToken = async (\n deviceCode: DeviceCodeResponse,\n): Promise<string> => {\n const sleepDuration = (deviceCode.interval + 1) * 1000\n\n while (true) {\n const response = await fetch(`${GITHUB_BASE_URL}/login/oauth/access_token`, {\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 if (!response.ok) {\n await sleep(sleepDuration)\n continue\n }\n\n const json = (await response.json()) as AccessTokenResponse\n if (json.access_token) {\n return json.access_token\n }\n\n await sleep(sleepDuration)\n }\n}\n\nconst getGitHubUser = async (\n githubToken: string,\n vsCodeVersion: string,\n): Promise<GitHubUserResponse> => {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: githubHeaders(githubToken, vsCodeVersion),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get GitHub user\", response)\n }\n\n return (await response.json()) as GitHubUserResponse\n}\n\nconst getCopilotToken = async (\n githubToken: string,\n vsCodeVersion: string,\n): Promise<CopilotTokenResponse> => {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(githubToken, vsCodeVersion),\n },\n )\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get Copilot token\", response)\n }\n\n return (await response.json()) as CopilotTokenResponse\n}\n\nconst ensureGitHubToken = async (\n config: BridgeConfig,\n options: AuthOptions = {},\n) => {\n await ensurePaths()\n\n const existingToken = options.force ? \"\" : await readGitHubToken()\n if (existingToken) {\n return existingToken\n }\n\n const deviceCode = await getDeviceCode()\n consola.info(\n `Open ${deviceCode.verification_uri} and enter code ${deviceCode.user_code}`,\n )\n\n const githubToken = await pollAccessToken(deviceCode)\n await writeGitHubToken(githubToken)\n\n if (options.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n\n const user = await getGitHubUser(githubToken, config.vsCodeVersion)\n consola.success(`Logged in as ${user.login}`)\n\n return githubToken\n}\n\nexport const setupBridgeAuth = async (\n config: BridgeConfig,\n options: AuthOptions = {},\n) => {\n if (config.copilotToken) {\n if (options.showToken) {\n consola.info(\"Using COPILOT_TOKEN from environment\")\n }\n await loadModels(config)\n return\n }\n\n const githubToken = await ensureGitHubToken(config, options)\n const applyCopilotToken = async () => {\n const { refresh_in, token } = await getCopilotToken(\n githubToken,\n config.vsCodeVersion,\n )\n\n config.copilotToken = token\n if (options.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n return refresh_in\n }\n\n const refreshIn = await applyCopilotToken()\n const refreshInterval = Math.max(refreshIn - 60, 60) * 1000\n\n setInterval(async () => {\n try {\n await applyCopilotToken()\n consola.debug(\"Refreshed Copilot token\")\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n }\n }, refreshInterval)\n\n await loadModels(config)\n}\n\nconst loadModels = async (config: BridgeConfig) => {\n try {\n runtimeState.models = await getModels(config)\n consola.success(\n `Loaded ${runtimeState.models.data.length} Copilot models`,\n )\n } catch (error) {\n consola.warn(\"Failed to load Copilot models:\", error)\n }\n}\n\nexport const runBridgeAuth = async (\n config: BridgeConfig,\n options: AuthOptions = {},\n) => {\n const githubToken = await ensureGitHubToken(config, {\n ...options,\n force: true,\n })\n\n const user = await getGitHubUser(githubToken, config.vsCodeVersion)\n consola.success(`GitHub token written to ${PATHS.GITHUB_TOKEN_PATH}`)\n consola.info(`Logged in as ${user.login}`)\n}","import { z } from \"zod\"\n\nconst accountTypeSchema = z.enum([\"individual\", \"business\", \"enterprise\"])\n\nconst inputSchema = z.object({\n host: z.string().min(1),\n port: z.number().int().min(1).max(65535),\n})\n\nexport interface BridgeConfig {\n host: string\n port: number\n accountType: \"individual\" | \"business\" | \"enterprise\"\n copilotBaseUrl: string\n copilotToken: string | undefined\n vsCodeVersion: string\n}\n\nexport interface BridgeEnv {\n Variables: {\n config: BridgeConfig\n }\n}\n\nexport const readBridgeConfig = (input: {\n host: string\n port: number\n}): BridgeConfig => {\n const parsedInput = inputSchema.parse(input)\n const accountType = accountTypeSchema.parse(\n process.env.COPILOT_ACCOUNT_TYPE ?? \"individual\",\n )\n const copilotBaseUrl =\n process.env.COPILOT_BASE_URL\n ?? (\n accountType === \"individual\" ?\n \"https://api.githubcopilot.com\"\n : `https://api.${accountType}.githubcopilot.com`\n )\n\n return {\n host: parsedInput.host,\n port: parsedInput.port,\n accountType,\n copilotBaseUrl,\n copilotToken: process.env.COPILOT_TOKEN,\n vsCodeVersion: process.env.COPILOT_VSCODE_VERSION ?? \"1.99.3\",\n }\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { setupBridgeAuth } from \"~/lib/auth\"\nimport { readBridgeConfig } from \"~/lib/config\"\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run GitHub device auth and cache credentials for copilot-bridge.\",\n },\n args: {\n host: {\n type: \"string\",\n default: \"127.0.0.1\",\n description: \"Host used for config initialization.\",\n },\n port: {\n type: \"string\",\n default: \"4142\",\n description: \"Port used for config initialization.\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Print GitHub and Copilot tokens during auth.\",\n },\n },\n async run({ args }) {\n const config = readBridgeConfig({\n host: String(args.host),\n port: Number(args.port),\n })\n\n config.copilotToken = undefined\n\n await setupBridgeAuth(config, {\n force: true,\n showToken: args[\"show-token\"],\n })\n\n consola.success(\"copilot-bridge auth completed\")\n },\n})","import fs from \"node:fs/promises\"\nimport os from \"node:os\"\nimport path from \"node:path\"\n\nimport consola from \"consola\"\n\ninterface ClaudeSettingsFile {\n env?: Record<string, unknown>\n}\n\nconst getClaudeSettingsPaths = (): Array<string> => {\n const cwd = process.cwd()\n const home = process.env.HOME ?? os.homedir()\n\n return [\n path.join(home, \".claude\", \"settings.json\"),\n path.join(cwd, \".claude\", \"settings.json\"),\n path.join(cwd, \".claude\", \"settings.local.json\"),\n ]\n}\n\nconst readClaudeSettingsFile = async (\n filePath: string,\n): Promise<ClaudeSettingsFile | undefined> => {\n try {\n const content = await fs.readFile(filePath, \"utf8\")\n return JSON.parse(content) as ClaudeSettingsFile\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return undefined\n }\n consola.warn(`Failed to read Claude settings from ${filePath}:`, error)\n return undefined\n }\n}\n\n/**\n * Read just the `ANTHROPIC_BASE_URL` from a single Claude settings file.\n * Used at startup so the user can pin the bridge port by editing one place\n * instead of passing `--port` every time.\n */\nexport const readClaudeBaseUrl = async (\n configPath: string,\n): Promise<string | undefined> => {\n const settings = await readClaudeSettingsFile(configPath)\n const value = settings?.env?.ANTHROPIC_BASE_URL\n return typeof value === \"string\" ? value : undefined\n}\n\n/**\n * Parse the port from an `ANTHROPIC_BASE_URL`-style string. Returns\n * `undefined` if the URL is malformed or has no explicit port.\n */\nexport const parsePortFromBaseUrl = (\n baseUrl: string | undefined,\n): number | undefined => {\n if (!baseUrl) return undefined\n try {\n const url = new URL(baseUrl)\n if (!url.port) return undefined\n const port = Number.parseInt(url.port, 10)\n return Number.isFinite(port) && port > 0 ? port : undefined\n } catch {\n return undefined\n }\n}\n\nexport const getClaudeSettingsEnv = async (): Promise<\n Record<string, string>\n> => {\n const merged: Record<string, string> = {}\n\n for (const filePath of getClaudeSettingsPaths()) {\n const settings = await readClaudeSettingsFile(filePath)\n if (!settings?.env) continue\n\n for (const [key, value] of Object.entries(settings.env)) {\n if (typeof value === \"string\") merged[key] = value\n }\n }\n\n return merged\n}\n\ninterface ApplyClaudeConfigInput {\n baseUrl: string\n configPath: string\n}\n\ninterface ApplyClaudeResult {\n configPath: string\n changed: boolean\n created: boolean\n previousBaseUrl?: string\n}\n\n/**\n * Update `~/.claude/settings.json` so its env block points Claude Code at the\n * running bridge. Preserves all unrelated keys (model overrides, plugins,\n * marketplaces, etc.). Sets a dummy auth token only if none is present.\n */\nexport async function applyClaudeConfig(\n input: ApplyClaudeConfigInput,\n): Promise<ApplyClaudeResult> {\n const { configPath, baseUrl } = input\n\n let raw = \"\"\n let created = false\n try {\n raw = await fs.readFile(configPath, \"utf8\")\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n created = true\n } else {\n throw error\n }\n }\n\n let parsed: Record<string, unknown> = {}\n if (raw.trim().length > 0) {\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n parsed = {}\n }\n } catch {\n // Refuse to overwrite a malformed file; bail without changes.\n return { configPath, changed: false, created: false }\n }\n }\n\n const env: Record<string, unknown> =\n typeof parsed.env === \"object\"\n && parsed.env !== null\n && !Array.isArray(parsed.env)\n ? { ...(parsed.env as Record<string, unknown>) }\n : {}\n\n const previousBaseUrl =\n typeof env.ANTHROPIC_BASE_URL === \"string\"\n ? (env.ANTHROPIC_BASE_URL as string)\n : undefined\n\n env.ANTHROPIC_BASE_URL = baseUrl\n if (typeof env.ANTHROPIC_AUTH_TOKEN !== \"string\" || !env.ANTHROPIC_AUTH_TOKEN) {\n env.ANTHROPIC_AUTH_TOKEN = \"dummy\"\n }\n\n const next: Record<string, unknown> = { ...parsed, env }\n const serialized = `${JSON.stringify(next, null, 2)}\\n`\n\n if (serialized === raw) {\n return { configPath, changed: false, created: false, previousBaseUrl }\n }\n\n await fs.mkdir(path.dirname(configPath), { recursive: true })\n await fs.writeFile(configPath, serialized)\n return { configPath, changed: true, created, previousBaseUrl }\n}\n","import fs from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport type { CodexDefaults } from \"./defaults\"\n\nconst BEGIN_MARK =\n \"# >>> copilot-bridge managed block — auto-generated, do not edit between markers >>>\"\nconst END_MARK =\n \"# <<< copilot-bridge managed block — edits outside this block are preserved <<<\"\n\n// Legacy markers from earlier releases. We still recognize and strip them so\n// upgrading users do not end up with duplicate managed blocks.\nconst LEGACY_BEGIN_MARK = \"# >>> copilot-bridge managed (do not edit) >>>\"\nconst LEGACY_END_MARK = \"# <<< copilot-bridge managed (do not edit) <<<\"\n\n// Top-level keys that the user (or codex itself) is the owner of.\n// We never put these in our managed block to avoid TOML duplicate-key errors.\nconst USER_OWNED_SCALARS = [\"model\", \"model_reasoning_effort\"] as const\ntype UserScalar = (typeof USER_OWNED_SCALARS)[number]\n\ninterface ApplyCodexConfigInput {\n baseUrl: string\n settings: CodexDefaults\n /** Optional model to write into the user-owned area of the file. */\n model?: string\n /** Optional reasoning effort to write into the user-owned area. */\n modelReasoningEffort?: string\n}\n\ninterface ApplyResult {\n configPath: string\n changed: boolean\n created: boolean\n}\n\nexport interface CodexUserConfig {\n model?: string\n modelReasoningEffort?: string\n}\n\nfunction tomlEscape(value: string): string {\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')\n}\n\nfunction buildManagedBlock(input: ApplyCodexConfigInput): string {\n const { baseUrl, settings } = input\n const lines: Array<string> = []\n lines.push(BEGIN_MARK)\n if (settings.setAsDefault) {\n lines.push(`model_provider = \"${tomlEscape(settings.providerId)}\"`)\n }\n lines.push(\"\")\n lines.push(`[model_providers.${settings.providerId}]`)\n lines.push(`name = \"${tomlEscape(settings.providerName)}\"`)\n lines.push(`base_url = \"${tomlEscape(baseUrl)}\"`)\n lines.push(`wire_api = \"responses\"`)\n lines.push(`prefer_websockets = false`)\n lines.push(`requires_openai_auth = false`)\n lines.push(END_MARK)\n return lines.join(\"\\n\")\n}\n\nfunction stripManagedBlock(content: string): string {\n let next = content\n for (const [begin, end] of [\n [BEGIN_MARK, END_MARK],\n [LEGACY_BEGIN_MARK, LEGACY_END_MARK],\n ]) {\n while (true) {\n const beginIdx = next.indexOf(begin)\n if (beginIdx === -1) break\n const endIdx = next.indexOf(end, beginIdx)\n if (endIdx === -1) break\n const before = next.slice(0, beginIdx).replace(/\\n*$/, \"\")\n const after = next.slice(endIdx + end.length).replace(/^\\n+/, \"\")\n if (before.length === 0) next = after\n else if (after.length === 0) next = `${before}\\n`\n else next = `${before}\\n\\n${after}`\n }\n }\n return next\n}\n\n// Lines belonging to the first (top-level) TOML section: from the start of\n// the file up to the first line that begins with `[`. This is where\n// codex's own `model = ...` and `model_reasoning_effort = ...` live.\nfunction splitTopSection(content: string): {\n top: string\n rest: string\n} {\n const lines = content.split(\"\\n\")\n let cut = lines.length\n for (let i = 0; i < lines.length; i++) {\n if (/^\\s*\\[/.test(lines[i])) {\n cut = i\n break\n }\n }\n return {\n top: lines.slice(0, cut).join(\"\\n\"),\n rest: lines.slice(cut).join(\"\\n\"),\n }\n}\n\nconst scalarRegex = (key: string) =>\n new RegExp(`^\\\\s*${key}\\\\s*=\\\\s*\"((?:[^\"\\\\\\\\]|\\\\\\\\.)*)\"\\\\s*$`, \"m\")\n\nexport function readCodexUserConfig(content: string): CodexUserConfig {\n const stripped = stripManagedBlock(content)\n const { top } = splitTopSection(stripped)\n const out: CodexUserConfig = {}\n const m = top.match(scalarRegex(\"model\"))\n if (m) out.model = m[1]\n const e = top.match(scalarRegex(\"model_reasoning_effort\"))\n if (e) out.modelReasoningEffort = e[1]\n return out\n}\n\nfunction setTopScalar(\n topSection: string,\n key: UserScalar,\n value: string | undefined,\n): string {\n const re = scalarRegex(key)\n if (value === undefined) {\n // Leave the existing value as-is when caller did not provide one.\n return topSection\n }\n const line = `${key} = \"${tomlEscape(value)}\"`\n if (re.test(topSection)) {\n return topSection.replace(re, line)\n }\n // Insert at the very top of the file, before any existing content.\n if (topSection.length === 0) return `${line}\\n`\n // Keep a single blank line between our inserted scalars and existing content.\n return `${line}\\n${topSection.startsWith(\"\\n\") ? \"\" : \"\"}${topSection}`\n}\n\nfunction applyUserScalars(\n content: string,\n input: ApplyCodexConfigInput,\n): string {\n const { top, rest } = splitTopSection(content)\n let nextTop = top\n nextTop = setTopScalar(nextTop, \"model\", input.model)\n nextTop = setTopScalar(\n nextTop,\n \"model_reasoning_effort\",\n input.modelReasoningEffort,\n )\n if (nextTop === top) return content\n if (rest.length === 0) {\n return nextTop.endsWith(\"\\n\") ? nextTop : `${nextTop}\\n`\n }\n const sep = nextTop.endsWith(\"\\n\") ? \"\" : \"\\n\"\n return `${nextTop}${sep}${rest}`\n}\n\nexport async function applyCodexConfig(\n input: ApplyCodexConfigInput & { configPath: string },\n): Promise<ApplyResult> {\n const { configPath } = input\n let existing = \"\"\n let created = false\n try {\n existing = await fs.readFile(configPath, \"utf8\")\n } catch {\n created = true\n }\n\n let stripped = stripManagedBlock(existing)\n stripped = applyUserScalars(stripped, input)\n const block = buildManagedBlock(input)\n const trimmed = stripped.replace(/\\n+$/, \"\")\n const next =\n trimmed.length === 0 ? `${block}\\n` : `${trimmed}\\n\\n${block}\\n`\n\n if (next === existing) {\n return { configPath, changed: false, created: false }\n }\n\n await fs.mkdir(path.dirname(configPath), { recursive: true })\n await fs.writeFile(configPath, next)\n return { configPath, changed: true, created }\n}\n\nexport async function readCodexUserConfigFromDisk(\n configPath: string,\n): Promise<CodexUserConfig> {\n try {\n const content = await fs.readFile(configPath, \"utf8\")\n return readCodexUserConfig(content)\n } catch {\n return {}\n }\n}\n","import os from \"node:os\"\nimport path from \"node:path\"\n\n/**\n * Static defaults for the bridge. Previously these lived in\n * `~/.config/copilot-bridge/settings.json`, but that file ended up being a\n * silent third source of truth (alongside `~/.codex/config.toml` and\n * `~/.claude/settings.json`) which caused subtle port-mismatch bugs. The\n * bridge now relies on these defaults plus CLI flags only — every other\n * persisted state lives in the consumer config files (codex / claude).\n */\n\nexport interface CodexDefaults {\n providerId: string\n providerName: string\n setAsDefault: boolean\n configPath: string\n}\n\nexport const DEFAULT_HOST = \"127.0.0.1\"\nexport const DEFAULT_PORT = 4142\n\nexport const CODEX_DEFAULTS: CodexDefaults = {\n providerId: \"bridge\",\n providerName: \"Copilot Bridge\",\n setAsDefault: true,\n configPath: path.join(os.homedir(), \".codex\", \"config.toml\"),\n}\n\nexport const CLAUDE_CONFIG_PATH = path.join(\n os.homedir(),\n \".claude\",\n \"settings.json\",\n)\n","// Model capability registry for copilot-bridge.\n// Source: GitHub Copilot Responses API model + reasoning_effort matrix.\n// Keep this tightly scoped to what we use to validate / clamp requests.\n\nexport type ReasoningEffort =\n | \"none\"\n | \"low\"\n | \"medium\"\n | \"high\"\n | \"xhigh\"\n | \"max\"\n\nexport interface ModelCapability {\n id: string\n // Optional aliases that resolve to this canonical id (e.g. trimming a\n // \"-preview\" suffix). Requests using an alias get their model rewritten\n // to the canonical id before being forwarded upstream.\n aliases?: ReadonlyArray<string>\n // If undefined, the model does not accept a reasoning parameter at all\n // and the bridge will strip any reasoning.* fields from the request.\n reasoning?: {\n supported: ReadonlyArray<ReasoningEffort>\n default: ReasoningEffort\n }\n // When set, /v1/responses requests for this model are translated to\n // upstream /v1/chat/completions because Copilot does not expose the\n // Responses API for this model.\n fallback?: \"chat-completions\"\n // Where to place the reasoning effort on the upstream chat payload.\n // - \"reasoning_effort\" (default for gpt-5 family / most claude)\n // - \"output_config.effort\" (claude-opus-4.7 family)\n // Has no effect when reasoning is undefined.\n reasoningField?: \"reasoning_effort\" | \"output_config.effort\"\n}\n\nexport const MODEL_CAPABILITIES: ReadonlyArray<ModelCapability> = [\n {\n id: \"gpt-5.5\",\n reasoning: {\n supported: [\"none\", \"low\", \"medium\", \"high\", \"xhigh\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5.4\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\", \"xhigh\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5.4-mini\",\n reasoning: {\n supported: [\"none\", \"low\", \"medium\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5.3-codex\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\", \"xhigh\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5.2\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\", \"xhigh\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5.2-codex\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\", \"xhigh\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5-mini\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\"],\n default: \"medium\",\n },\n },\n // Claude family — Copilot does not expose /v1/responses for Claude, so we\n // translate to /v1/chat/completions. Only opus-4.7 places effort under\n // output_config.effort; the others use the standard reasoning_effort.\n {\n id: \"claude-opus-4.7\",\n fallback: \"chat-completions\",\n reasoningField: \"output_config.effort\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"],\n default: \"medium\",\n },\n },\n {\n id: \"claude-opus-4.6\",\n fallback: \"chat-completions\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\"],\n default: \"medium\",\n },\n },\n {\n id: \"claude-opus-4.6-1m\",\n fallback: \"chat-completions\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\"],\n default: \"medium\",\n },\n },\n {\n id: \"claude-opus-4.5\",\n fallback: \"chat-completions\",\n },\n {\n id: \"claude-sonnet-4.6\",\n fallback: \"chat-completions\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\"],\n default: \"medium\",\n },\n },\n {\n id: \"claude-sonnet-4.5\",\n fallback: \"chat-completions\",\n },\n {\n id: \"claude-sonnet-4\",\n fallback: \"chat-completions\",\n },\n {\n id: \"claude-haiku-4.5\",\n fallback: \"chat-completions\",\n },\n // Gemini family currently does not accept a reasoning parameter on the\n // Copilot Responses endpoint — bridge strips reasoning.* before forwarding.\n {\n id: \"gemini-3.1-pro-preview\",\n fallback: \"chat-completions\",\n aliases: [\"gemini-3.1-pro\"],\n },\n {\n id: \"gemini-3-flash-preview\",\n fallback: \"chat-completions\",\n aliases: [\"gemini-3-flash\"],\n },\n {\n id: \"gemini-2.5-pro\",\n fallback: \"chat-completions\",\n },\n // Legacy GPT-4.x — chat-only upstream, no reasoning parameter accepted.\n {\n id: \"gpt-4.1\",\n fallback: \"chat-completions\",\n },\n {\n id: \"gpt-4o\",\n fallback: \"chat-completions\",\n },\n]\n\nconst CAPABILITY_BY_ID = new Map(\n MODEL_CAPABILITIES.flatMap((m) => {\n const entries: Array<readonly [string, ModelCapability]> = [[m.id, m]]\n for (const alias of m.aliases ?? []) entries.push([alias, m])\n return entries\n }),\n)\n\n// Resolve any alias to the canonical upstream id. Returns the input\n// unchanged when no mapping is found.\nexport const resolveModelId = (modelId: string): string =>\n CAPABILITY_BY_ID.get(modelId)?.id ?? modelId\n\nexport const getModelCapability = (\n modelId: string,\n): ModelCapability | undefined => CAPABILITY_BY_ID.get(modelId)\n\nexport const isReasoningEffort = (value: unknown): value is ReasoningEffort =>\n value === \"none\"\n || value === \"low\"\n || value === \"medium\"\n || value === \"high\"\n || value === \"xhigh\"\n || value === \"max\"\n\nexport interface NormalizedReasoning {\n effort: ReasoningEffort\n changed: boolean\n reason?: \"unsupported-model\" | \"unsupported-effort\"\n}\n\n// Clamp a requested effort to what the model supports. Returns undefined\n// when the model does not accept reasoning at all (caller should strip it).\nexport const clampReasoningEffort = (\n modelId: string,\n requested: unknown,\n): NormalizedReasoning | undefined => {\n const capability = getModelCapability(modelId)\n if (!capability?.reasoning) return undefined\n\n const { supported, default: defaultEffort } = capability.reasoning\n\n if (requested === undefined || requested === null) {\n return { effort: defaultEffort, changed: false }\n }\n\n if (!isReasoningEffort(requested)) {\n return {\n effort: defaultEffort,\n changed: true,\n reason: \"unsupported-effort\",\n }\n }\n\n if (supported.includes(requested)) {\n return { effort: requested, changed: false }\n }\n\n // Pick the closest supported value by ordering low<medium<high<xhigh<max,\n // treat 'none' as below 'low'. If requested exceeds max supported, fall to\n // the highest supported; if below the lowest, fall to the lowest.\n const order: ReadonlyArray<ReasoningEffort> = [\n \"none\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n ]\n const reqIdx = order.indexOf(requested)\n const supportedSorted = [...supported].sort(\n (a, b) => order.indexOf(a) - order.indexOf(b),\n )\n const lowest = supportedSorted[0]\n const highest = supportedSorted[supportedSorted.length - 1]\n const fallback =\n reqIdx > order.indexOf(highest) ? highest\n : reqIdx < order.indexOf(lowest) ? lowest\n : (supportedSorted.find((e) => order.indexOf(e) >= reqIdx) ?? defaultEffort)\n\n return { effort: fallback, changed: true, reason: \"unsupported-effort\" }\n}\n","import consola from \"consola\"\n\nimport { runtimeState } from \"./state\"\n\nconst sleep = (ms: number) =>\n new Promise<void>((resolve) => {\n setTimeout(resolve, ms)\n })\n\n/**\n * Enforces the configured rate limit window between mutating upstream calls.\n *\n * - Resolves silently if no rate limit is configured or enough time has passed.\n * - Throws a Response (HTTP 429) when the window has not elapsed and `wait` is\n * disabled, so route handlers can `c.json` it directly.\n * - When `wait` is enabled, sleeps until the window elapses, then resolves.\n */\nexport const checkRateLimit = async (): Promise<void> => {\n const { rateLimitSeconds, rateLimitWait } = runtimeState\n if (rateLimitSeconds === undefined) return\n\n const now = Date.now()\n if (!runtimeState.lastRequestTimestamp) {\n runtimeState.lastRequestTimestamp = now\n return\n }\n\n const elapsed = (now - runtimeState.lastRequestTimestamp) / 1000\n if (elapsed > rateLimitSeconds) {\n runtimeState.lastRequestTimestamp = now\n return\n }\n\n const waitSeconds = Math.ceil(rateLimitSeconds - elapsed)\n\n if (!rateLimitWait) {\n consola.warn(\n `Rate limit exceeded. Need to wait ${waitSeconds} more seconds.`,\n )\n throw new RateLimitError(waitSeconds)\n }\n\n consola.warn(\n `Rate limit reached. Waiting ${waitSeconds}s before proceeding...`,\n )\n await sleep(waitSeconds * 1000)\n runtimeState.lastRequestTimestamp = Date.now()\n}\n\nexport class RateLimitError extends Error {\n readonly waitSeconds: number\n\n constructor(waitSeconds: number) {\n super(`Rate limit exceeded. Try again in ${waitSeconds}s.`)\n this.name = \"RateLimitError\"\n this.waitSeconds = waitSeconds\n }\n}\n","import { randomUUID } from \"node:crypto\"\n\nimport type {\n ChatCompletionChunk,\n ChatCompletionResponse,\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n} from \"~/providers/copilot/chat-types\"\n\nimport { sanitizeUserIdentifier } from \"./create-chat-completions\"\n\nexport interface ResponseStreamEventMessage {\n data?: string\n event?: string\n}\n\nexport interface ResponsesApiResponse {\n id: string\n created_at: number\n model: string\n output: Array<ResponsesOutputItem>\n usage?: {\n input_tokens: number\n input_tokens_details?: {\n cached_tokens?: number\n }\n output_tokens: number\n output_tokens_details?: {\n reasoning_tokens?: number\n }\n total_tokens: number\n }\n incomplete_details?: {\n reason?: string | null\n } | null\n}\n\nexport type ResponsesReasoningEffort =\n | \"none\"\n | \"low\"\n | \"medium\"\n | \"high\"\n | \"max\"\n | \"xhigh\"\n\ntype ResponsesInput = string | Array<ResponsesInputItem>\n\ntype ResponsesInputItem =\n | ResponsesMessageInput\n | ResponsesFunctionCallInput\n | ResponsesFunctionCallOutputInput\n\ntype ResponsesMessageInput = {\n role: \"user\" | \"assistant\" | \"system\" | \"developer\"\n content: string | Array<ResponsesInputContentPart>\n}\n\ntype ResponsesInputContentPart =\n | {\n type: \"input_text\"\n text: string\n }\n | {\n type: \"input_image\"\n image_url: string\n detail: \"low\" | \"high\" | \"auto\"\n }\n\ntype ResponsesFunctionCallInput = {\n type: \"function_call\"\n call_id: string\n name: string\n arguments: string\n}\n\ntype ResponsesFunctionCallOutputInput = {\n type: \"function_call_output\"\n call_id: string\n output: string\n}\n\ntype ResponsesToolChoice =\n | \"none\"\n | \"auto\"\n | \"required\"\n | { type: \"function\"; name: string }\n\nexport interface ResponsesRequestPayload {\n model: string\n input: ResponsesInput\n stream?: boolean | null\n max_output_tokens?: number | null\n temperature?: number | null\n top_p?: number | null\n user?: string | null\n reasoning?: {\n effort: ResponsesReasoningEffort\n }\n tools?: Array<ResponsesTool>\n tool_choice?: ResponsesToolChoice | null\n text?: {\n format: {\n type: \"json_object\"\n }\n }\n}\n\ninterface ResponsesTool {\n type: \"function\"\n name: string\n description?: string\n parameters: Record<string, unknown>\n}\n\ntype ResponsesOutputItem =\n | ResponsesMessageOutputItem\n | ResponsesFunctionCallOutputItem\n | ResponsesReasoningOutputItem\n\ninterface ResponsesMessageOutputItem {\n type: \"message\"\n role: \"assistant\"\n content: Array<ResponsesMessageContentPart>\n}\n\ninterface ResponsesMessageContentPart {\n type: \"output_text\"\n text: string\n}\n\ninterface ResponsesFunctionCallOutputItem {\n type: \"function_call\"\n call_id: string\n name: string\n arguments: string\n}\n\ninterface ResponsesReasoningOutputItem {\n type: \"reasoning\"\n}\n\ninterface ResponsesStreamEnvelope {\n type: string\n response?: {\n id: string\n created_at: number\n model: string\n usage?: ResponsesApiResponse[\"usage\"]\n output?: Array<ResponsesOutputItem>\n incomplete_details?: ResponsesApiResponse[\"incomplete_details\"]\n }\n item?:\n | Partial<ResponsesMessageOutputItem>\n | Partial<ResponsesFunctionCallOutputItem>\n output_index?: number\n delta?: string\n}\n\ninterface ResponseTranslationState {\n responseId: string\n createdAt: number\n model: string\n started: boolean\n}\n\ninterface CreateChunkOptions {\n delta: ChatCompletionChunk[\"choices\"][0][\"delta\"]\n finishReason?: ChatCompletionChunk[\"choices\"][0][\"finish_reason\"]\n usage?: ChatCompletionChunk[\"usage\"]\n}\n\nconst RESPONSES_ONLY_MODEL_PATTERN = /^(?:gpt-5\\.3-codex|gpt-5\\.4-mini)(?:-|$)/i\n\nexport function shouldUseResponsesApiForModel(model: string): boolean {\n return RESPONSES_ONLY_MODEL_PATTERN.test(model)\n}\n\nexport function buildResponsesRequestPayload(\n payload: ChatCompletionsPayload,\n reasoningEffort: ResponsesReasoningEffort | undefined,\n): ResponsesRequestPayload {\n return {\n model: payload.model,\n input: translateMessagesToResponsesInput(payload.messages),\n stream: payload.stream,\n max_output_tokens: payload.max_tokens,\n temperature: payload.temperature,\n top_p: payload.top_p,\n user: sanitizeUserIdentifier(payload.user),\n tools: translateTools(payload.tools),\n tool_choice: translateToolChoice(payload.tool_choice),\n reasoning: reasoningEffort ? { effort: reasoningEffort } : undefined,\n text:\n payload.response_format?.type === \"json_object\" ?\n { format: { type: \"json_object\" } }\n : undefined,\n }\n}\n\nexport function translateResponsesToChatCompletion(\n response: ResponsesApiResponse,\n): ChatCompletionResponse {\n const assistantMessages = response.output.filter(\n (item): item is ResponsesMessageOutputItem => item.type === \"message\",\n )\n const functionCalls = response.output.filter(\n (item): item is ResponsesFunctionCallOutputItem =>\n item.type === \"function_call\",\n )\n\n const content = assistantMessages\n .flatMap((item) => item.content)\n .map((part) => part.text)\n .join(\"\")\n\n return {\n id: response.id,\n object: \"chat.completion\",\n created: response.created_at,\n model: response.model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content: content || null,\n ...(functionCalls.length > 0 && {\n tool_calls: functionCalls.map((toolCall) => ({\n id: toolCall.call_id,\n type: \"function\" as const,\n function: {\n name: toolCall.name,\n arguments: toolCall.arguments,\n },\n })),\n }),\n },\n logprobs: null,\n finish_reason: getFinishReason(response, functionCalls.length > 0),\n },\n ],\n usage: translateUsage(response.usage),\n }\n}\n\nexport async function* translateResponsesStreamToChatCompletionStream(\n responseStream: AsyncIterable<ResponseStreamEventMessage>,\n): AsyncGenerator<ResponseStreamEventMessage> {\n const state: ResponseTranslationState = {\n responseId: randomUUID(),\n createdAt: Math.floor(Date.now() / 1000),\n model: \"\",\n started: false,\n }\n\n for await (const rawEvent of responseStream) {\n if (!rawEvent.data || rawEvent.data === \"[DONE]\") {\n continue\n }\n\n const event = JSON.parse(rawEvent.data) as ResponsesStreamEnvelope\n\n if (event.response) {\n state.responseId = event.response.id\n state.createdAt = event.response.created_at\n state.model = event.response.model\n }\n\n if (event.type === \"response.output_item.added\") {\n const chunk = handleOutputItemAdded(state, event)\n if (chunk) {\n yield chunk\n }\n continue\n }\n\n if (event.type === \"response.output_text.delta\") {\n yield createRoleChunk(state)\n yield createChunk(state, { delta: { content: event.delta } })\n continue\n }\n\n if (event.type === \"response.function_call_arguments.delta\") {\n if (event.output_index === undefined) {\n continue\n }\n\n yield createRoleChunk(state)\n yield createChunk(state, {\n delta: {\n tool_calls: [\n {\n index: event.output_index,\n type: \"function\",\n function: {\n arguments: event.delta ?? \"\",\n },\n },\n ],\n },\n })\n continue\n }\n\n if (event.type === \"response.completed\") {\n if (!event.response) {\n continue\n }\n\n yield createChunk(\n {\n ...state,\n responseId: event.response.id,\n createdAt: event.response.created_at,\n model: event.response.model,\n },\n {\n delta: {},\n finishReason: getFinishReason(\n {\n output: event.response.output ?? [],\n incomplete_details: event.response.incomplete_details,\n },\n (event.response.output ?? []).some(\n (item) => item.type === \"function_call\",\n ),\n ),\n usage: translateUsage(event.response.usage),\n },\n )\n yield { data: \"[DONE]\" }\n return\n }\n }\n}\n\nfunction handleOutputItemAdded(\n state: ResponseTranslationState,\n event: ResponsesStreamEnvelope,\n): ResponseStreamEventMessage | undefined {\n if (event.item?.type === \"message\") {\n return createRoleChunk(state)\n }\n\n if (\n event.item?.type === \"function_call\"\n && event.output_index !== undefined\n ) {\n state.started = true\n return createChunk(state, {\n delta: {\n role: \"assistant\",\n tool_calls: [\n {\n index: event.output_index,\n id: event.item.call_id,\n type: \"function\",\n function: {\n name: event.item.name,\n arguments: event.item.arguments ?? \"\",\n },\n },\n ],\n },\n })\n }\n\n return undefined\n}\n\nfunction createRoleChunk(\n state: ResponseTranslationState,\n): ResponseStreamEventMessage {\n if (state.started) {\n return { data: \"\" }\n }\n\n state.started = true\n return createChunk(state, { delta: { role: \"assistant\" } })\n}\n\nfunction createChunk(\n state: ResponseTranslationState,\n { delta, finishReason = null, usage }: CreateChunkOptions,\n): ResponseStreamEventMessage {\n return {\n data: JSON.stringify({\n id: state.responseId,\n object: \"chat.completion.chunk\",\n created: state.createdAt,\n model: state.model,\n choices: [\n {\n index: 0,\n delta,\n finish_reason: finishReason,\n logprobs: null,\n },\n ],\n usage,\n } satisfies ChatCompletionChunk),\n }\n}\n\nfunction translateMessagesToResponsesInput(\n messages: Array<Message>,\n): ResponsesInput {\n const items = messages.flatMap((message) => translateMessage(message))\n\n if (\n items.length === 1\n && \"role\" in items[0]\n && items[0].role === \"user\"\n && typeof items[0].content === \"string\"\n ) {\n return items[0].content\n }\n\n return items\n}\n\nfunction translateMessage(message: Message): Array<ResponsesInputItem> {\n if (message.role === \"tool\") {\n return [\n {\n type: \"function_call_output\",\n call_id: message.tool_call_id ?? \"\",\n output: stringifyToolOutput(message.content),\n },\n ]\n }\n\n const translated: Array<ResponsesInputItem> = []\n\n if (hasContent(message.content)) {\n translated.push({\n role: message.role,\n content: translateContent(message.content),\n })\n }\n\n if (message.role === \"assistant\" && message.tool_calls) {\n translated.push(\n ...message.tool_calls.map((toolCall) => ({\n type: \"function_call\" as const,\n call_id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n })),\n )\n }\n\n return translated\n}\n\nfunction hasContent(content: Message[\"content\"]): boolean {\n if (content === null) {\n return false\n }\n\n if (typeof content === \"string\") {\n return content.length > 0\n }\n\n return content.length > 0\n}\n\nfunction translateContent(\n content: Message[\"content\"],\n): ResponsesMessageInput[\"content\"] {\n if (typeof content === \"string\") {\n return content\n }\n\n if (!content || content.length === 0) {\n return \"\"\n }\n\n return content.map((part) => translateContentPart(part))\n}\n\nfunction translateContentPart(part: ContentPart): ResponsesInputContentPart {\n if (part.type === \"text\") {\n return {\n type: \"input_text\",\n text: part.text,\n }\n }\n\n return {\n type: \"input_image\",\n image_url: part.image_url.url,\n detail: part.image_url.detail ?? \"auto\",\n }\n}\n\nfunction stringifyToolOutput(content: Message[\"content\"]): string {\n if (typeof content === \"string\") {\n return content\n }\n\n if (!content) {\n return \"\"\n }\n\n const text = content\n .filter(\n (part): part is Extract<ContentPart, { type: \"text\" }> =>\n part.type === \"text\",\n )\n .map((part) => part.text)\n .join(\"\\n\\n\")\n\n return text || JSON.stringify(content)\n}\n\nfunction translateTools(\n tools: Array<Tool> | null | undefined,\n): Array<ResponsesTool> | undefined {\n if (!tools) {\n return undefined\n }\n\n return tools.map((tool) => ({\n type: \"function\",\n name: tool.function.name,\n description: tool.function.description,\n parameters: tool.function.parameters,\n }))\n}\n\nfunction translateToolChoice(\n toolChoice: ChatCompletionsPayload[\"tool_choice\"],\n): ResponsesToolChoice | undefined {\n if (!toolChoice) {\n return undefined\n }\n\n if (typeof toolChoice === \"string\") {\n return toolChoice\n }\n\n return {\n type: \"function\",\n name: toolChoice.function.name,\n }\n}\n\nfunction translateUsage(\n usage: ResponsesApiResponse[\"usage\"] | undefined,\n): ChatCompletionResponse[\"usage\"] | undefined {\n if (!usage) {\n return undefined\n }\n\n return {\n prompt_tokens: usage.input_tokens,\n completion_tokens: usage.output_tokens,\n total_tokens: usage.total_tokens,\n ...(usage.input_tokens_details?.cached_tokens !== undefined && {\n prompt_tokens_details: {\n cached_tokens: usage.input_tokens_details.cached_tokens,\n },\n }),\n }\n}\n\nfunction getFinishReason(\n response: Pick<ResponsesApiResponse, \"output\" | \"incomplete_details\">,\n hasFunctionCalls: boolean,\n): \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" {\n if (hasFunctionCalls) {\n return \"tool_calls\"\n }\n\n if (response.incomplete_details?.reason?.includes(\"max_output_tokens\")) {\n return \"length\"\n }\n\n return \"stop\"\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport type { BridgeConfig } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { getClaudeSettingsEnv } from \"~/lib/claude-settings\"\nimport { fetchCopilot, getCopilotProviderContext } from \"~/providers/copilot/client\"\nimport type {\n ChatCompletionResponse,\n ChatCompletionsPayload,\n} from \"~/providers/copilot/chat-types\"\n\nimport {\n buildResponsesRequestPayload,\n shouldUseResponsesApiForModel,\n translateResponsesStreamToChatCompletionStream,\n translateResponsesToChatCompletion,\n type ResponsesApiResponse,\n type ResponsesReasoningEffort,\n} from \"./responses\"\n\nconst usesMaxCompletionTokens = (modelId: string): boolean =>\n modelId.startsWith(\"gpt-5\")\n\nconst isClaudeOpus47Model = (modelId: string): boolean =>\n modelId.startsWith(\"claude-opus-4.7\")\n\ntype ClaudeOpus47Effort = NonNullable<\n NonNullable<ChatCompletionsPayload[\"output_config\"]>[\"effort\"]\n>\n\nconst MAX_USER_LENGTH = 64\n\nconst defaultReasoningEffort = (\n modelId: string,\n): ChatCompletionsPayload[\"reasoning_effort\"] =>\n usesMaxCompletionTokens(modelId) ? \"medium\" : undefined\n\nconst getAllowedReasoningEfforts = (\n modelId: string,\n): Array<\n Exclude<ChatCompletionsPayload[\"reasoning_effort\"], null | undefined>\n> => {\n if (modelId.startsWith(\"gpt-5.5\")) {\n return [\"none\", \"low\", \"medium\", \"high\", \"xhigh\"]\n }\n\n if (modelId.startsWith(\"gpt-5.4-mini\")) {\n return [\"none\", \"low\", \"medium\"]\n }\n\n if (modelId.startsWith(\"gpt-5.4\") || modelId.startsWith(\"gpt-5.3-codex\")) {\n return [\"low\", \"medium\", \"high\", \"xhigh\"]\n }\n\n if (usesMaxCompletionTokens(modelId)) {\n return [\"low\", \"medium\", \"high\", \"xhigh\"]\n }\n\n return []\n}\n\nexport const sanitizeReasoningEffortForModel = (\n modelId: string,\n reasoningEffort: ChatCompletionsPayload[\"reasoning_effort\"],\n): ChatCompletionsPayload[\"reasoning_effort\"] => {\n if (!reasoningEffort) {\n return undefined\n }\n\n return getAllowedReasoningEfforts(modelId).includes(reasoningEffort) ?\n reasoningEffort\n : undefined\n}\n\nconst normalizeReasoningEffort = (\n value: string | undefined | null,\n): ChatCompletionsPayload[\"reasoning_effort\"] => {\n switch (value?.toLowerCase()) {\n case \"none\": {\n return \"none\"\n }\n case \"low\": {\n return \"low\"\n }\n case \"medium\": {\n return \"medium\"\n }\n case \"high\": {\n return \"high\"\n }\n case \"xhigh\": {\n return \"xhigh\"\n }\n case \"max\": {\n return \"max\"\n }\n default: {\n return undefined\n }\n }\n}\n\nconst normalizeClaudeOpus47Effort = (\n value: string | undefined | null,\n): ClaudeOpus47Effort | undefined => {\n switch (value?.toLowerCase()) {\n case \"low\": {\n return \"low\"\n }\n case \"medium\": {\n return \"medium\"\n }\n case \"high\": {\n return \"high\"\n }\n case \"xhigh\": {\n return \"xhigh\"\n }\n case \"max\": {\n return \"max\"\n }\n default: {\n return undefined\n }\n }\n}\n\nconst getRequestedReasoningEffort = (\n payload: ChatCompletionsPayload,\n claudeSettingsEnv: Record<string, string>,\n): ChatCompletionsPayload[\"reasoning_effort\"] => {\n const requestedReasoningEffort =\n payload.reasoning_effort\n ?? normalizeReasoningEffort(process.env.COPILOT_REASONING_EFFORT)\n ?? normalizeReasoningEffort(claudeSettingsEnv.COPILOT_REASONING_EFFORT)\n\n return (\n sanitizeReasoningEffortForModel(payload.model, requestedReasoningEffort)\n ?? defaultReasoningEffort(payload.model)\n )\n}\n\nconst getRequestedClaudeOpus47Effort = (\n payload: ChatCompletionsPayload,\n claudeSettingsEnv: Record<string, string>,\n): ClaudeOpus47Effort | undefined => {\n if (!isClaudeOpus47Model(payload.model)) {\n return undefined\n }\n\n return (\n payload.output_config?.effort\n ?? normalizeClaudeOpus47Effort(payload.reasoning_effort)\n ?? normalizeClaudeOpus47Effort(process.env.COPILOT_REASONING_EFFORT)\n ?? normalizeClaudeOpus47Effort(claudeSettingsEnv.COPILOT_REASONING_EFFORT)\n )\n}\n\nexport const sanitizeUserIdentifier = (\n user: string | null | undefined,\n): string | undefined => {\n if (!user) {\n return undefined\n }\n\n return user.slice(0, MAX_USER_LENGTH)\n}\n\ntype ChatCompletionsRequestPayload = Omit<\n ChatCompletionsPayload,\n \"max_tokens\"\n> & {\n max_tokens?: number | null\n max_completion_tokens?: number | null\n}\n\nconst buildRequestPayload = (\n payload: ChatCompletionsPayload,\n claudeSettingsEnv: Record<string, string>,\n): ChatCompletionsRequestPayload => {\n const requestedReasoningEffort = getRequestedReasoningEffort(\n payload,\n claudeSettingsEnv,\n )\n const requestedClaudeOpus47Effort = getRequestedClaudeOpus47Effort(\n payload,\n claudeSettingsEnv,\n )\n\n const reasoningEffort =\n (\n usesMaxCompletionTokens(payload.model)\n && payload.tools !== null\n && payload.tools !== undefined\n && payload.tools.length > 0\n ) ?\n undefined\n : requestedReasoningEffort\n\n if (\n !usesMaxCompletionTokens(payload.model)\n || payload.max_tokens === null\n || payload.max_tokens === undefined\n ) {\n const sanitizedPayload = {\n ...payload,\n output_config:\n requestedClaudeOpus47Effort ?\n {\n ...payload.output_config,\n effort: requestedClaudeOpus47Effort,\n }\n : payload.output_config,\n reasoning_effort:\n isClaudeOpus47Model(payload.model) ? undefined : (\n payload.reasoning_effort\n ),\n user: sanitizeUserIdentifier(payload.user),\n }\n\n return reasoningEffort === null || reasoningEffort === undefined ?\n sanitizedPayload\n : { ...sanitizedPayload, reasoning_effort: reasoningEffort }\n }\n\n return {\n ...payload,\n max_tokens: undefined,\n max_completion_tokens: payload.max_tokens,\n reasoning_effort: reasoningEffort,\n user: sanitizeUserIdentifier(payload.user),\n }\n}\n\nconst isAgentInitiator = (\n messages: ChatCompletionsPayload[\"messages\"],\n): \"agent\" | \"user\" =>\n messages.some((msg) => msg.role === \"assistant\" || msg.role === \"tool\") ?\n \"agent\"\n : \"user\"\n\nconst messagesIncludeImage = (\n messages: ChatCompletionsPayload[\"messages\"],\n): boolean =>\n messages.some(\n (msg) =>\n typeof msg.content !== \"string\"\n && msg.content?.some((part) => part.type === \"image_url\"),\n )\n\nexport const createChatCompletions = async (\n config: BridgeConfig,\n payload: ChatCompletionsPayload,\n) => {\n const provider = getCopilotProviderContext(config)\n const enableVision = messagesIncludeImage(payload.messages)\n const initiator = isAgentInitiator(payload.messages)\n const claudeSettingsEnv = await getClaudeSettingsEnv()\n const requestPayload = buildRequestPayload(payload, claudeSettingsEnv)\n\n if (shouldUseResponsesApiForModel(payload.model)) {\n return createResponses(provider, payload, claudeSettingsEnv, {\n vision: enableVision,\n initiator,\n })\n }\n\n const response = await fetchCopilot(\n provider,\n \"/chat/completions\",\n {\n method: \"POST\",\n headers: {\n accept: payload.stream ? \"text/event-stream\" : \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(requestPayload),\n },\n { vision: enableVision, initiator },\n )\n\n if (!response.ok) {\n if (await shouldRetryWithResponses(response)) {\n return createResponses(provider, payload, claudeSettingsEnv, {\n vision: enableVision,\n initiator,\n })\n }\n\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\nasync function createResponses(\n provider: ReturnType<typeof getCopilotProviderContext>,\n payload: ChatCompletionsPayload,\n claudeSettingsEnv: Record<string, string>,\n options: { vision: boolean; initiator: \"agent\" | \"user\" },\n) {\n const reasoningEffort = getRequestedReasoningEffort(\n payload,\n claudeSettingsEnv,\n ) as ResponsesReasoningEffort | undefined\n\n const response = await fetchCopilot(\n provider,\n \"/responses\",\n {\n method: \"POST\",\n headers: {\n accept: payload.stream ? \"text/event-stream\" : \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(\n buildResponsesRequestPayload(payload, reasoningEffort),\n ),\n },\n { vision: options.vision, initiator: options.initiator },\n )\n\n if (!response.ok) {\n consola.error(\"Failed to create responses\", response)\n throw new HTTPError(\"Failed to create responses\", response)\n }\n\n if (payload.stream) {\n return translateResponsesStreamToChatCompletionStream(events(response))\n }\n\n return translateResponsesToChatCompletion(\n (await response.json()) as ResponsesApiResponse,\n )\n}\n\nasync function shouldRetryWithResponses(response: Response): Promise<boolean> {\n try {\n const errorBody = (await response.clone().json()) as {\n error?: {\n code?: string\n }\n }\n\n return errorBody.error?.code === \"unsupported_api_for_model\"\n } catch {\n return false\n }\n}\n","import { Hono } from \"hono\"\nimport { streamSSE, type SSEMessage } from \"hono/streaming\"\n\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { BridgeNotImplementedError, HTTPError } from \"~/lib/error\"\nimport { checkRateLimit, RateLimitError } from \"~/lib/rate-limit\"\nimport type {\n ChatCompletionResponse,\n ChatCompletionsPayload,\n} from \"~/providers/copilot/chat-types\"\nimport { createChatCompletions } from \"~/services/copilot/create-chat-completions\"\n\nexport const chatCompletionRoutes = new Hono<BridgeEnv>()\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse =>\n typeof response === \"object\"\n && response !== null\n && Object.hasOwn(response, \"choices\")\n\nchatCompletionRoutes.post(\"/\", async (c) => {\n try {\n await checkRateLimit()\n const payload = await c.req.json<ChatCompletionsPayload>()\n const response = await createChatCompletions(c.var.config, payload)\n\n if (isNonStreaming(response)) {\n return c.json(response)\n }\n\n return streamSSE(c, async (stream) => {\n for await (const chunk of response) {\n await stream.writeSSE(chunk as SSEMessage)\n }\n })\n } catch (error) {\n if (error instanceof RateLimitError) {\n return c.json({ error: { message: error.message } }, 429)\n }\n if (error instanceof BridgeNotImplementedError) {\n return c.json(\n { error: { type: error.name, message: error.message } },\n 501,\n )\n }\n if (error instanceof HTTPError) {\n const text = await error.response.text().catch(() => \"\")\n return new Response(text, {\n status: error.response.status,\n headers: {\n \"content-type\":\n error.response.headers.get(\"content-type\") ?? \"application/json\",\n },\n })\n }\n throw error\n }\n})\n","import type { BridgeConfig } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { fetchCopilot, getCopilotProviderContext } from \"./client\"\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\nexport const createEmbeddings = async (\n config: BridgeConfig,\n payload: EmbeddingRequest,\n): Promise<EmbeddingResponse> => {\n const provider = getCopilotProviderContext(config)\n const response = await fetchCopilot(provider, \"/embeddings\", {\n method: \"POST\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to create embeddings\", response)\n }\n\n return (await response.json()) as EmbeddingResponse\n}\n","import { Hono } from \"hono\"\n\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { checkRateLimit, RateLimitError } from \"~/lib/rate-limit\"\nimport {\n createEmbeddings,\n type EmbeddingRequest,\n} from \"~/providers/copilot/create-embeddings\"\n\nexport const embeddingRoutes = new Hono<BridgeEnv>()\n\nembeddingRoutes.post(\"/\", async (c) => {\n try {\n await checkRateLimit()\n const payload = await c.req.json<EmbeddingRequest>()\n const response = await createEmbeddings(c.var.config, payload)\n return c.json(response)\n } catch (error) {\n if (error instanceof RateLimitError) {\n return c.json({ error: { message: error.message } }, 429)\n }\n if (error instanceof HTTPError) {\n const text = await error.response.text().catch(() => \"\")\n return new Response(text, {\n status: error.response.status,\n headers: {\n \"content-type\":\n error.response.headers.get(\"content-type\") ?? \"application/json\",\n },\n })\n }\n throw error\n }\n})\n","import type { Model } from \"~/providers/copilot/get-models\"\n\nimport { runtimeState } from \"./state\"\n\nconst normalizeModelId = (modelId: string): string =>\n modelId.trim().toLowerCase().replaceAll(/[\\s._-]+/g, \"\")\n\nconst stripSnapshotSuffix = (modelId: string): string => {\n const id = modelId.trim().toLowerCase().replace(/\\[1m\\]$/, \"\")\n\n if (id.startsWith(\"claude-sonnet-4-\")) {\n return \"claude-sonnet-4\"\n }\n\n if (/^claude-opus-4-7-\\d{8}$/.test(id)) {\n return \"claude-opus-4.7\"\n }\n\n if (id.startsWith(\"claude-opus-4-\")) {\n return \"claude-opus-4\"\n }\n\n return id\n}\n\nconst getAliasCandidates = (modelId: string): Array<string> => {\n const canonicalModelId = stripSnapshotSuffix(modelId)\n const aliases = new Set<string>([canonicalModelId])\n\n const familyMatch = canonicalModelId.match(\n /^[a-z]+(?:-[a-z]+)*-\\d+(?:\\.\\d+)?/,\n )\n if (familyMatch) {\n aliases.add(familyMatch[0])\n aliases.add(familyMatch[0].replace(/\\.\\d+$/, \"\"))\n }\n\n if (/^gpt-5(?:[.-]\\d+)?$/i.test(canonicalModelId)) {\n aliases.add(\"gpt-5\")\n }\n\n return [...aliases]\n}\n\nconst scoreModelCandidate = (model: Model): number => {\n let score = 0\n\n if (model.model_picker_enabled) {\n score += 20\n }\n\n if (!model.preview) {\n score += 10\n }\n\n if (/mini|nano|fast|flash|haiku/i.test(model.id)) {\n score -= 15\n }\n\n return score - model.id.length / 1000\n}\n\nconst pickBestModel = (models: Array<Model>): Model | undefined =>\n [...models].sort(\n (left, right) => scoreModelCandidate(right) - scoreModelCandidate(left),\n )[0]\n\nconst getBestPrefixMatches = (\n models: Array<Model>,\n aliasCandidates: Array<string>,\n): Array<Model> => {\n let bestMatchLength = 0\n const matches: Array<Model> = []\n\n for (const model of models) {\n const normalizedModelId = normalizeModelId(model.id)\n const matchedAliasLength = Math.max(\n 0,\n ...aliasCandidates.map((candidate) => {\n const normalizedCandidate = normalizeModelId(candidate)\n return normalizedCandidate.length >= 4\n && normalizedModelId.startsWith(normalizedCandidate)\n ? normalizedCandidate.length\n : 0\n }),\n )\n\n if (matchedAliasLength === 0) continue\n\n if (matchedAliasLength > bestMatchLength) {\n bestMatchLength = matchedAliasLength\n matches.length = 0\n matches.push(model)\n continue\n }\n\n if (matchedAliasLength === bestMatchLength) {\n matches.push(model)\n }\n }\n\n return matches\n}\n\nexport const resolveModel = (\n requestedModelId: string,\n models: Array<Model> | undefined = runtimeState.models?.data,\n): Model | undefined => {\n if (!models || models.length === 0) {\n return undefined\n }\n\n const exactMatch = models.find((model) => model.id === requestedModelId)\n if (exactMatch) return exactMatch\n\n const aliasCandidates = getAliasCandidates(requestedModelId)\n const normalizedAliases = new Set(\n aliasCandidates.map((candidate) => normalizeModelId(candidate)),\n )\n\n const normalizedExactMatches = models.filter((model) =>\n normalizedAliases.has(normalizeModelId(model.id)),\n )\n if (normalizedExactMatches.length > 0) {\n return pickBestModel(normalizedExactMatches)\n }\n\n const familyPrefixMatches = getBestPrefixMatches(models, aliasCandidates)\n return pickBestModel(familyPrefixMatches)\n}\n\nexport const resolveUpstreamModelId = (\n requestedModelId: string,\n models: Array<Model> | undefined = runtimeState.models?.data,\n): string =>\n resolveModel(requestedModelId, models)?.id ?? stripSnapshotSuffix(requestedModelId)\n","import type { AnthropicResponse } from \"~/bridges/claude/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\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\n return stopReasonMap[finishReason]\n}\n","import { resolveUpstreamModelId } from \"~/lib/models-resolver\"\nimport { sanitizeReasoningEffortForModel } from \"~/services/copilot/create-chat-completions\"\nimport type {\n ChatCompletionResponse,\n ChatCompletionsPayload,\n ContentPart,\n Message,\n TextPart,\n Tool,\n ToolCall,\n} from \"~/providers/copilot/chat-types\"\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 \"~/bridges/claude/anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"~/bridges/claude/utils\"\n\nconst normalizeClaudeModelAlias = (model: string): string => {\n const normalized = model.trim().toLowerCase().replace(/\\[1m\\]$/, \"\")\n\n if (/^claude-(opus|sonnet|haiku)-\\d-\\d(?:-1m)?$/.test(normalized)) {\n return normalized.replace(\n /^claude-(opus|sonnet|haiku)-(\\d)-(\\d)(-1m)?$/,\n \"claude-$1-$2.$3$4\",\n )\n }\n\n if (/^claude-opus-4-7-\\d{8}$/.test(normalized)) {\n return \"claude-opus-4.7\"\n }\n\n return normalized\n}\n\nfunction translateModelName(model: string): string {\n return resolveUpstreamModelId(normalizeClaudeModelAlias(model))\n}\n\nfunction isClaudeModel(modelId: string): boolean {\n return modelId.startsWith(\"claude-\")\n}\n\nfunction isClaudeOpus47Model(modelId: string): boolean {\n return modelId.startsWith(\"claude-opus-4.7\")\n}\n\ntype ClaudeOpus47Effort = NonNullable<\n NonNullable<ChatCompletionsPayload[\"output_config\"]>[\"effort\"]\n>\n\nfunction normalizeClaudeEffort(\n value: string | undefined,\n): ClaudeOpus47Effort | undefined {\n switch (value?.toLowerCase()) {\n case \"low\": {\n return \"low\"\n }\n case \"medium\": {\n return \"medium\"\n }\n case \"high\": {\n return \"high\"\n }\n case \"xhigh\": {\n return \"xhigh\"\n }\n case \"max\": {\n return \"max\"\n }\n default: {\n return undefined\n }\n }\n}\n\nfunction getClaudeOpus47Effort(\n payload: AnthropicMessagesPayload,\n): ClaudeOpus47Effort | undefined {\n const explicitEffort = normalizeClaudeEffort(payload.reasoning_effort)\n if (explicitEffort) {\n return explicitEffort\n }\n\n if (payload.thinking?.type !== \"enabled\") {\n return undefined\n }\n\n const budgetTokens = payload.thinking.budget_tokens\n if (budgetTokens === undefined) {\n return \"medium\"\n }\n\n if (budgetTokens <= 2_048) {\n return \"low\"\n }\n\n if (budgetTokens <= 8_192) {\n return \"medium\"\n }\n\n if (budgetTokens <= 24_576) {\n return \"high\"\n }\n\n return \"xhigh\"\n}\n\nfunction translateThinking(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload[\"thinking\"] {\n const modelId = translateModelName(payload.model)\n\n if (!isClaudeOpus47Model(modelId)) {\n return undefined\n }\n\n if (payload.thinking?.type === \"adaptive\") {\n return { type: \"adaptive\" }\n }\n\n return payload.thinking?.type === \"enabled\" ? { type: \"adaptive\" } : undefined\n}\n\nfunction translateOutputConfig(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload[\"output_config\"] {\n const modelId = translateModelName(payload.model)\n\n if (!isClaudeOpus47Model(modelId)) {\n return undefined\n }\n\n const effort = getClaudeOpus47Effort(payload)\n\n return effort ? { effort } : undefined\n}\n\nfunction normalizeReasoningEffort(\n value: string,\n): ChatCompletionsPayload[\"reasoning_effort\"] {\n switch (value.toLowerCase()) {\n case \"none\": {\n return \"none\"\n }\n case \"low\": {\n return \"low\"\n }\n case \"medium\": {\n return \"medium\"\n }\n case \"high\": {\n return \"high\"\n }\n case \"xhigh\": {\n return \"xhigh\"\n }\n case \"max\": {\n return \"max\"\n }\n default: {\n return undefined\n }\n }\n}\n\nfunction translateReasoningEffort(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload[\"reasoning_effort\"] {\n const modelId = translateModelName(payload.model)\n\n if (isClaudeModel(modelId)) {\n return undefined\n }\n\n if (payload.reasoning_effort) {\n const requested = normalizeReasoningEffort(payload.reasoning_effort)\n return sanitizeReasoningEffortForModel(modelId, requested)\n }\n\n if (payload.thinking?.type !== \"enabled\") {\n return undefined\n }\n\n const budgetTokens = payload.thinking.budget_tokens\n if (budgetTokens === undefined) {\n return sanitizeReasoningEffortForModel(modelId, \"medium\")\n }\n\n if (budgetTokens <= 2_048) {\n return sanitizeReasoningEffortForModel(modelId, \"low\")\n }\n\n if (budgetTokens <= 8_192) {\n return sanitizeReasoningEffortForModel(modelId, \"medium\")\n }\n\n if (budgetTokens <= 24_576) {\n return sanitizeReasoningEffortForModel(modelId, \"high\")\n }\n\n return sanitizeReasoningEffortForModel(modelId, \"xhigh\")\n}\n\nexport function translateToOpenAI(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload {\n const model = translateModelName(payload.model)\n\n return {\n model,\n messages: translateAnthropicMessagesToOpenAI(payload.messages, payload.system),\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 thinking: translateThinking(payload),\n output_config: translateOutputConfig(payload),\n reasoning_effort: translateReasoningEffort(payload),\n user: payload.metadata?.user_id,\n tools: translateAnthropicToolsToOpenAI(payload.tools),\n tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),\n }\n}\n\nfunction translateAnthropicMessagesToOpenAI(\n anthropicMessages: Array<AnthropicMessage>,\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n const systemMessages = handleSystemPrompt(system)\n const otherMessages = anthropicMessages.flatMap((message) =>\n message.role === \"user\" ? handleUserMessage(message) : handleAssistantMessage(message),\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 }\n\n return [{ role: \"system\", content: system.map((block) => block.text).join(\"\\n\\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 => block.type === \"tool_result\",\n )\n const otherBlocks = message.content.filter((block) => block.type !== \"tool_result\")\n\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(message: AnthropicAssistantMessage): Array<Message> {\n if (!Array.isArray(message.content)) {\n return [{ role: \"assistant\", content: mapContent(message.content) }]\n }\n\n const toolUseBlocks = message.content.filter(\n (block): block is AnthropicToolUseBlock => block.type === \"tool_use\",\n )\n const textBlocks = message.content.filter(\n (block): block is AnthropicTextBlock => block.type === \"text\",\n )\n const thinkingBlocks = message.content.filter(\n (block): block is AnthropicThinkingBlock => block.type === \"thinking\",\n )\n\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 : [{ role: \"assistant\", content: mapContent(message.content) }]\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\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 break\n }\n case \"thinking\": {\n contentParts.push({ type: \"text\", text: block.thinking })\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 break\n }\n }\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\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\nexport function translateToAnthropic(\n response: ChatCompletionResponse,\n): AnthropicResponse {\n const allTextBlocks: Array<AnthropicTextBlock> = []\n const allToolUseBlocks: Array<AnthropicToolUseBlock> = []\n let stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null = null\n\n stopReason = response.choices[0]?.finish_reason ?? stopReason\n\n for (const choice of response.choices) {\n allTextBlocks.push(...getAnthropicTextBlocks(choice.message.content))\n allToolUseBlocks.push(...getAnthropicToolUseBlocks(choice.message.tool_calls))\n\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\n stopReason = choice.finish_reason\n }\n }\n\n return {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n model: response.model,\n content: [...allTextBlocks, ...allToolUseBlocks],\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\n stop_sequence: null,\n usage: {\n input_tokens:\n (response.usage?.prompt_tokens ?? 0)\n - (response.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: response.usage?.completion_tokens ?? 0,\n ...(response.usage?.prompt_tokens_details?.cached_tokens !== undefined && {\n cache_read_input_tokens: 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\n return toolCalls.map((toolCall) => ({\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: safeJsonParse(toolCall.function.arguments),\n }))\n}\n\nfunction safeJsonParse(input: string): Record<string, unknown> {\n try {\n return JSON.parse(input) as Record<string, unknown>\n } catch {\n return { raw: input }\n }\n}\n","import type {\n AnthropicStreamEventData,\n AnthropicStreamState,\n} from \"~/bridges/claude/anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"~/bridges/claude/utils\"\nimport type { ChatCompletionChunk } from \"~/providers/copilot/chat-types\"\n\nfunction isToolBlockOpen(state: AnthropicStreamState): boolean {\n if (!state.contentBlockOpen) {\n return false\n }\n\n return Object.values(state.toolCalls).some(\n (tc) => tc.anthropicBlockIndex === state.contentBlockIndex,\n )\n}\n\nexport function translateChunkToAnthropicEvents(\n chunk: ChatCompletionChunk,\n state: AnthropicStreamState,\n): Array<AnthropicStreamEventData> {\n const events: Array<AnthropicStreamEventData> = []\n\n if (chunk.choices.length === 0) {\n return events\n }\n\n const choice = chunk.choices[0]\n const { delta } = choice\n\n if (!state.messageStartSent) {\n events.push({\n type: \"message_start\",\n message: {\n id: chunk.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: chunk.model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens:\n (chunk.usage?.prompt_tokens ?? 0)\n - (chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: 0,\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens !== undefined && {\n cache_read_input_tokens: chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n })\n state.messageStartSent = true\n }\n\n if (delta.content) {\n if (isToolBlockOpen(state)) {\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 if (state.contentBlockOpen) {\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 if (toolCallInfo) {\n events.push({\n type: \"content_block_delta\",\n index: toolCallInfo.anthropicBlockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: toolCall.function.arguments,\n },\n })\n }\n }\n }\n }\n\n if (choice.finish_reason) {\n if (state.contentBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockOpen = false\n }\n\n events.push(\n {\n type: \"message_delta\",\n delta: {\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\n stop_sequence: null,\n },\n usage: {\n input_tokens:\n (chunk.usage?.prompt_tokens ?? 0)\n - (chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: chunk.usage?.completion_tokens ?? 0,\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens !== undefined && {\n cache_read_input_tokens: chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n {\n type: \"message_stop\",\n },\n )\n }\n\n return events\n}\n\nexport function translateErrorToAnthropicErrorEvent(): AnthropicStreamEventData {\n return {\n type: \"error\",\n error: {\n type: \"api_error\",\n message: \"An unexpected error occurred during streaming.\",\n },\n }\n}\n","import type {\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n ToolCall,\n} from \"~/providers/copilot/chat-types\"\nimport type { Model } from \"~/providers/copilot/get-models\"\n\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\ninterface Encoder {\n encode: (text: string) => Array<number>\n}\n\nconst encodingCache = new Map<string, Encoder>()\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\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\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\") tokens += tokensPerName\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\nconst calculateTokens = (\n messages: Array<Message>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (messages.length === 0) return 0\n let numTokens = 0\n for (const message of messages) {\n numTokens += calculateMessageTokens(message, encoder, constants)\n }\n numTokens += 3\n return numTokens\n}\n\nconst getEncodeChatFunction = async (encoding: string): Promise<Encoder> => {\n if (encodingCache.has(encoding)) {\n const cached = encodingCache.get(encoding)\n if (cached) return cached\n }\n\n const supported = encoding as SupportedEncoding\n if (!(supported in ENCODING_MAP)) {\n const fallback = (await ENCODING_MAP.o200k_base()) as Encoder\n encodingCache.set(encoding, fallback)\n return fallback\n }\n\n const mod = (await ENCODING_MAP[supported]()) as Encoder\n encodingCache.set(encoding, mod)\n return mod\n}\n\nexport const getTokenizerFromModel = (model: Model): string =>\n model.capabilities.tokenizer || \"o200k_base\"\n\nconst getModelConstants = (model: Model) =>\n 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\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 if (typeof prop !== \"object\" || prop === null) return tokens\n\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 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 if (paramDesc.endsWith(\".\")) paramDesc = paramDesc.slice(0, -1)\n\n const line = `${paramName}:${paramType}:${paramDesc}`\n tokens += encoder.encode(line).length\n\n const excludedKeys = new Set([\"type\", \"description\", \"enum\"])\n for (const propertyName of Object.keys(param)) {\n if (excludedKeys.has(propertyName)) continue\n const propertyValue = param[propertyName]\n const propertyText =\n typeof propertyValue === \"string\"\n ? propertyValue\n : JSON.stringify(propertyValue)\n tokens += encoder.encode(`${propertyName}:${propertyText}`).length\n }\n\n return tokens\n}\n\nconst calculateParametersTokens = (\n parameters: unknown,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (!parameters || typeof parameters !== \"object\") return 0\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\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(\".\")) fDesc = fDesc.slice(0, -1)\n tokens += encoder.encode(`${fName}:${fDesc}`).length\n if (typeof func.parameters === \"object\" && func.parameters !== null) {\n tokens += calculateParametersTokens(func.parameters, encoder, constants)\n }\n return tokens\n}\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\nexport const getTokenCount = async (\n payload: ChatCompletionsPayload,\n model: Model,\n): Promise<{ input: number; output: number }> => {\n const tokenizer = getTokenizerFromModel(model)\n const encoder = await getEncodeChatFunction(tokenizer)\n\n const inputMessages = payload.messages.filter((msg) => msg.role !== \"assistant\")\n const outputMessages = payload.messages.filter((msg) => msg.role === \"assistant\")\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 { input: inputTokens, output: outputTokens }\n}\n","import consola from \"consola\"\nimport { Hono } from \"hono\"\nimport { streamSSE } from \"hono/streaming\"\n\nimport {\n type AnthropicMessagesPayload,\n type AnthropicStreamState,\n} from \"~/bridges/claude/anthropic-types\"\nimport {\n translateToAnthropic,\n translateToOpenAI,\n} from \"~/bridges/claude/non-stream-translation\"\nimport {\n translateChunkToAnthropicEvents,\n translateErrorToAnthropicErrorEvent,\n} from \"~/bridges/claude/stream-translation\"\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { BridgeNotImplementedError, HTTPError } from \"~/lib/error\"\nimport { checkRateLimit, RateLimitError } from \"~/lib/rate-limit\"\nimport { resolveModel } from \"~/lib/models-resolver\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\nimport type {\n ChatCompletionChunk,\n ChatCompletionResponse,\n} from \"~/providers/copilot/chat-types\"\nimport { createChatCompletions } from \"~/services/copilot/create-chat-completions\"\n\nexport const messageRoutes = new Hono<BridgeEnv>()\n\nconst isNonStreamingResponse = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse =>\n typeof response === \"object\"\n && response !== null\n && Object.hasOwn(response, \"choices\")\n\nmessageRoutes.post(\"/\", async (c) => {\n const config = c.get(\"config\")\n try {\n await checkRateLimit()\n } catch (error) {\n if (error instanceof RateLimitError) {\n return c.json({ error: { message: error.message } }, 429)\n }\n throw error\n }\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n try {\n const response = await createChatCompletions(config, openAIPayload)\n\n if (isNonStreamingResponse(response)) {\n return c.json(translateToAnthropic(response))\n }\n\n return streamSSE(c, async (stream) => {\n const streamState: AnthropicStreamState = {\n messageStartSent: false,\n contentBlockIndex: 0,\n contentBlockOpen: false,\n toolCalls: {},\n }\n\n try {\n for await (const rawEvent of response) {\n if (rawEvent.data === \"[DONE]\") {\n break\n }\n\n if (!rawEvent.data) {\n continue\n }\n\n let chunk: ChatCompletionChunk\n try {\n chunk = JSON.parse(rawEvent.data) as ChatCompletionChunk\n } catch {\n continue\n }\n\n const events = translateChunkToAnthropicEvents(chunk, streamState)\n for (const event of events) {\n await stream.writeSSE({\n event: event.type,\n data: JSON.stringify(event),\n })\n }\n }\n } catch (error) {\n consola.error(\"Error during Anthropic stream translation:\", error)\n const errorEvent = translateErrorToAnthropicErrorEvent()\n await stream.writeSSE({\n event: errorEvent.type,\n data: JSON.stringify(errorEvent),\n })\n }\n })\n } catch (error) {\n if (error instanceof BridgeNotImplementedError) {\n return c.json(\n { error: { type: error.name, message: error.message } },\n 501,\n )\n }\n\n if (error instanceof HTTPError) {\n const text = await error.response.text().catch(() => \"\")\n return new Response(text, {\n status: error.response.status,\n headers: {\n \"content-type\":\n error.response.headers.get(\"content-type\") ?? \"application/json\",\n },\n })\n }\n\n throw error\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n const selectedModel = resolveModel(openAIPayload.model)\n\n if (!selectedModel) {\n consola.warn(\n `Model ${openAIPayload.model} not found in registry, returning fallback token count`,\n )\n return c.json({ input_tokens: 1 })\n }\n\n const tokenCount = await getTokenCount(openAIPayload, selectedModel)\n const effectiveModelId = selectedModel.id\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 (effectiveModelId.startsWith(\"claude\")) {\n tokenCount.input += 346\n } else if (effectiveModelId.startsWith(\"grok\")) {\n tokenCount.input += 480\n }\n }\n }\n\n let finalTokenCount = tokenCount.input + tokenCount.output\n if (effectiveModelId.startsWith(\"claude\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.15)\n } else if (effectiveModelId.startsWith(\"grok\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.03)\n }\n\n return c.json({ input_tokens: Math.max(1, finalTokenCount) })\n } catch (error) {\n consola.error(\"Error counting tokens:\", error)\n return c.json({ input_tokens: 1 })\n }\n})\n","import { Hono } from \"hono\"\n\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { BridgeNotImplementedError } from \"~/lib/error\"\nimport {\n fetchCopilot,\n getCopilotProviderContext,\n} from \"~/providers/copilot/client\"\n\nexport const modelRoutes = new Hono<BridgeEnv>()\n\nmodelRoutes.get(\"/\", async (c) => {\n const config = c.get(\"config\")\n const provider = getCopilotProviderContext(config)\n const search = new URL(c.req.url).search\n\n try {\n const upstream = await fetchCopilot(provider, `/models${search}`, {\n method: \"GET\",\n headers: {\n accept: c.req.header(\"accept\") ?? \"application/json\",\n },\n })\n\n return new Response(upstream.body, {\n status: upstream.status,\n headers: upstream.headers,\n })\n } catch (error) {\n if (error instanceof BridgeNotImplementedError) {\n return c.json(\n {\n error: {\n type: error.name,\n message: error.message,\n },\n },\n 500,\n )\n }\n\n throw error\n }\n})\n","// Translation layer: Codex /v1/responses ⇄ Copilot /v1/chat/completions.\n// Used for models that do not implement the Responses API upstream\n// (claude-*, gemini-*).\n//\n// Strategy:\n// - Translate the Responses request to a Chat Completions request.\n// - Force upstream to non-stream (stream: false) so we get a single JSON.\n// - Translate that JSON to a Responses API JSON.\n// - If the original request asked for stream:true, synthesize a tiny\n// sequence of SSE events (response.created → output_item.added →\n// content_part.added → output_text.delta → ... → response.completed)\n// so codex's bookkeeping still works.\n\nimport { randomUUID } from \"node:crypto\"\n\nimport type { ModelCapability, ReasoningEffort } from \"~/lib/model-capabilities\"\n\n// ---------- Responses (input) types — only what we read ----------\n\ninterface ResponsesInputMessage {\n type?: \"message\"\n role: \"user\" | \"assistant\" | \"system\" | \"developer\"\n content: string | Array<ResponsesInputContentPart>\n}\n\ninterface ResponsesInputContentPart {\n type:\n | \"input_text\"\n | \"output_text\"\n | \"input_image\"\n | \"text\"\n text?: string\n image_url?: string | { url: string }\n detail?: \"low\" | \"high\" | \"auto\"\n}\n\ninterface ResponsesFunctionCallInput {\n type: \"function_call\"\n call_id: string\n name: string\n arguments: string\n}\n\ninterface ResponsesFunctionCallOutputInput {\n type: \"function_call_output\"\n call_id: string\n output: string\n}\n\ntype ResponsesInputItem =\n | ResponsesInputMessage\n | ResponsesFunctionCallInput\n | ResponsesFunctionCallOutputInput\n\ninterface ResponsesTool {\n type: \"function\"\n name?: string\n description?: string\n parameters?: Record<string, unknown>\n function?: {\n name: string\n description?: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ResponsesRequestLike {\n model: string\n input?: string | Array<ResponsesInputItem>\n instructions?: string\n stream?: boolean\n max_output_tokens?: number\n temperature?: number\n top_p?: number\n user?: string\n tools?: Array<ResponsesTool>\n tool_choice?:\n | \"auto\"\n | \"none\"\n | \"required\"\n | { type: \"function\"; name: string }\n reasoning?: { effort?: ReasoningEffort; [k: string]: unknown }\n [key: string]: unknown\n}\n\n// ---------- Chat completion types — only what we send/read ----------\n\ntype ChatRole = \"system\" | \"user\" | \"assistant\" | \"tool\"\n\ninterface ChatContentPart {\n type: \"text\" | \"image_url\"\n text?: string\n image_url?: { url: string; detail?: \"low\" | \"high\" | \"auto\" }\n}\n\ninterface ChatToolCall {\n id: string\n type: \"function\"\n function: { name: string; arguments: string }\n}\n\ninterface ChatMessage {\n role: ChatRole\n content?: string | Array<ChatContentPart> | null\n name?: string\n tool_call_id?: string\n tool_calls?: Array<ChatToolCall>\n}\n\ninterface ChatTool {\n type: \"function\"\n function: {\n name: string\n description?: string\n parameters?: Record<string, unknown>\n }\n}\n\ninterface ChatRequestPayload {\n model: string\n messages: Array<ChatMessage>\n stream: boolean\n max_tokens?: number\n temperature?: number\n top_p?: number\n user?: string\n tools?: Array<ChatTool>\n tool_choice?: unknown\n reasoning_effort?: ReasoningEffort\n output_config?: { effort?: ReasoningEffort }\n}\n\ninterface ChatCompletionResponse {\n id?: string\n created?: number\n model?: string\n choices: Array<{\n index?: number\n message: ChatMessage & { role: \"assistant\" }\n finish_reason?: string | null\n }>\n usage?: {\n prompt_tokens?: number\n completion_tokens?: number\n total_tokens?: number\n }\n}\n\n// ---------- Helpers ----------\n\nconst collectText = (\n content: string | Array<ResponsesInputContentPart> | undefined,\n): { text: string; parts: Array<ChatContentPart> } => {\n if (typeof content === \"string\") {\n return { text: content, parts: [{ type: \"text\", text: content }] }\n }\n const parts: Array<ChatContentPart> = []\n let textBuf = \"\"\n for (const p of content ?? []) {\n if (p.type === \"input_text\" || p.type === \"output_text\" || p.type === \"text\") {\n const t = p.text ?? \"\"\n textBuf += t\n parts.push({ type: \"text\", text: t })\n } else if (p.type === \"input_image\") {\n const url =\n typeof p.image_url === \"string\" ?\n p.image_url\n : (p.image_url?.url ?? \"\")\n if (url) parts.push({ type: \"image_url\", image_url: { url, detail: p.detail } })\n }\n }\n return { text: textBuf, parts }\n}\n\nconst placeReasoning = (\n payload: ChatRequestPayload,\n capability: ModelCapability,\n effort: ReasoningEffort | undefined,\n) => {\n if (!effort || !capability.reasoning) return\n if (capability.reasoningField === \"output_config.effort\") {\n payload.output_config = { ...(payload.output_config ?? {}), effort }\n } else {\n payload.reasoning_effort = effort\n }\n}\n\n// ---------- Public: translate request ----------\n\nexport const responsesPayloadToChatPayload = (\n request: ResponsesRequestLike,\n capability: ModelCapability,\n): ChatRequestPayload => {\n const messages: Array<ChatMessage> = []\n\n if (request.instructions) {\n messages.push({ role: \"system\", content: request.instructions })\n }\n\n const inputItems: Array<ResponsesInputItem> =\n typeof request.input === \"string\" ?\n [{ role: \"user\", content: request.input } as ResponsesInputMessage]\n : (request.input ?? [])\n\n for (const item of inputItems) {\n if (\"role\" in item && (item.type === undefined || item.type === \"message\")) {\n const { text, parts } = collectText(item.content)\n const role: ChatRole =\n item.role === \"developer\" ? \"system\"\n : item.role === \"system\" ? \"system\"\n : item.role === \"assistant\" ? \"assistant\"\n : \"user\"\n // Use string content when single text part for simplicity.\n const useStringContent =\n parts.length <= 1 && parts.every((p) => p.type === \"text\")\n messages.push({\n role,\n content: useStringContent ? text : parts,\n })\n } else if (item.type === \"function_call\") {\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: [\n {\n id: item.call_id,\n type: \"function\",\n function: { name: item.name, arguments: item.arguments },\n },\n ],\n })\n } else if (item.type === \"function_call_output\") {\n messages.push({\n role: \"tool\",\n tool_call_id: item.call_id,\n content: item.output,\n })\n }\n }\n\n const tools: Array<ChatTool> | undefined = request.tools\n ?.filter((t) => {\n const name = t.function?.name ?? t.name\n return t.type === \"function\" && typeof name === \"string\" && name.length > 0\n })\n .map((t) => ({\n type: \"function\",\n function: {\n name: t.function?.name ?? t.name ?? \"\",\n description: t.function?.description ?? t.description,\n parameters: t.function?.parameters ?? t.parameters,\n },\n }))\n\n const payload: ChatRequestPayload = {\n model: capability.id,\n messages,\n stream: false, // always non-stream upstream; we synthesize SSE later\n max_tokens: request.max_output_tokens,\n temperature: request.temperature,\n top_p: request.top_p,\n user: request.user,\n tools: tools && tools.length > 0 ? tools : undefined,\n tool_choice:\n tools && tools.length > 0 ? request.tool_choice : undefined,\n }\n\n placeReasoning(payload, capability, request.reasoning?.effort)\n\n return payload\n}\n\n// ---------- Public: translate non-stream response ----------\n\ninterface ResponsesApiResult {\n id: string\n object: \"response\"\n status: \"completed\" | \"incomplete\"\n created_at: number\n model: string\n output: Array<\n | {\n id: string\n type: \"message\"\n role: \"assistant\"\n status: \"completed\"\n content: Array<{ type: \"output_text\"; text: string; annotations: [] }>\n }\n | {\n id: string\n type: \"function_call\"\n status: \"completed\"\n call_id: string\n name: string\n arguments: string\n }\n >\n usage?: {\n input_tokens: number\n output_tokens: number\n total_tokens: number\n }\n}\n\nconst buildResponsesResult = (\n request: ResponsesRequestLike,\n chat: ChatCompletionResponse,\n): ResponsesApiResult => {\n const choice = chat.choices[0]\n const message = choice?.message\n const text =\n typeof message?.content === \"string\" ?\n message.content\n : Array.isArray(message?.content) ?\n message.content\n .filter((p): p is ChatContentPart => p.type === \"text\")\n .map((p) => p.text ?? \"\")\n .join(\"\")\n : \"\"\n\n const output: ResponsesApiResult[\"output\"] = []\n if (text.length > 0) {\n output.push({\n id: `msg_${randomUUID()}`,\n type: \"message\",\n role: \"assistant\",\n status: \"completed\",\n content: [{ type: \"output_text\", text, annotations: [] }],\n })\n }\n for (const tc of message?.tool_calls ?? []) {\n output.push({\n id: `fc_${randomUUID()}`,\n type: \"function_call\",\n status: \"completed\",\n call_id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n })\n }\n\n return {\n id: chat.id ?? `resp_${randomUUID()}`,\n object: \"response\",\n status: \"completed\",\n created_at: chat.created ?? Math.floor(Date.now() / 1000),\n model: chat.model ?? request.model,\n output,\n usage:\n chat.usage ?\n {\n input_tokens: chat.usage.prompt_tokens ?? 0,\n output_tokens: chat.usage.completion_tokens ?? 0,\n total_tokens: chat.usage.total_tokens ?? 0,\n }\n : undefined,\n }\n}\n\nexport const chatResponseToResponsesJson = buildResponsesResult\n\n// ---------- Public: synthesize SSE stream ----------\n\nconst sse = (event: string, data: unknown) =>\n `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`\n\nexport const synthesizeResponsesSseFromChat = (\n request: ResponsesRequestLike,\n chat: ChatCompletionResponse,\n): ReadableStream<Uint8Array> => {\n const result = buildResponsesResult(request, chat)\n const encoder = new TextEncoder()\n const baseResponse = {\n id: result.id,\n object: \"response\",\n created_at: result.created_at,\n model: result.model,\n status: \"in_progress\",\n output: [] as unknown[],\n }\n\n return new ReadableStream<Uint8Array>({\n start(controller) {\n const push = (event: string, data: unknown) =>\n controller.enqueue(encoder.encode(sse(event, data)))\n\n push(\"response.created\", { type: \"response.created\", response: baseResponse })\n push(\"response.in_progress\", {\n type: \"response.in_progress\",\n response: baseResponse,\n })\n\n result.output.forEach((item, index) => {\n push(\"response.output_item.added\", {\n type: \"response.output_item.added\",\n output_index: index,\n item,\n })\n\n if (item.type === \"message\") {\n const text = item.content[0]?.text ?? \"\"\n const part = { type: \"output_text\", text: \"\", annotations: [] }\n push(\"response.content_part.added\", {\n type: \"response.content_part.added\",\n item_id: item.id,\n output_index: index,\n content_index: 0,\n part,\n })\n if (text) {\n push(\"response.output_text.delta\", {\n type: \"response.output_text.delta\",\n item_id: item.id,\n output_index: index,\n content_index: 0,\n delta: text,\n })\n }\n push(\"response.output_text.done\", {\n type: \"response.output_text.done\",\n item_id: item.id,\n output_index: index,\n content_index: 0,\n text,\n })\n push(\"response.content_part.done\", {\n type: \"response.content_part.done\",\n item_id: item.id,\n output_index: index,\n content_index: 0,\n part: { ...part, text },\n })\n } else if (item.type === \"function_call\") {\n if (item.arguments) {\n push(\"response.function_call_arguments.delta\", {\n type: \"response.function_call_arguments.delta\",\n item_id: item.id,\n output_index: index,\n delta: item.arguments,\n })\n }\n push(\"response.function_call_arguments.done\", {\n type: \"response.function_call_arguments.done\",\n item_id: item.id,\n output_index: index,\n arguments: item.arguments,\n })\n }\n\n push(\"response.output_item.done\", {\n type: \"response.output_item.done\",\n output_index: index,\n item,\n })\n })\n\n push(\"response.completed\", {\n type: \"response.completed\",\n response: { ...result, status: \"completed\" },\n })\n controller.close()\n },\n })\n}\n","interface ResponseMetadata {\n created_at?: number\n id?: string\n model?: string\n}\n\ninterface ResponsesStreamEvent {\n response?: ResponseMetadata\n type?: string\n [key: string]: unknown\n}\n\ninterface StableResponseMetadata {\n created_at: number\n id: string\n initialized: boolean\n model: string\n}\n\nconst normalizeEventPayload = (\n rawData: string,\n stableResponse: StableResponseMetadata,\n): string => {\n let event: ResponsesStreamEvent\n try {\n event = JSON.parse(rawData) as ResponsesStreamEvent\n } catch {\n return rawData\n }\n\n if (event.response && typeof event.response === \"object\") {\n const incoming = event.response\n if (!stableResponse.initialized) {\n if (incoming.id) stableResponse.id = incoming.id\n if (typeof incoming.created_at === \"number\")\n stableResponse.created_at = incoming.created_at\n if (incoming.model) stableResponse.model = incoming.model\n stableResponse.initialized = true\n }\n\n event.response = {\n ...incoming,\n ...(stableResponse.id ? { id: stableResponse.id } : {}),\n ...(stableResponse.created_at\n ? { created_at: stableResponse.created_at }\n : {}),\n ...(stableResponse.model ? { model: stableResponse.model } : {}),\n }\n }\n\n return JSON.stringify(event)\n}\n\nconst transformSseChunk = (\n chunk: string,\n stableResponse: StableResponseMetadata,\n): string => {\n const lines = chunk.split(\"\\n\")\n\n return lines\n .map((line) => {\n if (!line.startsWith(\"data: \")) {\n return line\n }\n\n const rawData = line.slice(6)\n if (!rawData || rawData === \"[DONE]\") {\n return line\n }\n\n return `data: ${normalizeEventPayload(rawData, stableResponse)}`\n })\n .join(\"\\n\")\n}\n\nexport const normalizeResponsesSseStream = (\n upstreamBody: ReadableStream<Uint8Array>,\n) => {\n const stableResponse: StableResponseMetadata = {\n created_at: 0,\n id: \"\",\n initialized: false,\n model: \"\",\n }\n\n const decoder = new TextDecoder()\n const encoder = new TextEncoder()\n let buffer = \"\"\n\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const reader = upstreamBody.getReader()\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n\n if (done) {\n break\n }\n\n buffer += decoder.decode(value, { stream: true })\n\n let separatorIndex = buffer.indexOf(\"\\n\\n\")\n\n while (separatorIndex !== -1) {\n const rawEvent = buffer.slice(0, separatorIndex)\n buffer = buffer.slice(separatorIndex + 2)\n\n const transformed = transformSseChunk(rawEvent, stableResponse)\n controller.enqueue(encoder.encode(`${transformed}\\n\\n`))\n\n separatorIndex = buffer.indexOf(\"\\n\\n\")\n }\n }\n\n if (buffer.length > 0) {\n const transformed = transformSseChunk(buffer, stableResponse)\n controller.enqueue(encoder.encode(transformed))\n }\n } finally {\n reader.releaseLock()\n }\n\n controller.close()\n },\n })\n}\n","import { z } from \"zod\"\n\nimport {\n clampReasoningEffort,\n getModelCapability,\n resolveModelId,\n} from \"~/lib/model-capabilities\"\n\nconst codexResponsesRequestSchema = z\n .object({\n model: z.string().min(1),\n stream: z.boolean().optional(),\n })\n .passthrough()\n\nexport type CodexResponsesRequest = z.infer<typeof codexResponsesRequestSchema>\n\ninterface ReasoningField {\n effort?: unknown\n [key: string]: unknown\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n\nexport const normalizeCodexResponsesRequest = (\n payload: CodexResponsesRequest,\n): CodexResponsesRequest => {\n const parsed = codexResponsesRequestSchema.parse(payload) as CodexResponsesRequest\n & { reasoning?: ReasoningField }\n\n const canonical = resolveModelId(parsed.model)\n const capability = getModelCapability(canonical)\n if (!capability) return parsed\n\n const next = { ...parsed, model: canonical } as typeof parsed\n\n if (!capability.reasoning) {\n if (\"reasoning\" in next) {\n delete (next as Record<string, unknown>).reasoning\n }\n return next\n }\n\n const incoming: ReasoningField | undefined =\n isPlainObject(next.reasoning) ? (next.reasoning as ReasoningField) : undefined\n const clamped = clampReasoningEffort(canonical, incoming?.effort)\n if (clamped) {\n next.reasoning = { ...(incoming ?? {}), effort: clamped.effort }\n }\n\n return next\n}\n","import { Hono } from \"hono\"\n\nimport {\n chatResponseToResponsesJson,\n responsesPayloadToChatPayload,\n synthesizeResponsesSseFromChat,\n type ResponsesRequestLike,\n} from \"~/bridges/codex/chat-fallback\"\nimport { normalizeResponsesSseStream } from \"~/bridges/codex/normalize-stream\"\nimport { normalizeCodexResponsesRequest } from \"~/bridges/codex/responses\"\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { BridgeNotImplementedError } from \"~/lib/error\"\nimport { getModelCapability } from \"~/lib/model-capabilities\"\nimport { checkRateLimit, RateLimitError } from \"~/lib/rate-limit\"\nimport {\n fetchCopilot,\n getCopilotProviderContext,\n} from \"~/providers/copilot/client\"\n\nexport const responsesRoutes = new Hono<BridgeEnv>()\n\nresponsesRoutes.post(\"/\", async (c) => {\n try {\n await checkRateLimit()\n } catch (error) {\n if (error instanceof RateLimitError) {\n return c.json({ error: { message: error.message } }, 429)\n }\n throw error\n }\n const rawPayload = (await c.req.json()) as ResponsesRequestLike\n const payload = normalizeCodexResponsesRequest(\n rawPayload as unknown as Parameters<typeof normalizeCodexResponsesRequest>[0],\n ) as unknown as ResponsesRequestLike\n const config = c.get(\"config\")\n const provider = getCopilotProviderContext(config)\n const search = new URL(c.req.url).search\n\n const capability = getModelCapability(payload.model)\n\n try {\n if (capability?.fallback === \"chat-completions\") {\n const chatPayload = responsesPayloadToChatPayload(payload, capability)\n const upstream = await fetchCopilot(provider, `/chat/completions${search}`, {\n method: \"POST\",\n headers: { accept: \"application/json\", \"content-type\": \"application/json\" },\n body: JSON.stringify(chatPayload),\n })\n\n if (!upstream.ok) {\n const text = await upstream.text()\n return new Response(text, {\n status: upstream.status,\n headers: { \"content-type\": upstream.headers.get(\"content-type\") ?? \"application/json\" },\n })\n }\n\n const chatJson = (await upstream.json()) as Parameters<\n typeof chatResponseToResponsesJson\n >[1]\n\n if (payload.stream) {\n const stream = synthesizeResponsesSseFromChat(payload, chatJson)\n return new Response(stream, {\n status: 200,\n headers: {\n \"content-type\": \"text/event-stream; charset=utf-8\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n },\n })\n }\n\n const responsesJson = chatResponseToResponsesJson(payload, chatJson)\n return new Response(JSON.stringify(responsesJson), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n })\n }\n\n const upstream = await fetchCopilot(provider, `/responses${search}`, {\n method: \"POST\",\n headers: {\n accept: c.req.header(\"accept\") ?? \"application/json\",\n \"content-type\": c.req.header(\"content-type\") ?? \"application/json\",\n },\n body: JSON.stringify(payload),\n })\n\n const contentType = upstream.headers.get(\"content-type\") ?? \"\"\n\n if (payload.stream && upstream.body && contentType.includes(\"text/event-stream\")) {\n return new Response(normalizeResponsesSseStream(upstream.body), {\n status: upstream.status,\n headers: upstream.headers,\n })\n }\n\n return new Response(upstream.body, {\n status: upstream.status,\n headers: upstream.headers,\n })\n } catch (error) {\n if (error instanceof BridgeNotImplementedError) {\n return c.json(\n {\n error: {\n type: error.name,\n message: error.message,\n },\n },\n 501,\n )\n }\n\n throw error\n }\n})","import fs from \"node:fs/promises\"\n\nimport type { BridgeConfig } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { PATHS } from \"~/lib/paths\"\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\nconst GITHUB_API_VERSION = \"2022-11-28\"\nconst GITHUB_API_BASE_URL = \"https://api.github.com\"\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\nexport interface 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: {\n chat: QuotaDetail\n completions: QuotaDetail\n premium_interactions: QuotaDetail\n }\n}\n\nconst readGitHubToken = async (): Promise<string> => {\n const token = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return token.trim()\n}\n\nexport const getCopilotUsage = async (\n config: BridgeConfig,\n): Promise<CopilotUsageResponse> => {\n const githubToken = await readGitHubToken()\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/user`,\n {\n headers: {\n accept: \"application/json\",\n authorization: `token ${githubToken}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"editor-version\": `vscode/${config.vsCodeVersion}`,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": GITHUB_API_VERSION,\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n },\n },\n )\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get Copilot usage\", response)\n }\n\n return (await response.json()) as CopilotUsageResponse\n}\n","import { Hono } from \"hono\"\n\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { getCopilotUsage } from \"~/providers/github/get-copilot-usage\"\n\nexport const usageRoutes = new Hono<BridgeEnv>()\n\nusageRoutes.get(\"/\", async (c) => {\n // Allow the static usage viewer at https://betahi.github.io/copilot-bridge\n // (and local dev) to call this endpoint cross-origin.\n c.header(\"access-control-allow-origin\", \"*\")\n c.header(\"access-control-allow-methods\", \"GET, OPTIONS\")\n c.header(\"access-control-allow-headers\", \"*\")\n\n try {\n const usage = await getCopilotUsage(c.var.config)\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\nusageRoutes.options(\"/\", (c) => {\n c.header(\"access-control-allow-origin\", \"*\")\n c.header(\"access-control-allow-methods\", \"GET, OPTIONS\")\n c.header(\"access-control-allow-headers\", \"*\")\n return c.body(null, 204)\n})\n","import { serve } from \"@hono/node-server\"\nimport { Hono } from \"hono\"\nimport { cors } from \"hono/cors\"\nimport { logger } from \"hono/logger\"\n\nimport type { BridgeConfig, BridgeEnv } from \"~/lib/config\"\nimport { chatCompletionRoutes } from \"~/routes/chat-completions\"\nimport { embeddingRoutes } from \"~/routes/embeddings\"\nimport { messageRoutes } from \"~/routes/messages\"\nimport { modelRoutes } from \"~/routes/models\"\nimport { responsesRoutes } from \"~/routes/responses\"\nimport { usageRoutes } from \"~/routes/usage\"\n\nexport const createServer = (config: BridgeConfig) => {\n const app = new Hono<BridgeEnv>()\n\n app.use(logger())\n app.use(\"*\", cors())\n app.use(\"*\", async (c, next) => {\n c.set(\"config\", config)\n await next()\n })\n\n app.get(\"/\", (c) =>\n c.json({\n name: \"copilot-bridge\",\n status: \"ok\",\n }),\n )\n\n app.get(\"/healthz\", (c) => c.json({ ok: true }))\n app.route(\"/v1/models\", modelRoutes)\n app.route(\"/v1/responses\", responsesRoutes)\n app.route(\"/v1/messages\", messageRoutes)\n app.route(\"/v1/chat/completions\", chatCompletionRoutes)\n app.route(\"/v1/embeddings\", embeddingRoutes)\n app.route(\"/usage\", usageRoutes)\n\n return app\n}\n\nexport const startServer = (config: BridgeConfig) =>\n serve({\n fetch: createServer(config).fetch,\n hostname: config.host,\n port: config.port,\n })\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { setupBridgeAuth } from \"~/lib/auth\"\nimport {\n applyClaudeConfig,\n parsePortFromBaseUrl,\n readClaudeBaseUrl,\n} from \"~/lib/claude-settings\"\nimport {\n applyCodexConfig,\n readCodexUserConfigFromDisk,\n} from \"~/lib/codex-config\"\nimport { readBridgeConfig } from \"~/lib/config\"\nimport {\n CLAUDE_CONFIG_PATH,\n CODEX_DEFAULTS,\n DEFAULT_HOST,\n DEFAULT_PORT,\n} from \"~/lib/defaults\"\nimport {\n getModelCapability,\n MODEL_CAPABILITIES,\n} from \"~/lib/model-capabilities\"\nimport { runtimeState } from \"~/lib/state\"\nimport {\n fetchCopilot,\n getCopilotProviderContext,\n} from \"~/providers/copilot/client\"\nimport { startServer } from \"~/server\"\n\ninterface CopilotModel {\n id: string\n}\n\ninterface CopilotModelsResponse {\n data?: Array<CopilotModel>\n}\n\nconst fetchAvailableModels = async (\n config: ReturnType<typeof readBridgeConfig>,\n): Promise<Array<string>> => {\n try {\n const provider = getCopilotProviderContext(config)\n const response = await fetchCopilot(provider, \"/models\", {\n method: \"GET\",\n headers: { accept: \"application/json\" },\n })\n if (!response.ok) return []\n const payload = (await response.json()) as CopilotModelsResponse\n return (payload.data ?? []).map((m) => m.id).filter(Boolean)\n } catch {\n return []\n }\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the copilot-bridge HTTP server.\",\n },\n args: {\n host: {\n type: \"string\",\n description: `Host to bind (default: ${DEFAULT_HOST}).`,\n },\n port: {\n type: \"string\",\n description: `Port to listen on (default: ${DEFAULT_PORT}).`,\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Print GitHub and Copilot tokens during startup.\",\n },\n \"no-codex-setup\": {\n type: \"boolean\",\n default: false,\n description: \"Skip writing the bridge provider into ~/.codex/config.toml.\",\n },\n \"no-claude-setup\": {\n type: \"boolean\",\n default: false,\n description:\n \"Skip writing ANTHROPIC_BASE_URL into ~/.claude/settings.json.\",\n },\n \"select-model\": {\n type: \"boolean\",\n default: false,\n description:\n \"Force the model picker even when ~/.codex/config.toml already has a model.\",\n },\n \"no-prompt\": {\n type: \"boolean\",\n default: false,\n description:\n \"Never prompt; use the existing model from ~/.codex/config.toml as-is.\",\n },\n \"rate-limit\": {\n type: \"string\",\n description:\n \"Minimum seconds between upstream requests (anti-abuse throttle).\",\n },\n wait: {\n type: \"boolean\",\n default: false,\n description:\n \"When --rate-limit is set, wait instead of returning HTTP 429.\",\n },\n },\n async run({ args }) {\n // Port resolution priority (high → low):\n // 1. --port CLI flag\n // 2. $PORT environment variable\n // 3. ANTHROPIC_BASE_URL port in ~/.claude/settings.json\n // 4. DEFAULT_PORT\n // Once resolved, the chosen port is written back to BOTH claude\n // settings and codex config so the three sources stay in lockstep.\n const claudeConfigPath = CLAUDE_CONFIG_PATH\n const claudePort = parsePortFromBaseUrl(\n await readClaudeBaseUrl(claudeConfigPath),\n )\n const envPortRaw = process.env.PORT\n const envPort =\n envPortRaw && Number.isFinite(Number(envPortRaw)) ?\n Number(envPortRaw)\n : undefined\n\n const host = args.host ? String(args.host) : DEFAULT_HOST\n const port =\n args.port ? Number(args.port)\n : envPort !== undefined ? envPort\n : claudePort !== undefined ? claudePort\n : DEFAULT_PORT\n\n const config = readBridgeConfig({ host, port })\n\n const rateLimitRaw = args[\"rate-limit\"]\n if (rateLimitRaw !== undefined) {\n const parsed = Number.parseInt(String(rateLimitRaw), 10)\n if (!Number.isFinite(parsed) || parsed <= 0) {\n consola.error(`Invalid --rate-limit value: ${rateLimitRaw}`)\n process.exit(1)\n }\n runtimeState.rateLimitSeconds = parsed\n runtimeState.rateLimitWait = Boolean(args.wait)\n consola.info(\n `Rate limit: ${parsed}s between requests (${runtimeState.rateLimitWait ? \"wait\" : \"reject\"} on overflow)`,\n )\n }\n\n await setupBridgeAuth(config, {\n showToken: args[\"show-token\"],\n })\n\n const server = startServer(config)\n\n consola.success(\n `copilot-bridge listening on http://${config.host}:${config.port}`,\n )\n consola.info(`copilot base url: ${config.copilotBaseUrl}`)\n\n const baseUrl = `http://${config.host}:${config.port}`\n const codexConfigPath = CODEX_DEFAULTS.configPath\n\n // Sync Claude Code's settings.json and Codex's config.toml *before* any\n // potentially blocking interactive prompt. This guarantees `claude` and\n // `codex` work the moment the server is listening — even if the user\n // never answers the model picker below.\n if (!args[\"no-claude-setup\"]) {\n try {\n const claudeResult = await applyClaudeConfig({\n baseUrl,\n configPath: claudeConfigPath,\n })\n if (claudeResult.changed) {\n consola.success(\n `claude settings ${claudeResult.created ? \"created\" : \"updated\"}: ${claudeResult.configPath}`,\n )\n if (\n claudeResult.previousBaseUrl\n && claudeResult.previousBaseUrl !== baseUrl\n ) {\n consola.info(\n `ANTHROPIC_BASE_URL: ${claudeResult.previousBaseUrl} → ${baseUrl}`,\n )\n }\n } else {\n consola.info(\n `claude settings already up to date: ${claudeResult.configPath}`,\n )\n }\n } catch (error) {\n consola.warn(\n `Could not update claude settings (${claudeConfigPath}):`,\n error,\n )\n }\n }\n\n // Read the user's current codex model so the picker can default to it,\n // and so we can stamp the managed block immediately even if the picker\n // is skipped or interrupted.\n const codexUserConfig = await readCodexUserConfigFromDisk(codexConfigPath)\n let chosenModel: string | undefined = codexUserConfig.model\n let chosenEffort: string | undefined =\n codexUserConfig.modelReasoningEffort\n\n if (!args[\"no-codex-setup\"]) {\n try {\n const result = await applyCodexConfig({\n baseUrl: `${baseUrl}/v1`,\n configPath: codexConfigPath,\n settings: CODEX_DEFAULTS,\n model: chosenModel,\n modelReasoningEffort: chosenEffort,\n })\n if (result.changed) {\n consola.success(\n `codex config ${result.created ? \"created\" : \"updated\"}: ${result.configPath}`,\n )\n if (CODEX_DEFAULTS.setAsDefault) {\n consola.info(\n `codex now defaults to provider \"${CODEX_DEFAULTS.providerId}\". Run \\`codex exec \"...\"\\` directly.`,\n )\n } else {\n consola.info(\n `provider \"${CODEX_DEFAULTS.providerId}\" registered. Use \\`codex -c model_provider=\"${CODEX_DEFAULTS.providerId}\" ...\\``,\n )\n }\n } else {\n consola.info(`codex config already up to date: ${result.configPath}`)\n }\n } catch (error) {\n consola.warn(\n `Could not update codex config (${codexConfigPath}):`,\n error,\n )\n }\n }\n\n const models = await fetchAvailableModels(config)\n const supportedIds = new Set(MODEL_CAPABILITIES.map((m) => m.id))\n const pickable =\n models.length > 0 ?\n models.filter((id) => supportedIds.has(id))\n : MODEL_CAPABILITIES.map((m) => m.id)\n const finalPickable =\n pickable.length > 0 ? pickable : MODEL_CAPABILITIES.map((m) => m.id)\n if (models.length > 0) {\n consola.info(\n `Available models:\\n${models\n .map((id) => `- ${id}${supportedIds.has(id) ? \" (bridge-supported)\" : \"\"}`)\n .join(\"\\n\")}`,\n )\n } else {\n consola.warn(\"Could not fetch model list from upstream Copilot API\")\n }\n\n consola.box(\n [\n `🌐 Usage viewer`,\n ``,\n ` https://betahi.github.io/copilot-bridge?endpoint=${baseUrl}/usage`,\n ].join(\"\\n\"),\n )\n\n const shouldPrompt =\n !args[\"no-prompt\"]\n && finalPickable.length > 0\n && (args[\"select-model\"] || !chosenModel)\n\n if (shouldPrompt) {\n const defaultId =\n chosenModel && finalPickable.includes(chosenModel) ? chosenModel\n : finalPickable.includes(\"gpt-5.3-codex\") ? \"gpt-5.3-codex\"\n : finalPickable[0]\n const selected = (await consola.prompt(\n `Select a model for codex (writes to ${codexConfigPath})`,\n {\n type: \"select\",\n options: finalPickable,\n initial: defaultId,\n },\n )) as string\n if (selected && selected !== chosenModel) {\n chosenModel = selected\n // If the previously stored effort is no longer supported by the\n // newly chosen model, drop it so codex falls back to its default.\n const cap = getModelCapability(selected)\n const supported = cap?.reasoning?.supported\n if (\n chosenEffort\n && supported\n && !supported.includes(chosenEffort as never)\n ) {\n chosenEffort = undefined\n }\n // Re-stamp codex config with the user's freshly picked model.\n if (!args[\"no-codex-setup\"]) {\n try {\n const result = await applyCodexConfig({\n baseUrl: `${baseUrl}/v1`,\n configPath: codexConfigPath,\n settings: CODEX_DEFAULTS,\n model: chosenModel,\n modelReasoningEffort: chosenEffort,\n })\n if (result.changed) {\n consola.success(`codex config updated: ${result.configPath}`)\n }\n } catch (error) {\n consola.warn(\n `Could not update codex config (${codexConfigPath}):`,\n error,\n )\n }\n }\n }\n }\n\n await new Promise<void>((resolve, reject) => {\n server.on(\"close\", resolve)\n server.on(\"error\", reject)\n })\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand, runMain } from \"citty\"\n\nimport { auth } from \"./auth\"\nimport { start } from \"./start\"\n\nconst main = defineCommand({\n meta: {\n name: \"copilot-bridge\",\n description:\n \"Model-layer bridge for routing Codex CLI, Claude Code, and similar clients to GitHub Copilot.\",\n },\n subCommands: { auth, start },\n})\n\nawait runMain(main)\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"main.js","names":["runtimeState: RuntimeState","COPILOT_VERSION","EDITOR_PLUGIN_VERSION","USER_AGENT","path","COPILOT_VERSION","EDITOR_PLUGIN_VERSION","USER_AGENT","GITHUB_API_VERSION","GITHUB_API_BASE_URL","sleep","readGitHubToken","merged: Record<string, string>","parsed: Record<string, unknown>","env: Record<string, unknown>","next: Record<string, unknown>","lines: Array<string>","out: CodexUserConfig","CODEX_DEFAULTS: CodexDefaults","MODEL_CAPABILITIES: ReadonlyArray<ModelCapability>","entries: Array<readonly [string, ModelCapability]>","order: ReadonlyArray<ReasoningEffort>","state: ResponseTranslationState","translated: Array<ResponsesInputItem>","isClaudeOpus47Model","normalizeReasoningEffort","matches: Array<Model>","newMessages: Array<Message>","contentParts: Array<ContentPart>","allTextBlocks: Array<AnthropicTextBlock>","allToolUseBlocks: Array<AnthropicToolUseBlock>","stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null","events: Array<AnthropicStreamEventData>","events","streamState: AnthropicStreamState","chunk: ChatCompletionChunk","events","parts: Array<ChatContentPart>","messages: Array<ChatMessage>","inputItems: Array<ResponsesInputItem>","role: ChatRole","tools: Array<ChatTool> | undefined","payload: ChatRequestPayload","output: ResponsesApiResult[\"output\"]","event: ResponsesStreamEvent","stableResponse: StableResponseMetadata","incoming: ReasoningField | undefined","upstream","chosenModel: string | undefined","chosenEffort: string | undefined"],"sources":["../src/lib/error.ts","../src/lib/paths.ts","../src/lib/state.ts","../src/providers/copilot/client.ts","../src/providers/copilot/get-models.ts","../src/lib/auth.ts","../src/lib/config.ts","../src/auth.ts","../src/lib/claude-settings.ts","../src/lib/codex-config.ts","../src/lib/defaults.ts","../src/lib/model-capabilities.ts","../src/lib/rate-limit.ts","../src/services/copilot/responses.ts","../src/services/copilot/create-chat-completions.ts","../src/routes/chat-completions.ts","../src/providers/copilot/create-embeddings.ts","../src/routes/embeddings.ts","../src/lib/models-resolver.ts","../src/bridges/claude/utils.ts","../src/bridges/claude/non-stream-translation.ts","../src/bridges/claude/stream-translation.ts","../src/lib/tokenizer.ts","../src/routes/messages.ts","../src/routes/models.ts","../src/bridges/codex/chat-fallback.ts","../src/bridges/codex/normalize-stream.ts","../src/bridges/codex/responses.ts","../src/routes/responses.ts","../src/providers/github/get-copilot-usage.ts","../src/routes/usage.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["export class BridgeNotImplementedError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"BridgeNotImplementedError\"\n }\n}\n\nexport class HTTPError extends Error {\n response: Response\n\n constructor(message: string, response: Response) {\n super(message)\n this.name = \"HTTPError\"\n this.response = response\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-bridge\")\n\nconst GITHUB_TOKEN_PATH = path.join(APP_DIR, \"github_token\")\n\nexport const PATHS = {\n APP_DIR,\n GITHUB_TOKEN_PATH,\n}\n\nexport async function ensurePaths(): Promise<void> {\n await fs.mkdir(PATHS.APP_DIR, { recursive: true })\n await ensureFile(PATHS.GITHUB_TOKEN_PATH)\n}\n\nasync function ensureFile(filePath: string): Promise<void> {\n try {\n await fs.access(filePath, fs.constants.W_OK)\n } catch {\n await fs.writeFile(filePath, \"\")\n await fs.chmod(filePath, 0o600)\n }\n}","import type { ModelsResponse } from \"~/providers/copilot/get-models\"\n\nexport interface RuntimeState {\n models?: ModelsResponse\n rateLimitSeconds?: number\n rateLimitWait?: boolean\n lastRequestTimestamp?: number\n}\n\nexport const runtimeState: RuntimeState = {}\n","import { randomUUID } from \"node:crypto\"\n\nimport type { BridgeConfig } from \"~/lib/config\"\nimport { BridgeNotImplementedError } from \"~/lib/error\"\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\nconst API_VERSION = \"2025-04-01\"\n\nexport interface CopilotProviderContext {\n baseUrl: string\n token: string | undefined\n vsCodeVersion: string\n}\n\nexport const getCopilotProviderContext = (\n config: BridgeConfig,\n): CopilotProviderContext => ({\n baseUrl: config.copilotBaseUrl,\n token: config.copilotToken,\n vsCodeVersion: config.vsCodeVersion,\n})\n\nexport interface FetchCopilotOptions {\n vision?: boolean\n initiator?: \"agent\" | \"user\"\n}\n\nexport const fetchCopilot = async (\n provider: CopilotProviderContext,\n path: string,\n init: RequestInit,\n options: FetchCopilotOptions = {},\n) => {\n if (!provider.token) {\n throw new BridgeNotImplementedError(\n \"COPILOT_TOKEN is not configured for copilot-bridge.\",\n )\n }\n\n const headers = new Headers(init.headers)\n\n headers.set(\"authorization\", `Bearer ${provider.token}`)\n headers.set(\"copilot-integration-id\", \"vscode-chat\")\n headers.set(\"editor-version\", `vscode/${provider.vsCodeVersion}`)\n headers.set(\"editor-plugin-version\", EDITOR_PLUGIN_VERSION)\n headers.set(\"user-agent\", USER_AGENT)\n headers.set(\"openai-intent\", \"conversation-panel\")\n headers.set(\"x-github-api-version\", API_VERSION)\n headers.set(\"x-request-id\", randomUUID())\n headers.set(\"x-vscode-user-agent-library-version\", \"electron-fetch\")\n\n if (options.vision) {\n headers.set(\"copilot-vision-request\", \"true\")\n }\n\n if (options.initiator) {\n headers.set(\"x-initiator\", options.initiator)\n }\n\n if (!headers.has(\"content-type\") && init.body !== undefined) {\n headers.set(\"content-type\", \"application/json\")\n }\n\n if (!headers.has(\"accept\")) {\n headers.set(\"accept\", \"application/json\")\n }\n\n return fetch(`${provider.baseUrl}${path}`, {\n ...init,\n headers,\n })\n}\n","import type { BridgeConfig } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\n\nimport { fetchCopilot, getCopilotProviderContext } from \"./client\"\n\nexport const getModels = async (\n config: BridgeConfig,\n): Promise<ModelsResponse> => {\n const provider = getCopilotProviderContext(config)\n const response = await fetchCopilot(provider, \"/models\", {\n method: \"GET\",\n headers: { accept: \"application/json\" },\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get models\", response)\n\n return (await response.json()) as ModelsResponse\n}\n\nexport interface ModelsResponse {\n data: Array<Model>\n object: string\n}\n\ninterface ModelLimits {\n max_context_window_tokens?: number\n max_output_tokens?: number\n max_prompt_tokens?: number\n max_inputs?: number\n}\n\ninterface ModelSupports {\n tool_calls?: boolean\n parallel_tool_calls?: boolean\n dimensions?: boolean\n}\n\ninterface ModelCapabilities {\n family: string\n limits: ModelLimits\n object: string\n supports: ModelSupports\n tokenizer: string\n type: string\n}\n\nexport interface Model {\n capabilities: ModelCapabilities\n id: string\n model_picker_enabled: boolean\n name: string\n object: string\n preview: boolean\n vendor: string\n version: string\n policy?: {\n state: string\n terms: string\n }\n}\n","import fs from \"node:fs/promises\"\n\nimport consola from \"consola\"\n\nimport type { BridgeConfig } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { PATHS, ensurePaths } from \"~/lib/paths\"\nimport { runtimeState } from \"~/lib/state\"\nimport { getModels } from \"~/providers/copilot/get-models\"\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\nconst GITHUB_API_VERSION = \"2022-11-28\"\n\nconst GITHUB_API_BASE_URL = \"https://api.github.com\"\nconst GITHUB_BASE_URL = \"https://github.com\"\nconst GITHUB_CLIENT_ID = \"Iv1.b507a08c87ecfe98\"\nconst GITHUB_APP_SCOPES = [\"read:user\"].join(\" \")\n\ninterface DeviceCodeResponse {\n device_code: string\n expires_in: number\n interval: number\n user_code: string\n verification_uri: string\n}\n\ninterface AccessTokenResponse {\n access_token?: string\n}\n\ninterface CopilotTokenResponse {\n refresh_in: number\n token: string\n}\n\ninterface GitHubUserResponse {\n login: string\n}\n\ninterface AuthOptions {\n force?: boolean\n showToken?: boolean\n}\n\nconst standardHeaders = () => ({\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n})\n\nconst sleep = (ms: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, ms)\n })\n\nconst readGitHubToken = async () => {\n const token = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return token.trim()\n}\n\nconst writeGitHubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, `${token.trim()}\\n`, { mode: 0o600 })\n\nconst githubHeaders = (githubToken: string, vsCodeVersion: string) => ({\n ...standardHeaders(),\n authorization: `token ${githubToken}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"editor-version\": `vscode/${vsCodeVersion}`,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": GITHUB_API_VERSION,\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n})\n\nconst getDeviceCode = async (): 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) {\n throw new HTTPError(\"Failed to get device code\", response)\n }\n\n return (await response.json()) as DeviceCodeResponse\n}\n\nconst pollAccessToken = async (\n deviceCode: DeviceCodeResponse,\n): Promise<string> => {\n const sleepDuration = (deviceCode.interval + 1) * 1000\n\n while (true) {\n const response = await fetch(`${GITHUB_BASE_URL}/login/oauth/access_token`, {\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 if (!response.ok) {\n await sleep(sleepDuration)\n continue\n }\n\n const json = (await response.json()) as AccessTokenResponse\n if (json.access_token) {\n return json.access_token\n }\n\n await sleep(sleepDuration)\n }\n}\n\nconst getGitHubUser = async (\n githubToken: string,\n vsCodeVersion: string,\n): Promise<GitHubUserResponse> => {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: githubHeaders(githubToken, vsCodeVersion),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get GitHub user\", response)\n }\n\n return (await response.json()) as GitHubUserResponse\n}\n\nconst getCopilotToken = async (\n githubToken: string,\n vsCodeVersion: string,\n): Promise<CopilotTokenResponse> => {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(githubToken, vsCodeVersion),\n },\n )\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get Copilot token\", response)\n }\n\n return (await response.json()) as CopilotTokenResponse\n}\n\nconst ensureGitHubToken = async (\n config: BridgeConfig,\n options: AuthOptions = {},\n) => {\n await ensurePaths()\n\n const existingToken = options.force ? \"\" : await readGitHubToken()\n if (existingToken) {\n return existingToken\n }\n\n const deviceCode = await getDeviceCode()\n consola.info(\n `Open ${deviceCode.verification_uri} and enter code ${deviceCode.user_code}`,\n )\n\n const githubToken = await pollAccessToken(deviceCode)\n await writeGitHubToken(githubToken)\n\n if (options.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n\n const user = await getGitHubUser(githubToken, config.vsCodeVersion)\n consola.success(`Logged in as ${user.login}`)\n\n return githubToken\n}\n\nexport const setupBridgeAuth = async (\n config: BridgeConfig,\n options: AuthOptions = {},\n) => {\n if (config.copilotToken) {\n if (options.showToken) {\n consola.info(\"Using COPILOT_TOKEN from environment\")\n }\n await loadModels(config)\n return\n }\n\n const githubToken = await ensureGitHubToken(config, options)\n const applyCopilotToken = async () => {\n const { refresh_in, token } = await getCopilotToken(\n githubToken,\n config.vsCodeVersion,\n )\n\n config.copilotToken = token\n if (options.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n return refresh_in\n }\n\n const refreshIn = await applyCopilotToken()\n const refreshInterval = Math.max(refreshIn - 60, 60) * 1000\n\n setInterval(async () => {\n try {\n await applyCopilotToken()\n consola.debug(\"Refreshed Copilot token\")\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n }\n }, refreshInterval)\n\n await loadModels(config)\n}\n\nconst loadModels = async (config: BridgeConfig) => {\n try {\n runtimeState.models = await getModels(config)\n consola.success(\n `Loaded ${runtimeState.models.data.length} Copilot models`,\n )\n } catch (error) {\n consola.warn(\"Failed to load Copilot models:\", error)\n }\n}\n\nexport const runBridgeAuth = async (\n config: BridgeConfig,\n options: AuthOptions = {},\n) => {\n const githubToken = await ensureGitHubToken(config, {\n ...options,\n force: true,\n })\n\n const user = await getGitHubUser(githubToken, config.vsCodeVersion)\n consola.success(`GitHub token written to ${PATHS.GITHUB_TOKEN_PATH}`)\n consola.info(`Logged in as ${user.login}`)\n}","import { z } from \"zod\"\n\nconst accountTypeSchema = z.enum([\"individual\", \"business\", \"enterprise\"])\n\nconst inputSchema = z.object({\n host: z.string().min(1),\n port: z.number().int().min(1).max(65535),\n})\n\nexport interface BridgeConfig {\n host: string\n port: number\n accountType: \"individual\" | \"business\" | \"enterprise\"\n copilotBaseUrl: string\n copilotToken: string | undefined\n vsCodeVersion: string\n}\n\nexport interface BridgeEnv {\n Variables: {\n config: BridgeConfig\n }\n}\n\nexport const readBridgeConfig = (input: {\n host: string\n port: number\n}): BridgeConfig => {\n const parsedInput = inputSchema.parse(input)\n const accountType = accountTypeSchema.parse(\n process.env.COPILOT_ACCOUNT_TYPE ?? \"individual\",\n )\n const copilotBaseUrl =\n process.env.COPILOT_BASE_URL\n ?? (\n accountType === \"individual\" ?\n \"https://api.githubcopilot.com\"\n : `https://api.${accountType}.githubcopilot.com`\n )\n\n return {\n host: parsedInput.host,\n port: parsedInput.port,\n accountType,\n copilotBaseUrl,\n copilotToken: process.env.COPILOT_TOKEN,\n vsCodeVersion: process.env.COPILOT_VSCODE_VERSION ?? \"1.99.3\",\n }\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { setupBridgeAuth } from \"~/lib/auth\"\nimport { readBridgeConfig } from \"~/lib/config\"\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run GitHub device auth and cache credentials for copilot-bridge.\",\n },\n args: {\n host: {\n type: \"string\",\n default: \"127.0.0.1\",\n description: \"Host used for config initialization.\",\n },\n port: {\n type: \"string\",\n default: \"4142\",\n description: \"Port used for config initialization.\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Print GitHub and Copilot tokens during auth.\",\n },\n },\n async run({ args }) {\n const config = readBridgeConfig({\n host: String(args.host),\n port: Number(args.port),\n })\n\n config.copilotToken = undefined\n\n await setupBridgeAuth(config, {\n force: true,\n showToken: args[\"show-token\"],\n })\n\n consola.success(\"copilot-bridge auth completed\")\n },\n})","import fs from \"node:fs/promises\"\nimport os from \"node:os\"\nimport path from \"node:path\"\n\nimport consola from \"consola\"\n\ninterface ClaudeSettingsFile {\n env?: Record<string, unknown>\n}\n\nconst getClaudeSettingsPaths = (): Array<string> => {\n const cwd = process.cwd()\n const home = process.env.HOME ?? os.homedir()\n\n return [\n path.join(home, \".claude\", \"settings.json\"),\n path.join(cwd, \".claude\", \"settings.json\"),\n path.join(cwd, \".claude\", \"settings.local.json\"),\n ]\n}\n\nconst readClaudeSettingsFile = async (\n filePath: string,\n): Promise<ClaudeSettingsFile | undefined> => {\n try {\n const content = await fs.readFile(filePath, \"utf8\")\n return JSON.parse(content) as ClaudeSettingsFile\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return undefined\n }\n consola.warn(`Failed to read Claude settings from ${filePath}:`, error)\n return undefined\n }\n}\n\n/**\n * Read just the `ANTHROPIC_BASE_URL` from a single Claude settings file.\n * Used at startup so the user can pin the bridge port by editing one place\n * instead of passing `--port` every time.\n */\nexport const readClaudeBaseUrl = async (\n configPath: string,\n): Promise<string | undefined> => {\n const settings = await readClaudeSettingsFile(configPath)\n const value = settings?.env?.ANTHROPIC_BASE_URL\n return typeof value === \"string\" ? value : undefined\n}\n\n/**\n * Parse the port from an `ANTHROPIC_BASE_URL`-style string. Returns\n * `undefined` if the URL is malformed or has no explicit port.\n */\nexport const parsePortFromBaseUrl = (\n baseUrl: string | undefined,\n): number | undefined => {\n if (!baseUrl) return undefined\n try {\n const url = new URL(baseUrl)\n if (!url.port) return undefined\n const port = Number.parseInt(url.port, 10)\n return Number.isFinite(port) && port > 0 ? port : undefined\n } catch {\n return undefined\n }\n}\n\nexport const getClaudeSettingsEnv = async (): Promise<\n Record<string, string>\n> => {\n const merged: Record<string, string> = {}\n\n for (const filePath of getClaudeSettingsPaths()) {\n const settings = await readClaudeSettingsFile(filePath)\n if (!settings?.env) continue\n\n for (const [key, value] of Object.entries(settings.env)) {\n if (typeof value === \"string\") merged[key] = value\n }\n }\n\n return merged\n}\n\ninterface ApplyClaudeConfigInput {\n baseUrl: string\n configPath: string\n}\n\ninterface ApplyClaudeResult {\n configPath: string\n changed: boolean\n created: boolean\n previousBaseUrl?: string\n}\n\n/**\n * Update `~/.claude/settings.json` so its env block points Claude Code at the\n * running bridge. Preserves all unrelated keys (model overrides, plugins,\n * marketplaces, etc.). Sets a dummy auth token only if none is present.\n */\nexport async function applyClaudeConfig(\n input: ApplyClaudeConfigInput,\n): Promise<ApplyClaudeResult> {\n const { configPath, baseUrl } = input\n\n let raw = \"\"\n let created = false\n try {\n raw = await fs.readFile(configPath, \"utf8\")\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n created = true\n } else {\n throw error\n }\n }\n\n let parsed: Record<string, unknown> = {}\n if (raw.trim().length > 0) {\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n parsed = {}\n }\n } catch {\n // Refuse to overwrite a malformed file; bail without changes.\n return { configPath, changed: false, created: false }\n }\n }\n\n const env: Record<string, unknown> =\n typeof parsed.env === \"object\"\n && parsed.env !== null\n && !Array.isArray(parsed.env)\n ? { ...(parsed.env as Record<string, unknown>) }\n : {}\n\n const previousBaseUrl =\n typeof env.ANTHROPIC_BASE_URL === \"string\"\n ? (env.ANTHROPIC_BASE_URL as string)\n : undefined\n\n env.ANTHROPIC_BASE_URL = baseUrl\n if (typeof env.ANTHROPIC_AUTH_TOKEN !== \"string\" || !env.ANTHROPIC_AUTH_TOKEN) {\n env.ANTHROPIC_AUTH_TOKEN = \"dummy\"\n }\n\n const next: Record<string, unknown> = { ...parsed, env }\n const serialized = `${JSON.stringify(next, null, 2)}\\n`\n\n if (serialized === raw) {\n return { configPath, changed: false, created: false, previousBaseUrl }\n }\n\n await fs.mkdir(path.dirname(configPath), { recursive: true })\n await fs.writeFile(configPath, serialized)\n return { configPath, changed: true, created, previousBaseUrl }\n}\n","import fs from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport type { CodexDefaults } from \"./defaults\"\n\nconst BEGIN_MARK =\n \"# >>> copilot-bridge managed block — auto-generated, do not edit between markers >>>\"\nconst END_MARK =\n \"# <<< copilot-bridge managed block — edits outside this block are preserved <<<\"\n\n// Legacy markers from earlier releases. We still recognize and strip them so\n// upgrading users do not end up with duplicate managed blocks.\nconst LEGACY_BEGIN_MARK = \"# >>> copilot-bridge managed (do not edit) >>>\"\nconst LEGACY_END_MARK = \"# <<< copilot-bridge managed (do not edit) <<<\"\n\n// Top-level keys that the user (or codex itself) is the owner of.\n// We never put these in our managed block to avoid TOML duplicate-key errors.\nconst USER_OWNED_SCALARS = [\"model\", \"model_reasoning_effort\"] as const\ntype UserScalar = (typeof USER_OWNED_SCALARS)[number]\n\ninterface ApplyCodexConfigInput {\n baseUrl: string\n settings: CodexDefaults\n /** Optional model to write into the user-owned area of the file. */\n model?: string\n /** Optional reasoning effort to write into the user-owned area. */\n modelReasoningEffort?: string\n}\n\ninterface ApplyResult {\n configPath: string\n changed: boolean\n created: boolean\n}\n\nexport interface CodexUserConfig {\n model?: string\n modelReasoningEffort?: string\n}\n\nfunction tomlEscape(value: string): string {\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')\n}\n\nfunction buildManagedBlock(input: ApplyCodexConfigInput): string {\n const { baseUrl, settings } = input\n const lines: Array<string> = []\n lines.push(BEGIN_MARK)\n if (settings.setAsDefault) {\n lines.push(`model_provider = \"${tomlEscape(settings.providerId)}\"`)\n }\n lines.push(\"\")\n lines.push(`[model_providers.${settings.providerId}]`)\n lines.push(`name = \"${tomlEscape(settings.providerName)}\"`)\n lines.push(`base_url = \"${tomlEscape(baseUrl)}\"`)\n lines.push(`wire_api = \"responses\"`)\n lines.push(`prefer_websockets = false`)\n lines.push(`requires_openai_auth = false`)\n lines.push(END_MARK)\n return lines.join(\"\\n\")\n}\n\nfunction stripManagedBlock(content: string): string {\n let next = content\n for (const [begin, end] of [\n [BEGIN_MARK, END_MARK],\n [LEGACY_BEGIN_MARK, LEGACY_END_MARK],\n ]) {\n while (true) {\n const beginIdx = next.indexOf(begin)\n if (beginIdx === -1) break\n const endIdx = next.indexOf(end, beginIdx)\n if (endIdx === -1) break\n const before = next.slice(0, beginIdx).replace(/\\n*$/, \"\")\n const after = next.slice(endIdx + end.length).replace(/^\\n+/, \"\")\n if (before.length === 0) next = after\n else if (after.length === 0) next = `${before}\\n`\n else next = `${before}\\n\\n${after}`\n }\n }\n return next\n}\n\n// Lines belonging to the first (top-level) TOML section: from the start of\n// the file up to the first line that begins with `[`. This is where\n// codex's own `model = ...` and `model_reasoning_effort = ...` live.\nfunction splitTopSection(content: string): {\n top: string\n rest: string\n} {\n const lines = content.split(\"\\n\")\n let cut = lines.length\n for (let i = 0; i < lines.length; i++) {\n if (/^\\s*\\[/.test(lines[i])) {\n cut = i\n break\n }\n }\n return {\n top: lines.slice(0, cut).join(\"\\n\"),\n rest: lines.slice(cut).join(\"\\n\"),\n }\n}\n\nconst scalarRegex = (key: string) =>\n new RegExp(`^\\\\s*${key}\\\\s*=\\\\s*\"((?:[^\"\\\\\\\\]|\\\\\\\\.)*)\"\\\\s*$`, \"m\")\n\nexport function readCodexUserConfig(content: string): CodexUserConfig {\n const stripped = stripManagedBlock(content)\n const { top } = splitTopSection(stripped)\n const out: CodexUserConfig = {}\n const m = top.match(scalarRegex(\"model\"))\n if (m) out.model = m[1]\n const e = top.match(scalarRegex(\"model_reasoning_effort\"))\n if (e) out.modelReasoningEffort = e[1]\n return out\n}\n\nfunction setTopScalar(\n topSection: string,\n key: UserScalar,\n value: string | undefined,\n): string {\n const re = scalarRegex(key)\n if (value === undefined) {\n // Leave the existing value as-is when caller did not provide one.\n return topSection\n }\n const line = `${key} = \"${tomlEscape(value)}\"`\n if (re.test(topSection)) {\n return topSection.replace(re, line)\n }\n // Insert at the very top of the file, before any existing content.\n if (topSection.length === 0) return `${line}\\n`\n // Keep a single blank line between our inserted scalars and existing content.\n return `${line}\\n${topSection.startsWith(\"\\n\") ? \"\" : \"\"}${topSection}`\n}\n\nfunction applyUserScalars(\n content: string,\n input: ApplyCodexConfigInput,\n): string {\n const { top, rest } = splitTopSection(content)\n let nextTop = top\n nextTop = setTopScalar(nextTop, \"model\", input.model)\n nextTop = setTopScalar(\n nextTop,\n \"model_reasoning_effort\",\n input.modelReasoningEffort,\n )\n if (nextTop === top) return content\n if (rest.length === 0) {\n return nextTop.endsWith(\"\\n\") ? nextTop : `${nextTop}\\n`\n }\n const sep = nextTop.endsWith(\"\\n\") ? \"\" : \"\\n\"\n return `${nextTop}${sep}${rest}`\n}\n\nexport async function applyCodexConfig(\n input: ApplyCodexConfigInput & { configPath: string },\n): Promise<ApplyResult> {\n const { configPath } = input\n let existing = \"\"\n let created = false\n try {\n existing = await fs.readFile(configPath, \"utf8\")\n } catch {\n created = true\n }\n\n let stripped = stripManagedBlock(existing)\n stripped = applyUserScalars(stripped, input)\n const block = buildManagedBlock(input)\n const trimmed = stripped.replace(/\\n+$/, \"\")\n const next =\n trimmed.length === 0 ? `${block}\\n` : `${trimmed}\\n\\n${block}\\n`\n\n if (next === existing) {\n return { configPath, changed: false, created: false }\n }\n\n await fs.mkdir(path.dirname(configPath), { recursive: true })\n await fs.writeFile(configPath, next)\n return { configPath, changed: true, created }\n}\n\nexport async function readCodexUserConfigFromDisk(\n configPath: string,\n): Promise<CodexUserConfig> {\n try {\n const content = await fs.readFile(configPath, \"utf8\")\n return readCodexUserConfig(content)\n } catch {\n return {}\n }\n}\n","import os from \"node:os\"\nimport path from \"node:path\"\n\n/**\n * Static defaults for the bridge. Previously these lived in\n * `~/.config/copilot-bridge/settings.json`, but that file ended up being a\n * silent third source of truth (alongside `~/.codex/config.toml` and\n * `~/.claude/settings.json`) which caused subtle port-mismatch bugs. The\n * bridge now relies on these defaults plus CLI flags only — every other\n * persisted state lives in the consumer config files (codex / claude).\n */\n\nexport interface CodexDefaults {\n providerId: string\n providerName: string\n setAsDefault: boolean\n configPath: string\n}\n\nexport const DEFAULT_HOST = \"127.0.0.1\"\nexport const DEFAULT_PORT = 4142\n\nexport const CODEX_DEFAULTS: CodexDefaults = {\n providerId: \"bridge\",\n providerName: \"Copilot Bridge\",\n setAsDefault: true,\n configPath: path.join(os.homedir(), \".codex\", \"config.toml\"),\n}\n\nexport const CLAUDE_CONFIG_PATH = path.join(\n os.homedir(),\n \".claude\",\n \"settings.json\",\n)\n","// Model capability registry for copilot-bridge.\n// Source: GitHub Copilot Responses API model + reasoning_effort matrix.\n// Keep this tightly scoped to what we use to validate / clamp requests.\n\nexport type ReasoningEffort =\n | \"none\"\n | \"low\"\n | \"medium\"\n | \"high\"\n | \"xhigh\"\n | \"max\"\n\nexport interface ModelCapability {\n id: string\n // Optional aliases that resolve to this canonical id (e.g. trimming a\n // \"-preview\" suffix). Requests using an alias get their model rewritten\n // to the canonical id before being forwarded upstream.\n aliases?: ReadonlyArray<string>\n // If undefined, the model does not accept a reasoning parameter at all\n // and the bridge will strip any reasoning.* fields from the request.\n reasoning?: {\n supported: ReadonlyArray<ReasoningEffort>\n default: ReasoningEffort\n }\n // When set, /v1/responses requests for this model are translated to\n // upstream /v1/chat/completions because Copilot does not expose the\n // Responses API for this model.\n fallback?: \"chat-completions\"\n // Where to place the reasoning effort on the upstream chat payload.\n // - \"reasoning_effort\" (default for gpt-5 family / most claude)\n // - \"output_config.effort\" (claude-opus-4.7 family)\n // Has no effect when reasoning is undefined.\n reasoningField?: \"reasoning_effort\" | \"output_config.effort\"\n}\n\nexport const MODEL_CAPABILITIES: ReadonlyArray<ModelCapability> = [\n {\n id: \"gpt-5.5\",\n reasoning: {\n supported: [\"none\", \"low\", \"medium\", \"high\", \"xhigh\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5.4\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\", \"xhigh\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5.4-mini\",\n reasoning: {\n supported: [\"none\", \"low\", \"medium\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5.3-codex\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\", \"xhigh\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5.2\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\", \"xhigh\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5.2-codex\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\", \"xhigh\"],\n default: \"medium\",\n },\n },\n {\n id: \"gpt-5-mini\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\"],\n default: \"medium\",\n },\n },\n // Claude family — Copilot does not expose /v1/responses for Claude, so we\n // translate to /v1/chat/completions. Only opus-4.7 places effort under\n // output_config.effort; the others use the standard reasoning_effort.\n {\n id: \"claude-opus-4.7\",\n fallback: \"chat-completions\",\n reasoningField: \"output_config.effort\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"],\n default: \"medium\",\n },\n },\n {\n id: \"claude-opus-4.6\",\n fallback: \"chat-completions\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\"],\n default: \"medium\",\n },\n },\n {\n id: \"claude-opus-4.6-1m\",\n fallback: \"chat-completions\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\"],\n default: \"medium\",\n },\n },\n {\n id: \"claude-opus-4.5\",\n fallback: \"chat-completions\",\n },\n {\n id: \"claude-sonnet-4.6\",\n fallback: \"chat-completions\",\n reasoning: {\n supported: [\"low\", \"medium\", \"high\"],\n default: \"medium\",\n },\n },\n {\n id: \"claude-sonnet-4.5\",\n fallback: \"chat-completions\",\n },\n {\n id: \"claude-sonnet-4\",\n fallback: \"chat-completions\",\n },\n {\n id: \"claude-haiku-4.5\",\n fallback: \"chat-completions\",\n },\n // Gemini family currently does not accept a reasoning parameter on the\n // Copilot Responses endpoint — bridge strips reasoning.* before forwarding.\n {\n id: \"gemini-3.1-pro-preview\",\n fallback: \"chat-completions\",\n aliases: [\"gemini-3.1-pro\"],\n },\n {\n id: \"gemini-3-flash-preview\",\n fallback: \"chat-completions\",\n aliases: [\"gemini-3-flash\"],\n },\n {\n id: \"gemini-2.5-pro\",\n fallback: \"chat-completions\",\n },\n // Legacy GPT-4.x — chat-only upstream, no reasoning parameter accepted.\n {\n id: \"gpt-4.1\",\n fallback: \"chat-completions\",\n },\n {\n id: \"gpt-4o\",\n fallback: \"chat-completions\",\n },\n]\n\nconst CAPABILITY_BY_ID = new Map(\n MODEL_CAPABILITIES.flatMap((m) => {\n const entries: Array<readonly [string, ModelCapability]> = [[m.id, m]]\n for (const alias of m.aliases ?? []) entries.push([alias, m])\n return entries\n }),\n)\n\n// Resolve any alias to the canonical upstream id. Returns the input\n// unchanged when no mapping is found.\nexport const resolveModelId = (modelId: string): string =>\n CAPABILITY_BY_ID.get(modelId)?.id ?? modelId\n\nexport const getModelCapability = (\n modelId: string,\n): ModelCapability | undefined => CAPABILITY_BY_ID.get(modelId)\n\nexport const isReasoningEffort = (value: unknown): value is ReasoningEffort =>\n value === \"none\"\n || value === \"low\"\n || value === \"medium\"\n || value === \"high\"\n || value === \"xhigh\"\n || value === \"max\"\n\nexport interface NormalizedReasoning {\n effort: ReasoningEffort\n changed: boolean\n reason?: \"unsupported-model\" | \"unsupported-effort\"\n}\n\n// Clamp a requested effort to what the model supports. Returns undefined\n// when the model does not accept reasoning at all (caller should strip it).\nexport const clampReasoningEffort = (\n modelId: string,\n requested: unknown,\n): NormalizedReasoning | undefined => {\n const capability = getModelCapability(modelId)\n if (!capability?.reasoning) return undefined\n\n const { supported, default: defaultEffort } = capability.reasoning\n\n if (requested === undefined || requested === null) {\n return { effort: defaultEffort, changed: false }\n }\n\n if (!isReasoningEffort(requested)) {\n return {\n effort: defaultEffort,\n changed: true,\n reason: \"unsupported-effort\",\n }\n }\n\n if (supported.includes(requested)) {\n return { effort: requested, changed: false }\n }\n\n // Pick the closest supported value by ordering low<medium<high<xhigh<max,\n // treat 'none' as below 'low'. If requested exceeds max supported, fall to\n // the highest supported; if below the lowest, fall to the lowest.\n const order: ReadonlyArray<ReasoningEffort> = [\n \"none\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n ]\n const reqIdx = order.indexOf(requested)\n const supportedSorted = [...supported].sort(\n (a, b) => order.indexOf(a) - order.indexOf(b),\n )\n const lowest = supportedSorted[0]\n const highest = supportedSorted[supportedSorted.length - 1]\n const fallback =\n reqIdx > order.indexOf(highest) ? highest\n : reqIdx < order.indexOf(lowest) ? lowest\n : (supportedSorted.find((e) => order.indexOf(e) >= reqIdx) ?? defaultEffort)\n\n return { effort: fallback, changed: true, reason: \"unsupported-effort\" }\n}\n","import consola from \"consola\"\n\nimport { runtimeState } from \"./state\"\n\nconst sleep = (ms: number) =>\n new Promise<void>((resolve) => {\n setTimeout(resolve, ms)\n })\n\n/**\n * Enforces the configured rate limit window between mutating upstream calls.\n *\n * - Resolves silently if no rate limit is configured or enough time has passed.\n * - Throws a Response (HTTP 429) when the window has not elapsed and `wait` is\n * disabled, so route handlers can `c.json` it directly.\n * - When `wait` is enabled, sleeps until the window elapses, then resolves.\n */\nexport const checkRateLimit = async (): Promise<void> => {\n const { rateLimitSeconds, rateLimitWait } = runtimeState\n if (rateLimitSeconds === undefined) return\n\n const now = Date.now()\n if (!runtimeState.lastRequestTimestamp) {\n runtimeState.lastRequestTimestamp = now\n return\n }\n\n const elapsed = (now - runtimeState.lastRequestTimestamp) / 1000\n if (elapsed > rateLimitSeconds) {\n runtimeState.lastRequestTimestamp = now\n return\n }\n\n const waitSeconds = Math.ceil(rateLimitSeconds - elapsed)\n\n if (!rateLimitWait) {\n consola.warn(\n `Rate limit exceeded. Need to wait ${waitSeconds} more seconds.`,\n )\n throw new RateLimitError(waitSeconds)\n }\n\n consola.warn(\n `Rate limit reached. Waiting ${waitSeconds}s before proceeding...`,\n )\n await sleep(waitSeconds * 1000)\n runtimeState.lastRequestTimestamp = Date.now()\n}\n\nexport class RateLimitError extends Error {\n readonly waitSeconds: number\n\n constructor(waitSeconds: number) {\n super(`Rate limit exceeded. Try again in ${waitSeconds}s.`)\n this.name = \"RateLimitError\"\n this.waitSeconds = waitSeconds\n }\n}\n","import { randomUUID } from \"node:crypto\"\n\nimport type {\n ChatCompletionChunk,\n ChatCompletionResponse,\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n} from \"~/providers/copilot/chat-types\"\n\nimport { sanitizeUserIdentifier } from \"./create-chat-completions\"\n\nexport interface ResponseStreamEventMessage {\n data?: string\n event?: string\n}\n\nexport interface ResponsesApiResponse {\n id: string\n created_at: number\n model: string\n output: Array<ResponsesOutputItem>\n usage?: {\n input_tokens: number\n input_tokens_details?: {\n cached_tokens?: number\n }\n output_tokens: number\n output_tokens_details?: {\n reasoning_tokens?: number\n }\n total_tokens: number\n }\n incomplete_details?: {\n reason?: string | null\n } | null\n}\n\nexport type ResponsesReasoningEffort =\n | \"none\"\n | \"low\"\n | \"medium\"\n | \"high\"\n | \"max\"\n | \"xhigh\"\n\ntype ResponsesInput = string | Array<ResponsesInputItem>\n\ntype ResponsesInputItem =\n | ResponsesMessageInput\n | ResponsesFunctionCallInput\n | ResponsesFunctionCallOutputInput\n\ntype ResponsesMessageInput = {\n role: \"user\" | \"assistant\" | \"system\" | \"developer\"\n content: string | Array<ResponsesInputContentPart>\n}\n\ntype ResponsesInputContentPart =\n | {\n type: \"input_text\"\n text: string\n }\n | {\n type: \"input_image\"\n image_url: string\n detail: \"low\" | \"high\" | \"auto\"\n }\n\ntype ResponsesFunctionCallInput = {\n type: \"function_call\"\n call_id: string\n name: string\n arguments: string\n}\n\ntype ResponsesFunctionCallOutputInput = {\n type: \"function_call_output\"\n call_id: string\n output: string\n}\n\ntype ResponsesToolChoice =\n | \"none\"\n | \"auto\"\n | \"required\"\n | { type: \"function\"; name: string }\n\nexport interface ResponsesRequestPayload {\n model: string\n input: ResponsesInput\n stream?: boolean | null\n max_output_tokens?: number | null\n temperature?: number | null\n top_p?: number | null\n user?: string | null\n reasoning?: {\n effort: ResponsesReasoningEffort\n }\n tools?: Array<ResponsesTool>\n tool_choice?: ResponsesToolChoice | null\n text?: {\n format: {\n type: \"json_object\"\n }\n }\n}\n\ninterface ResponsesTool {\n type: \"function\"\n name: string\n description?: string\n parameters: Record<string, unknown>\n}\n\ntype ResponsesOutputItem =\n | ResponsesMessageOutputItem\n | ResponsesFunctionCallOutputItem\n | ResponsesReasoningOutputItem\n\ninterface ResponsesMessageOutputItem {\n type: \"message\"\n role: \"assistant\"\n content: Array<ResponsesMessageContentPart>\n}\n\ninterface ResponsesMessageContentPart {\n type: \"output_text\"\n text: string\n}\n\ninterface ResponsesFunctionCallOutputItem {\n type: \"function_call\"\n call_id: string\n name: string\n arguments: string\n}\n\ninterface ResponsesReasoningOutputItem {\n type: \"reasoning\"\n}\n\ninterface ResponsesStreamEnvelope {\n type: string\n response?: {\n id: string\n created_at: number\n model: string\n usage?: ResponsesApiResponse[\"usage\"]\n output?: Array<ResponsesOutputItem>\n incomplete_details?: ResponsesApiResponse[\"incomplete_details\"]\n }\n item?:\n | Partial<ResponsesMessageOutputItem>\n | Partial<ResponsesFunctionCallOutputItem>\n output_index?: number\n delta?: string\n}\n\ninterface ResponseTranslationState {\n responseId: string\n createdAt: number\n model: string\n started: boolean\n}\n\ninterface CreateChunkOptions {\n delta: ChatCompletionChunk[\"choices\"][0][\"delta\"]\n finishReason?: ChatCompletionChunk[\"choices\"][0][\"finish_reason\"]\n usage?: ChatCompletionChunk[\"usage\"]\n}\n\nconst RESPONSES_ONLY_MODEL_PATTERN = /^(?:gpt-5\\.3-codex|gpt-5\\.4-mini)(?:-|$)/i\n\nexport function shouldUseResponsesApiForModel(model: string): boolean {\n return RESPONSES_ONLY_MODEL_PATTERN.test(model)\n}\n\nexport function buildResponsesRequestPayload(\n payload: ChatCompletionsPayload,\n reasoningEffort: ResponsesReasoningEffort | undefined,\n): ResponsesRequestPayload {\n return {\n model: payload.model,\n input: translateMessagesToResponsesInput(payload.messages),\n stream: payload.stream,\n max_output_tokens: payload.max_tokens,\n temperature: payload.temperature,\n top_p: payload.top_p,\n user: sanitizeUserIdentifier(payload.user),\n tools: translateTools(payload.tools),\n tool_choice: translateToolChoice(payload.tool_choice),\n reasoning: reasoningEffort ? { effort: reasoningEffort } : undefined,\n text:\n payload.response_format?.type === \"json_object\" ?\n { format: { type: \"json_object\" } }\n : undefined,\n }\n}\n\nexport function translateResponsesToChatCompletion(\n response: ResponsesApiResponse,\n): ChatCompletionResponse {\n const assistantMessages = response.output.filter(\n (item): item is ResponsesMessageOutputItem => item.type === \"message\",\n )\n const functionCalls = response.output.filter(\n (item): item is ResponsesFunctionCallOutputItem =>\n item.type === \"function_call\",\n )\n\n const content = assistantMessages\n .flatMap((item) => item.content)\n .map((part) => part.text)\n .join(\"\")\n\n return {\n id: response.id,\n object: \"chat.completion\",\n created: response.created_at,\n model: response.model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content: content || null,\n ...(functionCalls.length > 0 && {\n tool_calls: functionCalls.map((toolCall) => ({\n id: toolCall.call_id,\n type: \"function\" as const,\n function: {\n name: toolCall.name,\n arguments: toolCall.arguments,\n },\n })),\n }),\n },\n logprobs: null,\n finish_reason: getFinishReason(response, functionCalls.length > 0),\n },\n ],\n usage: translateUsage(response.usage),\n }\n}\n\nexport async function* translateResponsesStreamToChatCompletionStream(\n responseStream: AsyncIterable<ResponseStreamEventMessage>,\n): AsyncGenerator<ResponseStreamEventMessage> {\n const state: ResponseTranslationState = {\n responseId: randomUUID(),\n createdAt: Math.floor(Date.now() / 1000),\n model: \"\",\n started: false,\n }\n\n for await (const rawEvent of responseStream) {\n if (!rawEvent.data || rawEvent.data === \"[DONE]\") {\n continue\n }\n\n const event = JSON.parse(rawEvent.data) as ResponsesStreamEnvelope\n\n if (event.response) {\n state.responseId = event.response.id\n state.createdAt = event.response.created_at\n state.model = event.response.model\n }\n\n if (event.type === \"response.output_item.added\") {\n const chunk = handleOutputItemAdded(state, event)\n if (chunk) {\n yield chunk\n }\n continue\n }\n\n if (event.type === \"response.output_text.delta\") {\n yield createRoleChunk(state)\n yield createChunk(state, { delta: { content: event.delta } })\n continue\n }\n\n if (event.type === \"response.function_call_arguments.delta\") {\n if (event.output_index === undefined) {\n continue\n }\n\n yield createRoleChunk(state)\n yield createChunk(state, {\n delta: {\n tool_calls: [\n {\n index: event.output_index,\n type: \"function\",\n function: {\n arguments: event.delta ?? \"\",\n },\n },\n ],\n },\n })\n continue\n }\n\n if (event.type === \"response.completed\") {\n if (!event.response) {\n continue\n }\n\n yield createChunk(\n {\n ...state,\n responseId: event.response.id,\n createdAt: event.response.created_at,\n model: event.response.model,\n },\n {\n delta: {},\n finishReason: getFinishReason(\n {\n output: event.response.output ?? [],\n incomplete_details: event.response.incomplete_details,\n },\n (event.response.output ?? []).some(\n (item) => item.type === \"function_call\",\n ),\n ),\n usage: translateUsage(event.response.usage),\n },\n )\n yield { data: \"[DONE]\" }\n return\n }\n }\n}\n\nfunction handleOutputItemAdded(\n state: ResponseTranslationState,\n event: ResponsesStreamEnvelope,\n): ResponseStreamEventMessage | undefined {\n if (event.item?.type === \"message\") {\n return createRoleChunk(state)\n }\n\n if (\n event.item?.type === \"function_call\"\n && event.output_index !== undefined\n ) {\n state.started = true\n return createChunk(state, {\n delta: {\n role: \"assistant\",\n tool_calls: [\n {\n index: event.output_index,\n id: event.item.call_id,\n type: \"function\",\n function: {\n name: event.item.name,\n arguments: event.item.arguments ?? \"\",\n },\n },\n ],\n },\n })\n }\n\n return undefined\n}\n\nfunction createRoleChunk(\n state: ResponseTranslationState,\n): ResponseStreamEventMessage {\n if (state.started) {\n return { data: \"\" }\n }\n\n state.started = true\n return createChunk(state, { delta: { role: \"assistant\" } })\n}\n\nfunction createChunk(\n state: ResponseTranslationState,\n { delta, finishReason = null, usage }: CreateChunkOptions,\n): ResponseStreamEventMessage {\n return {\n data: JSON.stringify({\n id: state.responseId,\n object: \"chat.completion.chunk\",\n created: state.createdAt,\n model: state.model,\n choices: [\n {\n index: 0,\n delta,\n finish_reason: finishReason,\n logprobs: null,\n },\n ],\n usage,\n } satisfies ChatCompletionChunk),\n }\n}\n\nfunction translateMessagesToResponsesInput(\n messages: Array<Message>,\n): ResponsesInput {\n const items = messages.flatMap((message) => translateMessage(message))\n\n if (\n items.length === 1\n && \"role\" in items[0]\n && items[0].role === \"user\"\n && typeof items[0].content === \"string\"\n ) {\n return items[0].content\n }\n\n return items\n}\n\nfunction translateMessage(message: Message): Array<ResponsesInputItem> {\n if (message.role === \"tool\") {\n return [\n {\n type: \"function_call_output\",\n call_id: message.tool_call_id ?? \"\",\n output: stringifyToolOutput(message.content),\n },\n ]\n }\n\n const translated: Array<ResponsesInputItem> = []\n\n if (hasContent(message.content)) {\n translated.push({\n role: message.role,\n content: translateContent(message.content),\n })\n }\n\n if (message.role === \"assistant\" && message.tool_calls) {\n translated.push(\n ...message.tool_calls.map((toolCall) => ({\n type: \"function_call\" as const,\n call_id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n })),\n )\n }\n\n return translated\n}\n\nfunction hasContent(content: Message[\"content\"]): boolean {\n if (content === null) {\n return false\n }\n\n if (typeof content === \"string\") {\n return content.length > 0\n }\n\n return content.length > 0\n}\n\nfunction translateContent(\n content: Message[\"content\"],\n): ResponsesMessageInput[\"content\"] {\n if (typeof content === \"string\") {\n return content\n }\n\n if (!content || content.length === 0) {\n return \"\"\n }\n\n return content.map((part) => translateContentPart(part))\n}\n\nfunction translateContentPart(part: ContentPart): ResponsesInputContentPart {\n if (part.type === \"text\") {\n return {\n type: \"input_text\",\n text: part.text,\n }\n }\n\n return {\n type: \"input_image\",\n image_url: part.image_url.url,\n detail: part.image_url.detail ?? \"auto\",\n }\n}\n\nfunction stringifyToolOutput(content: Message[\"content\"]): string {\n if (typeof content === \"string\") {\n return content\n }\n\n if (!content) {\n return \"\"\n }\n\n const text = content\n .filter(\n (part): part is Extract<ContentPart, { type: \"text\" }> =>\n part.type === \"text\",\n )\n .map((part) => part.text)\n .join(\"\\n\\n\")\n\n return text || JSON.stringify(content)\n}\n\nfunction translateTools(\n tools: Array<Tool> | null | undefined,\n): Array<ResponsesTool> | undefined {\n if (!tools) {\n return undefined\n }\n\n return tools.map((tool) => ({\n type: \"function\",\n name: tool.function.name,\n description: tool.function.description,\n parameters: tool.function.parameters,\n }))\n}\n\nfunction translateToolChoice(\n toolChoice: ChatCompletionsPayload[\"tool_choice\"],\n): ResponsesToolChoice | undefined {\n if (!toolChoice) {\n return undefined\n }\n\n if (typeof toolChoice === \"string\") {\n return toolChoice\n }\n\n return {\n type: \"function\",\n name: toolChoice.function.name,\n }\n}\n\nfunction translateUsage(\n usage: ResponsesApiResponse[\"usage\"] | undefined,\n): ChatCompletionResponse[\"usage\"] | undefined {\n if (!usage) {\n return undefined\n }\n\n return {\n prompt_tokens: usage.input_tokens,\n completion_tokens: usage.output_tokens,\n total_tokens: usage.total_tokens,\n ...(usage.input_tokens_details?.cached_tokens !== undefined && {\n prompt_tokens_details: {\n cached_tokens: usage.input_tokens_details.cached_tokens,\n },\n }),\n }\n}\n\nfunction getFinishReason(\n response: Pick<ResponsesApiResponse, \"output\" | \"incomplete_details\">,\n hasFunctionCalls: boolean,\n): \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" {\n if (hasFunctionCalls) {\n return \"tool_calls\"\n }\n\n if (response.incomplete_details?.reason?.includes(\"max_output_tokens\")) {\n return \"length\"\n }\n\n return \"stop\"\n}\n","import consola from \"consola\"\nimport { events } from \"fetch-event-stream\"\n\nimport type { BridgeConfig } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { getClaudeSettingsEnv } from \"~/lib/claude-settings\"\nimport { fetchCopilot, getCopilotProviderContext } from \"~/providers/copilot/client\"\nimport type {\n ChatCompletionResponse,\n ChatCompletionsPayload,\n} from \"~/providers/copilot/chat-types\"\n\nimport {\n buildResponsesRequestPayload,\n shouldUseResponsesApiForModel,\n translateResponsesStreamToChatCompletionStream,\n translateResponsesToChatCompletion,\n type ResponsesApiResponse,\n type ResponsesReasoningEffort,\n} from \"./responses\"\n\nconst usesMaxCompletionTokens = (modelId: string): boolean =>\n modelId.startsWith(\"gpt-5\")\n\nconst isClaudeOpus47Model = (modelId: string): boolean =>\n modelId.startsWith(\"claude-opus-4.7\")\n\ntype ClaudeOpus47Effort = NonNullable<\n NonNullable<ChatCompletionsPayload[\"output_config\"]>[\"effort\"]\n>\n\ntype ClientKind = \"claude\" | \"codex\" | \"generic\"\n\nconst MAX_USER_LENGTH = 64\n\nconst defaultReasoningEffort = (\n modelId: string,\n): ChatCompletionsPayload[\"reasoning_effort\"] =>\n usesMaxCompletionTokens(modelId) ? \"medium\" : undefined\n\nconst getAllowedReasoningEfforts = (\n modelId: string,\n): Array<\n Exclude<ChatCompletionsPayload[\"reasoning_effort\"], null | undefined>\n> => {\n if (modelId.startsWith(\"gpt-5.5\")) {\n return [\"none\", \"low\", \"medium\", \"high\", \"xhigh\"]\n }\n\n if (modelId.startsWith(\"gpt-5.4-mini\")) {\n return [\"none\", \"low\", \"medium\"]\n }\n\n if (modelId.startsWith(\"gpt-5.4\") || modelId.startsWith(\"gpt-5.3-codex\")) {\n return [\"low\", \"medium\", \"high\", \"xhigh\"]\n }\n\n if (usesMaxCompletionTokens(modelId)) {\n return [\"low\", \"medium\", \"high\", \"xhigh\"]\n }\n\n return []\n}\n\nexport const sanitizeReasoningEffortForModel = (\n modelId: string,\n reasoningEffort: ChatCompletionsPayload[\"reasoning_effort\"],\n): ChatCompletionsPayload[\"reasoning_effort\"] => {\n if (!reasoningEffort) {\n return undefined\n }\n\n return getAllowedReasoningEfforts(modelId).includes(reasoningEffort) ?\n reasoningEffort\n : undefined\n}\n\nconst normalizeReasoningEffort = (\n value: string | undefined | null,\n): ChatCompletionsPayload[\"reasoning_effort\"] => {\n switch (value?.toLowerCase()) {\n case \"none\": {\n return \"none\"\n }\n case \"low\": {\n return \"low\"\n }\n case \"medium\": {\n return \"medium\"\n }\n case \"high\": {\n return \"high\"\n }\n case \"xhigh\": {\n return \"xhigh\"\n }\n case \"max\": {\n return \"max\"\n }\n default: {\n return undefined\n }\n }\n}\n\nconst normalizeClaudeOpus47Effort = (\n value: string | undefined | null,\n): ClaudeOpus47Effort | undefined => {\n switch (value?.toLowerCase()) {\n case \"low\": {\n return \"low\"\n }\n case \"medium\": {\n return \"medium\"\n }\n case \"high\": {\n return \"high\"\n }\n case \"xhigh\": {\n return \"xhigh\"\n }\n case \"max\": {\n return \"max\"\n }\n default: {\n return undefined\n }\n }\n}\n\nconst getEnvValueCaseInsensitive = (\n env: Record<string, string>,\n key: string,\n): string | undefined => {\n const direct = env[key]\n if (typeof direct === \"string\") {\n return direct\n }\n const lower = key.toLowerCase()\n const matched = Object.entries(env).find(([k]) => k.toLowerCase() === lower)\n return matched?.[1]\n}\n\nconst getConfiguredReasoningEffort = (\n client: ClientKind,\n claudeSettingsEnv: Record<string, string>,\n): string | undefined => {\n if (client !== \"claude\") {\n return undefined\n }\n\n return (\n // Prefer the normalized key name, keep COPILOT_* as a compatibility alias.\n process.env.MODEL_REASONING_EFFORT\n ?? process.env.COPILOT_REASONING_EFFORT\n ?? getEnvValueCaseInsensitive(claudeSettingsEnv, \"MODEL_REASONING_EFFORT\")\n ?? getEnvValueCaseInsensitive(claudeSettingsEnv, \"COPILOT_REASONING_EFFORT\")\n )\n}\n\nconst getRequestedReasoningEffort = (\n payload: ChatCompletionsPayload,\n claudeSettingsEnv: Record<string, string>,\n client: ClientKind,\n): ChatCompletionsPayload[\"reasoning_effort\"] => {\n const configuredReasoningEffort = getConfiguredReasoningEffort(\n client,\n claudeSettingsEnv,\n )\n\n const defaultEffort =\n client === \"claude\" ? \"medium\" : defaultReasoningEffort(payload.model)\n\n const requestedReasoningEffort =\n payload.reasoning_effort\n ?? normalizeReasoningEffort(configuredReasoningEffort)\n\n return (\n sanitizeReasoningEffortForModel(payload.model, requestedReasoningEffort)\n ?? defaultEffort\n )\n}\n\nconst getRequestedClaudeOpus47Effort = (\n payload: ChatCompletionsPayload,\n claudeSettingsEnv: Record<string, string>,\n client: ClientKind,\n): ClaudeOpus47Effort | undefined => {\n if (!isClaudeOpus47Model(payload.model)) {\n return undefined\n }\n\n const configuredReasoningEffort = getConfiguredReasoningEffort(\n client,\n claudeSettingsEnv,\n )\n\n return (\n payload.output_config?.effort\n ?? normalizeClaudeOpus47Effort(payload.reasoning_effort)\n ?? normalizeClaudeOpus47Effort(configuredReasoningEffort)\n ?? (client === \"claude\" ? \"medium\" : undefined)\n )\n}\n\nexport const sanitizeUserIdentifier = (\n user: string | null | undefined,\n): string | undefined => {\n if (!user) {\n return undefined\n }\n\n return user.slice(0, MAX_USER_LENGTH)\n}\n\ntype ChatCompletionsRequestPayload = Omit<\n ChatCompletionsPayload,\n \"max_tokens\"\n> & {\n max_tokens?: number | null\n max_completion_tokens?: number | null\n}\n\nconst buildRequestPayload = (\n payload: ChatCompletionsPayload,\n claudeSettingsEnv: Record<string, string>,\n client: ClientKind,\n): ChatCompletionsRequestPayload => {\n const requestedReasoningEffort = getRequestedReasoningEffort(\n payload,\n claudeSettingsEnv,\n client,\n )\n const requestedClaudeOpus47Effort = getRequestedClaudeOpus47Effort(\n payload,\n claudeSettingsEnv,\n client,\n )\n\n const reasoningEffort =\n (\n usesMaxCompletionTokens(payload.model)\n && payload.tools !== null\n && payload.tools !== undefined\n && payload.tools.length > 0\n ) ?\n undefined\n : requestedReasoningEffort\n\n if (\n !usesMaxCompletionTokens(payload.model)\n || payload.max_tokens === null\n || payload.max_tokens === undefined\n ) {\n const shouldAttachReasoningEffort = !isClaudeOpus47Model(payload.model)\n\n const sanitizedPayload = {\n ...payload,\n output_config:\n requestedClaudeOpus47Effort ?\n {\n ...payload.output_config,\n effort: requestedClaudeOpus47Effort,\n }\n : payload.output_config,\n reasoning_effort:\n shouldAttachReasoningEffort ? (\n payload.reasoning_effort\n ) : undefined,\n user: sanitizeUserIdentifier(payload.user),\n }\n\n return (\n !shouldAttachReasoningEffort\n || reasoningEffort === null\n || reasoningEffort === undefined\n ) ?\n sanitizedPayload\n : { ...sanitizedPayload, reasoning_effort: reasoningEffort }\n }\n\n return {\n ...payload,\n max_tokens: undefined,\n max_completion_tokens: payload.max_tokens,\n reasoning_effort: reasoningEffort,\n user: sanitizeUserIdentifier(payload.user),\n }\n}\n\nconst isAgentInitiator = (\n messages: ChatCompletionsPayload[\"messages\"],\n): \"agent\" | \"user\" =>\n messages.some((msg) => msg.role === \"assistant\" || msg.role === \"tool\") ?\n \"agent\"\n : \"user\"\n\nconst messagesIncludeImage = (\n messages: ChatCompletionsPayload[\"messages\"],\n): boolean =>\n messages.some(\n (msg) =>\n typeof msg.content !== \"string\"\n && msg.content?.some((part) => part.type === \"image_url\"),\n )\n\nexport const createChatCompletions = async (\n config: BridgeConfig,\n payload: ChatCompletionsPayload,\n options?: { client?: ClientKind },\n) => {\n const provider = getCopilotProviderContext(config)\n const enableVision = messagesIncludeImage(payload.messages)\n const initiator = isAgentInitiator(payload.messages)\n const client = options?.client ?? \"generic\"\n const claudeSettingsEnv =\n client === \"claude\" ? await getClaudeSettingsEnv() : {}\n const requestPayload = buildRequestPayload(payload, claudeSettingsEnv, client)\n\n if (shouldUseResponsesApiForModel(payload.model)) {\n return createResponses(provider, payload, claudeSettingsEnv, client, {\n vision: enableVision,\n initiator,\n })\n }\n\n const response = await fetchCopilot(\n provider,\n \"/chat/completions\",\n {\n method: \"POST\",\n headers: {\n accept: payload.stream ? \"text/event-stream\" : \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(requestPayload),\n },\n { vision: enableVision, initiator },\n )\n\n if (!response.ok) {\n if (await shouldRetryWithResponses(response)) {\n return createResponses(provider, payload, claudeSettingsEnv, client, {\n vision: enableVision,\n initiator,\n })\n }\n\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\nasync function createResponses(\n provider: ReturnType<typeof getCopilotProviderContext>,\n payload: ChatCompletionsPayload,\n claudeSettingsEnv: Record<string, string>,\n client: ClientKind,\n options: { vision: boolean; initiator: \"agent\" | \"user\" },\n) {\n const reasoningEffort = getRequestedReasoningEffort(\n payload,\n claudeSettingsEnv,\n client,\n ) as ResponsesReasoningEffort | undefined\n\n const response = await fetchCopilot(\n provider,\n \"/responses\",\n {\n method: \"POST\",\n headers: {\n accept: payload.stream ? \"text/event-stream\" : \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(\n buildResponsesRequestPayload(payload, reasoningEffort),\n ),\n },\n { vision: options.vision, initiator: options.initiator },\n )\n\n if (!response.ok) {\n consola.error(\"Failed to create responses\", response)\n throw new HTTPError(\"Failed to create responses\", response)\n }\n\n if (payload.stream) {\n return translateResponsesStreamToChatCompletionStream(events(response))\n }\n\n return translateResponsesToChatCompletion(\n (await response.json()) as ResponsesApiResponse,\n )\n}\n\nasync function shouldRetryWithResponses(response: Response): Promise<boolean> {\n try {\n const errorBody = (await response.clone().json()) as {\n error?: {\n code?: string\n }\n }\n\n return errorBody.error?.code === \"unsupported_api_for_model\"\n } catch {\n return false\n }\n}\n","import { Hono } from \"hono\"\nimport { streamSSE, type SSEMessage } from \"hono/streaming\"\n\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { BridgeNotImplementedError, HTTPError } from \"~/lib/error\"\nimport { checkRateLimit, RateLimitError } from \"~/lib/rate-limit\"\nimport type {\n ChatCompletionResponse,\n ChatCompletionsPayload,\n} from \"~/providers/copilot/chat-types\"\nimport { createChatCompletions } from \"~/services/copilot/create-chat-completions\"\n\nexport const chatCompletionRoutes = new Hono<BridgeEnv>()\n\nconst isNonStreaming = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse =>\n typeof response === \"object\"\n && response !== null\n && Object.hasOwn(response, \"choices\")\n\nchatCompletionRoutes.post(\"/\", async (c) => {\n try {\n await checkRateLimit()\n const payload = await c.req.json<ChatCompletionsPayload>()\n const response = await createChatCompletions(c.var.config, payload, {\n client: \"generic\",\n })\n\n if (isNonStreaming(response)) {\n return c.json(response)\n }\n\n return streamSSE(c, async (stream) => {\n for await (const chunk of response) {\n await stream.writeSSE(chunk as SSEMessage)\n }\n })\n } catch (error) {\n if (error instanceof RateLimitError) {\n return c.json({ error: { message: error.message } }, 429)\n }\n if (error instanceof BridgeNotImplementedError) {\n return c.json(\n { error: { type: error.name, message: error.message } },\n 501,\n )\n }\n if (error instanceof HTTPError) {\n const text = await error.response.text().catch(() => \"\")\n return new Response(text, {\n status: error.response.status,\n headers: {\n \"content-type\":\n error.response.headers.get(\"content-type\") ?? \"application/json\",\n },\n })\n }\n throw error\n }\n})\n","import type { BridgeConfig } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { fetchCopilot, getCopilotProviderContext } from \"./client\"\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\nexport const createEmbeddings = async (\n config: BridgeConfig,\n payload: EmbeddingRequest,\n): Promise<EmbeddingResponse> => {\n const provider = getCopilotProviderContext(config)\n const response = await fetchCopilot(provider, \"/embeddings\", {\n method: \"POST\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to create embeddings\", response)\n }\n\n return (await response.json()) as EmbeddingResponse\n}\n","import { Hono } from \"hono\"\n\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { checkRateLimit, RateLimitError } from \"~/lib/rate-limit\"\nimport {\n createEmbeddings,\n type EmbeddingRequest,\n} from \"~/providers/copilot/create-embeddings\"\n\nexport const embeddingRoutes = new Hono<BridgeEnv>()\n\nembeddingRoutes.post(\"/\", async (c) => {\n try {\n await checkRateLimit()\n const payload = await c.req.json<EmbeddingRequest>()\n const response = await createEmbeddings(c.var.config, payload)\n return c.json(response)\n } catch (error) {\n if (error instanceof RateLimitError) {\n return c.json({ error: { message: error.message } }, 429)\n }\n if (error instanceof HTTPError) {\n const text = await error.response.text().catch(() => \"\")\n return new Response(text, {\n status: error.response.status,\n headers: {\n \"content-type\":\n error.response.headers.get(\"content-type\") ?? \"application/json\",\n },\n })\n }\n throw error\n }\n})\n","import type { Model } from \"~/providers/copilot/get-models\"\n\nimport { runtimeState } from \"./state\"\n\nconst normalizeModelId = (modelId: string): string =>\n modelId.trim().toLowerCase().replaceAll(/[\\s._-]+/g, \"\")\n\nconst stripSnapshotSuffix = (modelId: string): string => {\n const id = modelId.trim().toLowerCase().replace(/\\[1m\\]$/, \"\")\n\n if (id.startsWith(\"claude-sonnet-4-\")) {\n return \"claude-sonnet-4\"\n }\n\n if (/^claude-opus-4-7-\\d{8}$/.test(id)) {\n return \"claude-opus-4.7\"\n }\n\n if (id.startsWith(\"claude-opus-4-\")) {\n return \"claude-opus-4\"\n }\n\n return id\n}\n\nconst getAliasCandidates = (modelId: string): Array<string> => {\n const canonicalModelId = stripSnapshotSuffix(modelId)\n const aliases = new Set<string>([canonicalModelId])\n\n const familyMatch = canonicalModelId.match(\n /^[a-z]+(?:-[a-z]+)*-\\d+(?:\\.\\d+)?/,\n )\n if (familyMatch) {\n aliases.add(familyMatch[0])\n aliases.add(familyMatch[0].replace(/\\.\\d+$/, \"\"))\n }\n\n if (/^gpt-5(?:[.-]\\d+)?$/i.test(canonicalModelId)) {\n aliases.add(\"gpt-5\")\n }\n\n return [...aliases]\n}\n\nconst scoreModelCandidate = (model: Model): number => {\n let score = 0\n\n if (model.model_picker_enabled) {\n score += 20\n }\n\n if (!model.preview) {\n score += 10\n }\n\n if (/mini|nano|fast|flash|haiku/i.test(model.id)) {\n score -= 15\n }\n\n return score - model.id.length / 1000\n}\n\nconst pickBestModel = (models: Array<Model>): Model | undefined =>\n [...models].sort(\n (left, right) => scoreModelCandidate(right) - scoreModelCandidate(left),\n )[0]\n\nconst getBestPrefixMatches = (\n models: Array<Model>,\n aliasCandidates: Array<string>,\n): Array<Model> => {\n let bestMatchLength = 0\n const matches: Array<Model> = []\n\n for (const model of models) {\n const normalizedModelId = normalizeModelId(model.id)\n const matchedAliasLength = Math.max(\n 0,\n ...aliasCandidates.map((candidate) => {\n const normalizedCandidate = normalizeModelId(candidate)\n return normalizedCandidate.length >= 4\n && normalizedModelId.startsWith(normalizedCandidate)\n ? normalizedCandidate.length\n : 0\n }),\n )\n\n if (matchedAliasLength === 0) continue\n\n if (matchedAliasLength > bestMatchLength) {\n bestMatchLength = matchedAliasLength\n matches.length = 0\n matches.push(model)\n continue\n }\n\n if (matchedAliasLength === bestMatchLength) {\n matches.push(model)\n }\n }\n\n return matches\n}\n\nexport const resolveModel = (\n requestedModelId: string,\n models: Array<Model> | undefined = runtimeState.models?.data,\n): Model | undefined => {\n if (!models || models.length === 0) {\n return undefined\n }\n\n const exactMatch = models.find((model) => model.id === requestedModelId)\n if (exactMatch) return exactMatch\n\n const aliasCandidates = getAliasCandidates(requestedModelId)\n const normalizedAliases = new Set(\n aliasCandidates.map((candidate) => normalizeModelId(candidate)),\n )\n\n const normalizedExactMatches = models.filter((model) =>\n normalizedAliases.has(normalizeModelId(model.id)),\n )\n if (normalizedExactMatches.length > 0) {\n return pickBestModel(normalizedExactMatches)\n }\n\n const familyPrefixMatches = getBestPrefixMatches(models, aliasCandidates)\n return pickBestModel(familyPrefixMatches)\n}\n\nexport const resolveUpstreamModelId = (\n requestedModelId: string,\n models: Array<Model> | undefined = runtimeState.models?.data,\n): string =>\n resolveModel(requestedModelId, models)?.id ?? stripSnapshotSuffix(requestedModelId)\n","import type { AnthropicResponse } from \"~/bridges/claude/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\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\n return stopReasonMap[finishReason]\n}\n","import { resolveUpstreamModelId } from \"~/lib/models-resolver\"\nimport { sanitizeReasoningEffortForModel } from \"~/services/copilot/create-chat-completions\"\nimport type {\n ChatCompletionResponse,\n ChatCompletionsPayload,\n ContentPart,\n Message,\n TextPart,\n Tool,\n ToolCall,\n} from \"~/providers/copilot/chat-types\"\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 \"~/bridges/claude/anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"~/bridges/claude/utils\"\n\nconst normalizeClaudeModelAlias = (model: string): string => {\n const normalized = model.trim().toLowerCase().replace(/\\[1m\\]$/, \"\")\n\n if (/^claude-(opus|sonnet|haiku)-\\d-\\d(?:-1m)?$/.test(normalized)) {\n return normalized.replace(\n /^claude-(opus|sonnet|haiku)-(\\d)-(\\d)(-1m)?$/,\n \"claude-$1-$2.$3$4\",\n )\n }\n\n if (/^claude-opus-4-7-\\d{8}$/.test(normalized)) {\n return \"claude-opus-4.7\"\n }\n\n return normalized\n}\n\nfunction translateModelName(model: string): string {\n return resolveUpstreamModelId(normalizeClaudeModelAlias(model))\n}\n\nfunction isClaudeModel(modelId: string): boolean {\n return modelId.startsWith(\"claude-\")\n}\n\nfunction isClaudeOpus47Model(modelId: string): boolean {\n return modelId.startsWith(\"claude-opus-4.7\")\n}\n\ntype ClaudeOpus47Effort = NonNullable<\n NonNullable<ChatCompletionsPayload[\"output_config\"]>[\"effort\"]\n>\n\nfunction normalizeClaudeEffort(\n value: string | undefined,\n): ClaudeOpus47Effort | undefined {\n switch (value?.toLowerCase()) {\n case \"low\": {\n return \"low\"\n }\n case \"medium\": {\n return \"medium\"\n }\n case \"high\": {\n return \"high\"\n }\n case \"xhigh\": {\n return \"xhigh\"\n }\n case \"max\": {\n return \"max\"\n }\n default: {\n return undefined\n }\n }\n}\n\nfunction getClaudeOpus47Effort(\n payload: AnthropicMessagesPayload,\n): ClaudeOpus47Effort | undefined {\n const explicitEffort = normalizeClaudeEffort(payload.reasoning_effort)\n if (explicitEffort) {\n return explicitEffort\n }\n\n if (payload.thinking?.type !== \"enabled\") {\n return undefined\n }\n\n const budgetTokens = payload.thinking.budget_tokens\n if (budgetTokens === undefined) {\n return \"medium\"\n }\n\n if (budgetTokens <= 2_048) {\n return \"low\"\n }\n\n if (budgetTokens <= 8_192) {\n return \"medium\"\n }\n\n if (budgetTokens <= 24_576) {\n return \"high\"\n }\n\n return \"xhigh\"\n}\n\nfunction translateThinking(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload[\"thinking\"] {\n const modelId = translateModelName(payload.model)\n\n if (!isClaudeOpus47Model(modelId)) {\n return undefined\n }\n\n if (payload.thinking?.type === \"adaptive\") {\n return { type: \"adaptive\" }\n }\n\n return payload.thinking?.type === \"enabled\" ? { type: \"adaptive\" } : undefined\n}\n\nfunction translateOutputConfig(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload[\"output_config\"] {\n const modelId = translateModelName(payload.model)\n\n if (!isClaudeOpus47Model(modelId)) {\n return undefined\n }\n\n const effort = getClaudeOpus47Effort(payload)\n\n return effort ? { effort } : undefined\n}\n\nfunction normalizeReasoningEffort(\n value: string,\n): ChatCompletionsPayload[\"reasoning_effort\"] {\n switch (value.toLowerCase()) {\n case \"none\": {\n return \"none\"\n }\n case \"low\": {\n return \"low\"\n }\n case \"medium\": {\n return \"medium\"\n }\n case \"high\": {\n return \"high\"\n }\n case \"xhigh\": {\n return \"xhigh\"\n }\n case \"max\": {\n return \"max\"\n }\n default: {\n return undefined\n }\n }\n}\n\nfunction translateReasoningEffort(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload[\"reasoning_effort\"] {\n const modelId = translateModelName(payload.model)\n\n if (isClaudeModel(modelId)) {\n return undefined\n }\n\n if (payload.reasoning_effort) {\n const requested = normalizeReasoningEffort(payload.reasoning_effort)\n return sanitizeReasoningEffortForModel(modelId, requested)\n }\n\n if (payload.thinking?.type !== \"enabled\") {\n return undefined\n }\n\n const budgetTokens = payload.thinking.budget_tokens\n if (budgetTokens === undefined) {\n return sanitizeReasoningEffortForModel(modelId, \"medium\")\n }\n\n if (budgetTokens <= 2_048) {\n return sanitizeReasoningEffortForModel(modelId, \"low\")\n }\n\n if (budgetTokens <= 8_192) {\n return sanitizeReasoningEffortForModel(modelId, \"medium\")\n }\n\n if (budgetTokens <= 24_576) {\n return sanitizeReasoningEffortForModel(modelId, \"high\")\n }\n\n return sanitizeReasoningEffortForModel(modelId, \"xhigh\")\n}\n\nexport function translateToOpenAI(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload {\n const model = translateModelName(payload.model)\n\n return {\n model,\n messages: translateAnthropicMessagesToOpenAI(payload.messages, payload.system),\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 thinking: translateThinking(payload),\n output_config: translateOutputConfig(payload),\n reasoning_effort: translateReasoningEffort(payload),\n user: payload.metadata?.user_id,\n tools: translateAnthropicToolsToOpenAI(payload.tools),\n tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),\n }\n}\n\nfunction translateAnthropicMessagesToOpenAI(\n anthropicMessages: Array<AnthropicMessage>,\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n const systemMessages = handleSystemPrompt(system)\n const otherMessages = anthropicMessages.flatMap((message) =>\n message.role === \"user\" ? handleUserMessage(message) : handleAssistantMessage(message),\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 }\n\n return [{ role: \"system\", content: system.map((block) => block.text).join(\"\\n\\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 => block.type === \"tool_result\",\n )\n const otherBlocks = message.content.filter((block) => block.type !== \"tool_result\")\n\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(message: AnthropicAssistantMessage): Array<Message> {\n if (!Array.isArray(message.content)) {\n return [{ role: \"assistant\", content: mapContent(message.content) }]\n }\n\n const toolUseBlocks = message.content.filter(\n (block): block is AnthropicToolUseBlock => block.type === \"tool_use\",\n )\n const textBlocks = message.content.filter(\n (block): block is AnthropicTextBlock => block.type === \"text\",\n )\n const thinkingBlocks = message.content.filter(\n (block): block is AnthropicThinkingBlock => block.type === \"thinking\",\n )\n\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 : [{ role: \"assistant\", content: mapContent(message.content) }]\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\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 break\n }\n case \"thinking\": {\n contentParts.push({ type: \"text\", text: block.thinking })\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 break\n }\n }\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\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\nexport function translateToAnthropic(\n response: ChatCompletionResponse,\n): AnthropicResponse {\n const allTextBlocks: Array<AnthropicTextBlock> = []\n const allToolUseBlocks: Array<AnthropicToolUseBlock> = []\n let stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null = null\n\n stopReason = response.choices[0]?.finish_reason ?? stopReason\n\n for (const choice of response.choices) {\n allTextBlocks.push(...getAnthropicTextBlocks(choice.message.content))\n allToolUseBlocks.push(...getAnthropicToolUseBlocks(choice.message.tool_calls))\n\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\n stopReason = choice.finish_reason\n }\n }\n\n return {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n model: response.model,\n content: [...allTextBlocks, ...allToolUseBlocks],\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\n stop_sequence: null,\n usage: {\n input_tokens:\n (response.usage?.prompt_tokens ?? 0)\n - (response.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: response.usage?.completion_tokens ?? 0,\n ...(response.usage?.prompt_tokens_details?.cached_tokens !== undefined && {\n cache_read_input_tokens: 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\n return toolCalls.map((toolCall) => ({\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: safeJsonParse(toolCall.function.arguments),\n }))\n}\n\nfunction safeJsonParse(input: string): Record<string, unknown> {\n try {\n return JSON.parse(input) as Record<string, unknown>\n } catch {\n return { raw: input }\n }\n}\n","import type {\n AnthropicStreamEventData,\n AnthropicStreamState,\n} from \"~/bridges/claude/anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"~/bridges/claude/utils\"\nimport type { ChatCompletionChunk } from \"~/providers/copilot/chat-types\"\n\nfunction isToolBlockOpen(state: AnthropicStreamState): boolean {\n if (!state.contentBlockOpen) {\n return false\n }\n\n return Object.values(state.toolCalls).some(\n (tc) => tc.anthropicBlockIndex === state.contentBlockIndex,\n )\n}\n\nexport function translateChunkToAnthropicEvents(\n chunk: ChatCompletionChunk,\n state: AnthropicStreamState,\n): Array<AnthropicStreamEventData> {\n const events: Array<AnthropicStreamEventData> = []\n\n if (chunk.choices.length === 0) {\n return events\n }\n\n const choice = chunk.choices[0]\n const { delta } = choice\n\n if (!state.messageStartSent) {\n events.push({\n type: \"message_start\",\n message: {\n id: chunk.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: chunk.model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens:\n (chunk.usage?.prompt_tokens ?? 0)\n - (chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: 0,\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens !== undefined && {\n cache_read_input_tokens: chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n })\n state.messageStartSent = true\n }\n\n if (delta.content) {\n if (isToolBlockOpen(state)) {\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 if (state.contentBlockOpen) {\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 if (toolCallInfo) {\n events.push({\n type: \"content_block_delta\",\n index: toolCallInfo.anthropicBlockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: toolCall.function.arguments,\n },\n })\n }\n }\n }\n }\n\n if (choice.finish_reason) {\n if (state.contentBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockOpen = false\n }\n\n events.push(\n {\n type: \"message_delta\",\n delta: {\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\n stop_sequence: null,\n },\n usage: {\n input_tokens:\n (chunk.usage?.prompt_tokens ?? 0)\n - (chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: chunk.usage?.completion_tokens ?? 0,\n ...(chunk.usage?.prompt_tokens_details?.cached_tokens !== undefined && {\n cache_read_input_tokens: chunk.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n },\n {\n type: \"message_stop\",\n },\n )\n }\n\n return events\n}\n\nexport function translateErrorToAnthropicErrorEvent(): AnthropicStreamEventData {\n return {\n type: \"error\",\n error: {\n type: \"api_error\",\n message: \"An unexpected error occurred during streaming.\",\n },\n }\n}\n","import type {\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n ToolCall,\n} from \"~/providers/copilot/chat-types\"\nimport type { Model } from \"~/providers/copilot/get-models\"\n\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\ninterface Encoder {\n encode: (text: string) => Array<number>\n}\n\nconst encodingCache = new Map<string, Encoder>()\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\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\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\") tokens += tokensPerName\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\nconst calculateTokens = (\n messages: Array<Message>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (messages.length === 0) return 0\n let numTokens = 0\n for (const message of messages) {\n numTokens += calculateMessageTokens(message, encoder, constants)\n }\n numTokens += 3\n return numTokens\n}\n\nconst getEncodeChatFunction = async (encoding: string): Promise<Encoder> => {\n if (encodingCache.has(encoding)) {\n const cached = encodingCache.get(encoding)\n if (cached) return cached\n }\n\n const supported = encoding as SupportedEncoding\n if (!(supported in ENCODING_MAP)) {\n const fallback = (await ENCODING_MAP.o200k_base()) as Encoder\n encodingCache.set(encoding, fallback)\n return fallback\n }\n\n const mod = (await ENCODING_MAP[supported]()) as Encoder\n encodingCache.set(encoding, mod)\n return mod\n}\n\nexport const getTokenizerFromModel = (model: Model): string =>\n model.capabilities.tokenizer || \"o200k_base\"\n\nconst getModelConstants = (model: Model) =>\n 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\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 if (typeof prop !== \"object\" || prop === null) return tokens\n\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 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 if (paramDesc.endsWith(\".\")) paramDesc = paramDesc.slice(0, -1)\n\n const line = `${paramName}:${paramType}:${paramDesc}`\n tokens += encoder.encode(line).length\n\n const excludedKeys = new Set([\"type\", \"description\", \"enum\"])\n for (const propertyName of Object.keys(param)) {\n if (excludedKeys.has(propertyName)) continue\n const propertyValue = param[propertyName]\n const propertyText =\n typeof propertyValue === \"string\"\n ? propertyValue\n : JSON.stringify(propertyValue)\n tokens += encoder.encode(`${propertyName}:${propertyText}`).length\n }\n\n return tokens\n}\n\nconst calculateParametersTokens = (\n parameters: unknown,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (!parameters || typeof parameters !== \"object\") return 0\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\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(\".\")) fDesc = fDesc.slice(0, -1)\n tokens += encoder.encode(`${fName}:${fDesc}`).length\n if (typeof func.parameters === \"object\" && func.parameters !== null) {\n tokens += calculateParametersTokens(func.parameters, encoder, constants)\n }\n return tokens\n}\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\nexport const getTokenCount = async (\n payload: ChatCompletionsPayload,\n model: Model,\n): Promise<{ input: number; output: number }> => {\n const tokenizer = getTokenizerFromModel(model)\n const encoder = await getEncodeChatFunction(tokenizer)\n\n const inputMessages = payload.messages.filter((msg) => msg.role !== \"assistant\")\n const outputMessages = payload.messages.filter((msg) => msg.role === \"assistant\")\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 { input: inputTokens, output: outputTokens }\n}\n","import consola from \"consola\"\nimport { Hono } from \"hono\"\nimport { streamSSE } from \"hono/streaming\"\n\nimport {\n type AnthropicMessagesPayload,\n type AnthropicStreamState,\n} from \"~/bridges/claude/anthropic-types\"\nimport {\n translateToAnthropic,\n translateToOpenAI,\n} from \"~/bridges/claude/non-stream-translation\"\nimport {\n translateChunkToAnthropicEvents,\n translateErrorToAnthropicErrorEvent,\n} from \"~/bridges/claude/stream-translation\"\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { BridgeNotImplementedError, HTTPError } from \"~/lib/error\"\nimport { checkRateLimit, RateLimitError } from \"~/lib/rate-limit\"\nimport { resolveModel } from \"~/lib/models-resolver\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\nimport type {\n ChatCompletionChunk,\n ChatCompletionResponse,\n} from \"~/providers/copilot/chat-types\"\nimport { createChatCompletions } from \"~/services/copilot/create-chat-completions\"\n\nexport const messageRoutes = new Hono<BridgeEnv>()\n\nconst isNonStreamingResponse = (\n response: Awaited<ReturnType<typeof createChatCompletions>>,\n): response is ChatCompletionResponse =>\n typeof response === \"object\"\n && response !== null\n && Object.hasOwn(response, \"choices\")\n\nmessageRoutes.post(\"/\", async (c) => {\n const config = c.get(\"config\")\n try {\n await checkRateLimit()\n } catch (error) {\n if (error instanceof RateLimitError) {\n return c.json({ error: { message: error.message } }, 429)\n }\n throw error\n }\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n try {\n const response = await createChatCompletions(config, openAIPayload, {\n client: \"claude\",\n })\n\n if (isNonStreamingResponse(response)) {\n return c.json(translateToAnthropic(response))\n }\n\n return streamSSE(c, async (stream) => {\n const streamState: AnthropicStreamState = {\n messageStartSent: false,\n contentBlockIndex: 0,\n contentBlockOpen: false,\n toolCalls: {},\n }\n\n try {\n for await (const rawEvent of response) {\n if (rawEvent.data === \"[DONE]\") {\n break\n }\n\n if (!rawEvent.data) {\n continue\n }\n\n let chunk: ChatCompletionChunk\n try {\n chunk = JSON.parse(rawEvent.data) as ChatCompletionChunk\n } catch {\n continue\n }\n\n const events = translateChunkToAnthropicEvents(chunk, streamState)\n for (const event of events) {\n await stream.writeSSE({\n event: event.type,\n data: JSON.stringify(event),\n })\n }\n }\n } catch (error) {\n consola.error(\"Error during Anthropic stream translation:\", error)\n const errorEvent = translateErrorToAnthropicErrorEvent()\n await stream.writeSSE({\n event: errorEvent.type,\n data: JSON.stringify(errorEvent),\n })\n }\n })\n } catch (error) {\n if (error instanceof BridgeNotImplementedError) {\n return c.json(\n { error: { type: error.name, message: error.message } },\n 501,\n )\n }\n\n if (error instanceof HTTPError) {\n const text = await error.response.text().catch(() => \"\")\n return new Response(text, {\n status: error.response.status,\n headers: {\n \"content-type\":\n error.response.headers.get(\"content-type\") ?? \"application/json\",\n },\n })\n }\n\n throw error\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n const selectedModel = resolveModel(openAIPayload.model)\n\n if (!selectedModel) {\n consola.warn(\n `Model ${openAIPayload.model} not found in registry, returning fallback token count`,\n )\n return c.json({ input_tokens: 1 })\n }\n\n const tokenCount = await getTokenCount(openAIPayload, selectedModel)\n const effectiveModelId = selectedModel.id\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 (effectiveModelId.startsWith(\"claude\")) {\n tokenCount.input += 346\n } else if (effectiveModelId.startsWith(\"grok\")) {\n tokenCount.input += 480\n }\n }\n }\n\n let finalTokenCount = tokenCount.input + tokenCount.output\n if (effectiveModelId.startsWith(\"claude\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.15)\n } else if (effectiveModelId.startsWith(\"grok\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.03)\n }\n\n return c.json({ input_tokens: Math.max(1, finalTokenCount) })\n } catch (error) {\n consola.error(\"Error counting tokens:\", error)\n return c.json({ input_tokens: 1 })\n }\n})\n","import { Hono } from \"hono\"\n\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { BridgeNotImplementedError } from \"~/lib/error\"\nimport {\n fetchCopilot,\n getCopilotProviderContext,\n} from \"~/providers/copilot/client\"\n\nexport const modelRoutes = new Hono<BridgeEnv>()\n\nmodelRoutes.get(\"/\", async (c) => {\n const config = c.get(\"config\")\n const provider = getCopilotProviderContext(config)\n const search = new URL(c.req.url).search\n\n try {\n const upstream = await fetchCopilot(provider, `/models${search}`, {\n method: \"GET\",\n headers: {\n accept: c.req.header(\"accept\") ?? \"application/json\",\n },\n })\n\n return new Response(upstream.body, {\n status: upstream.status,\n headers: upstream.headers,\n })\n } catch (error) {\n if (error instanceof BridgeNotImplementedError) {\n return c.json(\n {\n error: {\n type: error.name,\n message: error.message,\n },\n },\n 500,\n )\n }\n\n throw error\n }\n})\n","// Translation layer: Codex /v1/responses ⇄ Copilot /v1/chat/completions.\n// Used for models that do not implement the Responses API upstream\n// (claude-*, gemini-*).\n//\n// Strategy:\n// - Translate the Responses request to a Chat Completions request.\n// - Force upstream to non-stream (stream: false) so we get a single JSON.\n// - Translate that JSON to a Responses API JSON.\n// - If the original request asked for stream:true, synthesize a tiny\n// sequence of SSE events (response.created → output_item.added →\n// content_part.added → output_text.delta → ... → response.completed)\n// so codex's bookkeeping still works.\n\nimport { randomUUID } from \"node:crypto\"\n\nimport type { ModelCapability, ReasoningEffort } from \"~/lib/model-capabilities\"\n\n// ---------- Responses (input) types — only what we read ----------\n\ninterface ResponsesInputMessage {\n type?: \"message\"\n role: \"user\" | \"assistant\" | \"system\" | \"developer\"\n content: string | Array<ResponsesInputContentPart>\n}\n\ninterface ResponsesInputContentPart {\n type:\n | \"input_text\"\n | \"output_text\"\n | \"input_image\"\n | \"text\"\n text?: string\n image_url?: string | { url: string }\n detail?: \"low\" | \"high\" | \"auto\"\n}\n\ninterface ResponsesFunctionCallInput {\n type: \"function_call\"\n call_id: string\n name: string\n arguments: string\n}\n\ninterface ResponsesFunctionCallOutputInput {\n type: \"function_call_output\"\n call_id: string\n output: string\n}\n\ntype ResponsesInputItem =\n | ResponsesInputMessage\n | ResponsesFunctionCallInput\n | ResponsesFunctionCallOutputInput\n\ninterface ResponsesTool {\n type: \"function\"\n name?: string\n description?: string\n parameters?: Record<string, unknown>\n function?: {\n name: string\n description?: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ResponsesRequestLike {\n model: string\n input?: string | Array<ResponsesInputItem>\n instructions?: string\n stream?: boolean\n max_output_tokens?: number\n temperature?: number\n top_p?: number\n user?: string\n tools?: Array<ResponsesTool>\n tool_choice?:\n | \"auto\"\n | \"none\"\n | \"required\"\n | { type: \"function\"; name: string }\n reasoning?: { effort?: ReasoningEffort; [k: string]: unknown }\n [key: string]: unknown\n}\n\n// ---------- Chat completion types — only what we send/read ----------\n\ntype ChatRole = \"system\" | \"user\" | \"assistant\" | \"tool\"\n\ninterface ChatContentPart {\n type: \"text\" | \"image_url\"\n text?: string\n image_url?: { url: string; detail?: \"low\" | \"high\" | \"auto\" }\n}\n\ninterface ChatToolCall {\n id: string\n type: \"function\"\n function: { name: string; arguments: string }\n}\n\ninterface ChatMessage {\n role: ChatRole\n content?: string | Array<ChatContentPart> | null\n name?: string\n tool_call_id?: string\n tool_calls?: Array<ChatToolCall>\n}\n\ninterface ChatTool {\n type: \"function\"\n function: {\n name: string\n description?: string\n parameters?: Record<string, unknown>\n }\n}\n\ninterface ChatRequestPayload {\n model: string\n messages: Array<ChatMessage>\n stream: boolean\n max_tokens?: number\n temperature?: number\n top_p?: number\n user?: string\n tools?: Array<ChatTool>\n tool_choice?: unknown\n reasoning_effort?: ReasoningEffort\n output_config?: { effort?: ReasoningEffort }\n}\n\ninterface ChatCompletionResponse {\n id?: string\n created?: number\n model?: string\n choices: Array<{\n index?: number\n message: ChatMessage & { role: \"assistant\" }\n finish_reason?: string | null\n }>\n usage?: {\n prompt_tokens?: number\n completion_tokens?: number\n total_tokens?: number\n }\n}\n\n// ---------- Helpers ----------\n\nconst collectText = (\n content: string | Array<ResponsesInputContentPart> | undefined,\n): { text: string; parts: Array<ChatContentPart> } => {\n if (typeof content === \"string\") {\n return { text: content, parts: [{ type: \"text\", text: content }] }\n }\n const parts: Array<ChatContentPart> = []\n let textBuf = \"\"\n for (const p of content ?? []) {\n if (p.type === \"input_text\" || p.type === \"output_text\" || p.type === \"text\") {\n const t = p.text ?? \"\"\n textBuf += t\n parts.push({ type: \"text\", text: t })\n } else if (p.type === \"input_image\") {\n const url =\n typeof p.image_url === \"string\" ?\n p.image_url\n : (p.image_url?.url ?? \"\")\n if (url) parts.push({ type: \"image_url\", image_url: { url, detail: p.detail } })\n }\n }\n return { text: textBuf, parts }\n}\n\nconst placeReasoning = (\n payload: ChatRequestPayload,\n capability: ModelCapability,\n effort: ReasoningEffort | undefined,\n) => {\n if (!effort || !capability.reasoning) return\n if (capability.reasoningField === \"output_config.effort\") {\n payload.output_config = { ...(payload.output_config ?? {}), effort }\n } else {\n payload.reasoning_effort = effort\n }\n}\n\n// ---------- Public: translate request ----------\n\nexport const responsesPayloadToChatPayload = (\n request: ResponsesRequestLike,\n capability: ModelCapability,\n): ChatRequestPayload => {\n const messages: Array<ChatMessage> = []\n\n if (request.instructions) {\n messages.push({ role: \"system\", content: request.instructions })\n }\n\n const inputItems: Array<ResponsesInputItem> =\n typeof request.input === \"string\" ?\n [{ role: \"user\", content: request.input } as ResponsesInputMessage]\n : (request.input ?? [])\n\n for (const item of inputItems) {\n if (\"role\" in item && (item.type === undefined || item.type === \"message\")) {\n const { text, parts } = collectText(item.content)\n const role: ChatRole =\n item.role === \"developer\" ? \"system\"\n : item.role === \"system\" ? \"system\"\n : item.role === \"assistant\" ? \"assistant\"\n : \"user\"\n // Use string content when single text part for simplicity.\n const useStringContent =\n parts.length <= 1 && parts.every((p) => p.type === \"text\")\n messages.push({\n role,\n content: useStringContent ? text : parts,\n })\n } else if (item.type === \"function_call\") {\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: [\n {\n id: item.call_id,\n type: \"function\",\n function: { name: item.name, arguments: item.arguments },\n },\n ],\n })\n } else if (item.type === \"function_call_output\") {\n messages.push({\n role: \"tool\",\n tool_call_id: item.call_id,\n content: item.output,\n })\n }\n }\n\n const tools: Array<ChatTool> | undefined = request.tools\n ?.filter((t) => {\n const name = t.function?.name ?? t.name\n return t.type === \"function\" && typeof name === \"string\" && name.length > 0\n })\n .map((t) => ({\n type: \"function\",\n function: {\n name: t.function?.name ?? t.name ?? \"\",\n description: t.function?.description ?? t.description,\n parameters: t.function?.parameters ?? t.parameters,\n },\n }))\n\n const payload: ChatRequestPayload = {\n model: capability.id,\n messages,\n stream: false, // always non-stream upstream; we synthesize SSE later\n max_tokens: request.max_output_tokens,\n temperature: request.temperature,\n top_p: request.top_p,\n user: request.user,\n tools: tools && tools.length > 0 ? tools : undefined,\n tool_choice:\n tools && tools.length > 0 ? request.tool_choice : undefined,\n }\n\n placeReasoning(payload, capability, request.reasoning?.effort)\n\n return payload\n}\n\n// ---------- Public: translate non-stream response ----------\n\ninterface ResponsesApiResult {\n id: string\n object: \"response\"\n status: \"completed\" | \"incomplete\"\n created_at: number\n model: string\n output: Array<\n | {\n id: string\n type: \"message\"\n role: \"assistant\"\n status: \"completed\"\n content: Array<{ type: \"output_text\"; text: string; annotations: [] }>\n }\n | {\n id: string\n type: \"function_call\"\n status: \"completed\"\n call_id: string\n name: string\n arguments: string\n }\n >\n usage?: {\n input_tokens: number\n output_tokens: number\n total_tokens: number\n }\n}\n\nconst buildResponsesResult = (\n request: ResponsesRequestLike,\n chat: ChatCompletionResponse,\n): ResponsesApiResult => {\n const choice = chat.choices[0]\n const message = choice?.message\n const text =\n typeof message?.content === \"string\" ?\n message.content\n : Array.isArray(message?.content) ?\n message.content\n .filter((p): p is ChatContentPart => p.type === \"text\")\n .map((p) => p.text ?? \"\")\n .join(\"\")\n : \"\"\n\n const output: ResponsesApiResult[\"output\"] = []\n if (text.length > 0) {\n output.push({\n id: `msg_${randomUUID()}`,\n type: \"message\",\n role: \"assistant\",\n status: \"completed\",\n content: [{ type: \"output_text\", text, annotations: [] }],\n })\n }\n for (const tc of message?.tool_calls ?? []) {\n output.push({\n id: `fc_${randomUUID()}`,\n type: \"function_call\",\n status: \"completed\",\n call_id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n })\n }\n\n return {\n id: chat.id ?? `resp_${randomUUID()}`,\n object: \"response\",\n status: \"completed\",\n created_at: chat.created ?? Math.floor(Date.now() / 1000),\n model: chat.model ?? request.model,\n output,\n usage:\n chat.usage ?\n {\n input_tokens: chat.usage.prompt_tokens ?? 0,\n output_tokens: chat.usage.completion_tokens ?? 0,\n total_tokens: chat.usage.total_tokens ?? 0,\n }\n : undefined,\n }\n}\n\nexport const chatResponseToResponsesJson = buildResponsesResult\n\n// ---------- Public: synthesize SSE stream ----------\n\nconst sse = (event: string, data: unknown) =>\n `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`\n\nexport const synthesizeResponsesSseFromChat = (\n request: ResponsesRequestLike,\n chat: ChatCompletionResponse,\n): ReadableStream<Uint8Array> => {\n const result = buildResponsesResult(request, chat)\n const encoder = new TextEncoder()\n const baseResponse = {\n id: result.id,\n object: \"response\",\n created_at: result.created_at,\n model: result.model,\n status: \"in_progress\",\n output: [] as unknown[],\n }\n\n return new ReadableStream<Uint8Array>({\n start(controller) {\n const push = (event: string, data: unknown) =>\n controller.enqueue(encoder.encode(sse(event, data)))\n\n push(\"response.created\", { type: \"response.created\", response: baseResponse })\n push(\"response.in_progress\", {\n type: \"response.in_progress\",\n response: baseResponse,\n })\n\n result.output.forEach((item, index) => {\n push(\"response.output_item.added\", {\n type: \"response.output_item.added\",\n output_index: index,\n item,\n })\n\n if (item.type === \"message\") {\n const text = item.content[0]?.text ?? \"\"\n const part = { type: \"output_text\", text: \"\", annotations: [] }\n push(\"response.content_part.added\", {\n type: \"response.content_part.added\",\n item_id: item.id,\n output_index: index,\n content_index: 0,\n part,\n })\n if (text) {\n push(\"response.output_text.delta\", {\n type: \"response.output_text.delta\",\n item_id: item.id,\n output_index: index,\n content_index: 0,\n delta: text,\n })\n }\n push(\"response.output_text.done\", {\n type: \"response.output_text.done\",\n item_id: item.id,\n output_index: index,\n content_index: 0,\n text,\n })\n push(\"response.content_part.done\", {\n type: \"response.content_part.done\",\n item_id: item.id,\n output_index: index,\n content_index: 0,\n part: { ...part, text },\n })\n } else if (item.type === \"function_call\") {\n if (item.arguments) {\n push(\"response.function_call_arguments.delta\", {\n type: \"response.function_call_arguments.delta\",\n item_id: item.id,\n output_index: index,\n delta: item.arguments,\n })\n }\n push(\"response.function_call_arguments.done\", {\n type: \"response.function_call_arguments.done\",\n item_id: item.id,\n output_index: index,\n arguments: item.arguments,\n })\n }\n\n push(\"response.output_item.done\", {\n type: \"response.output_item.done\",\n output_index: index,\n item,\n })\n })\n\n push(\"response.completed\", {\n type: \"response.completed\",\n response: { ...result, status: \"completed\" },\n })\n controller.close()\n },\n })\n}\n","interface ResponseMetadata {\n created_at?: number\n id?: string\n model?: string\n}\n\ninterface ResponsesStreamEvent {\n response?: ResponseMetadata\n type?: string\n [key: string]: unknown\n}\n\ninterface StableResponseMetadata {\n created_at: number\n id: string\n initialized: boolean\n model: string\n}\n\nconst normalizeEventPayload = (\n rawData: string,\n stableResponse: StableResponseMetadata,\n): string => {\n let event: ResponsesStreamEvent\n try {\n event = JSON.parse(rawData) as ResponsesStreamEvent\n } catch {\n return rawData\n }\n\n if (event.response && typeof event.response === \"object\") {\n const incoming = event.response\n if (!stableResponse.initialized) {\n if (incoming.id) stableResponse.id = incoming.id\n if (typeof incoming.created_at === \"number\")\n stableResponse.created_at = incoming.created_at\n if (incoming.model) stableResponse.model = incoming.model\n stableResponse.initialized = true\n }\n\n event.response = {\n ...incoming,\n ...(stableResponse.id ? { id: stableResponse.id } : {}),\n ...(stableResponse.created_at\n ? { created_at: stableResponse.created_at }\n : {}),\n ...(stableResponse.model ? { model: stableResponse.model } : {}),\n }\n }\n\n return JSON.stringify(event)\n}\n\nconst transformSseChunk = (\n chunk: string,\n stableResponse: StableResponseMetadata,\n): string => {\n const lines = chunk.split(\"\\n\")\n\n return lines\n .map((line) => {\n if (!line.startsWith(\"data: \")) {\n return line\n }\n\n const rawData = line.slice(6)\n if (!rawData || rawData === \"[DONE]\") {\n return line\n }\n\n return `data: ${normalizeEventPayload(rawData, stableResponse)}`\n })\n .join(\"\\n\")\n}\n\nexport const normalizeResponsesSseStream = (\n upstreamBody: ReadableStream<Uint8Array>,\n) => {\n const stableResponse: StableResponseMetadata = {\n created_at: 0,\n id: \"\",\n initialized: false,\n model: \"\",\n }\n\n const decoder = new TextDecoder()\n const encoder = new TextEncoder()\n let buffer = \"\"\n\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const reader = upstreamBody.getReader()\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n\n if (done) {\n break\n }\n\n buffer += decoder.decode(value, { stream: true })\n\n let separatorIndex = buffer.indexOf(\"\\n\\n\")\n\n while (separatorIndex !== -1) {\n const rawEvent = buffer.slice(0, separatorIndex)\n buffer = buffer.slice(separatorIndex + 2)\n\n const transformed = transformSseChunk(rawEvent, stableResponse)\n controller.enqueue(encoder.encode(`${transformed}\\n\\n`))\n\n separatorIndex = buffer.indexOf(\"\\n\\n\")\n }\n }\n\n if (buffer.length > 0) {\n const transformed = transformSseChunk(buffer, stableResponse)\n controller.enqueue(encoder.encode(transformed))\n }\n } finally {\n reader.releaseLock()\n }\n\n controller.close()\n },\n })\n}\n","import { z } from \"zod\"\n\nimport {\n clampReasoningEffort,\n getModelCapability,\n resolveModelId,\n} from \"~/lib/model-capabilities\"\n\nconst codexResponsesRequestSchema = z\n .object({\n model: z.string().min(1),\n stream: z.boolean().optional(),\n })\n .passthrough()\n\nexport type CodexResponsesRequest = z.infer<typeof codexResponsesRequestSchema>\n\ninterface ReasoningField {\n effort?: unknown\n [key: string]: unknown\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n\nexport const normalizeCodexResponsesRequest = (\n payload: CodexResponsesRequest,\n): CodexResponsesRequest => {\n const parsed = codexResponsesRequestSchema.parse(payload) as CodexResponsesRequest\n & { reasoning?: ReasoningField }\n\n const canonical = resolveModelId(parsed.model)\n const capability = getModelCapability(canonical)\n if (!capability) return parsed\n\n const next = { ...parsed, model: canonical } as typeof parsed\n\n if (!capability.reasoning) {\n if (\"reasoning\" in next) {\n delete (next as Record<string, unknown>).reasoning\n }\n return next\n }\n\n const incoming: ReasoningField | undefined =\n isPlainObject(next.reasoning) ? (next.reasoning as ReasoningField) : undefined\n const clamped = clampReasoningEffort(canonical, incoming?.effort)\n if (clamped) {\n next.reasoning = { ...(incoming ?? {}), effort: clamped.effort }\n }\n\n return next\n}\n","import { Hono } from \"hono\"\n\nimport {\n chatResponseToResponsesJson,\n responsesPayloadToChatPayload,\n synthesizeResponsesSseFromChat,\n type ResponsesRequestLike,\n} from \"~/bridges/codex/chat-fallback\"\nimport { normalizeResponsesSseStream } from \"~/bridges/codex/normalize-stream\"\nimport { normalizeCodexResponsesRequest } from \"~/bridges/codex/responses\"\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { BridgeNotImplementedError } from \"~/lib/error\"\nimport { getModelCapability } from \"~/lib/model-capabilities\"\nimport { checkRateLimit, RateLimitError } from \"~/lib/rate-limit\"\nimport {\n fetchCopilot,\n getCopilotProviderContext,\n} from \"~/providers/copilot/client\"\n\nexport const responsesRoutes = new Hono<BridgeEnv>()\n\nresponsesRoutes.post(\"/\", async (c) => {\n try {\n await checkRateLimit()\n } catch (error) {\n if (error instanceof RateLimitError) {\n return c.json({ error: { message: error.message } }, 429)\n }\n throw error\n }\n const rawPayload = (await c.req.json()) as ResponsesRequestLike\n const payload = normalizeCodexResponsesRequest(\n rawPayload as unknown as Parameters<typeof normalizeCodexResponsesRequest>[0],\n ) as unknown as ResponsesRequestLike\n const config = c.get(\"config\")\n const provider = getCopilotProviderContext(config)\n const search = new URL(c.req.url).search\n\n const capability = getModelCapability(payload.model)\n\n try {\n if (capability?.fallback === \"chat-completions\") {\n const chatPayload = responsesPayloadToChatPayload(payload, capability)\n const upstream = await fetchCopilot(provider, `/chat/completions${search}`, {\n method: \"POST\",\n headers: { accept: \"application/json\", \"content-type\": \"application/json\" },\n body: JSON.stringify(chatPayload),\n })\n\n if (!upstream.ok) {\n const text = await upstream.text()\n return new Response(text, {\n status: upstream.status,\n headers: { \"content-type\": upstream.headers.get(\"content-type\") ?? \"application/json\" },\n })\n }\n\n const chatJson = (await upstream.json()) as Parameters<\n typeof chatResponseToResponsesJson\n >[1]\n\n if (payload.stream) {\n const stream = synthesizeResponsesSseFromChat(payload, chatJson)\n return new Response(stream, {\n status: 200,\n headers: {\n \"content-type\": \"text/event-stream; charset=utf-8\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n },\n })\n }\n\n const responsesJson = chatResponseToResponsesJson(payload, chatJson)\n return new Response(JSON.stringify(responsesJson), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n })\n }\n\n const upstream = await fetchCopilot(provider, `/responses${search}`, {\n method: \"POST\",\n headers: {\n accept: c.req.header(\"accept\") ?? \"application/json\",\n \"content-type\": c.req.header(\"content-type\") ?? \"application/json\",\n },\n body: JSON.stringify(payload),\n })\n\n const contentType = upstream.headers.get(\"content-type\") ?? \"\"\n\n if (payload.stream && upstream.body && contentType.includes(\"text/event-stream\")) {\n return new Response(normalizeResponsesSseStream(upstream.body), {\n status: upstream.status,\n headers: upstream.headers,\n })\n }\n\n return new Response(upstream.body, {\n status: upstream.status,\n headers: upstream.headers,\n })\n } catch (error) {\n if (error instanceof BridgeNotImplementedError) {\n return c.json(\n {\n error: {\n type: error.name,\n message: error.message,\n },\n },\n 501,\n )\n }\n\n throw error\n }\n})","import fs from \"node:fs/promises\"\n\nimport type { BridgeConfig } from \"~/lib/config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { PATHS } from \"~/lib/paths\"\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\nconst GITHUB_API_VERSION = \"2022-11-28\"\nconst GITHUB_API_BASE_URL = \"https://api.github.com\"\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\nexport interface 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: {\n chat: QuotaDetail\n completions: QuotaDetail\n premium_interactions: QuotaDetail\n }\n}\n\nconst readGitHubToken = async (): Promise<string> => {\n const token = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return token.trim()\n}\n\nexport const getCopilotUsage = async (\n config: BridgeConfig,\n): Promise<CopilotUsageResponse> => {\n const githubToken = await readGitHubToken()\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/user`,\n {\n headers: {\n accept: \"application/json\",\n authorization: `token ${githubToken}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"editor-version\": `vscode/${config.vsCodeVersion}`,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": GITHUB_API_VERSION,\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n },\n },\n )\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get Copilot usage\", response)\n }\n\n return (await response.json()) as CopilotUsageResponse\n}\n","import { Hono } from \"hono\"\n\nimport type { BridgeEnv } from \"~/lib/config\"\nimport { getCopilotUsage } from \"~/providers/github/get-copilot-usage\"\n\nexport const usageRoutes = new Hono<BridgeEnv>()\n\nusageRoutes.get(\"/\", async (c) => {\n // Allow the static usage viewer at https://betahi.github.io/copilot-bridge\n // (and local dev) to call this endpoint cross-origin.\n c.header(\"access-control-allow-origin\", \"*\")\n c.header(\"access-control-allow-methods\", \"GET, OPTIONS\")\n c.header(\"access-control-allow-headers\", \"*\")\n\n try {\n const usage = await getCopilotUsage(c.var.config)\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\nusageRoutes.options(\"/\", (c) => {\n c.header(\"access-control-allow-origin\", \"*\")\n c.header(\"access-control-allow-methods\", \"GET, OPTIONS\")\n c.header(\"access-control-allow-headers\", \"*\")\n return c.body(null, 204)\n})\n","import { serve } from \"@hono/node-server\"\nimport { Hono } from \"hono\"\nimport { cors } from \"hono/cors\"\nimport { logger } from \"hono/logger\"\n\nimport type { BridgeConfig, BridgeEnv } from \"~/lib/config\"\nimport { chatCompletionRoutes } from \"~/routes/chat-completions\"\nimport { embeddingRoutes } from \"~/routes/embeddings\"\nimport { messageRoutes } from \"~/routes/messages\"\nimport { modelRoutes } from \"~/routes/models\"\nimport { responsesRoutes } from \"~/routes/responses\"\nimport { usageRoutes } from \"~/routes/usage\"\n\nexport const createServer = (config: BridgeConfig) => {\n const app = new Hono<BridgeEnv>()\n\n app.use(logger())\n app.use(\"*\", cors())\n app.use(\"*\", async (c, next) => {\n c.set(\"config\", config)\n await next()\n })\n\n app.get(\"/\", (c) =>\n c.json({\n name: \"copilot-bridge\",\n status: \"ok\",\n }),\n )\n\n app.get(\"/healthz\", (c) => c.json({ ok: true }))\n app.route(\"/v1/models\", modelRoutes)\n app.route(\"/v1/responses\", responsesRoutes)\n app.route(\"/v1/messages\", messageRoutes)\n app.route(\"/v1/chat/completions\", chatCompletionRoutes)\n app.route(\"/v1/embeddings\", embeddingRoutes)\n app.route(\"/usage\", usageRoutes)\n\n return app\n}\n\nexport const startServer = (config: BridgeConfig) =>\n serve({\n fetch: createServer(config).fetch,\n hostname: config.host,\n port: config.port,\n })\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { setupBridgeAuth } from \"~/lib/auth\"\nimport {\n applyClaudeConfig,\n parsePortFromBaseUrl,\n readClaudeBaseUrl,\n} from \"~/lib/claude-settings\"\nimport {\n applyCodexConfig,\n readCodexUserConfigFromDisk,\n} from \"~/lib/codex-config\"\nimport { readBridgeConfig } from \"~/lib/config\"\nimport {\n CLAUDE_CONFIG_PATH,\n CODEX_DEFAULTS,\n DEFAULT_HOST,\n DEFAULT_PORT,\n} from \"~/lib/defaults\"\nimport {\n getModelCapability,\n MODEL_CAPABILITIES,\n} from \"~/lib/model-capabilities\"\nimport { runtimeState } from \"~/lib/state\"\nimport {\n fetchCopilot,\n getCopilotProviderContext,\n} from \"~/providers/copilot/client\"\nimport { startServer } from \"~/server\"\n\ninterface CopilotModel {\n id: string\n}\n\ninterface CopilotModelsResponse {\n data?: Array<CopilotModel>\n}\n\nconst fetchAvailableModels = async (\n config: ReturnType<typeof readBridgeConfig>,\n): Promise<Array<string>> => {\n try {\n const provider = getCopilotProviderContext(config)\n const response = await fetchCopilot(provider, \"/models\", {\n method: \"GET\",\n headers: { accept: \"application/json\" },\n })\n if (!response.ok) return []\n const payload = (await response.json()) as CopilotModelsResponse\n return (payload.data ?? []).map((m) => m.id).filter(Boolean)\n } catch {\n return []\n }\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the copilot-bridge HTTP server.\",\n },\n args: {\n host: {\n type: \"string\",\n description: `Host to bind (default: ${DEFAULT_HOST}).`,\n },\n port: {\n type: \"string\",\n description: `Port to listen on (default: ${DEFAULT_PORT}).`,\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Print GitHub and Copilot tokens during startup.\",\n },\n \"no-codex-setup\": {\n type: \"boolean\",\n default: false,\n description: \"Skip writing the bridge provider into ~/.codex/config.toml.\",\n },\n \"no-claude-setup\": {\n type: \"boolean\",\n default: false,\n description:\n \"Skip writing ANTHROPIC_BASE_URL into ~/.claude/settings.json.\",\n },\n \"select-model\": {\n type: \"boolean\",\n default: false,\n description:\n \"Force the model picker even when ~/.codex/config.toml already has a model.\",\n },\n \"no-prompt\": {\n type: \"boolean\",\n default: false,\n description:\n \"Never prompt; use the existing model from ~/.codex/config.toml as-is.\",\n },\n \"rate-limit\": {\n type: \"string\",\n description:\n \"Minimum seconds between upstream requests (anti-abuse throttle).\",\n },\n wait: {\n type: \"boolean\",\n default: false,\n description:\n \"When --rate-limit is set, wait instead of returning HTTP 429.\",\n },\n },\n async run({ args }) {\n // Port resolution priority (high → low):\n // 1. --port CLI flag\n // 2. $PORT environment variable\n // 3. ANTHROPIC_BASE_URL port in ~/.claude/settings.json\n // 4. DEFAULT_PORT\n // Once resolved, the chosen port is written back to BOTH claude\n // settings and codex config so the three sources stay in lockstep.\n const claudeConfigPath = CLAUDE_CONFIG_PATH\n const claudePort = parsePortFromBaseUrl(\n await readClaudeBaseUrl(claudeConfigPath),\n )\n const envPortRaw = process.env.PORT\n const envPort =\n envPortRaw && Number.isFinite(Number(envPortRaw)) ?\n Number(envPortRaw)\n : undefined\n\n const host = args.host ? String(args.host) : DEFAULT_HOST\n const port =\n args.port ? Number(args.port)\n : envPort !== undefined ? envPort\n : claudePort !== undefined ? claudePort\n : DEFAULT_PORT\n\n const config = readBridgeConfig({ host, port })\n\n const rateLimitRaw = args[\"rate-limit\"]\n if (rateLimitRaw !== undefined) {\n const parsed = Number.parseInt(String(rateLimitRaw), 10)\n if (!Number.isFinite(parsed) || parsed <= 0) {\n consola.error(`Invalid --rate-limit value: ${rateLimitRaw}`)\n process.exit(1)\n }\n runtimeState.rateLimitSeconds = parsed\n runtimeState.rateLimitWait = Boolean(args.wait)\n consola.info(\n `Rate limit: ${parsed}s between requests (${runtimeState.rateLimitWait ? \"wait\" : \"reject\"} on overflow)`,\n )\n }\n\n await setupBridgeAuth(config, {\n showToken: args[\"show-token\"],\n })\n\n const server = startServer(config)\n\n consola.success(\n `copilot-bridge listening on http://${config.host}:${config.port}`,\n )\n consola.info(`copilot base url: ${config.copilotBaseUrl}`)\n\n const baseUrl = `http://${config.host}:${config.port}`\n const codexConfigPath = CODEX_DEFAULTS.configPath\n\n // Sync Claude Code's settings.json and Codex's config.toml *before* any\n // potentially blocking interactive prompt. This guarantees `claude` and\n // `codex` work the moment the server is listening — even if the user\n // never answers the model picker below.\n if (!args[\"no-claude-setup\"]) {\n try {\n const claudeResult = await applyClaudeConfig({\n baseUrl,\n configPath: claudeConfigPath,\n })\n if (claudeResult.changed) {\n consola.success(\n `claude settings ${claudeResult.created ? \"created\" : \"updated\"}: ${claudeResult.configPath}`,\n )\n if (\n claudeResult.previousBaseUrl\n && claudeResult.previousBaseUrl !== baseUrl\n ) {\n consola.info(\n `ANTHROPIC_BASE_URL: ${claudeResult.previousBaseUrl} → ${baseUrl}`,\n )\n }\n } else {\n consola.info(\n `claude settings already up to date: ${claudeResult.configPath}`,\n )\n }\n } catch (error) {\n consola.warn(\n `Could not update claude settings (${claudeConfigPath}):`,\n error,\n )\n }\n }\n\n // Read the user's current codex model so the picker can default to it,\n // and so we can stamp the managed block immediately even if the picker\n // is skipped or interrupted.\n const codexUserConfig = await readCodexUserConfigFromDisk(codexConfigPath)\n let chosenModel: string | undefined = codexUserConfig.model\n let chosenEffort: string | undefined =\n codexUserConfig.modelReasoningEffort\n\n if (chosenModel && !chosenEffort) {\n consola.info(\n `codex model_reasoning_effort not set; using ${chosenModel}'s default reasoning effort`,\n )\n }\n\n if (!args[\"no-codex-setup\"]) {\n try {\n const result = await applyCodexConfig({\n baseUrl: `${baseUrl}/v1`,\n configPath: codexConfigPath,\n settings: CODEX_DEFAULTS,\n model: chosenModel,\n modelReasoningEffort: chosenEffort,\n })\n if (result.changed) {\n consola.success(\n `codex config ${result.created ? \"created\" : \"updated\"}: ${result.configPath}`,\n )\n if (CODEX_DEFAULTS.setAsDefault) {\n consola.info(\n `codex now defaults to provider \"${CODEX_DEFAULTS.providerId}\". Run \\`codex exec \"...\"\\` directly.`,\n )\n } else {\n consola.info(\n `provider \"${CODEX_DEFAULTS.providerId}\" registered. Use \\`codex -c model_provider=\"${CODEX_DEFAULTS.providerId}\" ...\\``,\n )\n }\n } else {\n consola.info(`codex config already up to date: ${result.configPath}`)\n }\n } catch (error) {\n consola.warn(\n `Could not update codex config (${codexConfigPath}):`,\n error,\n )\n }\n }\n\n const models = await fetchAvailableModels(config)\n const supportedIds = new Set(MODEL_CAPABILITIES.map((m) => m.id))\n const pickable =\n models.length > 0 ?\n models.filter((id) => supportedIds.has(id))\n : MODEL_CAPABILITIES.map((m) => m.id)\n const finalPickable =\n pickable.length > 0 ? pickable : MODEL_CAPABILITIES.map((m) => m.id)\n if (models.length > 0) {\n consola.info(\n `Available models:\\n${models\n .map((id) => `- ${id}${supportedIds.has(id) ? \" (bridge-supported)\" : \"\"}`)\n .join(\"\\n\")}`,\n )\n } else {\n consola.warn(\"Could not fetch model list from upstream Copilot API\")\n }\n\n consola.box(\n [\n `🌐 Usage viewer`,\n ``,\n ` https://betahi.github.io/copilot-bridge?endpoint=${baseUrl}/usage`,\n ].join(\"\\n\"),\n )\n\n const shouldPrompt =\n !args[\"no-prompt\"]\n && finalPickable.length > 0\n && (args[\"select-model\"] || !chosenModel)\n\n if (shouldPrompt) {\n const defaultId =\n chosenModel && finalPickable.includes(chosenModel) ? chosenModel\n : finalPickable.includes(\"gpt-5.3-codex\") ? \"gpt-5.3-codex\"\n : finalPickable[0]\n const selected = (await consola.prompt(\n `Select a model for codex (writes to ${codexConfigPath})`,\n {\n type: \"select\",\n options: finalPickable,\n initial: defaultId,\n },\n )) as string\n if (selected && selected !== chosenModel) {\n chosenModel = selected\n // If the previously stored effort is no longer supported by the\n // newly chosen model, drop it so codex falls back to its default.\n const cap = getModelCapability(selected)\n const supported = cap?.reasoning?.supported\n if (\n chosenEffort\n && supported\n && !supported.includes(chosenEffort as never)\n ) {\n chosenEffort = undefined\n }\n // Re-stamp codex config with the user's freshly picked model.\n if (!args[\"no-codex-setup\"]) {\n try {\n const result = await applyCodexConfig({\n baseUrl: `${baseUrl}/v1`,\n configPath: codexConfigPath,\n settings: CODEX_DEFAULTS,\n model: chosenModel,\n modelReasoningEffort: chosenEffort,\n })\n if (result.changed) {\n consola.success(`codex config updated: ${result.configPath}`)\n }\n } catch (error) {\n consola.warn(\n `Could not update codex config (${codexConfigPath}):`,\n error,\n )\n }\n }\n }\n }\n\n await new Promise<void>((resolve, reject) => {\n server.on(\"close\", resolve)\n server.on(\"error\", reject)\n })\n },\n})\n","#!/usr/bin/env node\n\nimport { defineCommand, runMain } from \"citty\"\n\nimport { auth } from \"./auth\"\nimport { start } from \"./start\"\n\nconst main = defineCommand({\n meta: {\n name: \"copilot-bridge\",\n description:\n \"Model-layer bridge for routing Codex CLI, Claude Code, and similar clients to GitHub Copilot.\",\n },\n subCommands: { auth, start },\n})\n\nawait runMain(main)\n"],"mappings":"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"}
|