fix(cli): allow Moonshot Kimi TUI delegation

This commit is contained in:
Hunter Bown
2026-05-25 22:06:44 -05:00
parent af1f99e85d
commit 05e4b08335
2 changed files with 89 additions and 12 deletions
+73 -9
View File
@@ -1453,12 +1453,13 @@ fn build_tui_command(
| ProviderKind::Openrouter
| ProviderKind::Novita
| ProviderKind::Fireworks
| ProviderKind::Moonshot
| ProviderKind::Sglang
| ProviderKind::Vllm
| ProviderKind::Ollama
) {
bail!(
"The interactive TUI supports DeepSeek, NVIDIA NIM, OpenAI-compatible, AtlasCloud, Wanjie Ark, OpenRouter, Novita, Fireworks, SGLang, vLLM, and Ollama providers. Remove --provider {} or use `codewhale model ...` for provider registry inspection.",
"The interactive TUI supports DeepSeek, NVIDIA NIM, OpenAI-compatible, AtlasCloud, Wanjie Ark, OpenRouter, Novita, Fireworks, Moonshot/Kimi, SGLang, vLLM, and Ollama providers. Remove --provider {} or use `codewhale model ...` for provider registry inspection.",
resolved_runtime.provider.as_str()
);
}
@@ -1480,14 +1481,10 @@ fn build_tui_command(
}
if let Some(api_key) = resolved_runtime.api_key.as_ref() {
cmd.env("DEEPSEEK_API_KEY", api_key);
if resolved_runtime.provider == ProviderKind::Openai {
cmd.env("OPENAI_API_KEY", api_key);
}
if resolved_runtime.provider == ProviderKind::Atlascloud {
cmd.env("ATLASCLOUD_API_KEY", api_key);
}
if resolved_runtime.provider == ProviderKind::WanjieArk {
cmd.env("WANJIE_ARK_API_KEY", api_key);
for var in provider_env_vars(resolved_runtime.provider) {
if *var != "DEEPSEEK_API_KEY" {
cmd.env(var, api_key);
}
}
let source = resolved_runtime
.api_key_source
@@ -2668,6 +2665,73 @@ mod tests {
);
}
#[test]
fn build_tui_command_allows_moonshot_and_forwards_kimi_key() {
let _lock = env_lock();
let dir = tempfile::TempDir::new().expect("tempdir");
let custom = dir
.path()
.join(format!("custom-tui{}", std::env::consts::EXE_SUFFIX));
std::fs::write(&custom, b"").unwrap();
let custom_str = custom.to_string_lossy().into_owned();
let _bin = ScopedEnvVar::set("DEEPSEEK_TUI_BIN", &custom_str);
let cli = parse_ok(&[
"codewhale",
"--provider",
"moonshot",
"--model",
"kimi-k2.6",
"--workspace",
"/tmp/codewhale-workspace",
]);
let resolved = ResolvedRuntimeOptions {
provider: ProviderKind::Moonshot,
model: "kimi-k2.6".to_string(),
api_key: Some("resolved-kimi-key".to_string()),
api_key_source: Some(RuntimeApiKeySource::Env),
base_url: "https://api.moonshot.ai/v1".to_string(),
auth_mode: Some("api_key".to_string()),
output_mode: None,
log_level: None,
telemetry: false,
approval_policy: None,
sandbox_mode: None,
yolo: None,
http_headers: std::collections::BTreeMap::new(),
};
let cmd = build_tui_command(&cli, &resolved, Vec::new()).expect("command");
assert_eq!(
command_env(&cmd, "DEEPSEEK_PROVIDER").as_deref(),
Some("moonshot")
);
assert_eq!(
command_env(&cmd, "DEEPSEEK_MODEL").as_deref(),
Some("kimi-k2.6")
);
assert_eq!(
command_env(&cmd, "DEEPSEEK_BASE_URL").as_deref(),
Some("https://api.moonshot.ai/v1")
);
assert_eq!(
command_env(&cmd, "DEEPSEEK_API_KEY").as_deref(),
Some("resolved-kimi-key")
);
assert_eq!(
command_env(&cmd, "MOONSHOT_API_KEY").as_deref(),
Some("resolved-kimi-key")
);
assert_eq!(
command_env(&cmd, "KIMI_API_KEY").as_deref(),
Some("resolved-kimi-key")
);
assert_eq!(
command_env(&cmd, "DEEPSEEK_API_KEY_SOURCE").as_deref(),
Some("env")
);
}
#[test]
fn parses_top_level_prompt_flag_for_canonical_one_shot() {
let cli = parse_ok(&["deepseek", "-p", "Reply with exactly OK."]);
+16 -3
View File
@@ -484,9 +484,7 @@ impl Secrets {
/// Resolve a secret with `secret store → env → none` precedence.
///
/// `name` is the canonical provider name (`"deepseek"`,
/// `"openrouter"`, `"novita"`, `"nvidia"`/`"nvidia-nim"`, `"openai"`,
/// or `"atlascloud"`).
/// `name` is the canonical provider name or a supported provider alias.
/// Empty strings on either layer are treated as "not set".
#[must_use]
pub fn resolve(&self, name: &str) -> Option<String> {
@@ -779,6 +777,21 @@ mod tests {
unsafe { std::env::remove_var("FIREWORKS_API_KEY") };
}
#[test]
fn moonshot_kimi_env_aliases_resolve() {
let _lock = env_lock();
clear_known_envs();
// Safety: env mutation guarded by env_lock().
unsafe { std::env::set_var("KIMI_API_KEY", "kimi-key") };
assert_eq!(env_for("moonshot").as_deref(), Some("kimi-key"));
assert_eq!(env_for("moonshot-ai").as_deref(), Some("kimi-key"));
assert_eq!(env_for("kimi").as_deref(), Some("kimi-key"));
assert_eq!(env_for("kimi-k2").as_deref(), Some("kimi-key"));
// Safety: env mutation guarded by env_lock().
unsafe { std::env::remove_var("KIMI_API_KEY") };
}
#[test]
fn sglang_env_aliases_resolve() {
let _lock = env_lock();