feat(missions): forward ZAI/KIMI keys so one binary serves three backends
All three providers run through the SAME `claude` binary, verified live: Anthropic CLAUDE_CODE_OAUTH_TOKEN -> ANTHROPIC-OK GLM ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic -> GLM-OK Kimi ANTHROPIC_BASE_URL=https://api.kimi.com/coding/ -> KIMI-OK That is a stronger multi-provider story than a provider-per-implementation: skills, subagents, MCP, hooks and tool policy are identical across all three because it is literally the same harness. The `kimi` CLI (0.31.1, shipped in the image) 401s on this key and is not needed -- the claude binary reaches Kimi's Anthropic-compatible endpoint directly. Worth knowing before someone debugs the CLI. forwarded_provider_keys now ships ZAI_API_KEY and KIMI_API_KEY into mission containers in BOTH auth modes: they are unrelated to the Anthropic credential, so the api_key/subscription split does not apply to them. A mission that selects a backend without its key present would otherwise fail at the first turn. Keys persisted in /opt/clawmates/.env and passed through compose. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4ff4e6f7ee
commit
5d98fcf44a
@@ -91,7 +91,17 @@ impl RuntimeAuth {
|
|||||||
/// `claude -p` simply hangs with no credential, which is what a phase stuck
|
/// `claude -p` simply hangs with no credential, which is what a phase stuck
|
||||||
/// at `running` for ten minutes looked like when this was first switched on.
|
/// at `running` for ten minutes looked like when this was first switched on.
|
||||||
pub fn forwarded_provider_keys(auth: RuntimeAuth) -> Vec<&'static str> {
|
pub fn forwarded_provider_keys(auth: RuntimeAuth) -> Vec<&'static str> {
|
||||||
let mut keys = vec!["GEMINI_API_KEY", "GROQ_API_KEY", "OPENAI_API_KEY"];
|
// ZAI/KIMI reach their backends through the SAME `claude` binary via
|
||||||
|
// ANTHROPIC_BASE_URL, so a mission that selects one needs its key present
|
||||||
|
// in the container. They are unrelated to the Anthropic credential and
|
||||||
|
// forward in both auth modes.
|
||||||
|
let mut keys = vec![
|
||||||
|
"GEMINI_API_KEY",
|
||||||
|
"GROQ_API_KEY",
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"ZAI_API_KEY",
|
||||||
|
"KIMI_API_KEY",
|
||||||
|
];
|
||||||
match auth {
|
match auth {
|
||||||
RuntimeAuth::ApiKey => keys.push("ANTHROPIC_API_KEY"),
|
RuntimeAuth::ApiKey => keys.push("ANTHROPIC_API_KEY"),
|
||||||
RuntimeAuth::Subscription => keys.push("CLAUDE_CODE_OAUTH_TOKEN"),
|
RuntimeAuth::Subscription => keys.push("CLAUDE_CODE_OAUTH_TOKEN"),
|
||||||
@@ -810,7 +820,13 @@ mod tests {
|
|||||||
it silently bills the API. Forwarded: {keys:?}"
|
it silently bills the API. Forwarded: {keys:?}"
|
||||||
);
|
);
|
||||||
// Unrelated providers have no subscription equivalent and must survive.
|
// Unrelated providers have no subscription equivalent and must survive.
|
||||||
for k in ["GEMINI_API_KEY", "GROQ_API_KEY", "OPENAI_API_KEY"] {
|
for k in [
|
||||||
|
"GEMINI_API_KEY",
|
||||||
|
"GROQ_API_KEY",
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"ZAI_API_KEY",
|
||||||
|
"KIMI_API_KEY",
|
||||||
|
] {
|
||||||
assert!(keys.contains(&k), "{k} should still be forwarded");
|
assert!(keys.contains(&k), "{k} should still be forwarded");
|
||||||
}
|
}
|
||||||
// And the subscription credential MUST travel. A mission container
|
// And the subscription credential MUST travel. A mission container
|
||||||
|
|||||||
Reference in New Issue
Block a user