Use a sub2api-compatible API directly in VS Code Chat and GitHub Copilot Agent mode. The provider is endpoint-neutral: no server address or API key is bundled.
Highlights
- VS Code Stable 1.130+ and VS Code Insiders
- OpenAI Responses, OpenAI Chat Completions, and Anthropic Messages protocols
- Responses is the default and retains encrypted reasoning replay, stable implicit cache routing, and optional GPT-5.6 explicit cache breakpoints
- Streaming text, vision, function tools, and tool results
- One clean picker entry per model, plus visible status-bar selectors for reasoning effort and context management
- Official model context windows plus adaptive gateway-limit learning and stable-boundary compaction
- Per-endpoint/key request serialization and safe concurrency-limit retries
- Live request/session tokens, cache-hit rate, and optional server balance
- API keys stored in VS Code SecretStorage
Get started
- Install from the Visual Studio Marketplace or a VSIX.
- Run
sub2api: Configure Endpointand enter your API base URL. - Run
sub2api: Set API Key. - Keep
sub2api.apiFormatatopenai-responses, or select another compatible protocol. - Run
sub2api: Test Connection, open Chat, and choose a model from thesub2apiprovider.
Stable and Insiders use separate extension installations and SecretStorage databases. Configure the endpoint and key once in each edition you use.
API formats
The sub2api.apiFormat setting controls the wire protocol:
| Setting | Request path | Reasoning field |
|---|---|---|
openai-responses (default) |
/v1/responses |
reasoning.effort |
openai-completions |
/v1/chat/completions |
reasoning_effort |
anthropic-messages |
/v1/messages |
Extended-thinking token budget |
A base URL receives the selected suffix automatically. A full known inference URL is replaced when you switch formats. Only HTTP and HTTPS endpoints are accepted, and credentials embedded in URLs are rejected.
Responses sends stream: true, store: false, and a stable prompt_cache_key. The default auto mode uses compatibility-first implicit caching because some sub2api gateways turn explicit GPT-5.6 cache fields into an opaque HTTP 502. Select explicit only for a gateway known to support those fields; it then uses a fixed startup breakpoint, the previous user boundary for reading the prior round's cache, and the current user boundary for writing the next round's cache. Compatibility fallback is attempted only when the server explicitly identifies an unsupported cache field. A generic 500/502 is never treated as permission to resend the full prompt. Chat Completions uses stream_options.include_usage. Anthropic Messages sends the required Anthropic version header as well as the configured gateway key.
Automatic model routing
Choose sub2api \u00b7 Auto Adaptive in the Chat model picker to route a task without an additional classifier API call. The router only considers model IDs currently listed in sub2api.enabledModels; disabling a model removes it from the automatic subscription scope.
The local scorer considers message/context size, diagnostic and code signals, multi-step requests, vision, advanced engineering keywords, and deep-reasoning indicators. It maps simple, balanced, and complex tasks to the closest enabled model tier, preferring Luna, Terra, and Sol respectively when those models are enabled. The model choice is pinned for later rounds of the same task so tool calls and prompt caches do not repeatedly move between models. The first request also selects an appropriate reasoning effort from the latest user turn; by default that effort is pinned with the model because real gateways can isolate cache entries by Low, Medium, High, XHigh, and Max. If the pinned model can no longer fit the estimated context, the router promotes to an enabled model with enough context.
This is a deterministic cost-saving heuristic, not a guaranteed semantic judgment. It adds no classifier tokens and logs only the score, reason labels, selected model, and enabled model IDs?not prompt text. Manually select a specific model when a task has unusual stakes or when you need guaranteed model choice.
Reasoning selector
Click the reasoning icon in the Copilot Chat title bar, or sub2api Reasoning in the status bar to choose Model, Low, Medium, High, XHigh, or Max. The selection is forwarded on subsequent requests. "Model" follows the selected model variant or a reasoning setting supplied by VS Code.
Each enabled upstream model now appears only once in the model picker. Reasoning depth is selected exclusively through the separate visible Chat-title/status-bar control, keeping Low, Medium, High, XHigh, and Max out of the model list. Legacy model::effort IDs remain accepted for existing chats.
With sub2api.autoReasoningMode: pinned (default), Auto Adaptive chooses effort once per conversation and keeps it stable for cache locality. Set it to perTurn only when adapting effort on every question matters more than the extra cold-cache cost. A manual change from Low to High/XHigh can likewise enter a different upstream cache partition even though the model ID and client cache key stay unchanged.
Context and compaction
The catalog stores each model's total context window and maximum output. For each picker entry, the provider now calculates:
maxInputTokens = total context window - selected output budget - safety margin
With the default 32,768 output budget and 8,192 safety margin, this leaves 1,009,040 input tokens on a 1.05M model instead of permanently reserving the full 128K maximum output.
| Models | Total context window | Maximum output | Source |
|---|---|---|---|
| GPT-5.3 Codex Spark | 128,000 | 32,000 | sub2api gateway-specific model limit |
| Codex Mini | 200,000 | 100,000 | OpenAI model page |
| GPT-5.2, GPT-5.4 Mini | 400,000 | 128,000 | GPT-5.2, GPT-5.4 Mini |
| GPT-5.4, GPT-5.5, GPT-5.6 variants | 1,050,000 | 128,000 | GPT-5.4, GPT-5.5, GPT-5.6 Sol |
A compatible gateway can expose a smaller effective limit than the upstream model. In automatic mode, the provider initially advertises the official limit. If the gateway returns a context-window error, the provider learns a conservative endpoint/model/protocol-specific input budget, persists it in VS Code global state, updates the picker limit, and retries once without collapsing the conversation to a fixed 120K suffix.
Adaptive trimming preserves a fingerprinted boundary. Later turns reuse the same retained prefix until the conversation reaches the learned limit again; only then is a new boundary created with the configured headroom. This reduces the repeated cold-cache requests caused by shifting the first retained message on every turn.
Click the context icon in the Copilot Chat title bar, or sub2api Context in the status bar, to:
- compact the next request once;
- enable adaptive trimming (default);
- disable provider-side automatic trimming; or
- open context settings.
Leave sub2api.contextWindowCap at 0 to use each model's official total context window. Set it only when you already know the gateway's smaller total limit; custom values must be at least 16384. Version 1.0.15 automatically repairs legacy values from 1 through 16383 back to 0, because an accidental value such as 1 makes Copilot discard its entire prompt before invoking the provider. sub2api.requestSafetyRatio controls how much of a configured or learned input limit is retained when a new stable boundary is created; its default of 0.85 leaves room for several later turns.
Provider-side trimming keeps recent serialized messages but cannot create a semantic summary. VS Code/Copilot owns chat-level semantic compaction; when the old details are important, use Chat's compact action if available or start a fresh chat.
If Copilot invokes the provider with an empty message array, version 1.0.14 and later block the call locally before endpoint lookup or network I/O, so it cannot be billed. The most common confirmed cause is an invalid one-token sub2api.contextWindowCap; version 1.0.15 repairs that setting before registering the provider, allowing Copilot to render and send the real semantic-summary prompt.
Usage, cache, and balance
The usage status item shows spent and remaining USD allowance when /v1/usage supplies quota data; otherwise it shows the latest cache hit rate and cumulative tokens for this VS Code session. Hover it for input, cached, uncached, cache-write, output, and session totals. Click it to open the usage panel.
With sub2api.usageEndpoint: auto, the provider derives /v1/usage and refreshes it every five minutes and after completed requests. Compatible deployments can supply API-key quota (used, remaining, and limit), wallet balance, subscription daily/weekly/monthly windows, rate limits, today/total actual cost, and model statistics. If that endpoint is unavailable, request/session token metrics still work from inference responses. Status bars, hover details, selectors, notifications, and command titles automatically use Chinese when the VS Code display language starts with zh; otherwise they use English. Use a full sub2api.usageEndpoint override for deployments with a different path, or set it to an empty string to disable quota requests.
Responses cache routing is derived from the complete endpoint path, workspace, and cache scope. The default sub2api.promptCacheScope: family shares one affinity route and stable trim route across GPT-5.6 Sol, Terra, Luna, and base aliases; unrelated families remain isolated. Set it to model if a gateway requires exact-model routing. The shared key improves gateway affinity but cannot make model-specific KV tensors portable between different model backends. The route intentionally does not depend on the retained user message, so Copilot compaction, a changed trim boundary, and switching Max/XHigh do not change affinity. The gateway still requires an exact rendered prefix and can enforce stricter model-level isolation. Tool definitions and schemas are sorted, then a fixed developer content block marks the boundary immediately before the changing Copilot conversation. On each round, the two most recent user boundaries are marked: the older one reads the position written on the previous round, while the newest one writes the position needed by the next round. This follows the OpenAI GPT-5.6 prompt-caching guidance.
The first request after this cache-key upgrade, cache expiry, or changing the Copilot tool set is necessarily a cold cache write. Switching among compatible GPT-5.6 aliases no longer changes the client cache route, but a gateway that physically isolates caches by exact upstream model can still report a cold write. A cache cannot be read before an equivalent prefix has been written. Later independent chats can reuse the fixed startup prefix while the tool set and provider prefix remain identical. GPT-5.6 cache entries request a 30-minute TTL, and the usage log reports both cache reads and writes.
In explicit mode, rejected cache features are remembered in VS Code global state per endpoint path, protocol, and upstream model. The result contains no API key or prompt data and expires after seven days. Generic upstream 500/502 failures are not compatibility probes and are not automatically resent. Run sub2api: Re-detect Prompt Cache Compatibility after upgrading or reconfiguring a gateway if you want to test explicit mode again.
Privacy and security
- Keys are stored in VS Code SecretStorage, never settings.
- Prompt contents and keys are never written to logs.
- No endpoint is preconfigured or contacted before you configure one.
- Review the privacy, retention, and billing policy of your chosen endpoint.
Troubleshooting
Run sub2api: Show Logs for request number, anonymized request fingerprint, protocol, model, advertised input limit, conservative estimate, cache strategy, breakpoint count, startup-boundary presence, anonymized tool/provider foundation and stable-prefix fingerprints, cache expectation/cold reason, route fingerprint, usage, and server error bodies. In explicit mode, two new-chat requests can reuse the startup cache only when promptCacheFoundation matches and promptCacheBreakpoints is greater than zero. In Auto/implicit mode, use the returned cached_tokens value as the authoritative result. Two different request numbers from one Agent action indicate separate Copilot model rounds, commonly an intermediate tool round followed by a final answer round.
SUB2API_CONTEXT_WINDOW_EXCEEDED means the gateway rejected the official or learned limit. The provider learns from that error and retries once; if it repeats, inspect the logged learned budget, set a lower sub2api.contextWindowCap, or start a new chat.
SUB2API_CONCURRENCY_LIMIT means the gateway rejected overlapping work for the account behind the API key. Requests using the same endpoint origin and key are serialized inside one VS Code extension host. A rejected request is retried with exponential backoff only if no text or tool call has been emitted, preventing blind retries of partially generated work. Configure sub2api.concurrencyRetryCount and sub2api.concurrencyRetryDelaySeconds if needed. This cannot stop another machine, another VS Code window with a separate extension host, or gateway-internal shared-account traffic.
A log message saying the gateway explicitly rejected only the request-wide cache policy is not fatal: the provider keeps explicit content breakpoints. If it explicitly rejects content breakpoints too, the gateway cannot provide reliable cross-conversation first-turn caching for GPT-5.6; update or reconfigure the Responses-compatible gateway. An ordinary Upstream request failed 500/502 now stops after one attempt instead of risking two more billed requests.
A top-level fetch failed means no complete HTTP response was received. The provider logs a sanitized cause chain, including common DNS, connection, TLS/socket, and Undici timeout codes when Node exposes them. Failures proven to happen before TLS or HTTP transmission are retried three times by default; configure this with sub2api.connectionRetryCount and sub2api.connectionRetryDelaySeconds. Ambiguous transport retries remain controlled by sub2api.networkRetryCount and sub2api.networkRetryDelaySeconds, defaulting to zero because a POST can reach and be billed by the upstream even when its response connection fails. A stable Idempotency-Key is reused across attempts, and retries never run after text or a tool call has been emitted.
SUB2API_STREAM_TERMINATED means the gateway closed SSE before the selected protocol completed. Check upstream/reverse-proxy timeouts and SSE heartbeat behavior. The provider does not blindly retry incomplete generated output because that can duplicate tokens and tool calls.
License
MIT