agent-manager v0.2.0 : gestionnaire d'agents IA locaux
- CLI Rust (am) : list/install/uninstall/update/start/stop/restart/run/status/search/info/config/doctor/completion/export/import/self-update + shell interactif (Tab, historique) - 9 methodes d'installation (npm, pip, uv, cargo, go, bun, curl, binary, git) - catalogue de 72 agents, dependances, processus, securite (dry-run, checksums) - sondes de version paralleles + cache (am list ~25 ms a chaud) - installateurs one-liner : install.sh, install.ps1
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
//! update: compare the installed version with the latest available one and
|
||||
//! reinstall when an update exists.
|
||||
|
||||
use super::*;
|
||||
use crate::installers;
|
||||
use crate::runner::{Runner, SystemRunner};
|
||||
use anyhow::{bail, Result};
|
||||
use std::cmp::Ordering;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn run(app: &App, agent_name: Option<&str>, all: bool) -> Result<i32> {
|
||||
let runner = SystemRunner::new(app.dry_run(), app.cli.verbose, &app.log);
|
||||
if let Some(name) = agent_name {
|
||||
return update_one(app, &runner, name);
|
||||
}
|
||||
if all {
|
||||
let entries = app.state.all()?;
|
||||
let names: Vec<String> = entries.keys().cloned().collect();
|
||||
let mut failed = 0;
|
||||
for name in names {
|
||||
if let Err(e) = update_one(app, &runner, &name) {
|
||||
failed += 1;
|
||||
app.log.error(&format!("{name}: {e:#}"));
|
||||
}
|
||||
}
|
||||
return Ok(if failed > 0 { 1 } else { 0 });
|
||||
}
|
||||
bail!("update requires an agent name, or --all");
|
||||
}
|
||||
|
||||
fn update_one(app: &App, runner: &dyn Runner, name: &str) -> Result<i32> {
|
||||
let agent = require_agent(app, name)?;
|
||||
let Some(entry) = app.state.get(&agent.name).ok().flatten() else {
|
||||
bail!(
|
||||
"agent '{}' is not installed by agent-manager — use 'am install {}'",
|
||||
agent.name,
|
||||
agent.name
|
||||
);
|
||||
};
|
||||
let spec = agent
|
||||
.install
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow::anyhow!("agent '{}' has no install definition", agent.name))?;
|
||||
let methods = spec.all_methods();
|
||||
// Prefer the method that was originally used.
|
||||
let method = methods
|
||||
.iter()
|
||||
.find(|m| m.kind.as_str() == entry.method)
|
||||
.copied()
|
||||
.unwrap_or(methods[0]);
|
||||
|
||||
let latest = if app.dry_run() {
|
||||
None
|
||||
} else {
|
||||
installers::latest_version(app, agent, method, runner)?
|
||||
};
|
||||
let current = entry.version.clone().or_else(|| {
|
||||
entry
|
||||
.bins
|
||||
.first()
|
||||
.and_then(|b| installers::detect_version(runner, &PathBuf::from(b)))
|
||||
});
|
||||
|
||||
match (&latest, ¤t) {
|
||||
(Some(l), Some(c)) => match crate::version::compare(l, c) {
|
||||
Some(Ordering::Greater) => {
|
||||
app.log.info(&format!("update available: {c} -> {l}"));
|
||||
}
|
||||
Some(Ordering::Equal) | Some(Ordering::Less) => {
|
||||
app.log
|
||||
.success(&format!("{} is up to date (v{c})", agent.title()));
|
||||
return Ok(0);
|
||||
}
|
||||
None => {
|
||||
app.log.warn(&format!("cannot compare versions ({c} vs {l}); reinstalling"));
|
||||
}
|
||||
},
|
||||
(Some(l), None) => app.log.info(&format!(
|
||||
"latest available: {l} (installed version unknown); reinstalling"
|
||||
)),
|
||||
(None, Some(c)) => app.log.warn(&format!(
|
||||
"cannot determine the latest version (installed: {c}); reinstalling"
|
||||
)),
|
||||
(None, None) => app.log.warn("cannot determine versions; reinstalling"),
|
||||
}
|
||||
|
||||
if app.dry_run() {
|
||||
app.log
|
||||
.dry(format!("would reinstall {} via {}", agent.name, method.kind));
|
||||
return Ok(0);
|
||||
}
|
||||
crate::deps::ensure_deps(app, agent, runner)?;
|
||||
let outcome = installers::run_install(app, agent, method, runner)?;
|
||||
let mut new_entry = installers::make_entry(agent, method, &outcome, app);
|
||||
new_entry.installed_at = entry.installed_at.clone();
|
||||
new_entry.updated_at = Some(installers::now_rfc3339());
|
||||
let version = new_entry.version.clone().unwrap_or_else(|| "unknown".to_string());
|
||||
app.state.set(&new_entry)?;
|
||||
app.log.success(&format!(
|
||||
"updated {} to v{version}",
|
||||
agent.title()
|
||||
));
|
||||
Ok(0)
|
||||
}
|
||||
Reference in New Issue
Block a user