1use crate::runner::gateway::GatewayRunner;
4use anyhow::Result;
5use clap::Subcommand;
6use protocol::ServerMessage;
7
8#[derive(Subcommand, Debug)]
10pub enum AgentCommand {
11 List,
13 Info {
15 name: String,
17 },
18}
19
20impl AgentCommand {
21 pub async fn run(&self, runner: &mut GatewayRunner) -> Result<()> {
23 match self {
24 Self::List => list(runner).await,
25 Self::Info { name } => info(runner, name).await,
26 }
27 }
28}
29
30async fn list(runner: &mut GatewayRunner) -> Result<()> {
31 let agents = runner.list_agents().await?;
32 if agents.is_empty() {
33 println!("No agents registered.");
34 return Ok(());
35 }
36 for agent in agents {
37 let desc = if agent.description.is_empty() {
38 "(no description)"
39 } else {
40 agent.description.as_str()
41 };
42 println!(" {} — {}", agent.name, desc);
43 }
44 Ok(())
45}
46
47async fn info(runner: &mut GatewayRunner, name: &str) -> Result<()> {
48 match runner.agent_info(name).await? {
49 ServerMessage::AgentDetail {
50 name,
51 description,
52 tools,
53 skill_tags,
54 system_prompt,
55 } => {
56 println!("Name: {name}");
57 println!("Description: {description}");
58 let tools_str = if tools.is_empty() {
59 "(none)".to_owned()
60 } else {
61 tools
62 .iter()
63 .map(|t| t.as_str())
64 .collect::<Vec<_>>()
65 .join(", ")
66 };
67 let tags_str = if skill_tags.is_empty() {
68 "(none)".to_owned()
69 } else {
70 skill_tags
71 .iter()
72 .map(|t| t.as_str())
73 .collect::<Vec<_>>()
74 .join(", ")
75 };
76 println!("Tools: {tools_str}");
77 println!("Skill tags: {tags_str}");
78 if !system_prompt.is_empty() {
79 println!("\nSystem prompt:\n{system_prompt}");
80 }
81 }
82 ServerMessage::Error { code, message } => {
83 anyhow::bail!("error ({code}): {message}");
84 }
85 other => anyhow::bail!("unexpected response: {other:?}"),
86 }
87 Ok(())
88}