@jeffreycao/copilot-api 2.5.3 → 2.5.4

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
@@ -308,9 +308,7 @@ args = [
308
308
 
309
309
  Without this configuration, Codex cannot fetch `/v1/models` while not signed in to a GPT account, so custom models are unavailable in the model picker.
310
310
 
311
- When a Codex client (`User-Agent` starts with `codex`) requests the top-level `GET /v1/models`, the gateway merges native Codex models with models available through the Messages adapter. The latter advertise `use_responses_lite: true`, except DeepSeek models, which use `use_responses_lite: false` and `tool_mode: null`. For other models, `/v1/responses` uses **Responses → Messages** for Anthropic providers, while OpenAI-compatible providers and Chat-only Copilot models reuse the existing Messages route for **Responses → Messages → Chat Completions**, then translate streaming or JSON results back to Responses.
312
-
313
- > **Note:** DeepSeek models do not use Responses Lite (`use_responses_lite: false`, `tool_mode: null`), so the tool set they advertise to Codex differs from other models, which use `tool_mode: "code_mode_only"`. Switching between a DeepSeek model and a Responses Lite model mid-session is not compatible, because tool calls and conversation history produced under one tool set do not translate to the other. Start a new Codex session when switching between them.
311
+ When a Codex client (`User-Agent` starts with `codex`) requests the top-level `GET /v1/models`, the gateway merges native Codex models with models available through the Messages adapter. The latter advertise `use_responses_lite: true` and `tool_mode: "code_mode_only"`. For these models, `/v1/responses` uses **Responses → Messages** for Anthropic providers, while OpenAI-compatible providers and Chat-only Copilot models reuse the existing Messages route for **Responses → Messages → Chat Completions**, then translate streaming or JSON results back to Responses.
314
312
 
315
313
  The merged catalog is what Codex shows in its model picker, including the models exposed by your configured providers:
316
314
 
@@ -543,7 +541,7 @@ After installation, `agent-inject` injects `__SUBAGENT_MARKER__...` on `Subagent
543
541
 
544
542
  The `agent-inject` plugin also registers a `UserPromptSubmit` hook that returns `{"continue": true}`, and it can inject `SessionStart` reminder rules through environment variables:
545
543
 
546
- - `CLAUDE_PLUGIN_ENABLE_QUESTION_RULES=1` enables the two reminders about using the `question` tool automatically for Claude Code. Alternatively, you can add the same reminders manually in `CLAUDE.md`; see [CLAUDE.md or AGENTS.md Recommended Content](#claudemd-or-agentsmd-recommended-content).
544
+ - `CLAUDE_PLUGIN_ENABLE_QUESTION_RULES=1` enables the two reminders about using the `question` tool automatically for Claude Code.
547
545
  - `CLAUDE_PLUGIN_ENABLE_NO_BACKGROUND_AGENTS_RULE=1` enables the `run_in_background: true` avoidance reminder for agent hooks.
548
546
 
549
547
  The `tool-search` plugin bundles the same MCP bridge described in [GPT Tool Search](#gpt-tool-search), so Claude Code users do not need to add the `tool_search` server manually when they install that plugin.
@@ -714,7 +712,7 @@ Gateway API keys live under `auth.apiKeys` in `config.json`. Manage them with `c
714
712
  - **auth.adminApiKey:** Single admin key used only for `/admin/*` routes. If missing, the server generates a random key at startup and writes it back to `config.json`. Requests use the same `x-api-key` or `Authorization: Bearer` headers, but regular `auth.apiKeys` never grant access to `/admin/*`.
715
713
  - **modelMappings:** Exact `sourceModel -> targetModel` rewrites shared by top-level `POST /v1/messages`, `POST /v1/messages/count_tokens`, `POST /v1/responses`, and `POST /v1/chat/completions` requests. Omit it or leave it as `{}` to disable rewrites. Both the source and target must be non-empty strings. Targets can be regular model IDs or `provider/model` aliases such as `dashscope/qwen3.6-plus`, and the rewrite happens before provider alias parsing. These mappings are not split per interface. The admin endpoints `GET/POST /admin/config/model-mappings` read and update only this field.
716
714
  - **extraPrompts:** Map of `model -> prompt` appended to the first system prompt when translating Anthropic-style requests to Responses API. Use this to inject guardrails or guidance per model. Missing default entries are auto-added without overwriting your custom prompts. For GPT-5.3+ models (e.g. `gpt-5.3-codex`, `gpt-5.4`, `gpt-5.5`), a built-in commentary prompt is used as fallback when not explicitly configured. The built-in prompts enable phase-aware commentary, which lets the model emit a short user-facing progress update before tools or deeper reasoning.
717
- - **providers:** Global upstream provider map. Each provider key (for example `dashscope`) becomes a route prefix (`/dashscope/v1/messages`). Supports `type: "anthropic"`, `type: "openai-compatible"`, and `type: "openai-responses"`. Top-level clients can also use `model: "dashscope/model-id"` with `/v1/messages`, `/v1/messages/count_tokens`, `/v1/responses`, and `/v1/chat/completions`; the gateway strips the `dashscope/` prefix before forwarding upstream. The `/v1/responses` route for `anthropic` and `openai-compatible` providers uses the Responses Lite → Messages adapter; `openai-compatible` providers then reuse the Messages → Chat translation. Codex clients (`User-Agent` starting with `codex`) also use the adapter for non-`gpt-*` models on `openai-responses` providers. `GET /v1/models` aggregates enabled provider models with `provider/model-id` IDs, while the top-level Codex-UA catalog also merges these adaptable models as `use_responses_lite` entries (except DeepSeek models, which use `use_responses_lite: false` and `tool_mode: null`). Use `GET /dashscope/v1/models` for a single provider's raw model list.
715
+ - **providers:** Global upstream provider map. Each provider key (for example `dashscope`) becomes a route prefix (`/dashscope/v1/messages`). Supports `type: "anthropic"`, `type: "openai-compatible"`, and `type: "openai-responses"`. Top-level clients can also use `model: "dashscope/model-id"` with `/v1/messages`, `/v1/messages/count_tokens`, `/v1/responses`, and `/v1/chat/completions`; the gateway strips the `dashscope/` prefix before forwarding upstream. The `/v1/responses` route for `anthropic` and `openai-compatible` providers uses the Responses Lite → Messages adapter; `openai-compatible` providers then reuse the Messages → Chat translation. Codex clients (`User-Agent` starting with `codex`) also use the adapter for non-`gpt-*` models on `openai-responses` providers. `GET /v1/models` aggregates enabled provider models with `provider/model-id` IDs, while the top-level Codex-UA catalog also merges these adaptable models as `use_responses_lite` entries. Use `GET /dashscope/v1/models` for a single provider's raw model list.
718
716
  - `enabled` defaults to `true` if omitted.
719
717
  - `baseUrl` should be provider API base URL without the final endpoint. For Anthropic providers, omit `/v1/messages`; for OpenAI-compatible providers, omit `/v1/chat/completions`; for OpenAI Responses providers, omit `/v1/responses`.
720
718
  - `apiKey` is used as the upstream credential value and is required unless `authType` is `azure-entra`.
@@ -744,7 +742,7 @@ Gateway API keys live under `auth.apiKeys` in `config.json`. Manage them with `c
744
742
  - **Forwarding:** the resolved value remains `output_config.effort` for the Copilot native Messages API and becomes `reasoning.effort` when translated to the Responses API.
745
743
  - **Configuration values:** `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`.
746
744
  - **useMessagesApi:** When `true`, models that advertise Copilot's native `/v1/messages` endpoint use the Messages API. If Messages is disabled or unavailable for the selected model, the gateway uses Responses when that model advertises a Responses endpoint, then falls back to Chat Completions when supported. Set this to `false` to skip native Messages routing. Defaults to `true`.
747
- - **useResponsesApiWebSocket:** When `true`, Copilot Responses requests use WebSocket for models that advertise `ws:/responses`; models that advertise only `/responses` use HTTP. Streamed Responses requests for the built-in `codex` provider use WebSocket whenever this setting is enabled, while non-streaming Codex requests always use HTTP. Set this to `false` to make Copilot use HTTP `/responses` where the selected model advertises it and to send streamed Codex Responses requests over HTTP. WebSocket failures are not retried automatically over HTTP. Defaults to `true`. If a proxy, VPN, or network blocks or destabilizes WebSocket traffic, disable this setting or switch networks.
745
+ - **useResponsesApiWebSocket:** When `true`, Copilot Responses requests use WebSocket for models that advertise `ws:/responses`; models that advertise only `/responses` use HTTP. Streamed Responses requests for the built-in `codex` provider use WebSocket whenever this setting is enabled, while non-streaming Codex requests always use HTTP. Set this to `false` to make Copilot use HTTP `/responses` where the selected model advertises it and to send streamed Codex Responses requests over HTTP. WebSocket failures are not retried automatically over HTTP. Defaults to `true`. If a proxy, VPN, or network blocks or destabilizes WebSocket traffic, disable this setting or switch networks. Also set it to `false` when the GitHub Copilot provider fails with `Encrypted function output content could not be decrypted or decoded`; see [Troubleshooting](#troubleshooting).
748
746
  - **upstreamTransport:** Positive integer lifecycle and buffering limits for the upstream chat completions, responses, and messages transports. Invalid, zero, or negative values fall back to the defaults shown above. `headersTimeoutMs` covers connection setup through receipt of HTTP response headers; it is not a total generation deadline. `streamInactivityTimeoutMs` is reset by every HTTP body chunk or WebSocket message, allowing long generations to continue while they remain active. `websocketOpenTimeoutMs` limits the WebSocket handshake, while `websocketPoolIdleTimeoutMs` controls only completed, reusable pooled sockets. The byte and message limits bound queued WebSocket events; exceeding either limit fails that stream and invalidates its socket rather than dropping or reordering events.
749
747
  - **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`.
750
748
  - **alphaSearchCodexPriority:** Defaults to `true`. Top-level alpha-search requests prefer the Codex alpha-search endpoint because it does not consume provider quota. If Codex is unavailable, or this setting is `false`, requests with a `provider/model` alias other than `codex/model` use that provider's `/v1/responses` endpoint, and requests without a provider prefix use GitHub Copilot Responses web search. The adapter recognizes every current Codex search command; unsupported `image_query` and `screenshot` operations return successful no-retry tool output.
@@ -870,13 +868,18 @@ curl http://localhost:4141/dashscope/v1/messages \
870
868
  -d '{"model":"qwen3.6-plus","max_tokens":1024,"messages":[{"role":"user","content":"hello"}]}'
871
869
  ```
872
870
 
873
- ## Usage Tips
871
+ <a id="troubleshooting"></a>
874
872
 
875
- ### CLAUDE.md or AGENTS.md Recommended Content
873
+ ## Troubleshooting
876
874
 
877
- Same reminders as `CLAUDE_PLUGIN_ENABLE_QUESTION_RULES=1` in the `agent-inject` plugin, for when you don't use that plugin. Add to `CLAUDE.md` (Claude Code) or `AGENTS.md` (opencode/codex):
875
+ **GitHub Copilot encrypted output decryption failure**
878
876
 
877
+ When the GitHub Copilot provider returns or logs `Encrypted function output content could not be decrypted or decoded`, it is usually an upstream issue. Set `useResponsesApiWebSocket` to `false` in `config.json` so Copilot Responses traffic goes over HTTP `/responses` instead:
878
+
879
+ ```json
880
+ {
881
+ "useResponsesApiWebSocket": false
882
+ }
879
883
  ```
880
- - Prohibited from directly asking questions to users, MUST use question tool.
881
- - Once you can confirm that the task is complete, MUST use question tool to make user confirm. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again, after try again, MUST use question tool to make user confirm again.
882
- ```
884
+
885
+ Restart the server after changing the config. See [Configuration (config.json)](#configuration-configjson) for the full option reference.
package/README.zh-CN.md CHANGED
@@ -324,9 +324,7 @@ args = [
324
324
 
325
325
  未按上述方式配置时,Codex 未登录 GPT 账号拉不到 `/v1/models`,无法选择自定义模型。
326
326
 
327
- Codex 客户端(`User-Agent` 以 `codex` 开头)请求顶层 `GET /v1/models` 时,网关会把原生 Codex 模型与可通过 Messages 适配的模型合并返回。除 DeepSeek 模型外,后者会声明 `use_responses_lite: true`;DeepSeek 模型使用 `use_responses_lite: false` 和 `tool_mode: null`。调用 `/v1/responses` 后,Anthropic provider 走 **Responses → Messages**,OpenAI 兼容 provider 以及只支持 Chat 的 Copilot 模型则复用现有 Messages 路由继续走 **Responses → Messages → Chat Completions**,最终统一翻译回 Responses(包括流式事件)。
328
-
329
- > **注意:** DeepSeek 模型不使用 Responses Lite(`use_responses_lite: false`、`tool_mode: null`),因此向 Codex 暴露的工具集合与其他模型(`tool_mode: "code_mode_only"`)不一致。在会话中途切换 DeepSeek 模型与 Responses Lite 模型并不兼容——一套工具集合下产生的工具调用和会话历史无法直接沿用到另一套。切换模型时请新建 Codex 会话。
327
+ Codex 客户端(`User-Agent` 以 `codex` 开头)请求顶层 `GET /v1/models` 时,网关会把原生 Codex 模型与可通过 Messages 适配的模型合并返回。后者会声明 `use_responses_lite: true` 和 `tool_mode: "code_mode_only"`。调用 `/v1/responses` 后,Anthropic provider 走 **Responses → Messages**,OpenAI 兼容 provider 以及只支持 Chat 的 Copilot 模型则复用现有 Messages 路由继续走 **Responses → Messages → Chat Completions**,最终统一翻译回 Responses(包括流式事件)。
330
328
 
331
329
  合并后的模型列表会直接展示在 Codex 的模型选择界面中,包含各 provider 暴露的模型:
332
330
 
@@ -579,7 +577,7 @@ Claude Code 集成现在拆分为两个插件:
579
577
 
580
578
  `agent-inject` 还会注册一个 `UserPromptSubmit` hook,并返回 `{"continue": true}`;同时它也可以通过环境变量注入 `SessionStart` reminder 规则:
581
579
 
582
- - `CLAUDE_PLUGIN_ENABLE_QUESTION_RULES=1` 会自动为 Claude Code 启用两条关于使用 `question` 工具的提醒。你也可以把同样的提醒手动写进 `CLAUDE.md`;见 [CLAUDE.md 或 AGENTS.md 推荐内容](#claudemd-or-agentsmd-recommended-content)。
580
+ - `CLAUDE_PLUGIN_ENABLE_QUESTION_RULES=1` 会自动为 Claude Code 启用两条关于使用 `question` 工具的提醒。
583
581
  - `CLAUDE_PLUGIN_ENABLE_NO_BACKGROUND_AGENTS_RULE=1` 会启用关于避免在 agent hooks 中使用 `run_in_background: true` 的提醒。
584
582
 
585
583
  `tool-search` 插件内置了 [GPT Tool Search](#gpt-tool-search) 一节描述的同一个 MCP bridge,因此安装该插件后,Claude Code 用户无需再手动配置 `tool_search` server。
@@ -758,7 +756,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
758
756
  - **auth.adminApiKey:** 仅用于 `/admin/*` 路由的单个 admin key。若未配置,服务会在启动时自动生成一个随机 key,并回写到 `config.json`。它同样使用 `x-api-key` 或 `Authorization: Bearer` 这两种头,但普通 `auth.apiKeys` 不能访问 `/admin/*`。
759
757
  - **modelMappings:** 用于顶层 `POST /v1/messages`、`POST /v1/messages/count_tokens`、`POST /v1/responses` 和 `POST /v1/chat/completions` 请求的精确 `sourceModel -> targetModel` 重写映射,这几类接口共用同一份规则。省略该字段或保留为 `{}` 时,不会做模型重写。`source` 和 `target` 都必须是非空字符串。`target` 可以是普通模型 ID,也可以是 `provider/model` 形式的别名,例如 `dashscope/qwen3.6-plus`;重写发生在 provider alias 解析之前。这些映射不再按接口区分。`GET/POST /admin/config/model-mappings` 管理接口读写的也只有这个字段。
760
758
  - **extraPrompts:** `model -> prompt` 的映射。把 Anthropic 风格请求翻译为 Responses API 时,会将其附加到第一条 system prompt 后面。你可以借此为不同模型注入护栏或指引。缺失的默认项会自动补齐,但不会覆盖你自定义的 prompt。对于 GPT-5.3+ 模型(如 `gpt-5.3-codex`、`gpt-5.4`、`gpt-5.5`),未显式配置时会自动使用内置的 commentary prompt。内置 prompt 会启用带阶段感知的 commentary,让模型在工具调用或更深层推理前先发出简短的用户可见进度说明。
761
- - **providers:** 全局上游 provider 映射。每个 provider key(例如 `dashscope`)都会变成一个路由前缀(`/dashscope/v1/messages`)。支持 `type: "anthropic"`、`type: "openai-compatible"` 和 `type: "openai-responses"`。顶层客户端也可以在 `/v1/messages`、`/v1/messages/count_tokens`、`/v1/responses` 和 `/v1/chat/completions` 中使用 `model: "dashscope/model-id"`;AI gateway 会在转发上游前移除 `dashscope/` 前缀。`anthropic` 和 `openai-compatible` provider 的 `/v1/responses` 会通过 Responses Lite → Messages 适配;其中 `openai-compatible` provider 再复用 Messages → Chat 翻译。Codex 客户端(`User-Agent` 以 `codex` 开头)在 `openai-responses` provider 上请求非 `gpt-*` 模型时同样走该适配路径。`GET /v1/models` 会聚合已启用 provider 的模型,并以 `provider/model-id` 形式返回;Codex UA 的顶层模型列表还会把这些可适配模型合并为 `use_responses_lite` 模型(DeepSeek 模型除外,它们使用 `use_responses_lite: false` 和 `tool_mode: null`)。单个 provider 的原始模型列表仍可使用 `GET /dashscope/v1/models`。
759
+ - **providers:** 全局上游 provider 映射。每个 provider key(例如 `dashscope`)都会变成一个路由前缀(`/dashscope/v1/messages`)。支持 `type: "anthropic"`、`type: "openai-compatible"` 和 `type: "openai-responses"`。顶层客户端也可以在 `/v1/messages`、`/v1/messages/count_tokens`、`/v1/responses` 和 `/v1/chat/completions` 中使用 `model: "dashscope/model-id"`;AI gateway 会在转发上游前移除 `dashscope/` 前缀。`anthropic` 和 `openai-compatible` provider 的 `/v1/responses` 会通过 Responses Lite → Messages 适配;其中 `openai-compatible` provider 再复用 Messages → Chat 翻译。Codex 客户端(`User-Agent` 以 `codex` 开头)在 `openai-responses` provider 上请求非 `gpt-*` 模型时同样走该适配路径。`GET /v1/models` 会聚合已启用 provider 的模型,并以 `provider/model-id` 形式返回;Codex UA 的顶层模型列表还会把这些可适配模型合并为 `use_responses_lite` 模型。单个 provider 的原始模型列表仍可使用 `GET /dashscope/v1/models`。
762
760
  - `enabled`:可选,若省略则默认为 `true`。
763
761
  - `baseUrl`:provider API 的基础 URL,不要带结尾的 endpoint。Anthropic provider 不要带 `/v1/messages`;OpenAI 兼容 provider 不要带 `/v1/chat/completions`;OpenAI Responses provider 不要带 `/v1/responses`。
764
762
  - `apiKey`:作为上游凭据值使用;除 `authType` 为 `azure-entra` 外,普通 provider 必须配置。
@@ -788,7 +786,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
788
786
  - **转发字段:** 走 Copilot 原生 Messages API 时,最终值写入 `output_config.effort`;转换为 Responses API 时,最终值写入 `reasoning.effort`。
789
787
  - **配置可选值:** `none`、`minimal`、`low`、`medium`、`high`、`xhigh`、`max`。
790
788
  - **useMessagesApi:** 当为 `true` 时,声明了 Copilot 原生 `/v1/messages` 端点的模型会使用 Messages API。如果所选模型未声明 Messages 端点或关闭了该配置,网关会在模型声明了 Responses 端点时使用 Responses,否则在模型支持时回退到 Chat Completions。设为 `false` 可跳过原生 Messages 路由。默认值为 `true`。
791
- - **useResponsesApiWebSocket:** 当为 `true` 时,Copilot Responses 请求会对声明了 `ws:/responses` 的模型使用 WebSocket;仅声明 `/responses` 的模型使用 HTTP。内置 `codex` provider 的流式 Responses 请求只要启用了该配置就会使用 WebSocket,非流式 Codex 请求始终使用 HTTP。设为 `false` 后,Copilot 会在所选模型声明了 `/responses` 时使用 HTTP,Codex 的流式 Responses 请求也会改走 HTTP。WebSocket 失败后不会自动通过 HTTP 重试。默认值为 `true`。如果代理、VPN 或网络会阻断或干扰 WebSocket 流量,请关闭该配置或切换网络。
789
+ - **useResponsesApiWebSocket:** 当为 `true` 时,Copilot Responses 请求会对声明了 `ws:/responses` 的模型使用 WebSocket;仅声明 `/responses` 的模型使用 HTTP。内置 `codex` provider 的流式 Responses 请求只要启用了该配置就会使用 WebSocket,非流式 Codex 请求始终使用 HTTP。设为 `false` 后,Copilot 会在所选模型声明了 `/responses` 时使用 HTTP,Codex 的流式 Responses 请求也会改走 HTTP。WebSocket 失败后不会自动通过 HTTP 重试。默认值为 `true`。如果代理、VPN 或网络会阻断或干扰 WebSocket 流量,请关闭该配置或切换网络。使用 GitHub Copilot provider 时遇到 `Encrypted function output content could not be decrypted or decoded`,同样把该配置设为 `false`,详见[故障排查](#troubleshooting)。
792
790
  - **upstreamTransport:** 上游 chat completions、responses、messages 三类请求共用的生命周期与缓冲区正整数限制。无效值、零或负数会回退到上面列出的默认值。`headersTimeoutMs` 从连接建立开始计算,到收到 HTTP 响应头为止,并不是整个生成过程的总时限。每收到一个 HTTP body chunk 或 WebSocket message 都会重置 `streamInactivityTimeoutMs`,因此持续活跃的长推理任务不会被短总时限中断。`websocketOpenTimeoutMs` 限制 WebSocket 握手时间;`websocketPoolIdleTimeoutMs` 只控制已正常完成且可复用的空闲连接。WebSocket 队列同时受字节数和消息数上限约束;超过任一上限时会终止该 stream 并使 socket 失效,而不会丢弃或重排事件。
793
791
  - **useResponsesApiWebSearch:** 当为 `true` 时,服务端会保留 Responses API 中 `type: "web_search"` 的工具并透传到上游。设为 `false` 则会从 `/responses` payload 中移除这些工具。默认值为 `true`。
794
792
  - **alphaSearchCodexPriority:** 默认值为 `true`。顶层 alpha-search 请求优先使用 Codex alpha-search 端点,因为它不会消耗 provider 配额。若 Codex 不可用,或该配置设为 `false`,使用非 `codex/model` 的 `provider/model` 别名的请求会调用目标 provider 的 `/v1/responses` 端点,没有 provider 前缀的请求使用 GitHub Copilot Responses web search。该适配器会识别当前所有 Codex search command;不受支持的 `image_query` 和 `screenshot` 会返回成功且明确要求不要重试的 tool output。
@@ -920,17 +918,18 @@ curl http://localhost:4141/dashscope/v1/messages \
920
918
  -d '{"model":"qwen3.6-plus","max_tokens":1024,"messages":[{"role":"user","content":"hello"}]}'
921
919
  ```
922
920
 
923
- <a id="usage-tips"></a>
924
-
925
- ## 使用建议
921
+ <a id="troubleshooting"></a>
926
922
 
927
- <a id="claudemd-or-agentsmd-recommended-content"></a>
923
+ ## 故障排查
928
924
 
929
- ### CLAUDE.md 或 AGENTS.md 推荐内容
925
+ **GitHub Copilot 加密输出解密失败**
930
926
 
931
- 与 `agent-inject` 插件 `CLAUDE_PLUGIN_ENABLE_QUESTION_RULES=1` 注入的提醒一致,供不使用该插件时手动添加。加入 Claude Code 的 `CLAUDE.md` 或 opencode/codex 的 `AGENTS.md`:
927
+ 使用 GitHub Copilot provider 时,如果响应或日志中出现 `Encrypted function output content could not be decrypted or decoded`,通常是上游问题。把 `config.json` 里的 `useResponsesApiWebSocket` 设为 `false`,让 Copilot Responses 改走 HTTP `/responses` 即可绕过:
932
928
 
929
+ ```json
930
+ {
931
+ "useResponsesApiWebSocket": false
932
+ }
933
933
  ```
934
- - Prohibited from directly asking questions to users, MUST use question tool.
935
- - Once you can confirm that the task is complete, MUST use question tool to make user confirm. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again, after try again, MUST use question tool to make user confirm again.
936
- ```
934
+
935
+ 修改后重启服务生效。完整配置项说明见[配置(config.json)](#configuration-configjson)。
@@ -0,0 +1,2 @@
1
+ import { t as auth } from "./auth-LJ5y6v6e.js";
2
+ export { auth };
@@ -1,5 +1,5 @@
1
1
  import { M as setConfiguredApiKeys, N as PATHS, P as ensurePaths, a as normalizeProviderBaseUrl, c as setProviderConfig, n as getRawProviderConfig, r as isSupportedProviderType, y as SUPPORTED_PROVIDER_TYPES } from "./config-DYtohLpX.js";
2
- import { F as loginCodex, N as getConfiguredApiKeys, Y as state, a as setupGitHubToken, n as persistCodexCredentials } from "./token-Bm_dyi5a.js";
2
+ import { J as state, M as getConfiguredApiKeys, P as loginCodex, a as setupGitHubToken, n as persistCodexCredentials } from "./token-DZDtQb7h.js";
3
3
  import { defineCommand } from "citty";
4
4
  import consola from "consola";
5
5
  //#region src/lib/quick-providers.ts
@@ -490,4 +490,4 @@ const auth = defineCommand({
490
490
  //#endregion
491
491
  export { runProviderSetup as i, runAuthKeys as n, runAuthLogin as r, auth as t };
492
492
 
493
- //# sourceMappingURL=auth-BjbkSiVc.js.map
493
+ //# sourceMappingURL=auth-LJ5y6v6e.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-BjbkSiVc.js","names":[],"sources":["../src/lib/quick-providers.ts","../src/lib/interactive-prompt.ts","../src/auth.ts"],"sourcesContent":["import type { ProviderType } from \"./config\"\n\ninterface QuickProviderConfig {\n type: ProviderType\n baseUrl: string\n pricingCurrency: string\n editableType: boolean\n}\n\nexport const QUICK_PROVIDER_CONFIGS = {\n \"opencode-go\": {\n type: \"openai-compatible\",\n baseUrl: \"https://opencode.ai/zen/go\",\n pricingCurrency: \"USD\",\n editableType: false,\n },\n kimi: {\n type: \"openai-compatible\",\n baseUrl: \"https://api.kimi.com/coding\",\n pricingCurrency: \"USD\",\n editableType: true,\n },\n deepseek: {\n type: \"anthropic\",\n baseUrl: \"https://api.deepseek.com/anthropic\",\n pricingCurrency: \"CNY\",\n editableType: true,\n },\n dashscope: {\n type: \"openai-compatible\",\n baseUrl: \"https://dashscope.aliyuncs.com/compatible-mode\",\n pricingCurrency: \"CNY\",\n editableType: true,\n },\n openrouter: {\n type: \"anthropic\",\n baseUrl: \"https://openrouter.ai/api\",\n pricingCurrency: \"USD\",\n editableType: false,\n },\n} satisfies Record<string, QuickProviderConfig>\n\nexport type QuickProviderName = keyof typeof QUICK_PROVIDER_CONFIGS\n","import consola from \"consola\"\n\ninterface PromptSelectOption {\n label: string\n value: string\n hint?: string\n}\n\ninterface TextPromptOptions {\n type?: \"text\"\n default?: string\n initial?: string\n placeholder?: string\n}\n\ninterface SelectPromptOptions {\n type: \"select\"\n initial?: string\n options: Array<string | PromptSelectOption>\n}\n\nexport type InteractivePromptOptions = SelectPromptOptions | TextPromptOptions\n\ninterface ClackSelectOptions {\n message: string\n initialValue?: string\n options: Array<PromptSelectOption>\n}\n\ninterface ClackTextOptions {\n message: string\n defaultValue?: string\n initialValue?: string\n placeholder?: string\n}\n\nexport interface ClackPromptBackend {\n isCancel(value: unknown): boolean\n select(options: ClackSelectOptions): Promise<string | symbol>\n text(options: ClackTextOptions): Promise<string | symbol>\n}\n\ninterface PromptRuntime {\n bunVersion?: string\n platform: NodeJS.Platform\n stdinIsTTY?: boolean\n stdoutIsTTY?: boolean\n stdoutIsTTYStream?: boolean\n}\n\n// Consola 3.4.2 bundles a prompt implementation that writes keyboard input to\n// tty fd 0. Bun treats that as a real stdin write on Windows and throws EPIPE.\nexport function shouldUseClackPrompt(\n runtime: PromptRuntime = {\n bunVersion: process.versions.bun,\n platform: process.platform,\n stdinIsTTY: process.stdin.isTTY,\n stdoutIsTTY: process.stdout.isTTY,\n stdoutIsTTYStream: typeof process.stdout.getColorDepth === \"function\",\n },\n): boolean {\n return Boolean(\n runtime.platform === \"win32\"\n && runtime.bunVersion\n && runtime.stdinIsTTY\n && runtime.stdoutIsTTY\n && runtime.stdoutIsTTYStream,\n )\n}\n\nfunction getCancelValue(options: InteractivePromptOptions): string | undefined {\n return options.type === \"select\" ?\n options.initial\n : (options.default ?? options.initial)\n}\n\nexport async function promptWithClack(\n message: string,\n options: InteractivePromptOptions,\n backend: ClackPromptBackend,\n): Promise<string | undefined> {\n if (options.type === \"select\") {\n const value = await backend.select({\n message,\n options: options.options.map((option) =>\n typeof option === \"string\" ? { label: option, value: option } : option,\n ),\n initialValue: options.initial,\n })\n if (backend.isCancel(value)) {\n return getCancelValue(options)\n }\n return typeof value === \"string\" ? value : undefined\n }\n\n const value = await backend.text({\n message,\n defaultValue: options.default,\n initialValue: options.initial,\n placeholder: options.placeholder,\n })\n if (backend.isCancel(value)) {\n return getCancelValue(options)\n }\n return typeof value === \"string\" ? value : undefined\n}\n\nexport async function prompt(\n message: string,\n options: InteractivePromptOptions,\n): Promise<string | undefined> {\n if (!shouldUseClackPrompt()) {\n if (options.type === \"select\") {\n const value = await consola.prompt(message, options)\n return typeof value === \"string\" ? value : undefined\n }\n return await consola.prompt(message, options)\n }\n\n const clack = await import(\"@clack/prompts\")\n return await promptWithClack(message, options, clack)\n}\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport {\n getRawProviderConfig,\n isSupportedProviderType,\n normalizeProviderBaseUrl,\n setProviderConfig,\n setConfiguredApiKeys,\n SUPPORTED_PROVIDER_TYPES,\n type ProviderAuthType,\n type ProviderConfig,\n type ProviderType,\n} from \"./lib/config\"\nimport { loginCodex } from \"./lib/oauth/codex\"\nimport { PATHS, ensurePaths } from \"./lib/paths\"\nimport { getConfiguredApiKeys } from \"./lib/request-auth\"\nimport {\n QUICK_PROVIDER_CONFIGS,\n type QuickProviderName,\n} from \"./lib/quick-providers\"\nimport { prompt } from \"./lib/interactive-prompt\"\nimport { state } from \"./lib/state\"\nimport { persistCodexCredentials, setupGitHubToken } from \"./lib/token\"\n\ninterface RunAuthOptions {\n provider?: string\n verbose: boolean\n showToken: boolean\n}\n\nconst authArgs = {\n provider: {\n type: \"string\",\n description:\n \"Provider to log in with or configure (copilot, codex, opencode-go, kimi, deepseek, dashscope, openrouter, custom)\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show provider access token on auth\",\n },\n} as const\n\nconst BUILTIN_PROVIDER_NAMES = [\"copilot\", \"codex\"] as const\nconst QUICK_PROVIDER_NAMES = Object.keys(\n QUICK_PROVIDER_CONFIGS,\n) as Array<QuickProviderName>\nconst AUTH_PROVIDER_NAMES = [\n ...BUILTIN_PROVIDER_NAMES,\n ...QUICK_PROVIDER_NAMES,\n \"custom\",\n] as const\nconst CUSTOM_PROVIDER_AUTH_TYPE_OPTION = \"__default__\"\nconst QUICK_PROVIDER_DEFAULT_TYPE_OPTION = \"__default__\"\nconst CUSTOM_PROVIDER_AUTH_TYPES = [\"x-api-key\", \"authorization\"] as const\n\ntype BuiltinProviderName = (typeof BUILTIN_PROVIDER_NAMES)[number]\ntype AuthProviderName = (typeof AUTH_PROVIDER_NAMES)[number]\ntype CustomProviderAuthType = (typeof CUSTOM_PROVIDER_AUTH_TYPES)[number]\n\nconst BUILTIN_PROVIDER_LABELS: Record<BuiltinProviderName, string> = {\n copilot: \"GitHub Copilot\",\n codex: \"OpenAI Codex\",\n}\nconst AUTH_PROVIDER_LABELS: Record<AuthProviderName, string> = {\n ...BUILTIN_PROVIDER_LABELS,\n \"opencode-go\": \"OpenCode Go\",\n kimi: \"Kimi\",\n deepseek: \"DeepSeek\",\n dashscope: \"DashScope\",\n openrouter: \"OpenRouter\",\n custom: \"Custom provider\",\n}\n\nfunction isAuthProviderName(\n providerName: string,\n): providerName is AuthProviderName {\n return AUTH_PROVIDER_NAMES.includes(providerName as AuthProviderName)\n}\n\nfunction isCustomProviderAuthType(\n value: string,\n): value is CustomProviderAuthType {\n return CUSTOM_PROVIDER_AUTH_TYPES.includes(value as CustomProviderAuthType)\n}\n\nfunction isQuickProviderName(\n providerName: AuthProviderName,\n): providerName is QuickProviderName {\n return QUICK_PROVIDER_NAMES.includes(providerName as QuickProviderName)\n}\n\nasync function resolveProviderSelection(\n providerArg: string | undefined,\n): Promise<AuthProviderName> {\n const availableProviders = [...AUTH_PROVIDER_NAMES]\n\n if (providerArg !== undefined) {\n const providerName = providerArg.trim()\n if (!isAuthProviderName(providerName)) {\n throw new Error(\n `Unknown provider '${providerArg}'. Expected one of: ${availableProviders.join(\", \")}`,\n )\n }\n return providerName\n }\n\n if (availableProviders.length === 1) {\n return availableProviders[0]\n }\n\n const provider = await prompt(\"Select a provider to log in with\", {\n type: \"select\",\n options: availableProviders.map((providerName) => ({\n label: `${AUTH_PROVIDER_LABELS[providerName]} (${providerName})`,\n value: providerName,\n })),\n })\n\n if (!provider || !isAuthProviderName(provider)) {\n throw new Error(\"No provider selected\")\n }\n\n return provider\n}\n\nfunction assertCustomProviderName(providerName: string): void {\n if (!providerName) {\n throw new Error(\"Provider name must be a non-empty string\")\n }\n\n if (!/^[A-Za-z0-9][A-Za-z0-9_-]*$/u.test(providerName)) {\n throw new Error(\n \"Provider name must start with a letter or number and contain only letters, numbers, underscores, or hyphens\",\n )\n }\n\n if (providerName === \"copilot\" || providerName === \"codex\") {\n throw new Error(\n `Provider name '${providerName}' is reserved for a builtin provider`,\n )\n }\n}\n\nasync function promptRequiredText(\n message: string,\n fieldName: string,\n): Promise<string> {\n const value = await prompt(message, { type: \"text\" })\n const normalizedValue = typeof value === \"string\" ? value.trim() : \"\"\n if (!normalizedValue) {\n throw new Error(`${fieldName} must be a non-empty string`)\n }\n return normalizedValue\n}\n\nfunction canUseMaskedPrompt(): boolean {\n return Boolean(\n process.stdin.isTTY\n && process.stdout.isTTY\n && typeof process.stdin.setRawMode === \"function\",\n )\n}\n\nasync function promptMaskedText(message: string): Promise<string> {\n if (!canUseMaskedPrompt()) {\n const value = await prompt(message, { type: \"text\" })\n return typeof value === \"string\" ? value : \"\"\n }\n\n return await new Promise<string>((resolve, reject) => {\n let value = \"\"\n const rawModeWasEnabled = process.stdin.isRaw === true\n\n function cleanup(): void {\n process.stdin.off(\"data\", onData)\n process.stdin.setRawMode(rawModeWasEnabled)\n process.stdin.pause()\n }\n\n function finish(): void {\n cleanup()\n process.stdout.write(\"\\n\")\n resolve(value)\n }\n\n function cancel(): void {\n cleanup()\n process.stdout.write(\"\\n\")\n reject(new Error(\"Prompt cancelled\"))\n }\n\n function onData(chunk: Buffer): void {\n const input = chunk.toString(\"utf8\")\n\n if (input.startsWith(\"\\u001B\")) {\n return\n }\n\n for (const char of input) {\n if (char === \"\\u0003\") {\n cancel()\n return\n }\n\n if (char === \"\\r\" || char === \"\\n\") {\n finish()\n return\n }\n\n if (char === \"\\b\" || char === \"\\u007F\") {\n if (value.length > 0) {\n value = value.slice(0, -1)\n process.stdout.write(\"\\b \\b\")\n }\n continue\n }\n\n if (char >= \" \") {\n value += char\n process.stdout.write(\"*\")\n }\n }\n }\n\n process.stdout.write(`${message}: `)\n process.stdin.setRawMode(true)\n process.stdin.resume()\n process.stdin.on(\"data\", onData)\n })\n}\n\nasync function promptRequiredSecret(\n message: string,\n fieldName: string,\n): Promise<string> {\n const value = await promptMaskedText(message)\n const normalizedValue = value.trim()\n if (!normalizedValue) {\n throw new Error(`${fieldName} must be a non-empty string`)\n }\n return normalizedValue\n}\n\nasync function promptCustomProviderName(): Promise<string> {\n const providerName = await promptRequiredText(\n \"Enter provider name\",\n \"Provider name\",\n )\n assertCustomProviderName(providerName)\n return providerName\n}\n\nasync function promptCustomProviderType(): Promise<ProviderType> {\n const providerType = await prompt(\"Select provider type\", {\n type: \"select\",\n options: SUPPORTED_PROVIDER_TYPES.map((type) => ({\n label: type,\n value: type,\n })),\n })\n\n if (\n typeof providerType !== \"string\"\n || !isSupportedProviderType(providerType)\n ) {\n throw new Error(\"No provider type selected\")\n }\n\n return providerType\n}\n\nasync function promptQuickProviderType(\n defaultType: ProviderType,\n): Promise<ProviderType> {\n const providerType = await prompt(\n `Select provider type (default: ${defaultType})`,\n {\n type: \"select\",\n options: [\n {\n label: `Default (${defaultType})`,\n value: QUICK_PROVIDER_DEFAULT_TYPE_OPTION,\n },\n ...SUPPORTED_PROVIDER_TYPES.map((type) => ({\n label: type,\n value: type,\n })),\n ],\n },\n )\n\n if (providerType === QUICK_PROVIDER_DEFAULT_TYPE_OPTION) {\n return defaultType\n }\n\n if (\n typeof providerType === \"string\"\n && isSupportedProviderType(providerType)\n ) {\n return providerType\n }\n\n throw new Error(\"No provider type selected\")\n}\n\nfunction getDefaultProviderAuthType(\n providerType: ProviderType,\n): ProviderAuthType {\n return providerType === \"anthropic\" ? \"x-api-key\" : \"authorization\"\n}\n\nasync function promptCustomProviderAuthType(\n providerType: ProviderType,\n): Promise<ProviderAuthType | undefined> {\n const defaultAuthType = getDefaultProviderAuthType(providerType)\n const authType = await prompt(\"Select provider auth type\", {\n type: \"select\",\n options: [\n {\n label: `Default (${defaultAuthType})`,\n value: CUSTOM_PROVIDER_AUTH_TYPE_OPTION,\n },\n ...CUSTOM_PROVIDER_AUTH_TYPES.map((value) => ({\n label: value,\n value,\n })),\n ],\n })\n\n if (authType === CUSTOM_PROVIDER_AUTH_TYPE_OPTION) {\n return undefined\n }\n\n if (typeof authType === \"string\" && isCustomProviderAuthType(authType)) {\n return authType\n }\n\n throw new Error(\"No provider auth type selected\")\n}\n\nasync function promptQuickProviderBaseUrl(\n defaultBaseUrl: string,\n): Promise<string> {\n const value = await prompt(\n `Enter provider baseUrl (default: ${defaultBaseUrl})`,\n {\n type: \"text\",\n default: defaultBaseUrl,\n initial: defaultBaseUrl,\n },\n )\n const baseUrl = normalizeProviderBaseUrl(\n typeof value === \"string\" && value.trim() ? value : defaultBaseUrl,\n )\n if (!baseUrl) {\n throw new Error(\"baseUrl must be a non-empty string\")\n }\n\n return baseUrl\n}\n\nfunction buildCustomProviderConfig(\n existingProviderConfig: ProviderConfig,\n options: {\n apiKey: string\n authType?: ProviderAuthType\n baseUrl: string\n pricingCurrency?: string\n type: ProviderType\n },\n): ProviderConfig {\n return {\n type: options.type,\n enabled: true,\n baseUrl: options.baseUrl,\n apiKey: options.apiKey,\n ...(options.authType ? { authType: options.authType } : {}),\n pricingCurrency:\n options.pricingCurrency ?? existingProviderConfig.pricingCurrency,\n ...(existingProviderConfig.models ?\n { models: existingProviderConfig.models }\n : {}),\n }\n}\n\nasync function configureCustomProvider(): Promise<void> {\n const providerName = await promptCustomProviderName()\n const type = await promptCustomProviderType()\n const baseUrl = normalizeProviderBaseUrl(\n await promptRequiredText(\"Enter provider baseUrl\", \"baseUrl\"),\n )\n if (!baseUrl) {\n throw new Error(\"baseUrl must be a non-empty string\")\n }\n\n const apiKey = await promptRequiredSecret(\"Enter provider apiKey\", \"apiKey\")\n const authType = await promptCustomProviderAuthType(type)\n const existingProviderConfig = getRawProviderConfig(providerName) ?? {}\n\n setProviderConfig(\n providerName,\n buildCustomProviderConfig(existingProviderConfig, {\n apiKey,\n authType,\n baseUrl,\n type,\n }),\n )\n\n consola.success(\n `Custom provider '${providerName}' written to ${PATHS.CONFIG_PATH}`,\n )\n}\n\nasync function configureQuickProvider(\n providerName: QuickProviderName,\n): Promise<void> {\n const defaultProviderConfig = QUICK_PROVIDER_CONFIGS[providerName]\n const apiKey = await promptRequiredSecret(\n `Enter ${providerName} apiKey`,\n \"apiKey\",\n )\n const type =\n defaultProviderConfig.editableType ?\n await promptQuickProviderType(defaultProviderConfig.type)\n : defaultProviderConfig.type\n const baseUrl = await promptQuickProviderBaseUrl(\n defaultProviderConfig.baseUrl,\n )\n const existingProviderConfig = getRawProviderConfig(providerName) ?? {}\n\n setProviderConfig(\n providerName,\n buildCustomProviderConfig(existingProviderConfig, {\n apiKey,\n baseUrl,\n pricingCurrency: defaultProviderConfig.pricingCurrency,\n type,\n }),\n )\n\n consola.success(\n `${AUTH_PROVIDER_LABELS[providerName]} provider '${providerName}' written to ${PATHS.CONFIG_PATH}`,\n )\n}\n\nasync function loginWithCodex(): Promise<void> {\n const credentials = await loginCodex({\n onAuth(info) {\n consola.info(\"Open the following URL to authenticate with Codex:\")\n consola.log(info.url)\n if (info.instructions) {\n consola.info(info.instructions)\n }\n },\n onPrompt(message) {\n return prompt(message, { type: \"text\" }).then((value) => value ?? \"\")\n },\n onProgress(message) {\n consola.debug(message)\n },\n })\n\n await persistCodexCredentials(credentials, { enableProvider: true })\n consola.success(\n `Codex provider config written to ${PATHS.CONFIG_PATH} and credentials written to ${PATHS.CODEX_CREDENTIAL_PATH}`,\n )\n}\n\nasync function loginWithProvider(provider: AuthProviderName): Promise<void> {\n if (provider === \"copilot\") {\n await setupGitHubToken({ force: true })\n consola.success(\"GitHub token written to\", PATHS.GITHUB_TOKEN_PATH)\n return\n }\n\n if (provider === \"codex\") {\n await loginWithCodex()\n return\n }\n\n if (isQuickProviderName(provider)) {\n await configureQuickProvider(provider)\n return\n }\n\n await configureCustomProvider()\n}\n\nexport async function runProviderSetup(): Promise<void> {\n const provider = await resolveProviderSelection(undefined)\n consola.info(`Logging in with ${AUTH_PROVIDER_LABELS[provider]}`)\n await loginWithProvider(provider)\n}\n\nexport async function runAuthLogin(options: RunAuthOptions): Promise<void> {\n const tlsModule = await import(\"./lib/tls\")\n tlsModule.enableSystemCACompat()\n\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.showToken = options.showToken\n\n await ensurePaths()\n const provider = await resolveProviderSelection(options.provider)\n\n consola.info(`Logging in with ${AUTH_PROVIDER_LABELS[provider]}`)\n await loginWithProvider(provider)\n}\n\nconst authKeysArgs = {\n add: {\n alias: \"a\",\n type: \"string\",\n description: \"Add an API key for gateway authentication\",\n },\n remove: {\n alias: \"r\",\n type: \"string\",\n description: \"Remove an API key\",\n },\n list: {\n alias: \"l\",\n type: \"boolean\",\n default: false,\n description: \"List configured API keys\",\n },\n clear: {\n type: \"boolean\",\n default: false,\n description: \"Remove all configured API keys\",\n },\n} as const\n\ninterface RunAuthKeysOptions {\n add?: string\n remove?: string\n list?: boolean\n clear?: boolean\n}\n\nfunction normalizeAuthKeyValue(value: string): string {\n const normalizedKey = value.trim()\n if (!normalizedKey) {\n throw new Error(\"API key must be a non-empty string\")\n }\n return normalizedKey\n}\n\nexport async function runAuthKeys(options: RunAuthKeysOptions): Promise<void> {\n const tlsModule = await import(\"./lib/tls\")\n tlsModule.enableSystemCACompat()\n\n await ensurePaths()\n\n const operations = [\n ...(options.add !== undefined ? [\"add\"] : []),\n ...(options.remove !== undefined ? [\"remove\"] : []),\n ...(options.list ? [\"list\"] : []),\n ...(options.clear ? [\"clear\"] : []),\n ]\n if (operations.length > 1) {\n throw new Error(\n \"Use only one of --add, --remove, --list, or --clear per invocation\",\n )\n }\n\n const operation = operations[0] ?? \"list\"\n\n if (operation === \"add\") {\n const apiKey = normalizeAuthKeyValue(options.add ?? \"\")\n const currentKeys = getConfiguredApiKeys()\n if (currentKeys.includes(apiKey)) {\n consola.info(\n `API key already configured. ${currentKeys.length} API key(s) configured.`,\n )\n return\n }\n const storedKeys = setConfiguredApiKeys([...currentKeys, apiKey])\n consola.success(\n `API key added to ${PATHS.CONFIG_PATH}. ${storedKeys.length} API key(s) configured.`,\n )\n return\n }\n\n if (operation === \"remove\") {\n const apiKey = normalizeAuthKeyValue(options.remove ?? \"\")\n const currentKeys = getConfiguredApiKeys()\n if (!currentKeys.includes(apiKey)) {\n consola.info(\n `API key not found. ${currentKeys.length} API key(s) configured.`,\n )\n return\n }\n const storedKeys = setConfiguredApiKeys(\n currentKeys.filter((key) => key !== apiKey),\n )\n consola.success(\n `API key removed from ${PATHS.CONFIG_PATH}. ${storedKeys.length} API key(s) configured.`,\n )\n return\n }\n\n if (operation === \"clear\") {\n setConfiguredApiKeys([])\n consola.success(`Removed all API keys from ${PATHS.CONFIG_PATH}.`)\n return\n }\n\n const currentKeys = getConfiguredApiKeys()\n if (currentKeys.length === 0) {\n consola.info(\n \"No API keys configured. Run `npx copilot-api auth keys --add <key>` to add one.\",\n )\n return\n }\n consola.info(\"Configured API keys:\")\n for (const key of currentKeys) {\n consola.info(`- ${key}`)\n }\n}\n\nconst authLogin = defineCommand({\n meta: {\n name: \"login\",\n description:\n \"Authenticate or configure a provider without running the server\",\n },\n args: authArgs,\n run({ args }) {\n return runAuthLogin({\n provider: args.provider,\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n\nconst authKeys = defineCommand({\n meta: {\n name: \"keys\",\n description: \"Manage gateway API keys (auth.apiKeys) in the config\",\n },\n args: authKeysArgs,\n run({ args }) {\n return runAuthKeys({\n add: args.add,\n remove: args.remove,\n list: args.list,\n clear: args.clear,\n })\n },\n})\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run authentication flows without running the server\",\n },\n args: authArgs,\n subCommands: {\n login: authLogin,\n keys: authKeys,\n },\n run({ args }) {\n if ((args._[0] ?? \"\").trim()) {\n return\n }\n\n return runAuthLogin({\n provider: args.provider,\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"auth-LJ5y6v6e.js","names":[],"sources":["../src/lib/quick-providers.ts","../src/lib/interactive-prompt.ts","../src/auth.ts"],"sourcesContent":["import type { ProviderType } from \"./config\"\n\ninterface QuickProviderConfig {\n type: ProviderType\n baseUrl: string\n pricingCurrency: string\n editableType: boolean\n}\n\nexport const QUICK_PROVIDER_CONFIGS = {\n \"opencode-go\": {\n type: \"openai-compatible\",\n baseUrl: \"https://opencode.ai/zen/go\",\n pricingCurrency: \"USD\",\n editableType: false,\n },\n kimi: {\n type: \"openai-compatible\",\n baseUrl: \"https://api.kimi.com/coding\",\n pricingCurrency: \"USD\",\n editableType: true,\n },\n deepseek: {\n type: \"anthropic\",\n baseUrl: \"https://api.deepseek.com/anthropic\",\n pricingCurrency: \"CNY\",\n editableType: true,\n },\n dashscope: {\n type: \"openai-compatible\",\n baseUrl: \"https://dashscope.aliyuncs.com/compatible-mode\",\n pricingCurrency: \"CNY\",\n editableType: true,\n },\n openrouter: {\n type: \"anthropic\",\n baseUrl: \"https://openrouter.ai/api\",\n pricingCurrency: \"USD\",\n editableType: false,\n },\n} satisfies Record<string, QuickProviderConfig>\n\nexport type QuickProviderName = keyof typeof QUICK_PROVIDER_CONFIGS\n","import consola from \"consola\"\n\ninterface PromptSelectOption {\n label: string\n value: string\n hint?: string\n}\n\ninterface TextPromptOptions {\n type?: \"text\"\n default?: string\n initial?: string\n placeholder?: string\n}\n\ninterface SelectPromptOptions {\n type: \"select\"\n initial?: string\n options: Array<string | PromptSelectOption>\n}\n\nexport type InteractivePromptOptions = SelectPromptOptions | TextPromptOptions\n\ninterface ClackSelectOptions {\n message: string\n initialValue?: string\n options: Array<PromptSelectOption>\n}\n\ninterface ClackTextOptions {\n message: string\n defaultValue?: string\n initialValue?: string\n placeholder?: string\n}\n\nexport interface ClackPromptBackend {\n isCancel(value: unknown): boolean\n select(options: ClackSelectOptions): Promise<string | symbol>\n text(options: ClackTextOptions): Promise<string | symbol>\n}\n\ninterface PromptRuntime {\n bunVersion?: string\n platform: NodeJS.Platform\n stdinIsTTY?: boolean\n stdoutIsTTY?: boolean\n stdoutIsTTYStream?: boolean\n}\n\n// Consola 3.4.2 bundles a prompt implementation that writes keyboard input to\n// tty fd 0. Bun treats that as a real stdin write on Windows and throws EPIPE.\nexport function shouldUseClackPrompt(\n runtime: PromptRuntime = {\n bunVersion: process.versions.bun,\n platform: process.platform,\n stdinIsTTY: process.stdin.isTTY,\n stdoutIsTTY: process.stdout.isTTY,\n stdoutIsTTYStream: typeof process.stdout.getColorDepth === \"function\",\n },\n): boolean {\n return Boolean(\n runtime.platform === \"win32\"\n && runtime.bunVersion\n && runtime.stdinIsTTY\n && runtime.stdoutIsTTY\n && runtime.stdoutIsTTYStream,\n )\n}\n\nfunction getCancelValue(options: InteractivePromptOptions): string | undefined {\n return options.type === \"select\" ?\n options.initial\n : (options.default ?? options.initial)\n}\n\nexport async function promptWithClack(\n message: string,\n options: InteractivePromptOptions,\n backend: ClackPromptBackend,\n): Promise<string | undefined> {\n if (options.type === \"select\") {\n const value = await backend.select({\n message,\n options: options.options.map((option) =>\n typeof option === \"string\" ? { label: option, value: option } : option,\n ),\n initialValue: options.initial,\n })\n if (backend.isCancel(value)) {\n return getCancelValue(options)\n }\n return typeof value === \"string\" ? value : undefined\n }\n\n const value = await backend.text({\n message,\n defaultValue: options.default,\n initialValue: options.initial,\n placeholder: options.placeholder,\n })\n if (backend.isCancel(value)) {\n return getCancelValue(options)\n }\n return typeof value === \"string\" ? value : undefined\n}\n\nexport async function prompt(\n message: string,\n options: InteractivePromptOptions,\n): Promise<string | undefined> {\n if (!shouldUseClackPrompt()) {\n if (options.type === \"select\") {\n const value = await consola.prompt(message, options)\n return typeof value === \"string\" ? value : undefined\n }\n return await consola.prompt(message, options)\n }\n\n const clack = await import(\"@clack/prompts\")\n return await promptWithClack(message, options, clack)\n}\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport {\n getRawProviderConfig,\n isSupportedProviderType,\n normalizeProviderBaseUrl,\n setProviderConfig,\n setConfiguredApiKeys,\n SUPPORTED_PROVIDER_TYPES,\n type ProviderAuthType,\n type ProviderConfig,\n type ProviderType,\n} from \"./lib/config\"\nimport { loginCodex } from \"./lib/oauth/codex\"\nimport { PATHS, ensurePaths } from \"./lib/paths\"\nimport { getConfiguredApiKeys } from \"./lib/request-auth\"\nimport {\n QUICK_PROVIDER_CONFIGS,\n type QuickProviderName,\n} from \"./lib/quick-providers\"\nimport { prompt } from \"./lib/interactive-prompt\"\nimport { state } from \"./lib/state\"\nimport { persistCodexCredentials, setupGitHubToken } from \"./lib/token\"\n\ninterface RunAuthOptions {\n provider?: string\n verbose: boolean\n showToken: boolean\n}\n\nconst authArgs = {\n provider: {\n type: \"string\",\n description:\n \"Provider to log in with or configure (copilot, codex, opencode-go, kimi, deepseek, dashscope, openrouter, custom)\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show provider access token on auth\",\n },\n} as const\n\nconst BUILTIN_PROVIDER_NAMES = [\"copilot\", \"codex\"] as const\nconst QUICK_PROVIDER_NAMES = Object.keys(\n QUICK_PROVIDER_CONFIGS,\n) as Array<QuickProviderName>\nconst AUTH_PROVIDER_NAMES = [\n ...BUILTIN_PROVIDER_NAMES,\n ...QUICK_PROVIDER_NAMES,\n \"custom\",\n] as const\nconst CUSTOM_PROVIDER_AUTH_TYPE_OPTION = \"__default__\"\nconst QUICK_PROVIDER_DEFAULT_TYPE_OPTION = \"__default__\"\nconst CUSTOM_PROVIDER_AUTH_TYPES = [\"x-api-key\", \"authorization\"] as const\n\ntype BuiltinProviderName = (typeof BUILTIN_PROVIDER_NAMES)[number]\ntype AuthProviderName = (typeof AUTH_PROVIDER_NAMES)[number]\ntype CustomProviderAuthType = (typeof CUSTOM_PROVIDER_AUTH_TYPES)[number]\n\nconst BUILTIN_PROVIDER_LABELS: Record<BuiltinProviderName, string> = {\n copilot: \"GitHub Copilot\",\n codex: \"OpenAI Codex\",\n}\nconst AUTH_PROVIDER_LABELS: Record<AuthProviderName, string> = {\n ...BUILTIN_PROVIDER_LABELS,\n \"opencode-go\": \"OpenCode Go\",\n kimi: \"Kimi\",\n deepseek: \"DeepSeek\",\n dashscope: \"DashScope\",\n openrouter: \"OpenRouter\",\n custom: \"Custom provider\",\n}\n\nfunction isAuthProviderName(\n providerName: string,\n): providerName is AuthProviderName {\n return AUTH_PROVIDER_NAMES.includes(providerName as AuthProviderName)\n}\n\nfunction isCustomProviderAuthType(\n value: string,\n): value is CustomProviderAuthType {\n return CUSTOM_PROVIDER_AUTH_TYPES.includes(value as CustomProviderAuthType)\n}\n\nfunction isQuickProviderName(\n providerName: AuthProviderName,\n): providerName is QuickProviderName {\n return QUICK_PROVIDER_NAMES.includes(providerName as QuickProviderName)\n}\n\nasync function resolveProviderSelection(\n providerArg: string | undefined,\n): Promise<AuthProviderName> {\n const availableProviders = [...AUTH_PROVIDER_NAMES]\n\n if (providerArg !== undefined) {\n const providerName = providerArg.trim()\n if (!isAuthProviderName(providerName)) {\n throw new Error(\n `Unknown provider '${providerArg}'. Expected one of: ${availableProviders.join(\", \")}`,\n )\n }\n return providerName\n }\n\n if (availableProviders.length === 1) {\n return availableProviders[0]\n }\n\n const provider = await prompt(\"Select a provider to log in with\", {\n type: \"select\",\n options: availableProviders.map((providerName) => ({\n label: `${AUTH_PROVIDER_LABELS[providerName]} (${providerName})`,\n value: providerName,\n })),\n })\n\n if (!provider || !isAuthProviderName(provider)) {\n throw new Error(\"No provider selected\")\n }\n\n return provider\n}\n\nfunction assertCustomProviderName(providerName: string): void {\n if (!providerName) {\n throw new Error(\"Provider name must be a non-empty string\")\n }\n\n if (!/^[A-Za-z0-9][A-Za-z0-9_-]*$/u.test(providerName)) {\n throw new Error(\n \"Provider name must start with a letter or number and contain only letters, numbers, underscores, or hyphens\",\n )\n }\n\n if (providerName === \"copilot\" || providerName === \"codex\") {\n throw new Error(\n `Provider name '${providerName}' is reserved for a builtin provider`,\n )\n }\n}\n\nasync function promptRequiredText(\n message: string,\n fieldName: string,\n): Promise<string> {\n const value = await prompt(message, { type: \"text\" })\n const normalizedValue = typeof value === \"string\" ? value.trim() : \"\"\n if (!normalizedValue) {\n throw new Error(`${fieldName} must be a non-empty string`)\n }\n return normalizedValue\n}\n\nfunction canUseMaskedPrompt(): boolean {\n return Boolean(\n process.stdin.isTTY\n && process.stdout.isTTY\n && typeof process.stdin.setRawMode === \"function\",\n )\n}\n\nasync function promptMaskedText(message: string): Promise<string> {\n if (!canUseMaskedPrompt()) {\n const value = await prompt(message, { type: \"text\" })\n return typeof value === \"string\" ? value : \"\"\n }\n\n return await new Promise<string>((resolve, reject) => {\n let value = \"\"\n const rawModeWasEnabled = process.stdin.isRaw === true\n\n function cleanup(): void {\n process.stdin.off(\"data\", onData)\n process.stdin.setRawMode(rawModeWasEnabled)\n process.stdin.pause()\n }\n\n function finish(): void {\n cleanup()\n process.stdout.write(\"\\n\")\n resolve(value)\n }\n\n function cancel(): void {\n cleanup()\n process.stdout.write(\"\\n\")\n reject(new Error(\"Prompt cancelled\"))\n }\n\n function onData(chunk: Buffer): void {\n const input = chunk.toString(\"utf8\")\n\n if (input.startsWith(\"\\u001B\")) {\n return\n }\n\n for (const char of input) {\n if (char === \"\\u0003\") {\n cancel()\n return\n }\n\n if (char === \"\\r\" || char === \"\\n\") {\n finish()\n return\n }\n\n if (char === \"\\b\" || char === \"\\u007F\") {\n if (value.length > 0) {\n value = value.slice(0, -1)\n process.stdout.write(\"\\b \\b\")\n }\n continue\n }\n\n if (char >= \" \") {\n value += char\n process.stdout.write(\"*\")\n }\n }\n }\n\n process.stdout.write(`${message}: `)\n process.stdin.setRawMode(true)\n process.stdin.resume()\n process.stdin.on(\"data\", onData)\n })\n}\n\nasync function promptRequiredSecret(\n message: string,\n fieldName: string,\n): Promise<string> {\n const value = await promptMaskedText(message)\n const normalizedValue = value.trim()\n if (!normalizedValue) {\n throw new Error(`${fieldName} must be a non-empty string`)\n }\n return normalizedValue\n}\n\nasync function promptCustomProviderName(): Promise<string> {\n const providerName = await promptRequiredText(\n \"Enter provider name\",\n \"Provider name\",\n )\n assertCustomProviderName(providerName)\n return providerName\n}\n\nasync function promptCustomProviderType(): Promise<ProviderType> {\n const providerType = await prompt(\"Select provider type\", {\n type: \"select\",\n options: SUPPORTED_PROVIDER_TYPES.map((type) => ({\n label: type,\n value: type,\n })),\n })\n\n if (\n typeof providerType !== \"string\"\n || !isSupportedProviderType(providerType)\n ) {\n throw new Error(\"No provider type selected\")\n }\n\n return providerType\n}\n\nasync function promptQuickProviderType(\n defaultType: ProviderType,\n): Promise<ProviderType> {\n const providerType = await prompt(\n `Select provider type (default: ${defaultType})`,\n {\n type: \"select\",\n options: [\n {\n label: `Default (${defaultType})`,\n value: QUICK_PROVIDER_DEFAULT_TYPE_OPTION,\n },\n ...SUPPORTED_PROVIDER_TYPES.map((type) => ({\n label: type,\n value: type,\n })),\n ],\n },\n )\n\n if (providerType === QUICK_PROVIDER_DEFAULT_TYPE_OPTION) {\n return defaultType\n }\n\n if (\n typeof providerType === \"string\"\n && isSupportedProviderType(providerType)\n ) {\n return providerType\n }\n\n throw new Error(\"No provider type selected\")\n}\n\nfunction getDefaultProviderAuthType(\n providerType: ProviderType,\n): ProviderAuthType {\n return providerType === \"anthropic\" ? \"x-api-key\" : \"authorization\"\n}\n\nasync function promptCustomProviderAuthType(\n providerType: ProviderType,\n): Promise<ProviderAuthType | undefined> {\n const defaultAuthType = getDefaultProviderAuthType(providerType)\n const authType = await prompt(\"Select provider auth type\", {\n type: \"select\",\n options: [\n {\n label: `Default (${defaultAuthType})`,\n value: CUSTOM_PROVIDER_AUTH_TYPE_OPTION,\n },\n ...CUSTOM_PROVIDER_AUTH_TYPES.map((value) => ({\n label: value,\n value,\n })),\n ],\n })\n\n if (authType === CUSTOM_PROVIDER_AUTH_TYPE_OPTION) {\n return undefined\n }\n\n if (typeof authType === \"string\" && isCustomProviderAuthType(authType)) {\n return authType\n }\n\n throw new Error(\"No provider auth type selected\")\n}\n\nasync function promptQuickProviderBaseUrl(\n defaultBaseUrl: string,\n): Promise<string> {\n const value = await prompt(\n `Enter provider baseUrl (default: ${defaultBaseUrl})`,\n {\n type: \"text\",\n default: defaultBaseUrl,\n initial: defaultBaseUrl,\n },\n )\n const baseUrl = normalizeProviderBaseUrl(\n typeof value === \"string\" && value.trim() ? value : defaultBaseUrl,\n )\n if (!baseUrl) {\n throw new Error(\"baseUrl must be a non-empty string\")\n }\n\n return baseUrl\n}\n\nfunction buildCustomProviderConfig(\n existingProviderConfig: ProviderConfig,\n options: {\n apiKey: string\n authType?: ProviderAuthType\n baseUrl: string\n pricingCurrency?: string\n type: ProviderType\n },\n): ProviderConfig {\n return {\n type: options.type,\n enabled: true,\n baseUrl: options.baseUrl,\n apiKey: options.apiKey,\n ...(options.authType ? { authType: options.authType } : {}),\n pricingCurrency:\n options.pricingCurrency ?? existingProviderConfig.pricingCurrency,\n ...(existingProviderConfig.models ?\n { models: existingProviderConfig.models }\n : {}),\n }\n}\n\nasync function configureCustomProvider(): Promise<void> {\n const providerName = await promptCustomProviderName()\n const type = await promptCustomProviderType()\n const baseUrl = normalizeProviderBaseUrl(\n await promptRequiredText(\"Enter provider baseUrl\", \"baseUrl\"),\n )\n if (!baseUrl) {\n throw new Error(\"baseUrl must be a non-empty string\")\n }\n\n const apiKey = await promptRequiredSecret(\"Enter provider apiKey\", \"apiKey\")\n const authType = await promptCustomProviderAuthType(type)\n const existingProviderConfig = getRawProviderConfig(providerName) ?? {}\n\n setProviderConfig(\n providerName,\n buildCustomProviderConfig(existingProviderConfig, {\n apiKey,\n authType,\n baseUrl,\n type,\n }),\n )\n\n consola.success(\n `Custom provider '${providerName}' written to ${PATHS.CONFIG_PATH}`,\n )\n}\n\nasync function configureQuickProvider(\n providerName: QuickProviderName,\n): Promise<void> {\n const defaultProviderConfig = QUICK_PROVIDER_CONFIGS[providerName]\n const apiKey = await promptRequiredSecret(\n `Enter ${providerName} apiKey`,\n \"apiKey\",\n )\n const type =\n defaultProviderConfig.editableType ?\n await promptQuickProviderType(defaultProviderConfig.type)\n : defaultProviderConfig.type\n const baseUrl = await promptQuickProviderBaseUrl(\n defaultProviderConfig.baseUrl,\n )\n const existingProviderConfig = getRawProviderConfig(providerName) ?? {}\n\n setProviderConfig(\n providerName,\n buildCustomProviderConfig(existingProviderConfig, {\n apiKey,\n baseUrl,\n pricingCurrency: defaultProviderConfig.pricingCurrency,\n type,\n }),\n )\n\n consola.success(\n `${AUTH_PROVIDER_LABELS[providerName]} provider '${providerName}' written to ${PATHS.CONFIG_PATH}`,\n )\n}\n\nasync function loginWithCodex(): Promise<void> {\n const credentials = await loginCodex({\n onAuth(info) {\n consola.info(\"Open the following URL to authenticate with Codex:\")\n consola.log(info.url)\n if (info.instructions) {\n consola.info(info.instructions)\n }\n },\n onPrompt(message) {\n return prompt(message, { type: \"text\" }).then((value) => value ?? \"\")\n },\n onProgress(message) {\n consola.debug(message)\n },\n })\n\n await persistCodexCredentials(credentials, { enableProvider: true })\n consola.success(\n `Codex provider config written to ${PATHS.CONFIG_PATH} and credentials written to ${PATHS.CODEX_CREDENTIAL_PATH}`,\n )\n}\n\nasync function loginWithProvider(provider: AuthProviderName): Promise<void> {\n if (provider === \"copilot\") {\n await setupGitHubToken({ force: true })\n consola.success(\"GitHub token written to\", PATHS.GITHUB_TOKEN_PATH)\n return\n }\n\n if (provider === \"codex\") {\n await loginWithCodex()\n return\n }\n\n if (isQuickProviderName(provider)) {\n await configureQuickProvider(provider)\n return\n }\n\n await configureCustomProvider()\n}\n\nexport async function runProviderSetup(): Promise<void> {\n const provider = await resolveProviderSelection(undefined)\n consola.info(`Logging in with ${AUTH_PROVIDER_LABELS[provider]}`)\n await loginWithProvider(provider)\n}\n\nexport async function runAuthLogin(options: RunAuthOptions): Promise<void> {\n const tlsModule = await import(\"./lib/tls\")\n tlsModule.enableSystemCACompat()\n\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.showToken = options.showToken\n\n await ensurePaths()\n const provider = await resolveProviderSelection(options.provider)\n\n consola.info(`Logging in with ${AUTH_PROVIDER_LABELS[provider]}`)\n await loginWithProvider(provider)\n}\n\nconst authKeysArgs = {\n add: {\n alias: \"a\",\n type: \"string\",\n description: \"Add an API key for gateway authentication\",\n },\n remove: {\n alias: \"r\",\n type: \"string\",\n description: \"Remove an API key\",\n },\n list: {\n alias: \"l\",\n type: \"boolean\",\n default: false,\n description: \"List configured API keys\",\n },\n clear: {\n type: \"boolean\",\n default: false,\n description: \"Remove all configured API keys\",\n },\n} as const\n\ninterface RunAuthKeysOptions {\n add?: string\n remove?: string\n list?: boolean\n clear?: boolean\n}\n\nfunction normalizeAuthKeyValue(value: string): string {\n const normalizedKey = value.trim()\n if (!normalizedKey) {\n throw new Error(\"API key must be a non-empty string\")\n }\n return normalizedKey\n}\n\nexport async function runAuthKeys(options: RunAuthKeysOptions): Promise<void> {\n const tlsModule = await import(\"./lib/tls\")\n tlsModule.enableSystemCACompat()\n\n await ensurePaths()\n\n const operations = [\n ...(options.add !== undefined ? [\"add\"] : []),\n ...(options.remove !== undefined ? [\"remove\"] : []),\n ...(options.list ? [\"list\"] : []),\n ...(options.clear ? [\"clear\"] : []),\n ]\n if (operations.length > 1) {\n throw new Error(\n \"Use only one of --add, --remove, --list, or --clear per invocation\",\n )\n }\n\n const operation = operations[0] ?? \"list\"\n\n if (operation === \"add\") {\n const apiKey = normalizeAuthKeyValue(options.add ?? \"\")\n const currentKeys = getConfiguredApiKeys()\n if (currentKeys.includes(apiKey)) {\n consola.info(\n `API key already configured. ${currentKeys.length} API key(s) configured.`,\n )\n return\n }\n const storedKeys = setConfiguredApiKeys([...currentKeys, apiKey])\n consola.success(\n `API key added to ${PATHS.CONFIG_PATH}. ${storedKeys.length} API key(s) configured.`,\n )\n return\n }\n\n if (operation === \"remove\") {\n const apiKey = normalizeAuthKeyValue(options.remove ?? \"\")\n const currentKeys = getConfiguredApiKeys()\n if (!currentKeys.includes(apiKey)) {\n consola.info(\n `API key not found. ${currentKeys.length} API key(s) configured.`,\n )\n return\n }\n const storedKeys = setConfiguredApiKeys(\n currentKeys.filter((key) => key !== apiKey),\n )\n consola.success(\n `API key removed from ${PATHS.CONFIG_PATH}. ${storedKeys.length} API key(s) configured.`,\n )\n return\n }\n\n if (operation === \"clear\") {\n setConfiguredApiKeys([])\n consola.success(`Removed all API keys from ${PATHS.CONFIG_PATH}.`)\n return\n }\n\n const currentKeys = getConfiguredApiKeys()\n if (currentKeys.length === 0) {\n consola.info(\n \"No API keys configured. Run `npx copilot-api auth keys --add <key>` to add one.\",\n )\n return\n }\n consola.info(\"Configured API keys:\")\n for (const key of currentKeys) {\n consola.info(`- ${key}`)\n }\n}\n\nconst authLogin = defineCommand({\n meta: {\n name: \"login\",\n description:\n \"Authenticate or configure a provider without running the server\",\n },\n args: authArgs,\n run({ args }) {\n return runAuthLogin({\n provider: args.provider,\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n\nconst authKeys = defineCommand({\n meta: {\n name: \"keys\",\n description: \"Manage gateway API keys (auth.apiKeys) in the config\",\n },\n args: authKeysArgs,\n run({ args }) {\n return runAuthKeys({\n add: args.add,\n remove: args.remove,\n list: args.list,\n clear: args.clear,\n })\n },\n})\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run authentication flows without running the server\",\n },\n args: authArgs,\n subCommands: {\n login: authLogin,\n keys: authKeys,\n },\n run({ args }) {\n if ((args._[0] ?? \"\").trim()) {\n return\n }\n\n return runAuthLogin({\n provider: args.provider,\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n"],"mappings":";;;;;AASA,MAAa,yBAAyB;CACpC,eAAe;EACb,MAAM;EACN,SAAS;EACT,iBAAiB;EACjB,cAAc;EACf;CACD,MAAM;EACJ,MAAM;EACN,SAAS;EACT,iBAAiB;EACjB,cAAc;EACf;CACD,UAAU;EACR,MAAM;EACN,SAAS;EACT,iBAAiB;EACjB,cAAc;EACf;CACD,WAAW;EACT,MAAM;EACN,SAAS;EACT,iBAAiB;EACjB,cAAc;EACf;CACD,YAAY;EACV,MAAM;EACN,SAAS;EACT,iBAAiB;EACjB,cAAc;EACf;CACF;;;ACYD,SAAgB,qBACd,UAAyB;CACvB,YAAY,QAAQ,SAAS;CAC7B,UAAU,QAAQ;CAClB,YAAY,QAAQ,MAAM;CAC1B,aAAa,QAAQ,OAAO;CAC5B,mBAAmB,OAAO,QAAQ,OAAO,kBAAkB;CAC5D,EACQ;CACT,OAAO,QACL,QAAQ,aAAa,WAChB,QAAQ,cACR,QAAQ,cACR,QAAQ,eACR,QAAQ,kBACd;;AAGH,SAAS,eAAe,SAAuD;CAC7E,OAAO,QAAQ,SAAS,WACpB,QAAQ,UACP,QAAQ,WAAW,QAAQ;;AAGlC,eAAsB,gBACpB,SACA,SACA,SAC6B;CAC7B,IAAI,QAAQ,SAAS,UAAU;EAC7B,MAAM,QAAQ,MAAM,QAAQ,OAAO;GACjC;GACA,SAAS,QAAQ,QAAQ,KAAK,WAC5B,OAAO,WAAW,WAAW;IAAE,OAAO;IAAQ,OAAO;IAAQ,GAAG,OACjE;GACD,cAAc,QAAQ;GACvB,CAAC;EACF,IAAI,QAAQ,SAAS,MAAM,EACzB,OAAO,eAAe,QAAQ;EAEhC,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;;CAG7C,MAAM,QAAQ,MAAM,QAAQ,KAAK;EAC/B;EACA,cAAc,QAAQ;EACtB,cAAc,QAAQ;EACtB,aAAa,QAAQ;EACtB,CAAC;CACF,IAAI,QAAQ,SAAS,MAAM,EACzB,OAAO,eAAe,QAAQ;CAEhC,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;;AAG7C,eAAsB,OACpB,SACA,SAC6B;CAC7B,IAAI,CAAC,sBAAsB,EAAE;EAC3B,IAAI,QAAQ,SAAS,UAAU;GAC7B,MAAM,QAAQ,MAAM,QAAQ,OAAO,SAAS,QAAQ;GACpD,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;;EAE7C,OAAO,MAAM,QAAQ,OAAO,SAAS,QAAQ;;CAI/C,OAAO,MAAM,gBAAgB,SAAS,SAAS,MAD3B,OAAO,kBAC0B;;;;ACvFvD,MAAM,WAAW;CACf,UAAU;EACR,MAAM;EACN,aACE;EACH;CACD,SAAS;EACP,OAAO;EACP,MAAM;EACN,SAAS;EACT,aAAa;EACd;CACD,cAAc;EACZ,MAAM;EACN,SAAS;EACT,aAAa;EACd;CACF;AAED,MAAM,yBAAyB,CAAC,WAAW,QAAQ;AACnD,MAAM,uBAAuB,OAAO,KAClC,uBACD;AACD,MAAM,sBAAsB;CAC1B,GAAG;CACH,GAAG;CACH;CACD;AACD,MAAM,mCAAmC;AACzC,MAAM,qCAAqC;AAC3C,MAAM,6BAA6B,CAAC,aAAa,gBAAgB;AAUjE,MAAM,uBAAyD;CAH7D,SAAS;CACT,OAAO;CAIP,eAAe;CACf,MAAM;CACN,UAAU;CACV,WAAW;CACX,YAAY;CACZ,QAAQ;CACT;AAED,SAAS,mBACP,cACkC;CAClC,OAAO,oBAAoB,SAAS,aAAiC;;AAGvE,SAAS,yBACP,OACiC;CACjC,OAAO,2BAA2B,SAAS,MAAgC;;AAG7E,SAAS,oBACP,cACmC;CACnC,OAAO,qBAAqB,SAAS,aAAkC;;AAGzE,eAAe,yBACb,aAC2B;CAC3B,MAAM,qBAAqB,CAAC,GAAG,oBAAoB;CAEnD,IAAI,gBAAgB,KAAA,GAAW;EAC7B,MAAM,eAAe,YAAY,MAAM;EACvC,IAAI,CAAC,mBAAmB,aAAa,EACnC,MAAM,IAAI,MACR,qBAAqB,YAAY,sBAAsB,mBAAmB,KAAK,KAAK,GACrF;EAEH,OAAO;;CAGT,IAAI,mBAAmB,WAAW,GAChC,OAAO,mBAAmB;CAG5B,MAAM,WAAW,MAAM,OAAO,oCAAoC;EAChE,MAAM;EACN,SAAS,mBAAmB,KAAK,kBAAkB;GACjD,OAAO,GAAG,qBAAqB,cAAc,IAAI,aAAa;GAC9D,OAAO;GACR,EAAE;EACJ,CAAC;CAEF,IAAI,CAAC,YAAY,CAAC,mBAAmB,SAAS,EAC5C,MAAM,IAAI,MAAM,uBAAuB;CAGzC,OAAO;;AAGT,SAAS,yBAAyB,cAA4B;CAC5D,IAAI,CAAC,cACH,MAAM,IAAI,MAAM,2CAA2C;CAG7D,IAAI,CAAC,+BAA+B,KAAK,aAAa,EACpD,MAAM,IAAI,MACR,8GACD;CAGH,IAAI,iBAAiB,aAAa,iBAAiB,SACjD,MAAM,IAAI,MACR,kBAAkB,aAAa,sCAChC;;AAIL,eAAe,mBACb,SACA,WACiB;CACjB,MAAM,QAAQ,MAAM,OAAO,SAAS,EAAE,MAAM,QAAQ,CAAC;CACrD,MAAM,kBAAkB,OAAO,UAAU,WAAW,MAAM,MAAM,GAAG;CACnE,IAAI,CAAC,iBACH,MAAM,IAAI,MAAM,GAAG,UAAU,6BAA6B;CAE5D,OAAO;;AAGT,SAAS,qBAA8B;CACrC,OAAO,QACL,QAAQ,MAAM,SACT,QAAQ,OAAO,SACf,OAAO,QAAQ,MAAM,eAAe,WAC1C;;AAGH,eAAe,iBAAiB,SAAkC;CAChE,IAAI,CAAC,oBAAoB,EAAE;EACzB,MAAM,QAAQ,MAAM,OAAO,SAAS,EAAE,MAAM,QAAQ,CAAC;EACrD,OAAO,OAAO,UAAU,WAAW,QAAQ;;CAG7C,OAAO,MAAM,IAAI,SAAiB,SAAS,WAAW;EACpD,IAAI,QAAQ;EACZ,MAAM,oBAAoB,QAAQ,MAAM,UAAU;EAElD,SAAS,UAAgB;GACvB,QAAQ,MAAM,IAAI,QAAQ,OAAO;GACjC,QAAQ,MAAM,WAAW,kBAAkB;GAC3C,QAAQ,MAAM,OAAO;;EAGvB,SAAS,SAAe;GACtB,SAAS;GACT,QAAQ,OAAO,MAAM,KAAK;GAC1B,QAAQ,MAAM;;EAGhB,SAAS,SAAe;GACtB,SAAS;GACT,QAAQ,OAAO,MAAM,KAAK;GAC1B,uBAAO,IAAI,MAAM,mBAAmB,CAAC;;EAGvC,SAAS,OAAO,OAAqB;GACnC,MAAM,QAAQ,MAAM,SAAS,OAAO;GAEpC,IAAI,MAAM,WAAW,OAAS,EAC5B;GAGF,KAAK,MAAM,QAAQ,OAAO;IACxB,IAAI,SAAS,KAAU;KACrB,QAAQ;KACR;;IAGF,IAAI,SAAS,QAAQ,SAAS,MAAM;KAClC,QAAQ;KACR;;IAGF,IAAI,SAAS,QAAQ,SAAS,KAAU;KACtC,IAAI,MAAM,SAAS,GAAG;MACpB,QAAQ,MAAM,MAAM,GAAG,GAAG;MAC1B,QAAQ,OAAO,MAAM,QAAQ;;KAE/B;;IAGF,IAAI,QAAQ,KAAK;KACf,SAAS;KACT,QAAQ,OAAO,MAAM,IAAI;;;;EAK/B,QAAQ,OAAO,MAAM,GAAG,QAAQ,IAAI;EACpC,QAAQ,MAAM,WAAW,KAAK;EAC9B,QAAQ,MAAM,QAAQ;EACtB,QAAQ,MAAM,GAAG,QAAQ,OAAO;GAChC;;AAGJ,eAAe,qBACb,SACA,WACiB;CAEjB,MAAM,mBAAkB,MADJ,iBAAiB,QAAQ,EACf,MAAM;CACpC,IAAI,CAAC,iBACH,MAAM,IAAI,MAAM,GAAG,UAAU,6BAA6B;CAE5D,OAAO;;AAGT,eAAe,2BAA4C;CACzD,MAAM,eAAe,MAAM,mBACzB,uBACA,gBACD;CACD,yBAAyB,aAAa;CACtC,OAAO;;AAGT,eAAe,2BAAkD;CAC/D,MAAM,eAAe,MAAM,OAAO,wBAAwB;EACxD,MAAM;EACN,SAAS,yBAAyB,KAAK,UAAU;GAC/C,OAAO;GACP,OAAO;GACR,EAAE;EACJ,CAAC;CAEF,IACE,OAAO,iBAAiB,YACrB,CAAC,wBAAwB,aAAa,EAEzC,MAAM,IAAI,MAAM,4BAA4B;CAG9C,OAAO;;AAGT,eAAe,wBACb,aACuB;CACvB,MAAM,eAAe,MAAM,OACzB,kCAAkC,YAAY,IAC9C;EACE,MAAM;EACN,SAAS,CACP;GACE,OAAO,YAAY,YAAY;GAC/B,OAAO;GACR,EACD,GAAG,yBAAyB,KAAK,UAAU;GACzC,OAAO;GACP,OAAO;GACR,EAAE,CACJ;EACF,CACF;CAED,IAAI,iBAAiB,oCACnB,OAAO;CAGT,IACE,OAAO,iBAAiB,YACrB,wBAAwB,aAAa,EAExC,OAAO;CAGT,MAAM,IAAI,MAAM,4BAA4B;;AAG9C,SAAS,2BACP,cACkB;CAClB,OAAO,iBAAiB,cAAc,cAAc;;AAGtD,eAAe,6BACb,cACuC;CAEvC,MAAM,WAAW,MAAM,OAAO,6BAA6B;EACzD,MAAM;EACN,SAAS,CACP;GACE,OAAO,YALW,2BAA2B,aAKX,CAAC;GACnC,OAAO;GACR,EACD,GAAG,2BAA2B,KAAK,WAAW;GAC5C,OAAO;GACP;GACD,EAAE,CACJ;EACF,CAAC;CAEF,IAAI,aAAa,kCACf;CAGF,IAAI,OAAO,aAAa,YAAY,yBAAyB,SAAS,EACpE,OAAO;CAGT,MAAM,IAAI,MAAM,iCAAiC;;AAGnD,eAAe,2BACb,gBACiB;CACjB,MAAM,QAAQ,MAAM,OAClB,oCAAoC,eAAe,IACnD;EACE,MAAM;EACN,SAAS;EACT,SAAS;EACV,CACF;CACD,MAAM,UAAU,yBACd,OAAO,UAAU,YAAY,MAAM,MAAM,GAAG,QAAQ,eACrD;CACD,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,qCAAqC;CAGvD,OAAO;;AAGT,SAAS,0BACP,wBACA,SAOgB;CAChB,OAAO;EACL,MAAM,QAAQ;EACd,SAAS;EACT,SAAS,QAAQ;EACjB,QAAQ,QAAQ;EAChB,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,UAAU,GAAG,EAAE;EAC1D,iBACE,QAAQ,mBAAmB,uBAAuB;EACpD,GAAI,uBAAuB,SACzB,EAAE,QAAQ,uBAAuB,QAAQ,GACzC,EAAE;EACL;;AAGH,eAAe,0BAAyC;CACtD,MAAM,eAAe,MAAM,0BAA0B;CACrD,MAAM,OAAO,MAAM,0BAA0B;CAC7C,MAAM,UAAU,yBACd,MAAM,mBAAmB,0BAA0B,UAAU,CAC9D;CACD,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,qCAAqC;CAGvD,MAAM,SAAS,MAAM,qBAAqB,yBAAyB,SAAS;CAC5E,MAAM,WAAW,MAAM,6BAA6B,KAAK;CAGzD,kBACE,cACA,0BAJ6B,qBAAqB,aAAa,IAAI,EAAE,EAInB;EAChD;EACA;EACA;EACA;EACD,CAAC,CACH;CAED,QAAQ,QACN,oBAAoB,aAAa,eAAe,MAAM,cACvD;;AAGH,eAAe,uBACb,cACe;CACf,MAAM,wBAAwB,uBAAuB;CACrD,MAAM,SAAS,MAAM,qBACnB,SAAS,aAAa,UACtB,SACD;CACD,MAAM,OACJ,sBAAsB,eACpB,MAAM,wBAAwB,sBAAsB,KAAK,GACzD,sBAAsB;CAC1B,MAAM,UAAU,MAAM,2BACpB,sBAAsB,QACvB;CAGD,kBACE,cACA,0BAJ6B,qBAAqB,aAAa,IAAI,EAAE,EAInB;EAChD;EACA;EACA,iBAAiB,sBAAsB;EACvC;EACD,CAAC,CACH;CAED,QAAQ,QACN,GAAG,qBAAqB,cAAc,aAAa,aAAa,eAAe,MAAM,cACtF;;AAGH,eAAe,iBAAgC;CAiB7C,MAAM,wBAAwB,MAhBJ,WAAW;EACnC,OAAO,MAAM;GACX,QAAQ,KAAK,qDAAqD;GAClE,QAAQ,IAAI,KAAK,IAAI;GACrB,IAAI,KAAK,cACP,QAAQ,KAAK,KAAK,aAAa;;EAGnC,SAAS,SAAS;GAChB,OAAO,OAAO,SAAS,EAAE,MAAM,QAAQ,CAAC,CAAC,MAAM,UAAU,SAAS,GAAG;;EAEvE,WAAW,SAAS;GAClB,QAAQ,MAAM,QAAQ;;EAEzB,CAAC,EAEyC,EAAE,gBAAgB,MAAM,CAAC;CACpE,QAAQ,QACN,oCAAoC,MAAM,YAAY,8BAA8B,MAAM,wBAC3F;;AAGH,eAAe,kBAAkB,UAA2C;CAC1E,IAAI,aAAa,WAAW;EAC1B,MAAM,iBAAiB,EAAE,OAAO,MAAM,CAAC;EACvC,QAAQ,QAAQ,2BAA2B,MAAM,kBAAkB;EACnE;;CAGF,IAAI,aAAa,SAAS;EACxB,MAAM,gBAAgB;EACtB;;CAGF,IAAI,oBAAoB,SAAS,EAAE;EACjC,MAAM,uBAAuB,SAAS;EACtC;;CAGF,MAAM,yBAAyB;;AAGjC,eAAsB,mBAAkC;CACtD,MAAM,WAAW,MAAM,yBAAyB,KAAA,EAAU;CAC1D,QAAQ,KAAK,mBAAmB,qBAAqB,YAAY;CACjE,MAAM,kBAAkB,SAAS;;AAGnC,eAAsB,aAAa,SAAwC;CAEzE,CAAA,MADwB,OAAO,sBACrB,sBAAsB;CAEhC,IAAI,QAAQ,SAAS;EACnB,QAAQ,QAAQ;EAChB,QAAQ,KAAK,0BAA0B;;CAGzC,MAAM,YAAY,QAAQ;CAE1B,MAAM,aAAa;CACnB,MAAM,WAAW,MAAM,yBAAyB,QAAQ,SAAS;CAEjE,QAAQ,KAAK,mBAAmB,qBAAqB,YAAY;CACjE,MAAM,kBAAkB,SAAS;;AAGnC,MAAM,eAAe;CACnB,KAAK;EACH,OAAO;EACP,MAAM;EACN,aAAa;EACd;CACD,QAAQ;EACN,OAAO;EACP,MAAM;EACN,aAAa;EACd;CACD,MAAM;EACJ,OAAO;EACP,MAAM;EACN,SAAS;EACT,aAAa;EACd;CACD,OAAO;EACL,MAAM;EACN,SAAS;EACT,aAAa;EACd;CACF;AASD,SAAS,sBAAsB,OAAuB;CACpD,MAAM,gBAAgB,MAAM,MAAM;CAClC,IAAI,CAAC,eACH,MAAM,IAAI,MAAM,qCAAqC;CAEvD,OAAO;;AAGT,eAAsB,YAAY,SAA4C;CAE5E,CAAA,MADwB,OAAO,sBACrB,sBAAsB;CAEhC,MAAM,aAAa;CAEnB,MAAM,aAAa;EACjB,GAAI,QAAQ,QAAQ,KAAA,IAAY,CAAC,MAAM,GAAG,EAAE;EAC5C,GAAI,QAAQ,WAAW,KAAA,IAAY,CAAC,SAAS,GAAG,EAAE;EAClD,GAAI,QAAQ,OAAO,CAAC,OAAO,GAAG,EAAE;EAChC,GAAI,QAAQ,QAAQ,CAAC,QAAQ,GAAG,EAAE;EACnC;CACD,IAAI,WAAW,SAAS,GACtB,MAAM,IAAI,MACR,qEACD;CAGH,MAAM,YAAY,WAAW,MAAM;CAEnC,IAAI,cAAc,OAAO;EACvB,MAAM,SAAS,sBAAsB,QAAQ,OAAO,GAAG;EACvD,MAAM,cAAc,sBAAsB;EAC1C,IAAI,YAAY,SAAS,OAAO,EAAE;GAChC,QAAQ,KACN,+BAA+B,YAAY,OAAO,yBACnD;GACD;;EAEF,MAAM,aAAa,qBAAqB,CAAC,GAAG,aAAa,OAAO,CAAC;EACjE,QAAQ,QACN,oBAAoB,MAAM,YAAY,IAAI,WAAW,OAAO,yBAC7D;EACD;;CAGF,IAAI,cAAc,UAAU;EAC1B,MAAM,SAAS,sBAAsB,QAAQ,UAAU,GAAG;EAC1D,MAAM,cAAc,sBAAsB;EAC1C,IAAI,CAAC,YAAY,SAAS,OAAO,EAAE;GACjC,QAAQ,KACN,sBAAsB,YAAY,OAAO,yBAC1C;GACD;;EAEF,MAAM,aAAa,qBACjB,YAAY,QAAQ,QAAQ,QAAQ,OAAO,CAC5C;EACD,QAAQ,QACN,wBAAwB,MAAM,YAAY,IAAI,WAAW,OAAO,yBACjE;EACD;;CAGF,IAAI,cAAc,SAAS;EACzB,qBAAqB,EAAE,CAAC;EACxB,QAAQ,QAAQ,6BAA6B,MAAM,YAAY,GAAG;EAClE;;CAGF,MAAM,cAAc,sBAAsB;CAC1C,IAAI,YAAY,WAAW,GAAG;EAC5B,QAAQ,KACN,kFACD;EACD;;CAEF,QAAQ,KAAK,uBAAuB;CACpC,KAAK,MAAM,OAAO,aAChB,QAAQ,KAAK,KAAK,MAAM;;AAoC5B,MAAa,OAAO,cAAc;CAChC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM;CACN,aAAa;EACX,OAvCc,cAAc;GAC9B,MAAM;IACJ,MAAM;IACN,aACE;IACH;GACD,MAAM;GACN,IAAI,EAAE,QAAQ;IACZ,OAAO,aAAa;KAClB,UAAU,KAAK;KACf,SAAS,KAAK;KACd,WAAW,KAAK;KACjB,CAAC;;GAEL,CAyBU;EACP,MAxBa,cAAc;GAC7B,MAAM;IACJ,MAAM;IACN,aAAa;IACd;GACD,MAAM;GACN,IAAI,EAAE,QAAQ;IACZ,OAAO,YAAY;KACjB,KAAK,KAAK;KACV,QAAQ,KAAK;KACb,MAAM,KAAK;KACX,OAAO,KAAK;KACb,CAAC;;GAEL,CAUS;EACP;CACD,IAAI,EAAE,QAAQ;EACZ,KAAK,KAAK,EAAE,MAAM,IAAI,MAAM,EAC1B;EAGF,OAAO,aAAa;GAClB,UAAU,KAAK;GACf,SAAS,KAAK;GACd,WAAW,KAAK;GACjB,CAAC;;CAEL,CAAC"}
package/dist/main.js CHANGED
@@ -27,10 +27,10 @@ if (isMcpFastPath(process.argv)) {
27
27
  if (process.platform === "win32" && process.stdout.isTTY && !process.env.WT_SESSION) process.env.WT_SESSION = "copilot-api";
28
28
  const { bindElectronFetch } = await import("./electron-fetch-BRX-ug5E.js");
29
29
  bindElectronFetch();
30
- const { auth } = await import("./auth-BZLuISLH.js");
30
+ const { auth } = await import("./auth-BKEWjsYR.js");
31
31
  const { debug } = await import("./debug-CcgIYPL-.js");
32
32
  const { mcp } = await import("./mcp-fpSlKZxK.js");
33
- const { start } = await import("./start-DJrCCMlX.js");
33
+ const { start } = await import("./start-R_GdLsiW.js");
34
34
  await runMain(defineCommand({
35
35
  meta: {
36
36
  name: "copilot-api",
@@ -1,4 +1,4 @@
1
- import { Y as state } from "./token-Bm_dyi5a.js";
1
+ import { J as state } from "./token-DZDtQb7h.js";
2
2
  //#region src/lib/models.ts
3
3
  /**
4
4
  * Converts a Copilot upstream model ID to a client-friendly ID that Claude Code
@@ -87,4 +87,4 @@ const normalizeSdkModelId = (sdkModelId) => {
87
87
  //#endregion
88
88
  export { toClientModelId as i, getLatestModelForFamily as n, normalizeSdkModelId as r, findEndpointModel as t };
89
89
 
90
- //# sourceMappingURL=models-DRiRPEy3.js.map
90
+ //# sourceMappingURL=models-uKftaEt_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"models-DRiRPEy3.js","names":[],"sources":["../src/lib/models.ts"],"sourcesContent":["import type { Model } from \"~/lib/types/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
+ {"version":3,"file":"models-uKftaEt_.js","names":[],"sources":["../src/lib/models.ts"],"sourcesContent":["import type { Model } from \"~/lib/types/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,7 +1,7 @@
1
1
  import { A as isResponsesApiWebSocketEnabled, C as getClaudeTokenMultiplier, D as isAlphaSearchCodexPriorityEnabled, E as getUpstreamTransportConfig, N as PATHS, O as isMessagesApiEnabled, S as getClaudeAutoModel, T as getMessageApiWebSearchModel, _ as resolveMappedModel, b as getAlphaSearchModel, d as getModelResponsesApiCompactThreshold$1, f as getReasoningEffortForModel, g as isGpt56OrAbove, h as isContextManagementEnabledForResponses, i as listEnabledProviders, k as isResponsesApiWebSearchEnabled, l as getExtraPromptForModel, m as isContextManagementEnabledForMessages, n as getRawProviderConfig, o as resolveEffectiveProviderType, p as getSmallModel, s as resolveProviderAuthType, t as getProviderConfig, u as getModelMappings, v as setModelMappings, x as getAnthropicApiKey } from "./config-DYtohLpX.js";
2
- import { A as compactTextOnlyGuard, B as requestContext, C as prepareInteractionHeaders, D as compactMessageSections, E as compactAutoContinuePromptStarts, G as encodePoolKeyPart, H as fetchUpstreamWithLifecycle, I as CODEX_API_BASE_URL, J as createWebSocketUrl, K as isTerminalResponsesStreamChunk, L as buildCodexRequestHeaders, M as getConfiguredAdminApiKeys, R as forwardCodexResponses, S as prepareForCompact, U as createResponsesHttpEventStream, V as resolveTraceId$1, W as createResponsesSafeStream, X as HTTPError, Y as state, Z as forwardError, c as getUUID, d as isResponsesStream, f as parseUserIdMetadata, j as createAuthMiddleware, k as compactSystemPromptStarts, l as isAsyncIterable, m as getCopilotUsage, o as generateRequestIdFromPayload, p as sleep, q as createPooledWebSocketStream, r as setupCodexToken, s as getRootSessionId, u as isNullish, v as copilotBaseUrl, w as prepareMessageProxyHeaders, x as copilotWebSocketHeaders, y as copilotHeaders, z as generateTraceId } from "./token-Bm_dyi5a.js";
2
+ import { A as createAuthMiddleware, B as resolveTraceId$1, C as prepareMessageProxyHeaders, E as compactMessageSections, F as CODEX_API_BASE_URL, G as isTerminalResponsesStreamChunk, H as createResponsesHttpEventStream, I as buildCodexRequestHeaders, J as state, K as createPooledWebSocketStream, L as forwardCodexResponses, O as compactSystemPromptStarts, R as generateTraceId, S as prepareInteractionHeaders, T as compactAutoContinuePromptStarts, U as createResponsesSafeStream, V as fetchUpstreamWithLifecycle, W as encodePoolKeyPart, X as forwardError, Y as HTTPError, _ as copilotBaseUrl, b as copilotWebSocketHeaders, c as getUUID, d as isResponsesStream, f as parseUserIdMetadata, j as getConfiguredAdminApiKeys, k as compactTextOnlyGuard, l as isAsyncIterable, o as generateRequestIdFromPayload, p as getCopilotUsage, q as createWebSocketUrl, r as setupCodexToken, s as getRootSessionId, u as isNullish, v as copilotHeaders, x as prepareForCompact, z as requestContext } from "./token-DZDtQb7h.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-Ds1vbmGG.js";
4
- import { i as toClientModelId, r as normalizeSdkModelId, t as findEndpointModel } from "./models-DRiRPEy3.js";
4
+ import { i as toClientModelId, r as normalizeSdkModelId, t as findEndpointModel } from "./models-uKftaEt_.js";
5
5
  import consola from "consola";
6
6
  import { createHash } from "node:crypto";
7
7
  import fs, { createWriteStream, readFileSync, rmSync } from "node:fs";
@@ -636,24 +636,14 @@ const builtinProviderModelRegistry = new class BuiltinProviderModelRegistry {
636
636
  }
637
637
  },
638
638
  deepseek: {
639
- "deepseek-v4-flash": {
640
- contextWindow: 1e6,
641
- inputModalities: ["text"],
642
- maxOutputTokens: 64e3,
643
- pricing: {
644
- cachedInput: .1,
645
- input: 3,
646
- output: 9
647
- }
648
- },
649
- "deepseek-v4-flash-vision-exp": {
639
+ "deepseek-flash": {
650
640
  contextWindow: 1e6,
651
641
  inputModalities: ["text", "image"],
652
- maxOutputTokens: 64e3,
642
+ maxOutputTokens: 384e3,
653
643
  pricing: {
654
- cachedInput: .1,
655
- input: 3,
656
- output: 9
644
+ cachedInput: .04,
645
+ input: 2,
646
+ output: 8
657
647
  }
658
648
  },
659
649
  "deepseek-v4-pro": {
@@ -815,6 +805,21 @@ const builtinProviderModelRegistry = new class BuiltinProviderModelRegistry {
815
805
  "xhigh"
816
806
  ]
817
807
  },
808
+ "deepseek-flash": {
809
+ contextWindow: 1e6,
810
+ inputModalities: ["text", "image"],
811
+ maxOutputTokens: 384e3,
812
+ pricing: {
813
+ cachedInput: .006,
814
+ input: .3,
815
+ output: 1.2
816
+ },
817
+ reasoningEfforts: [
818
+ "low",
819
+ "high",
820
+ "max"
821
+ ]
822
+ },
818
823
  "deepseek-v4-flash": {
819
824
  contextWindow: 1e6,
820
825
  inputModalities: ["text"],
@@ -2211,8 +2216,6 @@ const isCopilotQuotaSnapshot = (value) => {
2211
2216
  };
2212
2217
  //#endregion
2213
2218
  //#region src/services/copilot/create-responses.ts
2214
- const ROOT_AGENT_MESSAGE_DELAY_MS = 1e3;
2215
- const createResponsesDependencies = { sleep };
2216
2219
  const createResponses = async (payload, { vision, initiator, subagentMarker, requestId, sessionId, compactType, transport = "http", clientSignal }) => {
2217
2220
  if (!state.copilotToken) throw new Error("Copilot token not found");
2218
2221
  const headers = {
@@ -2226,7 +2229,6 @@ const createResponses = async (payload, { vision, initiator, subagentMarker, req
2226
2229
  const effectiveTransport = compactType === 1 ? "http" : transport;
2227
2230
  if (payload.stream === true && effectiveTransport === "websocket") {
2228
2231
  clientSignal?.throwIfAborted();
2229
- if (shouldDelaySubagentRequestAfterRootMessage(payload.input)) await createResponsesDependencies.sleep(ROOT_AGENT_MESSAGE_DELAY_MS);
2230
2232
  return createPooledResponsesWebSocketStream(prepareResponsesWebSocketRequest(payload, headers, {
2231
2233
  requestId,
2232
2234
  subagentMarker
@@ -2234,11 +2236,6 @@ const createResponses = async (payload, { vision, initiator, subagentMarker, req
2234
2236
  }
2235
2237
  return await createHttpResponses(payload, headers, clientSignal);
2236
2238
  };
2237
- const shouldDelaySubagentRequestAfterRootMessage = (input) => {
2238
- if (!Array.isArray(input)) return false;
2239
- const lastItem = input.at(-1);
2240
- return typeof lastItem === "object" && lastItem !== null && "type" in lastItem && lastItem.type === "agent_message" && "author" in lastItem && lastItem.author === "/root";
2241
- };
2242
2239
  const createHttpResponses = async (payload, headers, clientSignal) => {
2243
2240
  const transportConfig = getUpstreamTransportConfig();
2244
2241
  const response = await fetchUpstreamWithLifecycle(`${copilotBaseUrl(state)}/responses`, {
@@ -10506,12 +10503,6 @@ const FALLBACK_BASE_INSTRUCTIONS = FALLBACK_CODEX_MODELS.find((model) => model.b
10506
10503
  function isCodexUserAgent(userAgent) {
10507
10504
  return CODEX_USER_AGENT_PATTERN.test(userAgent?.trim() ?? "");
10508
10505
  }
10509
- function isDeepSeekModelId(modelId) {
10510
- return modelId.toLowerCase().includes("deepseek");
10511
- }
10512
- function shouldInjectMessagesToolCallTips(userAgent, targetModel) {
10513
- return isCodexUserAgent(userAgent) && !isDeepSeekModelId(targetModel);
10514
- }
10515
10506
  /**
10516
10507
  * Proxies a models request to the fixed Codex upstream models endpoint.
10517
10508
  * Returns a 404 JSON response when the codex provider is unavailable.
@@ -10581,7 +10572,6 @@ function createSyntheticCodexModel(candidate, template, priority) {
10581
10572
  const defaultReasoningEffort = reasoningEfforts.includes(candidate.defaultReasoningEffort) ? candidate.defaultReasoningEffort : reasoningEfforts[0];
10582
10573
  const supportsReasoning = reasoningEfforts.some((effort) => effort !== "none");
10583
10574
  const inputModalities = [...new Set(candidate.inputModalities)];
10584
- const isDeepSeekModel = isDeepSeekModelId(candidate.slug);
10585
10575
  return {
10586
10576
  ...template,
10587
10577
  slug: candidate.slug,
@@ -10597,11 +10587,11 @@ function createSyntheticCodexModel(candidate, template, priority) {
10597
10587
  apply_patch_tool_type: "freeform",
10598
10588
  web_search_tool_type: "text_and_image",
10599
10589
  supports_search_tool: false,
10600
- use_responses_lite: isDeepSeekModel ? false : true,
10601
- tool_mode: isDeepSeekModel ? null : "code_mode_only",
10590
+ use_responses_lite: true,
10591
+ tool_mode: "code_mode_only",
10602
10592
  multi_agent_version: "v2",
10603
10593
  multi_agent_reasoning_effort: null,
10604
- shell_type: isDeepSeekModel ? "shell_command" : template.shell_type,
10594
+ shell_type: template.shell_type,
10605
10595
  experimental_supported_tools: [],
10606
10596
  input_modalities: inputModalities,
10607
10597
  supports_image_detail_original: false,
@@ -11955,7 +11945,7 @@ async function handleResponsesViaMessages(c, options) {
11955
11945
  }, {
11956
11946
  model: options.targetModel,
11957
11947
  publicModel: options.publicModel,
11958
- toolCallTips: shouldInjectMessagesToolCallTips(c.req.header("user-agent"), options.targetModel)
11948
+ toolCallTips: isCodexUserAgent(c.req.header("user-agent"))
11959
11949
  });
11960
11950
  const context = translation;
11961
11951
  debugJson(logger$3, "Translated Messages request:", {
@@ -12553,4 +12543,4 @@ createServer();
12553
12543
  //#endregion
12554
12544
  export { createServer };
12555
12545
 
12556
- //# sourceMappingURL=server-DriTUys0.js.map
12546
+ //# sourceMappingURL=server-Cqju93ku.js.map