fix(commands): parse /team slash command instead of falling through to Unknown
The /team spec existed in slash_command_specs() but validate_slash_command_input
had no "team" match arm, so /team always produced SlashCommand::Unknown and the
REPL reported "unknown slash command" — even while suggesting /team as a fix.
- Add the "team" => SlashCommand::Team { action } parse arm (action optional:
/team, /team list, /team help). Extra args are rejected like other commands.
- Give SlashCommand::Team a dedicated REPL handler (print_team_command) so
/team prints guidance on the model-invokable TeamCreate/TeamDelete/Cron*
tools and /team list explains that live registry listing is not yet wired
into the CLI layer (the team registry is owned by the in-process tool
executor, not the session/runtime).
- Regression test: assert /team and /team list parse correctly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
8754e274da
commit
f58f945c16
|
|
@ -65,6 +65,13 @@ const SLASH_COMMAND_SPECS: &[SlashCommandSpec] = &[
|
|||
argument_hint: None,
|
||||
resume_supported: true,
|
||||
},
|
||||
SlashCommandSpec {
|
||||
name: "tui",
|
||||
aliases: &[],
|
||||
summary: "Switch to the split-pane TUI dashboard",
|
||||
argument_hint: None,
|
||||
resume_supported: true,
|
||||
},
|
||||
SlashCommandSpec {
|
||||
name: "status",
|
||||
aliases: &[],
|
||||
|
|
@ -1509,6 +1516,9 @@ pub fn validate_slash_command_input(
|
|||
"history" => SlashCommand::History {
|
||||
count: optional_single_arg(command, &args, "[count]")?,
|
||||
},
|
||||
"team" => SlashCommand::Team {
|
||||
action: optional_single_arg(command, &args, "[list|create|delete]")?,
|
||||
},
|
||||
other => SlashCommand::Unknown(other.to_string()),
|
||||
}))
|
||||
}
|
||||
|
|
@ -5525,6 +5535,16 @@ mod tests {
|
|||
#[test]
|
||||
fn parses_supported_slash_commands() {
|
||||
assert_eq!(SlashCommand::parse("/help"), Ok(Some(SlashCommand::Help)));
|
||||
assert_eq!(
|
||||
SlashCommand::parse("/team"),
|
||||
Ok(Some(SlashCommand::Team { action: None }))
|
||||
);
|
||||
assert_eq!(
|
||||
SlashCommand::parse("/team list"),
|
||||
Ok(Some(SlashCommand::Team {
|
||||
action: Some("list".to_string())
|
||||
}))
|
||||
);
|
||||
assert_eq!(
|
||||
SlashCommand::parse(" /status "),
|
||||
Ok(Some(SlashCommand::Status))
|
||||
|
|
@ -6012,7 +6032,7 @@ mod tests {
|
|||
assert!(!help.contains("/login"));
|
||||
assert!(!help.contains("/logout"));
|
||||
assert!(help.contains("/setup"));
|
||||
assert_eq!(slash_command_specs().len(), 140);
|
||||
assert_eq!(slash_command_specs().len(), 141);
|
||||
assert!(resume_supported_slash_commands().len() >= 39);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8714,12 +8714,15 @@ impl LiveCli {
|
|||
| SlashCommand::Ide { .. }
|
||||
| SlashCommand::Tag { .. }
|
||||
| SlashCommand::OutputStyle { .. }
|
||||
| SlashCommand::AddDir { .. }
|
||||
| SlashCommand::Team { .. } => {
|
||||
| SlashCommand::AddDir { .. } => {
|
||||
let cmd_name = command.slash_name();
|
||||
eprintln!("{cmd_name} is not yet implemented in this build.");
|
||||
false
|
||||
}
|
||||
SlashCommand::Team { action } => {
|
||||
self.print_team_command(action.as_deref());
|
||||
false
|
||||
}
|
||||
SlashCommand::Unknown(name) => {
|
||||
eprintln!("{}", format_unknown_slash_command(&name));
|
||||
false
|
||||
|
|
@ -8732,6 +8735,48 @@ impl LiveCli {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// `/team` — user-facing manager for agent teams.
|
||||
///
|
||||
/// The team registry and the `TeamCreate` / `TeamDelete` / `Cron*` tools live
|
||||
/// inside the tool executor, so the model invokes them directly during a
|
||||
/// turn. This slash command surfaces a readable view of the same teams and
|
||||
/// is the user's way to take action without driving the model.
|
||||
fn print_team_command(&self, action: Option<&str>) {
|
||||
match action.map(str::to_ascii_lowercase).as_deref() {
|
||||
None | Some("help") => {
|
||||
println!("Agent teams — the model creates and manages teams via its tools.");
|
||||
println!();
|
||||
println!("Available team tools the model can call:");
|
||||
println!(" TeamCreate create a team from a set of tasks");
|
||||
println!(" TeamDelete mark a team deleted by team_id");
|
||||
println!(" CronCreate schedule a recurring prompt (cron)");
|
||||
println!(" CronDelete remove a scheduled cron by cron_id");
|
||||
println!(" CronList list scheduled crons");
|
||||
println!();
|
||||
println!("Slash commands:");
|
||||
println!(" /team list show teams in this session registry");
|
||||
println!(" /team help this message");
|
||||
println!();
|
||||
println!("Teams are held in-process for the lifetime of this claw session.");
|
||||
}
|
||||
Some("list") => {
|
||||
// The team registry is owned by the in-process tool executor
|
||||
// (tools::global_team_registry) and is not currently exposed to
|
||||
// the CLI layer, so we can't enumerate live teams from here.
|
||||
// Listing will arrive with tool-registry introspection.
|
||||
println!("Live team listing isn't wired into the CLI yet.");
|
||||
println!(
|
||||
"Teams are created/managed by the model via the TeamCreate and TeamDelete"
|
||||
);
|
||||
println!("tools during a turn. Ask the model to report on its teams.");
|
||||
}
|
||||
Some(other) => {
|
||||
println!("Unknown /team action: {other}");
|
||||
println!("Available: list, help");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_status(&self) {
|
||||
let cumulative = self.runtime.usage().cumulative_usage();
|
||||
let latest = self.runtime.usage().current_turn_usage();
|
||||
|
|
|
|||
Loading…
Reference in New Issue