feat: v0.7.0 — am run/start --provider/--model : résolution cloud via le registre (base_url + keyring + modèle), fallback cloud quand le modèle local est inconnu, canal model_env/model_arg/env_map, jamais de token en clair (closes #92)
- apply_provider : providers::resolve_for (flag > agent > défaut) + apply_env_map_resolved (api_key = @secret, base_url/model du provider résolu) - start/run/restart : --provider et --model dans le CLI, le REPL et la complétion ; specs help + man pages - Tests unitaires : résolution, cascade, canal déclaré, erreur provider inconnu (liste), absence de fuite (env sans valeur sk-), fallback embarqué
This commit is contained in:
+26
-3
@@ -63,23 +63,46 @@ pub fn provider_pref(agent: &AgentDef) -> Option<&str> {
|
||||
/// model/base_url/provider -> values of the resolved provider. Explicit
|
||||
/// values already present in agent.env are never overwritten.
|
||||
pub fn apply_env_map(env: &mut BTreeMap<String, String>, agent: &AgentDef, config: &Config) {
|
||||
apply_env_map_resolved(env, agent, config, None, None);
|
||||
}
|
||||
|
||||
/// Same as `apply_env_map` but with the provider and model fixed by the
|
||||
/// caller (issue #92: `am run/start --provider/--model`): the flags win
|
||||
/// over the agent declaration and the settings default.
|
||||
pub fn apply_env_map_resolved(
|
||||
env: &mut BTreeMap<String, String>,
|
||||
agent: &AgentDef,
|
||||
config: &Config,
|
||||
provider_override: Option<&str>,
|
||||
model_override: Option<&str>,
|
||||
) {
|
||||
let Some(cfg) = &agent.config else {
|
||||
return;
|
||||
};
|
||||
if cfg.env_map.is_empty() {
|
||||
return;
|
||||
}
|
||||
let Some(pname) = provider_pref(agent).or_else(|| crate::providers::default_name(config)) else {
|
||||
let Some(pname) = provider_override
|
||||
.filter(|p| !p.is_empty())
|
||||
.or_else(|| provider_pref(agent))
|
||||
.or_else(|| crate::providers::default_name(config))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(def) = crate::providers::get(config, pname) else {
|
||||
return;
|
||||
};
|
||||
let model = agent.model.as_deref().or(def.default_model.as_deref());
|
||||
let model = model_override
|
||||
.filter(|m| !m.is_empty())
|
||||
.or(agent.model.as_deref())
|
||||
.or(def.default_model.as_deref());
|
||||
for (slot, var) in &cfg.env_map {
|
||||
let value = match slot.as_str() {
|
||||
"api_key" => "@secret".to_string(),
|
||||
"model" => model.unwrap_or_default().to_string(),
|
||||
"model" => {
|
||||
let Some(m) = model else { continue };
|
||||
m.to_string()
|
||||
}
|
||||
"base_url" => def.base_url.clone(),
|
||||
"provider" => pname.to_string(),
|
||||
_ => continue, // unknown slots are ignored
|
||||
|
||||
Reference in New Issue
Block a user