feat(models): add Kimi K2.7 Code defaults

This commit is contained in:
Hunter B
2026-06-12 05:43:38 -07:00
parent de9a0131cf
commit efcf299712
10 changed files with 194 additions and 20 deletions
+4
View File
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- **Moonshot Kimi K2.7 Code model.** The Moonshot/Kimi provider now defaults to
`kimi-k2.7-code`, recognizes `kimi`/`kimi-k2` aliases for that model, keeps
explicit `kimi-k2.6` selectable, and adds the OpenRouter
`moonshotai/kimi-k2.7-code` registry row.
- **Cursor-style activity metadata rows (#3146).** Dense successful tool-run
summaries now render as a single muted `Explored ...` / `Updated metadata`
row while keeping keyboard/mouse expansion and detail inspection intact.
+46 -2
View File
@@ -286,6 +286,16 @@ impl Default for ModelRegistry {
supports_tools: true,
supports_reasoning: true,
},
ModelInfo {
id: "moonshotai/kimi-k2.7-code".to_string(),
provider: ProviderKind::Openrouter,
aliases: vec![
"kimi-k2.7-code".to_string(),
"openrouter-kimi-k2.7-code".to_string(),
],
supports_tools: true,
supports_reasoning: true,
},
ModelInfo {
id: "moonshotai/kimi-k2.6".to_string(),
provider: ProviderKind::Openrouter,
@@ -486,16 +496,25 @@ impl Default for ModelRegistry {
supports_reasoning: false,
},
ModelInfo {
id: "kimi-k2.6".to_string(),
id: "kimi-k2.7-code".to_string(),
provider: ProviderKind::Moonshot,
aliases: vec![
"kimi".to_string(),
"kimi-k2".to_string(),
"moonshot-kimi-k2.6".to_string(),
"kimi-k2.7".to_string(),
"kimi-code".to_string(),
"moonshot-kimi-k2.7-code".to_string(),
],
supports_tools: true,
supports_reasoning: true,
},
ModelInfo {
id: "kimi-k2.6".to_string(),
provider: ProviderKind::Moonshot,
aliases: vec!["kimi-k2.6".to_string(), "moonshot-kimi-k2.6".to_string()],
supports_tools: true,
supports_reasoning: true,
},
ModelInfo {
id: "deepseek-ai/DeepSeek-V4-Pro".to_string(),
provider: ProviderKind::Sglang,
@@ -1040,6 +1059,30 @@ mod tests {
assert!(resolved.resolved.supports_reasoning);
}
#[test]
fn moonshot_default_and_aliases_use_kimi_k27_code() {
let registry = ModelRegistry::default();
for requested in [None, Some("kimi"), Some("kimi-k2.7-code")] {
let resolved = registry.resolve(requested, Some(ProviderKind::Moonshot));
assert_eq!(resolved.resolved.provider, ProviderKind::Moonshot);
assert_eq!(resolved.resolved.id, "kimi-k2.7-code");
assert!(resolved.resolved.supports_tools);
assert!(resolved.resolved.supports_reasoning);
}
}
#[test]
fn moonshot_explicit_kimi_k26_remains_available() {
let registry = ModelRegistry::default();
let resolved = registry.resolve(Some("kimi-k2.6"), Some(ProviderKind::Moonshot));
assert_eq!(resolved.resolved.provider, ProviderKind::Moonshot);
assert_eq!(resolved.resolved.id, "kimi-k2.6");
assert!(resolved.resolved.supports_reasoning);
}
#[test]
fn xiaomi_mimo_tts_aliases_resolve_when_provider_hinted() {
let registry = ModelRegistry::default();
@@ -1222,6 +1265,7 @@ mod tests {
("glm-5.1", "z-ai/glm-5.1"),
("minimax-m3", "minimax/minimax-m3"),
("openrouter-mimo-v2.5-pro", "xiaomi/mimo-v2.5-pro"),
("openrouter-kimi-k2.7-code", "moonshotai/kimi-k2.7-code"),
("openrouter-kimi-k2.6", "moonshotai/kimi-k2.6"),
("nemotron-3-ultra", "nvidia/nemotron-3-ultra-550b-a55b"),
(
+3 -3
View File
@@ -3433,14 +3433,14 @@ mod tests {
"--provider",
"moonshot",
"--model",
"kimi-k2.6",
"kimi-k2.7-code",
"--workspace",
"/tmp/codewhale-workspace",
]);
let resolved = ResolvedRuntimeOptions {
provider: ProviderKind::Moonshot,
provider_source: ProviderSource::Cli,
model: "kimi-k2.6".to_string(),
model: "kimi-k2.7-code".to_string(),
api_key: Some("resolved-kimi-key".to_string()),
api_key_source: Some(RuntimeApiKeySource::Keyring),
base_url: "https://api.moonshot.ai/v1".to_string(),
@@ -3462,7 +3462,7 @@ mod tests {
);
assert_eq!(
command_env(&cmd, "DEEPSEEK_MODEL").as_deref(),
Some("kimi-k2.6")
Some("kimi-k2.7-code")
);
assert_eq!(
command_env(&cmd, "DEEPSEEK_API_KEY").as_deref(),
+46 -3
View File
@@ -43,6 +43,7 @@ const OPENROUTER_ARCEE_TRINITY_LARGE_THINKING_MODEL: &str = "arcee-ai/trinity-la
const OPENROUTER_GEMMA_4_31B_MODEL: &str = "google/gemma-4-31b-it";
const OPENROUTER_GEMMA_4_26B_A4B_MODEL: &str = "google/gemma-4-26b-a4b-it";
const OPENROUTER_GLM_5_1_MODEL: &str = "z-ai/glm-5.1";
const OPENROUTER_KIMI_K2_7_CODE_MODEL: &str = "moonshotai/kimi-k2.7-code";
const OPENROUTER_KIMI_K2_6_MODEL: &str = "moonshotai/kimi-k2.6";
const OPENROUTER_NEMOTRON_3_NANO_OMNI_MODEL: &str =
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free";
@@ -70,7 +71,8 @@ const DEFAULT_SILICONFLOW_FLASH_MODEL: &str = "deepseek-ai/DeepSeek-V4-Flash";
const DEFAULT_ARCEE_MODEL: &str = "trinity-large-thinking";
const ARCEE_TRINITY_LARGE_PREVIEW_MODEL: &str = "trinity-large-preview";
const ARCEE_TRINITY_MINI_MODEL: &str = "trinity-mini";
const DEFAULT_MOONSHOT_MODEL: &str = "kimi-k2.6";
const DEFAULT_MOONSHOT_MODEL: &str = "kimi-k2.7-code";
const MOONSHOT_KIMI_K2_6_MODEL: &str = "kimi-k2.6";
const DEFAULT_MOONSHOT_BASE_URL: &str = "https://api.moonshot.ai/v1";
const DEFAULT_KIMI_CODE_MODEL: &str = "kimi-for-coding";
const DEFAULT_KIMI_CODE_BASE_URL: &str = "https://api.kimi.com/coding/v1";
@@ -2370,7 +2372,20 @@ fn normalize_model_for_provider(provider: ProviderKind, model: &str) -> String {
(ProviderKind::Arcee, "arcee-trinity-large-preview") => {
ARCEE_TRINITY_LARGE_PREVIEW_MODEL.to_string()
}
(ProviderKind::Moonshot, "kimi-k2.6" | "kimi-k2") => DEFAULT_MOONSHOT_MODEL.to_string(),
(
ProviderKind::Moonshot,
"kimi"
| "kimi-k2"
| "kimi-k2.7"
| "kimi-k2-7"
| "kimi-k2.7-code"
| "kimi-k2-7-code"
| "kimi-code"
| "moonshot-kimi-k2.7-code",
) => DEFAULT_MOONSHOT_MODEL.to_string(),
(ProviderKind::Moonshot, "kimi-k2.6" | "kimi-k2-6" | "moonshot-kimi-k2.6") => {
MOONSHOT_KIMI_K2_6_MODEL.to_string()
}
(ProviderKind::Sglang, "deepseek-v4-pro" | "deepseek-v4pro") => {
DEFAULT_SGLANG_MODEL.to_string()
}
@@ -2471,6 +2486,16 @@ fn canonical_openrouter_recent_model_id(model: &str) -> Option<&'static str> {
OPENROUTER_GLM_5_1_MODEL | "glm-5.1" | "glm-5-1" | "zai-glm-5.1" | "zai-glm-5-1" => {
Some(OPENROUTER_GLM_5_1_MODEL)
}
OPENROUTER_KIMI_K2_7_CODE_MODEL
| "kimi"
| "kimi-k2"
| "kimi-k2.7"
| "kimi-k2-7"
| "kimi-k2.7-code"
| "kimi-k2-7-code"
| "kimi-code"
| "moonshot-kimi-k2.7-code"
| "openrouter-kimi-k2.7-code" => Some(OPENROUTER_KIMI_K2_7_CODE_MODEL),
OPENROUTER_KIMI_K2_6_MODEL | "kimi-k2.6" | "kimi-k2-6" | "moonshot-kimi-k2.6" => {
Some(OPENROUTER_KIMI_K2_6_MODEL)
}
@@ -5530,7 +5555,7 @@ mode = "token-plan-usa"
}
#[test]
fn moonshot_provider_defaults_to_kimi_k2() {
fn moonshot_provider_defaults_to_kimi_k27_code() {
let _lock = env_lock();
let _env = EnvGuard::without_deepseek_runtime_overrides();
let config = ConfigToml {
@@ -5545,6 +5570,22 @@ mode = "token-plan-usa"
assert_eq!(resolved.model, DEFAULT_MOONSHOT_MODEL);
}
#[test]
fn moonshot_provider_preserves_explicit_kimi_k26() {
let _lock = env_lock();
let _env = EnvGuard::without_deepseek_runtime_overrides();
let mut config = ConfigToml {
provider: ProviderKind::Moonshot,
..ConfigToml::default()
};
config.providers.moonshot.model = Some("kimi-k2.6".to_string());
let resolved = config.resolve_runtime_options(&CliRuntimeOverrides::default());
assert_eq!(resolved.provider, ProviderKind::Moonshot);
assert_eq!(resolved.model, MOONSHOT_KIMI_K2_6_MODEL);
}
#[test]
fn moonshot_kimi_oauth_uses_kimi_code_endpoint_and_model() {
let _lock = env_lock();
@@ -6298,6 +6339,8 @@ mode = "token-plan-usa"
("qwen3.6-max-preview", OPENROUTER_QWEN_3_6_MAX_PREVIEW_MODEL),
("qwen3.6-plus", OPENROUTER_QWEN_3_6_PLUS_MODEL),
("mimo-v2.5-pro", OPENROUTER_XIAOMI_MIMO_V2_5_PRO_MODEL),
("kimi-k2.7-code", OPENROUTER_KIMI_K2_7_CODE_MODEL),
("kimi", OPENROUTER_KIMI_K2_7_CODE_MODEL),
("kimi-k2.6", OPENROUTER_KIMI_K2_6_MODEL),
("gemma-4-31b-it", OPENROUTER_GEMMA_4_31B_MODEL),
("glm-5.1", OPENROUTER_GLM_5_1_MODEL),
+4
View File
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- **Moonshot Kimi K2.7 Code model.** The Moonshot/Kimi provider now defaults to
`kimi-k2.7-code`, recognizes `kimi`/`kimi-k2` aliases for that model, keeps
explicit `kimi-k2.6` selectable, and adds the OpenRouter
`moonshotai/kimi-k2.7-code` registry row.
- **Cursor-style activity metadata rows (#3146).** Dense successful tool-run
summaries now render as a single muted `Explored ...` / `Updated metadata`
row while keeping keyboard/mouse expansion and detail inspection intact.
+72 -4
View File
@@ -71,6 +71,7 @@ pub const OPENROUTER_ARCEE_TRINITY_LARGE_THINKING_MODEL: &str = "arcee-ai/trinit
pub const OPENROUTER_GEMMA_4_31B_MODEL: &str = "google/gemma-4-31b-it";
pub const OPENROUTER_GEMMA_4_26B_A4B_MODEL: &str = "google/gemma-4-26b-a4b-it";
pub const OPENROUTER_GLM_5_1_MODEL: &str = "z-ai/glm-5.1";
pub const OPENROUTER_KIMI_K2_7_CODE_MODEL: &str = "moonshotai/kimi-k2.7-code";
pub const OPENROUTER_KIMI_K2_6_MODEL: &str = "moonshotai/kimi-k2.6";
pub const OPENROUTER_MINIMAX_M3_MODEL: &str = "minimax/minimax-m3";
pub const OPENROUTER_NEMOTRON_3_NANO_OMNI_MODEL: &str =
@@ -99,6 +100,7 @@ pub const RECENT_OPENROUTER_LARGE_MODELS: &[&str] = &[
OPENROUTER_QWEN_3_7_MAX_MODEL,
OPENROUTER_MINIMAX_2_7_MODEL,
OPENROUTER_NEMOTRON_3_ULTRA_MODEL,
OPENROUTER_KIMI_K2_7_CODE_MODEL,
OPENROUTER_KIMI_K2_6_MODEL,
OPENROUTER_GLM_5_1_MODEL,
OPENROUTER_TENCENT_HY3_PREVIEW_MODEL,
@@ -132,7 +134,8 @@ pub const DEFAULT_ARCEE_MODEL: &str = "trinity-large-thinking";
pub const ARCEE_TRINITY_LARGE_PREVIEW_MODEL: &str = "trinity-large-preview";
pub const ARCEE_TRINITY_MINI_MODEL: &str = "trinity-mini";
pub const DEFAULT_ARCEE_BASE_URL: &str = "https://api.arcee.ai/api/v1";
pub const DEFAULT_MOONSHOT_MODEL: &str = "kimi-k2.6";
pub const DEFAULT_MOONSHOT_MODEL: &str = "kimi-k2.7-code";
pub const MOONSHOT_KIMI_K2_6_MODEL: &str = "kimi-k2.6";
pub const DEFAULT_MOONSHOT_BASE_URL: &str = "https://api.moonshot.ai/v1";
pub const DEFAULT_KIMI_CODE_MODEL: &str = "kimi-for-coding";
pub const DEFAULT_KIMI_CODE_BASE_URL: &str = "https://api.kimi.com/coding/v1";
@@ -653,6 +656,16 @@ fn canonical_openrouter_recent_model_id(model: &str) -> Option<&'static str> {
OPENROUTER_GLM_5_1_MODEL | "glm-5.1" | "glm-5-1" | "zai-glm-5.1" | "zai-glm-5-1" => {
Some(OPENROUTER_GLM_5_1_MODEL)
}
OPENROUTER_KIMI_K2_7_CODE_MODEL
| "kimi"
| "kimi-k2"
| "kimi-k2.7"
| "kimi-k2-7"
| "kimi-k2.7-code"
| "kimi-k2-7-code"
| "kimi-code"
| "moonshot-kimi-k2.7-code"
| "openrouter-kimi-k2.7-code" => Some(OPENROUTER_KIMI_K2_7_CODE_MODEL),
OPENROUTER_KIMI_K2_6_MODEL | "kimi-k2.6" | "kimi-k2-6" | "moonshot-kimi-k2.6" => {
Some(OPENROUTER_KIMI_K2_6_MODEL)
}
@@ -766,6 +779,23 @@ fn canonical_arcee_model_id(model: &str) -> Option<&'static str> {
}
}
fn canonical_moonshot_model_id(model: &str) -> Option<&'static str> {
let normalized = model.trim().to_ascii_lowercase();
let normalized = normalized.replace(['_', ' '], "-");
match normalized.as_str() {
"kimi"
| "kimi-k2"
| "kimi-k2.7"
| "kimi-k2-7"
| "kimi-k2.7-code"
| "kimi-k2-7-code"
| "kimi-code"
| "moonshot-kimi-k2.7-code" => Some(DEFAULT_MOONSHOT_MODEL),
"kimi-k2.6" | "kimi-k2-6" | "moonshot-kimi-k2.6" => Some(MOONSHOT_KIMI_K2_6_MODEL),
_ => None,
}
}
/// Normalize a model selected through the TUI for the active provider.
///
/// Official DeepSeek endpoints require bare model IDs. Provider-prefixed
@@ -796,6 +826,12 @@ pub fn normalize_model_name_for_provider(provider: ApiProvider, model: &str) ->
.or_else(|| normalize_custom_model_id(model));
}
if matches!(provider, ApiProvider::Moonshot) {
return canonical_moonshot_model_id(model)
.map(ToString::to_string)
.or_else(|| normalize_custom_model_id(model));
}
if matches!(provider, ApiProvider::Huggingface) {
return normalize_custom_model_id(model);
}
@@ -4653,6 +4689,20 @@ fn model_for_provider(provider: ApiProvider, normalized: String) -> String {
(ApiProvider::Sglang, "deepseek-v4-flash") => DEFAULT_SGLANG_FLASH_MODEL.to_string(),
(ApiProvider::Vllm, "deepseek-v4-pro") => DEFAULT_VLLM_MODEL.to_string(),
(ApiProvider::Vllm, "deepseek-v4-flash") => DEFAULT_VLLM_FLASH_MODEL.to_string(),
(
ApiProvider::Moonshot,
"kimi"
| "kimi-k2"
| "kimi-k2.7"
| "kimi-k2-7"
| "kimi-k2.7-code"
| "kimi-k2-7-code"
| "kimi-code"
| "moonshot-kimi-k2.7-code",
) => DEFAULT_MOONSHOT_MODEL.to_string(),
(ApiProvider::Moonshot, "kimi-k2.6" | "kimi-k2-6" | "moonshot-kimi-k2.6") => {
MOONSHOT_KIMI_K2_6_MODEL.to_string()
}
_ => normalized,
}
}
@@ -8168,6 +8218,8 @@ api_key = "old-openrouter-key"
("qwen3.6-max-preview", OPENROUTER_QWEN_3_6_MAX_PREVIEW_MODEL),
("qwen3.6-plus", OPENROUTER_QWEN_3_6_PLUS_MODEL),
("mimo-v2.5-pro", OPENROUTER_XIAOMI_MIMO_V2_5_PRO_MODEL),
("kimi-k2.7-code", OPENROUTER_KIMI_K2_7_CODE_MODEL),
("kimi", OPENROUTER_KIMI_K2_7_CODE_MODEL),
("kimi-k2.6", OPENROUTER_KIMI_K2_6_MODEL),
("minimax-m3", OPENROUTER_MINIMAX_M3_MODEL),
("gemma-4-31b-it", OPENROUTER_GEMMA_4_31B_MODEL),
@@ -8180,6 +8232,22 @@ api_key = "old-openrouter-key"
}
}
#[test]
fn normalize_model_name_for_provider_maps_moonshot_aliases() {
for (alias, expected) in [
("kimi", DEFAULT_MOONSHOT_MODEL),
("kimi-k2.7", DEFAULT_MOONSHOT_MODEL),
("kimi-k2.7-code", DEFAULT_MOONSHOT_MODEL),
("kimi-code", DEFAULT_MOONSHOT_MODEL),
("kimi-k2.6", MOONSHOT_KIMI_K2_6_MODEL),
] {
assert_eq!(
normalize_model_name_for_provider(ApiProvider::Moonshot, alias).as_deref(),
Some(expected)
);
}
}
#[test]
fn normalize_model_name_for_provider_maps_arcee_direct_aliases() {
for (alias, expected) in [
@@ -8284,7 +8352,7 @@ api_key = "old-openrouter-key"
}
#[test]
fn model_completion_names_for_moonshot_excludes_oauth_only_kimi_code_model() {
fn model_completion_names_for_moonshot_uses_latest_platform_model() {
assert_eq!(
model_completion_names_for_provider(ApiProvider::Moonshot),
vec![DEFAULT_MOONSHOT_MODEL]
@@ -10464,11 +10532,11 @@ base_url = "https://api.kimi.com/coding/v1"
/// Moonshot Platform path: when [providers.moonshot] is empty (or
/// missing) and no Kimi Code endpoint is configured, the resolver
/// defaults to the Moonshot Platform base URL and the `kimi-k2.6`
/// defaults to the Moonshot Platform base URL and the latest Kimi platform
/// model. This is the "I have a Moonshot Platform API key, not a
/// Kimi Code plan key" path.
#[test]
fn moonshot_platform_defaults_to_kimi_k26() -> Result<()> {
fn moonshot_platform_defaults_to_kimi_k27_code() -> Result<()> {
let _lock = lock_test_env();
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
+10
View File
@@ -280,8 +280,10 @@ fn known_context_window_for_model(model_lower: &str) -> Option<u32> {
| "qwen/qwen3.6-max-preview"
| "qwen/qwen3.6-27b"
| "tencent/hy3-preview"
| "moonshotai/kimi-k2.7-code"
| "moonshotai/kimi-k2.6"
| "moonshotai/kimi-k2.6:free"
| "kimi-k2.7-code"
| "kimi-k2.6"
| "kimi-for-coding" => Some(262_144),
"z-ai/glm-5.1" | "z-ai/glm-5v-turbo" | "glm-5.1" | "glm-5v-turbo" => Some(202_752),
@@ -316,7 +318,9 @@ pub fn max_output_tokens_for_model(model: &str) -> Option<u32> {
"claude-sonnet-4-6" | "claude-haiku-4-5" => Some(64_000),
"arcee-ai/trinity-large-thinking"
| "trinity-large-thinking"
| "moonshotai/kimi-k2.7-code"
| "moonshotai/kimi-k2.6"
| "kimi-k2.7-code"
| "kimi-k2.6"
| "kimi-for-coding" => Some(262_144),
"minimax/minimax-m3" | "minimax-m3" => Some(524_288),
@@ -367,8 +371,10 @@ pub fn model_supports_reasoning(model: &str) -> bool {
| "google/gemma-4-31b-it:free"
| "google/gemma-4-26b-a4b-it"
| "google/gemma-4-26b-a4b-it:free"
| "moonshotai/kimi-k2.7-code"
| "moonshotai/kimi-k2.6"
| "moonshotai/kimi-k2.6:free"
| "kimi-k2.7-code"
| "kimi-k2.6"
| "minimax/minimax-m3"
| "minimax-m3"
@@ -592,6 +598,7 @@ mod tests {
("mimo-v2.5-pro", 1_000_000),
("mimo-v2.5", 1_000_000),
("minimax/minimax-m3", 1_000_000),
("moonshotai/kimi-k2.7-code", 262_144),
("moonshotai/kimi-k2.6", 262_144),
("google/gemma-4-31b-it", 262_144),
("z-ai/glm-5.1", 202_752),
@@ -624,6 +631,7 @@ mod tests {
fn moonshot_native_kimi_ids_support_reasoning_except_for_coding() {
// #3016: bare Moonshot ids (no moonshotai/ prefix) emit
// reasoning_content; kimi-for-coding is the non-thinking exception.
assert!(model_supports_reasoning("kimi-k2.7-code"));
assert!(model_supports_reasoning("kimi-k2.6"));
assert!(model_supports_reasoning("kimi-k2.5"));
assert!(!model_supports_reasoning("kimi-for-coding"));
@@ -680,6 +688,7 @@ mod tests {
// ids without the OpenRouter vendor prefix; both spellings must
// resolve identical metadata (#1310 ride-along on #3023).
for (model, expected_window) in [
("kimi-k2.7-code", 262_144),
("kimi-k2.6", 262_144),
("minimax-m3", 1_000_000),
("glm-5.1", 202_752),
@@ -691,6 +700,7 @@ mod tests {
assert!(!model_supports_reasoning("kimi-for-coding"));
assert_eq!(context_window_for_model("glm-5v-turbo"), Some(202_752));
assert!(!model_supports_reasoning("glm-5v-turbo"));
assert_eq!(max_output_tokens_for_model("kimi-k2.7-code"), Some(262_144));
assert_eq!(max_output_tokens_for_model("kimi-k2.6"), Some(262_144));
assert_eq!(
max_output_tokens_for_model("kimi-for-coding"),
+1 -1
View File
@@ -956,7 +956,7 @@ If you are upgrading from older releases:
- `base_url` (string, optional): defaults to `https://api.deepseek.com/beta` for DeepSeek's OpenAI-compatible Chat Completions API, including legacy `provider = "deepseek-cn"` configs. Other defaults are `https://integrate.api.nvidia.com/v1` for `nvidia-nim`, `https://api.openai.com/v1` for `openai`, `https://api.atlascloud.ai/v1` for `atlascloud`, `https://maas-openapi.wanjiedata.com/api/v1` for `wanjie-ark`, `https://ark.cn-beijing.volces.com/api/coding/v3` for `volcengine`, `https://openrouter.ai/api/v1` for `openrouter`, `https://token-plan-sgp.xiaomimimo.com/v1` for `xiaomi-mimo` when the API key starts with `tp-...` and `https://api.xiaomimimo.com/v1` otherwise, `https://api.novita.ai/v1` for `novita`, `https://api.fireworks.ai/inference/v1` for `fireworks`, `https://api.siliconflow.com/v1` for `siliconflow`, `https://api.siliconflow.cn/v1` for `siliconflow-CN`, `https://api.arcee.ai/api/v1` for `arcee`, `https://api.moonshot.ai/v1` for `moonshot`, `http://localhost:30000/v1` for `sglang`, `http://localhost:8000/v1` for `vllm`, and `http://localhost:11434/v1` for `ollama`. Set `base_url = "https://token-plan-cn.xiaomimimo.com/v1"` explicitly if your Xiaomi MiMo Token Plan account is provisioned in the China region. Set `https://api.deepseek.com` or `https://api.deepseek.com/v1` explicitly to opt out of DeepSeek beta features.
- `path_suffix` (string, optional provider-table key): override the chat-completions path for OpenAI-compatible gateways that do not serve `/v1/chat/completions`. For example, `[providers.openai] path_suffix = "/chat/completions"` sends chat requests to the unversioned base URL plus `/chat/completions`; `models` and `beta/*` requests keep their normal routing.
- `insecure_skip_tls_verify` (bool, optional provider-table key): disabled by default. When true on the active provider table, only the LLM provider HTTP client skips TLS certificate verification. Prefer `SSL_CERT_FILE` for corporate or private CA bundles; `codewhale doctor` reports this setting when enabled.
- `default_text_model` (string, optional): defaults to `deepseek-v4-pro` for DeepSeek and generic OpenAI-compatible endpoints, `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, `trinity-large-thinking` for Arcee AI, `kimi-k2.6` for Moonshot, `deepseek-ai/DeepSeek-V4-Pro` for SGLang/vLLM, and `deepseek-coder:1.3b` for Ollama. Hugging Face and Together AI both default to `deepseek-ai/DeepSeek-V4-Pro`. Current public DeepSeek IDs are `deepseek-v4-pro` and `deepseek-v4-flash`, both with 1M context windows, 384K max output, and thinking mode enabled by default. Legacy `deepseek-chat` and `deepseek-reasoner` remain compatibility aliases for `deepseek-v4-flash` until July 24, 2026, except SiliconFlow maps `deepseek-reasoner` and `deepseek-r1` to its Pro model while `deepseek-chat` and `deepseek-v3` map to 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-2.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.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 Xiaomi MiMo recognizes chat IDs `mimo-v2.5-pro` and `mimo-v2.5`, while TTS IDs are selected through `codewhale speech` / `tts`. Generic `openai`, `atlascloud`, `wanjie-ark`, `xiaomi-mimo`, `arcee`, and Ollama 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-v4-pro` for DeepSeek and generic OpenAI-compatible endpoints, `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, `trinity-large-thinking` for Arcee AI, `kimi-k2.7-code` for Moonshot, `deepseek-ai/DeepSeek-V4-Pro` for SGLang/vLLM, and `deepseek-coder:1.3b` for Ollama. Hugging Face and Together AI both default to `deepseek-ai/DeepSeek-V4-Pro`. Current public DeepSeek IDs are `deepseek-v4-pro` and `deepseek-v4-flash`, both with 1M context windows, 384K max output, and thinking mode enabled by default. Legacy `deepseek-chat` and `deepseek-reasoner` remain compatibility aliases for `deepseek-v4-flash` until July 24, 2026, except SiliconFlow maps `deepseek-reasoner` and `deepseek-r1` to its Pro model while `deepseek-chat` and `deepseek-v3` map to 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-2.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-k2.7-code` and `kimi-k2.6`, with `kimi` and `kimi-k2` aliases selecting `kimi-k2.7-code`; direct Xiaomi MiMo recognizes chat IDs `mimo-v2.5-pro` and `mimo-v2.5`, while TTS IDs are selected through `codewhale speech` / `tts`. Generic `openai`, `atlascloud`, `wanjie-ark`, `xiaomi-mimo`, `arcee`, and Ollama 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.
- `reasoning_effort` (string, optional): `off`, `low`, `medium`, `high`, `max`, or `xhigh`; defaults to the configured UI tier. DeepSeek Platform receives top-level `thinking` / `reasoning_effort` fields. OpenAI Codex normalizes stale `off` to `low` and sends `max` as Responses `xhigh`. NVIDIA NIM receives equivalent settings through `chat_template_kwargs`.
- `allow_shell` (bool, optional): defaults to `false`; shell tools must be explicitly enabled.
- `approval_policy` (string, optional): `on-request`, `untrusted`, or `never`. Runtime `approval_mode` editing in `/config` also accepts `on-request` and `untrusted` aliases.
+6 -5
View File
@@ -123,14 +123,14 @@ endpoint.
| `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. |
| `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`, `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. |
| `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`, `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. |
| `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`; 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. 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. `codewhale speech` / `tts` uses the TTS models. |
| `novita` | `[providers.novita]` | `NOVITA_API_KEY` | `NOVITA_BASE_URL`; default `https://api.novita.ai/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` | `kimi-k2.6`; Kimi Code path uses `kimi-for-coding` at `https://api.kimi.com/coding/v1` | Moonshot/Kimi route. `MOONSHOT_MODEL`, `KIMI_MODEL_NAME`, and `KIMI_MODEL` are accepted. `[providers.moonshot] auth_mode = "kimi_oauth"` reads Kimi CLI OAuth credentials when present. |
| `moonshot` | `[providers.moonshot]` | `MOONSHOT_API_KEY`, `KIMI_API_KEY` | `MOONSHOT_BASE_URL`, `KIMI_BASE_URL`; default `https://api.moonshot.ai/v1` | `kimi-k2.7-code`, `kimi-k2.6`; Kimi Code path uses `kimi-for-coding` at `https://api.kimi.com/coding/v1` | Moonshot/Kimi route. `kimi` and `kimi-k2` aliases select `kimi-k2.7-code`; `MOONSHOT_MODEL`, `KIMI_MODEL_NAME`, and `KIMI_MODEL` are accepted. `[providers.moonshot] auth_mode = "kimi_oauth"` reads Kimi CLI OAuth credentials when present. |
| `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. |
| `ollama` | `[providers.ollama]` | Optional `OLLAMA_API_KEY` | `OLLAMA_BASE_URL`; default `http://localhost:11434/v1` | `deepseek-coder:1.3b`; provider-hinted custom tags pass through | Self-hosted Ollama OpenAI-compatible route. Localhost deployments commonly omit auth. `OLLAMA_MODEL` is accepted. |
@@ -186,7 +186,8 @@ large models verified through OpenRouter's model metadata:
`arcee-ai/trinity-large-thinking`, `qwen/qwen3.6-flash`,
`qwen/qwen3.6-35b-a3b`, `qwen/qwen3.6-max-preview`, `qwen/qwen3.6-27b`,
`qwen/qwen3.6-plus`, `minimax/minimax-m3`, `xiaomi/mimo-v2.5-pro`,
`xiaomi/mimo-v2.5`, `moonshotai/kimi-k2.6`, `z-ai/glm-5.1`, `tencent/hy3-preview`,
`xiaomi/mimo-v2.5`, `moonshotai/kimi-k2.7-code`, `moonshotai/kimi-k2.6`,
`z-ai/glm-5.1`, `tencent/hy3-preview`,
`google/gemma-4-31b-it`, `google/gemma-4-26b-a4b-it`, and
`nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free`.
`minimax/minimax-m3` was added from OpenRouter's May 31, 2026 listing as a 1M
@@ -207,13 +208,13 @@ endpoint when the endpoint supports model listing.
| `atlascloud` | `deepseek-ai/deepseek-v4-flash`, `deepseek-ai/deepseek-v4-pro` | yes | yes |
| `wanjie-ark` | `deepseek-reasoner` | yes | yes |
| `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-2.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.6`, `z-ai/glm-5.1`, `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 |
| `openrouter` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`, `arcee-ai/trinity-large-thinking`, `minimax/minimax-m3`, `minimax/minimax-2.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`, `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 |
| `xiaomi-mimo` | `mimo-v2.5-pro`, `mimo-v2.5`; 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 |
| `arcee` | `trinity-large-thinking`, `trinity-large-preview`; provider-hinted custom model IDs pass through | yes | yes for `trinity-large-thinking`; no for `trinity-large-preview` |
| `moonshot` | `kimi-k2.6` | yes | yes |
| `moonshot` | `kimi-k2.7-code`, `kimi-k2.6` | 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 |
| `ollama` | `deepseek-coder:1.3b`; custom tags pass through when provider hint is `ollama` | yes | no |
+2 -2
View File
@@ -152,10 +152,10 @@ example:
```toml
provider = "moonshot"
model = "kimi-k2.6"
model = "kimi-k2.7-code"
[subagents]
worker_model = "kimi-k2.5"
worker_model = "kimi-k2.6"
```
Spawn-time `model` arguments on `agent_open` are validated the same way; an