use bitrouter_config::BitrouterConfig;
pub fn run_list(config: &BitrouterConfig) -> Result<(), Box<dyn std::error::Error>> {
let mut known = bitrouter_config::builtin_agent_defs();
for (name, agent_config) in &config.agents {
known.insert(name.clone(), agent_config.clone());
}
if known.is_empty() {
println!(" (no agents configured)");
return Ok(());
}
let discovered = bitrouter_providers::acp::discovery::discover_agents(&known);
let mut names: Vec<_> = known.keys().cloned().collect();
names.sort();
for name in &names {
let agent = &known[name];
let on_path = discovered.iter().any(|d| &d.name == name);
let status = if on_path {
"\u{2713} found"
} else {
"\u{2717} not on PATH"
};
println!(" {name} {} {} {status}", agent.protocol, agent.binary,);
}
Ok(())
}
pub fn run_check(config: &BitrouterConfig) -> Result<(), Box<dyn std::error::Error>> {
let listen = config.server.listen;
let base = format!("http://{listen}");
println!();
println!(" Agent Routing Check");
println!(" ───────────────────");
println!();
let env_checks = [
("OPENAI_BASE_URL", format!("{base}/v1")),
("ANTHROPIC_BASE_URL", format!("{base}/v1")),
("GOOGLE_AI_BASE_URL", format!("{base}/v1beta")),
];
let mut env_ok = true;
for (var, expected) in &env_checks {
match std::env::var(var) {
Ok(val) if val == *expected => {
println!(" \u{2713} {var} = {val}");
}
Ok(val) => {
println!(" \u{26a0} {var} = {val} (expected {expected})");
env_ok = false;
}
Err(_) => {
println!(" \u{2717} {var} not set (expected {expected})");
env_ok = false;
}
}
}
if !env_ok {
println!();
println!(" Env vars missing or mismatched. To fix, add to your shell profile:");
for (var, expected) in &env_checks {
println!(" export {var}={expected}");
}
println!();
println!(" Then run: source ~/.zshrc (or open a new terminal)");
}
println!();
match std::net::TcpStream::connect_timeout(&listen, std::time::Duration::from_secs(2)) {
Ok(_) => {
println!(" \u{2713} BitRouter reachable at {listen}");
}
Err(_) => {
println!(" \u{2717} BitRouter not reachable at {listen}");
println!(" Start the server: bitrouter serve");
}
}
println!();
let mut known = bitrouter_config::builtin_agent_defs();
for (name, agent_config) in &config.agents {
known.insert(name.clone(), agent_config.clone());
}
let discovered = bitrouter_providers::acp::discovery::discover_agents(&known);
if discovered.is_empty() {
println!(" \u{2717} No ACP agents discovered");
} else {
use bitrouter_providers::acp::types::AgentAvailability;
let on_path: Vec<&str> = discovered
.iter()
.filter(|a| matches!(a.availability, AgentAvailability::OnPath(_)))
.map(|a| a.name.as_str())
.collect();
let distributable: Vec<&str> = discovered
.iter()
.filter(|a| matches!(a.availability, AgentAvailability::Distributable))
.map(|a| a.name.as_str())
.collect();
if !on_path.is_empty() {
println!(" \u{2713} Agents on PATH: {}", on_path.join(", "));
}
if !distributable.is_empty() {
println!(
" \u{2713} Agents available (auto-install): {}",
distributable.join(", ")
);
}
}
println!();
Ok(())
}