llm: named-provider registry — judges & topology nodes on GLM/Kimi
Adds a multi-provider registry so judges and topology execution can run on
providers beyond the default. cm-config gains [[llm.providers]] (name, base_url,
api_key_env) — all OpenAI-compatible (GLM, Kimi/Moonshot). The server builds an
Arc<dyn LlmProvider> per entry (OpenAiCompatProvider) keyed by name; a missing
key is skipped with a warning, not a boot failure. cm-runtime RuntimeConfig
carries a ProviderRegistry; Runtime::resolve_provider("<name>:<model>") selects a
registry provider (else the default). The door governor (Runtime::judge) and the
topology compare endpoint both resolve through it, so CLAWMATES_JUDGE_MODEL and
CLAWMATES_TOPOLOGY_EXEC_MODEL accept "glm:glm-4.6" / "kimi:kimi-k2".
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
325038e806
commit
2ec8832ef6
@@ -51,6 +51,29 @@ fn build_provider(config: &AppConfig) -> Result<Arc<dyn LlmProvider>, String> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds the extra named-provider registry (GLM, Kimi, …) from
|
||||
/// `[[llm.providers]]`. Each is OpenAI-compatible; its key comes from the named
|
||||
/// env var. A provider whose key env is unset is skipped with a warning, so a
|
||||
/// missing key degrades that one selector rather than failing boot.
|
||||
fn build_provider_registry(config: &AppConfig) -> cm_runtime::ProviderRegistry {
|
||||
let mut map = std::collections::HashMap::new();
|
||||
for p in &config.llm.providers {
|
||||
match std::env::var(&p.api_key_env) {
|
||||
Ok(key) if !key.is_empty() => {
|
||||
let provider: Arc<dyn LlmProvider> =
|
||||
Arc::new(OpenAiCompatProvider::new(p.base_url.clone(), Some(key)));
|
||||
map.insert(p.name.clone(), provider);
|
||||
println!("clawmates-server: registered LLM provider '{}'", p.name);
|
||||
}
|
||||
_ => eprintln!(
|
||||
"clawmates-server: provider '{}' skipped — {} is unset",
|
||||
p.name, p.api_key_env
|
||||
),
|
||||
}
|
||||
}
|
||||
cm_runtime::ProviderRegistry(map)
|
||||
}
|
||||
|
||||
async fn run() -> Result<(), String> {
|
||||
let config_path = PathBuf::from(
|
||||
std::env::var("CLAWMATES_CONFIG").unwrap_or_else(|_| "clawmates.toml".into()),
|
||||
@@ -98,6 +121,7 @@ async fn run() -> Result<(), String> {
|
||||
}
|
||||
|
||||
let provider = build_provider(&config)?;
|
||||
let provider_registry = build_provider_registry(&config);
|
||||
let blob: std::sync::Arc<dyn cm_files::BlobStore> = match config.storage.backend {
|
||||
cm_config::StorageBackend::Local => std::sync::Arc::new(cm_files::LocalBlobStore::new(
|
||||
PathBuf::from(&config.storage.data_dir),
|
||||
@@ -154,6 +178,7 @@ async fn run() -> Result<(), String> {
|
||||
slack_base_url: config.slack.base_url.clone(),
|
||||
sandboxes,
|
||||
browser,
|
||||
providers: provider_registry,
|
||||
},
|
||||
blob,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user