feat(cli): add register-agent and list-agents commands #82
2 changed files with 64 additions and 0 deletions
|
|
@ -48,6 +48,11 @@ enum Command {
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
category: Option<String>,
|
category: Option<String>,
|
||||||
},
|
},
|
||||||
|
RegisterAgent {
|
||||||
|
name: String,
|
||||||
|
capabilities: Vec<String>,
|
||||||
|
},
|
||||||
|
ListAgents,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_socket_path() -> PathBuf {
|
fn default_socket_path() -> PathBuf {
|
||||||
|
|
@ -81,6 +86,8 @@ Examples:
|
||||||
colibri list-tasks --status queued
|
colibri list-tasks --status queued
|
||||||
colibri register-skill freebsd-check --description "Live USB startup check" --category freebsd
|
colibri register-skill freebsd-check --description "Live USB startup check" --category freebsd
|
||||||
colibri list-skills
|
colibri list-skills
|
||||||
|
colibri register-agent NAME [--capability CAP]... [--capabilities CSV]
|
||||||
|
colibri list-agents
|
||||||
"#
|
"#
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,6 +173,7 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
"list-skills" => expect_arity(&args, 1).map(|()| Command::ListSkills),
|
"list-skills" => expect_arity(&args, 1).map(|()| Command::ListSkills),
|
||||||
|
"list-agents" => expect_arity(&args, 1).map(|()| Command::ListAgents),
|
||||||
"register-skill" => {
|
"register-skill" => {
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
Err("register-skill requires NAME\n\n".to_string() + usage())
|
Err("register-skill requires NAME\n\n".to_string() + usage())
|
||||||
|
|
@ -178,6 +186,17 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"register-agent" => {
|
||||||
|
if args.len() < 2 {
|
||||||
|
Err("register-agent requires NAME\n\n".to_string() + usage())
|
||||||
|
} else {
|
||||||
|
let capabilities = parse_capabilities(&args[2..])?;
|
||||||
|
Ok(Command::RegisterAgent {
|
||||||
|
name: args[1].clone(),
|
||||||
|
capabilities,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
other => Err(format!("unknown command: {other}\n\n{}", usage())),
|
other => Err(format!("unknown command: {other}\n\n{}", usage())),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
|
@ -328,6 +347,31 @@ fn parse_spawn_options(args: &[String]) -> Result<(Option<String>, Option<String
|
||||||
Ok((session_id, system_prompt))
|
Ok((session_id, system_prompt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_capabilities(args: &[String]) -> Result<Vec<String>, String> {
|
||||||
|
let mut caps = Vec::new();
|
||||||
|
let mut i = 0;
|
||||||
|
while i < args.len() {
|
||||||
|
match args[i].as_str() {
|
||||||
|
"--capability" => {
|
||||||
|
let Some(value) = args.get(i + 1) else {
|
||||||
|
return Err("--capability requires CAP\n\n".to_string() + usage());
|
||||||
|
};
|
||||||
|
caps.push(value.clone());
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
"--capabilities" => {
|
||||||
|
let Some(value) = args.get(i + 1) else {
|
||||||
|
return Err("--capabilities requires CSV\n\n".to_string() + usage());
|
||||||
|
};
|
||||||
|
caps.extend(value.split(',').map(str::trim).filter(|c| !c.is_empty()).map(ToString::to_string));
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
other => return Err(format!("unknown register-agent option: {other}\n\n{}", usage())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(caps)
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_skill_options(args: &[String]) -> Result<(Option<String>, Option<String>), String> {
|
fn parse_skill_options(args: &[String]) -> Result<(Option<String>, Option<String>), String> {
|
||||||
let mut description = None;
|
let mut description = None;
|
||||||
let mut category = None;
|
let mut category = None;
|
||||||
|
|
@ -395,6 +439,10 @@ async fn run(options: Options) -> Result<(), ClientError> {
|
||||||
description,
|
description,
|
||||||
category,
|
category,
|
||||||
} => print_json(&client.register_skill(name, description, category).await?),
|
} => print_json(&client.register_skill(name, description, category).await?),
|
||||||
|
Command::RegisterAgent { name, capabilities } => {
|
||||||
|
print_json(&client.register_agent(name, capabilities).await?)
|
||||||
|
}
|
||||||
|
Command::ListAgents => print_json(&client.list_agents().await?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,22 @@ impl DaemonClient {
|
||||||
self.request(&ColibriCommand::ListSkills).await
|
self.request(&ColibriCommand::ListSkills).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn register_agent(
|
||||||
|
&self,
|
||||||
|
name: impl Into<String>,
|
||||||
|
capabilities: Vec<String>,
|
||||||
|
) -> Result<serde_json::Value, ClientError> {
|
||||||
|
self.request(&ColibriCommand::RegisterAgent {
|
||||||
|
name: name.into(),
|
||||||
|
capabilities: Some(serde_json::to_value(capabilities).unwrap_or_default()),
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list_agents(&self) -> Result<serde_json::Value, ClientError> {
|
||||||
|
self.request(&ColibriCommand::ListAgents).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn register_skill(
|
pub async fn register_skill(
|
||||||
&self,
|
&self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue