@jeffreycao/copilot-api 1.14.9 → 1.14.10

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 CHANGED
@@ -162,7 +162,7 @@ To get started, run the `start` command with the `--claude-code` flag:
162
162
  npx @jeffreycao/copilot-api@latest start --claude-code
163
163
  ```
164
164
 
165
- You will be prompted to select a primary model and a "small, fast" model for background tasks. After selecting the models, a command will be copied to your clipboard. This command sets the necessary environment variables for Claude Code to use the gateway.
165
+ You will no longer be prompted to pick models manually. The gateway automatically detects the latest available model for each Claude Code size tier — opus maps to the newest Opus model, sonnet to the newest Sonnet model, and haiku to the newest Haiku model — and generates a command that sets `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, and `ANTHROPIC_DEFAULT_HAIKU_MODEL` accordingly. Any tier without a matching model available is omitted. The command is copied to your clipboard and sets the environment variables needed for Claude Code to use the gateway.
166
166
 
167
167
  Paste and run this command in a new terminal to launch Claude Code.
168
168
 
@@ -177,9 +177,12 @@ Here is an example `.claude/settings.json` file:
177
177
  "env": {
178
178
  "ANTHROPIC_BASE_URL": "http://localhost:4141",
179
179
  "ANTHROPIC_AUTH_TOKEN": "dummy",
180
- "ANTHROPIC_MODEL": "deepseek/deepseek-v4-pro",
181
- "ANTHROPIC_DEFAULT_SONNET_MODEL": "deepseek/deepseek-v4-pro",
182
- "ANTHROPIC_DEFAULT_HAIKU_MODEL": "deepseek/deepseek-v4-flash",
180
+ "ANTHROPIC_MODEL": "gpt-5.6-sol[1m]",
181
+ "ANTHROPIC_DEFAULT_SONNET_MODEL": "gpt-5.6-sol[1m]",
182
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL": "gpt-5.6-luna[1m]",
183
+ "CLAUDE_CODE_AUTO_COMPACT_WINDOW": "272000",
184
+ "CLAUDE_CODE_USE_VERTEX": "0",
185
+ "CLAUDE_CODE_USE_BEDROCK": "0",
183
186
  "DISABLE_NON_ESSENTIAL_MODEL_CALLS": "1",
184
187
  "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
185
188
  "CLAUDE_CODE_ATTRIBUTION_HEADER": "0",
@@ -187,15 +190,21 @@ Here is an example `.claude/settings.json` file:
187
190
  "CLAUDE_CODE_DISABLE_TERMINAL_TITLE": "true",
188
191
  "CLAUDE_CODE_ENABLE_AWAY_SUMMARY": "0"
189
192
  },
190
- "permissions": {
191
- "deny": [
192
- "mcp__ide__executeCode"
193
- ]
194
- }
193
+ "alwaysThinkingEnabled": true,
194
+ "effortLevel": "xhigh",
195
+ "showThinkingSummaries": true
195
196
  }
196
197
  ```
197
198
 
198
199
  - Replace `ANTHROPIC_MODEL`, `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, and `ANTHROPIC_DEFAULT_HAIKU_MODEL` according to your needs. After configuration, please install the claude code plugin [Plugin Integrations](#plugin-integrations).
200
+ - If you are using the codex provider, it is recommended **not** to configure the model name in the `codex/xxx` format (e.g. `codex/gpt-5.6-sol`). Claude Code treats the `codex/` prefix as a special pattern and applies degraded behavior — for example, it strips all previously returned thinking blocks on every request. Use the plain model name (e.g. `gpt-5.6-sol`) instead, and add a `modelMappings` entry in `config.json` to route it back to the codex provider:
201
+ ```json
202
+ "modelMappings": {
203
+ "gpt-5.6-sol": "codex/gpt-5.6-sol",
204
+ "gpt-5.6-terra": "codex/gpt-5.6-terra",
205
+ "gpt-5.6-luna": "codex/gpt-5.6-luna"
206
+ },
207
+ ```
199
208
  - Setting CLAUDE_CODE_ATTRIBUTION_HEADER to 0 can prevent Claude code from adding billing and version information in system prompts, thereby avoiding prompt cache invalidation.
200
209
  - Turning off CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION and CLAUDE_CODE_ENABLE_AWAY_SUMMARY can prevent quota from being consumed unnecessarily.
201
210
  - Claude Code WebSearch is supported for pure search requests. For Copilot, keep the global `messageApiWebSearchModel` set to a Responses-capable GPT model or a `provider/model` alias. For provider routes, use a native Anthropic provider or an `openai-responses` provider. Add `WebSearch` to `permissions.deny` only if you want to forbid this traffic.
@@ -310,7 +319,8 @@ enabled = false
310
319
  ```
311
320
 
312
321
  > [!NOTE]
313
- > This configuration is specific to Codex and the GitHub Copilot provider. `name` must be set to `"OpenAI"`. It can help mitigate Codex local compact cache miss issues.
322
+ > This configuration is specific to Codex and the GitHub Copilot provider. `name` must be set to `"OpenAI"`. It can help mitigate Codex local compact cache miss issues.
323
+ > If you are using the codex provider, it is recommended to set `base_url` to `"http://localhost:4141/codex"`.
314
324
 
315
325
  ## GPT Tool Search
316
326
 
@@ -610,7 +620,7 @@ Use `copilot-api auth login --provider custom` to add or update another third-pa
610
620
  }
611
621
  }
612
622
  ```
613
- Built-in token prices cover Codex GPT models in USD, DashScope `qwen3.7-max`, `qwen3.7-plus`, `glm-5.1`, `glm-5.2` in CNY, DeepSeek `deepseek-v4-flash`, `deepseek-v4-pro`, `deepseek-chat`, `deepseek-reasoner` in CNY, and OpenCode Go models (`glm-5.2`, `deepseek-v4-flash`, `deepseek-v4-pro`, `kimi-k2.7-code`, `mimo-v2.5`, `mimo-v2.5-pro`, `qwen3.7-plus`, `qwen3.7-max`, `minimax-m2.5`, `minimax-m3`) in USD. User `pricing` entries override built-ins. For DashScope, cached tokens are charged as explicit cache reads when the upstream usage includes `cache_creation_input_tokens`; otherwise `cachedInput` is used as the implicit cache read price. For DeepSeek, `prompt_cache_hit_tokens` map to cached input and `prompt_cache_miss_tokens` map to regular input.
623
+ Built-in token prices cover Codex GPT models in USD, DashScope `qwen3.7-max`, `qwen3.7-plus`, `glm-5.1`, `glm-5.2` in CNY, DeepSeek `deepseek-v4-flash`, `deepseek-v4-pro`, `deepseek-chat`, `deepseek-reasoner` in CNY, and OpenCode Go models (`glm-5.2`, `grok-4.5`, `deepseek-v4-flash`, `deepseek-v4-pro`, `kimi-k2.7-code`, `kimi-k3`, `mimo-v2.5`, `mimo-v2.5-pro`, `qwen3.7-plus`, `qwen3.7-max`, `minimax-m2.5`, `minimax-m3`) in USD. User `pricing` entries override built-ins. For DashScope, cached tokens are charged as explicit cache reads when the upstream usage includes `cache_creation_input_tokens`; otherwise `cachedInput` is used as the implicit cache read price. For DeepSeek, `prompt_cache_hit_tokens` map to cached input and `prompt_cache_miss_tokens` map to regular input.
614
624
  - **smallModel:** Fallback model used for tool-less warmup messages (e.g., Claude Code probe requests); defaults to gpt-5-mini.
615
625
  - **contextManagement:** Controls whether the proxy adds Responses API `context_management` compaction instructions. `messages` applies when Anthropic-style `/v1/messages` requests are translated to Responses API, including `openai-responses` provider message routes, and defaults to `true`. `responses` applies to native `/v1/responses` traffic, including `provider/model` aliases and the built-in `codex` provider, and defaults to `false`. Enable `responses` only after checking that your client supports context management compaction. When enabled, the request includes `context_management` in the body and keeps only the latest compaction carrier on follow-up turns. **Note:** Context management is forcibly disabled for GPT-5.6 and above models (e.g. `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`) because enabling it breaks prompt cache hits on those models. This override takes precedence over the `contextManagement` and `modelResponsesApiCompactThresholds` settings.
616
626
  - **modelResponsesApiCompactThresholds:** Per-model Responses API `compact_threshold` overrides used when the proxy adds `context_management`. These values take precedence over the fallback threshold from `resolveResponsesCompactThreshold` (`max_prompt_tokens * ratio`, or the default fallback). Defaults set `gpt-5.4` and `gpt-5.5` to `217600` (`272000 * 0.8`), and `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna` to `231200` (`272000 * 0.85`). Models not listed continue to use the normal fallback logic.
@@ -619,7 +629,7 @@ Use `copilot-api auth login --provider custom` to add or update another third-pa
619
629
  - **Forwarding:** the resolved value remains `output_config.effort` for the Copilot native Messages API and becomes `reasoning.effort` when translated to the Responses API.
620
630
  - **Configuration values:** `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`.
621
631
  - **useMessagesApi:** When `true`, Claude-family models that support Copilot's native `/v1/messages` endpoint will use the Messages API; otherwise they fall back to `/chat/completions`. Set to `false` to disable Messages API routing and always use `/chat/completions`. Defaults to `true`.
622
- - **useResponsesApiWebSocket:** When `true`, Responses API requests use Copilot's websocket transport for models that advertise `ws:/responses`; models that only advertise `/responses` continue to use HTTP. Set to `false` to disable websocket routing and use HTTP `/responses` whenever the selected model supports it. Defaults to `true`.
632
+ - **useResponsesApiWebSocket:** When `true`, Responses API requests use Copilot's websocket transport for models that advertise `ws:/responses`; models that only advertise `/responses` continue to use HTTP. Set to `false` to disable websocket routing and use HTTP `/responses` whenever the selected model supports it. Defaults to `true`. If the Responses API WebSocket gets closed, it is usually caused by your own network. If you are using a VPN, try switching to a different node.
623
633
  - **useResponsesApiWebSearch:** When `true`, the server keeps Responses API tools with `type: "web_search"` and forwards them upstream. Set to `false` to strip those tools from `/responses` payloads. Defaults to `true`.
624
634
  - **messageApiWebSearchModel:** Global fallback model used when a top-level Copilot `/v1/messages` request contains only the server-side `web_search` tool. Defaults to `gpt-5-mini`. If the value is a `provider/model` alias, the request is routed into that provider's Messages API path with the provider prefix stripped. For Copilot GPT models, web search runs through `/responses`. Mixed `web_search` plus custom tools are not supported and the server-side `web_search` tool is stripped.
625
635
  - **claudeTokenMultiplier:** Multiplier applied to the fallback GPT-tokenizer estimate for Claude `/v1/messages/count_tokens` requests. Defaults to `1.15`. Increase it if your client is still compacting too late. This setting is only used when the proxy is estimating Claude tokens locally; if `anthropicApiKey` is configured and Anthropic token counting succeeds, the exact Anthropic count is returned instead.
package/README.zh-CN.md CHANGED
@@ -162,7 +162,7 @@ https://github.com/caozhiyuan/copilot-api/releases
162
162
  npx @jeffreycao/copilot-api@latest start --claude-code
163
163
  ```
164
164
 
165
- 你会被提示选择一个主模型,以及一个用于后台任务的 "small, fast" 模型。选择完成后,会有一条命令被复制到剪贴板中。该命令会设置 Claude Code 使用这个 AI gateway 所需的环境变量。
165
+ 你不再需要手动选择模型。Gateway 会自动检测每个 Claude Code 尺寸档位对应的最新可用模型——opus 映射到最新的 Opus 模型,sonnet 映射到最新的 Sonnet 模型,haiku 映射到最新的 Haiku 模型——并生成相应设置 `ANTHROPIC_DEFAULT_OPUS_MODEL`、`ANTHROPIC_DEFAULT_SONNET_MODEL` 和 `ANTHROPIC_DEFAULT_HAIKU_MODEL` 的命令。若某个档位没有匹配的可用模型,则会被省略。该命令会被复制到剪贴板,并设置 Claude Code 使用这个 AI gateway 所需的环境变量。
166
166
 
167
167
  在新的终端中粘贴并执行这条命令,即可启动 Claude Code。
168
168
 
@@ -179,9 +179,12 @@ npx @jeffreycao/copilot-api@latest start --claude-code
179
179
  "env": {
180
180
  "ANTHROPIC_BASE_URL": "http://localhost:4141",
181
181
  "ANTHROPIC_AUTH_TOKEN": "dummy",
182
- "ANTHROPIC_MODEL": "deepseek/deepseek-v4-pro",
183
- "ANTHROPIC_DEFAULT_SONNET_MODEL": "deepseek/deepseek-v4-pro",
184
- "ANTHROPIC_DEFAULT_HAIKU_MODEL": "deepseek/deepseek-v4-flash",
182
+ "ANTHROPIC_MODEL": "gpt-5.6-sol[1m]",
183
+ "ANTHROPIC_DEFAULT_SONNET_MODEL": "gpt-5.6-sol[1m]",
184
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL": "gpt-5.6-luna[1m]",
185
+ "CLAUDE_CODE_AUTO_COMPACT_WINDOW": "272000",
186
+ "CLAUDE_CODE_USE_VERTEX": "0",
187
+ "CLAUDE_CODE_USE_BEDROCK": "0",
185
188
  "DISABLE_NON_ESSENTIAL_MODEL_CALLS": "1",
186
189
  "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
187
190
  "CLAUDE_CODE_ATTRIBUTION_HEADER": "0",
@@ -189,15 +192,21 @@ npx @jeffreycao/copilot-api@latest start --claude-code
189
192
  "CLAUDE_CODE_DISABLE_TERMINAL_TITLE": "true",
190
193
  "CLAUDE_CODE_ENABLE_AWAY_SUMMARY": "0"
191
194
  },
192
- "permissions": {
193
- "deny": [
194
- "mcp__ide__executeCode"
195
- ]
196
- }
195
+ "alwaysThinkingEnabled": true,
196
+ "effortLevel": "xhigh",
197
+ "showThinkingSummaries": true
197
198
  }
198
199
  ```
199
200
 
200
201
  - 请根据需要替换 `ANTHROPIC_MODEL`、`ANTHROPIC_DEFAULT_OPUS_MODEL`、`ANTHROPIC_DEFAULT_SONNET_MODEL` 和 `ANTHROPIC_DEFAULT_HAIKU_MODEL`。配置完成后,请安装 claude code 插件,见 [插件集成](#plugin-integrations)。
202
+ - 如果你使用的是 codex provider,建议**不要**将模型名配置成 `codex/xxx` 格式(如 `codex/gpt-5.6-sol`)。Claude Code 会针对 `codex/` 前缀做降智行为——例如每次请求时移除所有之前返回的思考块(thinking blocks)。请使用纯模型名(如 `gpt-5.6-sol`),并在 `config.json` 中配置 `modelMappings` 将其映射回 codex provider:
203
+ ```json
204
+ "modelMappings": {
205
+ "gpt-5.6-sol": "codex/gpt-5.6-sol",
206
+ "gpt-5.6-terra": "codex/gpt-5.6-terra",
207
+ "gpt-5.6-luna": "codex/gpt-5.6-luna"
208
+ },
209
+ ```
201
210
  - 将 `CLAUDE_CODE_ATTRIBUTION_HEADER` 设为 `0` 可以阻止 Claude Code 在 system prompt 中附加计费和版本信息,从而避免 prompt cache 失效。
202
211
  - 关闭 `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION` 和 `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` 可以避免不必要地消耗额度。
203
212
  - Claude Code WebSearch 已支持纯搜索请求。Copilot 路径请保持全局 `messageApiWebSearchModel` 指向 Responses-capable GPT 模型或 `provider/model` 别名;provider 路由请使用原生 Anthropic provider 或 `openai-responses` provider。只有在你明确想禁止这类流量时,才需要把 `WebSearch` 加到 `permissions.deny`。
@@ -313,6 +322,7 @@ enabled = false
313
322
 
314
323
  > [!NOTE]
315
324
  > 此配置仅限于 Codex 与 GitHub Copilot provider。`name` 一定要配置为 `"OpenAI"`。它可以缓解 Codex local compact 不命中缓存的问题。
325
+ > 如果使用 codex provider,建议将 `base_url` 配置为 `"http://localhost:4141/codex"`。
316
326
 
317
327
  ## GPT Tool Search
318
328
 
@@ -616,7 +626,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
616
626
  }
617
627
  }
618
628
  ```
619
- 内置 token 价格覆盖 Codex GPT 模型(USD)、DashScope `qwen3.7-max`、`qwen3.7-plus`、`glm-5.1`、`glm-5.2`(CNY),DeepSeek `deepseek-v4-flash`、`deepseek-v4-pro`、`deepseek-chat`、`deepseek-reasoner`(CNY),以及 OpenCode Go 模型(`glm-5.2`、`deepseek-v4-flash`、`deepseek-v4-pro`、`kimi-k2.7-code`、`mimo-v2.5`、`mimo-v2.5-pro`、`qwen3.7-plus`、`qwen3.7-max`、`minimax-m2.5`、`minimax-m3`,USD)。用户配置的 `pricing` 优先于内置价格。DashScope 若上游 usage 中出现 `cache_creation_input_tokens` 字段,cached tokens 按显式缓存读价计费;否则 `cachedInput` 作为隐式缓存读价。DeepSeek 的 `prompt_cache_hit_tokens` 会归入 cached input,`prompt_cache_miss_tokens` 会归入普通 input。
629
+ 内置 token 价格覆盖 Codex GPT 模型(USD)、DashScope `qwen3.7-max`、`qwen3.7-plus`、`glm-5.1`、`glm-5.2`(CNY),DeepSeek `deepseek-v4-flash`、`deepseek-v4-pro`、`deepseek-chat`、`deepseek-reasoner`(CNY),以及 OpenCode Go 模型(`glm-5.2`、`grok-4.5`、`deepseek-v4-flash`、`deepseek-v4-pro`、`kimi-k2.7-code`、`kimi-k3`、`mimo-v2.5`、`mimo-v2.5-pro`、`qwen3.7-plus`、`qwen3.7-max`、`minimax-m2.5`、`minimax-m3`,USD)。用户配置的 `pricing` 优先于内置价格。DashScope 若上游 usage 中出现 `cache_creation_input_tokens` 字段,cached tokens 按显式缓存读价计费;否则 `cachedInput` 作为隐式缓存读价。DeepSeek 的 `prompt_cache_hit_tokens` 会归入 cached input,`prompt_cache_miss_tokens` 会归入普通 input。
620
630
  - **smallModel:** 无工具预热消息的回退模型(例如 Claude Code 的探测请求);默认是 `gpt-5-mini`。
621
631
  - **contextManagement:** 控制代理是否为 Responses API 附加 `context_management` 压缩指令。`messages` 作用于被翻译成 Responses API 的 Anthropic 风格 `/v1/messages` 请求,包括 `openai-responses` provider 的 Messages 路由,默认值为 `true`。`responses` 作用于 native `/v1/responses` 流量,包括 `provider/model` 别名和内置 `codex` provider,默认值为 `false`。只有在确认客户端支持 context management compaction 后,才建议在 Responses API 下启用 `responses`。启用后,请求体会带上 `context_management`,并在后续轮次中仅保留最新的压缩承载内容。**注意:** 对于 GPT-5.6 及以上模型(如 `gpt-5.6-sol`、`gpt-5.6-terra`、`gpt-5.6-luna`),context management 功能会被强制禁用,因为开启后会破坏这些模型的 prompt 缓存命中。此强制覆盖优先于 `contextManagement` 和 `modelResponsesApiCompactThresholds` 配置。
622
632
  - **modelResponsesApiCompactThresholds:** 按模型覆盖 Responses API 的 `compact_threshold`,仅在代理自动附加 `context_management` 时使用。它的优先级高于 `resolveResponsesCompactThreshold` 基于 `max_prompt_tokens * ratio` 的兜底阈值。默认将 `gpt-5.4` 和 `gpt-5.5` 设为 `217600`(`272000 * 0.8`),将 `gpt-5.6-sol`、`gpt-5.6-terra`、`gpt-5.6-luna` 设为 `231200`(`272000 * 0.85`)。未列出的模型继续使用原有兜底逻辑。
@@ -625,7 +635,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
625
635
  - **转发字段:** 走 Copilot 原生 Messages API 时,最终值写入 `output_config.effort`;转换为 Responses API 时,最终值写入 `reasoning.effort`。
626
636
  - **配置可选值:** `none`、`minimal`、`low`、`medium`、`high`、`xhigh`、`max`。
627
637
  - **useMessagesApi:** 当为 `true` 时,支持 Copilot 原生 `/v1/messages` 的 Claude 系模型会走 Messages API;否则回退到 `/chat/completions`。设为 `false` 可禁用 Messages API 路由,始终使用 `/chat/completions`。默认值为 `true`。
628
- - **useResponsesApiWebSocket:** 当为 `true` 时,Responses API 请求会优先对声明了 `ws:/responses` 的模型使用 Copilot websocket transport;仅声明 `/responses` 的模型仍走 HTTP。设为 `false` 可禁用 websocket 路由,并在模型支持 `/responses` 时使用 HTTP `/responses`。默认值为 `true`。
638
+ - **useResponsesApiWebSocket:** 当为 `true` 时,Responses API 请求会优先对声明了 `ws:/responses` 的模型使用 Copilot websocket transport;仅声明 `/responses` 的模型仍走 HTTP。设为 `false` 可禁用 websocket 路由,并在模型支持 `/responses` 时使用 HTTP `/responses`。默认值为 `true`。如果遇到 Responses API WebSocket closed,一般是自己的网络问题。如果使用了 VPN,建议切换节点。
629
639
  - **useResponsesApiWebSearch:** 当为 `true` 时,服务端会保留 Responses API 中 `type: "web_search"` 的工具并透传到上游。设为 `false` 则会从 `/responses` payload 中移除这些工具。默认值为 `true`。
630
640
  - **messageApiWebSearchModel:** 顶层 Copilot `/v1/messages` 请求只包含服务端 `web_search` 工具时使用的全局模型,默认值为 `gpt-5-mini`。如果该值是 `provider/model` 别名,请求会进入对应 provider 的 Messages API 路径,并在转发前移除 provider 前缀。对于 Copilot GPT 模型,web search 会通过 `/responses` 执行。混合 `web_search` 与自定义工具的场景暂不支持,服务端会移除 server-side `web_search`。
631
641
  - **claudeTokenMultiplier:** 用于 Claude `/v1/messages/count_tokens` 请求在本地走 GPT tokenizer 估算时的乘数。默认值为 `1.15`。如果你的客户端仍然过晚触发上下文压缩,可以适当调大。这个配置只会在代理本地估算 Claude token 时生效;如果已经配置 `anthropicApiKey` 且 Anthropic token counting 调用成功,则会直接返回 Anthropic 的精确计数,不会使用这个乘数。
package/dist/main.js CHANGED
@@ -25,7 +25,7 @@ bindElectronFetch();
25
25
  const { auth } = await import("./auth-DvJ8r_tN.js");
26
26
  const { debug } = await import("./debug-Bb5hamXX.js");
27
27
  const { mcp } = await import("./mcp-BseuqgHR.js");
28
- const { start } = await import("./start-B0sr92AZ.js");
28
+ const { start } = await import("./start-BBonobw6.js");
29
29
  await runMain(defineCommand({
30
30
  meta: {
31
31
  name: "copilot-api",
@@ -0,0 +1,90 @@
1
+ import { z as state } from "./token-DHWoZfxf.js";
2
+ //#region src/lib/models.ts
3
+ /**
4
+ * Converts a Copilot upstream model ID to a client-friendly ID that Claude Code
5
+ * and Claude Desktop recognize (dots in version replaced with hyphens).
6
+ * e.g. "claude-sonnet-4.6" -> "claude-sonnet-4-6"
7
+ * Non-Claude models are returned unchanged.
8
+ */
9
+ const toClientModelId = (modelId) => {
10
+ const normalized = normalizeSdkModelId(modelId);
11
+ if (!normalized) return modelId;
12
+ const versionHyphenated = normalized.version.replaceAll(".", "-");
13
+ return `claude-${normalized.family}-${versionHyphenated}`;
14
+ };
15
+ const findEndpointModel = (sdkModelId) => {
16
+ const models = state.models?.data ?? [];
17
+ const exactMatch = models.find((m) => m.id === sdkModelId);
18
+ if (exactMatch) return exactMatch;
19
+ const normalized = normalizeSdkModelId(sdkModelId);
20
+ if (!normalized) return;
21
+ const modelName = `claude-${normalized.family}-${normalized.version}`;
22
+ const model = models.find((m) => m.id === modelName);
23
+ if (model) return model;
24
+ };
25
+ /**
26
+ * Finds the latest available model for a given Claude family (e.g. "opus",
27
+ * "sonnet", "haiku") among the models currently cached in `state.models`.
28
+ * "Latest" is determined by the highest semantic version parsed from the model
29
+ * ID. Returns `undefined` when no model of that family is available.
30
+ */
31
+ const getLatestModelForFamily = (family) => {
32
+ const models = state.models?.data ?? [];
33
+ let best;
34
+ for (const model of models) {
35
+ const normalized = normalizeSdkModelId(model.id);
36
+ if (!normalized || normalized.family !== family) continue;
37
+ const [majorPart, minorPart = "0"] = normalized.version.split(".");
38
+ const major = Number.parseInt(majorPart, 10);
39
+ const minor = Number.parseInt(minorPart, 10);
40
+ if (Number.isNaN(major) || Number.isNaN(minor)) continue;
41
+ if (!best || major > best.major || major === best.major && minor > best.minor) best = {
42
+ model,
43
+ major,
44
+ minor
45
+ };
46
+ }
47
+ return best?.model;
48
+ };
49
+ /**
50
+ * Normalizes an SDK model ID to extract the model family and version.
51
+ * this method from github copilot extension
52
+ * Examples:
53
+ * - "claude-opus-4-5-20251101" -> { family: "opus", version: "4.5" }
54
+ * - "claude-3-5-sonnet-20241022" -> { family: "sonnet", version: "3.5" }
55
+ * - "claude-sonnet-4-20250514" -> { family: "sonnet", version: "4" }
56
+ * - "claude-haiku-3-5-20250514" -> { family: "haiku", version: "3.5" }
57
+ * - "claude-haiku-4.5" -> { family: "haiku", version: "4.5" }
58
+ */
59
+ const normalizeSdkModelId = (sdkModelId) => {
60
+ const withoutDate = sdkModelId.toLowerCase().replace(/-\d{8}$/, "");
61
+ const pattern1 = withoutDate.match(/^claude-(\w+)-(\d+)\.(\d+)$/);
62
+ if (pattern1) return {
63
+ family: pattern1[1],
64
+ version: `${pattern1[2]}.${pattern1[3]}`
65
+ };
66
+ const pattern2 = withoutDate.match(/^claude-(\w+)-(\d+)-(\d+)$/);
67
+ if (pattern2) return {
68
+ family: pattern2[1],
69
+ version: `${pattern2[2]}.${pattern2[3]}`
70
+ };
71
+ const pattern3 = withoutDate.match(/^claude-(\d+)-(\d+)-(\w+)$/);
72
+ if (pattern3) return {
73
+ family: pattern3[3],
74
+ version: `${pattern3[1]}.${pattern3[2]}`
75
+ };
76
+ const pattern4 = withoutDate.match(/^claude-(\w+)-(\d+)$/);
77
+ if (pattern4) return {
78
+ family: pattern4[1],
79
+ version: pattern4[2]
80
+ };
81
+ const pattern5 = withoutDate.match(/^claude-(\d+)-(\w+)$/);
82
+ if (pattern5) return {
83
+ family: pattern5[2],
84
+ version: pattern5[1]
85
+ };
86
+ };
87
+ //#endregion
88
+ export { toClientModelId as i, getLatestModelForFamily as n, normalizeSdkModelId as r, findEndpointModel as t };
89
+
90
+ //# sourceMappingURL=models-haiuFowF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models-haiuFowF.js","names":[],"sources":["../src/lib/models.ts"],"sourcesContent":["import type { Model } from \"~/services/copilot/get-models\"\n\nimport { state } from \"~/lib/state\"\n\n/**\n * Converts a Copilot upstream model ID to a client-friendly ID that Claude Code\n * and Claude Desktop recognize (dots in version replaced with hyphens).\n * e.g. \"claude-sonnet-4.6\" -> \"claude-sonnet-4-6\"\n * Non-Claude models are returned unchanged.\n */\nexport const toClientModelId = (modelId: string): string => {\n const normalized = normalizeSdkModelId(modelId)\n if (!normalized) return modelId\n const versionHyphenated = normalized.version.replaceAll(\".\", \"-\")\n return `claude-${normalized.family}-${versionHyphenated}`\n}\n\nexport interface NormalizedSdkModelId {\n family: string\n version: string\n}\n\nexport const findEndpointModel = (sdkModelId: string): Model | undefined => {\n const models = state.models?.data ?? []\n const exactMatch = models.find((m) => m.id === sdkModelId)\n if (exactMatch) {\n return exactMatch\n }\n\n const normalized = normalizeSdkModelId(sdkModelId)\n if (!normalized) {\n return undefined\n }\n\n const modelName = `claude-${normalized.family}-${normalized.version}`\n const model = models.find((m) => m.id === modelName)\n if (model) {\n return model\n }\n\n return undefined\n}\n\n/**\n * Finds the latest available model for a given Claude family (e.g. \"opus\",\n * \"sonnet\", \"haiku\") among the models currently cached in `state.models`.\n * \"Latest\" is determined by the highest semantic version parsed from the model\n * ID. Returns `undefined` when no model of that family is available.\n */\nexport const getLatestModelForFamily = (family: string): Model | undefined => {\n const models = state.models?.data ?? []\n\n let best: { model: Model; major: number; minor: number } | undefined\n\n for (const model of models) {\n const normalized = normalizeSdkModelId(model.id)\n if (!normalized || normalized.family !== family) {\n continue\n }\n\n const [majorPart, minorPart = \"0\"] = normalized.version.split(\".\")\n const major = Number.parseInt(majorPart, 10)\n const minor = Number.parseInt(minorPart, 10)\n if (Number.isNaN(major) || Number.isNaN(minor)) {\n continue\n }\n\n if (\n !best\n || major > best.major\n || (major === best.major && minor > best.minor)\n ) {\n best = { model, major, minor }\n }\n }\n\n return best?.model\n}\n\n/**\n * Normalizes an SDK model ID to extract the model family and version.\n * this method from github copilot extension\n * Examples:\n * - \"claude-opus-4-5-20251101\" -> { family: \"opus\", version: \"4.5\" }\n * - \"claude-3-5-sonnet-20241022\" -> { family: \"sonnet\", version: \"3.5\" }\n * - \"claude-sonnet-4-20250514\" -> { family: \"sonnet\", version: \"4\" }\n * - \"claude-haiku-3-5-20250514\" -> { family: \"haiku\", version: \"3.5\" }\n * - \"claude-haiku-4.5\" -> { family: \"haiku\", version: \"4.5\" }\n */\nexport const normalizeSdkModelId = (\n sdkModelId: string,\n): NormalizedSdkModelId | undefined => {\n const lower = sdkModelId.toLowerCase()\n\n // Strip date suffix (8 digits at the end)\n const withoutDate = lower.replace(/-\\d{8}$/, \"\")\n\n // Pattern 1: claude-{family}-{major}.{minor} (e.g., claude-haiku-4.5)\n const pattern1 = withoutDate.match(/^claude-(\\w+)-(\\d+)\\.(\\d+)$/)\n if (pattern1) {\n return { family: pattern1[1], version: `${pattern1[2]}.${pattern1[3]}` }\n }\n\n // Pattern 2: claude-{family}-{major}-{minor} (e.g., claude-opus-4-5, claude-haiku-3-5)\n const pattern2 = withoutDate.match(/^claude-(\\w+)-(\\d+)-(\\d+)$/)\n if (pattern2) {\n return { family: pattern2[1], version: `${pattern2[2]}.${pattern2[3]}` }\n }\n\n // Pattern 3: claude-{major}-{minor}-{family} (e.g., claude-3-5-sonnet)\n const pattern3 = withoutDate.match(/^claude-(\\d+)-(\\d+)-(\\w+)$/)\n if (pattern3) {\n return { family: pattern3[3], version: `${pattern3[1]}.${pattern3[2]}` }\n }\n\n // Pattern 4: claude-{family}-{major} (e.g., claude-sonnet-4)\n const pattern4 = withoutDate.match(/^claude-(\\w+)-(\\d+)$/)\n if (pattern4) {\n return { family: pattern4[1], version: pattern4[2] }\n }\n\n // Pattern 5: claude-{major}-{family} (e.g., claude-3-opus)\n const pattern5 = withoutDate.match(/^claude-(\\d+)-(\\w+)$/)\n if (pattern5) {\n return { family: pattern5[2], version: pattern5[1] }\n }\n\n return undefined\n}\n"],"mappings":";;;;;;;;AAUA,MAAa,mBAAmB,YAA4B;CAC1D,MAAM,aAAa,oBAAoB,QAAQ;CAC/C,IAAI,CAAC,YAAY,OAAO;CACxB,MAAM,oBAAoB,WAAW,QAAQ,WAAW,KAAK,IAAI;CACjE,OAAO,UAAU,WAAW,OAAO,GAAG;;AAQxC,MAAa,qBAAqB,eAA0C;CAC1E,MAAM,SAAS,MAAM,QAAQ,QAAQ,EAAE;CACvC,MAAM,aAAa,OAAO,MAAM,MAAM,EAAE,OAAO,WAAW;CAC1D,IAAI,YACF,OAAO;CAGT,MAAM,aAAa,oBAAoB,WAAW;CAClD,IAAI,CAAC,YACH;CAGF,MAAM,YAAY,UAAU,WAAW,OAAO,GAAG,WAAW;CAC5D,MAAM,QAAQ,OAAO,MAAM,MAAM,EAAE,OAAO,UAAU;CACpD,IAAI,OACF,OAAO;;;;;;;;AAYX,MAAa,2BAA2B,WAAsC;CAC5E,MAAM,SAAS,MAAM,QAAQ,QAAQ,EAAE;CAEvC,IAAI;CAEJ,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,aAAa,oBAAoB,MAAM,GAAG;EAChD,IAAI,CAAC,cAAc,WAAW,WAAW,QACvC;EAGF,MAAM,CAAC,WAAW,YAAY,OAAO,WAAW,QAAQ,MAAM,IAAI;EAClE,MAAM,QAAQ,OAAO,SAAS,WAAW,GAAG;EAC5C,MAAM,QAAQ,OAAO,SAAS,WAAW,GAAG;EAC5C,IAAI,OAAO,MAAM,MAAM,IAAI,OAAO,MAAM,MAAM,EAC5C;EAGF,IACE,CAAC,QACE,QAAQ,KAAK,SACZ,UAAU,KAAK,SAAS,QAAQ,KAAK,OAEzC,OAAO;GAAE;GAAO;GAAO;GAAO;;CAIlC,OAAO,MAAM;;;;;;;;;;;;AAaf,MAAa,uBACX,eACqC;CAIrC,MAAM,cAHQ,WAAW,aAGA,CAAC,QAAQ,WAAW,GAAG;CAGhD,MAAM,WAAW,YAAY,MAAM,8BAA8B;CACjE,IAAI,UACF,OAAO;EAAE,QAAQ,SAAS;EAAI,SAAS,GAAG,SAAS,GAAG,GAAG,SAAS;EAAM;CAI1E,MAAM,WAAW,YAAY,MAAM,6BAA6B;CAChE,IAAI,UACF,OAAO;EAAE,QAAQ,SAAS;EAAI,SAAS,GAAG,SAAS,GAAG,GAAG,SAAS;EAAM;CAI1E,MAAM,WAAW,YAAY,MAAM,6BAA6B;CAChE,IAAI,UACF,OAAO;EAAE,QAAQ,SAAS;EAAI,SAAS,GAAG,SAAS,GAAG,GAAG,SAAS;EAAM;CAI1E,MAAM,WAAW,YAAY,MAAM,uBAAuB;CAC1D,IAAI,UACF,OAAO;EAAE,QAAQ,SAAS;EAAI,SAAS,SAAS;EAAI;CAItD,MAAM,WAAW,YAAY,MAAM,uBAAuB;CAC1D,IAAI,UACF,OAAO;EAAE,QAAQ,SAAS;EAAI,SAAS,SAAS;EAAI"}
@@ -1,6 +1,7 @@
1
1
  import { C as resolveEffectiveProviderType, E as setModelMappings, O as PATHS, T as resolveProviderAuthType, _ as isResponsesApiWebSearchEnabled, a as getExtraPromptForModel, b as listEnabledProviders, c as getModelResponsesApiCompactThreshold$1, d as getReasoningEffortForModel, f as getSmallModel, g as isMessagesApiEnabled, h as isGpt56OrAbove, i as getConfig, l as getProviderConfig, m as isContextManagementEnabledForResponses, n as getAnthropicApiKey, o as getMessageApiWebSearchModel, p as isContextManagementEnabledForMessages, r as getClaudeTokenMultiplier, s as getModelMappings, u as getRawProviderConfig, v as isResponsesApiWebSocketEnabled, w as resolveMappedModel } from "./config-DkgRPYZ6.js";
2
2
  import { B as HTTPError, C as prepareMessageProxyHeaders, E as compactMessageSections, F as requestContext, I as resolveTraceId$1, L as createPooledWebSocketStream, M as buildCodexRequestHeaders, N as forwardCodexResponses, O as compactSystemPromptStarts, P as generateTraceId, R as createWebSocketUrl, S as prepareInteractionHeaders, T as compactAutoContinuePromptStarts, V as forwardError, b as copilotWebSocketHeaders, d as generateRequestIdFromPayload, f as getRootSessionId, g as getCopilotUsage, h as parseUserIdMetadata, j as CODEX_API_BASE_URL, m as isNullish, p as getUUID, r as setupCodexToken, v as copilotBaseUrl, x as prepareForCompact, y as copilotHeaders, z as state } from "./token-DHWoZfxf.js";
3
3
  import { a as isDeferredToolName, c as parseMcpToolSearchSentinel, d as shouldEnableResponsesToolSearch, i as isBridgeToolSearchName, l as resolveBridgeToolSearchName, o as listDeferredToolNames, r as formatToolSearchBridgeArguments, s as normalizeToolSearchBridgeArguments, t as BRIDGE_TOOL_SEARCH_NAME, u as selectDeferredToolsByNames } from "./tool-search-OX6iPJ9D.js";
4
+ import { i as toClientModelId, r as normalizeSdkModelId, t as findEndpointModel } from "./models-haiuFowF.js";
4
5
  import consola from "consola";
5
6
  import { createHash } from "node:crypto";
6
7
  import fs, { readFileSync } from "node:fs";
@@ -1335,6 +1336,16 @@ const BUILTIN_PROVIDER_PRICING = {
1335
1336
  input: 1.4,
1336
1337
  output: 4.4
1337
1338
  },
1339
+ "grok-4.5": { tiers: [{
1340
+ cachedInput: .5,
1341
+ input: 2,
1342
+ maxInputTokens: 2e5,
1343
+ output: 6
1344
+ }, {
1345
+ cachedInput: 1,
1346
+ input: 4,
1347
+ output: 12
1348
+ }] },
1338
1349
  "deepseek-v4-flash": {
1339
1350
  cachedInput: .0028,
1340
1351
  input: .14,
@@ -1350,6 +1361,11 @@ const BUILTIN_PROVIDER_PRICING = {
1350
1361
  input: .95,
1351
1362
  output: 4
1352
1363
  },
1364
+ "kimi-k3": {
1365
+ cachedInput: .3,
1366
+ input: 3,
1367
+ output: 15
1368
+ },
1353
1369
  "mimo-v2.5": {
1354
1370
  cachedInput: .0028,
1355
1371
  input: .14,
@@ -2600,72 +2616,9 @@ function getAnthropicToolUseBlocks(toolCalls) {
2600
2616
  input: JSON.parse(toolCall.function.arguments)
2601
2617
  }));
2602
2618
  }
2603
- //#endregion
2604
- //#region src/lib/models.ts
2605
- /**
2606
- * Converts a Copilot upstream model ID to a client-friendly ID that Claude Code
2607
- * and Claude Desktop recognize (dots in version replaced with hyphens).
2608
- * e.g. "claude-sonnet-4.6" -> "claude-sonnet-4-6"
2609
- * Non-Claude models are returned unchanged.
2610
- */
2611
- const toClientModelId = (modelId) => {
2612
- const normalized = normalizeSdkModelId(modelId);
2613
- if (!normalized) return modelId;
2614
- const versionHyphenated = normalized.version.replaceAll(".", "-");
2615
- return `claude-${normalized.family}-${versionHyphenated}`;
2616
- };
2617
- const findEndpointModel = (sdkModelId) => {
2618
- const models = state.models?.data ?? [];
2619
- const exactMatch = models.find((m) => m.id === sdkModelId);
2620
- if (exactMatch) return exactMatch;
2621
- const normalized = normalizeSdkModelId(sdkModelId);
2622
- if (!normalized) return;
2623
- const modelName = `claude-${normalized.family}-${normalized.version}`;
2624
- const model = models.find((m) => m.id === modelName);
2625
- if (model) return model;
2626
- };
2627
- /**
2628
- * Normalizes an SDK model ID to extract the model family and version.
2629
- * this method from github copilot extension
2630
- * Examples:
2631
- * - "claude-opus-4-5-20251101" -> { family: "opus", version: "4.5" }
2632
- * - "claude-3-5-sonnet-20241022" -> { family: "sonnet", version: "3.5" }
2633
- * - "claude-sonnet-4-20250514" -> { family: "sonnet", version: "4" }
2634
- * - "claude-haiku-3-5-20250514" -> { family: "haiku", version: "3.5" }
2635
- * - "claude-haiku-4.5" -> { family: "haiku", version: "4.5" }
2636
- */
2637
- const normalizeSdkModelId = (sdkModelId) => {
2638
- const withoutDate = sdkModelId.toLowerCase().replace(/-\d{8}$/, "");
2639
- const pattern1 = withoutDate.match(/^claude-(\w+)-(\d+)\.(\d+)$/);
2640
- if (pattern1) return {
2641
- family: pattern1[1],
2642
- version: `${pattern1[2]}.${pattern1[3]}`
2643
- };
2644
- const pattern2 = withoutDate.match(/^claude-(\w+)-(\d+)-(\d+)$/);
2645
- if (pattern2) return {
2646
- family: pattern2[1],
2647
- version: `${pattern2[2]}.${pattern2[3]}`
2648
- };
2649
- const pattern3 = withoutDate.match(/^claude-(\d+)-(\d+)-(\w+)$/);
2650
- if (pattern3) return {
2651
- family: pattern3[3],
2652
- version: `${pattern3[1]}.${pattern3[2]}`
2653
- };
2654
- const pattern4 = withoutDate.match(/^claude-(\w+)-(\d+)$/);
2655
- if (pattern4) return {
2656
- family: pattern4[1],
2657
- version: pattern4[2]
2658
- };
2659
- const pattern5 = withoutDate.match(/^claude-(\d+)-(\w+)$/);
2660
- if (pattern5) return {
2661
- family: pattern5[2],
2662
- version: pattern5[1]
2663
- };
2664
- };
2665
2619
  const SYSTEM_REMINDER_START = "<system-reminder>";
2666
2620
  const SYSTEM_REMINDER_END = "</system-reminder>";
2667
2621
  const SUBAGENT_START_HOOK_ADDITIONAL_PREFIX = "SubagentStart hook additional";
2668
- const IDE_EXECUTE_CODE_TOOL = "mcp__ide__executeCode";
2669
2622
  const IDE_GET_DIAGNOSTICS_TOOL = "mcp__ide__getDiagnostics";
2670
2623
  const IDE_GET_DIAGNOSTICS_DESCRIPTION = "Get language diagnostics from VS Code. Returns errors, warnings, information, and hints for files in the workspace.";
2671
2624
  const PDF_FILE_READ_PREFIX = "PDF file read:";
@@ -2988,7 +2941,6 @@ const mergeToolResultForClaude = (anthropicPayload, options) => {
2988
2941
  const sanitizeIdeTools = (payload) => {
2989
2942
  if (!payload.tools || payload.tools.length === 0) return;
2990
2943
  payload.tools = payload.tools.flatMap((tool) => {
2991
- if (tool.name === IDE_EXECUTE_CODE_TOOL && !tool.defer_loading) return [];
2992
2944
  if (tool.name === IDE_GET_DIAGNOSTICS_TOOL) return [{
2993
2945
  ...tool,
2994
2946
  description: IDE_GET_DIAGNOSTICS_DESCRIPTION
@@ -7154,4 +7106,4 @@ server.route("/:provider/images", providerImageRoutes);
7154
7106
  //#endregion
7155
7107
  export { server };
7156
7108
 
7157
- //# sourceMappingURL=server-BgkyqOM7.js.map
7109
+ //# sourceMappingURL=server-B15THY2f.js.map