@jeffreycao/copilot-api 2.3.4 → 2.3.7

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
@@ -245,6 +245,7 @@ base_url = "http://localhost:4141"
245
245
  env_key = "GITHUB_COPILOT_API_KEY"
246
246
  requires_openai_auth = true
247
247
  supports_websockets = false
248
+ supports_standalone_web_search = true
248
249
  wire_api = "responses"
249
250
  request_max_retries = 3
250
251
  stream_max_retries = 3
@@ -254,6 +255,7 @@ stream_idle_timeout_ms = 300000
254
255
  remote_compaction_v2 = true
255
256
  # optional: set false only when the model does not support tool_search
256
257
  apps = false
258
+ standalone_web_search = true
257
259
 
258
260
  [analytics]
259
261
  enabled = false
@@ -263,6 +265,8 @@ enabled = false
263
265
  > `name` must be set to `"OpenAI"`.
264
266
  >
265
267
  > For third-party models that do not support `tool_search`, we recommend disabling features.apps. Otherwise, each prompt may consume an additional 20,000 or more tokens.
268
+ >
269
+ > `supports_standalone_web_search` and `[features] standalone_web_search` must both be enabled to expose the standalone `web.run` search tool.
266
270
 
267
271
  ### If Codex Is Not Signed In to a GPT Account
268
272
 
@@ -272,11 +276,15 @@ name = "OpenAI"
272
276
  base_url = "http://localhost:4141"
273
277
  requires_openai_auth = false
274
278
  supports_websockets = false
279
+ supports_standalone_web_search = true
275
280
  wire_api = "responses"
276
281
  request_max_retries = 3
277
282
  stream_max_retries = 3
278
283
  stream_idle_timeout_ms = 300000
279
284
 
285
+ [features]
286
+ standalone_web_search = true
287
+
280
288
  [model_providers.copilot_api.auth]
281
289
  command = "powershell.exe"
282
290
  args = [
@@ -300,7 +308,7 @@ args = [
300
308
 
301
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.
302
310
 
303
- 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`: `/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.
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.
304
312
 
305
313
  The merged catalog is what Codex shows in its model picker, including the models exposed by your configured providers:
306
314
 
@@ -694,7 +702,7 @@ Gateway API keys live under `auth.apiKeys` in `config.json`. Manage them with `c
694
702
  - **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/*`.
695
703
  - **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.
696
704
  - **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.
697
- - **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.
705
+ - **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.
698
706
  - `enabled` defaults to `true` if omitted.
699
707
  - `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`.
700
708
  - `apiKey` is used as the upstream credential value and is required for regular providers.
package/README.zh-CN.md CHANGED
@@ -261,6 +261,7 @@ base_url = "http://localhost:4141"
261
261
  env_key = "GITHUB_COPILOT_API_KEY"
262
262
  requires_openai_auth = true
263
263
  supports_websockets = false
264
+ supports_standalone_web_search = true
264
265
  wire_api = "responses"
265
266
  request_max_retries = 3
266
267
  stream_max_retries = 3
@@ -270,6 +271,7 @@ stream_idle_timeout_ms = 300000
270
271
  remote_compaction_v2 = true
271
272
  # optional: set false only when the model does not support tool_search
272
273
  apps = false
274
+ standalone_web_search = true
273
275
 
274
276
  [analytics]
275
277
  enabled = false
@@ -279,6 +281,8 @@ enabled = false
279
281
  > `name` 一定要配置为 `"OpenAI"`。
280
282
  >
281
283
  > 对于不支持 `tool_search` 的第三方模型,我们建议禁用 features.apps。否则,每个提示可能会额外消耗 20,000 多个 token。
284
+ >
285
+ > 必须同时启用 `supports_standalone_web_search` 和 `[features] standalone_web_search`,Codex 才会暴露独立的 `web.run` 搜索工具。
282
286
 
283
287
  ### Codex 未登录 GPT 账号时
284
288
 
@@ -288,11 +292,15 @@ name = "OpenAI"
288
292
  base_url = "http://localhost:4141"
289
293
  requires_openai_auth = false
290
294
  supports_websockets = false
295
+ supports_standalone_web_search = true
291
296
  wire_api = "responses"
292
297
  request_max_retries = 3
293
298
  stream_max_retries = 3
294
299
  stream_idle_timeout_ms = 300000
295
300
 
301
+ [features]
302
+ standalone_web_search = true
303
+
296
304
  [model_providers.copilot_api.auth]
297
305
  command = "powershell.exe"
298
306
  args = [
@@ -316,7 +324,7 @@ args = [
316
324
 
317
325
  未按上述方式配置时,Codex 未登录 GPT 账号拉不到 `/v1/models`,无法选择自定义模型。
318
326
 
319
- Codex 客户端(`User-Agent` 以 `codex` 开头)请求顶层 `GET /v1/models` 时,网关会把原生 Codex 模型与可通过 Messages 适配的模型合并返回。后者会声明 `use_responses_lite: true`:调用 `/v1/responses` 后,Anthropic provider 走 **Responses → Messages**,OpenAI 兼容 provider 以及只支持 Chat 的 Copilot 模型则复用现有 Messages 路由继续走 **Responses → Messages → Chat Completions**,最终统一翻译回 Responses(包括流式事件)。
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(包括流式事件)。
320
328
 
321
329
  合并后的模型列表会直接展示在 Codex 的模型选择界面中,包含各 provider 暴露的模型:
322
330
 
@@ -738,7 +746,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
738
746
  - **auth.adminApiKey:** 仅用于 `/admin/*` 路由的单个 admin key。若未配置,服务会在启动时自动生成一个随机 key,并回写到 `config.json`。它同样使用 `x-api-key` 或 `Authorization: Bearer` 这两种头,但普通 `auth.apiKeys` 不能访问 `/admin/*`。
739
747
  - **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` 管理接口读写的也只有这个字段。
740
748
  - **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,让模型在工具调用或更深层推理前先发出简短的用户可见进度说明。
741
- - **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`。
749
+ - **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`。
742
750
  - `enabled`:可选,若省略则默认为 `true`。
743
751
  - `baseUrl`:provider API 的基础 URL,不要带结尾的 endpoint。Anthropic provider 不要带 `/v1/messages`;OpenAI 兼容 provider 不要带 `/v1/chat/completions`;OpenAI Responses provider 不要带 `/v1/responses`。
744
752
  - `apiKey`:作为上游凭据值使用;普通 provider 必须配置。
package/dist/main.js CHANGED
@@ -30,7 +30,7 @@ if (isMcpFastPath(process.argv)) {
30
30
  const { auth } = await import("./auth-B-ry4rJx.js");
31
31
  const { debug } = await import("./debug-Db0SCVSP.js");
32
32
  const { mcp } = await import("./mcp-fpSlKZxK.js");
33
- const { start } = await import("./start-DqfeTNPH.js");
33
+ const { start } = await import("./start-Cfg3jwGS.js");
34
34
  await runMain(defineCommand({
35
35
  meta: {
36
36
  name: "copilot-api",
@@ -8011,6 +8011,12 @@ After deleting anything material, briefly tell the user what was removed and whe
8011
8011
  function isCodexUserAgent(userAgent) {
8012
8012
  return CODEX_USER_AGENT_PATTERN.test(userAgent?.trim() ?? "");
8013
8013
  }
8014
+ function isDeepSeekModelId(modelId) {
8015
+ return modelId.toLowerCase().includes("deepseek");
8016
+ }
8017
+ function shouldInjectMessagesToolCallTips(userAgent, targetModel) {
8018
+ return isCodexUserAgent(userAgent) && !isDeepSeekModelId(targetModel);
8019
+ }
8014
8020
  async function logCodexModelsResponse(response) {
8015
8021
  try {
8016
8022
  const models = await response.clone().json();
@@ -8099,6 +8105,7 @@ function createSyntheticCodexModel(candidate, template, priority) {
8099
8105
  const defaultReasoningEffort = reasoningEfforts.includes(candidate.defaultReasoningEffort) ? candidate.defaultReasoningEffort : reasoningEfforts[0];
8100
8106
  const supportsReasoning = reasoningEfforts.some((effort) => effort !== "none");
8101
8107
  const inputModalities = [...new Set(candidate.inputModalities)];
8108
+ const isDeepSeekModel = isDeepSeekModelId(candidate.slug);
8102
8109
  return {
8103
8110
  ...template,
8104
8111
  slug: candidate.slug,
@@ -8114,8 +8121,8 @@ function createSyntheticCodexModel(candidate, template, priority) {
8114
8121
  apply_patch_tool_type: "freeform",
8115
8122
  web_search_tool_type: "text_and_image",
8116
8123
  supports_search_tool: false,
8117
- use_responses_lite: true,
8118
- tool_mode: "code_mode_only",
8124
+ use_responses_lite: isDeepSeekModel ? false : true,
8125
+ tool_mode: isDeepSeekModel ? null : "code_mode_only",
8119
8126
  multi_agent_version: "v2",
8120
8127
  shell_type: "shell_command",
8121
8128
  experimental_supported_tools: [],
@@ -10144,7 +10151,7 @@ async function handleResponsesViaMessages(c, options) {
10144
10151
  }, {
10145
10152
  model: options.targetModel,
10146
10153
  publicModel: options.publicModel,
10147
- toolCallTips: isCodexUserAgent(c.req.header("user-agent"))
10154
+ toolCallTips: shouldInjectMessagesToolCallTips(c.req.header("user-agent"), options.targetModel)
10148
10155
  });
10149
10156
  const context = translation;
10150
10157
  debugJson(logger$3, "Translated Messages request:", {
@@ -10709,4 +10716,4 @@ server.route("/:provider/images", providerImageRoutes);
10709
10716
  //#endregion
10710
10717
  export { server };
10711
10718
 
10712
- //# sourceMappingURL=server-CKVtJPpg.js.map
10719
+ //# sourceMappingURL=server-DR94qLzm.js.map