feat: am setup — provider openrouter + modeles proposes ; am ai — role am-copilot par defaut ; fix migrate import (config active)
release / release (push) Successful in 13m7s
release / macos (push) Canceled after 0s

- setup: openrouter ajoute aux CHOICES (base URL, OPENROUTER_API_KEY,
  6 modeles declares dans le registre embarqué, proposes au choix)
- setup: pick_model liste les modeles disponibles (registre) + autre modele
- am ai sans --role: am-copilot par defaut (regeneration auto des roles si
  fichier manquant, degradation douce si echec; role explicite inconnu = erreur)
- fix migrate --import: import_bundle ecrivait la config dans user_config_dir()
  GLOBAL -> ecrasait la config reelle de la machine (et cargo test detruisait
  la config utilisateur a chaque suite via export_import_round_trip).
  L'import ecrit desormais dans app.paths.config_dir (config active).
v1.1.2
This commit is contained in:
2026-08-21 08:36:26 -04:00
parent 068940495a
commit 7fb65c257d
8 changed files with 65 additions and 19 deletions
+26 -11
View File
@@ -75,21 +75,36 @@ fn aichat_installed(app: &App) -> bool {
|| which::which("aichat").is_ok()
}
/// Validate the --role flag: the file must exist among the generated
/// am-* roles (v1.1.0 F3). Returns the aichat --agent arguments.
/// Build the aichat `--agent` arguments for the requested role. Without a
/// `--role` flag the am-copilot role is used by default (v1.1.2): when its
/// file is missing the roles are regenerated on the fly, and a generation
/// failure degrades gracefully (no role). An explicit unknown role is an
/// error.
fn role_args(app: &App, role: Option<&str>) -> Result<Vec<String>> {
let Some(role) = role else {
return Ok(Vec::new());
};
let role = role.unwrap_or("am-copilot");
let dir = crate::roles::aichat_agents_dir();
let path = dir.join(format!("{role}.md"));
if !path.exists() {
bail!(crate::i18n::tr_in(
app.lang(),
"rôle '{}' inconnu — générez les rôles avec: am setup --roles (am-copilot, am-operator, am-dev, am-do, am-analyst, am-orchestrator)"
).replace("{}", role));
if path.exists() {
return Ok(vec!["--agent".to_string(), role.to_string()]);
}
Ok(vec!["--agent".to_string(), role.to_string()])
if role == "am-copilot" {
if let Err(e) = crate::roles::generate_all(app) {
app.log.verbose(&format!("roles generation skipped: {e:#}"));
}
if path.exists() {
return Ok(vec!["--agent".to_string(), role.to_string()]);
}
app.log.warn(crate::i18n::tr_in(
app.lang(),
"rôle 'am-copilot' introuvable — lancez am setup --roles",
));
return Ok(Vec::new());
}
bail!(crate::i18n::tr_in(
app.lang(),
"rôle '{}' inconnu — générez les rôles avec: am setup --roles (am-copilot, am-operator, am-dev, am-do, am-analyst, am-orchestrator)"
)
.replace("{}", role));
}
/// Conversational mode: aichat -f <ctx> "<prompt>" in the foreground, with