xiaodcs-copilot-api 2.3.9-public.3 → 2.5.1-public.2

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
@@ -65,7 +65,8 @@ From here, jump to the guide for your client: [Claude Code](#using-with-claude-c
65
65
  - **Unified API Gateway**: Serve OpenAI-compatible Chat Completions (`/v1/chat/completions`), the OpenAI Responses API (`/v1/responses`), and Anthropic-compatible Messages (`/v1/messages`) from one local endpoint.
66
66
  - **Multi-Provider**: Route GitHub Copilot, the built-in `codex` provider, and third-party providers (Kimi, DeepSeek, DashScope, OpenRouter, OpenCode Go, or a custom provider) behind the same gateway. GitHub Copilot is optional — with at least one enabled provider, the server starts in provider-only mode without a GitHub token.
67
67
  - **Coding Agent Ready**: First-class setups for Claude Code, OpenCode, and Codex, including the interactive `--claude-code` launcher and a merged model catalog for Codex.
68
- - **Streaming & WebSocket**: SSE streaming on all three client-facing protocols. Upstream Copilot Responses traffic selects WebSocket or HTTP from each model's advertised endpoints; streamed Responses traffic for the built-in `codex` provider uses WebSocket by default and uses HTTP when `useResponsesApiWebSocket` is disabled.
68
+ - **Streaming & WebSocket**: SSE streaming on all three client-facing protocols. Upstream Copilot Responses traffic selects WebSocket or HTTP from each model's advertised endpoints. The built-in `codex` provider can independently select WebSocket with `useCodexResponsesApiWebSocket`; when omitted, it inherits `useResponsesApiWebSocket`.
69
+ - **Codex quota logs**: Healthy quota snapshots are debug-only (visible with `--verbose`). Warnings remain visible when a window reaches 90% used, `allowed=false`, or `limit_reached=true`. This changes console verbosity only; quota events, usage recording, and request handling are unchanged.
69
70
  - **Desktop App**: Electron GUI with GitHub Copilot sign-in, Codex OAuth, provider configuration, token usage, logs, and one-click start/stop.
70
71
 
71
72
  ## Compatibility
@@ -335,6 +336,8 @@ Without this configuration, Codex cannot fetch `/v1/models` while not signed in
335
336
 
336
337
  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.
337
338
 
339
+ > **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.
340
+
338
341
  The merged catalog is what Codex shows in its model picker, including the models exposed by your configured providers:
339
342
 
340
343
  <img src="./docs/screenshots/codex-models.png" alt="Codex model picker showing models provided by the gateway" width="900" />
@@ -429,9 +432,12 @@ npx xiaodcs-copilot-api-edge@latest start
429
432
  With options:
430
433
 
431
434
  ```sh
432
- npx xiaodcs-copilot-api-edge@latest start --port 8080
435
+ npx xiaodcs-copilot-api-edge@latest auth keys --add your-gateway-api-key
436
+ npx xiaodcs-copilot-api-edge@latest start --host 0.0.0.0 --port 8080
433
437
  ```
434
438
 
439
+ Binding to `0.0.0.0` exposes the gateway to the network, so the server requires at least one gateway API key and restricts CORS to same-origin requests.
440
+
435
441
  For authentication or provider configuration only:
436
442
 
437
443
  ```sh
@@ -457,15 +463,17 @@ Run the container with a bind mount so auth data survives restarts:
457
463
 
458
464
  ```sh
459
465
  mkdir -p ./copilot-data
466
+ docker run --rm -v $(pwd)/copilot-data:/root/.local/share/copilot-api copilot-api --auth keys --add your-gateway-api-key
460
467
  docker run -p 4141:4141 -v $(pwd)/copilot-data:/root/.local/share/copilot-api copilot-api
461
468
  ```
462
469
 
463
470
  This stores GitHub auth data, provider config, and other gateway state in `./copilot-data` on the host, mapped to `/root/.local/share/copilot-api` in the container.
471
+ The image explicitly listens on `0.0.0.0` so Docker port publishing works and refuses to start until at least one gateway API key is configured. Non-loopback listeners also restrict CORS to the request's own origin.
464
472
 
465
473
  Or pass a GitHub token directly:
466
474
 
467
475
  ```sh
468
- docker run -p 4141:4141 -e GH_TOKEN=your_github_token_here copilot-api
476
+ docker run -p 4141:4141 -v $(pwd)/copilot-data:/root/.local/share/copilot-api -e GH_TOKEN=your_github_token_here copilot-api
469
477
  ```
470
478
 
471
479
  ## Electron Desktop App
@@ -608,16 +616,16 @@ The dashboard provides a user-friendly interface to view your Copilot usage data
608
616
 
609
617
  - **API Endpoint URL**: The dashboard is pre-configured to fetch data from your local server endpoint via a URL query parameter. You can manually switch this to any other compatible API endpoint.
610
618
  - **API Key Authentication**: If API Key authentication is enabled, enter a raw API key (sent as the `x-api-key` header) or `Authorization: Bearer <key>`. Credentials are remembered in the browser's local storage per endpoint origin, and switching to a different endpoint origin does not automatically send the previous credential.
611
- - **Period Selector**: Choose from Day, Week, or Month time ranges. The URL query parameter updates automatically when you switch, making it easy to bookmark and share.
619
+ - **Period Selector**: Choose from six time ranges: `today` (the current local calendar day so far), `this_week` (Monday at 00:00 through now), `last_7_days` (the rolling seven calendar days through now), `this_month` (the first day of the current month at 00:00 through now), `last_30_days` (the rolling 30 calendar days through now), and `lifetime` (the earliest recorded event through now). Today is selected by default, and the exact date range appears next to the selector. The URL query parameter updates automatically when you switch, making it easy to bookmark and share. The legacy values `day`, `week`, and `month` are still accepted and mapped to their new equivalents.
612
620
  - **Fetch Data**: Click the "Refresh" button to load or refresh the usage data. The dashboard also fetches data automatically on page load.
613
621
  - **Copilot Quotas**: View quota usage for services such as Chat and Completions via progress bars. Hover over a card to see used/remaining details.
614
622
  - **Token Usage Metric Cards**: See a summary of Total, Input, Output, Cache Read, Cache Write, Requests, and estimated cost for the current period.
615
- - **Trend Chart (Week / Month)**: An interactive line chart with model and metric filters. Click a data point to inspect the usage breakdown for a specific day.
623
+ - **Trend Chart**: An interactive line chart with model and metric filters for the selected period. Click a data point to inspect the usage breakdown for a day; Lifetime chart data is sampled from the daily buckets and capped at 180 points for readability.
616
624
  - **Model Breakdown Table**: A per-model summary of requests, input/output/cache tokens, and estimated cost for the selected period.
617
625
  - **Request Events (Paginated)**: A time-sorted list of request event records with pagination support, showing timestamps, models, request IDs, and token counts.
618
626
  - **Detailed Information**: See the full JSON response from the API for a detailed breakdown of all available usage statistics.
619
627
  - **URL-based Configuration**: You can also specify the API endpoint and period directly via `endpoint` and `period` query parameters. For example:
620
- `http://localhost:4141/usage-viewer?endpoint=http://your-api-server/usage&period=week`
628
+ `http://localhost:4141/usage-viewer?endpoint=http://your-api-server/usage&period=this_week`
621
629
 
622
630
  ### Usage Viewer Screenshot
623
631
 
@@ -651,6 +659,7 @@ The following command line options are available for the `start` command:
651
659
 
652
660
  | Option | Description | Default | Alias |
653
661
  | -------------- | ----------------------------------------------------------------------------- | ---------- | ----- |
662
+ | --host | Host to listen on; non-loopback hosts require a configured gateway API key | 127.0.0.1 | none |
654
663
  | --port | Port to listen on | 4141 | -p |
655
664
  | --verbose | Enable verbose logging | false | -v |
656
665
  | --github-token | Provide GitHub token directly (must be generated using the `auth` subcommand) | none | -g |
@@ -672,7 +681,7 @@ Use `copilot-api auth login --provider deepseek`, `--provider dashscope`, `--pro
672
681
 
673
682
  Use `copilot-api auth login --provider custom` to add or update another third-party provider from the CLI. The command prompts for the provider name, supported type (`anthropic`, `openai-compatible`, or `openai-responses`), `baseUrl`, masked `apiKey`, and `authType`; `authType` may be left as the type default or set to `x-api-key` / `authorization`.
674
683
 
675
- Gateway API keys live under `auth.apiKeys` in `config.json`. Manage them with `copilot-api auth keys` (one operation per invocation): add a key with `--add <key>`, remove one with `--remove <key>`, list all with `--list`, or clear them all with `--clear`. Clients authenticate with any configured key via `x-api-key` or `Authorization: Bearer`. When no keys are configured, `copilot-api start` starts with authentication bypassed and prints a startup info message.
684
+ Gateway API keys live under `auth.apiKeys` in `config.json`. Manage them with `copilot-api auth keys` (one operation per invocation): add a key with `--add <key>`, remove one with `--remove <key>`, list all with `--list`, or clear them all with `--clear`. Clients authenticate with any configured key via `x-api-key` or `Authorization: Bearer`. Without keys, loopback listeners start with authentication bypassed and print an info message; non-loopback listeners refuse to start.
676
685
 
677
686
  ### Debug Command Options
678
687
 
@@ -710,6 +719,7 @@ Gateway API keys live under `auth.apiKeys` in `config.json`. Manage them with `c
710
719
  "useMessagesApi": true,
711
720
  "useResponsesApiCompactionRecovery": false,
712
721
  "useResponsesApiWebSocket": true,
722
+ "useCopilotFastTier": true,
713
723
  "responsesTransport": {
714
724
  "headersTimeoutMsV2": 300000,
715
725
  "streamInactivityTimeoutMs": 300000,
@@ -724,15 +734,15 @@ Gateway API keys live under `auth.apiKeys` in `config.json`. Manage them with `c
724
734
  "messageApiWebSearchModel": "gpt-5-mini"
725
735
  }
726
736
  ```
727
- - **auth.apiKeys:** API keys used for request authentication on non-admin routes. Supports multiple keys for rotation. Requests can authenticate with either `x-api-key: <key>` or `Authorization: Bearer <key>`. If empty or omitted, authentication for non-admin routes is disabled.
737
+ - **auth.apiKeys:** API keys used for request authentication on non-admin routes. Supports multiple keys for rotation. Requests can authenticate with either `x-api-key: <key>` or `Authorization: Bearer <key>`. If empty or omitted, authentication for non-admin routes is disabled only on loopback listeners; non-loopback listeners refuse to start.
728
738
  - **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/*`.
729
739
  - **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.
730
740
  - **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.
731
741
  - **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.
732
742
  - `enabled` defaults to `true` if omitted.
733
743
  - `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`.
734
- - `apiKey` is used as the upstream credential value and is required for regular providers.
735
- - `authType` (optional): Controls how `apiKey` is sent upstream. Supports `x-api-key` and `authorization` for regular providers. Anthropic providers default to `x-api-key`; OpenAI-compatible and OpenAI Responses providers default to `authorization`. When set to `authorization`, the proxy sends `Authorization: Bearer <apiKey>`. `oauth2` is reserved for the built-in `codex` provider and is written automatically by `auth login --provider codex`.
744
+ - `apiKey` is used as the upstream credential value and is required unless `authType` is `azure-entra`.
745
+ - `authType` (optional): Controls upstream authentication. Supports `x-api-key`, `authorization`, and `azure-entra` for regular providers. Anthropic providers default to `x-api-key`; OpenAI-compatible and OpenAI Responses providers default to `authorization`. `authorization` sends `Authorization: Bearer <apiKey>`. `azure-entra` uses Azure Identity's `DefaultAzureCredential` with the `https://cognitiveservices.azure.com/.default` scope, sends the resulting bearer token, and does not require `apiKey`. For an Azure OpenAI v1 endpoint, use a provider such as `{ "type": "openai-compatible", "baseUrl": "https://<resource-name>.openai.azure.com/openai", "authType": "azure-entra" }`. Authenticate locally with `az login`, use a managed identity in Azure, or set the standard `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, and `AZURE_CLIENT_SECRET` environment variables. `oauth2` is reserved for the built-in `codex` provider and is written automatically by `auth login --provider codex`.
736
746
  - `pricingCurrency` (optional): Provider-level currency used for token cost calculation, for example `USD` or `CNY`. Quick providers default to `CNY` for DashScope and DeepSeek, and `USD` for Codex, Kimi, OpenCode Go, and OpenRouter. Costs are grouped by currency and are not exchange-rate converted.
737
747
  - `models` (optional): Per-model configuration map. Each key is a model ID (matching the model name in requests), and the value is:
738
748
  - `temperature` (optional): Default temperature value used when the request does not specify one.
@@ -743,12 +753,13 @@ Gateway API keys live under `auth.apiKeys` in `config.json`. Manage them with `c
743
753
  - `contextCache` (optional): Defaults to `true` for providers whose name is `dashscope` or whose `baseUrl` contains `aliyuncs.com`; defaults to `false` for other OpenAI-compatible providers. This enables Alibaba Cloud Model Studio/DashScope explicit context cache by injecting `cache_control: { "type": "ephemeral" }` on up to 4 content blocks using the Context Cache format. The cache breakpoint strategy matches opencode's main provider flow: the first 2 system messages plus the last 2 non-system messages. Marked string content is converted to text content part arrays for `system` / `user` / `assistant` / `tool` messages; existing array content is marked on the last part. Set this to `false` when the model already supports implicit caching, or when the upstream does not accept this explicit-cache extension field. Set this to `true` for non-DashScope providers that support the same explicit-cache extension. Applied on both `/v1/messages` and `/v1/chat/completions` routes.
744
754
  - `supportPdf` (optional): Controls whether the model supports PDF/document content. Defaults to `false`; unsupported PDFs are converted to a text notice. Set it to `true` to send PDF/document blocks as OpenAI Chat Completions file parts.
745
755
  - `toolContentSupportType` (optional): Tool result content capabilities for that model, as an array of `array`, `image`, and `pdf`. Provider routes default to string-only tool content when omitted. If `supportPdf` is `true` but this list does not include `pdf`, file parts in tool results are moved to user role messages. The Copilot main flow uses the same string-only default, because some Copilot models do not support array or image tool content either.
746
- - `type` (optional): Per-model override of the provider protocol type. Supports `anthropic`, `openai-compatible`, and `openai-responses`. When set, the provider's `/v1/messages` route uses this model's type instead of the provider-level type for request routing, auth header resolution, and upstream endpoint selection. This is useful for providers like OpenCode Go whose upstream supports both OpenAI-compatible and Anthropic Messages APIs for different models. When the type is overridden, the auth header is resolved from the overridden type's default (Anthropic defaults to `x-api-key`; OpenAI-compatible/Responses default to `authorization`).
756
+ - `type` (optional): Per-model override of the provider protocol type. Supports `anthropic`, `openai-compatible`, and `openai-responses`. When set, the provider's `/v1/messages` route uses this model's type instead of the provider-level type for request routing, auth header resolution, and upstream endpoint selection. This is useful for providers like OpenCode Go whose upstream supports both OpenAI-compatible and Anthropic Messages APIs for different models. When the type is overridden, the auth header is resolved from the overridden type's default (Anthropic defaults to `x-api-key`; OpenAI-compatible/Responses default to `authorization`). Providers configured with `azure-entra` keep their Entra bearer credential instead of falling back to the overridden type's default.
747
757
  - `contextWindow` (optional): Context window token limit advertised when this model is merged into the Codex-UA model catalog; for example, `1000000` declares a 1M-token context window. Missing configured values use upstream metadata first, then the built-in non-GPT model catalog, then `256000`.
748
758
  - `maxOutputTokens` (optional): Maximum output token limit advertised in the Codex-UA model catalog. Missing configured values use upstream metadata first, then the built-in non-GPT model catalog, where defaults are capped at `64000`, then `32000`.
749
759
  - `inputModalities` (optional): Supported Codex input types. Use `["text", "image"]` for a model that accepts both text and images. Missing configured values use upstream metadata before the built-in non-GPT model catalog. GPT models do not receive these built-in capability defaults and continue to use the native Codex catalog or upstream metadata.
750
760
  - `reasoningEfforts` (optional): Reasoning levels advertised for Codex. Missing configured and upstream values use the built-in non-GPT model catalog before falling back to `["high", "xhigh", "max", "ultra"]`. Provider Responses requests with an unsupported effort are normalized to a supported level when these capabilities are known.
751
761
  - `defaultReasoningEffort` (optional): Default Codex reasoning level. Built-in model metadata may provide a known default; otherwise it defaults to `max` when available, then the first configured level. Synthetic Codex models always enable parallel tool calls.
762
+ - `reasoningField` (optional): Assistant thinking field sent upstream on OpenAI-compatible `/v1/messages` requests. Supports `reasoning` and `reasoning_content`; defaults to `reasoning_content`. Use `reasoning` for OpenRouter-style models; the built-in catalog already does this for OpenCode Go `hy3` and `hy4-preview`.
752
763
  - **smallModel:** Fallback model used for tool-less warmup messages (e.g., Claude Code probe requests); defaults to gpt-5-mini. The gateway forces this small model on no-tool warmup or probe requests to avoid consuming premium requests. This behavior only applies to non-token-based-billing GitHub Copilot accounts (`token_based_billing` is false); for token-based-billing accounts the warmup small-model fallback is skipped since there is no premium-request quota to preserve.
753
764
  - **contextManagement:** Controls whether the proxy adds Responses API `context_management` compaction instructions. `messages` applies when Anthropic-style `/v1/messages` requests are translated to Responses API, including `openai-responses` provider message routes, and defaults to `true`. `responses` applies to native `/v1/responses` traffic, including `provider/model` aliases and the built-in `codex` provider, and defaults to `false`. Enable `responses` only after checking that your client supports context management compaction. When enabled, the request includes `context_management` in the body and keeps only the latest compaction carrier on follow-up turns. The proxy only adds context management and compacts history for `gpt-*` models; both configuration switches have no effect on non-GPT models such as Grok. **Note:** Context management is also forcibly disabled for GPT-5.6 and above models (e.g. `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`) because enabling it breaks prompt cache hits on those models. These overrides take precedence over the `contextManagement` and `modelResponsesApiCompactThresholds` settings.
754
765
  - **modelResponsesApiCompactThresholds:** Per-model Responses API `compact_threshold` overrides used when the proxy adds `context_management`. These values take precedence over the fallback threshold from `resolveResponsesCompactThreshold` (`max_prompt_tokens * ratio`, or the default fallback). Defaults set `gpt-5.4` and `gpt-5.5` to `217600` (`272000 * 0.8`). Models not listed continue to use the normal fallback logic.
@@ -758,7 +769,20 @@ Gateway API keys live under `auth.apiKeys` in `config.json`. Manage them with `c
758
769
  - **Configuration values:** `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`.
759
770
  - **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`.
760
771
  - **useResponsesApiCompactionRecovery (experimental):** When `true`, successful remote Responses compactions enqueue a non-blocking, low-reasoning shadow-summary request and store only that summary under a hash of the opaque compaction item in the private `~/.local/share/copilot-api/compaction-recovery/cache.sqlite` directory. If Copilot later rejects that compaction or connection-bound history, HTTP requests progressively rebuild the request from cached summaries and visible messages. This option defaults to `false` because shadow summaries add one background model request and recovery is lossy. WebSocket errors are recovered on the client's next retry; automatic same-request recovery is HTTP-only.
761
- - **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.
772
+ - **useResponsesApiWebSocket:** Controls upstream Copilot Responses WebSocket use for models that advertise `ws:/responses`; HTTP is used where the model advertises `/responses` and WebSocket is disabled or unavailable in its endpoint metadata. Defaults to `true`. Also supplies the legacy default for `codex` when its independent override is omitted. Copilot WebSocket failures are not retried automatically over HTTP.
773
+ - **useCodexResponsesApiWebSocket (optional):** Overrides WebSocket use only for streamed Responses requests to the built-in `codex` (ChatGPT OAuth) provider, including requests translated from Messages. A boolean `false` forces HTTP and `true` selects WebSocket; omission inherits `useResponsesApiWebSocket` for backward compatibility. Non-streaming requests remain HTTP. A Codex WebSocket connection failure **before any send attempt** falls back to HTTP once, unless cancelled or carrying `previous_response_id`/`conversation` state. After send is attempted, no automatic replay occurs—even before the first event—because the upstream may already be executing the request. HTTP fallback failure is surfaced normally. This does not add a client-facing WebSocket endpoint, guarantee uninterrupted streams, or change third-party providers.
774
+
775
+ To enable WebSocket only between the gateway and ChatGPT while keeping Copilot on HTTP:
776
+
777
+ ```json
778
+ {
779
+ "useResponsesApiWebSocket": false,
780
+ "useCodexResponsesApiWebSocket": true
781
+ }
782
+ ```
783
+
784
+ Merge these keys into the intended API Home's existing `config.json`; do not replace the entire file. These are gateway-to-upstream settings. Keep the Codex client's gateway provider at `supports_websockets = false`, since client-facing Responses traffic still uses HTTP/SSE. Configuration is cached; restart the intended gateway instance after changing the file. To disable the Codex override explicitly, set it to `false`; to restore legacy inheritance, remove that key.
785
+ - **useCopilotFastTier:** Controls whether a client request with `service_tier: "fast"` or `"priority"` may route to a paired Copilot `*-fast` model. Defaults to `true`. Set it to `false` to force the standard model even when a Codex task retains a hidden Fast speed-tier selection. When enabled, an explicit upstream Fast 429 falls back once to the paired standard model and temporarily cools Fast routing according to `Retry-After` (30 seconds by default, capped at 5 minutes).
762
786
  - **responsesTransport:** Positive integer lifecycle and buffering limits for every upstream Responses transport. Invalid, zero, or negative values fall back to the defaults shown above. `headersTimeoutMsV2` 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.
763
787
  - **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`.
764
788
  - **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.
@@ -772,7 +796,7 @@ Edit this file to customize prompts or swap in your own fast model. Restart the
772
796
 
773
797
  ## API Authentication
774
798
 
775
- - **Protected non-admin routes:** All routes except `/`, `/usage-viewer`, and `/usage-viewer/` require authentication when `auth.apiKeys` is configured and non-empty.
799
+ - **Protected non-admin routes:** All routes except `/`, `/usage-viewer`, and `/usage-viewer/` require authentication when `auth.apiKeys` is configured and non-empty. Non-loopback listeners require a non-empty `auth.apiKeys` configuration at startup and continue failing closed if the keys are later cleared.
776
800
  - **Admin routes:** All `/admin/*` routes require `auth.adminApiKey`. If it is missing, the server generates one at startup and persists it to `config.json` before serving requests.
777
801
  - **Allowed auth headers:**
778
802
  - `x-api-key: <your_key>`
@@ -804,7 +828,7 @@ These endpoints mimic the OpenAI API structure.
804
828
 
805
829
  | Endpoint | Method | Description |
806
830
  | --------------------------- | ------ | ---------------------------------------------------------------- |
807
- | `POST /v1/responses` | `POST` | OpenAI Most advanced interface for generating model responses. Supports `provider/model` aliases for `openai-responses` providers. |
831
+ | `POST /v1/responses` | `POST` | OpenAI Most advanced interface for generating model responses. Supports `Content-Encoding: zstd` request bodies and `provider/model` aliases for `openai-responses` providers. Zstd request decompression is limited to Responses routes, including provider-scoped aliases. |
808
832
  | `POST /v1/chat/completions` | `POST` | Creates a model response for the given chat conversation. Supports `provider/model` aliases for `openai-compatible` providers and can be used without Copilot when the target provider is configured. |
809
833
  | `GET /v1/models` | `GET` | Lists Copilot models plus enabled provider models using `provider/model-id` IDs. Requests from Codex clients (`User-Agent` beginning with `codex`) are forwarded to the Codex Models upstream. |
810
834
  | `POST /v1/embeddings` | `POST` | Creates an embedding vector representing the input text. |
@@ -816,8 +840,8 @@ These endpoints implement Codex backend APIs. Top-level image requests require a
816
840
  | Endpoint | Method | Description |
817
841
  | -------------------------------------------------------------- | ------ | --------------------------------------------------------------- |
818
842
  | `POST /v1/alpha/search` | `POST` | Routes Codex alpha-search requests to the Codex backend, or handles supported commands locally and through Responses web search. |
819
- | `POST /v1/images/generations` | `POST` | Forwards a JSON image generation request to the Codex Images upstream. When the request omits `Content-Type`, the gateway defaults it to `application/json`. |
820
- | `POST /v1/images/edits` | `POST` | Forwards an image edit request to the Codex Images upstream. Send this request as `multipart/form-data` and let the HTTP client generate the `boundary`; the gateway preserves the incoming content type and streams the upload body. |
843
+ | `POST /v1/images/generations` | `POST` | Forwards a JSON image generation request to the Codex Images upstream. When the request omits `Content-Type`, the gateway defaults it to `application/json`. Configured model mappings apply to the request `model`; a mapping that resolves to a `provider/model` alias forwards the request to that provider's images endpoint when the provider is configured. |
844
+ | `POST /v1/images/edits` | `POST` | Forwards an image edit request to the Codex Images upstream. Send this request as `multipart/form-data` and let the HTTP client generate the `boundary`; the gateway preserves the incoming content type and buffers up to 64 MiB before forwarding it. Larger requests return `413`. Model mappings and `provider/model` alias routing apply to this endpoint as well. |
821
845
 
822
846
  For requests routed to the Codex backend, the gateway replaces client authorization and account headers with the active Codex login and preserves compatible request metadata. Responses-backed alpha search instead follows the selected Copilot or provider route.
823
847
 
@@ -856,7 +880,8 @@ Common `npx` commands:
856
880
  npx xiaodcs-copilot-api-edge@latest start
857
881
 
858
882
  # Start on a custom port with verbose logging
859
- npx xiaodcs-copilot-api-edge@latest start --port 8080 --verbose
883
+ npx xiaodcs-copilot-api-edge@latest auth keys --add your-gateway-api-key
884
+ npx xiaodcs-copilot-api-edge@latest start --host 0.0.0.0 --port 8080 --verbose
860
885
 
861
886
  # Run the auth flow
862
887
  npx xiaodcs-copilot-api-edge@latest auth login
@@ -894,3 +919,7 @@ Same reminders as `CLAUDE_PLUGIN_ENABLE_QUESTION_RULES=1` in the `agent-inject`
894
919
  - Prohibited from directly asking questions to users, MUST use question tool.
895
920
  - 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.
896
921
  ```
922
+
923
+ ## Builtin Qoder SDK provider
924
+
925
+ Run `copilot-api auth login --provider qoder` (Edge: `copilot-api-edge`), enter your Qoder PAT, then start the gateway normally. Credentials use the existing protected `config.json`; no separate sidecar or bridge key is needed. Supports text/image Chat Completions, SSE, model discovery and Credits. See [setup and capability limits](qoder-bridge/README.md). This integration is included in source and awaits npm release.
package/README.zh-CN.md CHANGED
@@ -68,7 +68,8 @@ curl http://localhost:4141/v1/models
68
68
  - **统一 API 网关**:在同一个本地端点上提供 OpenAI 兼容的 Chat Completions(`/v1/chat/completions`)、OpenAI Responses API(`/v1/responses`)和 Anthropic 兼容的 Messages(`/v1/messages`)。
69
69
  - **多 Provider 接入**:在同一个网关后面统一路由 GitHub Copilot、内置 `codex` provider 和第三方 provider(Kimi、DeepSeek、DashScope、OpenRouter、OpenCode Go 或自定义 provider)。GitHub Copilot 是可选能力——只要至少有一个启用中的 provider,无需 GitHub token 也能按 provider-only 模式启动。
70
70
  - **为 Coding Agent 而生**:为 Claude Code、OpenCode 和 Codex 提供完整的配置指南,包括交互式 `--claude-code` 启动器和面向 Codex 的合并模型目录。
71
- - **Streaming 与 WebSocket**:三种面向客户端的协议都支持 SSE 流式输出。上游 Copilot Responses 流量会根据每个模型声明的端点选择 WebSocket 或 HTTP;内置 `codex` provider 的流式 Responses 请求默认走 WebSocket,关闭 `useResponsesApiWebSocket` 后改走 HTTP。
71
+ - **Streaming 与 WebSocket**:三种面向客户端的协议都支持 SSE 流式输出。上游 Copilot Responses 流量根据模型声明的端点选择 WebSocket 或 HTTP;内置 `codex` provider 可用 `useCodexResponsesApiWebSocket` 独立选择传输,未设置时继承 `useResponsesApiWebSocket`。
72
+ - **Codex 额度日志**:正常额度快照仅在 debug / `--verbose` 模式显示;窗口已用额度达到 90%、`allowed=false` 或 `limit_reached=true` 时保留警告。只降低控制台噪声,不改变额度事件转发、用量记录或请求处理。
72
73
  - **桌面应用**:Electron 图形界面,支持 GitHub Copilot 登录、Codex OAuth、provider 配置、token 用量、日志查看和一键启动 / 停止。
73
74
 
74
75
  <a id="compatibility"></a>
@@ -349,6 +350,8 @@ args = [
349
350
 
350
351
  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(包括流式事件)。
351
352
 
353
+ > **注意:** DeepSeek 模型不使用 Responses Lite(`use_responses_lite: false`、`tool_mode: null`),因此向 Codex 暴露的工具集合与其他模型(`tool_mode: "code_mode_only"`)不一致。在会话中途切换 DeepSeek 模型与 Responses Lite 模型并不兼容——一套工具集合下产生的工具调用和会话历史无法直接沿用到另一套。切换模型时请新建 Codex 会话。
354
+
352
355
  合并后的模型列表会直接展示在 Codex 的模型选择界面中,包含各 provider 暴露的模型:
353
356
 
354
357
  <img src="./docs/screenshots/codex-models.png" alt="Codex 模型选择界面展示网关提供的模型列表" width="900" />
@@ -455,9 +458,12 @@ npx xiaodcs-copilot-api-edge@latest start
455
458
  带参数示例:
456
459
 
457
460
  ```sh
458
- npx xiaodcs-copilot-api-edge@latest start --port 8080
461
+ npx xiaodcs-copilot-api-edge@latest auth keys --add your-gateway-api-key
462
+ npx xiaodcs-copilot-api-edge@latest start --host 0.0.0.0 --port 8080
459
463
  ```
460
464
 
465
+ 绑定到 `0.0.0.0` 会将网关暴露到网络,因此服务要求至少配置一个网关 API Key,并将 CORS 限制为同源请求。
466
+
461
467
  如果只想做认证或 provider 配置:
462
468
 
463
469
  ```sh
@@ -485,15 +491,17 @@ docker build -t copilot-api .
485
491
 
486
492
  ```sh
487
493
  mkdir -p ./copilot-data
494
+ docker run --rm -v $(pwd)/copilot-data:/root/.local/share/copilot-api copilot-api --auth keys --add your-gateway-api-key
488
495
  docker run -p 4141:4141 -v $(pwd)/copilot-data:/root/.local/share/copilot-api copilot-api
489
496
  ```
490
497
 
491
498
  这会把宿主机上的 `./copilot-data` 映射到容器内的 `/root/.local/share/copilot-api`,用于持久化 GitHub 认证数据、provider 配置和其他 gateway 状态。
499
+ 镜像会显式监听 `0.0.0.0` 以支持 Docker 端口映射,并在未配置网关 API Key 时拒绝启动。非回环监听还会将 CORS 限制为请求自身的同源地址。
492
500
 
493
501
  也可以直接通过环境变量传入 GitHub token:
494
502
 
495
503
  ```sh
496
- docker run -p 4141:4141 -e GH_TOKEN=your_github_token_here copilot-api
504
+ docker run -p 4141:4141 -v $(pwd)/copilot-data:/root/.local/share/copilot-api -e GH_TOKEN=your_github_token_here copilot-api
497
505
  ```
498
506
 
499
507
  <a id="electron-desktop-app"></a>
@@ -644,16 +652,16 @@ cp plugin/opencode/subagent-marker.js ~/.config/opencode/plugins/
644
652
 
645
653
  - **API Endpoint URL**:通过 URL 查询参数指定 API endpoints,默认指向本地服务。支持手动切换为其他兼容 endpoints。
646
654
  - **API Key 认证**:如果启用了 API Key 认证,可填入原始 API key(默认通过 `x-api-key` 请求头发送)或 `Authorization: Bearer <key>`。凭据会按 endpoint origin 保存在浏览器本地存储中;切换到不同 endpoint origin 时,不会自动携带其他 origin 的凭据。
647
- - **Period 选择器**:支持 Day / Week / Month 三种时间范围,切换时 URL 参数会自动同步,方便收藏和分享。
655
+ - **Period 选择器**:支持六种时间范围:`today`(当前本地日历日至今)、`this_week`(本周一 00:00 至现在)、`last_7_days`(滚动 7 个日历日至现在)、`this_month`(本月 1 00:00 至现在)、`last_30_days`(滚动 30 个日历日至现在)和 `lifetime`(从最早记录事件至现在)。默认选择 Today,选择器旁会显示具体日期范围;切换时 URL 参数会自动同步,方便收藏和分享。旧版取值 `day`、`week`、`month` 仍被兼容,会自动映射到对应的新值。
648
656
  - **Fetch Data**:点击 "Refresh" 按钮加载或刷新使用数据。页面加载时也会自动拉取数据。
649
657
  - **Copilot Quotas 额度**:通过进度条展示 Chat、Completions 等不同服务的额度使用情况,悬停可查看已用/剩余详情。
650
658
  - **Token Usage 指标卡片**:汇总当前周期的 Total、Input、Output、Cache Read、Cache Write、Requests 和预估费用。
651
- - **趋势图(Week / Month)**:提供按模型和指标筛选的折线趋势图,点击数据点可查看单日用量明细。
659
+ - **趋势图**:提供按所选周期、模型和指标筛选的折线趋势图,点击数据点可查看用量明细;Lifetime 图表数据从每日数据桶中采样,最多显示 180 个点,以便查看长期趋势。
652
660
  - **Model Breakdown 表格**:按模型维度列出周期内的请求数、输入/输出/缓存 token 和预计费用。
653
661
  - **Request Events 分页列表**:按时间排序的请求事件记录,支持分页浏览,含时间戳、模型、请求 ID 和 token 用量。
654
662
  - **Detailed Information**:展示 API 返回的完整 JSON 响应,便于深入分析所有可用统计数据。
655
663
  - **URL-based Configuration**:也可通过 `endpoint` 和 `period` 查询参数直接指定 API 端点与时间范围。例如:
656
- `http://localhost:4141/usage-viewer?endpoint=http://your-api-server/usage&period=week`
664
+ `http://localhost:4141/usage-viewer?endpoint=http://your-api-server/usage&period=this_week`
657
665
 
658
666
  ### Usage Viewer 截图
659
667
 
@@ -691,6 +699,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
691
699
 
692
700
  | 选项 | 说明 | 默认值 | 别名 |
693
701
  | --- | --- | --- | --- |
702
+ | --host | 监听主机;非回环地址要求已配置网关 API Key | 127.0.0.1 | 无 |
694
703
  | --port | 监听端口 | 4141 | -p |
695
704
  | --verbose | 启用详细日志 | false | -v |
696
705
  | --github-token | 直接提供 GitHub token(必须通过 `auth` 子命令生成) | 无 | -g |
@@ -712,7 +721,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
712
721
 
713
722
  使用 `copilot-api auth login --provider custom` 可以通过 CLI 新增或更新其他第三方 provider。命令会依次提示输入 provider name、项目支持的 type(`anthropic`、`openai-compatible` 或 `openai-responses`)、`baseUrl`、掩码显示的 `apiKey` 和 `authType`;`authType` 可保持 type 默认值,也可选择 `x-api-key` / `authorization`。
714
723
 
715
- 网关 API Key 存放在 `config.json` 的 `auth.apiKeys` 中,可通过 `copilot-api auth keys` 管理(每次只执行一种操作):`--add <key>` 添加、`--remove <key>` 删除、`--list` 列出全部、`--clear` 清空。客户端通过 `x-api-key` 或 `Authorization: Bearer` 使用任意已配置的 Key 认证。未配置任何 Key 时,`copilot-api start` 会以“不校验认证”的方式启动并输出一条 info 级别的启动提示。
724
+ 网关 API Key 存放在 `config.json` 的 `auth.apiKeys` 中,可通过 `copilot-api auth keys` 管理(每次只执行一种操作):`--add <key>` 添加、`--remove <key>` 删除、`--list` 列出全部、`--clear` 清空。客户端通过 `x-api-key` 或 `Authorization: Bearer` 使用任意已配置的 Key 认证。未配置任何 Key 时,回环监听会以“不校验认证”的方式启动并输出一条 info 级别提示;非回环监听则拒绝启动。
716
725
 
717
726
  ### Debug 命令选项
718
727
 
@@ -752,6 +761,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
752
761
  "useMessagesApi": true,
753
762
  "useResponsesApiCompactionRecovery": false,
754
763
  "useResponsesApiWebSocket": true,
764
+ "useCopilotFastTier": true,
755
765
  "responsesTransport": {
756
766
  "headersTimeoutMsV2": 300000,
757
767
  "streamInactivityTimeoutMs": 300000,
@@ -766,15 +776,15 @@ Copilot API 现在使用子命令结构,主要命令包括:
766
776
  "messageApiWebSearchModel": "gpt-5-mini"
767
777
  }
768
778
  ```
769
- - **auth.apiKeys:** 用于普通非 admin 路由的 API key。支持多个 key 轮换使用。请求可通过 `x-api-key: <key>` 或 `Authorization: Bearer <key>` 进行认证。若为空或省略,则普通路由的认证会被禁用。
779
+ - **auth.apiKeys:** 用于普通非 admin 路由的 API key。支持多个 key 轮换使用。请求可通过 `x-api-key: <key>` 或 `Authorization: Bearer <key>` 进行认证。若为空或省略,仅回环监听会禁用普通路由认证;非回环监听会拒绝启动。
770
780
  - **auth.adminApiKey:** 仅用于 `/admin/*` 路由的单个 admin key。若未配置,服务会在启动时自动生成一个随机 key,并回写到 `config.json`。它同样使用 `x-api-key` 或 `Authorization: Bearer` 这两种头,但普通 `auth.apiKeys` 不能访问 `/admin/*`。
771
781
  - **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` 管理接口读写的也只有这个字段。
772
782
  - **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,让模型在工具调用或更深层推理前先发出简短的用户可见进度说明。
773
783
  - **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`。
774
784
  - `enabled`:可选,若省略则默认为 `true`。
775
785
  - `baseUrl`:provider API 的基础 URL,不要带结尾的 endpoint。Anthropic provider 不要带 `/v1/messages`;OpenAI 兼容 provider 不要带 `/v1/chat/completions`;OpenAI Responses provider 不要带 `/v1/responses`。
776
- - `apiKey`:作为上游凭据值使用;普通 provider 必须配置。
777
- - `authType`:可选,控制 `apiKey` 如何发送到上游。普通 provider 支持 `x-api-key` 和 `authorization`。Anthropic provider 默认 `x-api-key`;OpenAI 兼容和 OpenAI Responses provider 默认 `authorization`。当设置为 `authorization` 时,代理会发送 `Authorization: Bearer <apiKey>`。`oauth2` 仅保留给内置 `codex` provider,并由 `auth login --provider codex` 自动写入。
786
+ - `apiKey`:作为上游凭据值使用;除 `authType` 为 `azure-entra` 外,普通 provider 必须配置。
787
+ - `authType`:可选,控制上游认证方式。普通 provider 支持 `x-api-key`、`authorization` 和 `azure-entra`。Anthropic provider 默认 `x-api-key`;OpenAI 兼容和 OpenAI Responses provider 默认 `authorization`。`authorization` 会发送 `Authorization: Bearer <apiKey>`。`azure-entra` 使用 Azure Identity 的 `DefaultAzureCredential` 和 `https://cognitiveservices.azure.com/.default` scope 获取并发送 Bearer token,不需要配置 `apiKey`。Azure OpenAI v1 endpoint 可配置为 `{ "type": "openai-compatible", "baseUrl": "https://<resource-name>.openai.azure.com/openai", "authType": "azure-entra" }`。本地可先执行 `az login`,在 Azure 中可使用托管身份,也可设置标准的 `AZURE_TENANT_ID`、`AZURE_CLIENT_ID` 和 `AZURE_CLIENT_SECRET` 环境变量。`oauth2` 仅保留给内置 `codex` provider,并由 `auth login --provider codex` 自动写入。
778
788
  - `pricingCurrency`:可选,provider 维度的 token 费用币种,例如 `USD` 或 `CNY`。快捷 provider 默认 DashScope、DeepSeek 为 `CNY`,Codex、Kimi、OpenCode Go、OpenRouter 为 `USD`。费用按币种分别汇总,不做汇率换算。
779
789
  - `models`:可选,按模型 ID 配置的映射。每个键为请求中的模型名,值支持:
780
790
  - `temperature`:可选,当请求未指定时使用的默认温度。
@@ -785,12 +795,13 @@ Copilot API 现在使用子命令结构,主要命令包括:
785
795
  - `contextCache`:可选,provider name 为 `dashscope` 或 `baseUrl` 包含 `aliyuncs.com` 时默认 `true`,其他 OpenAI 兼容 provider 默认 `false`。用于启用阿里云百炼/DashScope 的显式缓存(explicit context cache),会按其 Context Cache 格式在最多 4 个 content block 上注入 `cache_control: { "type": "ephemeral" }`。缓存断点策略与 opencode 主链路保持一致:前 2 条 system 消息 + 最后 2 条非 system 消息。标记字符串 content 时会把 `system` / `user` / `assistant` / `tool` 消息转换为 text content part 数组;已有数组 content 则标记最后一个 part。如果模型本身已经支持隐式缓存,或上游不支持该显式缓存扩展字段,可在模型配置中设为 `false`。支持相同显式缓存扩展的非 DashScope provider 可设为 `true`。同时适用于 `/v1/messages` 和 `/v1/chat/completions` 路由。
786
796
  - `supportPdf`:可选,控制该模型是否支持 PDF/document content。默认 `false`,不支持时会把 PDF 转成提示文本;设为 `true` 时会把 PDF/document 转成 OpenAI Chat Completions 的 file part。
787
797
  - `toolContentSupportType`:可选,配置该模型的 tool result content 支持能力,值为 `array`、`image`、`pdf` 的数组。provider 侧未配置时默认只发送 string tool content。若 `supportPdf` 为 `true` 但这里不包含 `pdf`,tool result 里的 file part 会被转成 user role 消息。Copilot 主链路同样默认只发送 string tool content,因为部分 Copilot 模型也不支持数组或图片形式的 tool content。
788
- - `type`:可选,按模型覆盖 provider 的协议类型。支持 `anthropic`、`openai-compatible` 和 `openai-responses`。设置后,provider 的 `/v1/messages` 路由会使用该模型的 type 替代 provider 级别的 type 进行请求路由、认证头解析和上游端点选择。适用于 OpenCode Go 等上游对不同模型同时支持 OpenAI 兼容和 Anthropic Messages API 的 provider。覆盖 type 时,认证头按覆盖后 type 的默认值解析(Anthropic 默认 `x-api-key`;OpenAI 兼容/Responses 默认 `authorization`)。
798
+ - `type`:可选,按模型覆盖 provider 的协议类型。支持 `anthropic`、`openai-compatible` 和 `openai-responses`。设置后,provider 的 `/v1/messages` 路由会使用该模型的 type 替代 provider 级别的 type 进行请求路由、认证头解析和上游端点选择。适用于 OpenCode Go 等上游对不同模型同时支持 OpenAI 兼容和 Anthropic Messages API 的 provider。覆盖 type 时,认证头按覆盖后 type 的默认值解析(Anthropic 默认 `x-api-key`;OpenAI 兼容/Responses 默认 `authorization`)。配置了 `azure-entra` 的 provider 在覆盖 type 时会保留 Entra bearer 凭证,而不会回退到覆盖后 type 的默认值。
789
799
  - `contextWindow`:可选,模型合并到 Codex UA 模型列表时声明的上下文窗口 token 上限;例如 `1000000` 表示 1M token 上下文。用户未配置时依次使用上游元数据、非 GPT 模型的内置目录和 `256000`。
790
800
  - `maxOutputTokens`:可选,Codex UA 模型列表中声明的最大输出 token 数。用户未配置时优先使用上游元数据,其次使用非 GPT 模型的内置目录(内置默认值最高为 `64000`),最后默认为 `32000`。
791
801
  - `inputModalities`:可选,Codex 支持的输入类型;模型同时支持文本和图片时配置为 `["text", "image"]`。用户未配置时优先使用上游元数据,再使用非 GPT 模型的内置目录。GPT 模型不注入这些内置能力默认值,继续使用原生 Codex catalog 或上游元数据。
792
802
  - `reasoningEfforts`:可选,Codex 支持的推理档位。配置和上游元数据均未提供时,会先使用非 GPT 模型的内置目录,再回退到 `["high", "xhigh", "max", "ultra"]`。已知模型能力时,Provider Responses 请求中的不支持档位会被归一化为支持的档位。
793
803
  - `defaultReasoningEffort`:可选,Codex 默认推理档位;内置模型元数据可以提供已知默认值,否则可用档位包含 `max` 时默认取 `max`,再回退到配置的第一个档位。合成 Codex 模型始终启用并行工具调用。
804
+ - `reasoningField`:可选,OpenAI-compatible `/v1/messages` 转发 assistant 思考文本时使用的字段,支持 `reasoning` 与 `reasoning_content`,默认 `reasoning_content`;OpenRouter 风格模型设为 `reasoning`,内置目录已为 OpenCode Go `hy3`、`hy4-preview` 配置该值。
794
805
  - **smallModel:** 无工具预热消息的回退模型(例如 Claude Code 的探测请求);默认是 `gpt-5-mini`。网关会对无工具的预热或探测请求强制使用该小模型,以避免消耗 premium 请求。该行为仅在 GitHub Copilot 账户为非 token-based 计费时生效(`token_based_billing` 为 false);对于 token-based 计费账户,预热小模型回退会被跳过,因为不存在需要节省的 premium 请求配额。
795
806
  - **contextManagement:** 控制代理是否为 Responses API 附加 `context_management` 压缩指令。`messages` 作用于被翻译成 Responses API 的 Anthropic 风格 `/v1/messages` 请求,包括 `openai-responses` provider 的 Messages 路由,默认值为 `true`。`responses` 作用于 native `/v1/responses` 流量,包括 `provider/model` 别名和内置 `codex` provider,默认值为 `false`。只有在确认客户端支持 context management compaction 后,才建议在 Responses API 下启用 `responses`。启用后,请求体会带上 `context_management`,并在后续轮次中仅保留最新的压缩承载内容。代理仅为 `gpt-*` 模型添加 context management 并压缩历史;这两个配置开关对 Grok 等非 GPT 模型不生效。**注意:** 对于 GPT-5.6 及以上模型(如 `gpt-5.6-sol`、`gpt-5.6-terra`、`gpt-5.6-luna`),context management 功能同样会被强制禁用,因为开启后会破坏这些模型的 prompt 缓存命中。这些强制覆盖优先于 `contextManagement` 和 `modelResponsesApiCompactThresholds` 配置。
796
807
  - **modelResponsesApiCompactThresholds:** 按模型覆盖 Responses API 的 `compact_threshold`,仅在代理自动附加 `context_management` 时使用。它的优先级高于 `resolveResponsesCompactThreshold` 基于 `max_prompt_tokens * ratio` 的兜底阈值。默认将 `gpt-5.4` 和 `gpt-5.5` 设为 `217600`(`272000 * 0.8`)。未列出的模型继续使用原有兜底逻辑。
@@ -800,7 +811,20 @@ Copilot API 现在使用子命令结构,主要命令包括:
800
811
  - **配置可选值:** `none`、`minimal`、`low`、`medium`、`high`、`xhigh`、`max`。
801
812
  - **useMessagesApi:** 当为 `true` 时,声明了 Copilot 原生 `/v1/messages` 端点的模型会使用 Messages API。如果所选模型未声明 Messages 端点或关闭了该配置,网关会在模型声明了 Responses 端点时使用 Responses,否则在模型支持时回退到 Chat Completions。设为 `false` 可跳过原生 Messages 路由。默认值为 `true`。
802
813
  - **useResponsesApiCompactionRecovery(实验性):** 设为 `true` 后,成功的远程 Responses 压缩会异步生成低推理强度的影子摘要,并仅以 opaque compaction 哈希为键保存摘要。当 Copilot 后续拒绝该压缩内容或连接绑定历史时,HTTP 请求会逐步使用缓存摘要与可见消息重建请求。默认关闭,因为影子摘要会增加一次后台模型请求,且恢复过程存在信息损失。WebSocket 错误会在客户端下一次重试时恢复;同一次请求内的自动恢复仅支持 HTTP。
803
- - **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 流量,请关闭该配置或切换网络。
814
+ - **useResponsesApiWebSocket:** 控制上游 Copilot Responses 是否对声明了 `ws:/responses` 的模型使用 WebSocket;关闭或端点元数据不支持 WebSocket 时,在模型声明了 `/responses` 的情况下使用 HTTP。默认 `true`。内置 `codex` 未设置独立开关时也继承此值。Copilot WebSocket 失败后不会自动通过 HTTP 重试。
815
+ - **useCodexResponsesApiWebSocket(可选):** 仅覆盖内置 `codex`(ChatGPT OAuth)provider 的流式 Responses 传输,包括从 Messages 转换的请求。布尔值 `false` 使用 HTTP,`true` 选择 WebSocket;不填时继承 `useResponsesApiWebSocket`,兼容旧配置。非流式请求仍走 HTTP。Codex WebSocket 在**尚未尝试发送请求**时建连失败,会降级 HTTP 一次;已取消或带有 `previous_response_id` / `conversation` 续接状态时不降级。一旦尝试发送,即使尚未收到首个事件,也不会自动重放,因为上游可能已经开始执行。HTTP 降级也失败时正常返回错误。此功能不增加面向客户端的 WebSocket 接口、不保证永不断流,也不改变第三方 provider。
816
+
817
+ 只让网关到 ChatGPT 使用 WebSocket、Copilot 保持 HTTP 的配置:
818
+
819
+ ```json
820
+ {
821
+ "useResponsesApiWebSocket": false,
822
+ "useCodexResponsesApiWebSocket": true
823
+ }
824
+ ```
825
+
826
+ 把这两个键合并到目标 API Home 的现有 `config.json`,不要覆盖整份文件。这是网关连接上游的配置;Codex 客户端连接网关的 provider 仍保留 `supports_websockets = false`,使用 HTTP/SSE。配置会缓存,改文件后需重启对应网关实例。要明确关闭 Codex WebSocket,把独立开关设为 `false`;要恢复旧版继承行为,移除该键。
827
+ - **useCopilotFastTier:** 控制客户端请求中的 `service_tier: "fast"` 或 `"priority"` 是否可以路由到配对的 Copilot `*-fast` 模型,默认值为 `true`。设为 `false` 后,即使 Codex 任务保留了界面中不明显的 Fast 速度档位,也会强制使用标准模型。开启时,若 Fast 上游明确返回 429,会自动回退一次到配对标准模型,并按 `Retry-After` 暂停 Fast 路由(默认 30 秒,最长 5 分钟)。
804
828
  - **responsesTransport:** 所有上游 Responses transport 共用的生命周期与缓冲区正整数限制。无效值、零或负数会回退到上面列出的默认值。`headersTimeoutMsV2` 从连接建立开始计算,到收到 HTTP 响应头为止,并不是整个生成过程的总时限。每收到一个 HTTP body chunk 或 WebSocket message 都会重置 `streamInactivityTimeoutMs`,因此持续活跃的长推理任务不会被短总时限中断。`websocketOpenTimeoutMs` 限制 WebSocket 握手时间;`websocketPoolIdleTimeoutMs` 只控制已正常完成且可复用的空闲连接。WebSocket 队列同时受字节数和消息数上限约束;超过任一上限时会终止该 stream 并使 socket 失效,而不会丢弃或重排事件。
805
829
  - **useResponsesApiWebSearch:** 当为 `true` 时,服务端会保留 Responses API 中 `type: "web_search"` 的工具并透传到上游。设为 `false` 则会从 `/responses` payload 中移除这些工具。默认值为 `true`。
806
830
  - **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。
@@ -816,7 +840,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
816
840
 
817
841
  ## API 认证
818
842
 
819
- - **受保护的普通路由:** 当配置了 `auth.apiKeys` 且非空时,除 `/`、`/usage-viewer` 和 `/usage-viewer/` 以外的普通路由都需要认证。
843
+ - **受保护的普通路由:** 当配置了 `auth.apiKeys` 且非空时,除 `/`、`/usage-viewer` 和 `/usage-viewer/` 以外的普通路由都需要认证。非回环监听要求启动时存在非空的 `auth.apiKeys`,即使运行期间 Key 被清空也会继续以拒绝请求的方式安全失败。
820
844
  - **Admin 路由:** 所有 `/admin/*` 路由都要求 `auth.adminApiKey`。如果缺失,服务会在启动时自动生成并在开始提供服务前写回 `config.json`。
821
845
  - **允许的认证头:**
822
846
  - `x-api-key: <your_key>`
@@ -850,7 +874,7 @@ curl http://localhost:4141/admin/config/model-mappings \
850
874
 
851
875
  | 端点 | 方法 | 说明 |
852
876
  | --------------------------- | ---- | -------------------------------------------------------------------------------------------------------- |
853
- | `POST /v1/responses` | `POST` | OpenAI 中用于生成模型响应的高级接口。支持 `openai-responses` provider 的 `provider/model` 别名。 |
877
+ | `POST /v1/responses` | `POST` | OpenAI 中用于生成模型响应的高级接口。支持 `Content-Encoding: zstd` 请求体和 `openai-responses` provider 的 `provider/model` 别名。zstd 请求解压仅作用于 Responses 路由,包括 provider-scoped 别名路由。 |
854
878
  | `POST /v1/chat/completions` | `POST` | 为给定聊天对话创建模型响应。支持 `openai-compatible` provider 的 `provider/model` 别名;目标 provider 已配置时可在没有 Copilot 的情况下使用。 |
855
879
  | `GET /v1/models` | `GET` | 列出 Copilot 模型以及已启用 provider 的 `provider/model-id` 模型。来自 Codex 客户端(`User-Agent` 以 `codex` 开头)的请求会转发到 Codex Models 上游。 |
856
880
  | `POST /v1/embeddings` | `POST` | 创建表示输入文本的向量嵌入。 |
@@ -862,8 +886,8 @@ curl http://localhost:4141/admin/config/model-mappings \
862
886
  | 端点 | 方法 | 说明 |
863
887
  | ---------------------------------------------------------- | ---- | ---------------------------------------------------------------------------------------------------- |
864
888
  | `POST /v1/alpha/search` | `POST` | 将 Codex alpha-search 请求路由到 Codex 后端,或在本地及通过 Responses web search 处理支持的命令。 |
865
- | `POST /v1/images/generations` | `POST` | 将 JSON 图片生成请求转发到 Codex Images 上游。请求未携带 `Content-Type` 时,网关默认补充 `application/json`。 |
866
- | `POST /v1/images/edits` | `POST` | 将图片编辑请求转发到 Codex Images 上游。请使用 `multipart/form-data`,并让 HTTP 客户端自动生成 `boundary`;网关会保留传入的 content type,并以流式方式转发上传请求体。 |
889
+ | `POST /v1/images/generations` | `POST` | 将 JSON 图片生成请求转发到 Codex Images 上游。请求未携带 `Content-Type` 时,网关默认补充 `application/json`。请求 `model` 命中已配置的 model mapping 时会被改写;映射结果为已配置 provider 的 `provider/model` 别名时,请求将转发到该 provider 的 images 端点。 |
890
+ | `POST /v1/images/edits` | `POST` | 将图片编辑请求转发到 Codex Images 上游。请使用 `multipart/form-data`,并让 HTTP 客户端自动生成 `boundary`;网关会保留传入的 content type,并在转发前最多缓冲 64 MiB,超限请求返回 `413`。model mapping 与 `provider/model` 别名路由同样适用于此端点。 |
867
891
 
868
892
  对于路由到 Codex 后端的请求,网关会使用当前 Codex 登录态覆盖客户端的 authorization 和 account header,并保留兼容的请求元数据。基于 Responses 的 alpha-search 则遵循所选 Copilot 或 provider 的路由。
869
893
 
@@ -904,7 +928,8 @@ curl http://localhost:4141/admin/config/model-mappings \
904
928
  npx xiaodcs-copilot-api-edge@latest start
905
929
 
906
930
  # 自定义端口并开启详细日志
907
- npx xiaodcs-copilot-api-edge@latest start --port 8080 --verbose
931
+ npx xiaodcs-copilot-api-edge@latest auth keys --add your-gateway-api-key
932
+ npx xiaodcs-copilot-api-edge@latest start --host 0.0.0.0 --port 8080 --verbose
908
933
 
909
934
  # 执行认证流程
910
935
  npx xiaodcs-copilot-api-edge@latest auth login
@@ -946,3 +971,7 @@ curl http://localhost:4141/dashscope/v1/messages \
946
971
  - Prohibited from directly asking questions to users, MUST use question tool.
947
972
  - 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.
948
973
  ```
974
+
975
+ ## 内置 Qoder SDK provider
976
+
977
+ 运行 `copilot-api auth login --provider qoder`(Edge 包使用 `copilot-api-edge`),输入 Qoder PAT 后正常启动网关即可。凭证沿用受保护的 `config.json`,无需单独运行 bridge 或配置 bridge key。支持文本和图片输入、SSE、模型目录与 Credits 查询,详见 [Qoder 配置说明](qoder-bridge/README.md)。本次适配已进入源码,尚待 npm 发布。