Axe 11 (modèles) : - am models : inventaire des runtimes locaux (ollama list --format json, llama.cpp .gguf sur disque, LM Studio API locale) avec cache façon probe.rs (TTL 30s) et absence de runtime signalée sans erreur fatale - am run <agent> --model <m> : résolution dans l'inventaire, transmission via model_env/model_arg de l'agent (défaut AM_MODEL), tracé en session - am models --prune : candidats inutilisés depuis settings.models_prune_days (défaut 30), :latest toujours protégé, dry-run + confirmation + événement EventKind::Model journalisé Axes 7/9 (catalogue) : - am catalog update : fetch du catalogue officiel, diff (ajoutés/retirés/ modifiés), confirmation, enregistrement en include - am catalog add <url> : validation du format (parse + validate), cache catalog-cache.json (TTL 3600s), événement EventKind::Catalog journalisé - include par URL (http/https/file) dans config.yaml, résolu au chargement avec cache + TTL ; override local toujours prioritaire (issue #67) - am suggest <requête> : réutilise le scoring fuzzy du catalogue, boost par usage réel (lancements + durée depuis le journal), top 5 justifié, --json REPL : commandes models/catalog/suggest (parse, complétion, descriptions), help specs, tip cheat sheet, man pages régénérées (49 pages, dont 3 nouvelles). Version bump 0.4.5, ROADMAP cases cochées, 266 tests verts.
107 lines
3.3 KiB
Rust
107 lines
3.3 KiB
Rust
//! agent-manager — a CLI to manage local AI coding agents.
|
|
//!
|
|
//! The crate is organised around a few core concepts:
|
|
//!
|
|
//! * cli — clap definitions for the am command line interface.
|
|
//! * config — YAML schema, loading, validation, includes, path expansion.
|
|
//! * catalog — the merged agent catalog (embedded defaults + user config).
|
|
//! * state — the local installation database (JSON file).
|
|
//! * process — background/foreground process management (PID bookkeeping).
|
|
//! * installers — one installer per method (npm, pip, cargo, go, bun, curl,
|
|
//! binary, git).
|
|
//! * commands — one module per CLI command.
|
|
|
|
pub mod app;
|
|
pub mod catalog;
|
|
pub mod catalog_remote;
|
|
pub mod cli;
|
|
pub mod commands;
|
|
pub mod config;
|
|
pub mod context;
|
|
pub mod dashboard;
|
|
pub mod deps;
|
|
pub mod doctor;
|
|
pub mod download;
|
|
pub mod events;
|
|
pub mod help;
|
|
pub mod history;
|
|
pub mod hooks;
|
|
pub mod installers;
|
|
pub mod models;
|
|
pub mod nav;
|
|
pub mod output;
|
|
pub mod probe;
|
|
pub mod projects;
|
|
pub mod ps;
|
|
pub mod process;
|
|
pub mod repl;
|
|
pub mod runner;
|
|
pub mod secrets;
|
|
pub mod sessions;
|
|
pub mod shell;
|
|
pub mod state;
|
|
pub mod tables;
|
|
pub mod theme;
|
|
pub mod toolchain;
|
|
pub mod version;
|
|
|
|
use clap::Parser;
|
|
|
|
/// CLI entry point used by the am binary. Returns the process exit code.
|
|
///
|
|
/// The whole run happens on a dedicated thread with a large stack: clap's
|
|
/// derive code for the full command tree (40+ subcommands) uses deep stack
|
|
/// frames in debug builds, which overflows the Windows main-thread default
|
|
/// (1 MB). An 8 MB thread keeps every build mode on every platform safe.
|
|
pub fn main_entry() -> i32 {
|
|
std::thread::Builder::new()
|
|
.name("am-main".to_string())
|
|
.stack_size(8 * 1024 * 1024)
|
|
.spawn(real_main)
|
|
.expect("cannot spawn the am main thread")
|
|
.join()
|
|
.unwrap_or(1)
|
|
}
|
|
|
|
/// The actual entry point, running on the big-stack thread.
|
|
fn real_main() -> i32 {
|
|
// Enable ANSI escape sequences on Windows consoles (best effort): the
|
|
// colored crate and the theme palettes both emit raw VT codes.
|
|
#[cfg(windows)]
|
|
let _ = colored::control::set_virtual_terminal(true);
|
|
|
|
// Nushell-style help: 'am -h', 'am install -h', 'am ls --help', ... all
|
|
// show the custom help before clap gets a chance to parse the line.
|
|
let args: Vec<String> = std::env::args().collect();
|
|
if let Some(code) = help::intercept(&args) {
|
|
return code;
|
|
}
|
|
let cli = cli::Cli::parse();
|
|
match app::App::from_cli(cli) {
|
|
Ok(app) => match commands::execute(&app) {
|
|
Ok(code) => code,
|
|
Err(err) => {
|
|
if app.json() {
|
|
let payload = serde_json::json!({
|
|
"error": format!("{:#}", err),
|
|
});
|
|
let _ = serde_json::to_writer_pretty(std::io::stdout(), &payload);
|
|
let _ = writeln!(std::io::stdout());
|
|
} else {
|
|
eprintln!("{} {}", "error:".red().bold(), format!("{:#}", err));
|
|
}
|
|
1
|
|
}
|
|
},
|
|
Err(err) => {
|
|
// Config could not even be loaded: fall back to plain stderr output.
|
|
eprintln!("{} {}", "error:".red().bold(), format!("{:#}", err));
|
|
1
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(unused_imports)]
|
|
use colored::Colorize;
|
|
use std::io::Write;
|