mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-08 08:04:25 -10:00
Merge main into feat/FEAT-031 to resolve the generated agent-docs conflict
main moved after this PR was opened; the only conflict was the generated web/data/agent-docs.generated.json. It was regenerated on the merged tree with node web/scripts/derive-facts.mjs; node web/scripts/check-facts.mjs prints OK on the result. No source file was hand-edited. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NBKbhx19BRbZtvWK8rVKjz
This commit is contained in:
commit
fc5ac7d904
61 files changed
+2873
-1031
No files matched your search
@@ -7,6 +7,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- The model catalog now carries current models from Anthropic, Google and
|
||||
Meta. Anthropic: `claude-opus-5-5`, `claude-sonnet-5-5`, `claude-haiku-5-5`
|
||||
and `claude-fable-5-1`; the Auto router's cheap tier and the Scout companion
|
||||
stay on `claude-haiku-4-5`. The default stays `claude-sonnet-4-6`, because
|
||||
Codewhale does not yet apply the 5.5 models' request rules, and no default
|
||||
uses `claude-sonnet-4-5`, which retires on 2026-11-30. OpenAI's GPT-6
|
||||
family (`gpt-6-sol`, `gpt-6.1-sol`, `gpt-6-luna` and `gpt-6-astra`) is left
|
||||
out of the direct route because OpenAI does not support normal tool calling
|
||||
for them over Chat Completions. Google: `gemini-4-argon` and
|
||||
`gemini-3.8-flash`. Z.ai: `GLM-5.3-FlashX` is not offered because the
|
||||
Coding Plan endpoint the zai route defaults to does not serve it. Meta:
|
||||
`muse-spark-1.3`, `muse-spark-1.3-contributor` and the `muse-wonder-1.0`
|
||||
preview join the route, which stays on its previous `muse-spark-1.2`
|
||||
default.
|
||||
Several ids are retired. Xiaomi MiMo now defaults to `mimo-v2.6-pro`, and
|
||||
configs naming `mimo-v2.5-pro` or `mimo-v2.5` send `mimo-v2.6-pro` and
|
||||
`mimo-v2.6-flash`, because Xiaomi rejects the old names from 2026-10-21.
|
||||
`gemini-3.7-flash` and `gemini-3.5-flash`, which Google already serves as
|
||||
`gemini-3.8-flash` and `gemini-3.6-flash`, are now selector aliases of those
|
||||
models. `qwen3.8-max-preview` is gone from the Model Studio rosters. MiniMax
|
||||
M2.7 and M2.5 (including highspeed) leave the fallback picker before
|
||||
MiniMax closes them to new users on 2026-10-19, and keep working for
|
||||
existing configs until they retire on 2026-11-18.
|
||||
- Direct DeepSeek routes now send `deepseek-flash` for `deepseek-chat`,
|
||||
`deepseek-reasoner`, the `flash`, `deepseek-v4flash`, `flash-vision` and
|
||||
`deepseek-v4flashvisionexp` shorthands, and the Auto router's fast tier.
|
||||
`codewhale model set` and `/provider` now write `deepseek-flash` for those
|
||||
shorthands too, matching what `model = "flash"` and `/model flash` resolve
|
||||
to.
|
||||
DeepSeek has retired the V4 Flash and V4 Flash vision models. It still
|
||||
accepts `deepseek-v4-flash` and `deepseek-v4-flash-vision-exp`, but serves
|
||||
them with V4.1 Flash, bills them at the Flash price, and calls that routing
|
||||
temporary. Turns on either name from 2026-09-10 04:00 UTC are now priced at
|
||||
the Flash rates ($0.003 cache hit, $0.15 cache miss, $0.60 output per
|
||||
million tokens off-peak, doubled at peak) instead of the old V4 Flash rates,
|
||||
which overstated a cache hit by about 2.3 times. The vision name was not
|
||||
priced at all before. Earlier turns keep the rates they were billed at,
|
||||
including turns recorded under a shorthand. On NVIDIA NIM, OpenRouter,
|
||||
Novita, Fireworks, SiliconFlow, SGLang, vLLM, DeepInfra and Together,
|
||||
`deepseek-flash` selects that host's V4 Flash model, so the `flash`
|
||||
shorthand keeps working there.
|
||||
- When a `tool_search` activation pushes an earlier deferred tool out of the
|
||||
bounded conversation toolbox (8 tools, 16 KiB of schemas), the search
|
||||
result now names it under `evicted_tool_references`. Before, the tool
|
||||
silently disappeared from the next request, and a model could go on
|
||||
calling it. Thanks @asto18089 for the cost and correctness analysis
|
||||
(Refs #6969).
|
||||
- An ACP client that asks how to turn on Full Access is now told the
|
||||
routes that work: start the server with `codewhale --yolo serve --acp`,
|
||||
or set `yolo = true` in config.toml. The hint used to recommend
|
||||
`--approval-policy full-access` or `approval_policy = "full-access"` in
|
||||
config.toml. Both are refused when Codewhale starts, because config.toml's
|
||||
`approval_policy` only accepts on-request, untrusted, never, auto and
|
||||
suggest. Thanks @harryvizcaino-oss for the Paseo report (Refs #6992).
|
||||
- On Linux, a credential directory the sandbox hides no longer breaks every
|
||||
sandboxed command when it is reached through a symlink, such as `~/.kube`
|
||||
linked into a synced dotfiles folder or a `~/.config` that links
|
||||
|
||||
Generated
+21
-21
@@ -161,7 +161,7 @@ dependencies = [
|
||||
"objc2-foundation",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"windows-sys 0.60.2",
|
||||
"windows-sys 0.52.0",
|
||||
"wl-clipboard-rs",
|
||||
"x11rb",
|
||||
]
|
||||
@@ -365,9 +365,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-rs"
|
||||
version = "1.18.1"
|
||||
version = "1.18.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e"
|
||||
checksum = "faac5829c2b74c28f830747e7818ccfb684261b5f48a1118b1e2a13d36dfab13"
|
||||
dependencies = [
|
||||
"aws-lc-sys",
|
||||
"untrusted 0.7.1",
|
||||
@@ -376,9 +376,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-sys"
|
||||
version = "0.45.0"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27"
|
||||
checksum = "f1622d8446a2d4b2ce0c7eefc73dd43a99779028d5ee5c2dd8073a658ba8a2bc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cmake",
|
||||
@@ -1442,7 +1442,7 @@ version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2057,7 +2057,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2148,7 +2148,7 @@ checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"rustix",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3751,9 +3751,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.4"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
|
||||
checksum = "08849bbd4767dfae9457696856ae1c84fe4e0281bbe4a7abff2d0e06fb7981f8"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
@@ -3894,7 +3894,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4755,9 +4755,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rmcp"
|
||||
version = "3.5.0"
|
||||
version = "3.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fae7019994ae0fe4ada40b732f798f3ff26f0f04facb1477f1bf37eb4f18a2d3"
|
||||
checksum = "ab5023804cbe0304cbe06197ac16e645a0a0d0ffa2953bf735c15c2fa0213350"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
@@ -4937,7 +4937,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4993,7 +4993,7 @@ dependencies = [
|
||||
"security-framework 3.7.0",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5750,7 +5750,7 @@ dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6054,9 +6054,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.19"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52"
|
||||
checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
@@ -6484,9 +6484,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.27.0"
|
||||
version = "1.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97277d36b9c3ace13e58fa6e753f8b0bbbf302a18dd193240d70f9e29681059a"
|
||||
checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606"
|
||||
dependencies = [
|
||||
"atomic",
|
||||
"getrandom 0.4.3",
|
||||
@@ -6884,7 +6884,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+13
-14
@@ -690,22 +690,21 @@ mod tests {
|
||||
assert!(listed.iter().any(|model| {
|
||||
model.provider == ProviderKind::Deepseek
|
||||
&& model.id == "deepseek-v4-flash-vision-exp"
|
||||
&& model.aliases
|
||||
== [
|
||||
"flash-vision".to_string(),
|
||||
"deepseek-v4flashvisionexp".to_string(),
|
||||
]
|
||||
&& model.aliases.is_empty()
|
||||
}));
|
||||
|
||||
for selector in [
|
||||
"deepseek-v4-flash-vision-exp",
|
||||
"flash-vision",
|
||||
"deepseek-v4flashvisionexp",
|
||||
for (selector, expected) in [
|
||||
(
|
||||
"deepseek-v4-flash-vision-exp",
|
||||
"deepseek-v4-flash-vision-exp",
|
||||
),
|
||||
("flash-vision", "deepseek-flash"),
|
||||
("deepseek-v4flashvisionexp", "deepseek-flash"),
|
||||
] {
|
||||
let resolved = registry.resolve_ok(Some(selector), Some(ProviderKind::Deepseek));
|
||||
assert_eq!(
|
||||
resolved.resolved.id, "deepseek-v4-flash-vision-exp",
|
||||
"{selector} must resolve to the experimental vision model"
|
||||
resolved.resolved.id, expected,
|
||||
"{selector} must resolve to {expected}"
|
||||
);
|
||||
assert_eq!(resolved.resolved.provider, ProviderKind::Deepseek);
|
||||
assert!(!resolved.used_fallback, "{selector} must not fall back");
|
||||
@@ -824,7 +823,7 @@ mod tests {
|
||||
let resolved = registry.resolve_ok(None, Some(ProviderKind::XiaomiMimo));
|
||||
|
||||
assert_eq!(resolved.resolved.provider, ProviderKind::XiaomiMimo);
|
||||
assert_eq!(resolved.resolved.id, "mimo-v2.5-pro");
|
||||
assert_eq!(resolved.resolved.id, "mimo-v2.6-pro");
|
||||
assert!(resolved.resolved.supports_reasoning);
|
||||
}
|
||||
|
||||
@@ -939,7 +938,7 @@ mod tests {
|
||||
|
||||
let resolved = registry.resolve_ok(Some("omni"), Some(ProviderKind::XiaomiMimo));
|
||||
assert_eq!(resolved.resolved.provider, ProviderKind::XiaomiMimo);
|
||||
assert_eq!(resolved.resolved.id, "mimo-v2.5");
|
||||
assert_eq!(resolved.resolved.id, "mimo-v2.6-flash");
|
||||
assert!(resolved.resolved.supports_tools);
|
||||
}
|
||||
|
||||
@@ -1565,7 +1564,7 @@ mod tests {
|
||||
let resolved = registry.resolve_ok(Some("deepseek-reasoner"), Some(ProviderKind::Deepseek));
|
||||
|
||||
assert_eq!(resolved.resolved.provider, ProviderKind::Deepseek);
|
||||
assert_eq!(resolved.resolved.id, "deepseek-v4-flash");
|
||||
assert_eq!(resolved.resolved.id, "deepseek-flash");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1270,7 +1270,7 @@ api_key = {provider_api_key:?}
|
||||
let endpoint = resolve_endpoint(&config, ®istry, Some(alias))
|
||||
.expect("official DeepSeek route");
|
||||
assert_eq!(endpoint.provider, ProviderKind::Deepseek, "{base_url}");
|
||||
assert_eq!(endpoint.model, "deepseek-v4-flash", "{base_url} {alias}");
|
||||
assert_eq!(endpoint.model, "deepseek-flash", "{base_url} {alias}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-10
@@ -5729,13 +5729,12 @@ fn provider_source_label(source: ProviderSource) -> String {
|
||||
}
|
||||
|
||||
fn canonical_model_for_set(model: &str) -> &str {
|
||||
match model.to_ascii_lowercase().as_str() {
|
||||
"pro" | "deepseek-v4pro" => "deepseek-v4-pro",
|
||||
"flash" | "deepseek-v4flash" => "deepseek-v4-flash",
|
||||
"flash-vision" | "deepseek-v4flashvisionexp" => "deepseek-v4-flash-vision-exp",
|
||||
"auto" => "auto",
|
||||
_ => model,
|
||||
let lower = model.to_ascii_lowercase();
|
||||
if lower == "auto" {
|
||||
return "auto";
|
||||
}
|
||||
codewhale_config::catalog::reviewed::compatibility_alias("canonical_model_name", &lower)
|
||||
.unwrap_or(model)
|
||||
}
|
||||
|
||||
/// The provider (and its endpoint) whose model `model set` writes.
|
||||
@@ -7822,10 +7821,7 @@ verbosity = "concise"
|
||||
#[test]
|
||||
fn model_set_canonicalizes_deepseek_vision_aliases() {
|
||||
for alias in ["flash-vision", "deepseek-v4flashvisionexp"] {
|
||||
assert_eq!(
|
||||
canonical_model_for_set(alias),
|
||||
"deepseek-v4-flash-vision-exp"
|
||||
);
|
||||
assert_eq!(canonical_model_for_set(alias), "deepseek-flash");
|
||||
}
|
||||
assert_eq!(
|
||||
canonical_model_for_set("deepseek-v4-flash-vision-exp"),
|
||||
|
||||
@@ -372,6 +372,58 @@
|
||||
"source": "preserved reviewed bundled model facts; see source_receipts",
|
||||
"family": "Anthropic"
|
||||
},
|
||||
"claude-fable-5-1": {
|
||||
"context_window": 1000000,
|
||||
"max_output": 128000,
|
||||
"modalities": [
|
||||
"text"
|
||||
],
|
||||
"supported_parameters": [
|
||||
"reasoning"
|
||||
],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "Anthropic"
|
||||
},
|
||||
"claude-opus-5-5": {
|
||||
"context_window": 1000000,
|
||||
"max_output": 128000,
|
||||
"modalities": [
|
||||
"text"
|
||||
],
|
||||
"supported_parameters": [
|
||||
"reasoning"
|
||||
],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "Anthropic"
|
||||
},
|
||||
"claude-sonnet-5-5": {
|
||||
"context_window": 1000000,
|
||||
"max_output": 128000,
|
||||
"modalities": [
|
||||
"text"
|
||||
],
|
||||
"supported_parameters": [
|
||||
"reasoning"
|
||||
],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "Anthropic"
|
||||
},
|
||||
"claude-haiku-5-5": {
|
||||
"context_window": 1000000,
|
||||
"max_output": 128000,
|
||||
"modalities": [
|
||||
"text"
|
||||
],
|
||||
"supported_parameters": [
|
||||
"reasoning"
|
||||
],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "Anthropic"
|
||||
},
|
||||
"claude-haiku-4-5": {
|
||||
"context_window": 200000,
|
||||
"max_output": 64000,
|
||||
@@ -635,6 +687,48 @@
|
||||
"source": "preserved reviewed bundled model facts; see source_receipts",
|
||||
"family": "OpenAi"
|
||||
},
|
||||
"gpt-6-sol": {
|
||||
"context_window": 1050000,
|
||||
"max_output": 128000,
|
||||
"modalities": [
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"supported_parameters": [
|
||||
"reasoning"
|
||||
],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "OpenAi"
|
||||
},
|
||||
"gpt-6.1-sol": {
|
||||
"context_window": 1050000,
|
||||
"max_output": 128000,
|
||||
"modalities": [
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"supported_parameters": [
|
||||
"reasoning"
|
||||
],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "OpenAi"
|
||||
},
|
||||
"gpt-6-luna": {
|
||||
"context_window": 1050000,
|
||||
"max_output": 128000,
|
||||
"modalities": [
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"supported_parameters": [
|
||||
"reasoning"
|
||||
],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "OpenAi"
|
||||
},
|
||||
"kimi-k2.7-code": {
|
||||
"context_window": 262144,
|
||||
"max_output": 32768,
|
||||
@@ -699,6 +793,32 @@
|
||||
"source": "preserved reviewed bundled model facts; see source_receipts",
|
||||
"family": "XiaomiMimo"
|
||||
},
|
||||
"mimo-v2.6-pro": {
|
||||
"context_window": 1048576,
|
||||
"max_output": 131072,
|
||||
"modalities": [
|
||||
"text",
|
||||
"image",
|
||||
"audio"
|
||||
],
|
||||
"supported_parameters": [],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "XiaomiMimo"
|
||||
},
|
||||
"mimo-v2.6-flash": {
|
||||
"context_window": 1048576,
|
||||
"max_output": 131072,
|
||||
"modalities": [
|
||||
"text",
|
||||
"image",
|
||||
"audio"
|
||||
],
|
||||
"supported_parameters": [],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "XiaomiMimo"
|
||||
},
|
||||
"minimax-m2.7": {
|
||||
"context_window": 204800,
|
||||
"max_output": 131072,
|
||||
@@ -788,6 +908,45 @@
|
||||
"source": "preserved reviewed bundled model facts; see source_receipts",
|
||||
"family": "Meta"
|
||||
},
|
||||
"muse-spark-1.3": {
|
||||
"context_window": 1048576,
|
||||
"modalities": [
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"supported_parameters": [
|
||||
"reasoning"
|
||||
],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "Meta"
|
||||
},
|
||||
"muse-spark-1.3-contributor": {
|
||||
"context_window": 1048576,
|
||||
"modalities": [
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"supported_parameters": [
|
||||
"reasoning"
|
||||
],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "Meta"
|
||||
},
|
||||
"muse-wonder-1.0": {
|
||||
"context_window": 1048576,
|
||||
"modalities": [
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"supported_parameters": [
|
||||
"reasoning"
|
||||
],
|
||||
"reasoning": true,
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"family": "Meta"
|
||||
},
|
||||
"qwen/qwen3.6-flash": {
|
||||
"context_window": 1000000,
|
||||
"max_output": 65536,
|
||||
@@ -1402,6 +1561,12 @@
|
||||
"max_output": 65536,
|
||||
"family": "Google"
|
||||
},
|
||||
"gemini-3.8-flash": {
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"context_window": 1048576,
|
||||
"max_output": 65536,
|
||||
"family": "Google"
|
||||
},
|
||||
"gemini-3.6-flash": {
|
||||
"source": "preserved exact cited model lookup; see source_receipts",
|
||||
"context_window": 1048576,
|
||||
@@ -1426,6 +1591,11 @@
|
||||
"max_output": 65536,
|
||||
"family": "Google"
|
||||
},
|
||||
"gemini-4-argon": {
|
||||
"source": "official vendor model docs, verified 2026-10-17; see source_receipts",
|
||||
"context_window": 1048576,
|
||||
"family": "Google"
|
||||
},
|
||||
"gemini-3-pro-preview": {
|
||||
"source": "preserved exact cited model lookup; see source_receipts",
|
||||
"context_window": 1048576,
|
||||
@@ -1617,6 +1787,9 @@
|
||||
"deepseek-ai/deepseek-v4pro": "deepseek-v4-pro",
|
||||
"deepseek/deepseek-v4-pro": "deepseek-v4-pro",
|
||||
"deepseek/deepseek-v4pro": "deepseek-v4-pro",
|
||||
"deepseek-flash": "deepseek-flash",
|
||||
"deepseek-ai/deepseek-flash": "deepseek-flash",
|
||||
"deepseek/deepseek-flash": "deepseek-flash",
|
||||
"deepseek-v4-flash": "deepseek-v4-flash",
|
||||
"deepseek-v4flash": "deepseek-v4-flash",
|
||||
"deepseek-ai/deepseek-v4-flash": "deepseek-v4-flash",
|
||||
@@ -1631,6 +1804,9 @@
|
||||
"gpt-5.6-sol": "gpt_56",
|
||||
"gpt-5.6-terra": "gpt_56",
|
||||
"gpt-5.6-luna": "gpt_56",
|
||||
"gpt-6-sol": "gpt_56",
|
||||
"gpt-6.1-sol": "gpt_56",
|
||||
"gpt-6-luna": "gpt_56",
|
||||
"gpt-5-codex": "codex",
|
||||
"gpt-5.1-codex": "codex",
|
||||
"gpt-5.1-codex-mini": "codex",
|
||||
@@ -1657,24 +1833,30 @@
|
||||
"provider": "deepseek"
|
||||
},
|
||||
{
|
||||
"id": "deepseek-v4-flash",
|
||||
"id": "deepseek-flash",
|
||||
"aliases": [
|
||||
"deepseek-chat",
|
||||
"deepseek-reasoner",
|
||||
"deepseek-r1",
|
||||
"deepseek-v3",
|
||||
"deepseek-v3.2"
|
||||
"deepseek-v3.2",
|
||||
"flash-vision",
|
||||
"deepseek-v4flashvisionexp"
|
||||
],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "deepseek"
|
||||
},
|
||||
{
|
||||
"id": "deepseek-v4-flash",
|
||||
"aliases": [],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "deepseek"
|
||||
},
|
||||
{
|
||||
"id": "deepseek-v4-flash-vision-exp",
|
||||
"aliases": [
|
||||
"flash-vision",
|
||||
"deepseek-v4flashvisionexp"
|
||||
],
|
||||
"aliases": [],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "deepseek"
|
||||
@@ -2182,10 +2364,13 @@
|
||||
"provider": "openrouter"
|
||||
},
|
||||
{
|
||||
"id": "mimo-v2.5-pro",
|
||||
"id": "mimo-v2.6-pro",
|
||||
"aliases": [
|
||||
"mimo",
|
||||
"pro",
|
||||
"xiaomi-mimo-v2.6-pro",
|
||||
"xiaomi-mimo-v2-6-pro",
|
||||
"mimo-v2.5-pro",
|
||||
"xiaomi-mimo-v2.5-pro",
|
||||
"xiaomi-mimo-v2-5-pro"
|
||||
],
|
||||
@@ -2194,14 +2379,17 @@
|
||||
"provider": "xiaomi-mimo"
|
||||
},
|
||||
{
|
||||
"id": "mimo-v2.5",
|
||||
"id": "mimo-v2.6-flash",
|
||||
"aliases": [
|
||||
"omni",
|
||||
"mimo-omni",
|
||||
"v2.5-omni",
|
||||
"mimo-v2.5-omni",
|
||||
"mimo-v2.5",
|
||||
"xiaomi-mimo-v2.5",
|
||||
"xiaomi-mimo-v2.5-omni"
|
||||
"xiaomi-mimo-v2.5-omni",
|
||||
"xiaomi-mimo-v2.6-flash",
|
||||
"xiaomi-mimo-v2-6-flash"
|
||||
],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
@@ -2673,6 +2861,46 @@
|
||||
"supports_reasoning": true,
|
||||
"provider": "anthropic"
|
||||
},
|
||||
{
|
||||
"id": "claude-opus-5-5",
|
||||
"aliases": [
|
||||
"opus-5-5",
|
||||
"opus-5.5"
|
||||
],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "anthropic"
|
||||
},
|
||||
{
|
||||
"id": "claude-sonnet-5-5",
|
||||
"aliases": [
|
||||
"sonnet-5-5",
|
||||
"sonnet-5.5"
|
||||
],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "anthropic"
|
||||
},
|
||||
{
|
||||
"id": "claude-haiku-5-5",
|
||||
"aliases": [
|
||||
"haiku-5-5",
|
||||
"haiku-5.5"
|
||||
],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "anthropic"
|
||||
},
|
||||
{
|
||||
"id": "claude-fable-5-1",
|
||||
"aliases": [
|
||||
"fable-5-1",
|
||||
"fable-5.1"
|
||||
],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "anthropic"
|
||||
},
|
||||
{
|
||||
"id": "deepseek-v4-flash",
|
||||
"aliases": [
|
||||
@@ -2903,6 +3131,31 @@
|
||||
"supports_reasoning": true,
|
||||
"provider": "longcat"
|
||||
},
|
||||
{
|
||||
"id": "muse-spark-1.3",
|
||||
"aliases": [],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "meta"
|
||||
},
|
||||
{
|
||||
"id": "muse-spark-1.3-contributor",
|
||||
"aliases": [
|
||||
"muse-spark-contributor"
|
||||
],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "meta"
|
||||
},
|
||||
{
|
||||
"id": "muse-wonder-1.0",
|
||||
"aliases": [
|
||||
"muse-wonder"
|
||||
],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "meta"
|
||||
},
|
||||
{
|
||||
"id": "muse-spark-1.2",
|
||||
"aliases": [
|
||||
@@ -2915,9 +3168,7 @@
|
||||
},
|
||||
{
|
||||
"id": "muse-spark-1.2-contributor",
|
||||
"aliases": [
|
||||
"muse-spark-contributor"
|
||||
],
|
||||
"aliases": [],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "meta"
|
||||
@@ -2992,6 +3243,13 @@
|
||||
"supports_reasoning": false,
|
||||
"provider": "xai"
|
||||
},
|
||||
{
|
||||
"id": "gemini-4-argon",
|
||||
"aliases": [],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "google"
|
||||
},
|
||||
{
|
||||
"id": "gemini-3.1-pro-preview",
|
||||
"aliases": [
|
||||
@@ -3011,22 +3269,19 @@
|
||||
"provider": "google"
|
||||
},
|
||||
{
|
||||
"id": "gemini-3.7-flash",
|
||||
"aliases": [],
|
||||
"id": "gemini-3.8-flash",
|
||||
"aliases": [
|
||||
"gemini-3.7-flash"
|
||||
],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "google"
|
||||
},
|
||||
{
|
||||
"id": "gemini-3.6-flash",
|
||||
"aliases": [],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "google"
|
||||
},
|
||||
{
|
||||
"id": "gemini-3.5-flash",
|
||||
"aliases": [],
|
||||
"aliases": [
|
||||
"gemini-3.5-flash"
|
||||
],
|
||||
"supports_tools": true,
|
||||
"supports_reasoning": true,
|
||||
"provider": "google"
|
||||
@@ -3374,6 +3629,118 @@
|
||||
}
|
||||
],
|
||||
"public_models": [
|
||||
{
|
||||
"id": "claude-opus-5-5",
|
||||
"label": "Anthropic",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"claude-opus-5-5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "claude-sonnet-5-5",
|
||||
"label": "Anthropic",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"claude-sonnet-5-5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "claude-haiku-5-5",
|
||||
"label": "Anthropic",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"claude-haiku-5-5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "claude-fable-5-1",
|
||||
"label": "Anthropic",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"claude-fable-5-1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "gpt-6-sol",
|
||||
"label": "OpenAI",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"gpt-6-sol"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "gpt-6.1-sol",
|
||||
"label": "OpenAI",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"gpt-6.1-sol"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "gpt-6-luna",
|
||||
"label": "OpenAI",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"gpt-6-luna"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "gemini-4-argon",
|
||||
"label": "Google",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"gemini-4-argon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "gemini-3.8-flash",
|
||||
"label": "Google",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"gemini-3.8-flash"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "muse-spark-1.3",
|
||||
"label": "Meta",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"muse-spark-1.3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "muse-spark-1.3-contributor",
|
||||
"label": "Meta",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"muse-spark-1.3-contributor"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "muse-wonder-1.0",
|
||||
"label": "Meta",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"muse-wonder-1.0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "mimo-v2.6-pro",
|
||||
"label": "Xiaomi MiMo",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"mimo-v2.6-pro"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "mimo-v2.6-flash",
|
||||
"label": "Xiaomi MiMo",
|
||||
"added_at": "2026-10-17",
|
||||
"aliases": [
|
||||
"mimo-v2.6-flash"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "grok-4.7",
|
||||
"label": "xAI",
|
||||
@@ -3594,12 +3961,6 @@
|
||||
"added_at": "2026-08-02",
|
||||
"aliases": []
|
||||
},
|
||||
{
|
||||
"id": "qwen3.8-max-preview",
|
||||
"label": "Qwen",
|
||||
"added_at": "2026-08-02",
|
||||
"aliases": []
|
||||
},
|
||||
{
|
||||
"id": "kimi-for-coding-highspeed",
|
||||
"label": "Moonshot/Kimi",
|
||||
@@ -4020,7 +4381,7 @@
|
||||
"OPENROUTER_XIAOMI_MIMO_V2_5_PRO_MODEL": "xiaomi/mimo-v2.5-pro",
|
||||
"OPENROUTER_XIAOMI_MIMO_V2_5_MODEL": "xiaomi/mimo-v2.5",
|
||||
"XIAOMI_MIMO_V2_5_PRO_ULTRASPEED_MODEL": "mimo-v2.5-pro-ultraspeed",
|
||||
"XIAOMI_MIMO_V2_5_OMNI_MODEL": "mimo-v2.5",
|
||||
"XIAOMI_MIMO_V2_6_FLASH_MODEL": "mimo-v2.6-flash",
|
||||
"XIAOMI_MIMO_ASR_MODEL": "mimo-v2.5-asr",
|
||||
"XIAOMI_MIMO_TTS_MODEL": "mimo-v2.5-tts",
|
||||
"XIAOMI_MIMO_TTS_VOICE_DESIGN_MODEL": "mimo-v2.5-tts-voicedesign",
|
||||
@@ -4068,7 +4429,7 @@
|
||||
"XAI_GROK_COMPOSER_2_5_FAST_MODEL": "grok-composer-2.5-fast",
|
||||
"XAI_GROK_4_20_0309_REASONING_MODEL": "grok-4.20-0309-reasoning",
|
||||
"XAI_GROK_4_20_0309_NON_REASONING_MODEL": "grok-4.20-0309-non-reasoning",
|
||||
"DEEPSEEK_ALIAS_REPLACEMENT": "deepseek-v4-flash"
|
||||
"DEEPSEEK_ALIAS_REPLACEMENT": "deepseek-flash"
|
||||
},
|
||||
"groups": {
|
||||
"RECENT_OPENROUTER_LARGE_MODELS": [
|
||||
@@ -4134,7 +4495,22 @@
|
||||
"https://docs.mistral.ai/studio/conversations/reasoning": "verified 2026-10-02: explicit reasoning support for mistral-medium-latest/mistral-medium-3-5 and mistral-small-latest/mistral-small-2603; no family-prefix inference; verified 2026-10-03: exact magistral-small-latest is explicitly listed as a native reasoning model (deprecated), historical wire capability only; no availability/default inference",
|
||||
"https://docs.mistral.ai/vibe/code/cli/configuration": "verified 2026-10-02: explicit reasoning support for mistral-medium-latest/mistral-medium-3-5 and mistral-small-latest/mistral-small-2603; no family-prefix inference",
|
||||
"https://docs.mistral.ai/models/mistral-medium-3-5-26-04": "verified 2026-10-02: explicit reasoning support for mistral-medium-latest/mistral-medium-3-5 and mistral-small-latest/mistral-small-2603; no family-prefix inference",
|
||||
"https://docs.mistral.ai/models/mistral-small-4-0-26-03": "verified 2026-10-02: explicit reasoning support for mistral-medium-latest/mistral-medium-3-5 and mistral-small-latest/mistral-small-2603; no family-prefix inference"
|
||||
"https://docs.mistral.ai/models/mistral-small-4-0-26-03": "verified 2026-10-02: explicit reasoning support for mistral-medium-latest/mistral-medium-3-5 and mistral-small-latest/mistral-small-2603; no family-prefix inference",
|
||||
"https://platform.claude.com/docs/en/about-claude/models/overview": "verified 2026-10-17: claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5 and claude-fable-5-1 are current with 1M context and 128K output; every older direct-route id is listed as legacy",
|
||||
"https://platform.claude.com/docs/en/about-claude/pricing": "verified 2026-10-17: Fable 5.1 $10 in / $12.50 5m write / $0.25 hit / $50 out; Opus 5.5 $4 / $5 / $0.20 / $20; Sonnet 5.5 $2 / $2.50 / $0.10 / $10; Haiku 5.5 is $0.10 / $0.50 up to 100,000 prompt tokens and $0.50 / $2.50 above, so it carries no flat reference price",
|
||||
"https://platform.claude.com/docs/en/about-claude/model-deprecations": "verified 2026-10-17: claude-sonnet-4-5-20250929 retires 2026-11-30, replacement claude-sonnet-5-5; no Codewhale default uses it",
|
||||
"https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool": "verified 2026-10-17: web search examples run on claude-opus-5-5",
|
||||
"https://developers.openai.com/api/docs/changelog": "verified 2026-10-17: gpt-6-sol and gpt-6-luna 2026-09-22, gpt-6.1-sol 2026-09-29; gpt-6-astra lacks the none effort and its tool calls require the Responses API, so it is not offered on the direct Chat route",
|
||||
"https://developers.openai.com/api/docs/models/gpt-6-sol": "verified 2026-10-17: $2 in / $0.20 cached / $10 out / $2.50 cache write; gpt-6.1-sol $2 / $0.10 / $10 / $2.50 and gpt-6-luna $0.10 / $0.01 / $0.50 per the changelog",
|
||||
"https://developers.openai.com/api/docs/deprecations": "verified 2026-10-17: gpt-5.3-codex and gpt-5.1 move to gpt-6-sol and gpt-5.4-nano to gpt-6-luna, all shutting down 2027-04-01; the catalog has no lifecycle field, so the rows stay until shutdown",
|
||||
"https://ai.google.dev/gemini-api/docs/changelog": "verified 2026-10-17: gemini-4-argon GA 2026-10-13, gemini-3.8-flash GA 2026-09-02; gemini-3.7-flash (auto-routed to gemini-3.8-flash) and gemini-3.5-flash (auto-routed to gemini-3.6-flash) deprecated 2026-10-08 and kept only as selector aliases",
|
||||
"https://ai.google.dev/gemini-api/docs/models": "verified 2026-10-17: gemini-4-argon and gemini-3.8-flash are stable; argon's 1M context is stated but no output ceiling is, so none is recorded",
|
||||
"https://docs.z.ai/guides/vlm/glm-5.3-flash": "verified 2026-10-17: model code glm-5.3-flash, 1M context, 128K output, thinking.type only supports enabled",
|
||||
"https://dev.meta.ai/docs/models.md": "verified 2026-10-17: muse-spark-1.3 is recommended for new work, muse-spark-1.2 is the previous version, muse-spark-1.3-contributor has no max effort, muse-wonder-1.0 is a preview; all 1,048,576 context",
|
||||
"https://dev.meta.ai/docs/pricing-rate-limits": "verified 2026-10-17: Muse Spark 1.3 and 1.2 $1.25 in / $0.15 cached / $4.25 out, contributor $0.10 / $0.002 / $0.20; Muse Wonder 1.0 $4 / $0.20 / $20; no long-context premium",
|
||||
"https://mimo.mi.com/docs/updates/deprecate": "verified 2026-10-17 via its loaded chunk: mimo-v2.5-pro (to mimo-v2.6-pro) and mimo-v2.5 (to mimo-v2.6-flash) are replaced from 2026-10-14 10:00 UTC+8 and return errors from 2026-10-21 10:00 UTC+8",
|
||||
"https://platform.minimax.io/docs/guides/models-intro": "verified 2026-10-17: MiniMax-M2.7, M2.7-highspeed, M2.5 and M2.5-highspeed close to new users 2026-10-19 and retire 2026-11-18; they leave the fallback picker but stay accepted until then",
|
||||
"https://www.alibabacloud.com/en/notice/alibaba_cloud_model_studio_model_upgrade_notice_81a?_p_lc=1": "verified 2026-10-17: qwen3.8-max-preview retired 2026-08-05 and its requests route to qwen3.8-max"
|
||||
},
|
||||
"transports": [
|
||||
{
|
||||
@@ -5022,24 +5398,6 @@
|
||||
"server_side_web_search": "supported"
|
||||
}
|
||||
},
|
||||
{
|
||||
"provider": "modelstudio-token-plan",
|
||||
"id": "qwen3.8-max-preview",
|
||||
"endpoint_key": "chat",
|
||||
"default_for_provider": false,
|
||||
"source": "preserved reviewed exact transport snapshot; see source_receipts",
|
||||
"limits": {
|
||||
"context_tokens": 1000000,
|
||||
"output_tokens": 131072
|
||||
},
|
||||
"capabilities": {
|
||||
"reasoning": "supported",
|
||||
"native_tool_calls": "supported",
|
||||
"structured_output": "supported",
|
||||
"streaming": "supported",
|
||||
"image_input": "supported"
|
||||
}
|
||||
},
|
||||
{
|
||||
"provider": "modelstudio-token-plan",
|
||||
"id": "qwen3.7-plus",
|
||||
@@ -5172,6 +5530,9 @@
|
||||
"o4-mini"
|
||||
],
|
||||
"anthropic": [
|
||||
"claude-opus-5-5",
|
||||
"claude-sonnet-5-5",
|
||||
"claude-fable-5-1",
|
||||
"claude-fable-5",
|
||||
"claude-opus-4-8",
|
||||
"claude-mythos-5",
|
||||
@@ -5186,6 +5547,8 @@
|
||||
"grok-4.5"
|
||||
],
|
||||
"xiaomi-mimo": [
|
||||
"mimo-v2.6-pro",
|
||||
"mimo-v2.6-flash",
|
||||
"mimo-v2.5-pro",
|
||||
"mimo-v2.5"
|
||||
],
|
||||
@@ -5237,6 +5600,27 @@
|
||||
"source": "preserved exact cited reference; not endpoint/account pricing",
|
||||
"cache_write": 12.5
|
||||
},
|
||||
"claude-fable-5-1": {
|
||||
"cache_read": 0.25,
|
||||
"input": 10.0,
|
||||
"output": 50.0,
|
||||
"source": "official vendor pricing page, verified 2026-10-17; not endpoint/account pricing",
|
||||
"cache_write": 12.5
|
||||
},
|
||||
"claude-opus-5-5": {
|
||||
"cache_read": 0.2,
|
||||
"input": 4.0,
|
||||
"output": 20.0,
|
||||
"source": "official vendor pricing page, verified 2026-10-17; not endpoint/account pricing",
|
||||
"cache_write": 5.0
|
||||
},
|
||||
"claude-sonnet-5-5": {
|
||||
"cache_read": 0.1,
|
||||
"input": 2.0,
|
||||
"output": 10.0,
|
||||
"source": "official vendor pricing page, verified 2026-10-17; not endpoint/account pricing",
|
||||
"cache_write": 2.5
|
||||
},
|
||||
"claude-haiku-4-5": {
|
||||
"cache_read": 0.1,
|
||||
"input": 1.0,
|
||||
@@ -5422,6 +5806,27 @@
|
||||
"output": 1.2,
|
||||
"source": "preserved exact cited reference; not endpoint/account pricing"
|
||||
},
|
||||
"gpt-6-sol": {
|
||||
"cache_read": 0.2,
|
||||
"input": 2.0,
|
||||
"output": 10.0,
|
||||
"source": "official vendor pricing page, verified 2026-10-17; not endpoint/account pricing",
|
||||
"cache_write": 2.5
|
||||
},
|
||||
"gpt-6.1-sol": {
|
||||
"cache_read": 0.1,
|
||||
"input": 2.0,
|
||||
"output": 10.0,
|
||||
"source": "official vendor pricing page, verified 2026-10-17; not endpoint/account pricing",
|
||||
"cache_write": 2.5
|
||||
},
|
||||
"gpt-6-luna": {
|
||||
"cache_read": 0.01,
|
||||
"input": 0.1,
|
||||
"output": 0.5,
|
||||
"source": "official vendor pricing page, verified 2026-10-17; not endpoint/account pricing",
|
||||
"cache_write": 0.125
|
||||
},
|
||||
"meta/muse-spark-1.1": {
|
||||
"cache_read": 0.15,
|
||||
"input": 1.25,
|
||||
@@ -5458,6 +5863,24 @@
|
||||
"output": 0.2,
|
||||
"source": "preserved exact cited reference; not endpoint/account pricing"
|
||||
},
|
||||
"muse-spark-1.3": {
|
||||
"cache_read": 0.15,
|
||||
"input": 1.25,
|
||||
"output": 4.25,
|
||||
"source": "official vendor pricing page, verified 2026-10-17; not endpoint/account pricing"
|
||||
},
|
||||
"muse-spark-1.3-contributor": {
|
||||
"cache_read": 0.002,
|
||||
"input": 0.1,
|
||||
"output": 0.2,
|
||||
"source": "official vendor pricing page, verified 2026-10-17; not endpoint/account pricing"
|
||||
},
|
||||
"muse-wonder-1.0": {
|
||||
"cache_read": 0.2,
|
||||
"input": 4.0,
|
||||
"output": 20.0,
|
||||
"source": "official vendor pricing page, verified 2026-10-17; not endpoint/account pricing"
|
||||
},
|
||||
"moonshotai/kimi-k2.7-code-highspeed": {
|
||||
"cache_read": 0.38,
|
||||
"input": 1.9,
|
||||
@@ -5725,10 +6148,10 @@
|
||||
"canonical_model_name": {
|
||||
"pro": "deepseek-v4-pro",
|
||||
"deepseek-v4pro": "deepseek-v4-pro",
|
||||
"flash": "deepseek-v4-flash",
|
||||
"deepseek-v4flash": "deepseek-v4-flash",
|
||||
"flash-vision": "deepseek-v4-flash-vision-exp",
|
||||
"deepseek-v4flashvisionexp": "deepseek-v4-flash-vision-exp"
|
||||
"flash": "deepseek-flash",
|
||||
"deepseek-v4flash": "deepseek-flash",
|
||||
"flash-vision": "deepseek-flash",
|
||||
"deepseek-v4flashvisionexp": "deepseek-flash"
|
||||
},
|
||||
"canonical_direct_deepseek_model_id": {
|
||||
"deepseek-chat": "$DEEPSEEK_ALIAS_REPLACEMENT",
|
||||
@@ -5855,6 +6278,10 @@
|
||||
"canonical_xiaomi_mimo_model_id": {
|
||||
"mimo": "$DEFAULT_XIAOMI_MIMO_MODEL",
|
||||
"$DEFAULT_XIAOMI_MIMO_MODEL": "$DEFAULT_XIAOMI_MIMO_MODEL",
|
||||
"mimo-v2.5-pro": "$DEFAULT_XIAOMI_MIMO_MODEL",
|
||||
"mimo-v2-6-pro": "$DEFAULT_XIAOMI_MIMO_MODEL",
|
||||
"xiaomi-mimo-v2.6-pro": "$DEFAULT_XIAOMI_MIMO_MODEL",
|
||||
"xiaomi-mimo-v2-6-pro": "$DEFAULT_XIAOMI_MIMO_MODEL",
|
||||
"mimo-v2-5-pro": "$DEFAULT_XIAOMI_MIMO_MODEL",
|
||||
"xiaomi-mimo-v2.5-pro": "$DEFAULT_XIAOMI_MIMO_MODEL",
|
||||
"xiaomi-mimo-v2-5-pro": "$DEFAULT_XIAOMI_MIMO_MODEL",
|
||||
@@ -5864,20 +6291,24 @@
|
||||
"xiaomi-mimo-v2-5-pro-ultraspeed": "$XIAOMI_MIMO_V2_5_PRO_ULTRASPEED_MODEL",
|
||||
"ultraspeed": "$XIAOMI_MIMO_V2_5_PRO_ULTRASPEED_MODEL",
|
||||
"pro-ultraspeed": "$XIAOMI_MIMO_V2_5_PRO_ULTRASPEED_MODEL",
|
||||
"omni": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"mimo-omni": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"v2.5-omni": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"v25-omni": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"mimo-v2.5": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"mimo-v25": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"mimo-v2-5": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"mimo-v2.5-omni": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"mimo-v25-omni": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"mimo-v2-5-omni": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"xiaomi-mimo-v2.5": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"xiaomi-mimo-v2-5": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"xiaomi-mimo-v2.5-omni": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"xiaomi-mimo-v2-5-omni": "$XIAOMI_MIMO_V2_5_OMNI_MODEL",
|
||||
"omni": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"mimo-omni": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"v2.5-omni": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"v25-omni": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"mimo-v2.5": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"mimo-v25": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"mimo-v2-5": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"mimo-v2.5-omni": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"mimo-v25-omni": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"mimo-v2-5-omni": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"xiaomi-mimo-v2.5": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"xiaomi-mimo-v2-5": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"xiaomi-mimo-v2.5-omni": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"xiaomi-mimo-v2-5-omni": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"$XIAOMI_MIMO_V2_6_FLASH_MODEL": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"mimo-v2-6-flash": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"xiaomi-mimo-v2.6-flash": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"xiaomi-mimo-v2-6-flash": "$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"asr": "$XIAOMI_MIMO_ASR_MODEL",
|
||||
"mimo-asr": "$XIAOMI_MIMO_ASR_MODEL",
|
||||
"mimo-v2.5-asr": "$XIAOMI_MIMO_ASR_MODEL",
|
||||
@@ -6004,8 +6435,8 @@
|
||||
],
|
||||
"xiaomi-mimo": [
|
||||
"$DEFAULT_XIAOMI_MIMO_MODEL",
|
||||
"$XIAOMI_MIMO_V2_5_PRO_ULTRASPEED_MODEL",
|
||||
"$XIAOMI_MIMO_V2_5_OMNI_MODEL"
|
||||
"$XIAOMI_MIMO_V2_6_FLASH_MODEL",
|
||||
"$XIAOMI_MIMO_V2_5_PRO_ULTRASPEED_MODEL"
|
||||
],
|
||||
"novita": [
|
||||
"$DEFAULT_NOVITA_MODEL",
|
||||
@@ -6092,25 +6523,21 @@
|
||||
],
|
||||
"anthropic": [
|
||||
"$ANTHROPIC_OPUS_MODEL",
|
||||
"claude-sonnet-5-5",
|
||||
"claude-fable-5-1",
|
||||
"claude-opus-5-5",
|
||||
"claude-haiku-5-5",
|
||||
"$DEFAULT_ANTHROPIC_MODEL",
|
||||
"$ANTHROPIC_HAIKU_MODEL"
|
||||
],
|
||||
"minimax": [
|
||||
"$DEFAULT_MINIMAX_MODEL",
|
||||
"$MINIMAX_M2_7_MODEL",
|
||||
"$MINIMAX_M2_7_HIGHSPEED_MODEL",
|
||||
"$MINIMAX_M2_5_MODEL",
|
||||
"$MINIMAX_M2_5_HIGHSPEED_MODEL",
|
||||
"$MINIMAX_M2_1_MODEL",
|
||||
"$MINIMAX_M2_1_HIGHSPEED_MODEL",
|
||||
"$MINIMAX_M2_MODEL"
|
||||
],
|
||||
"minimax-anthropic": [
|
||||
"$DEFAULT_MINIMAX_MODEL",
|
||||
"$MINIMAX_M2_7_MODEL",
|
||||
"$MINIMAX_M2_7_HIGHSPEED_MODEL",
|
||||
"$MINIMAX_M2_5_MODEL",
|
||||
"$MINIMAX_M2_5_HIGHSPEED_MODEL",
|
||||
"$MINIMAX_M2_1_MODEL",
|
||||
"$MINIMAX_M2_1_HIGHSPEED_MODEL",
|
||||
"$MINIMAX_M2_MODEL"
|
||||
@@ -6133,8 +6560,11 @@
|
||||
],
|
||||
"meta": [
|
||||
"$DEFAULT_META_MODEL",
|
||||
"muse-spark-1.1",
|
||||
"muse-spark-1.2-contributor"
|
||||
"muse-spark-1.3-contributor",
|
||||
"muse-wonder-1.0",
|
||||
"muse-spark-1.2",
|
||||
"muse-spark-1.2-contributor",
|
||||
"muse-spark-1.1"
|
||||
],
|
||||
"xai": [
|
||||
"$DEFAULT_XAI_MODEL",
|
||||
@@ -6179,10 +6609,10 @@
|
||||
],
|
||||
"google": [
|
||||
"$DEFAULT_GOOGLE_MODEL",
|
||||
"gemini-4-argon",
|
||||
"gemini-3-pro-preview",
|
||||
"gemini-3.7-flash",
|
||||
"gemini-3.8-flash",
|
||||
"gemini-3.6-flash",
|
||||
"gemini-3.5-flash",
|
||||
"gemini-3.5-flash-lite",
|
||||
"gemini-2.5-pro",
|
||||
"gemini-2.5-flash"
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -377,7 +377,7 @@
|
||||
"id": "xiaomi-mimo",
|
||||
"label": "Xiaomi MiMo",
|
||||
"base_url": "https://token-plan-sgp.xiaomimimo.com/v1",
|
||||
"default_model": "mimo-v2.5-pro",
|
||||
"default_model": "mimo-v2.6-pro",
|
||||
"env_vars": [
|
||||
"XIAOMI_MIMO_TOKEN_PLAN_API_KEY",
|
||||
"MIMO_TOKEN_PLAN_API_KEY",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//!
|
||||
//! - **`deepseek-v4-pro`** — complex tasks (debugging, refactoring, design,
|
||||
//! security review, multi-file changes, code generation, …).
|
||||
//! - **`deepseek-v4-flash`** — simple tasks (lookups, formatting, small edits,
|
||||
//! - **`deepseek-flash`** — simple tasks (lookups, formatting, small edits,
|
||||
//! translation, Q&A, …).
|
||||
//!
|
||||
//! This is a pure rule-based classifier. It lives in the config crate because
|
||||
@@ -19,7 +19,7 @@
|
||||
pub const PRO_MODEL: &str = "deepseek-v4-pro";
|
||||
|
||||
/// The resolved model name for the flash tier.
|
||||
pub const FLASH_MODEL: &str = "deepseek-v4-flash";
|
||||
pub const FLASH_MODEL: &str = "deepseek-flash";
|
||||
|
||||
/// The threshold score above which a task is classified as complex (pro).
|
||||
/// Score ≥ 2 → pro, else → flash.
|
||||
|
||||
@@ -592,8 +592,8 @@ mod tests {
|
||||
fn reviewed_selection_and_transport_preserve_separate_scopes() {
|
||||
let reviewed = bundled_reviewed();
|
||||
reviewed.validate().expect("committed data");
|
||||
assert_eq!(reviewed.selections.len(), 175);
|
||||
assert_eq!(reviewed.transports.len(), 123);
|
||||
assert_eq!(reviewed.selections.len(), 183);
|
||||
assert_eq!(reviewed.transports.len(), 122);
|
||||
let go = reviewed_transport("opencode-go", "gpt-5.6-luna").unwrap();
|
||||
assert_eq!(go.endpoint_key, "responses");
|
||||
assert_eq!(
|
||||
|
||||
+36
-30
@@ -4041,16 +4041,12 @@ fn deepseek_family_model_id(model: &str) -> Option<String> {
|
||||
if trimmed.is_empty() {
|
||||
return None;
|
||||
}
|
||||
match trimmed.to_ascii_lowercase().as_str() {
|
||||
"pro" | "deepseek-v4pro" => return Some("deepseek-v4-pro".to_string()),
|
||||
"flash" | "deepseek-v4flash" => return Some("deepseek-v4-flash".to_string()),
|
||||
"flash-vision" | "deepseek-v4flashvisionexp" => {
|
||||
return Some("deepseek-v4-flash-vision-exp".to_string());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let normalized = trimmed.to_ascii_lowercase();
|
||||
if let Some(canonical) =
|
||||
crate::catalog::reviewed::compatibility_alias("canonical_model_name", &normalized)
|
||||
{
|
||||
return Some(canonical.to_string());
|
||||
}
|
||||
if !normalized.starts_with("deepseek") && !normalized.contains("/deepseek") {
|
||||
return None;
|
||||
}
|
||||
@@ -4253,43 +4249,45 @@ fn normalize_model_for_provider(provider: ProviderKind, model: &str) -> String {
|
||||
}
|
||||
(
|
||||
ProviderKind::NvidiaNim,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-reasoner"
|
||||
| "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-reasoner" | "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
) => DEFAULT_NVIDIA_NIM_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Openrouter, "deepseek-v4-pro" | "deepseek-v4pro") => {
|
||||
DEFAULT_OPENROUTER_MODEL.to_string()
|
||||
}
|
||||
(
|
||||
ProviderKind::Openrouter,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-reasoner"
|
||||
| "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-reasoner" | "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
) => DEFAULT_OPENROUTER_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Orcarouter, "deepseek-v4-pro" | "deepseek-v4pro") => {
|
||||
DEFAULT_ORCAROUTER_MODEL.to_string()
|
||||
}
|
||||
(
|
||||
ProviderKind::Orcarouter,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-reasoner"
|
||||
| "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-reasoner" | "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
) => DEFAULT_ORCAROUTER_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Novita, "deepseek-v4-pro" | "deepseek-v4pro") => {
|
||||
DEFAULT_NOVITA_MODEL.to_string()
|
||||
}
|
||||
(
|
||||
ProviderKind::Novita,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-reasoner"
|
||||
| "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-reasoner" | "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
) => DEFAULT_NOVITA_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Fireworks, "deepseek-v4-pro" | "deepseek-v4pro") => {
|
||||
DEFAULT_FIREWORKS_MODEL.to_string()
|
||||
}
|
||||
(ProviderKind::Fireworks, "deepseek-flash") => "deepseek-v4-flash".to_string(),
|
||||
(
|
||||
ProviderKind::Siliconflow | ProviderKind::SiliconflowCN,
|
||||
"deepseek-v4-pro" | "deepseek-v4pro" | "deepseek-reasoner" | "deepseek-r1",
|
||||
) => DEFAULT_SILICONFLOW_MODEL.to_string(),
|
||||
(
|
||||
ProviderKind::Siliconflow | ProviderKind::SiliconflowCN,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-v3",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-v3",
|
||||
) => DEFAULT_SILICONFLOW_FLASH_MODEL.to_string(),
|
||||
(
|
||||
ProviderKind::Arcee,
|
||||
@@ -4320,40 +4318,40 @@ fn normalize_model_for_provider(provider: ProviderKind, model: &str) -> String {
|
||||
}
|
||||
(
|
||||
ProviderKind::Sglang,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-reasoner"
|
||||
| "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-reasoner" | "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
) => DEFAULT_SGLANG_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Vllm, "deepseek-v4-pro" | "deepseek-v4pro") => {
|
||||
DEFAULT_VLLM_MODEL.to_string()
|
||||
}
|
||||
(
|
||||
ProviderKind::Vllm,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-reasoner"
|
||||
| "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-reasoner" | "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
) => DEFAULT_VLLM_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Huggingface, "deepseek-v4-pro" | "deepseek-v4pro") => {
|
||||
DEFAULT_HUGGINGFACE_MODEL.to_string()
|
||||
}
|
||||
(
|
||||
ProviderKind::Huggingface,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-reasoner"
|
||||
| "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-reasoner" | "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
) => DEFAULT_HUGGINGFACE_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Together, "deepseek-v4-pro" | "deepseek-v4pro") => {
|
||||
DEFAULT_TOGETHER_MODEL.to_string()
|
||||
}
|
||||
(
|
||||
ProviderKind::Together,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-reasoner"
|
||||
| "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-reasoner" | "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
) => DEFAULT_TOGETHER_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Deepinfra, "deepseek-v4-pro" | "deepseek-v4pro") => {
|
||||
DEFAULT_DEEPINFRA_MODEL.to_string()
|
||||
}
|
||||
(
|
||||
ProviderKind::Deepinfra,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-reasoner"
|
||||
| "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-reasoner" | "deepseek-r1" | "deepseek-v3" | "deepseek-v3.2",
|
||||
) => DEFAULT_DEEPINFRA_FLASH_MODEL.to_string(),
|
||||
_ => model.to_string(),
|
||||
}
|
||||
@@ -4365,6 +4363,10 @@ fn canonical_xiaomi_mimo_model_id(model: &str) -> Option<&'static str> {
|
||||
match normalized.as_str() {
|
||||
"mimo"
|
||||
| DEFAULT_XIAOMI_MIMO_MODEL
|
||||
| "mimo-v2-6-pro"
|
||||
| "xiaomi-mimo-v2.6-pro"
|
||||
| "xiaomi-mimo-v2-6-pro"
|
||||
| "mimo-v2.5-pro"
|
||||
| "mimo-v2-5-pro"
|
||||
| "xiaomi-mimo-v2.5-pro"
|
||||
| "xiaomi-mimo-v2-5-pro" => Some(DEFAULT_XIAOMI_MIMO_MODEL),
|
||||
@@ -4374,7 +4376,11 @@ fn canonical_xiaomi_mimo_model_id(model: &str) -> Option<&'static str> {
|
||||
| "xiaomi-mimo-v2-5-pro-ultraspeed"
|
||||
| "ultraspeed"
|
||||
| "pro-ultraspeed" => Some(XIAOMI_MIMO_V2_5_PRO_ULTRASPEED_MODEL),
|
||||
"omni"
|
||||
XIAOMI_MIMO_V2_6_FLASH_MODEL
|
||||
| "mimo-v2-6-flash"
|
||||
| "xiaomi-mimo-v2.6-flash"
|
||||
| "xiaomi-mimo-v2-6-flash"
|
||||
| "omni"
|
||||
| "mimo-omni"
|
||||
| "v2.5-omni"
|
||||
| "v25-omni"
|
||||
@@ -4387,7 +4393,7 @@ fn canonical_xiaomi_mimo_model_id(model: &str) -> Option<&'static str> {
|
||||
| "xiaomi-mimo-v2.5"
|
||||
| "xiaomi-mimo-v2-5"
|
||||
| "xiaomi-mimo-v2.5-omni"
|
||||
| "xiaomi-mimo-v2-5-omni" => Some(XIAOMI_MIMO_V2_5_OMNI_MODEL),
|
||||
| "xiaomi-mimo-v2-5-omni" => Some(XIAOMI_MIMO_V2_6_FLASH_MODEL),
|
||||
"asr" | "mimo-asr" | "mimo-v2.5-asr" | "speech-to-text" | "transcribe" => {
|
||||
Some(XIAOMI_MIMO_ASR_MODEL)
|
||||
}
|
||||
|
||||
@@ -175,14 +175,9 @@ fn modelstudio_image_input_capability_is_per_model() {
|
||||
use super::capabilities::CapabilityState;
|
||||
|
||||
// Owner's Token Plan console (verified 2026-08-03) lists Visual
|
||||
// Understanding for exactly these four models; upstream Models.dev
|
||||
// modalities agree (image/video input) and mark the rest text-only.
|
||||
const VISION: &[&str] = &[
|
||||
"qwen3.8-max",
|
||||
"qwen3.8-max-preview",
|
||||
"qwen3.7-plus",
|
||||
"qwen3.6-flash",
|
||||
];
|
||||
// Understanding for these models; upstream Models.dev modalities agree
|
||||
// (image/video input) and mark the rest text-only.
|
||||
const VISION: &[&str] = &["qwen3.8-max", "qwen3.7-plus", "qwen3.6-flash"];
|
||||
const TEXT_ONLY: &[&str] = &[
|
||||
"qwen3.7-max",
|
||||
"deepseek-v4-pro",
|
||||
|
||||
@@ -26,10 +26,18 @@
|
||||
{
|
||||
"id": "claude-fable-5"
|
||||
},
|
||||
{
|
||||
"id": "claude-fable-5-1",
|
||||
"canonical": "anthropic/claude-fable-5-1"
|
||||
},
|
||||
{
|
||||
"id": "claude-haiku-4-5",
|
||||
"canonical": "anthropic/claude-haiku-4-5"
|
||||
},
|
||||
{
|
||||
"id": "claude-haiku-5-5",
|
||||
"canonical": "anthropic/claude-haiku-5-5"
|
||||
},
|
||||
{
|
||||
"id": "claude-opus-4-8"
|
||||
},
|
||||
@@ -37,12 +45,20 @@
|
||||
"id": "claude-opus-5",
|
||||
"canonical": "anthropic/claude-opus-5"
|
||||
},
|
||||
{
|
||||
"id": "claude-opus-5-5",
|
||||
"canonical": "anthropic/claude-opus-5-5"
|
||||
},
|
||||
{
|
||||
"id": "claude-sonnet-4-6",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"id": "claude-sonnet-5"
|
||||
},
|
||||
{
|
||||
"id": "claude-sonnet-5-5",
|
||||
"canonical": "anthropic/claude-sonnet-5-5"
|
||||
}
|
||||
],
|
||||
"transport": "anthropic-messages"
|
||||
@@ -374,6 +390,18 @@
|
||||
{
|
||||
"id": "muse-spark-1.2-contributor",
|
||||
"canonical": "meta/muse-spark-1.2"
|
||||
},
|
||||
{
|
||||
"id": "muse-spark-1.3",
|
||||
"canonical": "meta/muse-spark-1.3"
|
||||
},
|
||||
{
|
||||
"id": "muse-spark-1.3-contributor",
|
||||
"canonical": "meta/muse-spark-1.3"
|
||||
},
|
||||
{
|
||||
"id": "muse-wonder-1.0",
|
||||
"canonical": "meta/muse-wonder-1.0"
|
||||
}
|
||||
],
|
||||
"transport": "chat-completions"
|
||||
@@ -512,10 +540,6 @@
|
||||
"id": "qwen3.8-max",
|
||||
"canonical": "alibaba/qwen3.8-max",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"id": "qwen3.8-max-preview",
|
||||
"canonical": "alibaba/qwen3.8-max-preview"
|
||||
}
|
||||
],
|
||||
"transport": "chat-completions"
|
||||
@@ -558,10 +582,6 @@
|
||||
"id": "qwen3.8-max",
|
||||
"canonical": "alibaba/qwen3.8-max",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"id": "qwen3.8-max-preview",
|
||||
"canonical": "alibaba/qwen3.8-max-preview"
|
||||
}
|
||||
],
|
||||
"transport": "anthropic-messages"
|
||||
@@ -612,10 +632,6 @@
|
||||
"id": "qwen3.8-max",
|
||||
"canonical": "alibaba/qwen3.8-max",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"id": "qwen3.8-max-preview",
|
||||
"canonical": "alibaba/qwen3.8-max-preview"
|
||||
}
|
||||
],
|
||||
"transport": "chat-completions"
|
||||
@@ -666,10 +682,6 @@
|
||||
"id": "qwen3.8-max",
|
||||
"canonical": "alibaba/qwen3.8-max",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"id": "qwen3.8-max-preview",
|
||||
"canonical": "alibaba/qwen3.8-max-preview"
|
||||
}
|
||||
],
|
||||
"transport": "anthropic-messages"
|
||||
@@ -1292,7 +1304,7 @@
|
||||
"label": "Xiaomi MiMo",
|
||||
"endpoint": "https://token-plan-sgp.xiaomimimo.com/v1",
|
||||
"wire": "chat-completions",
|
||||
"defaultModel": "mimo-v2.5-pro",
|
||||
"defaultModel": "mimo-v2.6-pro",
|
||||
"envVars": [
|
||||
"XIAOMI_MIMO_TOKEN_PLAN_API_KEY",
|
||||
"MIMO_TOKEN_PLAN_API_KEY",
|
||||
@@ -1307,18 +1319,12 @@
|
||||
}
|
||||
],
|
||||
"models": [
|
||||
{
|
||||
"id": "mimo-v2.5"
|
||||
},
|
||||
{
|
||||
"id": "mimo-v2.5-pro",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"id": "mimo-v2.6-flash"
|
||||
},
|
||||
{
|
||||
"id": "mimo-v2.6-pro"
|
||||
"id": "mimo-v2.6-pro",
|
||||
"default": true
|
||||
}
|
||||
],
|
||||
"transport": "chat-completions"
|
||||
|
||||
@@ -1866,7 +1866,7 @@ fn mimo_native_search_is_exact_to_documented_chat_models() {
|
||||
use crate::route::CapabilityState;
|
||||
|
||||
let resolver = RouteResolver::new();
|
||||
for model in ["mimo-v2.5-pro", "mimo-v2.5"] {
|
||||
for model in ["mimo-v2.6-pro", "mimo-v2.6-flash"] {
|
||||
let direct = resolver
|
||||
.resolve(&req(Some(ProviderKind::XiaomiMimo), Some(model)))
|
||||
.expect("official MiMo chat route resolves");
|
||||
|
||||
@@ -6040,7 +6040,7 @@ mode = "token-plan-usa"
|
||||
fn xiaomi_mimo_aliases_resolve_to_canonical_models() {
|
||||
assert_eq!(
|
||||
normalize_model_for_provider(ProviderKind::XiaomiMimo, "omni"),
|
||||
"mimo-v2.5"
|
||||
"mimo-v2.6-flash"
|
||||
);
|
||||
assert_eq!(
|
||||
normalize_model_for_provider(ProviderKind::XiaomiMimo, "pro-ultraspeed"),
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
"ConfigActionChoose": "Enter obre les opcions",
|
||||
"ConfigActionEdit": "Enter edita",
|
||||
"ConfigActionReadOnly": "només lectura",
|
||||
"ModelPickerAutoNetworkHint": "per torn · proveïdors disponibles · petició + context recent → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "per torn · proveïdors disponibles · petició + context recent → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoLocalHint": "per torn · heurística local · sense petició al router",
|
||||
"ModelPickerAutoLastRoute": "última {provider} · {model}",
|
||||
"AutoRouteSelectedToast": "Auto: {provider} / {model} via {source} · Ctrl+O: detalls de la ruta",
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
"ConfigActionChoose": "Enter öffnet Auswahl",
|
||||
"ConfigActionEdit": "Enter bearbeitet",
|
||||
"ConfigActionReadOnly": "schreibgeschützt",
|
||||
"ModelPickerAutoNetworkHint": "pro Zug · lauffähige Provider · Anfrage + letzter Kontext → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "pro Zug · lauffähige Provider · Anfrage + letzter Kontext → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoLocalHint": "pro Zug · lokale Heuristik · keine Router-Anfrage",
|
||||
"ModelPickerAutoLastRoute": "zuletzt {provider} · {model}",
|
||||
"AutoRouteSelectedToast": "Auto: {provider} / {model} via {source} · Ctrl+O: Routendetails",
|
||||
|
||||
@@ -420,7 +420,7 @@
|
||||
"ConfigActionChoose": "Enter opens choices",
|
||||
"ConfigActionEdit": "Enter edits",
|
||||
"ConfigActionReadOnly": "read only",
|
||||
"ModelPickerAutoNetworkHint": "per turn · runnable providers · request + recent context → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "per turn · runnable providers · request + recent context → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoNetworkActiveProviderHint": "per turn · active provider only · request + recent context → {provider} / {model}",
|
||||
"ModelPickerAutoLocalHint": "per turn · local heuristic · no router request",
|
||||
"ModelPickerAutoLastRoute": "last {provider} · {model}",
|
||||
|
||||
@@ -420,7 +420,7 @@
|
||||
"ConfigActionChoose": "Enter abre las opciones",
|
||||
"ConfigActionEdit": "Enter edita",
|
||||
"ConfigActionReadOnly": "solo lectura",
|
||||
"ModelPickerAutoNetworkHint": "por turno · proveedores disponibles · solicitud + contexto reciente → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "por turno · proveedores disponibles · solicitud + contexto reciente → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoNetworkActiveProviderHint": "por turno · solo el proveedor activo · solicitud + contexto reciente → {provider} / {model}",
|
||||
"ModelPickerAutoLocalHint": "por turno · heurística local · sin solicitud al enrutador",
|
||||
"ModelPickerAutoLastRoute": "última {provider} · {model}",
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
"ConfigActionChoose": "Enter ouvre les choix",
|
||||
"ConfigActionEdit": "Enter modifie",
|
||||
"ConfigActionReadOnly": "lecture seule",
|
||||
"ModelPickerAutoNetworkHint": "par tour · fournisseurs exécutables · requête + contexte récent → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "par tour · fournisseurs exécutables · requête + contexte récent → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoLocalHint": "par tour · heuristique locale · pas de requête au routeur",
|
||||
"ModelPickerAutoLastRoute": "dernière {provider} · {model}",
|
||||
"AutoRouteSelectedToast": "Auto : {provider} / {model} via {source} · Ctrl+O : détails de la route",
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
"ConfigActionChoose": "Enter विकल्प खोलता है",
|
||||
"ConfigActionEdit": "Enter संपादित करता है",
|
||||
"ConfigActionReadOnly": "केवल पठन",
|
||||
"ModelPickerAutoNetworkHint": "प्रति टर्न · चलाने योग्य प्रोवाइडर · अनुरोध + हालिया संदर्भ → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "प्रति टर्न · चलाने योग्य प्रोवाइडर · अनुरोध + हालिया संदर्भ → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoLocalHint": "प्रति टर्न · लोकल ह्यूरिस्टिक · कोई राउटर अनुरोध नहीं",
|
||||
"ModelPickerAutoLastRoute": "अंतिम {provider} · {model}",
|
||||
"AutoRouteSelectedToast": "Auto: {provider} / {model} ({source} द्वारा) · Ctrl+O: रूट विवरण",
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
"ConfigActionChoose": "Enter membuka pilihan",
|
||||
"ConfigActionEdit": "Enter mengedit",
|
||||
"ConfigActionReadOnly": "hanya baca",
|
||||
"ModelPickerAutoNetworkHint": "per giliran · penyedia yang dapat dijalankan · permintaan + konteks terbaru → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "per giliran · penyedia yang dapat dijalankan · permintaan + konteks terbaru → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoLocalHint": "per giliran · heuristik lokal · tanpa permintaan router",
|
||||
"ModelPickerAutoLastRoute": "terakhir {provider} · {model}",
|
||||
"AutoRouteSelectedToast": "Auto: {provider} / {model} via {source} · Ctrl+O: detail rute",
|
||||
|
||||
@@ -420,7 +420,7 @@
|
||||
"ConfigActionChoose": "Enter で選択肢を開く",
|
||||
"ConfigActionEdit": "Enter で編集",
|
||||
"ConfigActionReadOnly": "読み取り専用",
|
||||
"ModelPickerAutoNetworkHint": "ターンごと · 実行可能なプロバイダー · リクエスト+直近のコンテキスト → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "ターンごと · 実行可能なプロバイダー · リクエスト+直近のコンテキスト → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoNetworkActiveProviderHint": "ターンごと · アクティブなプロバイダーのみ · リクエスト+直近のコンテキスト → {provider} / {model}",
|
||||
"ModelPickerAutoLocalHint": "ターンごと · ローカル判定 · ルーター送信なし",
|
||||
"ModelPickerAutoLastRoute": "前回 {provider} · {model}",
|
||||
|
||||
@@ -420,7 +420,7 @@
|
||||
"ConfigActionChoose": "Enter로 선택 항목 열기",
|
||||
"ConfigActionEdit": "Enter로 편집",
|
||||
"ConfigActionReadOnly": "읽기 전용",
|
||||
"ModelPickerAutoNetworkHint": "턴별 · 실행 가능한 제공자 · 요청 + 최근 컨텍스트 → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "턴별 · 실행 가능한 제공자 · 요청 + 최근 컨텍스트 → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoNetworkActiveProviderHint": "턴별 · 활성 제공자만 · 요청 + 최근 컨텍스트 → {provider} / {model}",
|
||||
"ModelPickerAutoLocalHint": "턴별 · 로컬 휴리스틱 · 라우터 요청 없음",
|
||||
"ModelPickerAutoLastRoute": "최근 {provider} · {model}",
|
||||
|
||||
@@ -420,7 +420,7 @@
|
||||
"ConfigActionChoose": "Enter abre as opções",
|
||||
"ConfigActionEdit": "Enter edita",
|
||||
"ConfigActionReadOnly": "somente leitura",
|
||||
"ModelPickerAutoNetworkHint": "por turno · provedores executáveis · solicitação + contexto recente → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "por turno · provedores executáveis · solicitação + contexto recente → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoNetworkActiveProviderHint": "por turno · apenas o provedor ativo · solicitação + contexto recente → {provider} / {model}",
|
||||
"ModelPickerAutoLocalHint": "por turno · heurística local · sem solicitação ao roteador",
|
||||
"ModelPickerAutoLastRoute": "última {provider} · {model}",
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
"ConfigActionChoose": "Enter — открыть варианты",
|
||||
"ConfigActionEdit": "Enter — изменить",
|
||||
"ConfigActionReadOnly": "только чтение",
|
||||
"ModelPickerAutoNetworkHint": "на ход · готовые провайдеры · запрос + недавний контекст → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "на ход · готовые провайдеры · запрос + недавний контекст → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoLocalHint": "на ход · локальная эвристика · без запроса к маршрутизатору",
|
||||
"ModelPickerAutoLastRoute": "последний {provider} · {model}",
|
||||
"AutoRouteSelectedToast": "Auto: {provider} / {model} через {source} · Ctrl+O: детали маршрута",
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
"ConfigActionChoose": "Enter відкриває варіанти",
|
||||
"ConfigActionEdit": "Enter редагує",
|
||||
"ConfigActionReadOnly": "лише читання",
|
||||
"ModelPickerAutoNetworkHint": "за крок · доступні провайдери · запит + недавній контекст → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "за крок · доступні провайдери · запит + недавній контекст → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoLocalHint": "за крок · локальна евристика · без запиту до маршрутизатора",
|
||||
"ModelPickerAutoLastRoute": "останній {provider} · {model}",
|
||||
"AutoRouteSelectedToast": "Auto: {provider} / {model} через {source} · Ctrl+O: деталі маршруту",
|
||||
|
||||
@@ -420,7 +420,7 @@
|
||||
"ConfigActionChoose": "Enter mở các lựa chọn",
|
||||
"ConfigActionEdit": "Enter để sửa",
|
||||
"ConfigActionReadOnly": "chỉ đọc",
|
||||
"ModelPickerAutoNetworkHint": "mỗi lượt · nhà cung cấp khả dụng · yêu cầu + ngữ cảnh gần đây → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "mỗi lượt · nhà cung cấp khả dụng · yêu cầu + ngữ cảnh gần đây → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoNetworkActiveProviderHint": "mỗi lượt · chỉ nhà cung cấp đang dùng · yêu cầu + ngữ cảnh gần đây → {provider} / {model}",
|
||||
"ModelPickerAutoLocalHint": "mỗi lượt · heuristic cục bộ · không gửi yêu cầu định tuyến",
|
||||
"ModelPickerAutoLastRoute": "lần trước {provider} · {model}",
|
||||
|
||||
@@ -420,7 +420,7 @@
|
||||
"ConfigActionChoose": "按 Enter 打开选项",
|
||||
"ConfigActionEdit": "按 Enter 编辑",
|
||||
"ConfigActionReadOnly": "只读",
|
||||
"ModelPickerAutoNetworkHint": "每回合 · 可用提供商 · 请求及近期上下文 → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "每回合 · 可用提供商 · 请求及近期上下文 → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoNetworkActiveProviderHint": "每回合 · 仅当前提供商 · 请求及近期上下文 → {provider} / {model}",
|
||||
"ModelPickerAutoLocalHint": "每回合 · 本地启发式 · 不发送路由请求",
|
||||
"ModelPickerAutoLastRoute": "上次 {provider} · {model}",
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
"ConfigActionChoose": "按 Enter 開啟選項",
|
||||
"ConfigActionEdit": "按 Enter 編輯",
|
||||
"ConfigActionReadOnly": "唯讀",
|
||||
"ModelPickerAutoNetworkHint": "每回合 · 可用供應商 · 請求與近期上下文 → DeepSeek / deepseek-v4-flash",
|
||||
"ModelPickerAutoNetworkHint": "每回合 · 可用供應商 · 請求與近期上下文 → DeepSeek / deepseek-flash",
|
||||
"ModelPickerAutoNetworkActiveProviderHint": "每回合 · 僅目前供應商 · 請求與近期上下文 → {provider} / {model}",
|
||||
"ModelPickerAutoLocalHint": "每回合 · 本機啟發式 · 不傳送路由請求",
|
||||
"ModelPickerAutoLastRoute": "上次 {provider} · {model}",
|
||||
|
||||
@@ -7,6 +7,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- The model catalog now carries current models from Anthropic, Google and
|
||||
Meta. Anthropic: `claude-opus-5-5`, `claude-sonnet-5-5`, `claude-haiku-5-5`
|
||||
and `claude-fable-5-1`; the Auto router's cheap tier and the Scout companion
|
||||
stay on `claude-haiku-4-5`. The default stays `claude-sonnet-4-6`, because
|
||||
Codewhale does not yet apply the 5.5 models' request rules, and no default
|
||||
uses `claude-sonnet-4-5`, which retires on 2026-11-30. OpenAI's GPT-6
|
||||
family (`gpt-6-sol`, `gpt-6.1-sol`, `gpt-6-luna` and `gpt-6-astra`) is left
|
||||
out of the direct route because OpenAI does not support normal tool calling
|
||||
for them over Chat Completions. Google: `gemini-4-argon` and
|
||||
`gemini-3.8-flash`. Z.ai: `GLM-5.3-FlashX` is not offered because the
|
||||
Coding Plan endpoint the zai route defaults to does not serve it. Meta:
|
||||
`muse-spark-1.3`, `muse-spark-1.3-contributor` and the `muse-wonder-1.0`
|
||||
preview join the route, which stays on its previous `muse-spark-1.2`
|
||||
default.
|
||||
Several ids are retired. Xiaomi MiMo now defaults to `mimo-v2.6-pro`, and
|
||||
configs naming `mimo-v2.5-pro` or `mimo-v2.5` send `mimo-v2.6-pro` and
|
||||
`mimo-v2.6-flash`, because Xiaomi rejects the old names from 2026-10-21.
|
||||
`gemini-3.7-flash` and `gemini-3.5-flash`, which Google already serves as
|
||||
`gemini-3.8-flash` and `gemini-3.6-flash`, are now selector aliases of those
|
||||
models. `qwen3.8-max-preview` is gone from the Model Studio rosters. MiniMax
|
||||
M2.7 and M2.5 (including highspeed) leave the fallback picker before
|
||||
MiniMax closes them to new users on 2026-10-19, and keep working for
|
||||
existing configs until they retire on 2026-11-18.
|
||||
- Direct DeepSeek routes now send `deepseek-flash` for `deepseek-chat`,
|
||||
`deepseek-reasoner`, the `flash`, `deepseek-v4flash`, `flash-vision` and
|
||||
`deepseek-v4flashvisionexp` shorthands, and the Auto router's fast tier.
|
||||
`codewhale model set` and `/provider` now write `deepseek-flash` for those
|
||||
shorthands too, matching what `model = "flash"` and `/model flash` resolve
|
||||
to.
|
||||
DeepSeek has retired the V4 Flash and V4 Flash vision models. It still
|
||||
accepts `deepseek-v4-flash` and `deepseek-v4-flash-vision-exp`, but serves
|
||||
them with V4.1 Flash, bills them at the Flash price, and calls that routing
|
||||
temporary. Turns on either name from 2026-09-10 04:00 UTC are now priced at
|
||||
the Flash rates ($0.003 cache hit, $0.15 cache miss, $0.60 output per
|
||||
million tokens off-peak, doubled at peak) instead of the old V4 Flash rates,
|
||||
which overstated a cache hit by about 2.3 times. The vision name was not
|
||||
priced at all before. Earlier turns keep the rates they were billed at,
|
||||
including turns recorded under a shorthand. On NVIDIA NIM, OpenRouter,
|
||||
Novita, Fireworks, SiliconFlow, SGLang, vLLM, DeepInfra and Together,
|
||||
`deepseek-flash` selects that host's V4 Flash model, so the `flash`
|
||||
shorthand keeps working there.
|
||||
- When a `tool_search` activation pushes an earlier deferred tool out of the
|
||||
bounded conversation toolbox (8 tools, 16 KiB of schemas), the search
|
||||
result now names it under `evicted_tool_references`. Before, the tool
|
||||
silently disappeared from the next request, and a model could go on
|
||||
calling it. Thanks @asto18089 for the cost and correctness analysis
|
||||
(Refs #6969).
|
||||
- An ACP client that asks how to turn on Full Access is now told the
|
||||
routes that work: start the server with `codewhale --yolo serve --acp`,
|
||||
or set `yolo = true` in config.toml. The hint used to recommend
|
||||
`--approval-policy full-access` or `approval_policy = "full-access"` in
|
||||
config.toml. Both are refused when Codewhale starts, because config.toml's
|
||||
`approval_policy` only accepts on-request, untrusted, never, auto and
|
||||
suggest. Thanks @harryvizcaino-oss for the Paseo report (Refs #6992).
|
||||
- On Linux, a credential directory the sandbox hides no longer breaks every
|
||||
sandboxed command when it is reached through a symlink, such as `~/.kube`
|
||||
linked into a synced dotfiles folder or a `~/.config` that links
|
||||
|
||||
@@ -722,7 +722,7 @@ impl AcpServer {
|
||||
Ok(self.current_model())
|
||||
}
|
||||
}
|
||||
const ACP_FULL_ACCESS_HINT: &str = "Start the server with `codewhale --approval-policy full-access serve --acp`, or set approval_policy = \"full-access\" in config.toml. Full Access also turns off Codewhale's own sandbox unless sandbox_mode tightens it; Plan stays read-only.";
|
||||
const ACP_FULL_ACCESS_HINT: &str = "Start the server with `codewhale --yolo serve --acp`, or set `yolo = true` in config.toml. Full Access also turns off Codewhale's own sandbox unless sandbox_mode tightens it; Plan stays read-only.";
|
||||
|
||||
fn acp_mode(config: &Config) -> AppMode {
|
||||
if config.sandbox_mode.as_deref() == Some("read-only") {
|
||||
|
||||
@@ -209,9 +209,9 @@ fn expand_model_alias_for_provider(provider: ProviderKind, name: &str) -> String
|
||||
let lower = trimmed.to_ascii_lowercase();
|
||||
if matches!(provider, ProviderKind::XiaomiMimo) {
|
||||
return match lower.as_str() {
|
||||
"pro" | "mimo" => "mimo-v2.5-pro".to_string(),
|
||||
"pro" | "mimo" => "mimo-v2.6-pro".to_string(),
|
||||
"ultraspeed" | "pro-ultraspeed" => "mimo-v2.5-pro-ultraspeed".to_string(),
|
||||
"text" | "omni" | "v2.5-omni" => "mimo-v2.5".to_string(),
|
||||
"text" | "omni" | "v2.5-omni" => "mimo-v2.6-flash".to_string(),
|
||||
"tts" | "speech" | "mimo-tts" => "mimo-v2.5-tts".to_string(),
|
||||
"voicedesign" | "voice-design" | "mimo-voice-design" => {
|
||||
"mimo-v2.5-tts-voicedesign".to_string()
|
||||
@@ -227,7 +227,7 @@ fn expand_model_alias_for_provider(provider: ProviderKind, name: &str) -> String
|
||||
|
||||
match lower.as_str() {
|
||||
"pro" | "v4-pro" => "deepseek-v4-pro".to_string(),
|
||||
"flash" | "v4-flash" => "deepseek-v4-flash".to_string(),
|
||||
"flash" | "v4-flash" => "deepseek-flash".to_string(),
|
||||
// Not a shorthand: keep the id as typed (case preserved for opaque
|
||||
// model tags on passthrough providers like Ollama/HuggingFace).
|
||||
_ => trimmed.to_string(),
|
||||
@@ -413,8 +413,8 @@ mod tests {
|
||||
for (input, expected) in [
|
||||
("xiaomi-mimo pro-ultraspeed", "mimo-v2.5-pro-ultraspeed"),
|
||||
("xiaomi-mimo ultraspeed", "mimo-v2.5-pro-ultraspeed"),
|
||||
("xiaomi-mimo omni", "mimo-v2.5"),
|
||||
("xiaomi-mimo v2.5-omni", "mimo-v2.5"),
|
||||
("xiaomi-mimo omni", "mimo-v2.6-flash"),
|
||||
("xiaomi-mimo v2.5-omni", "mimo-v2.6-flash"),
|
||||
] {
|
||||
let result = provider(&mut app, Some(input));
|
||||
match result.action {
|
||||
@@ -537,7 +537,7 @@ mod tests {
|
||||
match result.action {
|
||||
Some(AppAction::SwitchProvider { provider, model }) => {
|
||||
assert_eq!(provider.as_str(), ProviderKind::Siliconflow.as_str());
|
||||
assert_eq!(model.as_deref(), Some("deepseek-v4-flash"));
|
||||
assert_eq!(model.as_deref(), Some("deepseek-flash"));
|
||||
}
|
||||
other => panic!("expected SwitchProvider, got {other:?}"),
|
||||
}
|
||||
@@ -550,7 +550,7 @@ mod tests {
|
||||
match result.action {
|
||||
Some(AppAction::SwitchProvider { provider, model }) => {
|
||||
assert_eq!(provider.as_str(), ProviderKind::SiliconflowCN.as_str());
|
||||
assert_eq!(model.as_deref(), Some("deepseek-v4-flash"));
|
||||
assert_eq!(model.as_deref(), Some("deepseek-flash"));
|
||||
}
|
||||
other => panic!("expected SwitchProvider, got {other:?}"),
|
||||
}
|
||||
@@ -576,7 +576,7 @@ mod tests {
|
||||
match result.action {
|
||||
Some(AppAction::SwitchProvider { provider, model }) => {
|
||||
assert_eq!(provider.as_str(), ProviderKind::Together.as_str());
|
||||
assert_eq!(model.as_deref(), Some("deepseek-v4-flash"));
|
||||
assert_eq!(model.as_deref(), Some("deepseek-flash"));
|
||||
}
|
||||
other => panic!("expected SwitchProvider, got {other:?}"),
|
||||
}
|
||||
@@ -589,7 +589,7 @@ mod tests {
|
||||
match result.action {
|
||||
Some(AppAction::SwitchProvider { provider, model }) => {
|
||||
assert_eq!(provider.as_str(), ProviderKind::Sglang.as_str());
|
||||
assert_eq!(model.as_deref(), Some("deepseek-v4-flash"));
|
||||
assert_eq!(model.as_deref(), Some("deepseek-flash"));
|
||||
}
|
||||
other => panic!("expected SwitchProvider, got {other:?}"),
|
||||
}
|
||||
@@ -602,7 +602,7 @@ mod tests {
|
||||
match result.action {
|
||||
Some(AppAction::SwitchProvider { provider, model }) => {
|
||||
assert_eq!(provider.as_str(), ProviderKind::Vllm.as_str());
|
||||
assert_eq!(model.as_deref(), Some("deepseek-v4-flash"));
|
||||
assert_eq!(model.as_deref(), Some("deepseek-flash"));
|
||||
}
|
||||
other => panic!("expected SwitchProvider, got {other:?}"),
|
||||
}
|
||||
@@ -651,7 +651,7 @@ mod tests {
|
||||
match result.action {
|
||||
Some(AppAction::SwitchProvider { provider, model }) => {
|
||||
assert_eq!(provider.as_str(), ProviderKind::NvidiaNim.as_str());
|
||||
assert_eq!(model.as_deref(), Some("deepseek-v4-flash"));
|
||||
assert_eq!(model.as_deref(), Some("deepseek-flash"));
|
||||
}
|
||||
other => panic!("expected SwitchProvider action, got {other:?}"),
|
||||
}
|
||||
@@ -677,7 +677,7 @@ mod tests {
|
||||
match result.action {
|
||||
Some(AppAction::SwitchProvider { provider, model }) => {
|
||||
assert_eq!(provider.as_str(), ProviderKind::Deepseek.as_str());
|
||||
assert_eq!(model.as_deref(), Some("deepseek-v4-flash"));
|
||||
assert_eq!(model.as_deref(), Some("deepseek-flash"));
|
||||
}
|
||||
other => panic!("expected SwitchProvider action, got {other:?}"),
|
||||
}
|
||||
|
||||
+27
-21
@@ -366,10 +366,8 @@ pub fn provider_capability_with_wire(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let exact_deepseek = canonical_official_deepseek_model_id(&model_lower);
|
||||
let is_v4_pro = exact_deepseek == Some("deepseek-v4-pro");
|
||||
let is_v4_flash =
|
||||
exact_deepseek == Some(DEEPSEEK_ALIAS_REPLACEMENT) || alias_deprecation.is_some();
|
||||
let official_deepseek =
|
||||
canonical_official_deepseek_model_id(&model_lower).is_some() || alias_deprecation.is_some();
|
||||
let is_reasoner = matches!(provider, ProviderKind::WanjieArk)
|
||||
&& (model_lower.contains("reasoner") || model_lower.contains("r1"));
|
||||
|
||||
@@ -377,7 +375,7 @@ pub fn provider_capability_with_wire(
|
||||
// model-only row. Reuse those facts before conservative fallback budgets.
|
||||
let offering =
|
||||
crate::provider_lake::bundled_catalog_offering_for_model(provider, resolved_model);
|
||||
let context_window = if is_v4_pro || is_v4_flash {
|
||||
let context_window = if official_deepseek {
|
||||
codewhale_models::DEEPSEEK_V4_CONTEXT_WINDOW_TOKENS
|
||||
} else if let Some(window) = codewhale_models::context_window_for_model(resolved_model) {
|
||||
window
|
||||
@@ -424,8 +422,7 @@ pub fn provider_capability_with_wire(
|
||||
});
|
||||
|
||||
// Exact catalog reasoning facts and recognized compatibility aliases only.
|
||||
let thinking_supported = is_v4_pro
|
||||
|| is_v4_flash
|
||||
let thinking_supported = official_deepseek
|
||||
|| is_reasoner
|
||||
|| offering
|
||||
.as_ref()
|
||||
@@ -467,7 +464,7 @@ fn deepseek_alias_deprecation(model_lower: &str) -> Option<ModelAliasDeprecation
|
||||
retirement_date: DEEPSEEK_ALIAS_RETIREMENT_DATE.to_string(),
|
||||
retirement_utc: DEEPSEEK_ALIAS_RETIREMENT_UTC.to_string(),
|
||||
notice: format!(
|
||||
"{model_lower} is a compatibility alias for {DEEPSEEK_ALIAS_REPLACEMENT} and is scheduled to retire on {DEEPSEEK_ALIAS_RETIREMENT_DATE}."
|
||||
"DeepSeek retired {model_lower} on {DEEPSEEK_ALIAS_RETIREMENT_DATE}; Codewhale sends {DEEPSEEK_ALIAS_REPLACEMENT} instead."
|
||||
),
|
||||
}),
|
||||
_ => None,
|
||||
@@ -476,9 +473,9 @@ fn deepseek_alias_deprecation(model_lower: &str) -> Option<ModelAliasDeprecation
|
||||
|
||||
/// Canonicalize compact DeepSeek model aliases to stable IDs.
|
||||
///
|
||||
/// Already-valid model IDs pass through unchanged. Only the compact
|
||||
/// `v4pro`/`v4flash` spellings and the experimental vision shorthand are
|
||||
/// rewritten to their hyphenated forms.
|
||||
/// Already-valid model IDs pass through unchanged. The compact `v4pro`
|
||||
/// spelling is rewritten to its hyphenated form, and the Flash and retired
|
||||
/// vision shorthands select `deepseek-flash`.
|
||||
#[must_use]
|
||||
pub fn canonical_model_name(model: &str) -> Option<&'static str> {
|
||||
codewhale_config::catalog::reviewed::compatibility_alias(
|
||||
@@ -10319,40 +10316,49 @@ fn model_for_provider(provider: ProviderKind, normalized: String) -> String {
|
||||
let lowered = normalized.to_ascii_lowercase();
|
||||
match (provider, lowered.as_str()) {
|
||||
(ProviderKind::NvidiaNim, "deepseek-v4-pro") => DEFAULT_NVIDIA_NIM_MODEL.to_string(),
|
||||
(ProviderKind::NvidiaNim, "deepseek-v4-flash") => {
|
||||
(ProviderKind::NvidiaNim, "deepseek-flash" | "deepseek-v4-flash") => {
|
||||
DEFAULT_NVIDIA_NIM_FLASH_MODEL.to_string()
|
||||
}
|
||||
(ProviderKind::Openrouter, "deepseek-v4-pro") => DEFAULT_OPENROUTER_MODEL.to_string(),
|
||||
(ProviderKind::Openrouter, "deepseek-v4-flash") => {
|
||||
(ProviderKind::Openrouter, "deepseek-flash" | "deepseek-v4-flash") => {
|
||||
DEFAULT_OPENROUTER_FLASH_MODEL.to_string()
|
||||
}
|
||||
(ProviderKind::Novita, "deepseek-v4-pro") => DEFAULT_NOVITA_MODEL.to_string(),
|
||||
(ProviderKind::Novita, "deepseek-v4-flash") => DEFAULT_NOVITA_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Novita, "deepseek-flash" | "deepseek-v4-flash") => {
|
||||
DEFAULT_NOVITA_FLASH_MODEL.to_string()
|
||||
}
|
||||
(ProviderKind::Fireworks, "deepseek-v4-pro") => DEFAULT_FIREWORKS_MODEL.to_string(),
|
||||
(ProviderKind::Fireworks, "deepseek-flash") => "deepseek-v4-flash".to_string(),
|
||||
(
|
||||
ProviderKind::Siliconflow | ProviderKind::SiliconflowCN,
|
||||
"deepseek-v4-pro" | "deepseek-reasoner" | "deepseek-r1",
|
||||
) => DEFAULT_SILICONFLOW_MODEL.to_string(),
|
||||
(
|
||||
ProviderKind::Siliconflow | ProviderKind::SiliconflowCN,
|
||||
"deepseek-v4-flash" | "deepseek-chat" | "deepseek-v3",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-chat" | "deepseek-v3",
|
||||
) => DEFAULT_SILICONFLOW_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Sglang, "deepseek-v4-pro") => DEFAULT_SGLANG_MODEL.to_string(),
|
||||
(ProviderKind::Sglang, "deepseek-v4-flash") => DEFAULT_SGLANG_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Sglang, "deepseek-flash" | "deepseek-v4-flash") => {
|
||||
DEFAULT_SGLANG_FLASH_MODEL.to_string()
|
||||
}
|
||||
(ProviderKind::Vllm, "deepseek-v4-pro") => DEFAULT_VLLM_MODEL.to_string(),
|
||||
(ProviderKind::Vllm, "deepseek-v4-flash") => DEFAULT_VLLM_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Vllm, "deepseek-flash" | "deepseek-v4-flash") => {
|
||||
DEFAULT_VLLM_FLASH_MODEL.to_string()
|
||||
}
|
||||
(ProviderKind::Deepinfra, "deepseek-v4-pro" | "deepseek-v4pro") => {
|
||||
DEFAULT_DEEPINFRA_MODEL.to_string()
|
||||
}
|
||||
(ProviderKind::Deepinfra, "deepseek-v4-flash" | "deepseek-chat" | "deepseek-reasoner") => {
|
||||
DEFAULT_DEEPINFRA_FLASH_MODEL.to_string()
|
||||
}
|
||||
(
|
||||
ProviderKind::Deepinfra,
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-chat" | "deepseek-reasoner",
|
||||
) => DEFAULT_DEEPINFRA_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Together, "deepseek-v4-pro" | "deepseek-v4pro") => {
|
||||
DEFAULT_TOGETHER_MODEL.to_string()
|
||||
}
|
||||
(
|
||||
ProviderKind::Together,
|
||||
"deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat" | "deepseek-reasoner",
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4flash" | "deepseek-chat"
|
||||
| "deepseek-reasoner",
|
||||
) => DEFAULT_TOGETHER_FLASH_MODEL.to_string(),
|
||||
(ProviderKind::Together, "inkling" | "together-inkling" | "thinkingmachines/inkling") => {
|
||||
TOGETHER_INKLING_MODEL.to_string()
|
||||
|
||||
@@ -7549,20 +7549,17 @@ fn normalize_model_name_preserves_v_series_snapshots() {
|
||||
);
|
||||
assert_eq!(
|
||||
normalize_model_name("flash").as_deref(),
|
||||
Some("deepseek-v4-flash")
|
||||
Some("deepseek-flash")
|
||||
);
|
||||
for alias in ["flash-vision", "deepseek-v4flashvisionexp"] {
|
||||
assert_eq!(
|
||||
canonical_model_name(alias),
|
||||
Some("deepseek-v4-flash-vision-exp")
|
||||
);
|
||||
assert_eq!(canonical_model_name(alias), Some("deepseek-flash"));
|
||||
assert_eq!(
|
||||
normalize_model_name(alias).as_deref(),
|
||||
Some("deepseek-v4-flash-vision-exp")
|
||||
Some("deepseek-flash")
|
||||
);
|
||||
assert_eq!(
|
||||
normalize_model_name_for_provider(ProviderKind::Deepseek, alias).as_deref(),
|
||||
Some("deepseek-v4-flash-vision-exp")
|
||||
Some("deepseek-flash")
|
||||
);
|
||||
assert!(validate_route(ProviderKind::Deepseek, alias).is_ok());
|
||||
}
|
||||
@@ -8124,7 +8121,7 @@ fn normalize_model_name_for_provider_maps_recent_openrouter_aliases() {
|
||||
fn normalize_xiaomi_mimo_aliases_for_provider() {
|
||||
assert_eq!(
|
||||
normalize_model_name_for_provider(ProviderKind::XiaomiMimo, "omni").as_deref(),
|
||||
Some("mimo-v2.5")
|
||||
Some("mimo-v2.6-flash")
|
||||
);
|
||||
assert_eq!(
|
||||
normalize_model_name_for_provider(ProviderKind::XiaomiMimo, "tts").as_deref(),
|
||||
@@ -8146,7 +8143,7 @@ fn model_completion_scenario() {
|
||||
// from model_completion_names_for_xiaomi_mimo_include_chat_models
|
||||
{
|
||||
let models = model_completion_names_for_provider(ProviderKind::XiaomiMimo);
|
||||
for expected in ["mimo-v2.5-pro", "mimo-v2.5"] {
|
||||
for expected in ["mimo-v2.6-pro", "mimo-v2.6-flash"] {
|
||||
assert!(models.contains(&expected), "missing {expected}");
|
||||
}
|
||||
for deprecated in ["mimo-v2-pro", "mimo-v2-omni", "mimo-v2-flash"] {
|
||||
@@ -8294,10 +8291,6 @@ fn model_completion_scenario_2() {
|
||||
|
||||
for expected in [
|
||||
DEFAULT_MINIMAX_MODEL,
|
||||
MINIMAX_M2_7_MODEL,
|
||||
MINIMAX_M2_7_HIGHSPEED_MODEL,
|
||||
MINIMAX_M2_5_MODEL,
|
||||
MINIMAX_M2_5_HIGHSPEED_MODEL,
|
||||
MINIMAX_M2_1_MODEL,
|
||||
MINIMAX_M2_1_HIGHSPEED_MODEL,
|
||||
MINIMAX_M2_MODEL,
|
||||
@@ -8314,7 +8307,7 @@ fn model_completion_scenario_2() {
|
||||
let models = model_completion_names_for_provider(ProviderKind::MinimaxAnthropic);
|
||||
|
||||
assert!(models.contains(&DEFAULT_MINIMAX_MODEL));
|
||||
assert!(models.contains(&MINIMAX_M2_7_MODEL));
|
||||
assert!(models.contains(&MINIMAX_M2_1_MODEL));
|
||||
}
|
||||
// from model_completion_names_for_sakana_include_fugu_models
|
||||
{
|
||||
@@ -9226,7 +9219,7 @@ fn xiaomi_mimo_scenario() -> Result<()> {
|
||||
config.active_provider_identity().unwrap().provider,
|
||||
ProviderKind::XiaomiMimo
|
||||
);
|
||||
assert_eq!(config.default_model(), "mimo-v2.5");
|
||||
assert_eq!(config.default_model(), "mimo-v2.6-flash");
|
||||
assert_eq!(
|
||||
config.active_route_base_url(),
|
||||
"https://token-plan-cn.xiaomimimo.com/v1"
|
||||
@@ -9401,7 +9394,7 @@ default_text_model = "deepseek/deepseek-v4-pro"
|
||||
[providers.xiaomi]
|
||||
api_key = "mimo-table-key"
|
||||
base_url = "https://token-plan-sgp.xiaomimimo.com/v1"
|
||||
model = "mimo-v2.5-pro"
|
||||
model = "mimo-v2.6-pro"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
@@ -9428,7 +9421,7 @@ provider = "xiaomi-mimo"
|
||||
[providers.xiaomi_mimo]
|
||||
api_key = "tp-test-token-plan-key"
|
||||
base_url = "https://api.xiaomimimo.com/v1"
|
||||
model = "mimo-v2.5-pro"
|
||||
model = "mimo-v2.6-pro"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
@@ -12746,7 +12739,7 @@ fn provider_capability_scenario() {
|
||||
.as_ref()
|
||||
.expect("alias deprecation metadata");
|
||||
assert_eq!(deprecation.alias, "deepseek-chat");
|
||||
assert_eq!(deprecation.replacement, "deepseek-v4-flash");
|
||||
assert_eq!(deprecation.replacement, "deepseek-flash");
|
||||
assert_eq!(deprecation.retirement_date, "2026-07-24");
|
||||
assert_eq!(deprecation.retirement_utc, "2026-07-24T15:59:00Z");
|
||||
}
|
||||
@@ -12766,7 +12759,7 @@ fn provider_capability_scenario() {
|
||||
.as_ref()
|
||||
.expect("alias deprecation metadata");
|
||||
assert_eq!(deprecation.alias, "deepseek-reasoner");
|
||||
assert_eq!(deprecation.replacement, "deepseek-v4-flash");
|
||||
assert_eq!(deprecation.replacement, "deepseek-flash");
|
||||
}
|
||||
// from provider_capability_deepseek_v4_flash_has_no_alias_deprecation
|
||||
{
|
||||
@@ -12834,7 +12827,7 @@ fn provider_capability_scenario_2() {
|
||||
// from provider_capability_xiaomi_mimo_has_thinking_no_cache
|
||||
{
|
||||
let cap = provider_capability(ProviderKind::XiaomiMimo, DEFAULT_XIAOMI_MIMO_MODEL);
|
||||
assert_eq!(cap.context_window, 1_000_000);
|
||||
assert_eq!(cap.context_window, 1_048_576);
|
||||
assert_eq!(cap.max_output, Some(131_072));
|
||||
assert!(cap.thinking_supported);
|
||||
assert!(!cap.cache_telemetry_supported);
|
||||
@@ -12843,8 +12836,8 @@ fn provider_capability_scenario_2() {
|
||||
RequestPayloadMode::ChatCompletions
|
||||
);
|
||||
|
||||
let omni = provider_capability(ProviderKind::XiaomiMimo, XIAOMI_MIMO_V2_5_OMNI_MODEL);
|
||||
assert_eq!(omni.context_window, 1_000_000);
|
||||
let omni = provider_capability(ProviderKind::XiaomiMimo, XIAOMI_MIMO_V2_6_FLASH_MODEL);
|
||||
assert_eq!(omni.context_window, 1_048_576);
|
||||
assert_eq!(omni.max_output, Some(131_072));
|
||||
assert!(omni.thinking_supported);
|
||||
assert!(!omni.cache_telemetry_supported);
|
||||
|
||||
@@ -1543,9 +1543,15 @@ fn execute_tool_search_inner(
|
||||
};
|
||||
|
||||
let mut cache_rejected = Vec::new();
|
||||
let mut evicted = Vec::new();
|
||||
if let Some(cache) = cache {
|
||||
let delta = cache.activate(catalog, &discovered);
|
||||
remove_evicted_cache_activations(catalog, active_tools, delta.evicted);
|
||||
remove_evicted_cache_activations(catalog, active_tools, delta.evicted.iter().cloned());
|
||||
evicted = delta
|
||||
.evicted
|
||||
.into_iter()
|
||||
.filter(|name| !active_tools.contains(name))
|
||||
.collect();
|
||||
cache_rejected = delta.rejected;
|
||||
discovered = delta.admitted;
|
||||
}
|
||||
@@ -1575,19 +1581,33 @@ fn execute_tool_search_inner(
|
||||
})
|
||||
}));
|
||||
|
||||
let payload = json!({
|
||||
let mut payload = json!({
|
||||
"type": "tool_search_tool_search_result",
|
||||
"tool_references": references,
|
||||
"unavailable_tool_references": unavailable_references.clone(),
|
||||
});
|
||||
let mut metadata = json!({
|
||||
"tool_references": discovered,
|
||||
"unavailable_tool_references": unavailable_references,
|
||||
});
|
||||
if !evicted.is_empty() {
|
||||
payload["evicted_tool_references"] = evicted
|
||||
.iter()
|
||||
.map(|name| {
|
||||
json!({
|
||||
"type": "evicted_tool_reference",
|
||||
"tool_name": name,
|
||||
"reason": "No longer in this conversation's bounded toolbox (8 cached tools, 16KiB of added serialized schemas), so it is not callable now. Search for it again before using it."
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
metadata["evicted_tool_references"] = json!(evicted);
|
||||
}
|
||||
|
||||
Ok(ToolResult {
|
||||
content: serde_json::to_string(&payload).unwrap_or_else(|_| payload.to_string()),
|
||||
success: true,
|
||||
metadata: Some(json!({
|
||||
"tool_references": discovered,
|
||||
"unavailable_tool_references": unavailable_references,
|
||||
})),
|
||||
metadata: Some(metadata),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -166,11 +166,11 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn unpinned_scout_gets_verified_catalog_companion_or_inherits() {
|
||||
// DeepSeek's documented cheap sibling is deepseek-v4-flash and it is
|
||||
// DeepSeek's documented cheap sibling is deepseek-flash and it is
|
||||
// in the bundled catalog — a verified suggestion.
|
||||
let resolution = resolve_scout_route(None, "deepseek", "deepseek-v4-pro");
|
||||
assert_eq!(resolution.provider, "deepseek");
|
||||
assert_eq!(resolution.model, "deepseek-v4-flash");
|
||||
assert_eq!(resolution.model, "deepseek-flash");
|
||||
assert_eq!(resolution.source, ScoutSource::CatalogSuggestion);
|
||||
|
||||
// Anthropic's Claude models have a documented cheap sibling
|
||||
@@ -224,7 +224,7 @@ mod tests {
|
||||
fn receipt_line_names_the_source() {
|
||||
let resolution = resolve_scout_route(None, "deepseek", "deepseek-v4-pro");
|
||||
let line = resolution.receipt_line();
|
||||
assert!(line.contains("deepseek-v4-flash"), "{line}");
|
||||
assert!(line.contains("deepseek-flash"), "{line}");
|
||||
assert!(line.contains("catalog suggestion"), "{line}");
|
||||
}
|
||||
}
|
||||
@@ -16499,14 +16499,11 @@ mod doctor_endpoint_tests {
|
||||
|
||||
let report = provider_capability_report(&config);
|
||||
|
||||
assert_eq!(report["resolved_model"], "deepseek-v4-flash");
|
||||
assert_eq!(report["resolved_model"], "deepseek-flash");
|
||||
assert_eq!(report["context_window"], 1_000_000);
|
||||
assert_eq!(report["thinking_supported"], true);
|
||||
assert_eq!(report["alias_deprecation"]["alias"], "deepseek-chat");
|
||||
assert_eq!(
|
||||
report["alias_deprecation"]["replacement"],
|
||||
"deepseek-v4-flash"
|
||||
);
|
||||
assert_eq!(report["alias_deprecation"]["replacement"], "deepseek-flash");
|
||||
assert_eq!(
|
||||
report["alias_deprecation"]["retirement_utc"],
|
||||
"2026-07-24T15:59:00Z"
|
||||
|
||||
@@ -472,7 +472,7 @@ impl ModelInventory {
|
||||
(
|
||||
ProviderKind::Deepseek,
|
||||
None,
|
||||
"deepseek-v4-flash".to_string(),
|
||||
"deepseek-flash".to_string(),
|
||||
None,
|
||||
)
|
||||
});
|
||||
|
||||
@@ -39,7 +39,7 @@ impl RouterCandidates {
|
||||
pub(crate) fn deepseek() -> Self {
|
||||
Self {
|
||||
big: "deepseek-v4-pro".to_string(),
|
||||
cheap: Some("deepseek-v4-flash".to_string()),
|
||||
cheap: Some("deepseek-flash".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,12 +65,16 @@ fn catalog_family_candidates(
|
||||
ProviderKind::Anthropic
|
||||
if matches!(
|
||||
lower.as_str(),
|
||||
"claude-opus-4-8" | "claude-sonnet-4-6" | "claude-sonnet-5"
|
||||
"claude-opus-4-8"
|
||||
| "claude-sonnet-4-6"
|
||||
| "claude-sonnet-5"
|
||||
| "claude-opus-5-5"
|
||||
| "claude-sonnet-5-5"
|
||||
) =>
|
||||
{
|
||||
Some("claude-haiku-4-5".to_string())
|
||||
}
|
||||
ProviderKind::XiaomiMimo if lower == "mimo-v2.5-pro" => Some("mimo-v2.5".to_string()),
|
||||
ProviderKind::XiaomiMimo if lower == "mimo-v2.6-pro" => Some("mimo-v2.6-flash".to_string()),
|
||||
ProviderKind::Arcee
|
||||
if matches!(
|
||||
lower.as_str(),
|
||||
@@ -2798,7 +2802,7 @@ mod tests {
|
||||
AutoRouteDataPath::Classifier {
|
||||
provider: "deepseek".into(),
|
||||
provider_kind: ProviderKind::Deepseek,
|
||||
model: "deepseek-v4-flash".to_string(),
|
||||
model: "deepseek-flash".to_string(),
|
||||
}
|
||||
);
|
||||
assert_eq!(receipt.reason, AutoRouteReason::ClassifierRecommendation);
|
||||
@@ -2973,7 +2977,7 @@ mod tests {
|
||||
ref provider,
|
||||
ref model,
|
||||
..
|
||||
} if provider.as_str() == "deepseek" && model == "deepseek-v4-flash"
|
||||
} if provider.as_str() == "deepseek" && model == "deepseek-flash"
|
||||
));
|
||||
assert_eq!(
|
||||
receipt.reason,
|
||||
@@ -3184,7 +3188,7 @@ mod tests {
|
||||
|
||||
let deepseek = provider_router_candidates(ProviderKind::Deepseek, "deepseek-v4-pro");
|
||||
assert_eq!(deepseek.big, "deepseek-v4-pro");
|
||||
assert_eq!(deepseek.cheap.as_deref(), Some("deepseek-v4-flash"));
|
||||
assert_eq!(deepseek.cheap.as_deref(), Some("deepseek-flash"));
|
||||
|
||||
let openrouter =
|
||||
provider_router_candidates(ProviderKind::Openrouter, "deepseek/deepseek-v4-pro");
|
||||
@@ -3260,7 +3264,7 @@ mod tests {
|
||||
"claude-sonnet-4-6",
|
||||
"claude-haiku-4-5",
|
||||
),
|
||||
(ProviderKind::XiaomiMimo, "mimo-v2.5-pro", "mimo-v2.5"),
|
||||
(ProviderKind::XiaomiMimo, "mimo-v2.6-pro", "mimo-v2.6-flash"),
|
||||
(
|
||||
ProviderKind::Arcee,
|
||||
"trinity-large-thinking",
|
||||
@@ -3763,7 +3767,7 @@ mod decision_router_tests {
|
||||
let raw = String::from_utf8(requests[0].body.clone()).expect("utf8 body");
|
||||
assert!(!raw.contains(TYPESAFE_TEST_KEY), "TypeSafe key leaked");
|
||||
|
||||
assert_eq!(selection.model, "deepseek-v4-flash");
|
||||
assert_eq!(selection.model, "deepseek-flash");
|
||||
let receipt = receipt(&selection);
|
||||
assert_eq!(receipt.reason, AutoRouteReason::ClassifierRecommendation);
|
||||
assert_eq!(
|
||||
|
||||
+53
-18
@@ -14,8 +14,8 @@ use codewhale_config::pricing::{
|
||||
#[cfg(test)]
|
||||
use crate::config::DEFAULT_STEPFUN_MODEL;
|
||||
use crate::config::{
|
||||
DEEPSEEK_ALIAS_REPLACEMENT, DEEPSEEK_ALIAS_RETIREMENT_UTC, DEFAULT_STEPFUN_BASE_URL,
|
||||
DEFAULT_STEPFUN_PLAN_BASE_URL, ProviderKind, canonical_model_id_for_provider,
|
||||
DEEPSEEK_ALIAS_RETIREMENT_UTC, DEFAULT_STEPFUN_BASE_URL, DEFAULT_STEPFUN_PLAN_BASE_URL,
|
||||
ProviderKind, canonical_model_id_for_provider,
|
||||
};
|
||||
use codewhale_models::{Usage, has_date_snapshot_suffix};
|
||||
|
||||
@@ -721,10 +721,16 @@ fn pricing_for_model_at(model: &str, now: DateTime<Utc>) -> Option<ModelPricing>
|
||||
}
|
||||
// A new or expiring model ID does not inherit a neighboring model's
|
||||
// rates. Keep this metadata lookup as exact as the billing route owner.
|
||||
match lower.as_str() {
|
||||
deepseek_time_aware_pricing(&lower, now)
|
||||
}
|
||||
|
||||
fn deepseek_time_aware_pricing(model_lower: &str, now: DateTime<Utc>) -> Option<ModelPricing> {
|
||||
match model_lower {
|
||||
"deepseek-v4-pro" => Some(deepseek_v4_pro_pricing(now)),
|
||||
"deepseek-v4-flash" => Some(deepseek_v4_flash_pricing(now)),
|
||||
"deepseek-flash" => Some(deepseek_flash_pricing(now)),
|
||||
"deepseek-v4-flash" | "deepseek-flash" => Some(deepseek_v4_flash_pricing(now)),
|
||||
"deepseek-v4-flash-vision-exp" => {
|
||||
(now >= deepseek_flash_effective_from()).then(|| deepseek_flash_pricing(now))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -821,6 +827,9 @@ fn direct_openai_long_context_tier_is_unpriced(
|
||||
| "gpt-5.6-sol"
|
||||
| "gpt-5.6-terra"
|
||||
| "gpt-5.6-luna"
|
||||
| "gpt-6-sol"
|
||||
| "gpt-6.1-sol"
|
||||
| "gpt-6-luna"
|
||||
) || has_date_snapshot_suffix(&model_lower, "gpt-5.4-")
|
||||
|| has_date_snapshot_suffix(&model_lower, "gpt-5.4-pro-")
|
||||
|| has_date_snapshot_suffix(&model_lower, "gpt-5.5-");
|
||||
@@ -965,11 +974,7 @@ fn deepseek_is_peak(now: DateTime<Utc>) -> bool {
|
||||
#[must_use]
|
||||
pub(crate) fn deepseek_time_tier(model: &str, now: DateTime<Utc>) -> Option<bool> {
|
||||
let lower = model.trim().to_ascii_lowercase();
|
||||
matches!(
|
||||
lower.as_str(),
|
||||
"deepseek-v4-pro" | "deepseek-v4-flash" | "deepseek-flash"
|
||||
)
|
||||
.then(|| deepseek_is_peak(now))
|
||||
deepseek_time_aware_pricing(&lower, now).map(|_| deepseek_is_peak(now))
|
||||
}
|
||||
|
||||
fn deepseek_v4_pro_pricing(now: DateTime<Utc>) -> ModelPricing {
|
||||
@@ -1045,7 +1050,16 @@ fn deepseek_flash_pricing(now: DateTime<Utc>) -> ModelPricing {
|
||||
}
|
||||
}
|
||||
|
||||
fn deepseek_flash_effective_from() -> DateTime<Utc> {
|
||||
Utc.with_ymd_and_hms(2026, 9, 10, 4, 0, 0)
|
||||
.single()
|
||||
.expect("2026-09-10T04:00Z is a valid UTC instant")
|
||||
}
|
||||
|
||||
fn deepseek_v4_flash_pricing(now: DateTime<Utc>) -> ModelPricing {
|
||||
if now >= deepseek_flash_effective_from() {
|
||||
return deepseek_flash_pricing(now);
|
||||
}
|
||||
let peak = deepseek_is_peak(now);
|
||||
let (hit, miss, out) = if peak {
|
||||
(0.014, 0.44, 1.32)
|
||||
@@ -1566,7 +1580,15 @@ fn audit_turn_cost_for_provider_on_endpoint_for_identity_at(
|
||||
if recorded_at >= retirement.with_timezone(&Utc) {
|
||||
return TurnCostAudit::unpriced(UnpricedReason::RetiredAlias);
|
||||
}
|
||||
DEEPSEEK_ALIAS_REPLACEMENT.to_string()
|
||||
"deepseek-v4-flash".to_string()
|
||||
} else if direct_deepseek
|
||||
&& matches!(
|
||||
model_lower.as_str(),
|
||||
"flash-vision" | "deepseek-v4flashvisionexp"
|
||||
)
|
||||
&& recorded_at < deepseek_flash_effective_from()
|
||||
{
|
||||
"deepseek-v4-flash-vision-exp".to_string()
|
||||
} else {
|
||||
canonical_model
|
||||
};
|
||||
@@ -2361,7 +2383,10 @@ fn provider_owned_hand_pricing_at(
|
||||
// just because DeepSeek does.
|
||||
matches!(
|
||||
model_lower.as_str(),
|
||||
"deepseek-v4-pro" | "deepseek-v4-flash" | "deepseek-flash"
|
||||
"deepseek-v4-pro"
|
||||
| "deepseek-v4-flash"
|
||||
| "deepseek-v4-flash-vision-exp"
|
||||
| "deepseek-flash"
|
||||
)
|
||||
}
|
||||
ProviderKind::Openai => matches!(
|
||||
@@ -2374,6 +2399,9 @@ fn provider_owned_hand_pricing_at(
|
||||
| "gpt-5.6-sol"
|
||||
| "gpt-5.6-terra"
|
||||
| "gpt-5.6-luna"
|
||||
| "gpt-6-sol"
|
||||
| "gpt-6.1-sol"
|
||||
| "gpt-6-luna"
|
||||
),
|
||||
ProviderKind::Anthropic => matches!(
|
||||
model_lower.as_str(),
|
||||
@@ -2383,6 +2411,9 @@ fn provider_owned_hand_pricing_at(
|
||||
| "claude-fable-5"
|
||||
| "claude-sonnet-5"
|
||||
| "claude-opus-5"
|
||||
| "claude-opus-5-5"
|
||||
| "claude-sonnet-5-5"
|
||||
| "claude-fable-5-1"
|
||||
),
|
||||
ProviderKind::Xai => is_grok_tiered(&model_lower),
|
||||
// GLM-5.3 is deliberately absent: this allowlist declares that Z.ai
|
||||
@@ -2419,13 +2450,17 @@ fn provider_owned_hand_pricing_at(
|
||||
| "codestral"
|
||||
),
|
||||
ProviderKind::Arcee => model_lower == "trinity-large-thinking",
|
||||
// 1.2 and its contributor tier own hand-written rows the same way 1.1
|
||||
// does (see `pricing_for_model_at`). 1.2 is now `DEFAULT_META_MODEL`,
|
||||
// so omitting them here left the default Meta route without a
|
||||
// Every Muse tier owns a hand-written row the same way 1.1 does (see
|
||||
// `pricing_for_model_at`), so `DEFAULT_META_MODEL` (1.3) always has a
|
||||
// provider-owned fallback row.
|
||||
ProviderKind::Meta => matches!(
|
||||
model_lower.as_str(),
|
||||
"muse-spark-1.1" | "muse-spark-1.2" | "muse-spark-1.2-contributor"
|
||||
"muse-spark-1.1"
|
||||
| "muse-spark-1.2"
|
||||
| "muse-spark-1.2-contributor"
|
||||
| "muse-spark-1.3"
|
||||
| "muse-spark-1.3-contributor"
|
||||
| "muse-wonder-1.0"
|
||||
),
|
||||
// Deployment-style ids (Fireworks account prefix, OpenCode Zen
|
||||
// gateway) have no Models.dev cost fields. When the live control
|
||||
@@ -2465,7 +2500,7 @@ fn provider_owned_hand_pricing_at(
|
||||
/// DeepSeek's $0.0028 cache-hit card — Fireworks publishes $0.028.
|
||||
fn fireworks_bundled_fallback_pricing(model_lower: &str) -> Option<ModelPricing> {
|
||||
match fireworks_deployment_id(model_lower) {
|
||||
"deepseek-v4-flash" | "deepseek-v4-flash-0731" => {
|
||||
"deepseek-flash" | "deepseek-v4-flash" | "deepseek-v4-flash-0731" => {
|
||||
Some(hosted_deepseek_v4_flash_standard_pricing())
|
||||
}
|
||||
"deepseek-v4-pro" => Some(hosted_deepseek_v4_pro_standard_pricing()),
|
||||
@@ -4331,7 +4366,7 @@ mod tests {
|
||||
|
||||
for (provider, model) in [
|
||||
(ProviderKind::Zai, "GLM-5.3"),
|
||||
(ProviderKind::XiaomiMimo, "mimo-v2.5-pro"),
|
||||
(ProviderKind::XiaomiMimo, "mimo-v2.6-pro"),
|
||||
(ProviderKind::ModelstudioTokenPlan, "qwen3.8-max"),
|
||||
] {
|
||||
let offering =
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
["sglang", "deepseek-ai/DeepSeek-V4-Pro", "http://localhost:30000/v1", "chat_completions", "local"],
|
||||
["vllm", "deepseek-ai/DeepSeek-V4-Pro", "http://localhost:8000/v1", "chat_completions", "local"],
|
||||
["volcengine", "DeepSeek-V4-Pro", "https://ark.cn-beijing.volces.com/api/coding/v3", "chat_completions", "subscription"],
|
||||
["xiaomi-mimo", "mimo-v2.5-pro", "https://token-plan-sgp.xiaomimimo.com/v1", "chat_completions", "subscription"],
|
||||
["xiaomi-mimo", "mimo-v2.6-pro", "https://token-plan-sgp.xiaomimimo.com/v1", "chat_completions", "subscription"],
|
||||
["zai", "GLM-5.3", "https://api.z.ai/api/coding/paas/v4", "chat_completions", "subscription"]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -990,6 +990,7 @@ async fn settle_prepared_history_operation(
|
||||
})
|
||||
.await?;
|
||||
if let Some((saved, _target_lease)) = saved {
|
||||
runtime.admit_history_execution().await?;
|
||||
let from = witness.seed_from_message_index;
|
||||
ensure!(
|
||||
from <= saved.messages.len(),
|
||||
@@ -1101,6 +1102,7 @@ async fn mutate_in_owner(
|
||||
return Ok(receipt);
|
||||
}
|
||||
}
|
||||
runtime.admit_history_execution().await?;
|
||||
let is_resume = matches!(&request.mutation, CanonicalThreadMutation::Resume { .. });
|
||||
let mut create = CreateThreadRequest::default();
|
||||
let mut source_thread = None;
|
||||
@@ -1238,48 +1240,65 @@ async fn mutate_in_owner(
|
||||
.saved_session_checkpoint
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("saved holder checkpoint is missing"))?;
|
||||
// The checkpoint records the history the holder was
|
||||
// seeded with; turns the holder ran since then extend the
|
||||
// document past it. Like the other checkpoint guards here,
|
||||
// require it to cover a prefix, and let the exact
|
||||
// live == document check below prove that everything
|
||||
// after that prefix came from this holder. Requiring full
|
||||
// coverage refused every second resume of a continued
|
||||
// session.
|
||||
ensure!(
|
||||
crate::runtime_threads::checkpoint_prefix_len(
|
||||
checkpoint,
|
||||
&observed.messages
|
||||
)?
|
||||
.is_some(),
|
||||
"saved holder checkpoint differs from the saved history; refresh history"
|
||||
);
|
||||
let full = snapshot_in_runtime(&runtime, &sessions_dir, thread.id.clone())
|
||||
.await
|
||||
.map_err(|error| anyhow!(error.message))?;
|
||||
let live: SavedSession = serde_json::from_value(full.session)?;
|
||||
if live.messages == observed.messages && live.journal == observed.journal {
|
||||
source_thread = Some(thread);
|
||||
} else if live.messages.len() < observed.messages.len()
|
||||
&& observed.messages.starts_with(&live.messages)
|
||||
{
|
||||
// After a resume the TUI runs its turns in its own
|
||||
// engine and saves them to the document; this holder
|
||||
// stayed at the history it was seeded with. It is
|
||||
// strictly behind the document and has no live work
|
||||
// (checked above), so it holds nothing the document
|
||||
// lacks: release its binding (receipt kept, turns
|
||||
// kept) and mount the document fresh. Refusing here
|
||||
// made every continued session impossible to resume
|
||||
// a second time.
|
||||
runtime.release_stale_session_holder(
|
||||
&thread,
|
||||
"the saved document advanced past this thread after a resume",
|
||||
)?;
|
||||
let covered = crate::runtime_threads::checkpoint_prefix_len(
|
||||
checkpoint,
|
||||
&observed.messages,
|
||||
)?;
|
||||
let released = if crate::runtime_threads::checkpoint_covers_every_turn(
|
||||
checkpoint,
|
||||
&detail.turns,
|
||||
) {
|
||||
match covered {
|
||||
Some(len) if len == observed.messages.len() => {
|
||||
source_thread = Some(thread);
|
||||
None
|
||||
}
|
||||
Some(_) => Some((
|
||||
thread,
|
||||
"the saved document advanced past this thread after a resume",
|
||||
)),
|
||||
None => Some((
|
||||
thread,
|
||||
"the saved document's head was rewritten after this thread's checkpoint",
|
||||
)),
|
||||
}
|
||||
} else {
|
||||
bail!(
|
||||
"saved holder has a successor outside the selected document; refresh history"
|
||||
ensure!(
|
||||
covered.is_some(),
|
||||
"saved holder checkpoint differs from the saved history; refresh history"
|
||||
);
|
||||
let full = snapshot_in_runtime(&runtime, &sessions_dir, thread.id.clone())
|
||||
.await
|
||||
.map_err(|error| anyhow!(error.message))?;
|
||||
let live: SavedSession = serde_json::from_value(full.session)?;
|
||||
if live.messages == observed.messages && live.journal == observed.journal {
|
||||
source_thread = Some(thread);
|
||||
None
|
||||
} else if live.messages.len() < observed.messages.len()
|
||||
&& observed.messages.starts_with(&live.messages)
|
||||
{
|
||||
let fresh = runtime.get_thread(&thread.id).await?;
|
||||
ensure!(
|
||||
fresh.session_id == thread.session_id
|
||||
&& fresh.latest_turn_id == thread.latest_turn_id,
|
||||
"saved holder changed during admission; retry"
|
||||
);
|
||||
Some((
|
||||
fresh,
|
||||
"the saved document advanced past this thread after a resume",
|
||||
))
|
||||
} else {
|
||||
bail!(
|
||||
"saved holder has a successor outside the selected document; refresh history"
|
||||
);
|
||||
}
|
||||
};
|
||||
if let Some((holder, reason)) = released {
|
||||
let release_runtime = Arc::clone(&runtime);
|
||||
history_owner_work(move || {
|
||||
release_runtime.release_stale_session_holder(&holder, reason)
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
observed
|
||||
|
||||
@@ -931,6 +931,16 @@ pub(crate) fn checkpoint_prefix_len(
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub(crate) fn checkpoint_covers_every_turn(
|
||||
checkpoint: &SavedSessionCheckpoint,
|
||||
turns: &[TurnRecord],
|
||||
) -> bool {
|
||||
match checkpoint.covered_turn_id.as_deref() {
|
||||
Some(id) => turns.last().is_some_and(|turn| turn.id == id),
|
||||
None => turns.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// A thread's saved-session binding no longer describes any readable
|
||||
/// document: the document is gone, or its prefix is not the one the thread
|
||||
/// was bound to. The thread still owns its turns, so the binding is dropped
|
||||
@@ -16453,6 +16463,11 @@ impl RuntimeThreadManager {
|
||||
Ok(manager)
|
||||
}
|
||||
|
||||
pub(crate) async fn admit_history_execution(&self) -> Result<()> {
|
||||
self.ensure_accepting_execution()?;
|
||||
self.subagent_manager().await.map(drop)
|
||||
}
|
||||
|
||||
/// The thread's engine only when it is already live in this process.
|
||||
/// Control routes that act on in-flight work (stopping an agent run) use
|
||||
/// this: loading a cold engine cannot reach work that is not running here.
|
||||
@@ -16594,7 +16609,7 @@ impl RuntimeThreadManager {
|
||||
// The binding describes no readable document. The thread's
|
||||
// own turns are its history; drop the dead link (keeping it
|
||||
// in a receipt) instead of stranding the thread (#6144).
|
||||
self.unbind_stale_session(thread, &stale.reason)?;
|
||||
self.unbind_stale_session(thread, &stale.reason, false)?;
|
||||
(Vec::new(), 0)
|
||||
}
|
||||
};
|
||||
@@ -16603,15 +16618,22 @@ impl RuntimeThreadManager {
|
||||
}
|
||||
|
||||
/// Drop `thread`'s saved-session binding when the stored record still
|
||||
/// carries exactly the binding that was found stale, and record the old
|
||||
/// binding in the session reconcile receipts.
|
||||
fn unbind_stale_session(&self, thread: &ThreadRecord, reason: &str) -> Result<()> {
|
||||
/// carries exactly the binding that was found stale (and, with
|
||||
/// `pin_latest_turn`, the same latest turn), and record the old binding in
|
||||
/// the session reconcile receipts. Returns whether the binding was dropped.
|
||||
fn unbind_stale_session(
|
||||
&self,
|
||||
thread: &ThreadRecord,
|
||||
reason: &str,
|
||||
pin_latest_turn: bool,
|
||||
) -> Result<bool> {
|
||||
let _thread_mutation = self.store.thread_mutation.lock();
|
||||
let mut stored = self.store.load_thread(&thread.id)?;
|
||||
if stored.session_id != thread.session_id
|
||||
|| stored.saved_session_checkpoint != thread.saved_session_checkpoint
|
||||
|| (pin_latest_turn && stored.latest_turn_id != thread.latest_turn_id)
|
||||
{
|
||||
return Ok(());
|
||||
return Ok(false);
|
||||
}
|
||||
crate::session_reconcile::record_thread_unbound(
|
||||
&self.session_store_binding().data_dir,
|
||||
@@ -16621,18 +16643,24 @@ impl RuntimeThreadManager {
|
||||
stored.session_id = None;
|
||||
stored.saved_session_checkpoint = None;
|
||||
stored.updated_at = Utc::now();
|
||||
self.store.save_thread(&stored)
|
||||
self.store.save_thread(&stored)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Release a canonical holder whose saved document has moved past it, using
|
||||
/// the same compare-and-swap unbind and reconcile receipt as a stale
|
||||
/// binding found while restoring messages.
|
||||
/// Release a canonical holder that holds nothing its saved document lacks,
|
||||
/// using the same compare-and-swap unbind and reconcile receipt as a stale
|
||||
/// binding found while restoring messages. Fails when the stored record
|
||||
/// changed since `thread` was read.
|
||||
pub(crate) fn release_stale_session_holder(
|
||||
&self,
|
||||
thread: &ThreadRecord,
|
||||
reason: &str,
|
||||
) -> Result<()> {
|
||||
self.unbind_stale_session(thread, reason)
|
||||
anyhow::ensure!(
|
||||
self.unbind_stale_session(thread, reason, true)?,
|
||||
"saved holder changed during admission; retry"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Unbind every thread in this store that names `session_id` (#6144).
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::config::ProviderKind;
|
||||
#[cfg(test)]
|
||||
use crate::config::{DEEPSEEK_ALIAS_REPLACEMENT, DEEPSEEK_ALIAS_RETIREMENT_UTC};
|
||||
use crate::config::DEEPSEEK_ALIAS_RETIREMENT_UTC;
|
||||
use crate::config::ProviderKind;
|
||||
use crate::pricing::{
|
||||
CostEstimate, TurnCostAudit, audit_turn_cost_for_route_at, token_usage_for_pricing,
|
||||
};
|
||||
@@ -1537,7 +1537,7 @@ mod tests {
|
||||
created_at: Some(&before_retirement),
|
||||
provider: Some("deepseek"),
|
||||
billing_surface: Some(crate::pricing::FIRST_PARTY_PAYG_BILLING_SURFACE),
|
||||
model: DEEPSEEK_ALIAS_REPLACEMENT.into(),
|
||||
model: "deepseek-v4-flash".into(),
|
||||
usage: &u,
|
||||
},
|
||||
TurnInput {
|
||||
|
||||
@@ -7765,7 +7765,7 @@ fn subagent_model_strength_faster_uses_known_family_sibling() {
|
||||
SubAgentThinking::Inherit,
|
||||
);
|
||||
assert_eq!(route.model_route, ModelRoute::Faster);
|
||||
assert_eq!(route.model, "deepseek-v4-flash");
|
||||
assert_eq!(route.model, "deepseek-flash");
|
||||
assert_eq!(route.reasoning_effort.as_deref(), Some("off"));
|
||||
}
|
||||
|
||||
@@ -7797,7 +7797,7 @@ fn explicit_child_thinking_overrides_faster_default_off() {
|
||||
ModelRoute::Faster,
|
||||
SubAgentThinking::Effort(ReasoningEffort::High),
|
||||
);
|
||||
assert_eq!(route.model, "deepseek-v4-flash");
|
||||
assert_eq!(route.model, "deepseek-flash");
|
||||
assert_eq!(route.reasoning_effort.as_deref(), Some("high"));
|
||||
assert_eq!(route.tuning.reasoning_effort, Some(ReasoningEffort::High));
|
||||
}
|
||||
@@ -7847,7 +7847,7 @@ async fn route_resolution_matrix_uses_explicit_model_strength_routes() {
|
||||
configured_model: None,
|
||||
requested_route: ModelRoute::Faster,
|
||||
expected_route: ModelRoute::Faster,
|
||||
expected_model: "deepseek-v4-flash",
|
||||
expected_model: "deepseek-flash",
|
||||
expected_reasoning: Some("off"),
|
||||
expected_tuning_effort: Some(ReasoningEffort::Off),
|
||||
},
|
||||
@@ -17921,7 +17921,7 @@ fn faster_route_uses_known_deepseek_and_glm_family_siblings() {
|
||||
ModelRoute::Faster,
|
||||
SubAgentThinking::Inherit,
|
||||
);
|
||||
assert_eq!(route.model, "deepseek-v4-flash");
|
||||
assert_eq!(route.model, "deepseek-flash");
|
||||
|
||||
let mut zai = stub_runtime_for_provider("zai");
|
||||
zai.model = "GLM-5.2".to_string();
|
||||
|
||||
@@ -489,7 +489,7 @@ fn custom_router_help(config: &Config, locale: Locale) -> String {
|
||||
[auto.router]\n\
|
||||
kind = \"chat\" # or \"decision\" for Jev\n\
|
||||
provider = \"deepseek\" # decision: \"openrouter\" or \"typesafe\"\n\
|
||||
model = \"deepseek-v4-flash\"\n\
|
||||
model = \"deepseek-flash\"\n\
|
||||
thinking = \"off\" # chat routers only\n\
|
||||
timeout_secs = 4\n\
|
||||
# min_confidence = 0.5 # decision routers only\n\n\
|
||||
@@ -885,7 +885,7 @@ mod tests {
|
||||
.expect("fast writes a table");
|
||||
assert_eq!(fast.kind.as_deref(), Some("chat"));
|
||||
assert_eq!(fast.provider.as_deref(), Some("deepseek"));
|
||||
assert_eq!(fast.model.as_deref(), Some("deepseek-v4-flash"));
|
||||
assert_eq!(fast.model.as_deref(), Some("deepseek-flash"));
|
||||
assert_eq!(fast.thinking.as_deref(), Some("off"));
|
||||
|
||||
assert!(matches!(
|
||||
|
||||
@@ -2117,7 +2117,7 @@ If you are upgrading from older releases:
|
||||
- Old: `/codewhale`
|
||||
New: `/links` (aliases: `/dashboard`, `/api`)
|
||||
- Old: `/set model deepseek-reasoner`
|
||||
New: `/config` and edit the `model` row to `deepseek-v4-pro` or `deepseek-v4-flash`
|
||||
New: `/config` and edit the `model` row to `deepseek-v4-pro` or `deepseek-flash`
|
||||
- Old: visible `Normal` mode or `default_mode = "normal"`
|
||||
New: use `Agent` / `default_mode = "agent"`; legacy `normal` still maps to `agent`
|
||||
- Old: discover `/set` in slash UX/help
|
||||
@@ -2153,7 +2153,7 @@ reasoning contract, and all four membership ids omit generic sampling fields.
|
||||
- `reasoning_stream_style` (string, optional provider-table key): override how streaming reasoning is separated from answer text for the active provider route. Use `separate_field` for `reasoning_content` / `reasoning` deltas, `inline_tags` for gateways that stream `<think>...</think>` inside `delta.content`, or `none` to render incoming content exactly as answer text. When unset, every Chat Completions route uses `separate_field` (Mistral's first-party route uses its typed thinking blocks); set `none` only for a gateway that streams its answer inside `reasoning_content`.
|
||||
- `[providers.<name>.auth]` (table, optional): provider-scoped auth source metadata. `source = "command"` stores a command argv plus optional `timeout_ms`; `source = "secret"` stores a `secret_id`. This slice lets provider readiness, `/provider`, and doctor JSON report the auth source class without exposing command argv output or secret values; executing commands and resolving external secret material is handled by the follow-up resolver work.
|
||||
- `insecure_skip_tls_verify` (bool, optional provider-table key): legacy compatibility key, disabled by default. When true on the active provider table, provider clients reject the configuration instead of skipping TLS certificate verification. Use `SSL_CERT_FILE` for corporate or private CA bundles; `codewhale doctor` reports stale uses of this setting.
|
||||
- `default_text_model` (string, optional): defaults to `deepseek-flash` for DeepSeek and `deepseek-anthropic`, `gpt-5.6` for OpenAI, `grok-4.6` for xAI, `deepseek-ai/deepseek-v4-pro` for NVIDIA NIM, `deepseek-ai/deepseek-v4-flash` for AtlasCloud, `deepseek-reasoner` for Wanjie Ark, `DeepSeek-V4-Pro` for Volcengine Ark, `deepseek/deepseek-v4-pro` for OpenRouter and Novita, `mimo-v2.5-pro` for Xiaomi MiMo, `accounts/fireworks/models/deepseek-v4-pro` for Fireworks, `deepseek-ai/DeepSeek-V4-Pro` for SiliconFlow and DeepInfra, `trinity-large-thinking` for Arcee AI, `kimi-k2.7-code` for Moonshot, `MiniMax-M3` for MiniMax, `GLM-5.3` for Z.ai, `step-3.7-flash` for StepFun, `ernie-4.0-turbo-8k` for Qianfan, `fugu` for Sakana AI, `deepseek-ai/DeepSeek-V4-Pro` for SGLang/vLLM, no fixed id for local Ollama (Codewhale adopts a chat-capable tag from the live local catalog — coder or tool-capable tags first, then the largest context — and never an embedding or reranker model), and `gpt-oss:120b` for Ollama Cloud. Hugging Face and Together AI both default to `deepseek-ai/DeepSeek-V4-Pro`; `openai-codex` defaults to `gpt-5.6`; `anthropic` defaults to `claude-sonnet-4-6`; `openmodel` defaults to `deepseek-v4-flash`. Current public DeepSeek IDs include `deepseek-v4-pro` and `deepseek-flash` (V4.1 Flash, shipped as the unversioned id), both with 1M context windows, 384K max output, and thinking mode enabled by default. DeepSeek's live pricing/model page now labels the Pro backend `DeepSeek-V4-Pro-0813`; the callable API ID remains `deepseek-v4-pro`, so Codewhale does not send the backend label or the Claude Code-specific `deepseek-v4-pro[1m]` selector. DeepSeek retires `deepseek-chat` and `deepseek-reasoner` on July 24, 2026; direct first-party routes migrate both to `deepseek-v4-flash`, with omitted reasoning settings preserving their former non-thinking (`off`) and thinking (`high`) intent. Explicit `reasoning_effort` wins, and provider-owned ids on Wanjie Ark, aggregators, self-hosted runtimes, and custom endpoints are not globally rewritten. SiliconFlow retains its own mapping: `deepseek-reasoner` and `deepseek-r1` select its Pro model while `deepseek-chat` and `deepseek-v3` select Flash. Provider-specific mappings translate `deepseek-v4-pro` / `deepseek-v4-flash` to each provider's model ID where supported. OpenRouter also recognizes recent large IDs such as `arcee-ai/trinity-large-thinking`, `minimax/minimax-m3`, `minimax/minimax-m2.7`, `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`, `qwen/qwen3.7-max`, `google/gemma-4-31b-it`, `moonshotai/kimi-k2.7-code`, `moonshotai/kimi-k2.6`, `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free`, and `nvidia/nemotron-3-ultra-550b-a55b`; direct Arcee uses bare IDs such as `trinity-large-thinking` and `trinity-large-preview`; direct Moonshot recognizes `kimi-k3`, `kimi-k2.7-code`, and `kimi-k2.6`. The exact Kimi Code endpoint recognizes bare `k3` for K3 and `kimi-for-coding` for K2.7; those membership IDs are distinct from the direct Moonshot IDs and are never rewritten across routes. Direct MiniMax recognizes `MiniMax-M3` and the documented M2.x chat model IDs; direct Z.ai recognizes `GLM-5.3` (the default), `GLM-5.2`, `GLM-5.1`, and `GLM-5-Turbo`, and OpenRouter recognizes the matching `z-ai/glm-5.1`, `z-ai/glm-5.2`, `z-ai/glm-5.3`, and `z-ai/glm-5-turbo` IDs — `GLM-5.3` has been live on the Z.ai Coding Plan since 2026-08-13; it inherits its catalog metadata from `GLM-5.2` until Z.ai publishes distinct 5.3 numbers and carries no price, and an explicit `GLM-5.2` selection keeps its own id; direct Sakana recognizes `fugu` and `fugu-ultra-20260615`; direct Xiaomi MiMo recognizes chat IDs `mimo-v2.5-pro`, `mimo-v2.5-pro-ultraspeed`, and `mimo-v2.5`, while TTS IDs are selected through `codewhale speech` / `tts`. Generic `openai`, `atlascloud`, `wanjie-ark`, `xiaomi-mimo`, `arcee`, `moonshot`, `minimax`, `openmodel`, `zai`, `stepfun`, `qianfan`, `sakana`, local Ollama, and Ollama Cloud model IDs are passed through unchanged after known aliases are normalized. OpenRouter and SiliconFlow provider configs with a custom `base_url` also preserve explicit model values, which lets OpenAI-compatible gateways accept bare model IDs. Use `/models` or `codewhale models` to discover live IDs from your configured endpoint. `CODEWHALE_MODEL` overrides this for a single process; `DEEPSEEK_MODEL` is the legacy alias.
|
||||
- `default_text_model` (string, optional): defaults to `deepseek-flash` for DeepSeek and `deepseek-anthropic`, `gpt-5.6` for OpenAI, `grok-4.6` for xAI, `deepseek-ai/deepseek-v4-pro` for NVIDIA NIM, `deepseek-ai/deepseek-v4-flash` for AtlasCloud, `deepseek-reasoner` for Wanjie Ark, `DeepSeek-V4-Pro` for Volcengine Ark, `deepseek/deepseek-v4-pro` for OpenRouter and Novita, `mimo-v2.6-pro` for Xiaomi MiMo, `accounts/fireworks/models/deepseek-v4-pro` for Fireworks, `deepseek-ai/DeepSeek-V4-Pro` for SiliconFlow and DeepInfra, `trinity-large-thinking` for Arcee AI, `kimi-k2.7-code` for Moonshot, `MiniMax-M3` for MiniMax, `GLM-5.3` for Z.ai, `step-3.7-flash` for StepFun, `ernie-4.0-turbo-8k` for Qianfan, `fugu` for Sakana AI, `deepseek-ai/DeepSeek-V4-Pro` for SGLang/vLLM, no fixed id for local Ollama (Codewhale adopts a chat-capable tag from the live local catalog — coder or tool-capable tags first, then the largest context — and never an embedding or reranker model), and `gpt-oss:120b` for Ollama Cloud. Hugging Face and Together AI both default to `deepseek-ai/DeepSeek-V4-Pro`; `openai-codex` defaults to `gpt-5.6`; `anthropic` defaults to `claude-sonnet-4-6`; `openmodel` defaults to `deepseek-v4-flash`. Current public DeepSeek IDs include `deepseek-v4-pro` and `deepseek-flash` (V4.1 Flash, shipped as the unversioned id), both with 1M context windows, 384K max output, and thinking mode enabled by default. DeepSeek's live pricing/model page now labels the Pro backend `DeepSeek-V4-Pro-0813`; the callable API ID remains `deepseek-v4-pro`, so Codewhale does not send the backend label or the Claude Code-specific `deepseek-v4-pro[1m]` selector. DeepSeek retired `deepseek-chat` and `deepseek-reasoner` on July 24, 2026; direct first-party routes migrate both to `deepseek-flash`, with omitted reasoning settings preserving their former non-thinking (`off`) and thinking (`high`) intent. DeepSeek has also retired the `deepseek-v4-flash` and `deepseek-v4-flash-vision-exp` models: it still accepts both names, serves them with V4.1 Flash, and bills them at the `deepseek-flash` price, which Codewhale applies to turns from 2026-09-10 04:00 UTC. The `flash`, `deepseek-v4flash`, `flash-vision`, and `deepseek-v4flashvisionexp` shorthands select `deepseek-flash`. Explicit `reasoning_effort` wins, and provider-owned ids on Wanjie Ark, aggregators, self-hosted runtimes, and custom endpoints are not globally rewritten. SiliconFlow retains its own mapping: `deepseek-reasoner` and `deepseek-r1` select its Pro model while `deepseek-chat` and `deepseek-v3` select Flash. Provider-specific mappings translate `deepseek-v4-pro` / `deepseek-v4-flash` to each provider's model ID where supported. OpenRouter also recognizes recent large IDs such as `arcee-ai/trinity-large-thinking`, `minimax/minimax-m3`, `minimax/minimax-m2.7`, `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`, `qwen/qwen3.7-max`, `google/gemma-4-31b-it`, `moonshotai/kimi-k2.7-code`, `moonshotai/kimi-k2.6`, `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free`, and `nvidia/nemotron-3-ultra-550b-a55b`; direct Arcee uses bare IDs such as `trinity-large-thinking` and `trinity-large-preview`; direct Moonshot recognizes `kimi-k3`, `kimi-k2.7-code`, and `kimi-k2.6`. The exact Kimi Code endpoint recognizes bare `k3` for K3 and `kimi-for-coding` for K2.7; those membership IDs are distinct from the direct Moonshot IDs and are never rewritten across routes. Direct MiniMax recognizes `MiniMax-M3` and the documented M2.x chat model IDs; direct Z.ai recognizes `GLM-5.3` (the default), `GLM-5.2`, `GLM-5.1`, and `GLM-5-Turbo`, and OpenRouter recognizes the matching `z-ai/glm-5.1`, `z-ai/glm-5.2`, `z-ai/glm-5.3`, and `z-ai/glm-5-turbo` IDs — `GLM-5.3` has been live on the Z.ai Coding Plan since 2026-08-13; it inherits its catalog metadata from `GLM-5.2` until Z.ai publishes distinct 5.3 numbers and carries no price, and an explicit `GLM-5.2` selection keeps its own id; direct Sakana recognizes `fugu` and `fugu-ultra-20260615`; direct Xiaomi MiMo recognizes chat IDs `mimo-v2.6-pro`, `mimo-v2.6-flash`, and `mimo-v2.5-pro-ultraspeed` (the retired `mimo-v2.5-pro` and `mimo-v2.5` are sent as `mimo-v2.6-pro` and `mimo-v2.6-flash`), while TTS IDs are selected through `codewhale speech` / `tts`. Generic `openai`, `atlascloud`, `wanjie-ark`, `xiaomi-mimo`, `arcee`, `moonshot`, `minimax`, `openmodel`, `zai`, `stepfun`, `qianfan`, `sakana`, local Ollama, and Ollama Cloud model IDs are passed through unchanged after known aliases are normalized. OpenRouter and SiliconFlow provider configs with a custom `base_url` also preserve explicit model values, which lets OpenAI-compatible gateways accept bare model IDs. Use `/models` or `codewhale models` to discover live IDs from your configured endpoint. `CODEWHALE_MODEL` overrides this for a single process; `DEEPSEEK_MODEL` is the legacy alias.
|
||||
- TelecomJS uses `deepseek-v4-pro` only as a conservative pre-refresh fallback. Once its key-scoped `/models` catalog is available, the picker uses those live rows; Codewhale omits unsupported reasoning request fields on this route.
|
||||
- `reasoning_effort` (string, optional): `auto`, `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `ultra` (`ultracode` is an alias of `ultra`), or `max`; defaults to the configured UI tier. DeepSeek Platform receives top-level `thinking` / `reasoning_effort` fields. Ollama Cloud's OpenAI-compatible Chat Completions route preserves its documented `none` / `low` / `medium` / `high` / `max` ladder (`off` is sent as `none`; `xhigh` and `ultracode` normalize to `max`). Direct xAI `grok-4.7` and `grok-4.6` on exact `https://api.x.ai/v1` receive top-level `reasoning_effort = "low" | "medium" | "high" | "xhigh"` (the ladder comes from the bundled catalog row; `grok-4.5` maps `xhigh` to `high`, and rows without a documented effort such as `grok-4.3` get no field); Grok reasoning cannot be disabled, so `off` normalizes to `high`, `max`/`ultracode` to `xhigh`, and `auto` leaves the field omitted so xAI's documented default `high` applies. A custom xAI-compatible `base_url` does not inherit that dialect. Direct Moonshot `kimi-k3` on exact `https://api.moonshot.ai/v1` is always-thinking and receives only top-level `reasoning_effort = "low" | "high" | "max"`; `off` normalizes to `low`, and `medium` to `high`. Kimi Code membership `k3` on exact `https://api.kimi.com/coding/v1` instead receives nested `thinking.effort`, and its `off` setting also normalizes to enabled `low`. Normal dispatched `auto` uses Codewhale's auto-reasoning selector and sends a concrete route-normalized tier; only an omitted reasoning setting leaves the provider default in control. Neighboring gateways and model/endpoint combinations retain the generic Moonshot contract. OpenAI Codex normalizes stale `off` to `low` and sends `max` / `ultracode` as Responses `xhigh`. Z.ai receives documented `thinking` controls and treats enabled thinking as the GLM coding high/max lane. NVIDIA NIM receives equivalent settings through `chat_template_kwargs`.
|
||||
- `verbosity` (string, optional): `normal` or `concise`. `normal` keeps the
|
||||
|
||||
+1
-1
@@ -425,7 +425,7 @@ level per turn. When the DeepSeek routing model is available, Auto may select
|
||||
any runnable provider/model pair in the redacted inventory. That classification
|
||||
sends the latest request (capped at 4,000 characters) plus a bounded summary of
|
||||
up to six recent context rows (900 characters each) to
|
||||
`DeepSeek / deepseek-v4-flash`. Credentials, endpoints, and provider error text
|
||||
`DeepSeek / deepseek-flash`. Credentials, endpoints, and provider error text
|
||||
are not included in the inventory. Without that router, Auto uses a local,
|
||||
provider-aware heuristic and sends no routing request. If a classifier attempt
|
||||
fails validation or errors, Auto falls back to that heuristic while retaining
|
||||
|
||||
+29
-27
@@ -425,7 +425,7 @@ provider = "modelstudio-token-plan"
|
||||
[providers.modelstudio_token_plan]
|
||||
api_key = "YOUR_MODELSTUDIO_API_KEY"
|
||||
# base_url defaults to https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1
|
||||
model = "qwen3.8-max" # or qwen3.8-max-preview | qwen3.7-plus | qwen3.7-max |
|
||||
model = "qwen3.8-max" # or qwen3.7-plus | qwen3.7-max |
|
||||
# qwen3.6-flash | deepseek-v4-pro | deepseek-v4-flash-0731 |
|
||||
# glm-5.2
|
||||
```
|
||||
@@ -472,9 +472,8 @@ handed Alibaba's dialect. On a verified host:
|
||||
|
||||
- **Hybrid models** (`qwen3.7-*`, `qwen3.6-*`, `deepseek-v4*`, `glm-*`,
|
||||
`kimi-k2.6*`) get `enable_thinking`: `false` for `off`, `true` otherwise.
|
||||
- **Thinking-only models** — `qwen3.8-max` (catalogued `thinking: always_on`),
|
||||
`qwen3.8-max-preview` (effort/budget options, no toggle), and
|
||||
`kimi-k2.7-code` — get **no** enable/disable switch at all. Sending one is at
|
||||
- **Thinking-only models** — `qwen3.8-max` (catalogued `thinking: always_on`)
|
||||
and `kimi-k2.7-code` — get **no** enable/disable switch at all. Sending one is at
|
||||
best ignored.
|
||||
- `preserve_thinking` is sent for the models documented to accept it
|
||||
(`qwen3.7-max`/`-plus`, `qwen3.6-max-preview`/`-plus`/`-flash`, `kimi-k2.6*`,
|
||||
@@ -817,26 +816,26 @@ overlay and lets DSH resolve its own keys.
|
||||
|
||||
| Provider ID | TOML table | Auth env | Base URL env and default | Default or static models | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `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. |
|
||||
| `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`; 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, and no funded image round trip was made during this release work. DeepSeek has since retired both `deepseek-v4-flash` and the vision ID; it still accepts them, serves them with V4.1 Flash, and bills them at the `deepseek-flash` price, which Codewhale applies from 2026-09-10 04:00 UTC. The `flash`, `deepseek-v4flash`, `flash-vision`, and `deepseek-v4flashvisionexp` shorthands now select `deepseek-flash`. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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. The [GPT-6 family](https://developers.openai.com/api/docs/models/gpt-6-sol) (`gpt-6-sol`, `gpt-6.1-sol`, `gpt-6-luna`, `gpt-6-astra`) is not offered on this Chat Completions route because OpenAI does not support normal tool calling for them over Chat Completions. OpenAI has [deprecated](https://developers.openai.com/api/docs/deprecations) `gpt-5.3-codex` and `gpt-5.1` (replacement `gpt-6-sol`) and `gpt-5.4-nano` (replacement `gpt-6-luna`), all shutting down 2027-04-01, but those replacements need a Responses-wire OpenAI route here. Custom gateways remain free to select an explicit gateway-owned model. `OPENAI_MODEL` is accepted. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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`. |
|
||||
| `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. |
|
||||
| `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.6-pro` (default), `mimo-v2.6-flash`, `mimo-v2.5-pro-ultraspeed`; 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. Xiaomi [retires](https://mimo.mi.com/docs/updates/deprecate) `mimo-v2.5-pro` and `mimo-v2.5` at 2026-10-21 10:00 UTC+8; Codewhale sends `mimo-v2.6-pro` and `mimo-v2.6-flash` for those configured ids. `mimo-v2.6-pro` and `mimo-v2.6-flash` 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. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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`. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `zai` | `[providers.zai]` | `ZAI_API_KEY`, `Z_AI_API_KEY`, `ZHIPU_API_KEY`, `GLM_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. |
|
||||
| `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-4-argon`, `gemini-3-pro-preview`, `gemini-3.8-flash`, `gemini-3.6-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. Google [deprecated](https://ai.google.dev/gemini-api/docs/changelog) `gemini-3.7-flash` (served as `gemini-3.8-flash`) and `gemini-3.5-flash` (served as `gemini-3.6-flash`) on 2026-10-08; both ids stay accepted as selector aliases of their replacements. `gemini-4-argon` is paid-tier only. 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. |
|
||||
| `zai` | `[providers.zai]` | `ZAI_API_KEY`, `Z_AI_API_KEY`, `ZHIPU_API_KEY`, `GLM_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"`). `GLM-5.3-FlashX` is not offered because the Coding Plan endpoint this route defaults to does not serve it. 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. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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. MiniMax [closes](https://platform.minimax.io/docs/guides/models-intro) `MiniMax-M2.7`, `MiniMax-M2.7-highspeed`, `MiniMax-M2.5` and `MiniMax-M2.5-highspeed` to new users on 2026-10-19 and retires them on 2026-11-18; they are no longer in the fallback picker, stay accepted for existing configs until then, and `MiniMax-M3` remains the default. 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. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
@@ -848,13 +847,13 @@ overlay and lets DSH resolve its own keys.
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `openai-codex` | `[providers.openai_codex]` | Official Sign in with ChatGPT (`codewhale auth chatgpt` / `/provider setup openai-codex`) | Official `https://api.openai.com/v1` | Selected account catalog; configured model IDs remain explicit selections | **Experimental.** Public Responses endpoint (`/v1/responses`) with a validated `chatgpt.tokens.use.direct` grant. Dynamic OSS registration issues a client ID for the selected account/workspace; Codewhale protects and renews its own tokens. The account catalog supplies selectable models; public model lists and legacy Codex tokens do not establish plan permission. No silent billing fallback. See [Sign in with ChatGPT](#sign-in-with-chatgpt) for setup, usage limits, and preview boundaries. |
|
||||
| `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. |
|
||||
| `anthropic` | `[providers.anthropic]` | `ANTHROPIC_API_KEY` | `ANTHROPIC_BASE_URL`; default `https://api.anthropic.com` | `claude-opus-5-5`, `claude-sonnet-5-5`, `claude-fable-5-1`, `claude-sonnet-4-6` (default), `claude-haiku-5-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. The [current models](https://platform.claude.com/docs/en/about-claude/models/overview) have 1M context and 128K output; the auto-router's cheap tier stays `claude-haiku-4-5`; `claude-haiku-5-5` is selectable and priced from the catalog because its rate rises above 100,000 prompt tokens. Codewhale does not yet apply the 5.5 models' per-model request rules (Opus 5.5 and Sonnet 5.5 reject forced `tool_choice`; Sonnet 5.5 replaces disabled thinking with `between_tools`; Haiku 5.5 may reject `budget_tokens` and sampling parameters), so the default stays `claude-sonnet-4-6`. No default uses `claude-sonnet-4-5`, which [retires](https://platform.claude.com/docs/en/about-claude/model-deprecations) on 2026-11-30. `ANTHROPIC_MODEL` is accepted. |
|
||||
| `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. |
|
||||
| `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`. |
|
||||
| `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`. |
|
||||
| `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. |
|
||||
| `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.6` (default); current GPT, Claude, Qwen, DeepSeek, MiniMax, GLM, Kimi, Grok, Muse Spark, 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. Each model's wire comes from the curated snapshot, then from the AI SDK package its [Models.dev](https://models.dev) row names: GPT, Grok, and Muse Spark rows use `/responses`; Claude and most Qwen rows use `/messages`; DeepSeek, MiniMax, GLM, Kimi, `qwen3.8-max`, and the 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 fails closed because its model-specific Google wire protocol is not implemented; Models.dev rows marked `deprecated` and models no loaded catalog lists also fail closed. See [OpenCode Zen protocol catalog](#opencode-zen-protocol-catalog). |
|
||||
| `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`. |
|
||||
| `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), `muse-spark-1.3`, `muse-spark-1.3-contributor`, `muse-wonder-1.0` (preview), `muse-spark-1.2-contributor`, `muse-spark-1.1` | [Meta Model API](https://developer.meta.com/ai/resources/blog/build-with-muse-spark/) public-preview route using OpenAI-compatible Chat Completions. The default stays `muse-spark-1.2`, which keeps its wire ID, tool support, 1M context, 32K output metadata, and `none` through `xhigh` reasoning effort; [Meta recommends](https://dev.meta.ai/docs/models.md) `muse-spark-1.3` for new work (1,048,576 context) and it stays selectable. `META_MODEL_API_MODEL` and `MODEL_API_MODEL` are accepted. Provider aliases: `meta-ai`, `meta_model_api`, `muse`, `muse-spark`. |
|
||||
| `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`. |
|
||||
| `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`. |
|
||||
| `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`. |
|
||||
@@ -863,7 +862,7 @@ overlay and lets DSH resolve its own keys.
|
||||
| `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). |
|
||||
| `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`. |
|
||||
| `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.7`, `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`). [Grok 4.7](https://docs.x.ai/docs/models/grok-4.7) has the same 500K window, text/image input, function calls, structured output, reasoning ladder and $2.00 / $0.50 cached / $6.00 rates; xAI documents no web-search support for it yet, so Codewhale does not claim it. Grok reasoning cannot be disabled ([reasoning guide](https://docs.x.ai/docs/guides/reasoning)). 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`. |
|
||||
| `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`. |
|
||||
| `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.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 Coding Plan and Anthropic routes do not inherit that capability. Alibaba retired `qwen3.8-max-preview` on 2026-08-05 and routes it to `qwen3.8-max`, so it is no longer listed. 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`. |
|
||||
| `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`. |
|
||||
| `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`. |
|
||||
| `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`. |
|
||||
@@ -999,9 +998,9 @@ upload to Hugging Face and does not perform direct Hugging Face Hub HTTP search.
|
||||
|
||||
### Xiaomi MiMo Notes
|
||||
|
||||
`xiaomi-mimo` defaults to `mimo-v2.5-pro` for long-context reasoning and coding
|
||||
work. The chat picker also exposes `mimo-v2.5-pro-ultraspeed` and the latest
|
||||
Omni model `mimo-v2.5`. Xiaomi MiMo TTS is available through
|
||||
`xiaomi-mimo` defaults to `mimo-v2.6-pro` for long-context reasoning and coding
|
||||
work. The chat picker also exposes `mimo-v2.6-flash` (the replacement for the
|
||||
retired Omni model `mimo-v2.5`) and `mimo-v2.5-pro-ultraspeed`. Xiaomi MiMo TTS is available through
|
||||
`codewhale --provider xiaomi-mimo speech "text" --model tts` (or the `tts`
|
||||
alias). In Act and Operate, the provider-specific `speech` / `tts` tools are
|
||||
available through deferred discovery when the Xiaomi MiMo route is configured.
|
||||
@@ -1163,7 +1162,7 @@ See [Catalog refresh](CATALOG_REFRESH.md) for freshness and estimate boundaries.
|
||||
| `volcengine` | `DeepSeek-V4-Pro`, `DeepSeek-V4-Flash` | yes | yes |
|
||||
| `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 |
|
||||
| `orcarouter` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`, `orcarouter/auto` | yes | yes |
|
||||
| `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 |
|
||||
| `xiaomi-mimo` | `mimo-v2.6-pro`, `mimo-v2.6-flash`, `mimo-v2.5-pro-ultraspeed`; speech/TTS IDs are selected through `codewhale speech` / `tts` | yes | yes for chat models; no for speech/TTS models |
|
||||
| `novita` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash` | yes | yes |
|
||||
| `fireworks` | `accounts/fireworks/models/deepseek-v4-pro` | yes | yes |
|
||||
| `siliconflow` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | yes | yes |
|
||||
@@ -1171,7 +1170,7 @@ See [Catalog refresh](CATALOG_REFRESH.md) for freshness and estimate boundaries.
|
||||
| `moonshot` | `kimi-k2.7-code`, `kimi-k2.6` | yes | yes |
|
||||
| `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 |
|
||||
| `stepfun` | `step-3.7-flash` (default), `step-5-preview`, `step-3.5-flash`, `step-3.5-flash-2603` | yes | yes |
|
||||
| `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 |
|
||||
| `minimax` | `MiniMax-M3`, `MiniMax-M2.1`, `MiniMax-M2.1-highspeed`, `MiniMax-M2`; `MiniMax-M2.7`, `MiniMax-M2.7-highspeed`, `MiniMax-M2.5` and `MiniMax-M2.5-highspeed` stay accepted until their 2026-11-18 retirement | yes | yes |
|
||||
| `minimax-anthropic` | `MiniMax-M3`, `MiniMax-M2.7` | yes | yes |
|
||||
| `sglang` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | yes | yes |
|
||||
| `vllm` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | yes | yes |
|
||||
@@ -1182,16 +1181,16 @@ See [Catalog refresh](CATALOG_REFRESH.md) for freshness and estimate boundaries.
|
||||
| `deepinfra` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | yes | yes |
|
||||
| `together` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash`, `thinkingmachines/inkling` | yes | yes |
|
||||
| `openai-codex` | `gpt-5.5` | yes | yes |
|
||||
| `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` |
|
||||
| `anthropic` | `claude-opus-5-5`, `claude-sonnet-5-5`, `claude-haiku-5-5`, `claude-fable-5-1`, `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` |
|
||||
| `openmodel` | `deepseek-v4-flash`; provider-scoped custom model IDs pass through | yes | model-dependent |
|
||||
| `sakana` | `fugu`, `fugu-ultra-20260615` | yes | yes for `fugu-ultra-20260615` |
|
||||
| `longcat` | `LongCat-2.0` | yes | yes |
|
||||
| `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 |
|
||||
| `meta` | `muse-spark-1.2` | yes | yes |
|
||||
| `meta` | `muse-spark-1.3`, `muse-spark-1.3-contributor`, `muse-wonder-1.0`, `muse-spark-1.2`, `muse-spark-1.2-contributor` | yes | yes |
|
||||
| `xai` | `grok-4.6`, `grok-4.7`, `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.7`, `grok-4.5`, `grok-4.3`, `grok-build`, and `grok-4.20-0309-reasoning` |
|
||||
| `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` |
|
||||
| `google` | `gemini-4-argon`, `gemini-3.1-pro-preview`, `gemini-3-pro-preview`, `gemini-3.8-flash`, `gemini-3.6-flash`, `gemini-3.5-flash-lite`, `gemini-2.5-pro`, `gemini-2.5-flash` | yes | yes except `gemini-3.5-flash-lite` |
|
||||
| `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 |
|
||||
| `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 |
|
||||
| `modelstudio-token-plan`, `modelstudio-coding-plan` | `qwen3.8-max`, `qwen3.7-plus`, `qwen3.7-max`, `qwen3.6-flash`, `deepseek-v4-pro`, `deepseek-v4-flash-0731`, `glm-5.2` | yes | yes |
|
||||
| `csdn` | `glm_for_coding`; other marketplace model IDs pass through | yes | yes |
|
||||
|
||||
AtlasCloud keeps the same default model as the config layer and adds
|
||||
@@ -1245,14 +1244,17 @@ while bare `k3` can use an entitled 1M override.
|
||||
| NVIDIA NIM V4 registry models | 1,000,000 | 384,000 | yes | yes | not documented in code |
|
||||
| Volcengine Ark V4 model IDs | 1,000,000 | 384,000 | yes | yes | not documented in code |
|
||||
| OpenRouter, Novita, Fireworks, SiliconFlow, SGLang, and vLLM V4 model IDs | 1,000,000 | 384,000 | yes | no | not documented in code |
|
||||
| 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 |
|
||||
| Xiaomi MiMo `mimo-v2.6-pro`, `mimo-v2.6-flash` | 1,048,576 | 131,072 | yes | no | not documented in code |
|
||||
| Xiaomi MiMo `mimo-v2.5-pro-ultraspeed` | 1,000,000 | 131,072 | yes | no | not documented in code |
|
||||
| OpenRouter Qwen 3.6 Flash / Plus | 1,000,000 | 65,536 | yes | no | not documented in code |
|
||||
| OpenRouter Qwen 3.6 35B / 27B | 262,144 | 262,140 | yes | no | not documented in code |
|
||||
| OpenRouter Qwen 3.6 Max Preview | 262,144 | 65,536 | yes | no | not documented in code |
|
||||
| OpenAI API `gpt-5.5` | 1,050,000 | 128,000 | yes | no | not documented in code |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| Anthropic API `claude-opus-5-5`, `claude-sonnet-5-5`, `claude-haiku-5-5`, `claude-fable-5-1`, `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 |
|
||||
| Google Gemini API `gemini-4-argon` | 1,048,576 | not published | model-dependent | no | not documented in code |
|
||||
| Google Gemini API `gemini-3.8-flash`, `gemini-3.6-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 |
|
||||
| Meta Model API `muse-spark-1.3`, `muse-spark-1.3-contributor`, `muse-wonder-1.0` | 1,048,576 | not published | yes | no | not documented in code |
|
||||
| Meta Model API `muse-spark-1.2` | 1,000,000 | 32,000 | yes | no | not documented in code |
|
||||
| ChatGPT plan route (`openai-codex`) | conservatively budgeted; account listing does not state a window | no output cap sent in preview | model dependent | no | public `/v1/responses`; no context limit is inferred from account eligibility |
|
||||
| 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` |
|
||||
@@ -1335,8 +1337,8 @@ Changing `provider`, `base_url`, or `model` can select a route that supports the
|
||||
OpenAI-compatible payload shape, but Codewhale cannot convert arbitrary JSON
|
||||
text into a trusted tool call after the model has emitted it as prose.
|
||||
|
||||
DeepSeek will retire `deepseek-chat` and `deepseek-reasoner` on 2026-07-24 at
|
||||
15:59 UTC. Codewhale migrates either name to `deepseek-v4-flash` before a
|
||||
DeepSeek retired `deepseek-chat` and `deepseek-reasoner` on 2026-07-24 at
|
||||
15:59 UTC. Codewhale migrates either name to `deepseek-flash` before a
|
||||
request reaches DeepSeek's first-party OpenAI or Anthropic endpoint. If no
|
||||
reasoning tier was configured, `deepseek-chat` also migrates to `off` and
|
||||
`deepseek-reasoner` to `high`, preserving their former non-thinking / thinking
|
||||
|
||||
@@ -194,6 +194,15 @@ entry against the current catalog and policy before advertising it again. A
|
||||
session sync clears it. The cache cannot resurrect a removed, denied, or
|
||||
newly-eager tool.
|
||||
|
||||
When a search's activation pushes a previously activated tool out of the
|
||||
cache, that search's result lists it under `evicted_tool_references`, so the
|
||||
model is told the tool is no longer callable rather than finding it missing
|
||||
from the next request. Only tools that actually left the active set are listed;
|
||||
a tool that became eager stays callable and is not reported. Known limit: a
|
||||
tool dropped by the per-turn revalidation (removed, denied, or no longer
|
||||
deferred) outside a search is still dropped silently, because there is no tool
|
||||
result to carry the notice.
|
||||
|
||||
Each subagent gets its own policy-filtered deferred catalog, always-present
|
||||
`tool_search`, and bounded activation cache. Forked messages and instructions
|
||||
remain in context, but the child cache starts empty and discovers tools locally;
|
||||
|
||||
@@ -1152,7 +1152,7 @@ DeepSeek V4 前缀缓存让 token 标签变得重要。这些数量保持分离
|
||||
如果你从更旧的版本升级:
|
||||
|
||||
- 旧:`/codewhale` 新:`/links`(别名:`/dashboard`、`/api`)
|
||||
- 旧:`/set model deepseek-reasoner` 新:`/config` 并把 `model` 行编辑为 `deepseek-v4-pro` 或 `deepseek-v4-flash`
|
||||
- 旧:`/set model deepseek-reasoner` 新:`/config` 并把 `model` 行编辑为 `deepseek-v4-pro` 或 `deepseek-flash`
|
||||
- 旧:可见 `Normal` 模式或 `default_mode = "normal"` 新:使用 `Agent` / `default_mode = "agent"`;旧 `normal` 仍映射到 `agent`
|
||||
- 旧:在斜杠 UX/帮助中发现 `/set` 新:编辑用 `/config`,只读检查用 `/settings`
|
||||
|
||||
@@ -1199,7 +1199,7 @@ DeepSeek V4 前缀缓存让 token 标签变得重要。这些数量保持分离
|
||||
|
||||
- `insecure_skip_tls_verify`(bool,可选的 provider 表键):旧兼容键,默认禁用。活动 provider 表上为 true 时,provider 客户端拒绝该配置,而不是跳过 TLS 证书验证。企业或私有 CA 包用 `SSL_CERT_FILE`;`codewhale doctor` 报告此设置的过期使用。
|
||||
|
||||
- `default_text_model`(字符串,可选):DeepSeek 和 `deepseek-anthropic` 默认 `deepseek-flash`,OpenAI 是 `gpt-5.6`,xAI 是 `grok-4.6`,NVIDIA NIM 是 `deepseek-ai/deepseek-v4-pro`,AtlasCloud 是 `deepseek-ai/deepseek-v4-flash`,Wanjie Ark 是 `deepseek-reasoner`,火山方舟是 `DeepSeek-V4-Pro`,OpenRouter 和 Novita 是 `deepseek/deepseek-v4-pro`,小米 MiMo 是 `mimo-v2.5-pro`,Fireworks 是 `accounts/fireworks/models/deepseek-v4-pro`,SiliconFlow 和 DeepInfra 是 `deepseek-ai/DeepSeek-V4-Pro`,Arcee AI 是 `trinity-large-thinking`,Moonshot 是 `kimi-k2.7-code`,MiniMax 是 `MiniMax-M3`,Z.ai 是 `GLM-5.3`,StepFun 是 `step-3.7-flash`,千帆是 `ernie-4.0-turbo-8k`,Sakana AI 是 `fugu`,SGLang/vLLM 是 `deepseek-ai/DeepSeek-V4-Pro`,本地 Ollama 没有固定 id(Codewhale 会从实时本地目录中选用一个支持聊天的标签——优先选 coder 或支持工具的标签,然后是上下文最大的——绝不会选嵌入模型或重排序模型),Ollama Cloud 是 `gpt-oss:120b`。Hugging Face 和 Together AI 都默认 `deepseek-ai/DeepSeek-V4-Pro`;`openai-codex` 默认 `gpt-5.6`;`anthropic` 默认 `claude-sonnet-4-6`;`openmodel` 默认 `deepseek-v4-flash`。当前公开的 DeepSeek ID 包括 `deepseek-v4-pro` 和 `deepseek-flash`(V4.1 Flash,以不带版本号的 id 发布),两者都是 1M 上下文窗口、384K 最大输出、默认启用思考模式。DeepSeek 的实时定价/模型页现在把 Pro 后端标为 `DeepSeek-V4-Pro-0813`;可调用的 API ID 仍是 `deepseek-v4-pro`,所以 Codewhale 不发送后端标签,也不发送 Claude Code 特有的 `deepseek-v4-pro[1m]` 选择器。DeepSeek 于 2026 年 7 月 24 日退役 `deepseek-chat` 和 `deepseek-reasoner`;直连官方路由把两者都迁移到 `deepseek-v4-flash`,省略推理设置时保留它们此前的不思考(`off`)和思考(`high`)意图。显式的 `reasoning_effort` 优先,Wanjie Ark、聚合器、自托管运行时和自定义端点上由 provider 自己拥有的 id 不会被全局改写。SiliconFlow 保留自己的映射:`deepseek-reasoner` 和 `deepseek-r1` 选择其 Pro 模型,而 `deepseek-chat` 和 `deepseek-v3` 选择 Flash。各 provider 特有的映射在受支持之处把 `deepseek-v4-pro` / `deepseek-v4-flash` 翻译成该 provider 的模型 ID。OpenRouter 还识别最近的大模型 ID,如 `arcee-ai/trinity-large-thinking`、`minimax/minimax-m3`、`minimax/minimax-m2.7`、`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`、`qwen/qwen3.7-max`、`google/gemma-4-31b-it`、`moonshotai/kimi-k2.7-code`、`moonshotai/kimi-k2.6`、`nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free` 和 `nvidia/nemotron-3-ultra-550b-a55b`;直连 Arcee 使用 `trinity-large-thinking` 和 `trinity-large-preview` 这样的裸 ID;直连 Moonshot 识别 `kimi-k3`、`kimi-k2.7-code` 和 `kimi-k2.6`。确切的 Kimi Code 端点识别 K3 的裸 `k3` 和 K2.7 的 `kimi-for-coding`;这些会员 ID 与直连 Moonshot 的 ID 不同,绝不会跨路由改写。直连 MiniMax 识别 `MiniMax-M3` 和有文档记录的 M2.x 聊天模型 ID;直连 Z.ai 识别 `GLM-5.3`(默认)、`GLM-5.2`、`GLM-5.1` 和 `GLM-5-Turbo`,OpenRouter 识别对应的 `z-ai/glm-5.1`、`z-ai/glm-5.2`、`z-ai/glm-5.3` 和 `z-ai/glm-5-turbo` ID——`GLM-5.3` 自 2026-08-13 起已在 Z.ai Coding Plan 上线;在 Z.ai 发布独立的 5.3 数据之前,它继承 `GLM-5.2` 的目录元数据且不带价格,而显式选择 `GLM-5.2` 会保留它自己的 id;直连 Sakana 识别 `fugu` 和 `fugu-ultra-20260615`;直连小米 MiMo 识别聊天 ID `mimo-v2.5-pro`、`mimo-v2.5-pro-ultraspeed` 和 `mimo-v2.5`,而 TTS ID 通过 `codewhale speech` / `tts` 选择。通用 `openai`、`atlascloud`、`wanjie-ark`、`xiaomi-mimo`、`arcee`、`moonshot`、`minimax`、`openmodel`、`zai`、`stepfun`、`qianfan`、`sakana`、本地 Ollama 和 Ollama Cloud 的模型 ID,在已知别名规范化之后原样透传。带自定义 `base_url` 的 OpenRouter 和 SiliconFlow provider 配置也保留显式的模型值,这样 OpenAI 兼容网关就能接受裸模型 ID。用 `/models` 或 `codewhale models` 从你配置的端点发现实时 ID。`CODEWHALE_MODEL` 为单个进程覆盖它;`DEEPSEEK_MODEL` 是旧别名。
|
||||
- `default_text_model`(字符串,可选):DeepSeek 和 `deepseek-anthropic` 默认 `deepseek-flash`,OpenAI 是 `gpt-5.6`,xAI 是 `grok-4.6`,NVIDIA NIM 是 `deepseek-ai/deepseek-v4-pro`,AtlasCloud 是 `deepseek-ai/deepseek-v4-flash`,Wanjie Ark 是 `deepseek-reasoner`,火山方舟是 `DeepSeek-V4-Pro`,OpenRouter 和 Novita 是 `deepseek/deepseek-v4-pro`,小米 MiMo 是 `mimo-v2.6-pro`,Fireworks 是 `accounts/fireworks/models/deepseek-v4-pro`,SiliconFlow 和 DeepInfra 是 `deepseek-ai/DeepSeek-V4-Pro`,Arcee AI 是 `trinity-large-thinking`,Moonshot 是 `kimi-k2.7-code`,MiniMax 是 `MiniMax-M3`,Z.ai 是 `GLM-5.3`,StepFun 是 `step-3.7-flash`,千帆是 `ernie-4.0-turbo-8k`,Sakana AI 是 `fugu`,SGLang/vLLM 是 `deepseek-ai/DeepSeek-V4-Pro`,本地 Ollama 没有固定 id(Codewhale 会从实时本地目录中选用一个支持聊天的标签——优先选 coder 或支持工具的标签,然后是上下文最大的——绝不会选嵌入模型或重排序模型),Ollama Cloud 是 `gpt-oss:120b`。Hugging Face 和 Together AI 都默认 `deepseek-ai/DeepSeek-V4-Pro`;`openai-codex` 默认 `gpt-5.6`;`anthropic` 默认 `claude-sonnet-4-6`;`openmodel` 默认 `deepseek-v4-flash`。当前公开的 DeepSeek ID 包括 `deepseek-v4-pro` 和 `deepseek-flash`(V4.1 Flash,以不带版本号的 id 发布),两者都是 1M 上下文窗口、384K 最大输出、默认启用思考模式。DeepSeek 的实时定价/模型页现在把 Pro 后端标为 `DeepSeek-V4-Pro-0813`;可调用的 API ID 仍是 `deepseek-v4-pro`,所以 Codewhale 不发送后端标签,也不发送 Claude Code 特有的 `deepseek-v4-pro[1m]` 选择器。DeepSeek 已于 2026 年 7 月 24 日退役 `deepseek-chat` 和 `deepseek-reasoner`;直连官方路由把两者都迁移到 `deepseek-flash`,省略推理设置时保留它们此前的不思考(`off`)和思考(`high`)意图。DeepSeek 也已退役 `deepseek-v4-flash` 和 `deepseek-v4-flash-vision-exp` 模型:两个名称仍被接受,由 V4.1 Flash 提供服务,并按 `deepseek-flash` 的价格计费;Codewhale 对 2026-09-10 04:00 UTC 起的回合采用该价格。`flash`、`deepseek-v4flash`、`flash-vision` 和 `deepseek-v4flashvisionexp` 简写选择 `deepseek-flash`。显式的 `reasoning_effort` 优先,Wanjie Ark、聚合器、自托管运行时和自定义端点上由 provider 自己拥有的 id 不会被全局改写。SiliconFlow 保留自己的映射:`deepseek-reasoner` 和 `deepseek-r1` 选择其 Pro 模型,而 `deepseek-chat` 和 `deepseek-v3` 选择 Flash。各 provider 特有的映射在受支持之处把 `deepseek-v4-pro` / `deepseek-v4-flash` 翻译成该 provider 的模型 ID。OpenRouter 还识别最近的大模型 ID,如 `arcee-ai/trinity-large-thinking`、`minimax/minimax-m3`、`minimax/minimax-m2.7`、`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`、`qwen/qwen3.7-max`、`google/gemma-4-31b-it`、`moonshotai/kimi-k2.7-code`、`moonshotai/kimi-k2.6`、`nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free` 和 `nvidia/nemotron-3-ultra-550b-a55b`;直连 Arcee 使用 `trinity-large-thinking` 和 `trinity-large-preview` 这样的裸 ID;直连 Moonshot 识别 `kimi-k3`、`kimi-k2.7-code` 和 `kimi-k2.6`。确切的 Kimi Code 端点识别 K3 的裸 `k3` 和 K2.7 的 `kimi-for-coding`;这些会员 ID 与直连 Moonshot 的 ID 不同,绝不会跨路由改写。直连 MiniMax 识别 `MiniMax-M3` 和有文档记录的 M2.x 聊天模型 ID;直连 Z.ai 识别 `GLM-5.3`(默认)、`GLM-5.2`、`GLM-5.1` 和 `GLM-5-Turbo`,OpenRouter 识别对应的 `z-ai/glm-5.1`、`z-ai/glm-5.2`、`z-ai/glm-5.3` 和 `z-ai/glm-5-turbo` ID——`GLM-5.3` 自 2026-08-13 起已在 Z.ai Coding Plan 上线;在 Z.ai 发布独立的 5.3 数据之前,它继承 `GLM-5.2` 的目录元数据且不带价格,而显式选择 `GLM-5.2` 会保留它自己的 id;直连 Sakana 识别 `fugu` 和 `fugu-ultra-20260615`;直连小米 MiMo 识别聊天 ID `mimo-v2.6-pro`、`mimo-v2.6-flash` 和 `mimo-v2.5-pro-ultraspeed`(已停用的 `mimo-v2.5-pro` 和 `mimo-v2.5` 会以 `mimo-v2.6-pro` 和 `mimo-v2.6-flash` 发送),而 TTS ID 通过 `codewhale speech` / `tts` 选择。通用 `openai`、`atlascloud`、`wanjie-ark`、`xiaomi-mimo`、`arcee`、`moonshot`、`minimax`、`openmodel`、`zai`、`stepfun`、`qianfan`、`sakana`、本地 Ollama 和 Ollama Cloud 的模型 ID,在已知别名规范化之后原样透传。带自定义 `base_url` 的 OpenRouter 和 SiliconFlow provider 配置也保留显式的模型值,这样 OpenAI 兼容网关就能接受裸模型 ID。用 `/models` 或 `codewhale models` 从你配置的端点发现实时 ID。`CODEWHALE_MODEL` 为单个进程覆盖它;`DEEPSEEK_MODEL` 是旧别名。
|
||||
- TelecomJS 只把 `deepseek-v4-pro` 用作刷新前的保守回退。其 key 作用域的 `/models` 目录可用后,选择器使用那些实时行;Codewhale 在该路由上省略不受支持的推理请求字段。
|
||||
|
||||
- `reasoning_effort`(字符串,可选):`auto`、`off`、`minimal`、`low`、`medium`、`high`、`xhigh`、`ultra`(`ultracode` 是 `ultra` 的别名)或 `max`;默认取已配置的 UI 档位。DeepSeek Platform 收到顶层 `thinking` / `reasoning_effort` 字段。Ollama Cloud 的 OpenAI 兼容 Chat Completions 路由保留其有文档记录的 `none` / `low` / `medium` / `high` / `max` 阶梯(`off` 作为 `none` 发送;`xhigh` 和 `ultracode` 规范化为 `max`)。确切 `https://api.x.ai/v1` 上的直连 xAI `grok-4.7` 和 `grok-4.6` 收到顶层 `reasoning_effort = "low" | "medium" | "high" | "xhigh"`(阶梯来自内置目录行;`grok-4.5` 把 `xhigh` 映射为 `high`,没有文档记录 effort 的行,如 `grok-4.3`,则不发送该字段);Grok 的推理无法关闭,因此 `off` 规范化为 `high`,`max`/`ultracode` 规范化为 `xhigh`,`auto` 让该字段省略,从而使用 xAI 文档记录的默认值 `high`。自定义的 xAI 兼容 `base_url` 不继承该方言。确切 `https://api.moonshot.ai/v1` 上的直连 Moonshot `kimi-k3` 始终思考,只收到顶层 `reasoning_effort = "low" | "high" | "max"`;`off` 规范化为 `low`,`medium` 规范化为 `high`。确切 `https://api.kimi.com/coding/v1` 上的 Kimi Code 会员 `k3` 则收到嵌套的 `thinking.effort`,其 `off` 设置同样规范化为启用的 `low`。正常调度的 `auto` 使用 Codewhale 的自动推理选择器,发送一个具体的、按路由规范化后的档位;只有省略推理设置时,才由 provider 的默认值控制。相邻的网关以及其他模型/端点组合保留通用的 Moonshot 契约。OpenAI Codex 把过期的 `off` 规范化为 `low`,并把 `max` / `ultracode` 作为 Responses 的 `xhigh` 发送。Z.ai 收到有文档记录的 `thinking` 控制,并把启用的思考视为 GLM coding 的 high/max 通道。NVIDIA NIM 通过 `chat_template_kwargs` 收到等效设置。
|
||||
|
||||
@@ -275,7 +275,7 @@ Operate 保持直接的工具面及其审批、沙箱、shell、ask 规则和仓
|
||||
|
||||
Fleet 是持久花名册对外的名称。`codewhale fleet …` 是命令,`/fleet` 是斜杠命令。Fleet 这个名字也用在那些必须跨版本保持稳定的地方:持久账本 `.codewhale/fleet.jsonl`、已保存的花名册 `fleets/<name>.toml`、`[fleet]` 配置表,以及 `codewhale workflow run --fleet` 标志。
|
||||
|
||||
想让 Codewhale 每回合自己选模型和思考级别时,用 `/model auto`。当 DeepSeek 路由模型可用时,Auto 可以在脱敏清单中选取任何可运行的 provider/模型组合。该分类会把最新请求(上限 4,000 字符)加上最多六条最近上下文行的有界摘要(每条 900 字符)发送到 `DeepSeek / deepseek-v4-flash`。凭据、端点和提供商错误文本不会包含在清单里。没有该路由器时,Auto 使用本地的、感知提供商的启发式方法,不发送任何路由请求。如果分类尝试未通过验证或出错,Auto 回退到该启发式方法,同时把尝试过的分类器数据路径保留在回合回执中。
|
||||
想让 Codewhale 每回合自己选模型和思考级别时,用 `/model auto`。当 DeepSeek 路由模型可用时,Auto 可以在脱敏清单中选取任何可运行的 provider/模型组合。该分类会把最新请求(上限 4,000 字符)加上最多六条最近上下文行的有界摘要(每条 900 字符)发送到 `DeepSeek / deepseek-flash`。凭据、端点和提供商错误文本不会包含在清单里。没有该路由器时,Auto 使用本地的、感知提供商的启发式方法,不发送任何路由请求。如果分类尝试未通过验证或出错,Auto 回退到该启发式方法,同时把尝试过的分类器数据路径保留在回合回执中。
|
||||
|
||||
`/model` 选择器会说明哪条数据路径可用,并显示最后解析的路由。`Ctrl+O` 打开所选或当前回合的推理详情;`Ctrl+Alt+O`(或 `/turn inspect`)打开整回合的回合检查器(Turn Inspector),其模型路由区记录具体的 provider/模型、strong/fast 配对、所选层级、选择范围、路由原因,以及分类器是否收到了路由上下文。当你需要可重复的比较、严格的提供商边界或完全不要分类请求时,使用固定模型。
|
||||
|
||||
|
||||
+19
-16
@@ -246,7 +246,7 @@ provider = "modelstudio-token-plan"
|
||||
[providers.modelstudio_token_plan]
|
||||
api_key = "YOUR_MODELSTUDIO_API_KEY"
|
||||
# base_url 默认为 https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1
|
||||
model = "qwen3.8-max" # 或 qwen3.8-max-preview | qwen3.7-plus | qwen3.7-max |
|
||||
model = "qwen3.8-max" # 或 qwen3.7-plus | qwen3.7-max |
|
||||
# qwen3.6-flash | deepseek-v4-pro | deepseek-v4-flash-0731 |
|
||||
# glm-5.2
|
||||
```
|
||||
@@ -280,7 +280,7 @@ model = "qwen3.8-max"
|
||||
在 OpenAI 兼容路由上,顶层控制是**路由和模型特定**的,Codewhale 失败关闭:只有当配置的 `base_url` 是官方阿里 Chat Completions 主机(`*.maas.aliyuncs.com/compatible-mode/v1`,包括工作区级主机,或 `coding-intl.dashscope.aliyuncs.com/v1`)时,它们才会被发送。同一提供商 ID 上的自定义 `base_url` 会剥离 `thinking`、`enable_thinking`、`preserve_thinking` 和 `reasoning_effort`,因此任意的 OpenAI 兼容网关永远不会收到阿里的方言。在已验证的主机上:
|
||||
|
||||
- **混合模型**(`qwen3.7-*`、`qwen3.6-*`、`deepseek-v4*`、`glm-*`、`kimi-k2.6*`)获得 `enable_thinking`:`off` 时为 `false`,否则为 `true`。
|
||||
- **仅思考模型** —— `qwen3.8-max`(编目为 `thinking: always_on`)、`qwen3.8-max-preview`(提供 effort/预算选项,无开关)和 `kimi-k2.7-code` —— 完全没有启用/禁用开关。发送这样的开关,最好的情况也只是被忽略。
|
||||
- **仅思考模型** —— `qwen3.8-max`(编目为 `thinking: always_on`)和 `kimi-k2.7-code` —— 完全没有启用/禁用开关。发送这样的开关,最好的情况也只是被忽略。
|
||||
- 对文档记录为接受它的模型(`qwen3.7-max`/`-plus`、`qwen3.6-max-preview`/`-plus`/`-flash`、`kimi-k2.6*`、`kimi-k2.7-code`)发送 `preserve_thinking`,这样下一回合会保留助手的思考轨迹。
|
||||
- `reasoning_effort` 只对有文档记载的分档(档位阶梯)的两个系列发送 —— `deepseek-v4*` 和 `glm-5`/`5.1`/`5.2` —— 映射到 `high` 或 `max`。
|
||||
|
||||
@@ -497,7 +497,7 @@ Kimi 仍然仅支持 API 密钥;对 Kimi 的外部授权被拒绝。
|
||||
|
||||
| 提供商 ID | TOML 表 | 认证环境变量 | Base URL 环境变量和默认值 | 默认或静态模型 | 备注 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `deepseek` | `[providers.deepseek]` | `DEEPSEEK_API_KEY` | `CODEWHALE_BASE_URL` / `DEEPSEEK_BASE_URL`;默认 `https://api.deepseek.com/beta` | `deepseek-flash`(出厂默认;V4.1 Flash,无版本号的 ID), `deepseek-v4-pro`, `deepseek-v4-flash`,实验性的 `deepseek-v4-flash-vision-exp`;视觉别名 `flash-vision`, `deepseek-v4flashvisionexp`;兼容别名 `deepseek-chat`, `deepseek-reasoner` | 一等默认提供商。线上 Pro 后端标记为 `DeepSeek-V4-Pro-0813`;可调用的 API ID 仍是 `deepseek-v4-pro`。Beta URL 启用严格工具模式、chat 前缀补全和 FIM 补全。文档中记载的 V4 路由可以通过单独的、有界的 Responses 请求使用提供商原生的网页搜索;兼容的自定义端点不会继承这一能力。显式设置 `https://api.deepseek.com` 或 `/v1` 可退出仅限 beta 的功能。出厂默认的 `deepseek-flash` 使用 Responses API(自 2026-07-31 的 Flash 生产环境更新起,这是 DeepSeek 文档中记载的 Codex 式集成路径);仅适用于 Chat 的控制项(`thinking` 开关和严格工具的 `/beta` 路由)只作用于 Chat Completions 路由,而 `deepseek-v4-pro` 在其已宣布的 Responses 推出之前仍走 Chat Completions。思考强度遵循 DeepSeek 文档中记载的“请求值到实际值”映射:`minimal`/`low` 落到 `low`,`medium`/`xhigh` 落到 `high`,`max`/`ultra` 落到 `max`;`off` 关闭思考(Chat 上为 `thinking: {"type":"disabled"}`,Responses 上为 `reasoning.effort: "none"`)。该实验性视觉 ID 于 2026-08-21 在已认证的 `/models` 名单中被观察到,仅在直连的 Chat Completions 路由上声明支持图像输入。它的限制、推理和工具调用标志暂时继承自 Flash;价格未知,本次发布工作中也没有做过付费的图像往返测试。 |
|
||||
| `deepseek` | `[providers.deepseek]` | `DEEPSEEK_API_KEY` | `CODEWHALE_BASE_URL` / `DEEPSEEK_BASE_URL`;默认 `https://api.deepseek.com/beta` | `deepseek-flash`(出厂默认;V4.1 Flash,无版本号的 ID), `deepseek-v4-pro`, `deepseek-v4-flash`,实验性的 `deepseek-v4-flash-vision-exp`;兼容别名 `deepseek-chat`, `deepseek-reasoner` | 一等默认提供商。线上 Pro 后端标记为 `DeepSeek-V4-Pro-0813`;可调用的 API ID 仍是 `deepseek-v4-pro`。Beta URL 启用严格工具模式、chat 前缀补全和 FIM 补全。文档中记载的 V4 路由可以通过单独的、有界的 Responses 请求使用提供商原生的网页搜索;兼容的自定义端点不会继承这一能力。显式设置 `https://api.deepseek.com` 或 `/v1` 可退出仅限 beta 的功能。出厂默认的 `deepseek-flash` 使用 Responses API(自 2026-07-31 的 Flash 生产环境更新起,这是 DeepSeek 文档中记载的 Codex 式集成路径);仅适用于 Chat 的控制项(`thinking` 开关和严格工具的 `/beta` 路由)只作用于 Chat Completions 路由,而 `deepseek-v4-pro` 在其已宣布的 Responses 推出之前仍走 Chat Completions。思考强度遵循 DeepSeek 文档中记载的“请求值到实际值”映射:`minimal`/`low` 落到 `low`,`medium`/`xhigh` 落到 `high`,`max`/`ultra` 落到 `max`;`off` 关闭思考(Chat 上为 `thinking: {"type":"disabled"}`,Responses 上为 `reasoning.effort: "none"`)。该实验性视觉 ID 于 2026-08-21 在已认证的 `/models` 名单中被观察到,仅在直连的 Chat Completions 路由上声明支持图像输入。它的限制、推理和工具调用标志暂时继承自 Flash,本次发布工作中也没有做过付费的图像往返测试。DeepSeek 此后已退役 `deepseek-v4-flash` 和该视觉 ID;两者仍被接受,由 V4.1 Flash 提供服务,并按 `deepseek-flash` 的价格计费,Codewhale 从 2026-09-10 04:00 UTC 起采用该价格。`flash`、`deepseek-v4flash`、`flash-vision` 和 `deepseek-v4flashvisionexp` 简写现在选择 `deepseek-flash`。 |
|
||||
| `deepseek-anthropic` | `[providers.deepseek_anthropic]` | `DEEPSEEK_API_KEY` | `DEEPSEEK_ANTHROPIC_BASE_URL`;默认 `https://api.deepseek.com/anthropic` | `deepseek-v4-pro`, `deepseek-v4-flash`;兼容别名 `deepseek-chat`, `deepseek-reasoner` | 面向 Anthropic Messages 线协议的 DeepSeek 显式选择加入路由。使用 `/v1/messages`、`x-api-key` 和 `anthropic-version: 2023-06-01`。默认 Chat Completions 路径请保持 `provider = "deepseek"`。 |
|
||||
| `nvidia-nim` | `[providers.nvidia_nim]` | `NVIDIA_API_KEY`, `NVIDIA_NIM_API_KEY` | `NVIDIA_NIM_BASE_URL`, `NIM_BASE_URL`, `NVIDIA_BASE_URL`;默认 `https://integrate.api.nvidia.com/v1` | `deepseek-ai/deepseek-v4-pro`, `deepseek-ai/deepseek-v4-flash` | 通过 NVIDIA NIM 托管的 DeepSeek V4。TUI 配置路径接受 `NVIDIA_NIM_MODEL`。 |
|
||||
| `openai` | `[providers.openai]` | `OPENAI_API_KEY` | `OPENAI_BASE_URL`;默认 `https://api.openai.com/v1` | `gpt-5.6`(默认), `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna` | 通用 OpenAI 兼容路由,其内置端点和回退目录均以 OpenAI 原生为准。[GPT-5.6 系列](https://developers.openai.com/api/docs/models/gpt-5.6-sol)使用 OpenAI 文档中记载的 1.05M 上下文、128K 最大输出和推理级别。自定义网关仍可自由选择由网关自己提供的显式模型。接受 `OPENAI_MODEL`。 |
|
||||
@@ -506,14 +506,14 @@ Kimi 仍然仅支持 API 密钥;对 Kimi 的外部授权被拒绝。
|
||||
| `volcengine` | `[providers.volcengine]` | `VOLCENGINE_API_KEY`, `VOLCENGINE_ARK_API_KEY`, `ARK_API_KEY` | `VOLCENGINE_BASE_URL`, `VOLCENGINE_ARK_BASE_URL`, `ARK_BASE_URL`;默认 `https://ark.cn-beijing.volces.com/api/coding/v3` | `DeepSeek-V4-Pro`, `DeepSeek-V4-Flash` | 火山引擎/Volcengine Ark OpenAI 兼容编码端点。接受 `VOLCENGINE_MODEL` 和 `VOLCENGINE_ARK_MODEL`。 |
|
||||
| `openrouter` | `[providers.openrouter]` | `OPENROUTER_API_KEY` | `OPENROUTER_BASE_URL`;默认 `https://openrouter.ai/api/v1` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`;近期大模型 ID 包括 `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` | 附加的开放模型路由层。它不是 DeepSeek 的替代品;它让用户在选择 OpenRouter 时把受支持的模型 ID 路由过去。 |
|
||||
| `orcarouter` | `[providers.orcarouter]` | `ORCAROUTER_API_KEY` | `ORCAROUTER_BASE_URL`;默认 `https://api.orcarouter.ai/v1` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`;路由别名 `orcarouter/auto`;近期大模型 ID 镜像 OpenRouter 的命名空间目录 | [OrcaRouter](https://www.orcarouter.ai) OpenAI 兼容聚合网关。与 OpenRouter 共享命名空间的 `vendor/model` 线协议模型格式和 DeepSeek 模型集,因此 OpenRouter 的 base-URL 和模型规范化规则适用。接受 `ORCAROUTER_MODEL`。提供商别名:`orcarouter`, `orca_router`, `orca`。 |
|
||||
| `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`;默认 `https://token-plan-sgp.xiaomimimo.com/v1` | 聊天:`mimo-v2.5-pro`, `mimo-v2.5-pro-ultraspeed`, `mimo-v2.5`;语音/TTS:`mimo-v2.5-tts`, `mimo-v2.5-tts-voicedesign`, `mimo-v2.5-tts-voiceclone`, `mimo-v2-tts` | 小米 MiMo OpenAI 兼容聊天补全路由。`mimo-v2.5-pro` 和 `mimo-v2.5` 可以使用文档中记载的提供商原生网页搜索插件;ultraspeed、语音/TTS 以及自定义兼容路由不会继承它。Token Plan 密钥(`tp-...`)默认使用 `api-key` 认证和 token-plan 端点;按量付费模式使用标准 API 密钥(`sk-...`)和 `https://api.xiaomimimo.com/v1`。它发送 `max_completion_tokens` 并用 MiMo 的 `thinking` 字段进行推理控制。Token Plan 成本/用量基于额度/配额;在小米暴露可靠的余额 API 之前,Codewhale 将其显示为未知。`codewhale speech` / `tts` 使用 TTS 模型。 |
|
||||
| `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`;默认 `https://token-plan-sgp.xiaomimimo.com/v1` | 聊天:`mimo-v2.6-pro`(默认), `mimo-v2.6-flash`, `mimo-v2.5-pro-ultraspeed`;语音/TTS:`mimo-v2.5-tts`, `mimo-v2.5-tts-voicedesign`, `mimo-v2.5-tts-voiceclone`, `mimo-v2-tts` | 小米 MiMo OpenAI 兼容聊天补全路由。小米于 2026-10-21 10:00(UTC+8)[停用](https://mimo.mi.com/docs/updates/deprecate) `mimo-v2.5-pro` 和 `mimo-v2.5`;对这两个已配置的 ID,Codewhale 改为发送 `mimo-v2.6-pro` 和 `mimo-v2.6-flash`。`mimo-v2.6-pro` 和 `mimo-v2.6-flash` 可以使用文档中记载的提供商原生网页搜索插件;ultraspeed、语音/TTS 以及自定义兼容路由不会继承它。Token Plan 密钥(`tp-...`)默认使用 `api-key` 认证和 token-plan 端点;按量付费模式使用标准 API 密钥(`sk-...`)和 `https://api.xiaomimimo.com/v1`。它发送 `max_completion_tokens` 并用 MiMo 的 `thinking` 字段进行推理控制。Token Plan 成本/用量基于额度/配额;在小米暴露可靠的余额 API 之前,Codewhale 将其显示为未知。`codewhale speech` / `tts` 使用 TTS 模型。 |
|
||||
| `novita` | `[providers.novita]` | `NOVITA_API_KEY` | `NOVITA_BASE_URL`;默认 `https://api.novita.ai/openai/v1` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash` | 面向 DeepSeek 模型 ID 的 OpenAI 兼容托管路由。模型覆盖使用配置或 `CODEWHALE_MODEL` / `DEEPSEEK_MODEL`。 |
|
||||
| `fireworks` | `[providers.fireworks]` | `FIREWORKS_API_KEY` | `FIREWORKS_BASE_URL`;默认 `https://api.fireworks.ai/inference/v1` | `accounts/fireworks/models/deepseek-v4-pro` | OpenAI 兼容托管路由。模型覆盖使用配置或 `CODEWHALE_MODEL` / `DEEPSEEK_MODEL`。 |
|
||||
| `siliconflow` | `[providers.siliconflow]` | `SILICONFLOW_API_KEY` | `SILICONFLOW_BASE_URL`;默认 `https://api.siliconflow.com/v1` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | OpenAI 兼容托管路由。官方文档使用 `.com` 端点。接受 `SILICONFLOW_MODEL`。推理别名 `deepseek-reasoner` 和 `deepseek-r1` 映射到 Pro;`deepseek-chat` 和 `deepseek-v3` 映射到 Flash。 |
|
||||
| `siliconflow-CN` | `[providers.siliconflow_cn]` | `SILICONFLOW_API_KEY` | `SILICONFLOW_BASE_URL`;默认 `https://api.siliconflow.cn/v1` | 使用 SiliconFlow 模型集 | 中国区 SiliconFlow 路由。未设置时回退到 `[providers.siliconflow]` 的 api_key / base_url / model。用 `provider = "siliconflow-CN"` 或 `CODEWHALE_PROVIDER=siliconflow-CN` 选择它。 |
|
||||
| `arcee` | `[providers.arcee]` | `ARCEE_API_KEY` | `ARCEE_BASE_URL`;默认 `https://api.arcee.ai/api/v1` | `trinity-large-thinking`, `trinity-large-preview` | Arcee AI 直连 OpenAI 兼容路由,按 256K 上下文 BF16 服务跟踪。接受 `ARCEE_MODEL`。OpenRouter 的 `arcee-ai/trinity-large-thinking` 仍是 OpenRouter 命名空间的模型 ID;直连 Arcee 使用裸 `trinity-large-thinking` ID。 |
|
||||
| `moonshot` | `[providers.moonshot]` | `MOONSHOT_API_KEY`, `KIMI_API_KEY` | `MOONSHOT_BASE_URL`, `KIMI_BASE_URL`;默认 `https://api.moonshot.ai/v1` | 直连 Moonshot:`kimi-k3`, `kimi-k2.7-code`, `kimi-k2.7-code-highspeed`, `kimi-k2.6`;Kimi Code 会员:`k3`, `kimi-for-coding`, `kimi-for-coding-highspeed`(在 `https://api.kimi.com/coding/v1`) | Moonshot/Kimi 路由。精确的直连 `kimi-k3` 路由使用文档中记载的 Formula 网页搜索工具/fiber 循环;直连的 `kimi-k2.6` 保留内置的 `$web_search` 约定,精确的 Kimi Code 会员路由使用其结构化的 `/search` 服务。相邻路径、K2.7 直连模型以及跨产品的模型 ID 不会继承原生搜索。`kimi` 和 `kimi-k2` 别名选择 `kimi-k2.7-code`;接受 `MOONSHOT_MODEL`, `KIMI_MODEL_NAME` 和 `KIMI_MODEL`。Kimi 思考通过 `reasoning_content` 流式返回;Codewhale 把它保留在 Thinking 单元格中,并为思考/工具调用连续性重放它。直连 K3 请使用精确的 `base_url = "https://api.moonshot.ai/v1"` 和 `model = "kimi-k3"`;它始终思考,接收顶层 `reasoning_effort = "low" \| "high" \| "max"`(`off` 规范化为 `low`),只使用 `max_completion_tokens`,并按 [K3 快速入门](https://platform.kimi.ai/docs/guide/kimi-k3-quickstart)省略 `temperature`/`top_p`。Kimi Code K3 请使用来自 [Kimi Code 控制台](https://www.kimi.com/code/console)的密钥、精确的 `base_url = "https://api.kimi.com/coding/v1"` 和裸 `model = "k3"`;`off` 变成启用的 `low`,而正常分派的 `auto` 选择并发送具体的 Codewhale 层级。只有省略推理设置时才由提供商默认值控制。该会员路由默认安全地使用 262,144 上下文 token;[Kimi Code 模型层级表](https://www.kimi.com/code/docs/en/kimi-code/models.html)授予 Allegretto 及以上套餐最高 1M,这些套餐可将其表示为 `context_window = 1048576`。`k3[1m]` 仅限 Claude Code,Codewhale 拒绝它。`kimi-for-coding` 仍是有效的 K2.7 会员路由,`kimi-for-coding-highspeed` 是它自己的高速名册条目(262,144 上下文);会员 id 在直连平台端点上被拒绝,`kimi-k3` 在会员端点上仍被拒绝。计费由路由解析到的端点决定,对照两个精确的产品端点各判断一次:直连 Moonshot(`https://api.moonshot.ai/v1` 或默认值)按用量计费并显示美元估算,精确的 Kimi Code 会员端点按 Kimi Code 额度计费且从不显示美元估算,其他任何情况——网关主机、邻近的 Kimi 托管路径——报告 `cost: unknown` 而不是借用任一产品。导入的没有 `base_url` 的 Kimi Code token 仍解析到会员端点,因此按 Kimi Code 额度计费,绝不累积美元。完成的回合(父智能体或子智能体)从构建其客户端时不可变的端点回执计费,绝不从之后重新读取的配置计费:`MOONSHOT_BASE_URL`/`KIMI_BASE_URL` 只合并到*活动*提供商的表中,回合内的提供商切换可以把常驻配置移离实际运行的路由。遗留的 `auth_mode = "kimi_oauth"` 在不探测 Kimi CLI 文件的情况下失败于 API 密钥指引。Codewhale 不冒充 `kimi_cli` 或 `kimi_code_cli`。**中国区密钥:** 贡献者现场证据(@vFONGv,PR #5229,Windows 10 上验证)报告中国区 Moonshot 密钥必须搭配 `base_url = "https://api.moonshot.cn/v1"`;留在默认国际主机(`https://api.moonshot.ai/v1`)上会认证失败。我们自己没有中国区密钥来验证这一点,因此记录为用户报告而非测试过的路由。另请注意,仅编辑 `base_url` 不会生效,直到为该提供商重新运行 `codewhale auth set`。 |
|
||||
| `google` | `[providers.google]` | `GOOGLE_API_KEY`, `GEMINI_API_KEY` | `GOOGLE_BASE_URL`, `GEMINI_BASE_URL`;默认 `https://generativelanguage.googleapis.com/v1beta/openai/` | `gemini-3.1-pro-preview`(默认);`/model` 还列出 `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 作为官方 OpenAI 兼容 Chat Completions 路由上的自有后端。思考模型在工具调用时捕获 `extra_content.google.thought_signature` 并在助手工具调用消息中重放它;重放一个未捕获签名的工具调用会失败关闭并给出可操作的错误,而不是让工具循环中断。`gemini-2.5-flash-lite` 默认关闭思考,并以警告降级。推理强度映射到文档化的 `google.thinking_config.thinking_level`(`low`/`high`)。该方言绑定精确的官方 base URL:指向其他网关的 `google` 行获得普通 OpenAI 语义且无签名要求。Codewhale 从不读取 Google OAuth 文件;只使用 AI Studio API 密钥。本环境未对真实端点做实时测试。 |
|
||||
| `google` | `[providers.google]` | `GOOGLE_API_KEY`, `GEMINI_API_KEY` | `GOOGLE_BASE_URL`, `GEMINI_BASE_URL`;默认 `https://generativelanguage.googleapis.com/v1beta/openai/` | `gemini-3.1-pro-preview`(默认);`/model` 还列出 `gemini-4-argon`, `gemini-3-pro-preview`, `gemini-3.8-flash`, `gemini-3.6-flash`, `gemini-3.5-flash-lite`, `gemini-2.5-pro`, `gemini-2.5-flash` | Google Gemini 作为官方 OpenAI 兼容 Chat Completions 路由上的自有后端。思考模型在工具调用时捕获 `extra_content.google.thought_signature` 并在助手工具调用消息中重放它;重放一个未捕获签名的工具调用会失败关闭并给出可操作的错误,而不是让工具循环中断。`gemini-2.5-flash-lite` 默认关闭思考,并以警告降级。推理强度映射到文档化的 `google.thinking_config.thinking_level`(`low`/`high`)。该方言绑定精确的官方 base URL:指向其他网关的 `google` 行获得普通 OpenAI 语义且无签名要求。Codewhale 从不读取 Google OAuth 文件;只使用 AI Studio API 密钥。本环境未对真实端点做实时测试。 |
|
||||
| `zai` | `[providers.zai]` | `ZAI_API_KEY`, `Z_AI_API_KEY`, `ZHIPU_API_KEY`, `GLM_API_KEY` | `ZAI_BASE_URL`, `Z_AI_BASE_URL`;默认 `https://api.z.ai/api/coding/paas/v4`;通用 API `https://api.z.ai/api/paas/v4` 和 `https://open.bigmodel.cn/api/paas/v4` | `GLM-5.3` 默认;`/model` 还列出 `GLM-5.3-Flash`, `GLM-5.2`, `GLM-5.1` 和 `GLM-5-Turbo` | Z.AI GLM Coding Plan 路由。三条第一方 Chat 路由(api.z.ai 的两个产品与 BigModel 通用平台端点)共用同一种请求方言,因此推理控制——GLM-5.2 的思考开关、分档思考强度,以及把 `off` 改写为 `enabled` + `reasoning_effort: "low"` 的 GLM-5.3 强制思考改写——在 BigModel 上同样生效;`/preview` 等相邻路径仍保持失败关闭。两个通用 API 产品提供结构化的提供商原生网页搜索(全球为 `search-prime`,中国区为 `search_std`);Coding Plan 和兼容的自定义端点不会继承它。`GLM-5.3` 是默认值,也是一等选择器行(`model = "GLM-5.3"` 或 `ZAI_MODEL=GLM-5.3`);`GLM-5.3-Flash` 是 1M 多模态的快速同系模型(`model = "GLM-5.3-Flash"`)。显式选择 `GLM-5.2` 会保留它自己的 id。在 Z.ai 发布不同的 5.3 元数据之前,5.3 的限制和推理选项继承自 `GLM-5.2`;5.3 不带价格。Flash 采用已公布的 $0.15/$0.50 价目。在未开通 5.3 的账户上,真实调用仍可能以权限代码 1311 返回 429。 |
|
||||
| `stepfun` | `[providers.stepfun]` | `STEPFUN_API_KEY`, `STEP_API_KEY` | `STEPFUN_BASE_URL`, `STEP_BASE_URL`;默认 `https://api.stepfun.ai/v1`;Coding Plan 端点 `https://api.stepfun.ai/step_plan/v1` | `step-3.7-flash` | StepFun / StepFlash 直连 OpenAI 兼容路由。`/provider` 设置询问密钥属于哪种计费路由——按量付费还是 Step Plan——对照所选端点验证密钥,并把答案只写入 `[providers.stepfun].base_url`。既非两条已识别路由的 base URL 会被保留,问题被跳过。你也可以手动把 `[providers.stepfun].base_url` 或 `STEP_BASE_URL` 设为 Coding Plan URL。离线核算把已识别路由标记为 `stepfun-payg` 或 `stepfun-plan`,不持久化原始端点,只有标准 PAYG 路由接收 token 定价。接受 `STEPFUN_MODEL` 和 `STEP_MODEL`。 |
|
||||
| `minimax` | `[providers.minimax]` | `MINIMAX_API_KEY` | `MINIMAX_BASE_URL`;默认 `https://api.minimax.io/v1`;中国 `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 直连 OpenAI 兼容路由。Codewhale 发送 `reasoning_split = true`,这样 MiniMax 思考与答案文本分开到达。两种 MiniMax 方言都在相同端点和相同密钥上售卖按量付费和 Token Plan,因此计费从凭据*产品*分类,绝不由端点或默认值决定。`[providers.minimax]`/`[providers.minimax_anthropic]` 中的 `mode = "token-plan"`,或形如 `sk-cp…` 的 Token Plan 密钥,按 MiniMax Token Plan 额度计费且无美元估算;显式的按量付费模式(`pay-as-you-go`/`payg`/`metered`)胜过密钥形状。密钥的产品前缀只有在密钥位于配置中、由 `api_key_env` 绑定或作为 `MINIMAX_API_KEY` 导出到官方端点时才可见——通过 `codewhale auth set` 保存的密钥(secret store / OS keyring)刻意不被读取用于计费分类。没有显式模式且没有可见的产品标记时,路由报告 `cost: unknown` 而不是假定按量付费,因此 Token Plan 账户永远不会被收取虚构的美元。自定义/网关端点也以 `cost: unknown` 失败关闭。官方 M3 输入模态是文本、图像和视频;M2.7 仅文本。 |
|
||||
@@ -528,13 +528,13 @@ Kimi 仍然仅支持 API 密钥;对 Kimi 的外部授权被拒绝。
|
||||
| `together` | `[providers.together]` | `TOGETHER_API_KEY` | `TOGETHER_BASE_URL`;默认 `https://api.together.xyz/v1` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash`, `thinkingmachines/inkling` | Together AI OpenAI 兼容路由。接受 `TOGETHER_MODEL`。模型别名 `deepseek-v4-pro` 和 `deepseek-v4-flash` 规范化为 Together 的 org 前缀 ID;`inkling` 和 `together-inkling` 规范化为 Together 发布的小写 Inkling 线协议 ID。Inkling 使用 Thinking Machines 的[官方模型仓库](https://huggingface.co/thinkingmachines/Inkling)中精确的 `none`/`minimal`/`low`/`medium`/`high`/`max` 推理词汇。Together 的[发布帖](https://www.together.ai/blog/together-ai-brings-thinking-machines-labs-new-model-inkling-on-day-0)目前称 Inkling 以 1M 上下文上线,而其[模型详情页](https://www.together.ai/models/inkling)称即将推出 256K 上下文且不公布价格。在 Together 活跃的 `/models` 端点和 Models.dev 目录解决该冲突之前,Inkling 不会种入 Codewhale 的离线选择器,也不会推断路由特定的上下文或成本。 |
|
||||
| `qianfan` | `[providers.qianfan]` | `QIANFAN_API_KEY`, `BAIDU_QIANFAN_API_KEY` | `QIANFAN_BASE_URL`, `BAIDU_QIANFAN_BASE_URL`;默认 `https://api.baiduqianfan.ai/v1` | `ernie-4.0-turbo-8k`;提供商范围的定制 Qianfan 服务/模型 ID 直通 | 百度千帆 OpenAI 兼容路由。请求使用 Bearer 认证和 Chat Completions 负载。接受 `QIANFAN_MODEL` 和 `BAIDU_QIANFAN_MODEL`;别名 `baidu-qianfan`, `baidu_qianfan` 和 `baidu` 解析到该提供商。千帆文档中工具/函数调用按模型范围限定,因此 Codewhale 保留所选线协议模型,把实时能力证明留给后续的路由/能力工作。 |
|
||||
| `openai-codex` | `[providers.openai_codex]` | 官方“使用 ChatGPT 登录”(`codewhale auth chatgpt` / `/provider setup openai-codex`) | 官方端点 `https://api.openai.com/v1` | 当前账户目录;手动配置的模型 ID 仍属于显式选择 | **实验性。** 使用公共 Responses 端点(`/v1/responses`),要求已验证的 `chatgpt.tokens.use.direct` 授权。开源应用动态注册会为所选账户/工作区签发客户端 ID,Codewhale 保护并续期自己的令牌。可选模型由账户目录提供;公开模型表和旧版 Codex 令牌不能证明套餐使用权限。不会自动切换计费路径。设置、额度和预览限制见[使用 ChatGPT 登录](#使用-chatgpt-登录)。 |
|
||||
| `anthropic` | `[providers.anthropic]` | `ANTHROPIC_API_KEY` | `ANTHROPIC_BASE_URL`;默认 `https://api.anthropic.com` | `claude-opus-4-8`, `claude-sonnet-4-6`(默认), `claude-haiku-4-5` | 原生 Anthropic Messages API 路由(`/v1/messages`、`x-api-key` + `anthropic-version: 2023-06-01`)——不是 OpenAI 兼容。通过 `cache_control` 断点提示缓存、自适应思考 + `output_config.effort`、按原样重放带签名的思考块、按 #2961 规范化的缓存遥测。接受 `ANTHROPIC_MODEL`。 |
|
||||
| `anthropic` | `[providers.anthropic]` | `ANTHROPIC_API_KEY` | `ANTHROPIC_BASE_URL`;默认 `https://api.anthropic.com` | `claude-opus-5-5`, `claude-sonnet-5-5`, `claude-fable-5-1`, `claude-sonnet-4-6`(默认), `claude-haiku-5-5` | 原生 Anthropic Messages API 路由(`/v1/messages`、`x-api-key` + `anthropic-version: 2023-06-01`)——不是 OpenAI 兼容。通过 `cache_control` 断点提示缓存、自适应思考 + `output_config.effort`、按原样重放带签名的思考块、按 #2961 规范化的缓存遥测。接受 `ANTHROPIC_MODEL`。 |
|
||||
| `openmodel` | `[providers.openmodel]` | `OPENMODEL_API_KEY` | `OPENMODEL_BASE_URL`;默认 `https://api.openmodel.ai` | `deepseek-v4-flash`;提供商范围的定制模型 ID 直通 | OpenModel Anthropic 兼容 Messages 路由。使用 `/v1/messages`、Bearer 认证和 `anthropic-version: 2023-06-01`;OpenModel 按模型 id 选择 DeepSeek、DashScope、Xiaomi、Claude 和其他路由。接受 `OPENMODEL_MODEL`。 |
|
||||
| `sakana` | `[providers.sakana]` | `FUGU_API_KEY`, `SAKANA_API_KEY` | `SAKANA_BASE_URL`;默认 `https://api.sakana.ai/v1` | `fugu`(默认), `fugu-ultra-20260615` | Sakana AI Fugu OpenAI 兼容路由。标准 Chat Completions 线协议;支持流式。`fugu-ultra-20260615` 是重型/推理变体。环境变量别名:`FUGU_API_KEY`(主), `SAKANA_API_KEY`;提供商别名:`sakana-ai`, `sakana_ai`, `fugu`。 |
|
||||
| `longcat` | `[providers.longcat]` | `LONGCAT_API_KEY` | `LONGCAT_BASE_URL`;默认 `https://api.longcat.chat/openai/v1` | `LongCat-2.0`(默认) | 美团 LongCat 精选模型网关。OpenAI 兼容 Chat Completions 线协议。在 https://longcat.chat/platform 注册获取 API 密钥。提供商别名:`long-cat`, `meituan-longcat`, `meituan`。 |
|
||||
| `opencode-go` | `[providers.opencode_go]` | `OPENCODE_GO_API_KEY` | `OPENCODE_GO_BASE_URL`;默认 `https://opencode.ai/zen/go/v1` | `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` | [OpenCode Go](https://opencode.ai/docs/go/) 订阅路由,使用 OpenAI 兼容 Chat Completions。接受 `OPENCODE_GO_MODEL`。Codewhale 使用裸线协议 ID;常见的 `opencode-go/<model-id>` 输入别名规范化为裸 ID。只在 Anthropic `/messages` 端点文档化的 Go 模型,在 Codewhale 支持按模型选择线协议之前被该路由刻意不公布。计费界面显示 Go 额度而不是 token 价格估算。 |
|
||||
| `opencode-zen` | `[providers.opencode_zen]` | `OPENCODE_ZEN_API_KEY`, 回退 `OPENCODE_API_KEY` | `OPENCODE_ZEN_BASE_URL`;默认 `https://opencode.ai/zen/v1` | `gpt-5.6`(默认);当前的 GPT、Claude、Qwen、DeepSeek、MiniMax、GLM、Kimi、Grok、Muse Spark 和免费模型 ID | [OpenCode Zen](https://opencode.ai/docs/zen/) 模型感知网关。接受 `OPENCODE_ZEN_MODEL`,官方 `opencode/<model-id>` 选择器规范化为裸线协议 ID。每个模型的线协议先取自精选快照,再取自其 [Models.dev](https://models.dev) 行声明的 AI SDK 包:GPT、Grok 和 Muse Spark 行使用 `/responses`;Claude 和大多数 Qwen 行使用 `/messages`;DeepSeek、MiniMax、GLM、Kimi、`qwen3.8-max` 和免费行使用 `/chat/completions`。Responses 和 Chat Completions 用 Bearer `Authorization` 认证,而 Anthropic Messages 用 `x-api-key`;这些路由都不用 ChatGPT/Codex OAuth 指引或头。Gemini 失败关闭,因为其模型特定的 Google 线协议未实现;Models.dev 标记为 `deprecated` 的行以及任何已加载目录都未列出的模型也失败关闭。见 [OpenCode Zen 协议目录](#opencode-zen-协议目录)。 |
|
||||
| `meta` | `[providers.meta]` | `META_MODEL_API_KEY`, `MODEL_API_KEY` | `META_MODEL_API_BASE_URL`, `MODEL_API_BASE_URL`;默认 `https://api.meta.ai/v1` | `muse-spark-1.2`(默认) | [Meta Model API](https://developer.meta.com/ai/resources/blog/build-with-muse-spark/) 公开预览路由,使用 OpenAI 兼容 Chat Completions。Muse Spark 1.2 保留其线协议 ID、工具支持、1M 上下文、32K 输出元数据和 `none` 到 `xhigh` 的推理强度。接受 `META_MODEL_API_MODEL` 和 `MODEL_API_MODEL`。提供商别名:`meta-ai`, `meta_model_api`, `muse`, `muse-spark`。 |
|
||||
| `meta` | `[providers.meta]` | `META_MODEL_API_KEY`, `MODEL_API_KEY` | `META_MODEL_API_BASE_URL`, `MODEL_API_BASE_URL`;默认 `https://api.meta.ai/v1` | `muse-spark-1.2`(默认), `muse-spark-1.3`, `muse-spark-1.3-contributor`, `muse-wonder-1.0`(预览), `muse-spark-1.2-contributor`, `muse-spark-1.1` | [Meta Model API](https://developer.meta.com/ai/resources/blog/build-with-muse-spark/) 公开预览路由,使用 OpenAI 兼容 Chat Completions。默认仍为 `muse-spark-1.2`,保留其线协议 ID、工具支持、1M 上下文、32K 输出元数据和 `none` 到 `xhigh` 的推理强度;[Meta 推荐](https://dev.meta.ai/docs/models.md) 新工作使用 `muse-spark-1.3`(1,048,576 上下文),它仍可选择。接受 `META_MODEL_API_MODEL` 和 `MODEL_API_MODEL`。提供商别名:`meta-ai`, `meta_model_api`, `muse`, `muse-spark`。 |
|
||||
| `telecomjs` | `[providers.telecomjs]` | `TELECOMJS_API_KEY` | `TELECOMJS_BASE_URL`;默认 `https://aigw.telecomjs.com/v1` | 保守回退 `deepseek-v4-pro`;配置密钥后认证的 `/models` 行 | TelecomJS TokenHub OpenAI 兼容 Chat Completions 路由。实时目录按提供商和密钥指纹隔离,过期的行在瞬时刷新失败时存活,不支持的推理请求字段被省略。接受 `TELECOMJS_MODEL`。提供商别名:`telecom-js`, `telecom_js`, `telecomjs-cn`, `tokenhub`。 |
|
||||
| `mistral` | `[providers.mistral]` | `MISTRAL_API_KEY` | `MISTRAL_BASE_URL`;默认 `https://api.mistral.ai/v1` | `mistral-code-latest`(默认;`codestral-latest` 接受为别名), `mistral-medium-latest`(别名:`mistral-medium-3-5`), `mistral-small-latest`(别名:`mistral-small-2603`), `mistral-large-latest` | Mistral AI(la Plateforme)OpenAI 兼容 Chat 路由。在文档化的第一方 HTTPS `/v1` 主机上,Medium 和 Small 发送可调的 `reasoning_effort`(仅 `none` 或 `high`),解析 Mistral 的多态 thinking/text 块,并以相同线协议形状重放存储的思考。已废弃的原生 Magistral ID 仍是显式配置兼容路由:它们始终思考,从不接收可调 effort 字段。Code 和 Large 不推理。除非是文档化的第一方主机之一,自定义 `MISTRAL_BASE_URL` 保持通用 Chat 语义。接受 `MISTRAL_MODEL`。提供商别名:`mistral-ai`, `mistralai`, `la-plateforme`。 |
|
||||
| `edenai` | `[providers.edenai]` | `EDENAI_API_KEY` | `EDENAI_BASE_URL`;默认 `https://api.edenai.run/v3`;欧盟 `https://api.eu.edenai.run/v3` | `deepseek/deepseek-v4-pro`(默认);`provider/model` id 的实时 `/models` 目录 | Eden AI OpenAI 兼容聚合网关。目录行保持提供商范围;通用推理控制被省略,因为受支持的字段取决于所选上游家族。接受 `EDENAI_MODEL`。默认的 `deepseek/deepseek-v4-pro` 只列在全球目录上;在欧盟端点上把 `EDENAI_MODEL`(或 `model`)设为欧盟 `/models` 列表中的一行,例如 `qwen/deepseek-v4-pro`。提供商别名:`eden-ai`, `eden_ai`。 |
|
||||
@@ -543,7 +543,7 @@ Kimi 仍然仅支持 API 密钥;对 Kimi 的外部授权被拒绝。
|
||||
| `concentrate` | `[providers.concentrate]` | `CONCENTRATE_API_KEY` | `CONCENTRATE_BASE_URL`;默认 `https://api.concentrate.ai/v1` | `deepseek-v4-pro`(默认;使用普通目录 ID 时由网关选择上游提供商);形如 `openai/gpt-5.6-sol` 的 `provider/model` ID 会固定一个上游;`concentrate/auto` 是网关自己的路由器;无需认证即可读取的实时 `/v1/models` 目录 | Concentrate OpenAI Responses 兼容网关(`POST /v1/responses`,Bearer 认证,使用 Universal API 密钥)。需主动启用,且仅支持自带密钥(BYOK):用你自己的密钥、走你自己的 Concentrate 账单,Codewhale 不收任何费用,也没有托管的默认路由。请求只携带文档中记载的字段(系统提示词作为 `system` 输入项传递)。约定见:[API 简介](https://concentrate.ai/docs/api-reference/introduction)、[请求参数](https://concentrate.ai/docs/api-reference/endpoint/request-parameters)、[流式传输](https://concentrate.ai/docs/api-reference/endpoint/streaming)、[错误](https://concentrate.ai/docs/api-reference/endpoint/errors)。参见 [Concentrate 说明](#concentrate-说明)。 |
|
||||
| `codewhale` | `[providers.codewhale]` | `CODEWHALE_API_KEY` | `CODEWHALE_API_BASE`;默认 `https://api.codewhale.net/v1` | `deepseek/deepseek-v4-pro`(默认)、`anthropic/claude-sonnet-5`、`openai/gpt-5.6` 仅是离线引导行;目录以已认证的 `GET /v1/models` 返回的、账户已连接的提供商列表为准 | Codewhale API:基于客户已连接到其 Codewhale 账户的提供商密钥,提供账户级的模型访问。一个带 `models:infer` 权限范围的 `cwc_key_…` 账户 API 密钥即可认证所有模型。模型 ID 就是账户目录返回的 `provider/model` 原样字符串,每一行都会声明自己的协议(`chat-completions` → `/v1/chat/completions`,`anthropic-messages` → `/v1/messages`,`responses` → `/v1/responses`);所有协议都使用 `Authorization: Bearer`,绝不使用 `x-api-key`。`CODEWHALE_API_BASE` 必须是 HTTPS,回环地址除外。用 `codewhale account keys set <provider>` 连接提供商密钥。提供商别名:`codewhale-api`, `cw-api`, `codewhale-cloud`。 |
|
||||
| `xai` | `[providers.xai]` | `XAI_API_KEY`、Codewhale 自有的设备 OAuth,或显式的只读 Grok CLI 授权 | `XAI_BASE_URL`;默认 `https://api.x.ai/v1` | `grok-4.6`(默认), `grok-4.7`, `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 兼容 Chat Completions 路由。Grok 4.6 有 500K 上下文窗口、文本/图像输入、函数调用、结构化输出、服务端 web 搜索和 `low`/`medium`/`high`/`xhigh` 推理(默认 `high`)。[Grok 4.7](https://docs.x.ai/docs/models/grok-4.7) 有相同的 500K 窗口、文本/图像输入、函数调用、结构化输出、推理阶梯和 $2.00 / $0.50 缓存 / $6.00 费率;xAI 尚未记录其 web 搜索支持,因此 Codewhale 不声明。Grok 推理无法关闭([推理指南](https://docs.x.ai/docs/guides/reasoning))。提示达到 200K token 时其标准费率翻倍;同样的 2 倍长上下文规则适用于 `grok-4.5`(500K 上下文,$2.00 / $0.30 缓存 / $6.00)和 `grok-4.3`(1M 上下文,$1.25 / $0.20 缓存 / $2.50),按其[模型页](https://docs.x.ai/docs/models/grok-4.5)。没有文档化的 `latest`/`fast` 别名,也没有公布的数字输出上限。**API 密钥**(默认):来自 console.x.ai 的 Bearer token,通过 `XAI_API_KEY` / keyring / `api_key`。**OAuth**:`codewhale auth xai-device` 使用 SSH 友好的设备登录和 Codewhale 自有的存储,它可能自行刷新。现有的 Grok CLI 凭据需要 `codewhale auth external-consent --provider xai --mode read-only`;被授予的外部文件从不刷新或重写。OAuth 在某些 SuperGrok 层级上可能返回 HTTP 403——把 API 密钥作为可靠回退。接受 `XAI_MODEL`。提供商别名:`x-ai`, `x_ai`, `grok`。 |
|
||||
| `modelstudio-token-plan` | `[providers.modelstudio_token_plan]` | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` | `MODELSTUDIO_TOKEN_PLAN_BASE_URL`;默认 `https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1` | `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` | 阿里云 Model Studio Token Plan OpenAI 兼容 Chat Completions 路由。Token Plan 个人版和团队版共享该端点。`qwen3.8-max`、`qwen3.7-plus` 和 `qwen3.7-max` 可以通过 Token Plan Responses Harness 使用提供商原生网页搜索;预览版、Coding Plan 和 Anthropic 路由不会继承该能力。列出的所有模型都是可推理的文本/编码模型。DeepSeek 和 GLM 条目是提供商范围的,不与第一方路由冲突。接受 `MODELSTUDIO_TOKEN_PLAN_MODEL`。提供商别名:`modelstudio-token-plan`, `alibaba-token-plan`, `dashscope-token-plan`。 |
|
||||
| `modelstudio-token-plan` | `[providers.modelstudio_token_plan]` | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` | `MODELSTUDIO_TOKEN_PLAN_BASE_URL`;默认 `https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1` | `qwen3.8-max`(默认), `qwen3.7-plus`, `qwen3.7-max`, `qwen3.6-flash`, `deepseek-v4-pro`, `deepseek-v4-flash-0731`, `glm-5.2` | 阿里云 Model Studio Token Plan OpenAI 兼容 Chat Completions 路由。Token Plan 个人版和团队版共享该端点。`qwen3.8-max`、`qwen3.7-plus` 和 `qwen3.7-max` 可以通过 Token Plan Responses Harness 使用提供商原生网页搜索;预览版、Coding Plan 和 Anthropic 路由不会继承该能力。列出的所有模型都是可推理的文本/编码模型。DeepSeek 和 GLM 条目是提供商范围的,不与第一方路由冲突。接受 `MODELSTUDIO_TOKEN_PLAN_MODEL`。提供商别名:`modelstudio-token-plan`, `alibaba-token-plan`, `dashscope-token-plan`。 |
|
||||
| `modelstudio-token-plan-anthropic` | `[providers.modelstudio_token_plan_anthropic]` | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` | 默认 `https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic` | 与 `modelstudio-token-plan` 相同的模型目录 | Token Plan Anthropic 兼容 Messages 路由(`/apps/anthropic`)。与 OpenAI 方言相同的 API 密钥。提供商别名:`modelstudio-token-plan-anthropic`, `alibaba-token-plan-anthropic`。 |
|
||||
| `modelstudio-coding-plan` | `[providers.modelstudio_coding_plan]` | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` | `MODELSTUDIO_CODING_PLAN_BASE_URL`;默认 `https://coding-intl.dashscope.aliyuncs.com/v1` | `qwen3.8-max`(默认);与 Token Plan 相同的目录 | 阿里云 Model Studio Coding Plan OpenAI 兼容 Chat Completions 路由。接受 `MODELSTUDIO_CODING_PLAN_MODEL`。提供商别名:`modelstudio-coding-plan`, `alibaba-coding-plan`, `dashscope-coding-plan`。 |
|
||||
| `modelstudio-coding-plan-anthropic` | `[providers.modelstudio_coding_plan_anthropic]` | `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` | 默认 `https://coding-intl.dashscope.aliyuncs.com/apps/anthropic` | 与 `modelstudio-coding-plan` 相同的模型目录 | Coding Plan Anthropic 兼容 Messages 路由(`/apps/anthropic`)。提供商别名:`modelstudio-coding-plan-anthropic`, `alibaba-coding-plan-anthropic`。 |
|
||||
@@ -609,7 +609,7 @@ Hub 发布或仓库管理仍然是通过 Hub 原生工具(如 `huggingface_hub
|
||||
|
||||
### Xiaomi MiMo 说明
|
||||
|
||||
`xiaomi-mimo` 默认为 `mimo-v2.5-pro`,用于长上下文推理和编码工作。聊天选择器还暴露 `mimo-v2.5-pro-ultraspeed` 和最新的 Omni 模型 `mimo-v2.5`。Xiaomi MiMo TTS 可通过 `codewhale --provider xiaomi-mimo speech "text" --model tts`(或 `tts` 别名)使用。在 Work 和 Operate 模式中,提供商特定的 `speech` / `tts` 工具在配置了 Xiaomi MiMo 路由时可通过延迟发现使用。
|
||||
`xiaomi-mimo` 默认为 `mimo-v2.6-pro`,用于长上下文推理和编码工作。聊天选择器还暴露 `mimo-v2.6-flash`(已停用的 Omni 模型 `mimo-v2.5` 的替代)和 `mimo-v2.5-pro-ultraspeed`。Xiaomi MiMo TTS 可通过 `codewhale --provider xiaomi-mimo speech "text" --model tts`(或 `tts` 别名)使用。在 Work 和 Operate 模式中,提供商特定的 `speech` / `tts` 工具在配置了 Xiaomi MiMo 路由时可通过延迟发现使用。
|
||||
|
||||
`/provider xiaomi-mimo ultraspeed` 和 `/provider xiaomi-mimo pro-ultraspeed` 都选择 `mimo-v2.5-pro-ultraspeed`。`tts`、`voice-design` 和 `voice-clone` 等语音别名与正常的聊天默认值分开。
|
||||
|
||||
@@ -676,7 +676,7 @@ OpenRouter completions 和静态注册表行包括自 2026 年 4 月起通过 Op
|
||||
| `volcengine` | `DeepSeek-V4-Pro`, `DeepSeek-V4-Flash` | 是 | 是 |
|
||||
| `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` | 是 | 是 |
|
||||
| `orcarouter` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`, `orcarouter/auto` | 是 | 是 |
|
||||
| `xiaomi-mimo` | `mimo-v2.5-pro`, `mimo-v2.5-pro-ultraspeed`, `mimo-v2.5`;语音/TTS ID 通过 `codewhale speech` / `tts` 选择 | 是 | 聊天模型是;语音/TTS 模型否 |
|
||||
| `xiaomi-mimo` | `mimo-v2.6-pro`, `mimo-v2.6-flash`, `mimo-v2.5-pro-ultraspeed`;语音/TTS ID 通过 `codewhale speech` / `tts` 选择 | 是 | 聊天模型是;语音/TTS 模型否 |
|
||||
| `novita` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash` | 是 | 是 |
|
||||
| `fireworks` | `accounts/fireworks/models/deepseek-v4-pro` | 是 | 是 |
|
||||
| `siliconflow` | `deepseek-ai/DeepSeek-V4-Pro`, `deepseek-ai/DeepSeek-V4-Flash` | 是 | 是 |
|
||||
@@ -700,11 +700,11 @@ OpenRouter completions 和静态注册表行包括自 2026 年 4 月起通过 Op
|
||||
| `sakana` | `fugu`, `fugu-ultra-20260615` | 是 | `fugu-ultra-20260615` 是 |
|
||||
| `longcat` | `LongCat-2.0` | 是 | 是 |
|
||||
| `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` | 是 | 是 |
|
||||
| `meta` | `muse-spark-1.2` | 是 | 是 |
|
||||
| `meta` | `muse-spark-1.3`, `muse-spark-1.3-contributor`, `muse-wonder-1.0`, `muse-spark-1.2`, `muse-spark-1.2-contributor` | 是 | 是 |
|
||||
| `xai` | `grok-4.6`, `grok-4.7`, `grok-4.5`, `grok-4.3`, `grok-build`, `grok-composer-2.5-fast`, `grok-4.20-0309-reasoning`, `grok-4.20-0309-non-reasoning` | 是 | `grok-4.6`, `grok-4.7`, `grok-4.5`, `grok-4.3`, `grok-build` 和 `grok-4.20-0309-reasoning` 是 |
|
||||
| `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` | 是 | 除 `gemini-3.5-flash-lite` 外都是 |
|
||||
| `google` | `gemini-4-argon`, `gemini-3.1-pro-preview`, `gemini-3-pro-preview`, `gemini-3.8-flash`, `gemini-3.6-flash`, `gemini-3.5-flash-lite`, `gemini-2.5-pro`, `gemini-2.5-flash` | 是 | 除 `gemini-3.5-flash-lite` 外都是 |
|
||||
| `mistral` | `mistral-code-latest`, `mistral-medium-latest`, `mistral-small-latest`, `mistral-large-latest` | 是 | Medium 和 Small 是(在精确的第一方路由上 `reasoning_effort` 为 `none` 或 `high`);已弃用的原生 Magistral 仍然是始终启用的显式兼容 ID;Code 和 Large 否 |
|
||||
| `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` | 是 | 是 |
|
||||
| `modelstudio-token-plan`, `modelstudio-coding-plan` | `qwen3.8-max`, `qwen3.7-plus`, `qwen3.7-max`, `qwen3.6-flash`, `deepseek-v4-pro`, `deepseek-v4-flash-0731`, `glm-5.2` | 是 | 是 |
|
||||
| `csdn` | `glm_for_coding`;其他市场模型 ID 原样通过 | 是 | 是 |
|
||||
|
||||
AtlasCloud 与配置层保持相同的默认模型,并为 Pro 和 Flash 行添加提供商范围的别名。其他 AtlasCloud 模型 ID 仍应通过 `ATLASCLOUD_MODEL`、配置或可用的实时模型列表来选择。
|
||||
@@ -734,14 +734,17 @@ AtlasCloud 与配置层保持相同的默认模型,并为 Pro 和 Flash 行添
|
||||
| NVIDIA NIM V4 注册表模型 | 1,000,000 | 384,000 | 是 | 是 | 代码中未记录 |
|
||||
| Volcengine Ark V4 模型 ID | 1,000,000 | 384,000 | 是 | 是 | 代码中未记录 |
|
||||
| OpenRouter、Novita、Fireworks、SiliconFlow、SGLang 和 vLLM V4 模型 ID | 1,000,000 | 384,000 | 是 | 否 | 代码中未记录 |
|
||||
| Xiaomi MiMo `mimo-v2.5-pro`, `mimo-v2.5-pro-ultraspeed`, `mimo-v2.5` | 1,000,000 | 131,072 | 是 | 否 | 代码中未记录 |
|
||||
| Xiaomi MiMo `mimo-v2.6-pro`, `mimo-v2.6-flash` | 1,048,576 | 131,072 | 是 | 否 | 代码中未记录 |
|
||||
| Xiaomi MiMo `mimo-v2.5-pro-ultraspeed` | 1,000,000 | 131,072 | 是 | 否 | 代码中未记录 |
|
||||
| OpenRouter Qwen 3.6 Flash / Plus | 1,000,000 | 65,536 | 是 | 否 | 代码中未记录 |
|
||||
| OpenRouter Qwen 3.6 35B / 27B | 262,144 | 262,140 | 是 | 否 | 代码中未记录 |
|
||||
| OpenRouter Qwen 3.6 Max Preview | 262,144 | 65,536 | 是 | 否 | 代码中未记录 |
|
||||
| OpenAI API `gpt-5.5` | 1,050,000 | 128,000 | 是 | 否 | 代码中未记录 |
|
||||
| OpenAI API `gpt-5.6`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna` | 1,050,000 | 128,000 | 是 | 否 | 代码中未记录 |
|
||||
| Anthropic API `claude-opus-5`, `claude-opus-4-8`, `claude-sonnet-5`, `claude-sonnet-4-6`, `claude-fable-5` | 1,000,000 | 128,000 | 是 | 是 | 代码中未记录 |
|
||||
| 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 | 取决于模型 | 否 | 代码中未记录 |
|
||||
| Google Gemini API `gemini-4-argon` | 1,048,576 | 未公布 | 取决于模型 | 否 | 代码中未记录 |
|
||||
| Google Gemini API `gemini-3.8-flash`, `gemini-3.6-flash`, `gemini-3.5-flash-lite`, `gemini-3.1-pro-preview`, `gemini-2.5-pro`, `gemini-2.5-flash` | 1,048,576 | 65,536 | 取决于模型 | 否 | 代码中未记录 |
|
||||
| Meta Model API `muse-spark-1.3`, `muse-spark-1.3-contributor`, `muse-wonder-1.0` | 1,048,576 | 未公布 | 是 | 否 | 代码中未记录 |
|
||||
| Meta Model API `muse-spark-1.2` | 1,000,000 | 32,000 | 是 | 否 | 代码中未记录 |
|
||||
| ChatGPT 套餐路由(`openai-codex`) | 保守预算;账户列表不提供窗口大小 | 预览请求不发送输出上限 | 取决于模型 | 否 | 公共 `/v1/responses`;不从账户访问权限推断上下文上限 |
|
||||
| OpenModel 默认/自定义模型 ID | 回退 200,000,除非模型元数据或配置覆盖 | 回退 64,000 | 取决于模型 | 否 | 路由在 `/v1/messages` 使用 Messages 负载 |
|
||||
@@ -800,7 +803,7 @@ MiniMax M3 使用输入长度和服务层级。Codewhale 省略 `service_tier`
|
||||
|
||||
更改 `provider`、`base_url` 或 `model` 可以选择支持 OpenAI 兼容负载形态的路由,但 Codewhale 无法在模型已将其作为散文发出之后,把任意的 JSON 文本转换成受信的工具调用。
|
||||
|
||||
DeepSeek 将于 2026-07-24 15:59 UTC 退役 `deepseek-chat` 和 `deepseek-reasoner`。在请求到达 DeepSeek 第一方 OpenAI 或 Anthropic 端点之前,Codewhale 会把任一名称迁移到 `deepseek-v4-flash`。如果未配置推理层级,`deepseek-chat` 也会迁移到 `off`,`deepseek-reasoner` 迁移到 `high`,保留它们原先的非思考/思考意图;显式的 `reasoning_effort` 仍然权威。该映射刻意不是全局的:Wanjie Ark、聚合器、自托管运行时和自定义端点继续拥有它们自己的模型 id。
|
||||
DeepSeek 已于 2026-07-24 15:59 UTC 退役 `deepseek-chat` 和 `deepseek-reasoner`。在请求到达 DeepSeek 第一方 OpenAI 或 Anthropic 端点之前,Codewhale 会把任一名称迁移到 `deepseek-flash`。如果未配置推理层级,`deepseek-chat` 也会迁移到 `off`,`deepseek-reasoner` 迁移到 `high`,保留它们原先的非思考/思考意图;显式的 `reasoning_effort` 仍然权威。该映射刻意不是全局的:Wanjie Ark、聚合器、自托管运行时和自定义端点继续拥有它们自己的模型 id。
|
||||
|
||||
## 推理强度
|
||||
|
||||
|
||||
@@ -151,6 +151,12 @@ MCP 工具是动态的。连接成功的服务器会从 `~/.codewhale/mcp.json`
|
||||
让每个条目对照当前目录与策略重新校验。会话同步会清空它。
|
||||
缓存无法让已移除、已被拒绝或刚刚变为预加载的工具复活。
|
||||
|
||||
如果某次搜索的激活把之前激活的工具挤出了缓存,这次搜索的结果会在
|
||||
`evicted_tool_references` 中列出它,告诉模型该工具已不可调用,而不是让它在下一次请求里
|
||||
悄悄消失。只列出真正离开激活集合的工具;刚刚变为预加载的工具仍可调用,不会列出。
|
||||
已知限制:在搜索之外,按回合重新校验时被丢弃的工具(已移除、已被拒绝或不再延迟加载)
|
||||
仍然会被静默丢弃,因为没有工具结果可以携带这条通知。
|
||||
|
||||
每个子智能体都有自己的、经策略过滤的延迟目录,始终存在的 `tool_search`,
|
||||
以及有界的激活缓存。分叉出来的消息和指令仍留在上下文(context)中,
|
||||
但子智能体的缓存从空开始,并在本地发现工具;分叉的上下文和缓存都不能变成发现白名单。
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -127,7 +127,6 @@ env = ["MODELSTUDIO_API_KEY", "DASHSCOPE_API_KEY"]
|
||||
default = "qwen3.8-max"
|
||||
models = [
|
||||
"qwen3.8-max",
|
||||
"qwen3.8-max-preview",
|
||||
"qwen3.7-plus",
|
||||
"qwen3.7-max",
|
||||
"qwen3.6-flash",
|
||||
@@ -146,7 +145,6 @@ env = ["MODELSTUDIO_API_KEY", "DASHSCOPE_API_KEY"]
|
||||
default = "qwen3.8-max"
|
||||
models = [
|
||||
"qwen3.8-max",
|
||||
"qwen3.8-max-preview",
|
||||
"qwen3.7-plus",
|
||||
"qwen3.7-max",
|
||||
"qwen3.6-flash",
|
||||
@@ -165,7 +163,6 @@ env = ["MODELSTUDIO_API_KEY", "DASHSCOPE_API_KEY"]
|
||||
default = "qwen3.8-max"
|
||||
models = [
|
||||
{ id = "qwen3.8-max", from = "alibaba-token-plan" },
|
||||
{ id = "qwen3.8-max-preview", from = "alibaba-token-plan" },
|
||||
"qwen3.7-plus",
|
||||
{ id = "deepseek-v4-pro", from = "alibaba-token-plan" },
|
||||
{ id = "deepseek-v4-flash-0731", from = "alibaba-token-plan" },
|
||||
@@ -182,7 +179,6 @@ env = ["MODELSTUDIO_API_KEY", "DASHSCOPE_API_KEY"]
|
||||
default = "qwen3.8-max"
|
||||
models = [
|
||||
{ id = "qwen3.8-max", from = "alibaba-token-plan" },
|
||||
{ id = "qwen3.8-max-preview", from = "alibaba-token-plan" },
|
||||
"qwen3.7-plus",
|
||||
{ id = "deepseek-v4-pro", from = "alibaba-token-plan" },
|
||||
{ id = "deepseek-v4-flash-0731", from = "alibaba-token-plan" },
|
||||
@@ -200,6 +196,9 @@ models = [
|
||||
"muse-spark-1.1",
|
||||
"muse-spark-1.2",
|
||||
"muse-spark-1.2-contributor",
|
||||
"muse-spark-1.3",
|
||||
"muse-spark-1.3-contributor",
|
||||
"muse-wonder-1.0",
|
||||
]
|
||||
|
||||
[[providers]]
|
||||
@@ -233,6 +232,10 @@ models = [
|
||||
"claude-opus-5",
|
||||
"claude-sonnet-5",
|
||||
"claude-fable-5",
|
||||
"claude-opus-5-5",
|
||||
"claude-sonnet-5-5",
|
||||
"claude-haiku-5-5",
|
||||
"claude-fable-5-1",
|
||||
]
|
||||
|
||||
[[providers]]
|
||||
@@ -339,10 +342,8 @@ name = "Xiaomi MiMo"
|
||||
api = "https://api-mimo.xiaomi.com/v1"
|
||||
npm = "@ai-sdk/openai-compatible"
|
||||
env = ["XIAOMI_MIMO_API_KEY", "MIMO_API_KEY"]
|
||||
default = "mimo-v2.5-pro"
|
||||
default = "mimo-v2.6-pro"
|
||||
models = [
|
||||
"mimo-v2.5-pro",
|
||||
"mimo-v2.5",
|
||||
"mimo-v2.6-pro",
|
||||
"mimo-v2.6-flash",
|
||||
]
|
||||
|
||||
@@ -342,7 +342,7 @@ class CommittedSeedTests(unittest.TestCase):
|
||||
self.assertEqual(data["_reviewed"], source["reviewed"])
|
||||
lock = json.loads((ROOT / "scripts/catalog/models_dev_seed.lock.json").read_text())
|
||||
self.assertIn(f"fetched {lock['source']['fetched_at']}", data["_meta"]["upstream"])
|
||||
self.assertEqual(len(data["_reviewed"]["public_models"]), 78)
|
||||
self.assertEqual(len(data["_reviewed"]["public_models"]), 91)
|
||||
|
||||
def test_reviewed_malformed_and_duplicate_public_facts_are_refused(self) -> None:
|
||||
sys.path.insert(0, str(ROOT / "scripts"))
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"path": "docs/GUIDE.md",
|
||||
"sha256": "070147fc19193df10e096ff78b32fbb5f775de3f126c0d211c375f50bcd2111e",
|
||||
"content": "# Codewhale User Guide\n\nThis guide is for your first hour with Codewhale. It explains the main\nworkflow, the important safety controls, and where to go next when you need a\ncomplete reference.\n\nCodewhale has deeper reference documents for installation, configuration,\nproviders, modes, keybindings, tools, and operations. Use this page as a guided\nwalkthrough, then follow the \"Next\" links when you need every option.\n\n## 1. Welcome to Codewhale\n\nCodewhale is a terminal coding agent. You run it from a workspace, give it a\ntask, and it can use structured tools to inspect files, run commands, edit\ncode, and report back with evidence.\n\nThe important difference from a normal chat model is that Codewhale is built\naround a harness:\n\n- It keeps the active workspace and session visible.\n- It routes each turn through explicit modes and approval rules.\n- It shows tool calls in the transcript instead of hiding the work.\n- It can preserve sessions, fork conversations, and continue later.\n- It can run sub-agents for focused background work.\n\nYou can use Codewhale for small questions:\n\n```text\nExplain the authentication flow in this repository.\n```\n\nYou can also use it for multi-step work:\n\n```text\nFind the failing validation path, propose a fix, and wait for my approval\nbefore editing files.\n```\n\nFor a new repository, start conservatively. Ask Codewhale to explore and plan\nbefore asking it to change files. That gives you a reviewable path and makes it\neasier to catch wrong assumptions early.\n\nNext: [ARCHITECTURE.md](ARCHITECTURE.md) explains the internal harness and\nruntime model.\n\n## 2. First Launch\n\nFor a new macOS or Linux installation, use the official GitHub release.\nThe installer verifies the release checksums and provides the same runtime\nunder the `codewhale` and `codew` command names:\n\n```bash\ncurl -fsSL https://codewhale.net/install.sh | sh\n```\n\nWindows users should choose the matching installer or archive from\n[GitHub Releases](https://github.com/codewhale-hq/CodeWhale/releases/latest).\nFor an existing direct install, use `codewhale update --check`, then\n`codewhale update`. npm and Cargo remain secondary packaging routes; Cargo\nalso supports source builds where a compatible prebuilt is unavailable.\nFor occupied directories, package-managed installs, and PATH setup, follow\n[the installation and migration guide](INSTALL.md#recommended-official-github-releases).\nAndroid/Termux uses its own [preview archive or source-build path](INSTALL.md#android--termux-arm64).\n\nDocker is also available when you want an isolated runtime. The published\nimage is currently 0.10.0; to test current `main`, [build it from source](DOCKER.md#building-locally).\n\n```bash\ndocker volume create codewhale-home\ndocker run --rm -it \\\n -e DEEPSEEK_API_KEY=\"$DEEPSEEK_API_KEY\" \\\n -v codewhale-home:/home/codewhale/.codewhale \\\n -v \"$PWD:/workspace\" \\\n -w /workspace \\\n ghcr.io/hmbown/codewhale:latest\n```\n\nOnce the install directory is on PATH, launch Codewhale from the repository or\ndirectory you want it to work in:\n\n```bash\ncodewhale\n```\n\nFor the default GitHub installer destination, you can use\n`\"$HOME/.local/bin/codewhale\"` until that directory is on PATH.\n\nOn first launch, Codewhale opens the composer, even with no key or route.\nWith no key or route, workspace trust is asked once a provider is connected;\notherwise only when the folder requires a decision. A provider is asked for\nwhen you send your first message: the message stays in the box while you sign\nin or use your own key, and a local model is offered only when a local Ollama\nserver answers. The provider step also has an explicit offline route.\n\nEverything optional stays available after that. Use `/setup` for the\nprogressive setup and repair guide, `/settings` for the full typed editor, and\n`/constitution` when you want your own constitution on top of the bundled one.\nThe localized telemetry choice appears only after the workspace is ready and\ndoes not block the composer.\n\nDeepSeek is the default provider. If you want to configure its key before or\nafter the first launch, the most direct setup path is:\n\n```bash\ncodewhale auth set --provider deepseek\n```\n\nYou can also provide a key through the environment:\n\n```bash\nexport DEEPSEEK_API_KEY=\"your-key\"\ncodewhale\n```\n\nNew Codewhale config is stored under `~/.codewhale/config.toml`. Legacy\n`~/.deepseek/config.toml` files are still supported for users migrating from\nthe old name.\n\nUse `/constitution` to review or change standing guidance. After setup, run a\ndoctor check:\n\n```bash\ncodewhale doctor\n```\n\nUse the JSON form when you need a machine-readable report for an issue:\n\n```bash\ncodewhale doctor --json\n```\n\nBoth forms are offline by default. They report structural configuration and\nliteral unknown/not-probed credential states without loading workspace `.env`\ncredentials, openiLine truncated
|
||||
"sha256": "a66c3dda8fef31d70746eb9b11e4a734ee0acfe68addd4d3b35d07489f07cc61",
|
||||
"content": "# Codewhale User Guide\n\nThis guide is for your first hour with Codewhale. It explains the main\nworkflow, the important safety controls, and where to go next when you need a\ncomplete reference.\n\nCodewhale has deeper reference documents for installation, configuration,\nproviders, modes, keybindings, tools, and operations. Use this page as a guided\nwalkthrough, then follow the \"Next\" links when you need every option.\n\n## 1. Welcome to Codewhale\n\nCodewhale is a terminal coding agent. You run it from a workspace, give it a\ntask, and it can use structured tools to inspect files, run commands, edit\ncode, and report back with evidence.\n\nThe important difference from a normal chat model is that Codewhale is built\naround a harness:\n\n- It keeps the active workspace and session visible.\n- It routes each turn through explicit modes and approval rules.\n- It shows tool calls in the transcript instead of hiding the work.\n- It can preserve sessions, fork conversations, and continue later.\n- It can run sub-agents for focused background work.\n\nYou can use Codewhale for small questions:\n\n```text\nExplain the authentication flow in this repository.\n```\n\nYou can also use it for multi-step work:\n\n```text\nFind the failing validation path, propose a fix, and wait for my approval\nbefore editing files.\n```\n\nFor a new repository, start conservatively. Ask Codewhale to explore and plan\nbefore asking it to change files. That gives you a reviewable path and makes it\neasier to catch wrong assumptions early.\n\nNext: [ARCHITECTURE.md](ARCHITECTURE.md) explains the internal harness and\nruntime model.\n\n## 2. First Launch\n\nFor a new macOS or Linux installation, use the official GitHub release.\nThe installer verifies the release checksums and provides the same runtime\nunder the `codewhale` and `codew` command names:\n\n```bash\ncurl -fsSL https://codewhale.net/install.sh | sh\n```\n\nWindows users should choose the matching installer or archive from\n[GitHub Releases](https://github.com/codewhale-hq/CodeWhale/releases/latest).\nFor an existing direct install, use `codewhale update --check`, then\n`codewhale update`. npm and Cargo remain secondary packaging routes; Cargo\nalso supports source builds where a compatible prebuilt is unavailable.\nFor occupied directories, package-managed installs, and PATH setup, follow\n[the installation and migration guide](INSTALL.md#recommended-official-github-releases).\nAndroid/Termux uses its own [preview archive or source-build path](INSTALL.md#android--termux-arm64).\n\nDocker is also available when you want an isolated runtime. The published\nimage is currently 0.10.0; to test current `main`, [build it from source](DOCKER.md#building-locally).\n\n```bash\ndocker volume create codewhale-home\ndocker run --rm -it \\\n -e DEEPSEEK_API_KEY=\"$DEEPSEEK_API_KEY\" \\\n -v codewhale-home:/home/codewhale/.codewhale \\\n -v \"$PWD:/workspace\" \\\n -w /workspace \\\n ghcr.io/hmbown/codewhale:latest\n```\n\nOnce the install directory is on PATH, launch Codewhale from the repository or\ndirectory you want it to work in:\n\n```bash\ncodewhale\n```\n\nFor the default GitHub installer destination, you can use\n`\"$HOME/.local/bin/codewhale\"` until that directory is on PATH.\n\nOn first launch, Codewhale opens the composer, even with no key or route.\nWith no key or route, workspace trust is asked once a provider is connected;\notherwise only when the folder requires a decision. A provider is asked for\nwhen you send your first message: the message stays in the box while you sign\nin or use your own key, and a local model is offered only when a local Ollama\nserver answers. The provider step also has an explicit offline route.\n\nEverything optional stays available after that. Use `/setup` for the\nprogressive setup and repair guide, `/settings` for the full typed editor, and\n`/constitution` when you want your own constitution on top of the bundled one.\nThe localized telemetry choice appears only after the workspace is ready and\ndoes not block the composer.\n\nDeepSeek is the default provider. If you want to configure its key before or\nafter the first launch, the most direct setup path is:\n\n```bash\ncodewhale auth set --provider deepseek\n```\n\nYou can also provide a key through the environment:\n\n```bash\nexport DEEPSEEK_API_KEY=\"your-key\"\ncodewhale\n```\n\nNew Codewhale config is stored under `~/.codewhale/config.toml`. Legacy\n`~/.deepseek/config.toml` files are still supported for users migrating from\nthe old name.\n\nUse `/constitution` to review or change standing guidance. After setup, run a\ndoctor check:\n\n```bash\ncodewhale doctor\n```\n\nUse the JSON form when you need a machine-readable report for an issue:\n\n```bash\ncodewhale doctor --json\n```\n\nBoth forms are offline by default. They report structural configuration and\nliteral unknown/not-probed credential states without loading workspace `.env`\ncredentials, openiLine truncated
|
||||
},
|
||||
{
|
||||
"path": "docs/KEYBINDINGS.md",
|
||||
@@ -32,8 +32,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"path": "docs/CONFIGURATION.md",
|
||||
"sha256": "f61542d1de3cd954591e3e4d686a1639d1327016c9e26cf9b92cefedcc5501a3",
|
||||
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
|
||||
"sha256": "d86ea7aebae614a2567bad8790978e0a85791a405f052ad5906aa284e7b58314",
|
||||
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
|
||||
},
|
||||
{
|
||||
"path": "docs/CODEWHALE_AGENT.md",
|
||||
@@ -48,8 +48,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"path": "docs/PROVIDERS.md",
|
||||
"sha256": "aef170b600dcdc4b461fe7214072a1b3caa313b714f894461ba894e3b0124d99",
|
||||
"content": "# Provider Registry\n\n> 阅读简体中文版:[zh_hans/PROVIDERS.md](zh_hans/PROVIDERS.md)\n\nSpeech recognition, synthesis, translation and video have separate execution\npaths. See [media models](MEDIA_MODELS.md) for current support and reviewed\nupstream candidates; a chat catalogue row alone does not add a media backend.\n\nThis registry describes provider behavior that is wired into the current\nCodewhale codebase. It is intentionally conservative: shipped entries are\nlimited to provider IDs, config keys, auth paths, base URLs, model resolution,\nand capability metadata that the code already knows about.\n\nDeepSeek remains the default provider, but every entry in `ProviderKind::ALL`\nis a first-class selectable provider route. `ALL` is the catalog/picker\nsurface — one identity per vendor. Dual-wire dialect kinds (`*Anthropic`, e.g.\n`deepseek-anthropic`) and the Model Studio plan variants stay on the enum for\nserde and `provider_for_kind` but are deliberately **not** catalog rows:\na plan is `mode`/`base_url` and a dialect is `wire = openai|anthropic` on the\nprimary provider config (`crates/config/src/provider_kind.rs:221-226`). Hosted\nroutes, generic OpenAI-compatible endpoints, the OpenAI Codex/ChatGPT route,\nnative Anthropic, and local runtimes all run the same terminal harness against\nthe selected provider/model/base URL.\n\nA host reached over plain Chat Completions is an ordinary named provider,\nnot a `ProviderKind`: enum variants are reserved for distinct *wires*\n(Anthropic Messages, Codex Responses, Google thought signatures). Any such\nhost is a `[providers.<name>]` table with a base URL, a model, and a key env\n(`docs/CONFIGURATION.md`); `/provider` and `/setup` keep a \"paste a Base URL\nand a key\" path for exactly this. Offerings come from live `GET /v1/models`\nplus the Codewhale catalog rather than a compiled roster (#5350, #6289).\n\nKnown-good hosts. These ship as bundled descriptor rows in\n`crates/config/assets/provider_descriptors.json` (compiled in by\n`crates/config/src/descriptors.rs`): each row says how to reach the host — wire,\nbase URL, key env, aliases — while model ids stay live from `GET /v1/models`\nand the Codewhale catalog; the example model is only a bootstrap hint. Verify\nagainst the vendor's own docs before trusting any value here:\n\n| Host | Base URL | Example models | API key env |\n| --- | --- | --- | --- |\n| SenseNova | `https://token.sensenova.cn/v1` | `deepseek-v4-flash` | `SENSENOVA_API_KEY` |\n| Baseten | `https://inference.baseten.co/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `BASETEN_API_KEY` |\n| Groq | `https://api.groq.com/openai/v1` | `llama-3.3-70b-versatile` | `GROQ_API_KEY` |\n| Cerebras | `https://api.cerebras.ai/v1` | `llama-3.3-70b` | `CEREBRAS_API_KEY` |\n| Command Code | `https://api.commandcode.ai/provider/v1` | `deepseek/deepseek-v4-flash` | `COMMAND_CODE_API_KEY` |\n| Alibaba Model Studio (DashScope) | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `qwen3.8-flash` | `DASHSCOPE_API_KEY` |\n| AICraft | `https://aicraftapi.com/v1` | `claude-4.6-sonnet`; DeepSeek / Claude / Gemini / Qwen / GLM / MiniMax / Doubao families | `AICRAFT_API_KEY` |\n| Tsubasa | `https://api.tsubasa.sh/v1` | `tsubasa-pro`, `tsubasa-fast` (32,768-token context) | `TSUBASA_API_KEY` |\n| Cheaper Inference | `https://api.cheaperinference.com/v1` | `gpt-5.4-mini`, `claude-sonnet-5`, `gemini-3.1-pro` | `CHEAPER_INFERENCE_API_KEY` |\n| Yolo-Auto | `https://yolo-auto.com/v1` | `qwen3.8-flash`; `yolo` / `yolo-small` | `YOLO_AUTO_API_KEY` |\n| Standard Compute | `https://api.stdcmpt.com/v1` | `standardcompute` (router); `deepseek/deepseek-v4-pro`, `anthropic/claude-sonnet-5.5` | `STANDARDCOMPUTE_API_KEY` |\n\nAICraft's roster spans DeepSeek, Anthropic Claude, Google Gemini, Qwen, GLM,\nMiniMax and Doubao ids on its OpenAI-compatible endpoint. The authority is\n`GET https://aicraftapi.com/v1/models` with your key — pick a model from that\nlist, not from this table.\nTsubasa implements only `GET /v1/models` and Chat Completions. Its two public\nmodel ids share a 32,768-token context, smaller than the 128,000 tokens Codewhale assumes\nfor an unknown model, so set it on the route after saving:\n`codewhale config set providers.tsubasa.context_window 32768`.\n\nCheaper Inference is an OpenAI-compatible gateway with one key for models from\nseveral labs. Model ids are bare, such as `gpt-5.4-mini` or `claude-sonnet-5`.\nPricing varies by model and route; consult the provider’s current catalog.\nThe authority is `GET https://api.cheaperinference.com/v1/models` with your key.\nDocs: <https://cheaperinference.com/docs>.\n\nStandard Compute offers flat monthly plans with a compute budget. By default,\nrequests return HTTP 402 when it is used; eligible plans can enable Pay as you go\nto continue with additional prepaid charges. See its\n[budget policy](https://docs.standardcompute.com/budgets-and-limits).\nThe `standardcompute` model id roLine truncated
|
||||
"sha256": "afbeb0ad27a3e919bd3e72538aa6a930c40529083270729ced489231eb1c6f68",
|
||||
"content": "# Provider Registry\n\n> 阅读简体中文版:[zh_hans/PROVIDERS.md](zh_hans/PROVIDERS.md)\n\nSpeech recognition, synthesis, translation and video have separate execution\npaths. See [media models](MEDIA_MODELS.md) for current support and reviewed\nupstream candidates; a chat catalogue row alone does not add a media backend.\n\nThis registry describes provider behavior that is wired into the current\nCodewhale codebase. It is intentionally conservative: shipped entries are\nlimited to provider IDs, config keys, auth paths, base URLs, model resolution,\nand capability metadata that the code already knows about.\n\nDeepSeek remains the default provider, but every entry in `ProviderKind::ALL`\nis a first-class selectable provider route. `ALL` is the catalog/picker\nsurface — one identity per vendor. Dual-wire dialect kinds (`*Anthropic`, e.g.\n`deepseek-anthropic`) and the Model Studio plan variants stay on the enum for\nserde and `provider_for_kind` but are deliberately **not** catalog rows:\na plan is `mode`/`base_url` and a dialect is `wire = openai|anthropic` on the\nprimary provider config (`crates/config/src/provider_kind.rs:221-226`). Hosted\nroutes, generic OpenAI-compatible endpoints, the OpenAI Codex/ChatGPT route,\nnative Anthropic, and local runtimes all run the same terminal harness against\nthe selected provider/model/base URL.\n\nA host reached over plain Chat Completions is an ordinary named provider,\nnot a `ProviderKind`: enum variants are reserved for distinct *wires*\n(Anthropic Messages, Codex Responses, Google thought signatures). Any such\nhost is a `[providers.<name>]` table with a base URL, a model, and a key env\n(`docs/CONFIGURATION.md`); `/provider` and `/setup` keep a \"paste a Base URL\nand a key\" path for exactly this. Offerings come from live `GET /v1/models`\nplus the Codewhale catalog rather than a compiled roster (#5350, #6289).\n\nKnown-good hosts. These ship as bundled descriptor rows in\n`crates/config/assets/provider_descriptors.json` (compiled in by\n`crates/config/src/descriptors.rs`): each row says how to reach the host — wire,\nbase URL, key env, aliases — while model ids stay live from `GET /v1/models`\nand the Codewhale catalog; the example model is only a bootstrap hint. Verify\nagainst the vendor's own docs before trusting any value here:\n\n| Host | Base URL | Example models | API key env |\n| --- | --- | --- | --- |\n| SenseNova | `https://token.sensenova.cn/v1` | `deepseek-v4-flash` | `SENSENOVA_API_KEY` |\n| Baseten | `https://inference.baseten.co/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `BASETEN_API_KEY` |\n| Groq | `https://api.groq.com/openai/v1` | `llama-3.3-70b-versatile` | `GROQ_API_KEY` |\n| Cerebras | `https://api.cerebras.ai/v1` | `llama-3.3-70b` | `CEREBRAS_API_KEY` |\n| Command Code | `https://api.commandcode.ai/provider/v1` | `deepseek/deepseek-v4-flash` | `COMMAND_CODE_API_KEY` |\n| Alibaba Model Studio (DashScope) | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `qwen3.8-flash` | `DASHSCOPE_API_KEY` |\n| AICraft | `https://aicraftapi.com/v1` | `claude-4.6-sonnet`; DeepSeek / Claude / Gemini / Qwen / GLM / MiniMax / Doubao families | `AICRAFT_API_KEY` |\n| Tsubasa | `https://api.tsubasa.sh/v1` | `tsubasa-pro`, `tsubasa-fast` (32,768-token context) | `TSUBASA_API_KEY` |\n| Cheaper Inference | `https://api.cheaperinference.com/v1` | `gpt-5.4-mini`, `claude-sonnet-5`, `gemini-3.1-pro` | `CHEAPER_INFERENCE_API_KEY` |\n| Yolo-Auto | `https://yolo-auto.com/v1` | `qwen3.8-flash`; `yolo` / `yolo-small` | `YOLO_AUTO_API_KEY` |\n| Standard Compute | `https://api.stdcmpt.com/v1` | `standardcompute` (router); `deepseek/deepseek-v4-pro`, `anthropic/claude-sonnet-5.5` | `STANDARDCOMPUTE_API_KEY` |\n\nAICraft's roster spans DeepSeek, Anthropic Claude, Google Gemini, Qwen, GLM,\nMiniMax and Doubao ids on its OpenAI-compatible endpoint. The authority is\n`GET https://aicraftapi.com/v1/models` with your key — pick a model from that\nlist, not from this table.\nTsubasa implements only `GET /v1/models` and Chat Completions. Its two public\nmodel ids share a 32,768-token context, smaller than the 128,000 tokens Codewhale assumes\nfor an unknown model, so set it on the route after saving:\n`codewhale config set providers.tsubasa.context_window 32768`.\n\nCheaper Inference is an OpenAI-compatible gateway with one key for models from\nseveral labs. Model ids are bare, such as `gpt-5.4-mini` or `claude-sonnet-5`.\nPricing varies by model and route; consult the provider’s current catalog.\nThe authority is `GET https://api.cheaperinference.com/v1/models` with your key.\nDocs: <https://cheaperinference.com/docs>.\n\nStandard Compute offers flat monthly plans with a compute budget. By default,\nrequests return HTTP 402 when it is used; eligible plans can enable Pay as you go\nto continue with additional prepaid charges. See its\n[budget policy](https://docs.standardcompute.com/budgets-and-limits).\nThe `standardcompute` model id roLine truncated
|
||||
},
|
||||
{
|
||||
"path": "docs/MODEL_LAB.md",
|
||||
@@ -64,8 +64,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"path": "docs/CONFIGURATION.md",
|
||||
"sha256": "f61542d1de3cd954591e3e4d686a1639d1327016c9e26cf9b92cefedcc5501a3",
|
||||
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
|
||||
"sha256": "d86ea7aebae614a2567bad8790978e0a85791a405f052ad5906aa284e7b58314",
|
||||
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
|
||||
},
|
||||
{
|
||||
"path": "docs/LEGACY_PATHS.md",
|
||||
@@ -96,8 +96,8 @@
|
||||
},
|
||||
{
|
||||
"path": "docs/CONFIGURATION.md",
|
||||
"sha256": "f61542d1de3cd954591e3e4d686a1639d1327016c9e26cf9b92cefedcc5501a3",
|
||||
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
|
||||
"sha256": "d86ea7aebae614a2567bad8790978e0a85791a405f052ad5906aa284e7b58314",
|
||||
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -107,8 +107,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"path": "docs/TOOL_SURFACE.md",
|
||||
"sha256": "95e6f75cd887b9216c7ba9a4cbf6f15c6146c39667df0eeaea2704676337dc65",
|
||||
"content": "# Tool surface\n\n> 阅读简体中文版:[zh_hans/TOOL_SURFACE.md](zh_hans/TOOL_SURFACE.md)。\n\nThis document describes the current model-facing tool contract. The v0.9.1\ncutover that produced it is recorded in `docs/RUNTIME_SIMPLIFICATION_DESIGN.md`;\nread the workspace version from `Cargo.toml`, not from this line. The registry\nremains larger than the first-turn catalog so\nsaved transcripts can replay and uncommon capabilities can be loaded on demand.\nThe model should learn one canonical name for each common operation.\n\nImplementation sources:\n\n- `crates/tui/src/core/engine/tool_catalog.rs` owns the eager/deferred catalog.\n- `crates/tui/src/tools/registry.rs` registers canonical tools and hidden aliases.\n- `crates/tui/src/tools/{file,file_tool,shell}.rs` own the small foreground\n primitive behavior and schemas; the other native tools remain searchable.\n- `docs/RUNTIME_SIMPLIFICATION_DESIGN.md` records the v0.9.1 cutover and receipt.\n\n## Default-active contract\n\nNew turns start with twelve eager native names plus synthetic `tool_search`:\n\n1. `read`\n2. `write`\n3. `edit`\n4. `file_search`\n5. `bash`\n6. `agent`\n7. `workflow`\n8. `todo_write`\n9. `create_goal`\n10. `get_goal`\n11. `update_goal`\n12. `load_skill`\n13. `tool_search` (synthetic, always active)\n\nThe twelve native names are `DEFAULT_ACTIVE_NATIVE_TOOLS` in\n`crates/tui/src/core/engine/tool_catalog.rs`, pinned by\n`default_active_contract_keeps_discovery_and_core_tools_eager`. An authority\nboundary may remove `agent` at the maximum child depth, but route size alone\nmust not change this core vocabulary.\n\nThe direct schemas deliberately stay small:\n\n| Tool | Input | Purpose |\n|---|---|---|\n| `read` | `path`, optional `offset`, optional `limit` | Read a bounded file window with explicit continuation or truncation notices. |\n| `write` | `path`, `content` | Create or replace a file. |\n| `edit` | `path`, `edits` | Apply one or more unambiguous text replacements against one original snapshot. |\n| `file_search` | `query`, optional `path`, `limit`, `extensions`, `exclude` | Find files by name, path fragment or glob and return bounded, ranked matches. Respects ignore files; `exclude` replaces default exclusions. |\n| `bash` | `command`, optional `timeout`, optional `description` | Run one cancellable foreground shell command and return a bounded tail. The optional description is display-only. |\n| `agent` | delegated task and optional scope/context controls | Start or inspect focused child work. |\n| `workflow` | plan/script/source_path plus run controls | Coordinate multi-agent phases with dependencies and completion checks. |\n| `todo_write` | complete replacement list of `{content, status}` items | Keep optional, agent-owned progress notes for genuinely multi-step work. |\n| `create_goal` | objective plus optional budget | Start the session goal the turn works toward. |\n| `get_goal` | none | Read the active goal and its progress. |\n| `update_goal` | terminal status | Mark the goal complete or blocked. |\n| `load_skill` | optional `name`, `query` | Load a named skill's `SKILL.md` body and companion-file list; omit `name` or use `name=\"list\"` to list eligible skills, or use `query` to search names and descriptions. |\n| `tool_search` | `query`, optional matching controls | Discover policy-allowed deferred tools and add selected schemas to this conversation's toolbox. |\n\nMode is an authority decision, not a synonym system. Plan, Work, and Operate\nuse the same primitive identities. Plan centrally refuses `write`, `edit`, and\n`bash`; Work and Operate still pass those calls through approval, sandbox,\ntrusted-path, repository-law, and managed-policy gates. Full Access changes\nordinary approval behavior but does not bypass hard safety or repository law.\n\n`update_plan` remains registered only for saved-artifact compatibility and is\nnot model-visible. `tasks`, `Git`, `Run`, `Web`, `remember`, and other\nspecialized capabilities are searchable rather than first-turn ceremony.\n\nA Bash description appears as a muted, bounded note under the command on the\nTUI shell card, including on automatic runs. It never replaces the command and\nis excluded from execution, exact approval keys and Auto-Review input. The\noriginal description remains in the recorded tool input and exports. Approval\nprompts, `/jobs`, the activity inspector, ACP and other Runtime clients keep\nshowing the command; this change adds no description row to those surfaces.\n\n## Local code execution\n\n`code_execution` (Python) and `js_execution` (Node.js) use the same\npermission-aware local launcher as workspace task gates and test runs. Ordinary\napproval retains the effective session policy. To retry a denied exact call\nwith wider permissions, supply `sandbox_permissions` (`workspace-write` or\n`danger-full-access`) and a nonempty `justification`; Ask mode requires explicit\none-shot user approval. The approved policy affectLine truncated
|
||||
"sha256": "2c63b6bd3eaa0026811366bd8ebc31822ce7ae5ea4ea3907395eb79d89e96483",
|
||||
"content": "# Tool surface\n\n> 阅读简体中文版:[zh_hans/TOOL_SURFACE.md](zh_hans/TOOL_SURFACE.md)。\n\nThis document describes the current model-facing tool contract. The v0.9.1\ncutover that produced it is recorded in `docs/RUNTIME_SIMPLIFICATION_DESIGN.md`;\nread the workspace version from `Cargo.toml`, not from this line. The registry\nremains larger than the first-turn catalog so\nsaved transcripts can replay and uncommon capabilities can be loaded on demand.\nThe model should learn one canonical name for each common operation.\n\nImplementation sources:\n\n- `crates/tui/src/core/engine/tool_catalog.rs` owns the eager/deferred catalog.\n- `crates/tui/src/tools/registry.rs` registers canonical tools and hidden aliases.\n- `crates/tui/src/tools/{file,file_tool,shell}.rs` own the small foreground\n primitive behavior and schemas; the other native tools remain searchable.\n- `docs/RUNTIME_SIMPLIFICATION_DESIGN.md` records the v0.9.1 cutover and receipt.\n\n## Default-active contract\n\nNew turns start with twelve eager native names plus synthetic `tool_search`:\n\n1. `read`\n2. `write`\n3. `edit`\n4. `file_search`\n5. `bash`\n6. `agent`\n7. `workflow`\n8. `todo_write`\n9. `create_goal`\n10. `get_goal`\n11. `update_goal`\n12. `load_skill`\n13. `tool_search` (synthetic, always active)\n\nThe twelve native names are `DEFAULT_ACTIVE_NATIVE_TOOLS` in\n`crates/tui/src/core/engine/tool_catalog.rs`, pinned by\n`default_active_contract_keeps_discovery_and_core_tools_eager`. An authority\nboundary may remove `agent` at the maximum child depth, but route size alone\nmust not change this core vocabulary.\n\nThe direct schemas deliberately stay small:\n\n| Tool | Input | Purpose |\n|---|---|---|\n| `read` | `path`, optional `offset`, optional `limit` | Read a bounded file window with explicit continuation or truncation notices. |\n| `write` | `path`, `content` | Create or replace a file. |\n| `edit` | `path`, `edits` | Apply one or more unambiguous text replacements against one original snapshot. |\n| `file_search` | `query`, optional `path`, `limit`, `extensions`, `exclude` | Find files by name, path fragment or glob and return bounded, ranked matches. Respects ignore files; `exclude` replaces default exclusions. |\n| `bash` | `command`, optional `timeout`, optional `description` | Run one cancellable foreground shell command and return a bounded tail. The optional description is display-only. |\n| `agent` | delegated task and optional scope/context controls | Start or inspect focused child work. |\n| `workflow` | plan/script/source_path plus run controls | Coordinate multi-agent phases with dependencies and completion checks. |\n| `todo_write` | complete replacement list of `{content, status}` items | Keep optional, agent-owned progress notes for genuinely multi-step work. |\n| `create_goal` | objective plus optional budget | Start the session goal the turn works toward. |\n| `get_goal` | none | Read the active goal and its progress. |\n| `update_goal` | terminal status | Mark the goal complete or blocked. |\n| `load_skill` | optional `name`, `query` | Load a named skill's `SKILL.md` body and companion-file list; omit `name` or use `name=\"list\"` to list eligible skills, or use `query` to search names and descriptions. |\n| `tool_search` | `query`, optional matching controls | Discover policy-allowed deferred tools and add selected schemas to this conversation's toolbox. |\n\nMode is an authority decision, not a synonym system. Plan, Work, and Operate\nuse the same primitive identities. Plan centrally refuses `write`, `edit`, and\n`bash`; Work and Operate still pass those calls through approval, sandbox,\ntrusted-path, repository-law, and managed-policy gates. Full Access changes\nordinary approval behavior but does not bypass hard safety or repository law.\n\n`update_plan` remains registered only for saved-artifact compatibility and is\nnot model-visible. `tasks`, `Git`, `Run`, `Web`, `remember`, and other\nspecialized capabilities are searchable rather than first-turn ceremony.\n\nA Bash description appears as a muted, bounded note under the command on the\nTUI shell card, including on automatic runs. It never replaces the command and\nis excluded from execution, exact approval keys and Auto-Review input. The\noriginal description remains in the recorded tool input and exports. Approval\nprompts, `/jobs`, the activity inspector, ACP and other Runtime clients keep\nshowing the command; this change adds no description row to those surfaces.\n\n## Local code execution\n\n`code_execution` (Python) and `js_execution` (Node.js) use the same\npermission-aware local launcher as workspace task gates and test runs. Ordinary\napproval retains the effective session policy. To retry a denied exact call\nwith wider permissions, supply `sandbox_permissions` (`workspace-write` or\n`danger-full-access`) and a nonempty `justification`; Ask mode requires explicit\none-shot user approval. The approved policy affectLine truncated
|
||||
},
|
||||
{
|
||||
"path": "docs/TOOL_LIFECYCLE.md",
|
||||
@@ -224,8 +224,8 @@
|
||||
},
|
||||
{
|
||||
"path": "docs/CONFIGURATION.md",
|
||||
"sha256": "f61542d1de3cd954591e3e4d686a1639d1327016c9e26cf9b92cefedcc5501a3",
|
||||
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
|
||||
"sha256": "d86ea7aebae614a2567bad8790978e0a85791a405f052ad5906aa284e7b58314",
|
||||
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -256,8 +256,8 @@
|
||||
},
|
||||
{
|
||||
"path": "docs/CONFIGURATION.md",
|
||||
"sha256": "f61542d1de3cd954591e3e4d686a1639d1327016c9e26cf9b92cefedcc5501a3",
|
||||
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
|
||||
"sha256": "d86ea7aebae614a2567bad8790978e0a85791a405f052ad5906aa284e7b58314",
|
||||
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -310,8 +310,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"path": "docs/GUIDE.md",
|
||||
"sha256": "070147fc19193df10e096ff78b32fbb5f775de3f126c0d211c375f50bcd2111e",
|
||||
"content": "# Codewhale User Guide\n\nThis guide is for your first hour with Codewhale. It explains the main\nworkflow, the important safety controls, and where to go next when you need a\ncomplete reference.\n\nCodewhale has deeper reference documents for installation, configuration,\nproviders, modes, keybindings, tools, and operations. Use this page as a guided\nwalkthrough, then follow the \"Next\" links when you need every option.\n\n## 1. Welcome to Codewhale\n\nCodewhale is a terminal coding agent. You run it from a workspace, give it a\ntask, and it can use structured tools to inspect files, run commands, edit\ncode, and report back with evidence.\n\nThe important difference from a normal chat model is that Codewhale is built\naround a harness:\n\n- It keeps the active workspace and session visible.\n- It routes each turn through explicit modes and approval rules.\n- It shows tool calls in the transcript instead of hiding the work.\n- It can preserve sessions, fork conversations, and continue later.\n- It can run sub-agents for focused background work.\n\nYou can use Codewhale for small questions:\n\n```text\nExplain the authentication flow in this repository.\n```\n\nYou can also use it for multi-step work:\n\n```text\nFind the failing validation path, propose a fix, and wait for my approval\nbefore editing files.\n```\n\nFor a new repository, start conservatively. Ask Codewhale to explore and plan\nbefore asking it to change files. That gives you a reviewable path and makes it\neasier to catch wrong assumptions early.\n\nNext: [ARCHITECTURE.md](ARCHITECTURE.md) explains the internal harness and\nruntime model.\n\n## 2. First Launch\n\nFor a new macOS or Linux installation, use the official GitHub release.\nThe installer verifies the release checksums and provides the same runtime\nunder the `codewhale` and `codew` command names:\n\n```bash\ncurl -fsSL https://codewhale.net/install.sh | sh\n```\n\nWindows users should choose the matching installer or archive from\n[GitHub Releases](https://github.com/codewhale-hq/CodeWhale/releases/latest).\nFor an existing direct install, use `codewhale update --check`, then\n`codewhale update`. npm and Cargo remain secondary packaging routes; Cargo\nalso supports source builds where a compatible prebuilt is unavailable.\nFor occupied directories, package-managed installs, and PATH setup, follow\n[the installation and migration guide](INSTALL.md#recommended-official-github-releases).\nAndroid/Termux uses its own [preview archive or source-build path](INSTALL.md#android--termux-arm64).\n\nDocker is also available when you want an isolated runtime. The published\nimage is currently 0.10.0; to test current `main`, [build it from source](DOCKER.md#building-locally).\n\n```bash\ndocker volume create codewhale-home\ndocker run --rm -it \\\n -e DEEPSEEK_API_KEY=\"$DEEPSEEK_API_KEY\" \\\n -v codewhale-home:/home/codewhale/.codewhale \\\n -v \"$PWD:/workspace\" \\\n -w /workspace \\\n ghcr.io/hmbown/codewhale:latest\n```\n\nOnce the install directory is on PATH, launch Codewhale from the repository or\ndirectory you want it to work in:\n\n```bash\ncodewhale\n```\n\nFor the default GitHub installer destination, you can use\n`\"$HOME/.local/bin/codewhale\"` until that directory is on PATH.\n\nOn first launch, Codewhale opens the composer, even with no key or route.\nWith no key or route, workspace trust is asked once a provider is connected;\notherwise only when the folder requires a decision. A provider is asked for\nwhen you send your first message: the message stays in the box while you sign\nin or use your own key, and a local model is offered only when a local Ollama\nserver answers. The provider step also has an explicit offline route.\n\nEverything optional stays available after that. Use `/setup` for the\nprogressive setup and repair guide, `/settings` for the full typed editor, and\n`/constitution` when you want your own constitution on top of the bundled one.\nThe localized telemetry choice appears only after the workspace is ready and\ndoes not block the composer.\n\nDeepSeek is the default provider. If you want to configure its key before or\nafter the first launch, the most direct setup path is:\n\n```bash\ncodewhale auth set --provider deepseek\n```\n\nYou can also provide a key through the environment:\n\n```bash\nexport DEEPSEEK_API_KEY=\"your-key\"\ncodewhale\n```\n\nNew Codewhale config is stored under `~/.codewhale/config.toml`. Legacy\n`~/.deepseek/config.toml` files are still supported for users migrating from\nthe old name.\n\nUse `/constitution` to review or change standing guidance. After setup, run a\ndoctor check:\n\n```bash\ncodewhale doctor\n```\n\nUse the JSON form when you need a machine-readable report for an issue:\n\n```bash\ncodewhale doctor --json\n```\n\nBoth forms are offline by default. They report structural configuration and\nliteral unknown/not-probed credential states without loading workspace `.env`\ncredentials, openiLine truncated
|
||||
"sha256": "a66c3dda8fef31d70746eb9b11e4a734ee0acfe68addd4d3b35d07489f07cc61",
|
||||
"content": "# Codewhale User Guide\n\nThis guide is for your first hour with Codewhale. It explains the main\nworkflow, the important safety controls, and where to go next when you need a\ncomplete reference.\n\nCodewhale has deeper reference documents for installation, configuration,\nproviders, modes, keybindings, tools, and operations. Use this page as a guided\nwalkthrough, then follow the \"Next\" links when you need every option.\n\n## 1. Welcome to Codewhale\n\nCodewhale is a terminal coding agent. You run it from a workspace, give it a\ntask, and it can use structured tools to inspect files, run commands, edit\ncode, and report back with evidence.\n\nThe important difference from a normal chat model is that Codewhale is built\naround a harness:\n\n- It keeps the active workspace and session visible.\n- It routes each turn through explicit modes and approval rules.\n- It shows tool calls in the transcript instead of hiding the work.\n- It can preserve sessions, fork conversations, and continue later.\n- It can run sub-agents for focused background work.\n\nYou can use Codewhale for small questions:\n\n```text\nExplain the authentication flow in this repository.\n```\n\nYou can also use it for multi-step work:\n\n```text\nFind the failing validation path, propose a fix, and wait for my approval\nbefore editing files.\n```\n\nFor a new repository, start conservatively. Ask Codewhale to explore and plan\nbefore asking it to change files. That gives you a reviewable path and makes it\neasier to catch wrong assumptions early.\n\nNext: [ARCHITECTURE.md](ARCHITECTURE.md) explains the internal harness and\nruntime model.\n\n## 2. First Launch\n\nFor a new macOS or Linux installation, use the official GitHub release.\nThe installer verifies the release checksums and provides the same runtime\nunder the `codewhale` and `codew` command names:\n\n```bash\ncurl -fsSL https://codewhale.net/install.sh | sh\n```\n\nWindows users should choose the matching installer or archive from\n[GitHub Releases](https://github.com/codewhale-hq/CodeWhale/releases/latest).\nFor an existing direct install, use `codewhale update --check`, then\n`codewhale update`. npm and Cargo remain secondary packaging routes; Cargo\nalso supports source builds where a compatible prebuilt is unavailable.\nFor occupied directories, package-managed installs, and PATH setup, follow\n[the installation and migration guide](INSTALL.md#recommended-official-github-releases).\nAndroid/Termux uses its own [preview archive or source-build path](INSTALL.md#android--termux-arm64).\n\nDocker is also available when you want an isolated runtime. The published\nimage is currently 0.10.0; to test current `main`, [build it from source](DOCKER.md#building-locally).\n\n```bash\ndocker volume create codewhale-home\ndocker run --rm -it \\\n -e DEEPSEEK_API_KEY=\"$DEEPSEEK_API_KEY\" \\\n -v codewhale-home:/home/codewhale/.codewhale \\\n -v \"$PWD:/workspace\" \\\n -w /workspace \\\n ghcr.io/hmbown/codewhale:latest\n```\n\nOnce the install directory is on PATH, launch Codewhale from the repository or\ndirectory you want it to work in:\n\n```bash\ncodewhale\n```\n\nFor the default GitHub installer destination, you can use\n`\"$HOME/.local/bin/codewhale\"` until that directory is on PATH.\n\nOn first launch, Codewhale opens the composer, even with no key or route.\nWith no key or route, workspace trust is asked once a provider is connected;\notherwise only when the folder requires a decision. A provider is asked for\nwhen you send your first message: the message stays in the box while you sign\nin or use your own key, and a local model is offered only when a local Ollama\nserver answers. The provider step also has an explicit offline route.\n\nEverything optional stays available after that. Use `/setup` for the\nprogressive setup and repair guide, `/settings` for the full typed editor, and\n`/constitution` when you want your own constitution on top of the bundled one.\nThe localized telemetry choice appears only after the workspace is ready and\ndoes not block the composer.\n\nDeepSeek is the default provider. If you want to configure its key before or\nafter the first launch, the most direct setup path is:\n\n```bash\ncodewhale auth set --provider deepseek\n```\n\nYou can also provide a key through the environment:\n\n```bash\nexport DEEPSEEK_API_KEY=\"your-key\"\ncodewhale\n```\n\nNew Codewhale config is stored under `~/.codewhale/config.toml`. Legacy\n`~/.deepseek/config.toml` files are still supported for users migrating from\nthe old name.\n\nUse `/constitution` to review or change standing guidance. After setup, run a\ndoctor check:\n\n```bash\ncodewhale doctor\n```\n\nUse the JSON form when you need a machine-readable report for an issue:\n\n```bash\ncodewhale doctor --json\n```\n\nBoth forms are offline by default. They report structural configuration and\nliteral unknown/not-probed credential states without loading workspace `.env`\ncredentials, openiLine truncated
|
||||
},
|
||||
{
|
||||
"path": "docs/CODEWHALE_AGENT.md",
|
||||
@@ -400,8 +400,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"path": "docs/TOOL_SURFACE.md",
|
||||
"sha256": "95e6f75cd887b9216c7ba9a4cbf6f15c6146c39667df0eeaea2704676337dc65",
|
||||
"content": "# Tool surface\n\n> 阅读简体中文版:[zh_hans/TOOL_SURFACE.md](zh_hans/TOOL_SURFACE.md)。\n\nThis document describes the current model-facing tool contract. The v0.9.1\ncutover that produced it is recorded in `docs/RUNTIME_SIMPLIFICATION_DESIGN.md`;\nread the workspace version from `Cargo.toml`, not from this line. The registry\nremains larger than the first-turn catalog so\nsaved transcripts can replay and uncommon capabilities can be loaded on demand.\nThe model should learn one canonical name for each common operation.\n\nImplementation sources:\n\n- `crates/tui/src/core/engine/tool_catalog.rs` owns the eager/deferred catalog.\n- `crates/tui/src/tools/registry.rs` registers canonical tools and hidden aliases.\n- `crates/tui/src/tools/{file,file_tool,shell}.rs` own the small foreground\n primitive behavior and schemas; the other native tools remain searchable.\n- `docs/RUNTIME_SIMPLIFICATION_DESIGN.md` records the v0.9.1 cutover and receipt.\n\n## Default-active contract\n\nNew turns start with twelve eager native names plus synthetic `tool_search`:\n\n1. `read`\n2. `write`\n3. `edit`\n4. `file_search`\n5. `bash`\n6. `agent`\n7. `workflow`\n8. `todo_write`\n9. `create_goal`\n10. `get_goal`\n11. `update_goal`\n12. `load_skill`\n13. `tool_search` (synthetic, always active)\n\nThe twelve native names are `DEFAULT_ACTIVE_NATIVE_TOOLS` in\n`crates/tui/src/core/engine/tool_catalog.rs`, pinned by\n`default_active_contract_keeps_discovery_and_core_tools_eager`. An authority\nboundary may remove `agent` at the maximum child depth, but route size alone\nmust not change this core vocabulary.\n\nThe direct schemas deliberately stay small:\n\n| Tool | Input | Purpose |\n|---|---|---|\n| `read` | `path`, optional `offset`, optional `limit` | Read a bounded file window with explicit continuation or truncation notices. |\n| `write` | `path`, `content` | Create or replace a file. |\n| `edit` | `path`, `edits` | Apply one or more unambiguous text replacements against one original snapshot. |\n| `file_search` | `query`, optional `path`, `limit`, `extensions`, `exclude` | Find files by name, path fragment or glob and return bounded, ranked matches. Respects ignore files; `exclude` replaces default exclusions. |\n| `bash` | `command`, optional `timeout`, optional `description` | Run one cancellable foreground shell command and return a bounded tail. The optional description is display-only. |\n| `agent` | delegated task and optional scope/context controls | Start or inspect focused child work. |\n| `workflow` | plan/script/source_path plus run controls | Coordinate multi-agent phases with dependencies and completion checks. |\n| `todo_write` | complete replacement list of `{content, status}` items | Keep optional, agent-owned progress notes for genuinely multi-step work. |\n| `create_goal` | objective plus optional budget | Start the session goal the turn works toward. |\n| `get_goal` | none | Read the active goal and its progress. |\n| `update_goal` | terminal status | Mark the goal complete or blocked. |\n| `load_skill` | optional `name`, `query` | Load a named skill's `SKILL.md` body and companion-file list; omit `name` or use `name=\"list\"` to list eligible skills, or use `query` to search names and descriptions. |\n| `tool_search` | `query`, optional matching controls | Discover policy-allowed deferred tools and add selected schemas to this conversation's toolbox. |\n\nMode is an authority decision, not a synonym system. Plan, Work, and Operate\nuse the same primitive identities. Plan centrally refuses `write`, `edit`, and\n`bash`; Work and Operate still pass those calls through approval, sandbox,\ntrusted-path, repository-law, and managed-policy gates. Full Access changes\nordinary approval behavior but does not bypass hard safety or repository law.\n\n`update_plan` remains registered only for saved-artifact compatibility and is\nnot model-visible. `tasks`, `Git`, `Run`, `Web`, `remember`, and other\nspecialized capabilities are searchable rather than first-turn ceremony.\n\nA Bash description appears as a muted, bounded note under the command on the\nTUI shell card, including on automatic runs. It never replaces the command and\nis excluded from execution, exact approval keys and Auto-Review input. The\noriginal description remains in the recorded tool input and exports. Approval\nprompts, `/jobs`, the activity inspector, ACP and other Runtime clients keep\nshowing the command; this change adds no description row to those surfaces.\n\n## Local code execution\n\n`code_execution` (Python) and `js_execution` (Node.js) use the same\npermission-aware local launcher as workspace task gates and test runs. Ordinary\napproval retains the effective session policy. To retry a denied exact call\nwith wider permissions, supply `sandbox_permissions` (`workspace-write` or\n`danger-full-access`) and a nonempty `justification`; Ask mode requires explicit\none-shot user approval. The approved policy affectLine truncated
|
||||
"sha256": "2c63b6bd3eaa0026811366bd8ebc31822ce7ae5ea4ea3907395eb79d89e96483",
|
||||
"content": "# Tool surface\n\n> 阅读简体中文版:[zh_hans/TOOL_SURFACE.md](zh_hans/TOOL_SURFACE.md)。\n\nThis document describes the current model-facing tool contract. The v0.9.1\ncutover that produced it is recorded in `docs/RUNTIME_SIMPLIFICATION_DESIGN.md`;\nread the workspace version from `Cargo.toml`, not from this line. The registry\nremains larger than the first-turn catalog so\nsaved transcripts can replay and uncommon capabilities can be loaded on demand.\nThe model should learn one canonical name for each common operation.\n\nImplementation sources:\n\n- `crates/tui/src/core/engine/tool_catalog.rs` owns the eager/deferred catalog.\n- `crates/tui/src/tools/registry.rs` registers canonical tools and hidden aliases.\n- `crates/tui/src/tools/{file,file_tool,shell}.rs` own the small foreground\n primitive behavior and schemas; the other native tools remain searchable.\n- `docs/RUNTIME_SIMPLIFICATION_DESIGN.md` records the v0.9.1 cutover and receipt.\n\n## Default-active contract\n\nNew turns start with twelve eager native names plus synthetic `tool_search`:\n\n1. `read`\n2. `write`\n3. `edit`\n4. `file_search`\n5. `bash`\n6. `agent`\n7. `workflow`\n8. `todo_write`\n9. `create_goal`\n10. `get_goal`\n11. `update_goal`\n12. `load_skill`\n13. `tool_search` (synthetic, always active)\n\nThe twelve native names are `DEFAULT_ACTIVE_NATIVE_TOOLS` in\n`crates/tui/src/core/engine/tool_catalog.rs`, pinned by\n`default_active_contract_keeps_discovery_and_core_tools_eager`. An authority\nboundary may remove `agent` at the maximum child depth, but route size alone\nmust not change this core vocabulary.\n\nThe direct schemas deliberately stay small:\n\n| Tool | Input | Purpose |\n|---|---|---|\n| `read` | `path`, optional `offset`, optional `limit` | Read a bounded file window with explicit continuation or truncation notices. |\n| `write` | `path`, `content` | Create or replace a file. |\n| `edit` | `path`, `edits` | Apply one or more unambiguous text replacements against one original snapshot. |\n| `file_search` | `query`, optional `path`, `limit`, `extensions`, `exclude` | Find files by name, path fragment or glob and return bounded, ranked matches. Respects ignore files; `exclude` replaces default exclusions. |\n| `bash` | `command`, optional `timeout`, optional `description` | Run one cancellable foreground shell command and return a bounded tail. The optional description is display-only. |\n| `agent` | delegated task and optional scope/context controls | Start or inspect focused child work. |\n| `workflow` | plan/script/source_path plus run controls | Coordinate multi-agent phases with dependencies and completion checks. |\n| `todo_write` | complete replacement list of `{content, status}` items | Keep optional, agent-owned progress notes for genuinely multi-step work. |\n| `create_goal` | objective plus optional budget | Start the session goal the turn works toward. |\n| `get_goal` | none | Read the active goal and its progress. |\n| `update_goal` | terminal status | Mark the goal complete or blocked. |\n| `load_skill` | optional `name`, `query` | Load a named skill's `SKILL.md` body and companion-file list; omit `name` or use `name=\"list\"` to list eligible skills, or use `query` to search names and descriptions. |\n| `tool_search` | `query`, optional matching controls | Discover policy-allowed deferred tools and add selected schemas to this conversation's toolbox. |\n\nMode is an authority decision, not a synonym system. Plan, Work, and Operate\nuse the same primitive identities. Plan centrally refuses `write`, `edit`, and\n`bash`; Work and Operate still pass those calls through approval, sandbox,\ntrusted-path, repository-law, and managed-policy gates. Full Access changes\nordinary approval behavior but does not bypass hard safety or repository law.\n\n`update_plan` remains registered only for saved-artifact compatibility and is\nnot model-visible. `tasks`, `Git`, `Run`, `Web`, `remember`, and other\nspecialized capabilities are searchable rather than first-turn ceremony.\n\nA Bash description appears as a muted, bounded note under the command on the\nTUI shell card, including on automatic runs. It never replaces the command and\nis excluded from execution, exact approval keys and Auto-Review input. The\noriginal description remains in the recorded tool input and exports. Approval\nprompts, `/jobs`, the activity inspector, ACP and other Runtime clients keep\nshowing the command; this change adds no description row to those surfaces.\n\n## Local code execution\n\n`code_execution` (Python) and `js_execution` (Node.js) use the same\npermission-aware local launcher as workspace task gates and test runs. Ordinary\napproval retains the effective session policy. To retry a denied exact call\nwith wider permissions, supply `sandbox_permissions` (`workspace-write` or\n`danger-full-access`) and a nonempty `justification`; Ask mode requires explicit\none-shot user approval. The approved policy affectLine truncated
|
||||
},
|
||||
{
|
||||
"path": "docs/RUNTIME_SIMPLIFICATION_DESIGN.md",
|
||||
|
||||
+113
-9
@@ -37,7 +37,7 @@ export interface RepoFacts {
|
||||
}
|
||||
|
||||
export const FACTS: RepoFacts = {
|
||||
"generatedAt": "2026-10-10T12:21:52.760Z",
|
||||
"generatedAt": "2026-10-17T10:13:49.765Z",
|
||||
"sourceRevision": null,
|
||||
"sourceCommittedAt": null,
|
||||
"version": "0.10.2",
|
||||
@@ -329,6 +329,118 @@ export const FACTS: RepoFacts = {
|
||||
}
|
||||
],
|
||||
"models": [
|
||||
{
|
||||
"id": "claude-fable-5-1",
|
||||
"provider": "Anthropic",
|
||||
"contextWindow": 1000000,
|
||||
"maxOutput": 128000,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "claude-haiku-5-5",
|
||||
"provider": "Anthropic",
|
||||
"contextWindow": 1000000,
|
||||
"maxOutput": 128000,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "claude-opus-5-5",
|
||||
"provider": "Anthropic",
|
||||
"contextWindow": 1000000,
|
||||
"maxOutput": 128000,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "claude-sonnet-5-5",
|
||||
"provider": "Anthropic",
|
||||
"contextWindow": 1000000,
|
||||
"maxOutput": 128000,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "gemini-3.8-flash",
|
||||
"provider": "Google",
|
||||
"contextWindow": 1048576,
|
||||
"maxOutput": 65536,
|
||||
"reasoning": false,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "gemini-4-argon",
|
||||
"provider": "Google",
|
||||
"contextWindow": 1048576,
|
||||
"maxOutput": null,
|
||||
"reasoning": false,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "gpt-6-luna",
|
||||
"provider": "OpenAI",
|
||||
"contextWindow": 1050000,
|
||||
"maxOutput": 128000,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "gpt-6-sol",
|
||||
"provider": "OpenAI",
|
||||
"contextWindow": 1050000,
|
||||
"maxOutput": 128000,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "gpt-6.1-sol",
|
||||
"provider": "OpenAI",
|
||||
"contextWindow": 1050000,
|
||||
"maxOutput": 128000,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "mimo-v2.6-flash",
|
||||
"provider": "Xiaomi MiMo",
|
||||
"contextWindow": 1048576,
|
||||
"maxOutput": 131072,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "mimo-v2.6-pro",
|
||||
"provider": "Xiaomi MiMo",
|
||||
"contextWindow": 1048576,
|
||||
"maxOutput": 131072,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "muse-spark-1.3",
|
||||
"provider": "Meta",
|
||||
"contextWindow": 1048576,
|
||||
"maxOutput": null,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "muse-spark-1.3-contributor",
|
||||
"provider": "Meta",
|
||||
"contextWindow": 1048576,
|
||||
"maxOutput": null,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "muse-wonder-1.0",
|
||||
"provider": "Meta",
|
||||
"contextWindow": 1048576,
|
||||
"maxOutput": null,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-10-17"
|
||||
},
|
||||
{
|
||||
"id": "grok-4.7",
|
||||
"provider": "xAI",
|
||||
@@ -553,14 +665,6 @@ export const FACTS: RepoFacts = {
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-08-02"
|
||||
},
|
||||
{
|
||||
"id": "qwen3.8-max-preview",
|
||||
"provider": "Qwen",
|
||||
"contextWindow": 1000000,
|
||||
"maxOutput": 131072,
|
||||
"reasoning": true,
|
||||
"addedAt": "2026-08-02"
|
||||
},
|
||||
{
|
||||
"id": "kimi-for-coding-highspeed",
|
||||
"provider": "Moonshot/Kimi",
|
||||
|
||||
@@ -7,8 +7,8 @@ const source = JSON.parse(readFileSync(new URL("../../crates/config/assets/model
|
||||
describe("reviewed public model projection", () => {
|
||||
it("preserves all public identities, labels and proven source-support dates", () => {
|
||||
const rows = parseModelCatalog(source);
|
||||
expect(rows).toHaveLength(78);
|
||||
expect(new Set(rows?.map(row => row.id)).size).toBe(78);
|
||||
expect(rows).toHaveLength(91);
|
||||
expect(new Set(rows?.map(row => row.id)).size).toBe(91);
|
||||
for (const original of source._reviewed.public_models) {
|
||||
expect(rows?.find(row => row.id === original.id)).toMatchObject({ provider: original.label, addedAt: original.added_at });
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user