返回 CodeWhale
PROVIDERS.md
根目录 / docs / PROVIDERS.md
1 # Provider Registry
2
3 > 阅读简体中文版:[zh_hans/PROVIDERS.md](zh_hans/PROVIDERS.md)
4
5 This registry describes provider behavior that is wired into the current
6 Codewhale codebase. It is intentionally conservative: shipped entries are
7 limited to provider IDs, config keys, auth paths, base URLs, model resolution,
8 and capability metadata that the code already knows about.
9
10 DeepSeek remains the default provider, but every entry in `ProviderKind::ALL`
11 is a first-class selectable provider route. `ALL` is the catalog/picker
12 surface — one identity per vendor. Dual-wire dialect kinds (`*Anthropic`, e.g.
13 `deepseek-anthropic`) and the Model Studio plan variants stay on the enum for
14 serde and `provider_for_kind` but are deliberately **not** catalog rows:
15 a plan is `mode`/`base_url` and a dialect is `wire = openai|anthropic` on the
16 primary provider config (`crates/config/src/provider_kind.rs:221-226`). Hosted
17 routes, generic OpenAI-compatible endpoints, the OpenAI Codex/ChatGPT route,
18 native Anthropic, and local runtimes all run the same terminal harness against
19 the selected provider/model/base URL.
20
21 A host reached over plain Chat Completions is an ordinary named provider,
22 not a `ProviderKind`: enum variants are reserved for distinct *wires*
23 (Anthropic Messages, Codex Responses, Google thought signatures). Any such
24 host is a `[providers.<name>]` table with a base URL, a model, and a key env
25 (`docs/CONFIGURATION.md`); `/provider` and `/setup` keep a "paste a Base URL
26 and a key" path for exactly this. Offerings come from live `GET /v1/models`
27 plus the Codewhale catalog rather than a compiled roster (#5350, #6289).
28
29 Known-good hosts (documentation, not compiled rows — verify against the
30 vendor's own docs before trusting any value here):
31
32 | Host | Base URL | Example models | API key env |
33 | --- | --- | --- | --- |
34 | SenseNova | `https://token.sensenova.cn/v1` | `deepseek-v4-flash` | `SENSENOVA_API_KEY` |
35 | Baseten | `https://inference.baseten.co/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `BASETEN_API_KEY` |
36 | Groq | `https://api.groq.com/openai/v1` | `llama-3.3-70b-versatile` | `GROQ_API_KEY` |
37 | Cerebras | `https://api.cerebras.ai/v1` | `llama-3.3-70b` | `CEREBRAS_API_KEY` |
38 | Command Code | `https://api.commandcode.ai/provider/v1` | `deepseek/deepseek-v4-flash` | `COMMAND_CODE_API_KEY` |
39 | AICraft | `https://aicraftapi.com/v1` | DeepSeek / Qwen / GLM / MiniMax / Doubao families | `AICRAFT_API_KEY` |
40
41 AICraft advertises DeepSeek, Qwen, GLM, MiniMax and Doubao and lists no
42 Anthropic models — pick a model from their roster, not from this table.
43 OpenCode Zen and OpenCode Go are first-class provider routes, configured like
44 any other provider below; they are not part of this table. `/provider` `P`
45 opens the template list; `S` still fills SenseNova; `T` probes `/models` and
46 records reachability only (a 2xx is not model-ready).
47
48 Sources to keep in sync:
49
50 - `crates/config/src/lib.rs` - shared provider IDs, defaults, env precedence.
51 - `crates/tui/src/config.rs` - TUI provider IDs, provider capability metadata,
52 and provider-specific env handling.
53 - `crates/agent/src/lib.rs` - static `ModelRegistry` used by
54 `codewhale model list` and `codewhale model resolve`.
55 - `config.example.toml` and `docs/CONFIGURATION.md` - user-facing config
56 examples and environment variable reference.
57 - `scripts/check-provider-registry.py` - drift check for canonical provider
58 IDs, live TUI provider IDs, TOML table names, static registry rows, and
59 documented defaults.
60
61 ## Provider Selection
62
63 With no saved model, no `default_text_model`, and no `CODEWHALE_MODEL` or
64 provider-specific model variable, a fresh install runs `deepseek-flash` on the
65 DeepSeek provider. Precedence is the active provider's configured default, then
66 its catalog default — so an explicit `default_text_model` is not silently
67 overridden by whichever model the shipped catalog lists first.
68
69 Refresh model catalogs without installing a new Codewhale release:
70
71 ```sh
72 codewhale models --update
73 codewhale models --update --provider openai
74 codewhale models --provider openai --json
75 ```
76
77 `models --update` (also `--refresh`) updates the shared Models.dev metadata
78 and calls the existing `/models` endpoint for each configured provider with
79 its own credentials. `--provider ID` restricts the refresh to that exact
80 provider, including named custom endpoints. It makes no inference requests
81 and never changes the saved provider or model. A command-line API key is
82 confined to the active provider; other routes are reported as skipped for
83 that invocation.
84
85 Plain `models` lists the active provider's saved catalog without provider requests or
86 authentication checks. Successful refreshes are saved under Codewhale's
87 catalog directory and used by the model/provider pickers. Cache files are
88 scoped to provider identity and endpoint; a failed refresh preserves prior
89 rows. Text output reports source, last successful fetch time (Unix seconds),
90 and freshness. `--update --json` adds per-source receipts and aggregate counts;
91 partial failures return a nonzero exit code after writing those receipts.
92 Ordinary `models --json` keeps its model-array format. Bundled/configured
93 fallbacks are not proof that an account can use every listed model.
94
95 `codewhale models --update --provider openai-codex` asks the installed Codex
96 CLI for its signed-in ChatGPT account's model list through the documented
97 [app-server stdio API](https://learn.chatgpt.com/docs/app-server). Pagination
98 and supported reasoning efforts are preserved. This requires a Codex version
99 with `account/read` and `model/list` support. It starts no conversation, imports
100 no tokens, and sends no Codewhale provider keys to Codex. Standalone credential
101 overrides or custom endpoints that could select a different account are skipped.
102
103 Codex controls its own upstream cache policy; `model/list` does not expose a
104 force-refresh option. Receipts therefore count the result as `loaded`, with an
105 `observed_at` lookup time and no claimed upstream `fetched_at`. The observed
106 roster is saved for offline listing and pickers, alongside the existing Codex
107 cache fallback. A new model, such as GPT-6 Astra, appears only if that account's
108 roster supplies its exact ID. Codewhale never guesses availability or substitutes
109 a different billing route. Missing/stale rosters, CLI failures, and unsupported
110 OAuth catalogs are reported explicitly.
111
112 Codewhale's observed Codex rosters are bound to the exact filesystem home
113 and the metadata version of its `auth.json`; tokens are never read for this
114 cache binding. Replacing that login invalidates the observation. A native
115 Codex cache fetched before an observed login-file change is also stale.
116 Keyring-only accounts without an observable login file can still load a live
117 roster, but the receipt reports `codex_observation_not_persisted` and no
118 Codewhale observation is retained. The separately attributed Codex-owned
119 native cache keeps its existing freshness policy when no login-file version
120 can be observed; this is not proof of account identity in an external keyring.
121
122 The canonical provider IDs are the 44 entries of `ProviderKind::ALL`
123 (`crates/config/src/provider_kind.rs`), in that order:
124
125 `deepseek`, `nvidia-nim`, `openai`, `atlascloud`, `wanjie-ark`, `volcengine`,
126 `openrouter`, `orcarouter`, `xiaomi-mimo`, `novita`, `fireworks`, `siliconflow`, `arcee`,
127 `siliconflow-CN`, `moonshot`, `sglang`, `vllm`, `ollama`, `ollama-cloud`, `huggingface`,
128 `together`, `qianfan`, `openai-codex`, `anthropic`, `openmodel`, `zai`,
129 `stepfun`, `minimax`, `deepinfra`, `sakana`, `longcat`, `opencode-go`,
130 `opencode-zen`, `meta`, `xai`, `mistral`, `telecomjs`, `modelstudio-token-plan`, `modelscope`,
131 `google`, `edenai`, `zenmux`, `csdn`, `concentrate`, `codewhale`, and `custom`.
132
133 `deepseek-anthropic` is *not* on this list — it is a wire dialect of
134 `deepseek`, reached with `wire = "anthropic"`, not a separate route to select.
135
136 Use any of these surfaces to select a provider:
137
138 - CLI: `codewhale --provider <id>`
139 - TUI: `/provider <id>` or the provider picker
140 - Env: `CODEWHALE_PROVIDER=<id>`; `DEEPSEEK_PROVIDER=<id>` is the legacy alias
141 - Config: `provider = "<id>"`
142
143 `deepseek-cn`, `deepseek_china`, `deepseekcn`, and `deepseek-china` are accepted
144 as legacy aliases for `deepseek`. They do not select a different official host;
145 DeepSeek uses the same official API host worldwide.
146
147 `deepseek_anthropic`, `deepseek-claude`, and `deepseek_claude` select
148 `deepseek-anthropic`, the opt-in DeepSeek route that speaks the Anthropic
149 Messages API at `https://api.deepseek.com/anthropic`. It keeps the normal
150 DeepSeek API key path but uses `x-api-key` plus `anthropic-version: 2023-06-01`
151 instead of Bearer auth. If the key already lives in official DeepSeek Harness
152 (`dsh`) at `$DSH_HOME/.credentials.yaml`, grant read-only access with
153 `codewhale auth external-consent --provider deepseek --mode read-only`.
154 Codewhale never writes that file and only reads `DEEPSEEK_API_KEY`.
155
156 `huggingface`, `hugging-face`, `hugging_face`, and `hf` all select the
157 Hugging Face Inference Providers route. This is the OpenAI-compatible router
158 path for chat/inference, not Hub browsing, model-card inspection, uploads, or
159 artifact export.
160
161 `telecomjs`, `telecom-js`, `telecom_js`, `telecomjs-cn`, and `tokenhub` all
162 select the TelecomJS TokenHub route. Its authenticated `/models` catalog is
163 key-scoped and remains isolated from every other provider's live snapshot.
164
165 Fresh shared config writes to `~/.codewhale/config.toml`. Existing
166 `~/.deepseek/config.toml` files are still read for compatibility.
167
168 ### Legacy Antigravity tombstone
169
170 Antigravity is not a Codewhale provider and cannot be selected or run. Existing
171 legacy Antigravity provider state is recognized only as a non-runnable migration
172 tombstone. Run `codewhale auth clear --provider antigravity` to forget only
173 Codewhale-owned legacy configuration and consent metadata. This does not sign
174 out of, revoke, read, or otherwise alter any official Google or Antigravity
175 session. For Gemini, select the supported `google` provider and supply
176 `GEMINI_API_KEY`.
177
178 ### Wire Protocol Compatibility
179
180 Provider selection is explicit. A model string prefix such as
181 `deepseek-ai/...`, `deepseek/...`, `qwen/...`, or `arcee-ai/...` is a
182 provider-owned wire ID or catalog namespace hint under the selected provider.
183 It is not a provider switch and must not be treated as proof that the route is
184 DeepSeek, OpenRouter, or any other provider.
185
186 Set the route with `provider = "<id>"`, `CODEWHALE_PROVIDER=<id>`, or
187 `codewhale --provider <id>`. Set the request model with `CODEWHALE_MODEL`, a
188 provider-specific model env var, top-level `default_text_model`, or
189 `[providers.<table>].model`. Set the endpoint with `CODEWHALE_BASE_URL`, a
190 provider-specific base URL env var, or `[providers.<table>].base_url`. Set auth
191 with `codewhale auth set --provider <id>`, `[providers.<table>].api_key`, or
192 the listed provider env vars.
193
194 | Provider ID | TOML table | Wire protocol | Auth env vars |
195 | --- | --- | --- | --- |
196 | `deepseek` | `[providers.deepseek]` | Model-aware: Responses default (`deepseek-flash`); Chat Completions (`deepseek-v4-pro`) | `DEEPSEEK_API_KEY` |
197 | `deepseek-anthropic` | `[providers.deepseek_anthropic]` | Anthropic Messages | `DEEPSEEK_API_KEY` |
198 | `nvidia-nim` | `[providers.nvidia_nim]` | OpenAI Chat Completions | `NVIDIA_API_KEY`, `NVIDIA_NIM_API_KEY` |
199 | `openai` | `[providers.openai]` | OpenAI Chat Completions | `OPENAI_API_KEY` |
200 | `atlascloud` | `[providers.atlascloud]` | OpenAI Chat Completions | `ATLASCLOUD_API_KEY` |
201 | `wanjie-ark` | `[providers.wanjie_ark]` | OpenAI Chat Completions | `WANJIE_ARK_API_KEY`, `WANJIE_API_KEY`, `WANJIE_MAAS_API_KEY` |
202 | `volcengine` | `[providers.volcengine]` | OpenAI Chat Completions | `VOLCENGINE_API_KEY`, `VOLCENGINE_ARK_API_KEY`, `ARK_API_KEY` |
203 | `openrouter` | `[providers.openrouter]` | OpenAI Chat Completions | `OPENROUTER_API_KEY` |
204 | `xiaomi-mimo` | `[providers.xiaomi_mimo]` | OpenAI Chat Completions | `XIAOMI_MIMO_TOKEN_PLAN_API_KEY`, `MIMO_TOKEN_PLAN_API_KEY`, `XIAOMI_MIMO_API_KEY`, `XIAOMI_API_KEY`, `MIMO_API_KEY` |
205 | `novita` | `[providers.novita]` | OpenAI Chat Completions | `NOVITA_API_KEY` |
206 | `fireworks` | `[providers.fireworks]` | OpenAI Chat Completions | `FIREWORKS_API_KEY` |
207 | `siliconflow` | `[providers.siliconflow]` | OpenAI Chat Completions | `SILICONFLOW_API_KEY` |
208 | `arcee` | `[providers.arcee]` | OpenAI Chat Completions | `ARCEE_API_KEY` |
209 | `siliconflow-CN` | `[providers.siliconflow_cn]` | OpenAI Chat Completions | `SILICONFLOW_API_KEY` |
210 | `moonshot` | `[providers.moonshot]` | OpenAI Chat Completions | `MOONSHOT_API_KEY`, `KIMI_API_KEY` |
211 | `sglang` | `[providers.sglang]` | OpenAI Chat Completions | `SGLANG_API_KEY` |
212 | `vllm` | `[providers.vllm]` | OpenAI Chat Completions | `VLLM_API_KEY` |
213 | `ollama` | `[providers.ollama]` | Local OpenAI-compatible Chat Completions | `OLLAMA_API_KEY` (optional; only for an authenticated local route) |
214 | `ollama-cloud` | `[providers.ollama_cloud]` | Hosted OpenAI-compatible Chat Completions | `OLLAMA_CLOUD_API_KEY`, `OLLAMA_API_KEY` |
215 | `huggingface` | `[providers.huggingface]` | OpenAI Chat Completions | `HUGGINGFACE_API_KEY`, `HF_TOKEN` |
216 | `modelscope` | `[providers.modelscope]` | OpenAI Chat Completions | `MODELSCOPE_API_KEY` |
217 | `together` | `[providers.together]` | OpenAI Chat Completions | `TOGETHER_API_KEY` |
218 | `qianfan` | `[providers.qianfan]` | OpenAI Chat Completions | `QIANFAN_API_KEY`, `BAIDU_QIANFAN_API_KEY` |
219 | `openai-codex` | `[providers.openai_codex]` | OpenAI Responses | Native ChatGPT PKCE (`codewhale auth chatgpt`), `OPENAI_CODEX_ACCESS_TOKEN`, `CODEX_ACCESS_TOKEN`, or explicit Codex CLI consent |
220 | `anthropic` | `[providers.anthropic]` | Anthropic Messages | `ANTHROPIC_API_KEY` |
221 | `openmodel` | `[providers.openmodel]` | Anthropic Messages | `OPENMODEL_API_KEY` |
222 | `zai` | `[providers.zai]` | OpenAI Chat Completions | `ZAI_API_KEY`, `Z_AI_API_KEY` |
223 | `stepfun` | `[providers.stepfun]` | OpenAI Chat Completions | `STEPFUN_API_KEY`, `STEP_API_KEY` |
224 | `minimax` | `[providers.minimax]` | OpenAI Chat Completions | `MINIMAX_API_KEY` |
225 | `deepinfra` | `[providers.deepinfra]` | OpenAI Chat Completions | `DEEPINFRA_API_KEY`, `DEEPINFRA_TOKEN` |
226 | `sakana` | `[providers.sakana]` | OpenAI Chat Completions | `FUGU_API_KEY`, `SAKANA_API_KEY` |
227 | `longcat` | `[providers.longcat]` | OpenAI Chat Completions | `LONGCAT_API_KEY` |
228 | `opencode-go` | `[providers.opencode_go]` | OpenAI Chat Completions | `OPENCODE_GO_API_KEY` |
229 | `opencode-zen` | `[providers.opencode_zen]` | Model-aware: OpenAI Responses, Anthropic Messages, or OpenAI Chat Completions | `OPENCODE_ZEN_API_KEY`, `OPENCODE_API_KEY` |
230 | `meta` | `[providers.meta]` | OpenAI Chat Completions | `META_MODEL_API_KEY`, `MODEL_API_KEY` |
231 | `telecomjs` | `[providers.telecomjs]` | OpenAI Chat Completions | `TELECOMJS_API_KEY` |
232 | `xai` | `[providers.xai]` | OpenAI Chat Completions | `XAI_API_KEY` |
233 | `mistral` | `[providers.mistral]` | OpenAI Chat Completions | `MISTRAL_API_KEY` |
234 | `google` | `[providers.google]` | OpenAI Chat Completions (official Gemini OpenAI-compat route; captures and replays thought signatures on tool calls) | `GOOGLE_API_KEY`, `GEMINI_API_KEY` |
235 | `edenai` | `[providers.edenai]` | OpenAI Chat Completions | `EDENAI_API_KEY` |
236 | `zenmux` | `[providers.zenmux]` | OpenAI Chat Completions | `ZENMUX_API_KEY` |
237 | `csdn` | `[providers.csdn]` | OpenAI Chat Completions | `CSDN_API_KEY` |
238 | `concentrate` | `[providers.concentrate]` | OpenAI Responses (`/v1/responses`) | `CONCENTRATE_API_KEY` |
239 | `codewhale` | `[providers.codewhale]` | Model-aware: OpenAI Chat Completions (`/v1/chat/completions`) or Anthropic Messages (`/v1/messages`), chosen per model by the account catalog | `CODEWHALE_API_KEY` |
240 | `modelstudio-token-plan` | `[providers.modelstudio_token_plan]` | OpenAI Chat Completions | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` |
241 | `modelstudio-token-plan-anthropic` | `[providers.modelstudio_token_plan_anthropic]` | Anthropic Messages | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` |
242 | `modelstudio-coding-plan` | `[providers.modelstudio_coding_plan]` | OpenAI Chat Completions | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` |
243 | `modelstudio-coding-plan-anthropic` | `[providers.modelstudio_coding_plan_anthropic]` | Anthropic Messages | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` |
244
245 Default base URLs and models for each route are listed in the shipped provider
246 table below. The wire protocol values above are derived from
247 `crates/config/src/provider.rs`: `ChatCompletions` is the default,
248 `openai-codex` overrides to `Responses`; `deepseek-anthropic`, `anthropic`, and
249 `openmodel` override to `AnthropicMessages`; `opencode-zen` resolves the
250 protocol from the selected model's curated offering; and `deepseek` is
251 model-aware — the shipped default `deepseek-flash` (and legacy
252 `deepseek-v4-flash`) rides the Responses endpoint while `deepseek-v4-pro`
253 stays on Chat Completions.
254
255 ## Auth And Env Rules
256
257 For hosted providers, `codewhale auth set --provider <id>` saves an API key for
258 that provider. API-key environment variables are fallback inputs after saved
259 config and keyring credentials; an explicit process-level `--api-key` still
260 wins for that launch.
261
262 For base URL and model selection, prefer:
263
264 - `CODEWHALE_BASE_URL` / `CODEWHALE_MODEL` for the active provider.
265 - Provider-specific base URL/model env vars when listed below.
266 - `DEEPSEEK_BASE_URL`, `DEEPSEEK_MODEL`, and `DEEPSEEK_DEFAULT_TEXT_MODEL` as
267 legacy aliases.
268
269 Non-local `http://` base URLs are rejected unless
270 `DEEPSEEK_ALLOW_INSECURE_HTTP=1` is set. Loopback HTTP URLs are allowed for
271 self-hosted runtimes.
272
273 ## Custom DeepSeek-Compatible Endpoints
274
275 Most custom DeepSeek-compatible deployments can use an existing provider ID.
276 Do not create `[providers.deepseek_custom]`; the provider table names are fixed.
277 Instead, choose the closest shipped route and override its endpoint/model:
278
279 - DeepSeek-compatible hosted API: keep `provider = "deepseek"` and set
280 `[providers.deepseek].base_url` plus `[providers.deepseek].model`, or launch
281 with `DEEPSEEK_BASE_URL` and `DEEPSEEK_MODEL`.
282 - Generic OpenAI-compatible gateway: use `provider = "openai"` with
283 `[providers.openai].base_url` plus `[providers.openai].model`, or launch with
284 `OPENAI_BASE_URL` and `OPENAI_MODEL`.
285 - Multiple named OpenAI-compatible gateways, or local routes you want to pin
286 from an AgentProfile, can use a custom table such as
287 `[providers.lm-studio] kind = "openai-compatible"` and select it with
288 `provider = "lm-studio"` or a profile `provider = "lm-studio"`.
289 - Local OpenAI-compatible runtimes: use `provider = "vllm"`, `"sglang"`, or
290 `"ollama"` with the matching provider-specific base URL/model values.
291
292 Example user config for a DeepSeek-compatible host:
293
294 ```toml
295 provider = "deepseek"
296
297 [providers.deepseek]
298 api_key = "YOUR_API_KEY"
299 base_url = "https://your-provider.example/v1"
300 model = "deepseek-ai/DeepSeek-V4-Pro"
301 ```
302
303 Example user config for a generic gateway:
304
305 ```toml
306 provider = "openai"
307
308 [providers.openai]
309 api_key = "YOUR_GATEWAY_API_KEY"
310 base_url = "https://gateway.example/v1"
311 model = "your-deepseek-compatible-model"
312 ```
313
314 Alibaba Cloud Model Studio (Bailian / DashScope) is a first-class provider as
315 of v0.9.4 with two plan profiles: Token Plan (Personal / Team) and Coding Plan.
316 Both plans expose an OpenAI-compatible Chat Completions endpoint and an
317 Anthropic-compatible Messages endpoint.
318
319 **Token Plan** (Personal and Team share the same AP-Southeast endpoint):
320
321 ```toml
322 provider = "modelstudio-token-plan"
323
324 [providers.modelstudio_token_plan]
325 api_key = "YOUR_MODELSTUDIO_API_KEY"
326 # base_url defaults to https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1
327 model = "qwen3.8-max" # or qwen3.8-max-preview | qwen3.7-plus | qwen3.7-max |
328 # qwen3.6-flash | deepseek-v4-pro | deepseek-v4-flash-0731 |
329 # glm-5.2
330 ```
331
332 **Coding Plan** (separate international endpoint):
333
334 ```toml
335 provider = "modelstudio-coding-plan"
336
337 [providers.modelstudio_coding_plan]
338 api_key = "YOUR_MODELSTUDIO_API_KEY"
339 # base_url defaults to https://coding-intl.dashscope.aliyuncs.com/v1
340 model = "qwen3.8-max"
341 ```
342
343 **Anthropic-compatible dialect** — both plans also expose a native Anthropic
344 Messages path. Select it with the `-anthropic` provider suffix:
345
346 ```toml
347 provider = "modelstudio-token-plan-anthropic"
348
349 [providers.modelstudio_token_plan_anthropic]
350 api_key = "YOUR_MODELSTUDIO_API_KEY"
351 # base_url defaults to https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic
352 model = "qwen3.8-max"
353 ```
354
355 Create or copy a Model Studio API key from the
356 [Bailian console](https://bailian.console.aliyun.com/). The API key is shared
357 across all four provider IDs above; only the base URL and wire protocol differ.
358
359 **Thinking / reasoning.** Reasoning surfaces in the TUI's Thinking view on both
360 dialects, per Model Studio's
361 [deep-thinking docs](https://www.alibabacloud.com/help/en/model-studio/deep-thinking).
362
363 On the OpenAI-compatible routes the top-level controls are **route- and
364 model-specific**, and Codewhale fails closed: they are sent only when the
365 configured `base_url` is an official Alibaba Chat Completions host
366 (`*.maas.aliyuncs.com/compatible-mode/v1`, including workspace-scoped hosts, or
367 `coding-intl.dashscope.aliyuncs.com/v1`). A custom `base_url` on the same
368 provider ID gets `thinking`, `enable_thinking`, `preserve_thinking`, and
369 `reasoning_effort` stripped, so an arbitrary OpenAI-compatible gateway is never
370 handed Alibaba's dialect. On a verified host:
371
372 - **Hybrid models** (`qwen3.7-*`, `qwen3.6-*`, `deepseek-v4*`, `glm-*`,
373 `kimi-k2.6*`) get `enable_thinking`: `false` for `off`, `true` otherwise.
374 - **Thinking-only models** — `qwen3.8-max` (catalogued `thinking: always_on`),
375 `qwen3.8-max-preview` (effort/budget options, no toggle), and
376 `kimi-k2.7-code` — get **no** enable/disable switch at all. Sending one is at
377 best ignored.
378 - `preserve_thinking` is sent for the models documented to accept it
379 (`qwen3.7-max`/`-plus`, `qwen3.6-max-preview`/`-plus`/`-flash`, `kimi-k2.6*`,
380 `kimi-k2.7-code`), so the next turn keeps the assistant's trace.
381 - `reasoning_effort` is sent only for the two families with a documented ladder
382 — `deepseek-v4*` and `glm-5`/`5.1`/`5.2` — mapped to `high` or `max`.
383
384 Reasoning streams back as `delta.reasoning_content`. It is replayed to the
385 provider on later turns only for the `preserve_thinking` models above and the
386 thinking-only models; `deepseek-v3.1`, `deepseek-v3.2`, and `glm-*` history
387 stays stripped pending live confirmation that DashScope accepts
388 `reasoning_content` in input messages. (`deepseek-v4*` replays regardless — the
389 DeepSeek thinking-mode contract requires it on every provider.)
390
391 On the Anthropic-compatible routes, thinking uses the documented
392 `{"type":"enabled","budget_tokens":N}` / `{"type":"disabled"}` shapes from the
393 [Anthropic-compatible Messages API](https://www.alibabacloud.com/help/en/model-studio/anthropic-api-messages),
394 with `budget_tokens` derived from the effort level.
395
396 DeepSeek (`deepseek-v4-pro`, `deepseek-v4-flash-0731`) and GLM (`glm-5.2`)
397 models served by Model Studio are provider-scoped and do not collide with the
398 first-party DeepSeek or Zhipu/Z.ai routes. Model Studio publishes no `glm-5.3`
399 entry, so Codewhale does not offer one on this route.
400 Pay-as-you-go workspace-id templating is not yet in the built-in provider; use
401 a custom provider entry for that plan until a follow-up adds it.
402
403 Private gateways with broken or intercepted certificates should use
404 `SSL_CERT_FILE` with a trusted CA bundle. The legacy
405 `insecure_skip_tls_verify = true` key is still parsed so `codewhale doctor` can
406 report stale configs, but provider clients reject it instead of skipping TLS
407 certificate verification.
408
409 Keep `provider`, `api_key`, and `base_url` in user config or process
410 environment. Project-local config overlays intentionally cannot set those keys,
411 so a repository cannot silently redirect prompts or credentials to another
412 endpoint.
413
414 ## Local Models (DS4, Ollama, vLLM, SGLang)
415
416 Self-hosted OpenAI-compatible runtimes are first-class routes and are keyless
417 by default — set an API key only when your server requires one. Start your
418 runner, then point Codewhale at it with `--provider` / `/provider` or a config
419 table.
420
421 | Runner | Default base URL | Default model | Base URL override |
422 | --- | --- | --- | --- |
423 | `ollama` | `http://localhost:11434/v1` | live tag from `GET /v1/models` (pre-refresh: `unknown`) | `OLLAMA_BASE_URL` |
424 | `vllm` | `http://localhost:8000/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `VLLM_BASE_URL` |
425 | `sglang` | `http://localhost:30000/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `SGLANG_BASE_URL` |
426
427 ### DS4 (DwarfStar)
428
429 [DS4](https://github.com/antirez/ds4/tree/84cc882352757baf628a1776badf7cc54d584e28)
430 serves DeepSeek V4 Flash and Pro locally
431 through an OpenAI-compatible API. Start DS4, then open Codewhale's prefilled,
432 keyless setup form:
433
434 ```bash
435 ./ds4-server --ctx 100000 --kv-disk-dir /tmp/ds4-kv --kv-disk-space-mb 8192
436 codewhale
437 # In Codewhale: /setup provider ds4
438 ```
439
440 Review the prefilled route and press Enter to save it. The preset budgets a
441 100,000-token context to match that starter command and defaults to the Flash
442 compatibility alias. Check the local route explicitly with
443 `codewhale doctor --probe-local`.
444
445 DS4 loads the actual GGUF when the server starts. Its `deepseek-v4-flash` and
446 `deepseek-v4-pro` API ids are compatibility aliases; changing `/model` does
447 not swap the resident model. To run Pro, download the supported Pro weights
448 and start `ds4-server -m <pro.gguf> ...` as described by DS4. Update
449 `context_window` whenever the server's `--ctx` value changes.
450
451 The equivalent config is:
452
453 ```toml
454 provider = "ds4"
455
456 [providers.ds4]
457 kind = "openai-compatible"
458 base_url = "http://127.0.0.1:8000/v1"
459 model = "deepseek-v4-flash"
460 auth_mode = "none"
461 context_window = 100000
462 ```
463
464 Codewhale reuses its existing OpenAI-compatible transport and DeepSeek
465 reasoning/tool-call shaping for DS4. It does not invent an API key, confuse an
466 API alias with the loaded GGUF, or silently switch to a hosted DeepSeek route.
467 The pinned DS4 [agent-client contract](https://github.com/antirez/ds4/blob/84cc882352757baf628a1776badf7cc54d584e28/README.md#agent-client-usage)
468 documents Chat Completions at `/v1`, DeepSeek thinking replay, streamed usage,
469 `max_tokens`, and no strict-tool mode; Codewhale follows those exact route
470 facts instead of inheriting unsupported capabilities from a generic gateway.
471 The primary sources for model-facing behavior are DeepSeek's official
472 [thinking-mode](https://api-docs.deepseek.com/guides/thinking_mode),
473 [tool-call](https://api-docs.deepseek.com/guides/tool_calls), and
474 [Chat Completion](https://api-docs.deepseek.com/api/create-chat-completion)
475 contracts. The pinned
476 [DeepSeek Harness adapter](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/llm/llm-deepseek/README.md)
477 is only a secondary implementation cross-check; it is not the API contract.
478
479 ### Ollama
480
481 ```bash
482 ollama serve # if not already running
483 ollama pull <model> # e.g. deepseek-v4-flash, or any tag you prefer
484 codewhale --provider ollama --model <model>
485 ```
486
487 Provider-hinted model names are sent as-is, so `--model qwen3:8b` works with
488 any tag Ollama has pulled.
489
490 ### Ollama Cloud
491
492 Ollama Cloud is a separate hosted provider. It uses the authenticated
493 OpenAI-compatible `/v1/chat/completions` route and defaults to `gpt-oss:120b`:
494
495 ```toml
496 provider = "ollama-cloud"
497
498 [providers.ollama_cloud]
499 base_url = "https://ollama.com/v1"
500 model = "gpt-oss:120b"
501 ```
502
503 Create a key in [Ollama account settings](https://ollama.com/settings/keys),
504 then run `codewhale auth set --provider ollama-cloud`. For ambient auth,
505 `OLLAMA_CLOUD_API_KEY` wins over Ollama's official `OLLAMA_API_KEY`.
506 `OLLAMA_CLOUD_BASE_URL` and `OLLAMA_CLOUD_MODEL` override the Cloud defaults;
507 arbitrary provider-owned model IDs pass through unchanged. Local `ollama`
508 remains a separate, keyless-by-default provider.
509
510 Compatibility is read-only and in memory: a released config that selected
511 `provider = "ollama"` with the exact normalized
512 `[providers.ollama] base_url = "https://ollama.com/v1"` tuple is treated as
513 `ollama-cloud` at runtime. Only that exact tuple may fall back to the legacy
514 `ollama` secret slot. Codewhale does not rewrite the config, copy or delete a
515 secret, migrate neighboring paths, or make an explicit `ollama-cloud` route
516 consume the legacy slot.
517
518 ### vLLM
519
520 ```bash
521 vllm serve <model> --port 8000
522 # or: python -m vllm.entrypoints.openai.api_server --model <model> --port 8000
523 codewhale --provider vllm --model <model>
524 ```
525
526 vLLM's OpenAI-compatible server listens on port 8000 by default, matching
527 Codewhale's `VLLM_BASE_URL`.
528
529 ### SGLang
530
531 ```bash
532 python -m sglang.launch_server --model-path <model> --port 30000
533 codewhale --provider sglang --model <model>
534 ```
535
536 SGLang's default port 30000 matches Codewhale's `SGLANG_BASE_URL`.
537
538 ### Pinning a local route in config
539
540 ```toml
541 provider = "ollama" # or "vllm" / "sglang"
542
543 [providers.ollama]
544 model = "qwen3:8b" # default is deepseek-v4-flash
545 # base_url defaults to http://localhost:11434/v1
546 ```
547
548 Local models that print tool-call JSON without the wire markers: see
549 [When a Local Model Prints Tool JSON](#when-a-local-model-prints-tool-json).
550
551 ## Credential Links
552
553 Provider setup surfaces use the same typed credential metadata as onboarding,
554 `/provider`, `/links`, setup receipts, and doctor output. A missing URL is
555 intentional: local, OAuth-only, and user-defined routes show their supported
556 configuration path instead of guessing a vendor page.
557
558 | Provider ID | Credential or console link |
559 | --- | --- |
560 | `deepseek`, `deepseek-anthropic` | [DeepSeek API keys](https://platform.deepseek.com/api_keys) |
561 | `nvidia-nim` | [NVIDIA NIM API keys](https://build.nvidia.com/settings/api-keys) |
562 | `openai` | [OpenAI API keys](https://platform.openai.com/api-keys) |
563 | `atlascloud` | [Atlas Cloud API keys](https://atlascloud.ai/docs/en/api-keys) |
564 | `wanjie-ark` | [Wanjie MaaS APIKEY docs](https://docs.wanjiedata.com/maas/maas-openapi-v1.html) |
565 | `volcengine` | [Volcengine Ark API keys](https://console.volcengine.com/ark/apiKey) |
566 | `openrouter` | [OpenRouter keys](https://openrouter.ai/settings/keys) |
567 | `xiaomi-mimo` | [Xiaomi MiMo Token Plan](https://platform.xiaomimimo.com/token-plan) |
568 | `novita` | [Novita key management](https://novita.ai/en/settings/key-management) |
569 | `fireworks` | [Fireworks API keys](https://fireworks.ai/api-keys) |
570 | `siliconflow` | [SiliconFlow global API keys](https://cloud.siliconflow.com/account/ak) |
571 | `siliconflow-CN` | [SiliconFlow China API keys](https://cloud.siliconflow.cn/account/ak) |
572 | `arcee` | [Arcee API key guide](https://docs.arcee.ai/other/create-your-first-api-key) |
573 | `moonshot` | [Kimi API platform keys](https://platform.kimi.ai/console/api-keys) or [Kimi Code membership console](https://www.kimi.com/code/console) |
574 | `zai` | [Z.ai model API](https://z.ai/model-api) |
575 | `stepfun` | [StepFun Open Platform](https://platform.stepfun.ai/) |
576 | `minimax`, `minimax-anthropic` | [MiniMax interface keys](https://platform.minimax.io/user-center/basic-information/interface-key) |
577 | `huggingface` | [Hugging Face tokens](https://huggingface.co/settings/tokens) |
578 | `modelscope` | [ModelScope API Keys](https://modelscope.cn/my/settings/token) |
579 | `deepinfra` | [DeepInfra API keys](https://deepinfra.com/dash/api_keys) |
580 | `together` | [Together API keys](https://api.together.ai/settings/api-keys) |
581 | `qianfan` | [Baidu Cloud access keys](https://console.bce.baidu.com/iam/#/iam/accesslist) |
582 | `anthropic` | [Anthropic API keys](https://console.anthropic.com/settings/keys) |
583 | `openmodel` | [OpenModel console](https://console.openmodel.ai/) ([authentication guide](https://docs.openmodel.ai/en/docs/getting-started/authentication)) |
584 | `openai-codex` | Sign in with ChatGPT via `codewhale auth chatgpt` (subscription billing, Codewhale-owned tokens). The `openai` API-key route is a different billing owner. Codex CLI import remains an explicit alternative after `codex login` plus `codewhale auth external-consent`. |
585 | `sglang`, `vllm` | Local OpenAI-compatible endpoints are keyless by default; configure a key only when the server requires one. |
586 | `ollama` | Local Ollama is keyless by default; configure a key only when the local server requires one. |
587 | `ollama-cloud` | Create an [Ollama API key](https://ollama.com/settings/keys), save it with `codewhale auth set --provider ollama-cloud`, or set `OLLAMA_CLOUD_API_KEY` / `OLLAMA_API_KEY` in that precedence order. |
588 | `sakana` | [Sakana AI API keys](https://console.sakana.ai/api-keys) ([get started](https://console.sakana.ai/get-started)) |
589 | `longcat` | [Meituan LongCat platform](https://longcat.chat/platform) |
590 | `opencode-go` | [OpenCode Go](https://opencode.ai/docs/go/) |
591 | `opencode-zen` | [OpenCode Zen](https://opencode.ai/docs/zen/) |
592 | `meta` | [Meta Model API](https://developer.meta.com/ai/) |
593 | `telecomjs` | [TelecomJS TokenHub](https://aigw.telecomjs.com/) |
594 | `xai` | [xAI Console](https://console.x.ai/) for an API key, Codewhale-owned device login, or explicitly consented read-only Grok CLI credentials. |
595 | `mistral` | [Mistral Console (la Plateforme)](https://console.mistral.ai/api-keys) |
596 | `google` | [Google AI Studio](https://aistudio.google.com/apikey) — Codewhale uses the official Gemini OpenAI-compatible endpoint and never reads Google OAuth files. |
597 | `edenai` | [Eden AI API keys](https://app.edenai.run/settings/api-keys) |
598 | `zenmux` | [ZenMux API keys](https://zenmux.ai/platform/pay-as-you-go) |
599 | `csdn` | [CSDN 星图 console](https://ai.csdn.net/workbench/api-key) — choose the Coding Plan key type for the `glm_for_coding` plan route; a general key bills metered. Docs: [Coding Plan](https://ai.csdn.net/coding-plan). |
600 | `concentrate` | [Concentrate dashboard](https://concentrate.ai/) → API Keys → Create API Key (a Universal API key); docs: [API introduction](https://concentrate.ai/docs/api-reference/introduction). BYOK only — the key stays in the local secret store. |
601 | `modelstudio-token-plan`, `modelstudio-token-plan-anthropic`, `modelstudio-coding-plan`, `modelstudio-coding-plan-anthropic` | [Alibaba Cloud Model Studio (Bailian console)](https://bailian.console.aliyun.com/) — create or copy a Model Studio API key. |
602 | `codewhale` | [Codewhale account settings](https://app.codewhale.net/settings?section=api) — create an API key with the `models:infer` scope, or run `codewhale account api-keys create --name <name> --use`. |
603 | `custom` | Set the named provider's `base_url` and `api_key_env` or `api_key`; no canonical vendor credential page exists. |
604
605 For Kimi, the official [quickstart](https://platform.kimi.ai/docs/overview)
606 directs users to sign in, open **API Keys**, create and copy a key, and keep it
607 secret. Codewhale links straight to that console and accepts the copied key.
608 It never probes or impersonates `kimi_cli`/`kimi_code_cli`; first-class Kimi
609 OAuth remains blocked on a vendor-registered Codewhale identity.
610
611 ### External CLI credential consent
612
613 Credential files owned by another CLI are disabled by default. Without an
614 explicit grant, provider discovery, setup, routing, `auth status`, and doctor
615 do not stat, read, refresh, contact an identity provider for, or rewrite Codex,
616 Grok, Kimi, or future external credential files.
617
618 Codewhale currently supports exact-path, provider-scoped **read-only** grants
619 for the Codex CLI and Grok CLI:
620
621 ```bash
622 codex login
623 codewhale auth external-consent --provider openai-codex --mode read-only
624
625 grok login
626 codewhale auth external-consent --provider xai --mode read-only
627
628 codewhale auth status --provider openai-codex
629 codewhale auth external-revoke --provider openai-codex
630 ```
631
632 Pass `--path /absolute/path/to/auth.json` when the external CLI uses a custom
633 location. Consent persists the provider, external owner, exact absolute path,
634 and consent schema version. Later environment-variable changes do not redirect
635 that authority to a different file. Read-only grants never refresh, contact an
636 identity/discovery service, or rewrite the external file; normal requests to
637 the explicitly selected provider may use its token. An expired token fails
638 with login guidance. Doctor reports structural consent/config state without
639 opening credential files and is always non-mutating.
640
641 `managed` is reserved for a future provider-specific preservation adapter.
642 v0.9.1 rejects it before file or network I/O because no reviewed adapter can
643 yet preserve every unknown external schema field safely. Codewhale-started xAI
644 device login instead atomically activates a Codewhale-owned generation named
645 `$CODEWHALE_HOME/credentials/xai-auth-<generation>.json`, stores only that
646 validated basename in config, and revokes any Grok-file grant. Superseded
647 generations are cleaned only after the new config pointer commits.
648 Kimi remains API-key-only; external consent for Kimi is rejected.
649
650 The official DeepSeek Harness (`dsh`) is a third read-only credential owner:
651 `codewhale auth external-consent --provider deepseek --mode read-only` grants
652 exact-path read access to `DEEPSEEK_API_KEY` in `$DSH_HOME/.credentials.yaml`
653 (or `~/.dsh/.credentials.yaml`), which Codewhale never writes, refreshes, or
654 loads into the process environment. This is separate from the DSH *harness*
655 integration (`codewhale integrations dsh …`, see
656 [INTEGRATIONS_DSH.md](INTEGRATIONS_DSH.md)), which never touches credentials
657 in either direction: it pins Codewhale's route identity into a `--patch`
658 overlay and lets DSH resolve its own keys.
659
660 ## Shipped Providers
661
662 | Provider ID | TOML table | Auth env | Base URL env and default | Default or static models | Notes |
663 | --- | --- | --- | --- | --- | --- |
664 | `deepseek` | `[providers.deepseek]` | `DEEPSEEK_API_KEY` | `CODEWHALE_BASE_URL` / `DEEPSEEK_BASE_URL`; default `https://api.deepseek.com/beta` | `deepseek-flash` (shipped default; V4.1 Flash, unversioned id), `deepseek-v4-pro`, `deepseek-v4-flash`, experimental `deepseek-v4-flash-vision-exp`; vision aliases `flash-vision`, `deepseek-v4flashvisionexp`; compatibility aliases `deepseek-chat`, `deepseek-reasoner` | First-class default. The live Pro backend is labeled `DeepSeek-V4-Pro-0813`; the callable API ID remains `deepseek-v4-pro`. Beta URL enables strict tool mode, chat prefix completion, and FIM completion. The documented V4 routes can use provider-native web search through a separate bounded Responses request; compatible custom endpoints do not inherit that capability. Set `https://api.deepseek.com` or `/v1` explicitly to opt out of beta-only features. The shipped default `deepseek-flash` speaks the Responses API (DeepSeek's documented path for Codex-style integration, since the 2026-07-31 Flash production update); the Chat-only controls (the `thinking` toggle and strict-tool `/beta` routing) apply to Chat Completions routes, and `deepseek-v4-pro` stays on Chat Completions until its announced Responses rollout. Reasoning effort follows DeepSeek's documented requested-to-actual mapping: `minimal`/`low` land on `low`, `medium`/`xhigh` on `high`, and `max`/`ultra` on `max`; `off` disables thinking (`thinking: {"type":"disabled"}` on Chat, `reasoning.effort: "none"` on Responses). The experimental vision ID was observed in the authenticated `/models` roster on 2026-08-21 and is advertised as image-input capable on the direct Chat Completions route only. Its limits, reasoning, and tool-call flags provisionally inherit Flash; pricing remains unknown, and no funded image round trip was made during this release work. |
665 | `deepseek-anthropic` | `[providers.deepseek_anthropic]` | `DEEPSEEK_API_KEY` | `DEEPSEEK_ANTHROPIC_BASE_URL`; default `https://api.deepseek.com/anthropic` | `deepseek-v4-pro`, `deepseek-v4-flash`; compatibility aliases `deepseek-chat`, `deepseek-reasoner` | Opt-in DeepSeek route for the Anthropic Messages wire protocol. Uses `/v1/messages`, `x-api-key`, and `anthropic-version: 2023-06-01`. Keep `provider = "deepseek"` for the default Chat Completions path. |
666 | `nvidia-nim` | `[providers.nvidia_nim]` | `NVIDIA_API_KEY`, `NVIDIA_NIM_API_KEY` | `NVIDIA_NIM_BASE_URL`, `NIM_BASE_URL`, `NVIDIA_BASE_URL`; default `https://integrate.api.nvidia.com/v1` | `deepseek-ai/deepseek-v4-pro`, `deepseek-ai/deepseek-v4-flash` | Hosted DeepSeek V4 through NVIDIA NIM. `NVIDIA_NIM_MODEL` is accepted by the TUI config path. |
667 | `openai` | `[providers.openai]` | `OPENAI_API_KEY` | `OPENAI_BASE_URL`; default `https://api.openai.com/v1` | `gpt-5.6` (default), `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna` | Generic OpenAI-compatible route whose built-in endpoint and fallback catalog are native to OpenAI. The [GPT-5.6 family](https://developers.openai.com/api/docs/models/gpt-5.6-sol) uses OpenAI's documented 1.05M context, 128K max output, and reasoning levels. Custom gateways remain free to select an explicit gateway-owned model. `OPENAI_MODEL` is accepted. |
668 | `atlascloud` | `[providers.atlascloud]` | `ATLASCLOUD_API_KEY` | `ATLASCLOUD_BASE_URL`; default `https://api.atlascloud.ai/v1` | Default `deepseek-ai/deepseek-v4-flash`; explicit `vendor/model-id` values pass through when AtlasCloud is selected | OpenAI-compatible hosted route. `ATLASCLOUD_MODEL` is accepted by the TUI config path, the static `ModelRegistry` keeps DeepSeek V4 fallback rows, and provider-hinted CLI model IDs are sent to AtlasCloud exactly as requested. Use Atlas Cloud's own catalog or Coding Plan page for the current provider-owned model list and pricing. |
669 | `wanjie-ark` | `[providers.wanjie_ark]` | `WANJIE_ARK_API_KEY`, `WANJIE_API_KEY`, `WANJIE_MAAS_API_KEY` | `WANJIE_ARK_BASE_URL`, `WANJIE_BASE_URL`, `WANJIE_MAAS_BASE_URL`; default `https://maas-openapi.wanjiedata.com/api/v1` | `deepseek-reasoner` | OpenAI-compatible hosted route. `WANJIE_ARK_MODEL`, `WANJIE_MODEL`, and `WANJIE_MAAS_MODEL` are accepted. |
670 | `volcengine` | `[providers.volcengine]` | `VOLCENGINE_API_KEY`, `VOLCENGINE_ARK_API_KEY`, `ARK_API_KEY` | `VOLCENGINE_BASE_URL`, `VOLCENGINE_ARK_BASE_URL`, `ARK_BASE_URL`; default `https://ark.cn-beijing.volces.com/api/coding/v3` | `DeepSeek-V4-Pro`, `DeepSeek-V4-Flash` | Volcengine/Volcano Engine Ark OpenAI-compatible coding endpoint. `VOLCENGINE_MODEL` and `VOLCENGINE_ARK_MODEL` are accepted. |
671 | `openrouter` | `[providers.openrouter]` | `OPENROUTER_API_KEY` | `OPENROUTER_BASE_URL`; default `https://openrouter.ai/api/v1` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`; recent large IDs include `arcee-ai/trinity-large-thinking`, `minimax/minimax-m3`, `xiaomi/mimo-v2.5-pro`, `qwen/qwen3.6-flash`, `qwen/qwen3.6-35b-a3b`, `qwen/qwen3.6-max-preview`, `qwen/qwen3.6-27b`, `qwen/qwen3.6-plus`, `google/gemma-4-31b-it`, `z-ai/glm-5.1`, `z-ai/glm-5.2`, `moonshotai/kimi-k2.7-code`, `moonshotai/kimi-k2.6` | Additive open-model routing layer. It does not replace DeepSeek; it lets users route supported model IDs through OpenRouter when they choose it. |
672 | `orcarouter` | `[providers.orcarouter]` | `ORCAROUTER_API_KEY` | `ORCAROUTER_BASE_URL`; default `https://api.orcarouter.ai/v1` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`; router alias `orcarouter/auto`; recent large IDs mirror the OpenRouter namespaced catalog | [OrcaRouter](https://www.orcarouter.ai) OpenAI-compatible aggregation gateway. Shares the namespaced `vendor/model` wire-model format and DeepSeek model set with OpenRouter, so the OpenRouter base-URL and model-normalization rules apply. `ORCAROUTER_MODEL` is accepted. Provider aliases: `orcarouter`, `orca_router`, `orca`. |
673 | `xiaomi-mimo` | `[providers.xiaomi_mimo]` | `XIAOMI_MIMO_TOKEN_PLAN_API_KEY`, `MIMO_TOKEN_PLAN_API_KEY`, `XIAOMI_MIMO_API_KEY`, `XIAOMI_API_KEY`, `MIMO_API_KEY` | `XIAOMI_MIMO_BASE_URL`, `MIMO_BASE_URL`, `XIAOMI_MIMO_MODE`, `MIMO_MODE`; default `https://token-plan-sgp.xiaomimimo.com/v1` | Chat: `mimo-v2.5-pro`, `mimo-v2.5-pro-ultraspeed`, `mimo-v2.5`; speech/TTS: `mimo-v2.5-tts`, `mimo-v2.5-tts-voicedesign`, `mimo-v2.5-tts-voiceclone`, `mimo-v2-tts` | Xiaomi MiMo OpenAI-compatible chat completions route. `mimo-v2.5-pro` and `mimo-v2.5` can use the documented provider-native web-search plugin; ultraspeed, speech/TTS, and custom-compatible routes do not inherit it. Token Plan keys (`tp-...`) use `api-key` auth and the token-plan endpoint by default; pay-as-you-go mode uses standard API keys (`sk-...`) and `https://api.xiaomimimo.com/v1`. It sends `max_completion_tokens` and uses MiMo's `thinking` field for reasoning control. Token Plan cost/usage is credit/quota based; Codewhale shows it as unknown until Xiaomi exposes a reliable balance API. `codewhale speech` / `tts` uses the TTS models. |
674 | `novita` | `[providers.novita]` | `NOVITA_API_KEY` | `NOVITA_BASE_URL`; default `https://api.novita.ai/openai/v1` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash` | OpenAI-compatible hosted route for DeepSeek model IDs. Use config or `CODEWHALE_MODEL` / `DEEPSEEK_MODEL` for model overrides. |
675 | `fireworks` | `[providers.fireworks]` | `FIREWORKS_API_KEY` | `FIREWORKS_BASE_URL`; default `https://api.fireworks.ai/inference/v1` | `accounts/fireworks/models/deepseek-v4-pro` | OpenAI-compatible hosted route. Use config or `CODEWHALE_MODEL` / `DEEPSEEK_MODEL` for model overrides. |
676 | `siliconflow` | `[providers.siliconflow]` | `SILICONFLOW_API_KEY` | `SILICONFLOW_BASE_URL`; default `https://api.siliconflow.com/v1` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | OpenAI-compatible hosted route. Official docs use the `.com` endpoint. `SILICONFLOW_MODEL` is accepted. Reasoning aliases `deepseek-reasoner` and `deepseek-r1` map to Pro; `deepseek-chat` and `deepseek-v3` map to Flash. |
677 | `siliconflow-CN` | `[providers.siliconflow_cn]` | `SILICONFLOW_API_KEY` | `SILICONFLOW_BASE_URL`; default `https://api.siliconflow.cn/v1` | Uses the SiliconFlow model set | China regional SiliconFlow route. Falls back to `[providers.siliconflow]` for api_key / base_url / model when unset. Select it with `provider = "siliconflow-CN"` or `CODEWHALE_PROVIDER=siliconflow-CN`. |
678 | `arcee` | `[providers.arcee]` | `ARCEE_API_KEY` | `ARCEE_BASE_URL`; default `https://api.arcee.ai/api/v1` | `trinity-large-thinking`, `trinity-large-preview` | Arcee AI direct OpenAI-compatible route, tracked as 256K-context BF16 serving. `ARCEE_MODEL` is accepted. OpenRouter's `arcee-ai/trinity-large-thinking` remains the OpenRouter namespaced model ID; direct Arcee uses the bare `trinity-large-thinking` ID. |
679 | `moonshot` | `[providers.moonshot]` | `MOONSHOT_API_KEY`, `KIMI_API_KEY` | `MOONSHOT_BASE_URL`, `KIMI_BASE_URL`; default `https://api.moonshot.ai/v1` | Direct Moonshot: `kimi-k3`, `kimi-k2.7-code`, `kimi-k2.7-code-highspeed`, `kimi-k2.6`; Kimi Code membership: `k3`, `kimi-for-coding`, `kimi-for-coding-highspeed` at `https://api.kimi.com/coding/v1` | Moonshot/Kimi route. Exact direct `kimi-k3` routes use the documented Formula web-search tool/fiber loop; direct `kimi-k2.6` retains the built-in `$web_search` contract, and exact Kimi Code membership routes use their structured `/search` service. Adjacent paths, K2.7 direct models, and cross-product model IDs do not inherit native search. `kimi` and `kimi-k2` aliases select `kimi-k2.7-code`; `MOONSHOT_MODEL`, `KIMI_MODEL_NAME`, and `KIMI_MODEL` are accepted. Kimi thinking streams through `reasoning_content`; Codewhale keeps it in Thinking cells and replays it for thinking/tool-call continuity. For direct K3, use exact `base_url = "https://api.moonshot.ai/v1"` and `model = "kimi-k3"`; it is always-thinking and receives top-level `reasoning_effort = "low" | "high" | "max"` (`off` normalizes to `low`), uses only `max_completion_tokens`, and omits `temperature`/`top_p` per the [K3 quickstart](https://platform.kimi.ai/docs/guide/kimi-k3-quickstart). For Kimi Code K3, use a key from the [Kimi Code console](https://www.kimi.com/code/console), exact `base_url = "https://api.kimi.com/coding/v1"`, and bare `model = "k3"`; `off` becomes enabled `low`, while normal dispatched `auto` selects and sends a concrete Codewhale tier. Only an omitted reasoning setting leaves the provider default in control. That membership route defaults safely to 262,144 context tokens; the [Kimi Code model-tier table](https://www.kimi.com/code/docs/en/kimi-code/models.html) grants Allegretto and higher plans up to 1M, which those plans may express as `context_window = 1048576`. `k3[1m]` is Claude Code-only and Codewhale rejects it. `kimi-for-coding` remains the valid K2.7 membership route, and `kimi-for-coding-highspeed` is its own high-speed roster entry (262,144 context); membership ids are rejected on the direct platform endpoint, and `kimi-k3` stays rejected on the membership endpoint. Billing is decided by the endpoint the route resolves to, judged once against the two exact product endpoints: direct Moonshot (`https://api.moonshot.ai/v1` or the default) bills metered with dollar estimates, the exact Kimi Code membership endpoint bills as Kimi Code quota and never shows dollar estimates, and anything else — a gateway host, a neighboring Kimi-hosted path — reports `cost: unknown` rather than borrowing either product. An imported Kimi Code token with no `base_url` in its table still resolves to the membership endpoint, so it bills as Kimi Code quota and never accrues dollars. A completed turn, parent or sub-agent, is billed from the immutable endpoint receipt its own client was built with, never from a later config re-read: `MOONSHOT_BASE_URL`/`KIMI_BASE_URL` are merged into the *active* provider's table only, and an in-turn provider switch can move the ambient config off the route that actually ran. Legacy `auth_mode = "kimi_oauth"` fails to API-key guidance without probing Kimi CLI files. Codewhale does not impersonate `kimi_cli` or `kimi_code_cli`. **China-region keys:** contributor field evidence (@vFONGv, PR #5229, verified on Windows 10) reports that a China-region Moonshot key must be paired with `base_url = "https://api.moonshot.cn/v1"`; left on the default international host (`https://api.moonshot.ai/v1`) it fails authentication. We have no China-region key to verify this ourselves, so it is recorded as a user report rather than a tested route. Note also that editing `base_url` alone does not take effect until `codewhale auth set` is re-run for that provider. |
680 | `google` | `[providers.google]` | `GOOGLE_API_KEY`, `GEMINI_API_KEY` | `GOOGLE_BASE_URL`, `GEMINI_BASE_URL`; default `https://generativelanguage.googleapis.com/v1beta/openai/` | `gemini-3.1-pro-preview` (default); `/model` also lists `gemini-3-pro-preview`, `gemini-3.7-flash`, `gemini-3.6-flash`, `gemini-3.5-flash`, `gemini-3.5-flash-lite`, `gemini-2.5-pro`, `gemini-2.5-flash` | Google Gemini as its own backend on the official OpenAI-compatible Chat Completions route. Thinking models capture `extra_content.google.thought_signature` on tool calls and replay it with the assistant tool-call messages; replaying a tool call whose signature was not captured fails closed with an actionable error instead of letting the tool loop break. `gemini-2.5-flash-lite` ships thinking off and degrades with a warning instead. Reasoning effort maps onto the documented `google.thinking_config.thinking_level` (`low`/`high`). The dialect binds to the exact official base URL: a `google` row pointed at another gateway gets plain OpenAI semantics and no signature requirements. Codewhale never reads Google OAuth files; only an AI Studio API key is used. Not live-tested against the real endpoint in this environment. |
681 | `zai` | `[providers.zai]` | `ZAI_API_KEY`, `Z_AI_API_KEY` | `ZAI_BASE_URL`, `Z_AI_BASE_URL`; default `https://api.z.ai/api/coding/paas/v4`; general APIs `https://api.z.ai/api/paas/v4` and `https://open.bigmodel.cn/api/paas/v4` | `GLM-5.3` default; `/model` also lists `GLM-5.3-Flash`, `GLM-5.2`, `GLM-5.1`, and `GLM-5-Turbo` | Z.AI GLM Coding Plan route. All three first-party Chat routes (both api.z.ai products and BigModel's general platform endpoint) share one request dialect, so reasoning controls — the GLM-5.2 thinking toggle, tiered effort, and the forced-thinking GLM-5.3 rewrite that sends `off` as `enabled` + `reasoning_effort: "low"` — apply on BigModel too; neighboring paths such as `/preview` stay fail-closed. The two general API products expose structured provider-native web search (`search-prime` globally, `search_std` in China); Coding Plan and compatible custom endpoints do not inherit it. `GLM-5.3` is the default and a first-class picker row (`model = "GLM-5.3"` or `ZAI_MODEL=GLM-5.3`); `GLM-5.3-Flash` is the 1M multimodal fast sibling (`model = "GLM-5.3-Flash"`). An explicit `GLM-5.2` selection keeps its own id. Limits and reasoning options for 5.3 are inherited from `GLM-5.2` until Z.ai publishes distinct 5.3 metadata; 5.3 carries no price. Flash ships the published $0.15/$0.50 list. A live call can still 429 with entitlement code 1311 on accounts that are not provisioned for 5.3. |
682 | `stepfun` | `[providers.stepfun]` | `STEPFUN_API_KEY`, `STEP_API_KEY` | `STEPFUN_BASE_URL`, `STEP_BASE_URL`; default `https://api.stepfun.ai/v1`; Coding Plan endpoint `https://api.stepfun.ai/step_plan/v1` | `step-3.7-flash` | StepFun / StepFlash direct OpenAI-compatible route. `/provider` setup asks which billing route the key belongs to — pay-as-you-go or Step Plan — validates the key against the chosen endpoint, and writes the answer to `[providers.stepfun].base_url` only. A base URL that is neither recognized route is left alone and the question is skipped. You can also set `[providers.stepfun].base_url` or `STEP_BASE_URL` to the Coding Plan URL by hand. Offline accounting labels recognized routes as `stepfun-payg` or `stepfun-plan` without persisting the raw endpoint, and only the standard PAYG route receives token pricing. `STEPFUN_MODEL` and `STEP_MODEL` are accepted. |
683 | `minimax` | `[providers.minimax]` | `MINIMAX_API_KEY` | `MINIMAX_BASE_URL`; default `https://api.minimax.io/v1`; China `https://api.minimaxi.com/v1` | `MiniMax-M3`, `MiniMax-M2.7`, `MiniMax-M2.7-highspeed`, `MiniMax-M2.5`, `MiniMax-M2.5-highspeed`, `MiniMax-M2.1`, `MiniMax-M2.1-highspeed`, `MiniMax-M2` | MiniMax direct OpenAI-compatible route. Codewhale sends `reasoning_split = true` so MiniMax thinking arrives separately from answer text. Both MiniMax dialects sell pay-as-you-go and Token Plan over the same endpoints and the same key, so billing is classified from the credential *product*, never from the endpoint or from a default. `mode = "token-plan"` in `[providers.minimax]`/`[providers.minimax_anthropic]`, or a Token Plan key shaped `sk-cp…`, bills as MiniMax Token Plan quota with no dollar estimates; an explicit pay-as-you-go mode (`pay-as-you-go`/`payg`/`metered`) wins over key shape. The key's product prefix is only visible when the key is in config, bound by `api_key_env`, or exported as `MINIMAX_API_KEY` on an official endpoint — a key saved through `codewhale auth set` (secret store / OS keyring) is deliberately not read to classify billing. With no explicit mode and no visible product marker the route reports `cost: unknown` rather than assuming pay-as-you-go, so a Token Plan account is never charged invented dollars. Custom/gateway endpoints also fail closed with `cost: unknown`. Official M3 input modalities are text, image, and video; M2.7 is text-only. |
684 | `minimax-anthropic` | `[providers.minimax_anthropic]` | `MINIMAX_API_KEY` | `MINIMAX_ANTHROPIC_BASE_URL`; default `https://api.minimax.io/anthropic`; China `https://api.minimaxi.com/anthropic` | `MiniMax-M3`, `MiniMax-M2.7` | MiniMax direct Anthropic-compatible Messages route. Keep the `/anthropic` suffix because Codewhale appends `/v1/messages`; the route uses `x-api-key`. M3 supports adaptive or disabled thinking. M2.7 always keeps thinking enabled. |
685 | `sglang` | `[providers.sglang]` | Optional `SGLANG_API_KEY` | `SGLANG_BASE_URL`; default `http://localhost:30000/v1` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | Self-hosted OpenAI-compatible route. Localhost deployments commonly omit auth. `SGLANG_MODEL` is accepted. |
686 | `vllm` | `[providers.vllm]` | Optional `VLLM_API_KEY` | `VLLM_BASE_URL`; default `http://localhost:8000/v1` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | Self-hosted vLLM OpenAI-compatible route. Localhost deployments commonly omit auth. `VLLM_MODEL` is accepted. |
687 | `ollama` | `[providers.ollama]` | Local optional `OLLAMA_API_KEY` | `OLLAMA_BASE_URL`; default `http://localhost:11434/v1` | live tag from the local catalog; pre-refresh placeholder `unknown`; provider-hinted custom tags pass through | Local Ollama is keyless by default. `OLLAMA_MODEL` is accepted. The header must not paint a hosted id the local daemon did not list. |
688 | `ollama-cloud` | `[providers.ollama_cloud]` | `OLLAMA_CLOUD_API_KEY`, then `OLLAMA_API_KEY` | `OLLAMA_CLOUD_BASE_URL`; default `https://ollama.com/v1` | `gpt-oss:120b`; arbitrary provider-owned IDs pass through | Hosted OpenAI-compatible `/v1/chat/completions` route. Save credentials under `ollama-cloud`; the exact released `ollama` + Cloud URL tuple has bounded read-only in-memory compatibility with its legacy table and secret slot. `OLLAMA_CLOUD_MODEL` is accepted. |
689 | `huggingface` | `[providers.huggingface]` | `HUGGINGFACE_API_KEY`, `HF_TOKEN` | `HUGGINGFACE_BASE_URL`, `HF_BASE_URL`; default `https://router.huggingface.co/v1` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | Hugging Face Inference Providers OpenAI-compatible router route. Accepted aliases: `huggingface`, `hugging-face`, `hugging_face`, `hf`. Org-prefixed model IDs pass through. `HUGGINGFACE_MODEL` and `HF_MODEL` are accepted. Hub browsing/export are separate future features. |
690 | `modelscope` | `[providers.modelscope]` | `MODELSCOPE_API_KEY` | `MODELSCOPE_BASE_URL`; default `https://api-inference.modelscope.cn/v1` | `Qwen/Qwen3.5-397B-A17B` (default), `Qwen/Qwen3.5-122B-A10B`, `Qwen/Qwen3.5-27B`, `Qwen/Qwen3.5-35B-A3B`, `Qwen/Qwen3.8-27B`, `Qwen/Qwen3.8-Flash-Next`, `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Pro-0813`, `deepseek-ai/DeepSeek-V4.1-Flash`, `ZhipuAI/GLM-4.7-Flash`, `ZhipuAI/GLM-5.2` | ModelScope OpenAI-compatible inference route. Org-prefixed model IDs pass through. `MODELSCOPE_MODEL` is accepted. |
691 | `deepinfra` | `[providers.deepinfra]` | `DEEPINFRA_API_KEY`, `DEEPINFRA_TOKEN` | `DEEPINFRA_BASE_URL`; default `https://api.deepinfra.com/v1/openai` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | DeepInfra OpenAI-compatible route. Drop-in replacement for OpenAI SDK. |
692 | `together` | `[providers.together]` | `TOGETHER_API_KEY` | `TOGETHER_BASE_URL`; default `https://api.together.xyz/v1` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash`, `thinkingmachines/inkling` | Together AI OpenAI-compatible route. `TOGETHER_MODEL` is accepted. Model aliases `deepseek-v4-pro` and `deepseek-v4-flash` normalize to Together's org-prefixed IDs; `inkling` and `together-inkling` normalize to Together's published lowercase Inkling wire ID. Inkling uses the exact `none`/`minimal`/`low`/`medium`/`high`/`max` reasoning vocabulary from Thinking Machines' [official model repository](https://huggingface.co/thinkingmachines/Inkling). Together's [launch post](https://www.together.ai/blog/together-ai-brings-thinking-machines-labs-new-model-inkling-on-day-0) currently says Inkling is live with 1M context, while its [model detail page](https://www.together.ai/models/inkling) says coming soon with 256K context and publishes no price. Until Together's active `/models` endpoint and the Models.dev catalog resolve that conflict, Inkling is not seeded into Codewhale's offline picker and no route-specific context or cost is inferred. |
693 | `qianfan` | `[providers.qianfan]` | `QIANFAN_API_KEY`, `BAIDU_QIANFAN_API_KEY` | `QIANFAN_BASE_URL`, `BAIDU_QIANFAN_BASE_URL`; default `https://api.baiduqianfan.ai/v1` | `ernie-4.0-turbo-8k`; provider-scoped custom Qianfan service/model IDs pass through | Baidu Qianfan OpenAI-compatible route. Requests use Bearer auth and Chat Completions payloads. `QIANFAN_MODEL` and `BAIDU_QIANFAN_MODEL` are accepted; aliases `baidu-qianfan`, `baidu_qianfan`, and `baidu` resolve to this provider. Tool/function calling is model-scoped in Qianfan docs, so Codewhale preserves the selected wire model and leaves live capability proof to follow-up route/capability work. |
694 | `openai-codex` | `[providers.openai_codex]` | Native ChatGPT PKCE (`codewhale auth chatgpt` / `/provider setup openai-codex`), process token via `OPENAI_CODEX_ACCESS_TOKEN`/`CODEX_ACCESS_TOKEN`, or exact-path read-only consent after `codex login` | `OPENAI_CODEX_BASE_URL`/`CODEX_BASE_URL`; default `https://chatgpt.com/backend-api` | `gpt-5.5` | **Experimental.** Talks to the OpenAI Responses API at `/codex/responses`. Native Sign in with ChatGPT stores refreshable tokens in Codewhale-owned storage and bills the ChatGPT subscription; the `openai` API-key route is a different billing owner. Codex CLI files remain disabled by default; `codewhale auth external-consent --provider openai-codex --mode read-only` is an explicit import alternative. Codewhale never refreshes or rewrites that external file, and expired external tokens fail closed. Revoke owned tokens with `codewhale auth chatgpt-revoke`. `OPENAI_CODEX_MODEL`/`CODEX_MODEL` and `OPENAI_CODEX_ACCOUNT_ID`/`CODEX_ACCOUNT_ID` are accepted. Codewhale budgets this route with the 400K Codex-family effective context window even when the public API model table lists a larger native `gpt-5.5` window. OpenAI has not published a third-party client registration for this public Codex OAuth client; the adapter uses the published issuer, PKCE S256, honest `originator=codewhale`, and does not call unpublished device-auth endpoints. |
695 | `anthropic` | `[providers.anthropic]` | `ANTHROPIC_API_KEY` | `ANTHROPIC_BASE_URL`; default `https://api.anthropic.com` | `claude-opus-4-8`, `claude-sonnet-4-6` (default), `claude-haiku-4-5` | Native Anthropic Messages API route (`/v1/messages`, `x-api-key` + `anthropic-version: 2023-06-01`) — not OpenAI-compatible. Prompt caching via `cache_control` breakpoints, adaptive thinking + `output_config.effort`, signed thinking blocks replayed verbatim, cache telemetry normalized per #2961. `ANTHROPIC_MODEL` is accepted. |
696 | `openmodel` | `[providers.openmodel]` | `OPENMODEL_API_KEY` | `OPENMODEL_BASE_URL`; default `https://api.openmodel.ai` | `deepseek-v4-flash`; provider-scoped custom model IDs pass through | OpenModel Anthropic-compatible Messages route. Uses `/v1/messages`, Bearer auth, and `anthropic-version: 2023-06-01`; OpenModel selects DeepSeek, DashScope, Xiaomi, Claude, and other routes by model id. `OPENMODEL_MODEL` is accepted. |
697 | `sakana` | `[providers.sakana]` | `FUGU_API_KEY`, `SAKANA_API_KEY` | `SAKANA_BASE_URL`; default `https://api.sakana.ai/v1` | `fugu` (default), `fugu-ultra-20260615` | Sakana AI Fugu OpenAI-compatible route. Standard Chat Completions wire protocol; streaming supported. `fugu-ultra-20260615` is the heavy/reasoning variant. Env var aliases: `FUGU_API_KEY` (primary), `SAKANA_API_KEY`; provider aliases: `sakana-ai`, `sakana_ai`, `fugu`. |
698 | `longcat` | `[providers.longcat]` | `LONGCAT_API_KEY` | `LONGCAT_BASE_URL`; default `https://api.longcat.chat/openai/v1` | `LongCat-2.0` (default) | Meituan LongCat curated model gateway. OpenAI-compatible Chat Completions wire protocol. Sign up at https://longcat.chat/platform for an API key. Provider aliases: `long-cat`, `meituan-longcat`, `meituan`. |
699 | `opencode-go` | `[providers.opencode_go]` | `OPENCODE_GO_API_KEY` | `OPENCODE_GO_BASE_URL`; default `https://opencode.ai/zen/go/v1` | `deepseek-v4-pro` (default), `grok-4.5`, `glm-5.2`, `glm-5.1`, `kimi-k3`, `kimi-k2.7-code`, `kimi-k2.6`, `deepseek-v4-flash`, `mimo-v2.5`, `mimo-v2.5-pro` | [OpenCode Go](https://opencode.ai/docs/go/) subscription route using OpenAI-compatible Chat Completions. `OPENCODE_GO_MODEL` is accepted. Codewhale uses bare wire IDs; familiar `opencode-go/<model-id>` input aliases normalize to the bare ID. Go models documented only on the Anthropic `/messages` endpoint are deliberately not advertised by this route until Codewhale supports per-model wire selection. Billing surfaces show the Go allowance instead of token-price estimates. |
700 | `opencode-zen` | `[providers.opencode_zen]` | `OPENCODE_ZEN_API_KEY`, fallback `OPENCODE_API_KEY` | `OPENCODE_ZEN_BASE_URL`; default `https://opencode.ai/zen/v1` | `gpt-5.5` (default); current documented GPT, Claude, Qwen, DeepSeek, MiniMax, GLM, Kimi, Grok, and free-model IDs | [OpenCode Zen](https://opencode.ai/docs/zen/) model-aware gateway. `OPENCODE_ZEN_MODEL` is accepted, and official `opencode/<model-id>` selectors normalize to bare wire IDs. GPT rows use `/responses`; Claude and Qwen rows use `/messages`; DeepSeek, MiniMax, GLM, Kimi, Grok, and the listed free rows use `/chat/completions`. Responses and Chat Completions authenticate with Bearer `Authorization`, while Anthropic Messages uses `x-api-key`; none of these routes use ChatGPT/Codex OAuth guidance or headers. Gemini currently fails closed because its model-specific Google wire protocol is not implemented. Unknown models also fail closed until their protocol is present in the curated catalog. |
701 | `meta` | `[providers.meta]` | `META_MODEL_API_KEY`, `MODEL_API_KEY` | `META_MODEL_API_BASE_URL`, `MODEL_API_BASE_URL`; default `https://api.meta.ai/v1` | `muse-spark-1.2` (default) | [Meta Model API](https://developer.meta.com/ai/resources/blog/build-with-muse-spark/) public-preview route using OpenAI-compatible Chat Completions. Muse Spark 1.2 keeps its wire ID, tool support, 1M context, 32K output metadata, and `none` through `xhigh` reasoning effort. `META_MODEL_API_MODEL` and `MODEL_API_MODEL` are accepted. Provider aliases: `meta-ai`, `meta_model_api`, `muse`, `muse-spark`. |
702 | `telecomjs` | `[providers.telecomjs]` | `TELECOMJS_API_KEY` | `TELECOMJS_BASE_URL`; default `https://aigw.telecomjs.com/v1` | `deepseek-v4-pro` conservative fallback; authenticated `/models` rows when a key is configured | TelecomJS TokenHub OpenAI-compatible Chat Completions route. Live catalogs are isolated by provider and key fingerprint, stale rows survive transient refresh failures, and unsupported reasoning request fields are omitted. `TELECOMJS_MODEL` is accepted. Provider aliases: `telecom-js`, `telecom_js`, `telecomjs-cn`, `tokenhub`. |
703 | `mistral` | `[providers.mistral]` | `MISTRAL_API_KEY` | `MISTRAL_BASE_URL`; default `https://api.mistral.ai/v1` | `mistral-code-latest` (default; `codestral-latest` accepted as alias), `mistral-medium-latest` (aliases: `mistral-medium-3-5`), `mistral-small-latest` (aliases: `mistral-small-2603`), `mistral-large-latest` | Mistral AI (la Plateforme) OpenAI-compatible Chat route. On the documented first-party HTTPS `/v1` hosts, Medium and Small send adjustable `reasoning_effort` (`none` or `high` only), parse Mistral's polymorphic thinking/text blocks, and replay stored thinking in that same wire shape. Deprecated native Magistral IDs remain explicit-configuration compatibility routes: they are always-reasoning and never receive the adjustable effort field. Code and Large are non-reasoning. A custom `MISTRAL_BASE_URL` keeps generic Chat semantics unless it is one of the documented first-party hosts. `MISTRAL_MODEL` is accepted. Provider aliases: `mistral-ai`, `mistralai`, `la-plateforme`. |
704 | `edenai` | `[providers.edenai]` | `EDENAI_API_KEY` | `EDENAI_BASE_URL`; default `https://api.edenai.run/v3`; EU `https://api.eu.edenai.run/v3` | `deepseek/deepseek-v4-pro` (default); live `/models` catalog of `provider/model` ids | Eden AI OpenAI-compatible aggregation gateway. Catalog rows remain provider-scoped; generic reasoning controls are omitted because supported fields depend on the selected upstream family. `EDENAI_MODEL` is accepted. The default `deepseek/deepseek-v4-pro` is listed on the global catalog only; on the EU endpoint set `EDENAI_MODEL` (or `model`) to a row from the EU `/models` list, for example `qwen/deepseek-v4-pro`. Provider aliases: `eden-ai`, `eden_ai`. |
705 | `zenmux` | `[providers.zenmux]` | `ZENMUX_API_KEY` | `ZENMUX_BASE_URL`; default `https://zenmux.ai/api/v1` | `deepseek/deepseek-v4.1-flash` (default); live `/models` catalog of `provider/model` ids (keyless-readable) | ZenMux OpenAI-compatible aggregation gateway (~190 models). Catalog rows remain provider-scoped; generic reasoning controls are omitted because supported fields depend on the selected upstream family. `ZENMUX_MODEL` is accepted. Provider aliases: `zen-mux`, `zen_mux`. |
706 | `csdn` | `[providers.csdn]` | `CSDN_API_KEY` | `CSDN_BASE_URL`; default `https://ai.csdn.net/api/model/v1` | `glm_for_coding` (default; the Coding Plan's dedicated model id); other marketplace model ids pass through | CSDN 星图 (Starmap) OpenAI-compatible hosted platform. Coding Plan keys and general marketplace keys share the one endpoint, so billing follows the credential product, never the URL alone: routing `glm_for_coding` — the shipped default — or setting `mode = "coding_plan"`/`"plan"`/`"subscription"` bills as CSDN Coding Plan quota with no dollar estimates; any other model, or an explicit `pay-as-you-go`/`metered` mode, bills metered; an unrecognized mode or an endpoint off `ai.csdn.net/api/model/v1` reports `cost: unknown`. `CSDN_MODEL` is accepted. Provider aliases: `csdn-ai`, `csdn_ai`, `csdn-coding-plan`, `csdn_coding_plan`, `starmap`. |
707 | `concentrate` | `[providers.concentrate]` | `CONCENTRATE_API_KEY` | `CONCENTRATE_BASE_URL`; default `https://api.concentrate.ai/v1` | `deepseek-v4-pro` (default; a plain catalog id lets the gateway pick the upstream provider); `provider/model` ids such as `openai/gpt-5.6-sol` pin one upstream; `concentrate/auto` is the gateway's own router; unauthenticated live `/v1/models` catalog | Concentrate OpenAI Responses-compatible gateway (`POST /v1/responses`, bearer Universal API key). Opt-in and BYOK only: your key, your Concentrate bill, zero Codewhale fee, no managed default. Requests carry only documented fields (the system prompt rides as a `system` input item). Contract: [API introduction](https://concentrate.ai/docs/api-reference/introduction), [request parameters](https://concentrate.ai/docs/api-reference/endpoint/request-parameters), [streaming](https://concentrate.ai/docs/api-reference/endpoint/streaming), [errors](https://concentrate.ai/docs/api-reference/endpoint/errors). See [Concentrate Notes](#concentrate-notes). |
708 | `codewhale` | `[providers.codewhale]` | `CODEWHALE_API_KEY` | `CODEWHALE_API_BASE`; default `https://api.codewhale.net/v1` | `deepseek/deepseek-v4-pro` (default), `anthropic/claude-sonnet-5`, `openai/gpt-5.6` are offline bootstrap rows only; the authenticated `GET /v1/models` listing of the account's connected providers is the catalog authority | Codewhale API: account-backed model access over the provider keys the customer connected to their Codewhale account. One `cwc_key_…` account API key with the `models:infer` scope authenticates every model. Model ids are `provider/model` exactly as the account catalog returns them, and each row states its protocol (`chat-completions` → `/v1/chat/completions`, `anthropic-messages` → `/v1/messages`, `responses` → `/v1/responses`); every protocol uses `Authorization: Bearer`, never `x-api-key`. `CODEWHALE_API_BASE` must be HTTPS except on loopback. Connect provider keys with `codewhale account keys set <provider>`. Provider aliases: `codewhale-api`, `cw-api`, `codewhale-cloud`. |
709 | `xai` | `[providers.xai]` | `XAI_API_KEY`, Codewhale-owned device OAuth, or explicit read-only Grok CLI consent | `XAI_BASE_URL`; default `https://api.x.ai/v1` | `grok-4.6` (default), `grok-4.5`, `grok-4.3`, `grok-build`, `grok-composer-2.5-fast`, `grok-4.20-0309-reasoning`, `grok-4.20-0309-non-reasoning` | xAI/Grok OpenAI-compatible Chat Completions route. Grok 4.6 has a 500K context window, text/image input, function calls, structured output, server-side web search, and `low`/`medium`/`high`/`xhigh` reasoning (default `high`). Its standard rates double when the prompt reaches 200K tokens; the same 2x long-context rule applies to `grok-4.5` (500K context, $2.00 / $0.30 cached / $6.00) and `grok-4.3` (1M context, $1.25 / $0.20 cached / $2.50) per their [model pages](https://docs.x.ai/docs/models/grok-4.5). There is no documented `latest`/`fast` alias and no published numeric output limit. **API-key** (default): Bearer token from console.x.ai via `XAI_API_KEY` / keyring / `api_key`. **OAuth**: `codewhale auth xai-device` uses SSH-friendly device login and Codewhale-owned storage, which may refresh itself. Existing Grok CLI credentials require `codewhale auth external-consent --provider xai --mode read-only`; the granted external file is never refreshed or rewritten. OAuth may return HTTP 403 on some SuperGrok tiers — keep API-key as the reliable fallback. `XAI_MODEL` is accepted. Provider aliases: `x-ai`, `x_ai`, `grok`. |
710 | `modelstudio-token-plan` | `[providers.modelstudio_token_plan]` | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` | `MODELSTUDIO_TOKEN_PLAN_BASE_URL`; default `https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1` | `qwen3.8-max` (default), `qwen3.8-max-preview`, `qwen3.7-plus`, `qwen3.7-max`, `qwen3.6-flash`, `deepseek-v4-pro`, `deepseek-v4-flash-0731`, `glm-5.2` | Alibaba Cloud Model Studio Token Plan OpenAI-compatible Chat Completions route. Token Plan Personal and Team share this endpoint. `qwen3.8-max`, `qwen3.7-plus`, and `qwen3.7-max` can use provider-native web search through the Token Plan Responses Harness; the preview, Coding Plan, and Anthropic routes do not inherit that capability. All listed models are reasoning-capable text/coding models. DeepSeek and GLM entries are provider-scoped and do not collide with first-party routes. `MODELSTUDIO_TOKEN_PLAN_MODEL` is accepted. Provider aliases: `modelstudio-token-plan`, `alibaba-token-plan`, `dashscope-token-plan`. |
711 | `modelstudio-token-plan-anthropic` | `[providers.modelstudio_token_plan_anthropic]` | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` | default `https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic` | Same model catalog as `modelstudio-token-plan` | Token Plan Anthropic-compatible Messages route (`/apps/anthropic`). Same API key as the OpenAI dialect. Provider aliases: `modelstudio-token-plan-anthropic`, `alibaba-token-plan-anthropic`. |
712 | `modelstudio-coding-plan` | `[providers.modelstudio_coding_plan]` | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` | `MODELSTUDIO_CODING_PLAN_BASE_URL`; default `https://coding-intl.dashscope.aliyuncs.com/v1` | `qwen3.8-max` (default); same catalog as Token Plan | Alibaba Cloud Model Studio Coding Plan OpenAI-compatible Chat Completions route. `MODELSTUDIO_CODING_PLAN_MODEL` is accepted. Provider aliases: `modelstudio-coding-plan`, `alibaba-coding-plan`, `dashscope-coding-plan`. |
713 | `modelstudio-coding-plan-anthropic` | `[providers.modelstudio_coding_plan_anthropic]` | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` | default `https://coding-intl.dashscope.aliyuncs.com/apps/anthropic` | Same model catalog as `modelstudio-coding-plan` | Coding Plan Anthropic-compatible Messages route (`/apps/anthropic`). Provider aliases: `modelstudio-coding-plan-anthropic`, `alibaba-coding-plan-anthropic`. |
714
715 StepFun's four coding models are available through both its standard API and
716 [Step Plan](https://platform.stepfun.ai/docs/en/step-plan/integrations/reasoning-api).
717 Choose the billing route in `/provider`, then the model in `/model`; existing
718 Step 3.7 selections remain unchanged. [Step 5 Preview](https://platform.stepfun.ai/docs/en/guides/models/step-5-preview)
719 has a 1M context window. Step 5 and Step 3.7 expose low/medium/high reasoning;
720 Step 3.5 Flash 2603 exposes low/high; base Step 3.5 uses provider-default reasoning.
721 [Published API prices](https://platform.stepfun.ai/docs/en/guides/pricing/details)
722 apply only to verified PAYG routes. Step Plan displays subscription allowance.
723 Speech, music and image-generation models use separate interfaces and are not
724 presented as coding models. Provider video capability metadata does not imply
725 that every Codewhale client can attach video.
726
727
728 ### OpenCode Zen protocol catalog
729
730 Zen Responses and Chat Completions requests authenticate with Bearer
731 `Authorization`; Zen Anthropic Messages requests use `x-api-key`. None of these
732 routes add ChatGPT/Codex OAuth headers.
733
734 The bundled Zen transport snapshot follows the [official endpoint
735 table](https://opencode.ai/docs/zen/) and is intentionally explicit:
736
737 - Responses: `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5`,
738 `gpt-5.5-pro`, `gpt-5.4`, `gpt-5.4-pro`, `gpt-5.4-mini`, `gpt-5.4-nano`,
739 `gpt-5.3-codex`, `gpt-5.3-codex-spark`, `gpt-5.2`, `gpt-5.2-codex`,
740 `gpt-5.1`, `gpt-5.1-codex`, `gpt-5.1-codex-max`,
741 `gpt-5.1-codex-mini`, `gpt-5`, `gpt-5-codex`, `gpt-5-nano`.
742 - Anthropic Messages: `claude-fable-5`, `claude-opus-4-8`,
743 `claude-opus-4-7`, `claude-opus-4-6`, `claude-opus-4-5`,
744 `claude-sonnet-5`, `claude-sonnet-4-6`, `claude-sonnet-4-5`,
745 `claude-haiku-4-5`, `qwen3.7-max`, `qwen3.7-plus`, `qwen3.6-plus`,
746 `qwen3.5-plus`.
747 - Chat Completions: `deepseek-v4-pro`, `deepseek-v4-flash`, `minimax-m3`,
748 `minimax-m2.7`, `minimax-m2.5`, `glm-5.2`, `glm-5.1`, `glm-5`,
749 `kimi-k2.5`, `kimi-k2.6`, `kimi-k2.7-code`, `grok-4.5`,
750 `grok-build-0.1`, `big-pickle`, `mimo-v2.5-free`,
751 `north-mini-code-free`, `nemotron-3-ultra-free`,
752 `deepseek-v4-flash-free`.
753
754 Gemini entries are excluded because the official table assigns them Google's
755 model-specific protocol. A catalog miss never falls back to another Zen wire
756 shape, including when a custom Zen base URL is configured.
757
758 ### Concentrate Notes
759
760 Concentrate (`concentrate`) is an OpenAI **Responses**-compatible gateway:
761 `POST https://api.concentrate.ai/v1/responses` with `Authorization: Bearer
762 <Universal API key>`. It is opt-in and **BYOK only**.
763
764 - **Model ids pass through.** A plain catalog id (`gpt-5.6-sol`,
765 `deepseek-v4-pro`) lets the gateway choose the upstream provider;
766 `provider/model` (`openai/gpt-5.6-sol`) pins the upstream provider inside the
767 gateway; `concentrate/auto` sends the gateway's own `auto` router. Codewhale's
768 bare `--model auto` remains the resolver sentinel (provider default), which is
769 why the gateway router has its own explicit spelling. Once streaming begins
770 the gateway commits to one provider ([auto routing](https://concentrate.ai/docs/api-reference/endpoint/auto-routing)).
771 - **Wire.** Fixed Responses dialect. The request carries only documented
772 fields — `model`, `input`, `stream`, `max_output_tokens`, `tools`,
773 `tool_choice`, `parallel_tool_calls`, `reasoning.effort` — and the system
774 prompt travels as a leading `system` input item because `instructions` is
775 not in the gateway's [parameter reference](https://concentrate.ai/docs/api-reference/endpoint/request-parameters).
776 Streaming follows the typed `response.*` SSE events and ends on
777 `response.completed` without a `[DONE]` sentinel ([streaming](https://concentrate.ai/docs/api-reference/endpoint/streaming)).
778 - **Errors.** `{ "error", "message", "model"?, "retry_after"? }` with 400
779 (bad request / unknown model), 401 (invalid key), 402 (insufficient
780 credits), 424 (upstream provider unavailable), 429 (rate limit) —
781 surfaced verbatim and classified by message ([errors](https://concentrate.ai/docs/api-reference/endpoint/errors)).
782 - **Catalog.** `GET /v1/models` needs no key
783 ([list models](https://concentrate.ai/docs/api-reference/endpoint/list-models)); the live rows
784 are provider-scoped and unclaimed (no pricing or capability claims).
785 - **Commercial boundary.** Concentrate's [Terms of Service](https://concentrate.ai/legal/terms-of-service)
786 forbid reselling, white-labeling, or providing the service on a
787 service-bureau basis without written consent, and its
788 [Acceptable Use Policy](https://concentrate.ai/legal/acceptable-use-policy)
789 forbids sharing or sublicensing keys. Codewhale therefore ships **no**
790 Codewhale-owned Concentrate key, no stored customer key, no default or
791 managed routing, and no markup — activation of any hosted lane is gated on
792 written consent, terms, and billing approval (tracked in the Codewhale ops
793 evidence checklist `concentrate-gateway-20260829/CHECKLIST.md`). Public
794 pricing states "No platform markup on tokens".
795 - **Self-test without a key.** `scripts/concentrate-selftest.sh` boots a
796 local stub that speaks the documented contract and drives the real
797 `codewhale exec` path through it, asserting the URL, bearer header, model
798 passthrough, streaming, and the completed-turn receipt. No network call
799 leaves the machine and no account is required.
800
801 ### Hugging Face Provider vs MCP vs Hub
802
803 Codewhale's `huggingface` provider ID is only the OpenAI-compatible chat
804 inference route through Hugging Face Inference Providers. It is selected with
805 `/provider huggingface`, `CODEWHALE_PROVIDER=huggingface`, or
806 `provider = "huggingface"`.
807
808 Hugging Face MCP is a separate external-tool route. Configure it through the
809 MCP config described in `docs/MCP.md`, preferably using the settings-generated
810 snippet from <https://huggingface.co/settings/mcp>. In the TUI, `/hf mcp status`
811 checks whether the Hugging Face MCP server appears in the resolved MCP config,
812 `/hf mcp setup` prints the settings workflow and a placeholder-only shape, and
813 `/hf concepts` explains the provider/MCP/Hub distinction.
814
815 Hub publishing or repository management remains explicit user action through
816 Hub-native tooling such as `huggingface_hub` or git. The `/hf` helper does not
817 upload to Hugging Face and does not perform direct Hugging Face Hub HTTP search.
818
819 ### Xiaomi MiMo Notes
820
821 `xiaomi-mimo` defaults to `mimo-v2.5-pro` for long-context reasoning and coding
822 work. The chat picker also exposes `mimo-v2.5-pro-ultraspeed` and the latest
823 Omni model `mimo-v2.5`. Xiaomi MiMo TTS is available through
824 `codewhale --provider xiaomi-mimo speech "text" --model tts` (or the `tts`
825 alias). In Act and Operate, the provider-specific `speech` / `tts` tools are
826 available through deferred discovery when the Xiaomi MiMo route is configured.
827
828 `/provider xiaomi-mimo ultraspeed` and `/provider xiaomi-mimo pro-ultraspeed`
829 both select `mimo-v2.5-pro-ultraspeed`. Speech aliases such as `tts`,
830 `voice-design`, and `voice-clone` are separate from normal chat defaults.
831
832 Token Plan keys default to the Singapore endpoint
833 `https://token-plan-sgp.xiaomimimo.com/v1`. If your MiMo account is provisioned
834 for the China region, set `base_url = "https://token-plan-cn.xiaomimimo.com/v1"`
835 explicitly in `[providers.xiaomi_mimo]` or set `mode = "token-plan-cn"`. Europe
836 Token Plan accounts can set
837 `base_url = "https://token-plan-ams.xiaomimimo.com/v1"` or use
838 `mode = "token-plan-ams"`; `mode = "pay-as-you-go"`
839 selects the standard API endpoint and standard MiMo key family. Xiaomi Token
840 Plan docs and console expose credit/quota semantics, but Codewhale does not
841 currently have a documented balance endpoint to poll, so cost display remains
842 unknown rather than reusing token-price estimates from another provider.
843
844 Voice-design and voice-clone shorthands map to `mimo-v2.5-tts-voicedesign` and
845 `mimo-v2.5-tts-voiceclone`. Xiaomi's current
846 [image-understanding guide](https://platform.xiaomimimo.com/docs/en-US/usage-guide/multimodal-understanding/image-understanding)
847 includes `mimo-v2.5` for image input. Codewhale exposes image analysis through the
848 separate `[vision_model]` / `image_analyze` path; set that model to
849 `mimo-v2.5` when using MiMo for vision.
850
851 ### OpenRouter-Compatible Base URLs
852
853 OpenRouter-compatible gateways should usually stay on the `openrouter`
854 provider with a provider-scoped `base_url` override instead of moving through
855 the generic `openai` route. That keeps OpenRouter-style reasoning, streaming,
856 cache usage, and namespaced wire model parsing attached to the selected route:
857
858 ```toml
859 provider = "openrouter"
860
861 [providers.openrouter]
862 api_key = "sk-..."
863 base_url = "https://openrouter-compatible.example/v1"
864 model = "deepseek/deepseek-v4-pro"
865 ```
866
867 Codewhale preserves the `deepseek/` wire-model prefix under the OpenRouter
868 provider scope; it does not infer a switch to the direct DeepSeek provider from
869 that model string. Cache fields such as `prompt_cache_hit_tokens`,
870 `prompt_cache_miss_tokens`, and `prompt_tokens_details.cached_tokens` are
871 parsed when the upstream gateway sends them. If a key/account type omits those
872 fields, Codewhale treats them as absent for that response rather than as a
873 different provider route.
874
875 OrcaRouter (`https://api.orcarouter.ai/v1`) is a dedicated named route
876 ([OrcaRouter](https://www.orcarouter.ai)) that speaks the same OpenAI
877 Chat Completions wire protocol and serves the same namespaced
878 `vendor/model` catalog. It does not need an OpenRouter-compatible
879 `base_url` override: select `provider = "orcarouter"` and its namespaced
880 wire models (for example `deepseek/deepseek-v4-pro` or its own
881 `orcarouter/auto` router) pass through verbatim, exactly as they do on the
882 OpenRouter provider scope.
883
884 ### Recent OpenRouter Large Models
885
886 OpenRouter completions and static registry rows include the April 2026 onward
887 large models verified through OpenRouter's model metadata:
888 `arcee-ai/trinity-large-thinking`, `qwen/qwen3.6-flash`,
889 `qwen/qwen3.6-35b-a3b`, `qwen/qwen3.6-max-preview`, `qwen/qwen3.6-27b`,
890 `qwen/qwen3.6-plus`, `minimax/minimax-m3`, `xiaomi/mimo-v2.5-pro`,
891 `xiaomi/mimo-v2.5`, `moonshotai/kimi-k2.7-code`, `moonshotai/kimi-k2.6`,
892 `z-ai/glm-5.1`, `z-ai/glm-5.2`, `z-ai/glm-5-turbo`, `tencent/hy3-preview`,
893 `google/gemma-4-31b-it`, `google/gemma-4-26b-a4b-it`, and
894 `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free`.
895 `minimax/minimax-m3` was added from OpenRouter's May 31, 2026 listing as a 1M
896 context multimodal model for coding, tool use, and long-horizon agentic work.
897 `GLM-5.3` is now the default direct Z.AI Coding Plan model; `GLM-5.2` /
898 `z-ai/glm-5.2` remain available (explicit selections keep their own id),
899 `GLM-5.1` / `z-ai/glm-5.1` remain available as the smaller model,
900 `GLM-5.3-Flash` / `z-ai/glm-5.3-flash` is the faster/explore sibling of
901 `GLM-5.3`, and `GLM-5-Turbo` / `z-ai/glm-5-turbo` remains the faster sibling
902 of `GLM-5.2`.
903 `GLM-5.3` / `z-ai/glm-5.3` and `GLM-5.3-Flash` / `z-ai/glm-5.3-flash` are
904 first-class picker ids on the Z.ai and OpenRouter routes (`/model` after
905 `/provider zai`, or `model = "GLM-5.3-Flash"`).
906 Limits and reasoning options for 5.3 are inherited from
907 `GLM-5.2` until Z.ai publishes distinct 5.3 metadata, and 5.3 carries no
908 price. Flash ships the published $0.15/$0.50 list. A live call can still
909 429 with entitlement code 1311 on accounts that are not provisioned for 5.3.
910
911 ## Static Model Registry
912
913 `codewhale model list` and `codewhale model resolve` use the static registry in
914 `crates/agent/src/lib.rs`. This is not the same as live `/models` discovery.
915 Use `/models` or `codewhale models` to fetch model IDs from the active API
916 endpoint when the endpoint supports model listing.
917
918 | Provider | Static registry entries | Tool calls | Registry reasoning flag |
919 | --- | --- | --- | --- |
920 | `deepseek` | `deepseek-v4-pro`, `deepseek-v4-flash`, `deepseek-v4-flash-vision-exp` | yes | yes |
921 | `nvidia-nim` | `deepseek-ai/deepseek-v4-pro`, `deepseek-ai/deepseek-v4-flash` | yes | yes |
922 | `openai` | `deepseek-v4-pro`, `deepseek-v4-flash`, `gpt-5.6`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna` | yes | yes |
923 | `atlascloud` | `deepseek-ai/deepseek-v4-flash`, `deepseek-ai/deepseek-v4-pro` | yes | yes |
924 | `wanjie-ark` | `deepseek-reasoner` | yes | yes |
925 | `volcengine` | `DeepSeek-V4-Pro`, `DeepSeek-V4-Flash` | yes | yes |
926 | `openrouter` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`, `arcee-ai/trinity-large-thinking`, `minimax/minimax-m3`, `minimax/minimax-m2.7`, `xiaomi/mimo-v2.5-pro`, `xiaomi/mimo-v2.5`, `qwen/qwen3.6-flash`, `qwen/qwen3.6-35b-a3b`, `qwen/qwen3.6-max-preview`, `qwen/qwen3.6-27b`, `qwen/qwen3.6-plus`, `qwen/qwen3.7-max`, `moonshotai/kimi-k2.7-code`, `moonshotai/kimi-k2.6`, `z-ai/glm-5.1`, `z-ai/glm-5.2`, `z-ai/glm-5.3`, `z-ai/glm-5.3-flash`, `z-ai/glm-5-turbo`, `tencent/hy3-preview`, `google/gemma-4-31b-it`, `google/gemma-4-26b-a4b-it`, `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free`, `nvidia/nemotron-3-ultra-550b-a55b` | yes | yes |
927 | `orcarouter` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`, `orcarouter/auto` | yes | yes |
928 | `xiaomi-mimo` | `mimo-v2.5-pro`, `mimo-v2.5-pro-ultraspeed`, `mimo-v2.5`; speech/TTS IDs are selected through `codewhale speech` / `tts` | yes | yes for chat models; no for speech/TTS models |
929 | `novita` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash` | yes | yes |
930 | `fireworks` | `accounts/fireworks/models/deepseek-v4-pro` | yes | yes |
931 | `siliconflow` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | yes | yes |
932 | `arcee` | `trinity-large-thinking`, `trinity-large-preview`; provider-hinted custom model IDs pass through | yes | yes for `trinity-large-thinking`; no for `trinity-large-preview` |
933 | `moonshot` | `kimi-k2.7-code`, `kimi-k2.6` | yes | yes |
934 | `zai` | `GLM-5.3`, `GLM-5.3-Flash`, `GLM-5.2`, `GLM-5.1`, `GLM-5-Turbo`; provider-hinted custom model IDs pass through | yes | yes |
935 | `stepfun` | `step-3.7-flash` (default), `step-5-preview`, `step-3.5-flash`, `step-3.5-flash-2603` | yes | yes |
936 | `minimax` | `MiniMax-M3`, `MiniMax-M2.7`, `MiniMax-M2.7-highspeed`, `MiniMax-M2.5`, `MiniMax-M2.5-highspeed`, `MiniMax-M2.1`, `MiniMax-M2.1-highspeed`, `MiniMax-M2` | yes | yes |
937 | `minimax-anthropic` | `MiniMax-M3`, `MiniMax-M2.7` | yes | yes |
938 | `sglang` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | yes | yes |
939 | `vllm` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | yes | yes |
940 | `ollama` | live local tag; custom tags pass through when provider hint is `ollama` | yes | no |
941 | `ollama-cloud` | `gpt-oss:120b`; arbitrary provider-owned model IDs pass through | yes | yes |
942 | `huggingface` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | yes | no |
943 | `modelscope` | `Qwen/Qwen3.5-397B-A17B`, `Qwen/Qwen3.5-122B-A10B`, `Qwen/Qwen3.5-27B`, `Qwen/Qwen3.5-35B-A3B`, `Qwen/Qwen3.8-27B`, `Qwen/Qwen3.8-Flash-Next`, `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Pro-0813`, `deepseek-ai/DeepSeek-V4.1-Flash`, `ZhipuAI/GLM-4.7-Flash`, `ZhipuAI/GLM-5.2` | yes | no |
944 | `deepinfra` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | yes | yes |
945 | `together` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash`, `thinkingmachines/inkling` | yes | yes |
946 | `openai-codex` | `gpt-5.5` | yes | yes |
947 | `anthropic` | `claude-opus-5`, `claude-opus-4-8`, `claude-sonnet-5`, `claude-sonnet-4-6`, `claude-fable-5`, `claude-haiku-4-5` | yes | yes except `claude-haiku-4-5` |
948 | `openmodel` | `deepseek-v4-flash`; provider-scoped custom model IDs pass through | yes | model-dependent |
949 | `sakana` | `fugu`, `fugu-ultra-20260615` | yes | yes for `fugu-ultra-20260615` |
950 | `longcat` | `LongCat-2.0` | yes | yes |
951 | `opencode-go` | `deepseek-v4-pro`, `grok-4.5`, `glm-5.2`, `glm-5.1`, `kimi-k3`, `kimi-k2.7-code`, `kimi-k2.6`, `deepseek-v4-flash`, `mimo-v2.5`, `mimo-v2.5-pro` | yes | yes |
952 | `meta` | `muse-spark-1.2` | yes | yes |
953 | `xai` | `grok-4.6`, `grok-4.5`, `grok-4.3`, `grok-build`, `grok-composer-2.5-fast`, `grok-4.20-0309-reasoning`, `grok-4.20-0309-non-reasoning` | yes | yes for `grok-4.6`, `grok-4.5`, `grok-4.3`, `grok-build`, and `grok-4.20-0309-reasoning` |
954 | `google` | `gemini-3.1-pro-preview`, `gemini-3-pro-preview`, `gemini-3.7-flash`, `gemini-3.6-flash`, `gemini-3.5-flash`, `gemini-3.5-flash-lite`, `gemini-2.5-pro`, `gemini-2.5-flash` | yes | yes except `gemini-3.5-flash-lite` |
955 | `mistral` | `mistral-code-latest`, `mistral-medium-latest`, `mistral-small-latest`, `mistral-large-latest` | yes | yes for Medium and Small (`reasoning_effort` `none` or `high` on exact first-party routes); deprecated native Magistral remains an always-on explicit compatibility ID; no for Code and Large |
956 | `modelstudio-token-plan`, `modelstudio-coding-plan` | `qwen3.8-max`, `qwen3.8-max-preview`, `qwen3.7-plus`, `qwen3.7-max`, `qwen3.6-flash`, `deepseek-v4-pro`, `deepseek-v4-flash-0731`, `glm-5.2` | yes | yes |
957 | `csdn` | `glm_for_coding`; other marketplace model IDs pass through | yes | yes |
958
959 AtlasCloud keeps the same default model as the config layer and adds
960 provider-scoped aliases for the Pro and Flash rows. Other AtlasCloud model IDs
961 should still be selected through `ATLASCLOUD_MODEL`, config, or live model
962 listing when available.
963
964 ## Capability Metadata
965
966 `codewhale doctor --json` exposes the `capability` object. It is static
967 metadata, not a live API probe. Current fields are:
968
969 `resolved_provider`, `resolved_model`, `context_window`, `max_output`,
970 `thinking_supported`, `cache_telemetry_supported`, and `request_payload_mode`.
971
972 When configuration cannot be loaded or validated, `doctor --json` exits
973 nonzero and prints a bounded, secret-redacted JSON error envelope with
974 `status = "error"` and `error.kind = "config_validation"` instead of emitting
975 misleading route or capability metadata.
976
977 Most shipped providers use the Chat Completions request payload mode. Native
978 Messages routes, including `minimax-anthropic`, use `/v1/messages`, and
979 `openai-codex` uses Responses.
980
981 For OpenAI-compatible gateways or self-hosted runtimes whose real window
982 differs from the static table, set `[providers.<name>] context_window = N`.
983 The configured value becomes the route-effective context window for prompts,
984 context-pressure checks, compaction, and output-cap budgeting.
985
986 `max_output` is optional and truthful: it is `null` (and omitted from the
987 capability struct on the wire) when the route publishes no output maximum we
988 can stand behind — the Kimi Code membership `kimi-for-coding` family is the
989 canonical example, since the membership catalog owns their limits. An unknown
990 output ceiling is never backfilled with a placeholder, and it applies **no**
991 compatibility clamp to a turn's requested `max_tokens`; only a concrete
992 route/offering maximum narrows the request. A model the catalogue simply has no
993 row for is a different fact — absence is not permission, so an uncatalogued id
994 keeps a conservative ceiling. The "Max output metadata" column below reads
995 `unknown` wherever no documented maximum exists.
996
997 The exact Kimi Code membership roster contains `k3`, `k3-256k`,
998 `kimi-for-coding`, and `kimi-for-coding-highspeed`. The two K3 ids share the
999 same reasoning and fixed-sampling contract; `k3-256k` stays at 262,144 tokens,
1000 while bare `k3` can use an entitled 1M override.
1001
1002 | Provider/model class | Context window | Max output metadata | Thinking support | Cache telemetry | FIM endpoint |
1003 | --- | --- | --- | --- | --- | --- |
1004 | DeepSeek V4 (`deepseek-v4-pro`, `deepseek-v4-flash`) | 1,000,000 | 384,000 | yes | yes | DeepSeek beta only |
1005 | DeepSeek V4 Flash Vision experimental (`deepseek-v4-flash-vision-exp`) | 1,000,000 inherited from Flash | 384,000 inherited from Flash | yes, inherited | yes, inherited | not claimed; Chat Completions route only |
1006 | DeepSeek compatibility aliases (`deepseek-chat`, `deepseek-reasoner`) | 1,000,000 | 384,000 | yes | yes | DeepSeek beta only |
1007 | NVIDIA NIM V4 registry models | 1,000,000 | 384,000 | yes | yes | not documented in code |
1008 | Volcengine Ark V4 model IDs | 1,000,000 | 384,000 | yes | yes | not documented in code |
1009 | OpenRouter, Novita, Fireworks, SiliconFlow, SGLang, and vLLM V4 model IDs | 1,000,000 | 384,000 | yes | no | not documented in code |
1010 | Xiaomi MiMo `mimo-v2.5-pro`, `mimo-v2.5-pro-ultraspeed`, `mimo-v2.5` | 1,000,000 | 131,072 | yes | no | not documented in code |
1011 | OpenRouter Qwen 3.6 Flash / Plus | 1,000,000 | 65,536 | yes | no | not documented in code |
1012 | OpenRouter Qwen 3.6 35B / 27B | 262,144 | 262,140 | yes | no | not documented in code |
1013 | OpenRouter Qwen 3.6 Max Preview | 262,144 | 65,536 | yes | no | not documented in code |
1014 | OpenAI API `gpt-5.5` | 1,050,000 | 128,000 | yes | no | not documented in code |
1015 | OpenAI API `gpt-5.6`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna` | 1,050,000 | 128,000 | yes | no | not documented in code |
1016 | Anthropic API `claude-opus-5`, `claude-opus-4-8`, `claude-sonnet-5`, `claude-sonnet-4-6`, `claude-fable-5` | 1,000,000 | 128,000 | yes | yes | not documented in code |
1017 | Google Gemini API `gemini-3.7-flash`, `gemini-3.6-flash`, `gemini-3.5-flash`, `gemini-3.5-flash-lite`, `gemini-3.1-pro-preview`, `gemini-2.5-pro`, `gemini-2.5-flash` | 1,048,576 | 65,536 | model-dependent | no | not documented in code |
1018 | Meta Model API `muse-spark-1.2` | 1,000,000 | 32,000 | yes | no | not documented in code |
1019 | OpenAI Codex / ChatGPT route (`openai-codex`) | 400,000 effective | 128,000 | yes | no | route uses Responses payload at `/codex/responses` |
1020 | OpenModel default/custom model IDs | 200,000 fallback unless model metadata or config overrides it | 64,000 fallback | model-dependent | no | route uses Messages payload at `/v1/messages` |
1021 | Wanjie Ark `reasoner` / `r1` model IDs | 128,000 | unknown (no documented maximum) | yes | no | not documented in code |
1022 | Direct Arcee API `trinity-large-thinking` | 262,144 | 262,144 | yes | no | not documented in code |
1023 | Direct Arcee API `trinity-large-preview` | 262,144 | unknown (no documented maximum) | no in doctor capability metadata | no | not documented in code |
1024 | Direct Moonshot `kimi-k3` | 1,048,576 | 1,048,576 documented maximum; 131,072 provider default | yes | no | exact route uses `max_completion_tokens` and omits fixed sampling fields ([K3 quickstart](https://platform.kimi.ai/docs/guide/kimi-k3-quickstart)) |
1025 | Kimi Code membership `k3` | 262,144 safe baseline; 1,048,576 with an explicit entitled-plan override | 131,072 conservative default ceiling; membership maximum is not published | yes | no | exact `https://api.kimi.com/coding/v1` route |
1026 | Kimi Code membership `k3-256k` | 262,144 fixed | 131,072 conservative default ceiling; membership maximum is not published | yes | no | exact `https://api.kimi.com/coding/v1` route |
1027 | Direct Moonshot/Kimi K2.7/K2.6 (`kimi-k2.7-code`, `kimi-k2.7-code-highspeed`, `kimi-k2.6`) | 262,144 | 32,768 | yes | no | provider-reported bundled catalog |
1028 | Kimi Code membership `kimi-for-coding`, `kimi-for-coding-highspeed` | 262,144 | unknown — the membership catalog owns these limits and no client-side ceiling is claimed | yes | no | exact `https://api.kimi.com/coding/v1` route |
1029 | Direct Z.AI `GLM-5.3` (default) | 1,000,000 | 131,072 | yes | no | live on the GLM Coding Plan; limits inherited from `GLM-5.2` until Z.ai publishes distinct 5.3 numbers; no USD price |
1030 | Direct Z.AI `GLM-5.3-Flash` | 1,000,000 | 131,072 | yes | no | natively multimodal; $0.15/$0.50 list (2026-08-26); faster/explore sibling of `GLM-5.3` |
1031 | Direct Z.AI `GLM-5.2` | 1,000,000 | 131,072 | yes | no | not documented in code |
1032 | Direct Z.AI `GLM-5.1` | 202,752 | 131,072 | yes | no | not documented in code |
1033 | Direct Z.AI `GLM-5-Turbo` | 202,752 | 131,072 | yes | no | faster/explore sub-agent sibling |
1034 | Direct MiniMax `MiniMax-M3` | 1,000,000 | 524,288 | yes | no | not documented in code |
1035 | Direct MiniMax M2.x models | 204,800 | unknown until MiniMax output metadata is promoted | yes | no | not documented in code |
1036 | MiniMax Messages route (`MiniMax-M3`, `MiniMax-M2.7`) | model-specific values above | model-specific values above | yes | no | route uses `/anthropic/v1/messages` |
1037 | Generic `openai` and AtlasCloud | 128,000 | unknown (no documented maximum) | no in doctor capability metadata | no | not documented in code |
1038 | Ollama | 8,192 | unknown (no documented maximum) | no | no | not documented in code |
1039 | Hugging Face Inference Providers V4 model IDs | 131,072 | unknown (no documented maximum) | yes | no | not documented in code |
1040 | Other recognized DeepSeek model IDs | 128,000 unless the model name carries an explicit `Nk` hint | unknown (no documented maximum) | no unless V4/reasoner logic matches | DeepSeek/NIM only | DeepSeek beta only |
1041
1042 MiniMax M3 uses input-length and service tiers. Codewhale omits
1043 `service_tier`, so requests use the standard tier and cost estimates select the
1044 correct standard rate from total input usage. Priority rates are listed to keep
1045 the official tier structure visible. Prices are USD per million tokens.
1046
1047 | Model / service tier | Input length | Input | Output | Cache read | Cache write |
1048 | --- | --- | ---: | ---: | ---: | ---: |
1049 | `MiniMax-M3` standard | up to 512,000 input tokens | $0.30 | $1.20 | $0.06 | not published |
1050 | `MiniMax-M3` standard | over 512,000 input tokens | $0.60 | $2.40 | $0.12 | not published |
1051 | `MiniMax-M3` priority | up to 512,000 input tokens | $0.45 | $1.80 | $0.09 | not published |
1052 | `MiniMax-M3` priority | over 512,000 input tokens | $0.90 | $3.60 | $0.18 | not published |
1053 | `MiniMax-M2.7` standard | all supported inputs | $0.30 | $1.20 | $0.06 | $0.375 |
1054
1055 These values come from the [MiniMax pay-as-you-go pricing
1056 guide](https://platform.minimax.io/docs/guides/pricing-paygo). M3 thinking is
1057 adaptive or disabled; the OpenAI-compatible API defaults to adaptive and the
1058 Anthropic-compatible API defaults to disabled. M2.7 thinking cannot be
1059 disabled. Codewhale sends explicit controls when the user selects a reasoning
1060 mode.
1061
1062 Tool-call support is tracked separately by the static `ModelRegistry` and by
1063 the endpoint's ability to accept OpenAI-compatible `tools` payloads. A custom
1064 OpenAI-compatible or local endpoint can still reject tool calls even if
1065 Codewhale can send the schema.
1066
1067 ### Hugging Face Inference Providers Notes
1068
1069 The shipped Hugging Face route targets the OpenAI-compatible Inference Providers
1070 router at `https://router.huggingface.co/v1`. Configure auth with
1071 `HUGGINGFACE_API_KEY` first, or `HF_TOKEN` as a fallback. Configure the endpoint
1072 with `HUGGINGFACE_BASE_URL` first, or `HF_BASE_URL` as a fallback; configure the
1073 model with `HUGGINGFACE_MODEL` first, or `HF_MODEL` as a fallback.
1074
1075 This route does not imply Hub browsing, model-card metadata, dataset access,
1076 Jobs, uploads, or export. Those remain explicit Model Lab work items so
1077 provider auth and artifact movement stay separate.
1078
1079 ### When a Local Model Prints Tool JSON
1080
1081 Codewhale only executes tools when the provider returns Chat Completions
1082 `tool_calls` or streamed `delta.tool_calls`. If a local model prints text such
1083 as `{"name":"File","arguments":{"action":"search_content",...}}` in the
1084 assistant message, that is ordinary model output, not an executable tool
1085 request.
1086
1087 For OpenAI-compatible or local runtimes, check:
1088
1089 - The endpoint accepts the `tools` array in `/v1/chat/completions` requests.
1090 - The selected model or chat template is configured for function/tool calls.
1091 - The server returns `tool_calls` in the response rather than plain JSON text.
1092 - The compatibility layer does not strip tools before forwarding the request.
1093 - If in doubt, test a small `File` `read` or `search_content` action against a
1094 known tool-calling model before debugging Codewhale's tool registry.
1095
1096 Changing `provider`, `base_url`, or `model` can select a route that supports the
1097 OpenAI-compatible payload shape, but Codewhale cannot convert arbitrary JSON
1098 text into a trusted tool call after the model has emitted it as prose.
1099
1100 DeepSeek will retire `deepseek-chat` and `deepseek-reasoner` on 2026-07-24 at
1101 15:59 UTC. Codewhale migrates either name to `deepseek-v4-flash` before a
1102 request reaches DeepSeek's first-party OpenAI or Anthropic endpoint. If no
1103 reasoning tier was configured, `deepseek-chat` also migrates to `off` and
1104 `deepseek-reasoner` to `high`, preserving their former non-thinking / thinking
1105 intent; an explicit `reasoning_effort` remains authoritative. The mapping is
1106 deliberately not global: Wanjie Ark, aggregators, self-hosted runtimes, and
1107 custom endpoints continue to own their model ids.
1108
1109 ## Reasoning Effort
1110
1111 `/reasoning <effort>` (and the `reasoning_effort` config key) is translated to
1112 each provider's wire dialect by the client before the request is sent. `off`
1113 disables thinking where the route supports it. Both exact K3 routes map `off`
1114 to their lowest supported tier, `low`, and the model is never switched to
1115 satisfy `off` — but they do so for different reasons:
1116
1117 - **Kimi Code membership K3** (exact `https://api.kimi.com/coding/v1` with
1118 `model = "k3"` or `model = "k3-256k"`) — the membership roster declares K3 always-thinking, so `off`
1119 cannot be honored without changing what the model is. The clamp preserves the
1120 fixed K3 identity.
1121 - **Direct Moonshot K3** (exact `https://api.moonshot.ai/v1` with
1122 `model = "kimi-k3"`) — this clamp is *defensive*, not a documented contract.
1123 The direct platform publishes no `off` state for K3, and Codewhale will not
1124 assert a fixed-thinking guarantee it cannot verify for a given key's
1125 entitlement, so the requested `off` is normalized to the lowest tier with the
1126 live entitlement left unknown.
1127
1128 Normal dispatched
1129 `auto` uses Codewhale's auto-reasoning selector and sends a concrete tier;
1130 only an omitted reasoning setting leaves the provider default in control.
1131 Providers marked "omitted" receive no reasoning fields at all for that tier.
1132
1133 | Provider | `off` | `low`/`medium`/`high` | `max`/`xhigh` |
1134 | --- | --- | --- | --- |
1135 | `deepseek`, `deepseek-cn`, `siliconflow`, `siliconflow-CN`, `sglang`, `volcengine`, `atlascloud` | `thinking: {type: disabled}` | `reasoning_effort: "high"` + `thinking: {type: enabled}` | `reasoning_effort: "max"` + `thinking: {type: enabled}` |
1136 | `openrouter`, `novita`, other `together` models | `thinking: {type: disabled}` | `reasoning_effort` pass-through + `thinking: {type: enabled}` | `reasoning_effort: "xhigh"` + `thinking: {type: enabled}` |
1137 | `together` + `thinkingmachines/inkling` | `reasoning_effort: "none"` | exact `minimal`/`low`/`medium`/`high` `reasoning_effort` | `reasoning_effort: "max"` |
1138 | Direct Moonshot `kimi-k3` at exact `https://api.moonshot.ai/v1` | top-level `reasoning_effort: "low"` (effective normalization) | top-level `reasoning_effort: "low"` / `"high"` (`medium` becomes `high`) | top-level `reasoning_effort: "max"` |
1139 | Kimi Code membership `k3`, `k3-256k` at exact `https://api.kimi.com/coding/v1` | `thinking: {type: enabled, effort: "low"}` (effective normalization) | `thinking: {type: enabled, effort: "low" | "high"}` | `thinking: {type: enabled, effort: "max"}` |
1140 | Other `moonshot` routes | `thinking: {type: disabled}` | `thinking: {type: enabled}` | `thinking: {type: enabled}` |
1141 | `ollama` | `think: false` | `think: true` | `think: true` |
1142 | `ollama-cloud` | `reasoning_effort: "none"` | exact `low`/`medium`/`high` `reasoning_effort` | `reasoning_effort: "max"` |
1143 | `xiaomi-mimo` | `thinking: {type: disabled}` | `thinking: {type: enabled}` | `thinking: {type: enabled}` |
1144 | First-party `minimax` `MiniMax-M3` | `reasoning_split: true` + `thinking: {type: disabled}` | `reasoning_split: true` + `thinking: {type: adaptive}`; effective tier granularity unavailable | `reasoning_split: true` + `thinking: {type: adaptive}`; effective tier granularity unavailable |
1145 | First-party Z.ai `GLM-5.2` | `thinking: {type: disabled}`; no `reasoning_effort` | enabled thinking; only effective `high` adds `reasoning_effort: "high"` | enabled thinking + `reasoning_effort: "max"` |
1146 | First-party Z.ai `GLM-5.3` | `thinking: {type: disabled}`; no `reasoning_effort` | enabled thinking; only effective `high` adds `reasoning_effort: "high"` | enabled thinking + `reasoning_effort: "max"` |
1147 | First-party Z.ai `GLM-5.3-Flash` | `thinking: {type: disabled}`; no `reasoning_effort` | enabled thinking; only effective `high` adds `reasoning_effort: "high"` | enabled thinking + `reasoning_effort: "max"` |
1148 | First-party Z.ai `GLM-5-Turbo` | `thinking: {type: disabled}` | enabled thinking; effort granularity unavailable | enabled thinking; effort granularity unavailable |
1149 | Compatible gateways configured as `zai` | omitted; effective unavailable | omitted; effective unavailable | omitted; effective unavailable |
1150 | `nvidia-nim` | `chat_template_kwargs.thinking: false` | `chat_template_kwargs`: `thinking: true` + `reasoning_effort: "high"` | `chat_template_kwargs`: `thinking: true` + `reasoning_effort: "max"` |
1151 | `vllm` | `chat_template_kwargs.enable_thinking: false` | `chat_template_kwargs.enable_thinking: true` + `reasoning_effort` low/medium/high | `chat_template_kwargs.enable_thinking: true` + `reasoning_effort: "high"` (vLLM has no max tier) |
1152 | `arcee`, `huggingface` | omitted | `reasoning_effort` pass-through | `reasoning_effort: "high"` |
1153 | `fireworks` | omitted | `reasoning_effort: "high"` | `reasoning_effort: "max"` |
1154 | `openai`, `wanjie-ark`, `telecomjs` | omitted | omitted | omitted |
1155 | `openmodel` | Anthropic Messages adapter handles thinking/output configuration | Anthropic Messages adapter handles thinking/output configuration | Anthropic Messages adapter handles thinking/output configuration |
1156 | `openai-codex` | Responses API `reasoning` field (handled by the Responses bridge) | Responses API `reasoning` field | Responses API `reasoning` field |
1157
1158 AtlasCloud serves DeepSeek models, so it speaks the DeepSeek reasoning dialect,
1159 including the `max` tier (#3024).
1160
1161 On the exact MiniMax OpenAI-compatible Chat endpoints, `MiniMax-M3` uses
1162 `max_completion_tokens`. Other MiniMax models and compatible gateways retain
1163 `max_tokens`; the MiniMax Anthropic endpoints use the separate Messages
1164 adapter.
1165
1166 ## Drift Check
1167
1168 Run this before changing provider IDs, provider TOML tables, static model
1169 registry rows, or provider default strings:
1170
1171 ```bash
1172 python3 scripts/check-provider-registry.py
1173 ```
1174
1175 The check fails when:
1176
1177 - `docs/PROVIDERS.md` omits a canonical `ProviderKind::as_str()` ID.
1178 - `crates/tui/src/config.rs` `ApiProvider::as_str()` diverges from
1179 `ProviderKind::as_str()` except for the explicit `deepseek-cn` legacy alias.
1180 - The shipped-provider table omits or adds a `[providers.*]` TOML table.
1181 - The static model registry table drifts from providers used by
1182 `crates/agent/src/lib.rs`.
1183 - A provider default model or base URL constant in `crates/tui/src/config.rs`
1184 is no longer mentioned here.
1185
1186 ## Planned, Not Shipped Yet
1187
1188 These items belong to the v0.8.48+ provider-abstraction milestone or related
1189 provider docs work, but they are not native shipped behavior in this checkout:
1190
1191 - A unified `Provider` trait in `codewhale-agent` that owns env precedence,
1192 secret resolution, base URL normalization, auth-header construction, and
1193 provider metadata. Those responsibilities are still split across
1194 `crates/config`, `crates/secrets`, and `crates/tui/src/client.rs`.
1195 - Hugging Face model passport metadata in the picker, including license, base
1196 model, context length, chat template, tool-call support, reasoning support,
1197 and gated/private status.
1198
1198 lines MARKDOWN