agent_core/tui/commands/
registry.rs

1//! Command registry for managing slash commands.
2
3use super::standard::default_commands;
4use super::traits::SlashCommand;
5
6/// Registry of slash commands for an agent.
7///
8/// Provides a builder-style API for configuring which commands are available.
9///
10/// # Example
11///
12/// ```ignore
13/// use agent_core::tui::commands::{
14///     CommandRegistry, CustomCommand, CommandResult,
15///     HelpCommand, ClearCommand, ThemesCommand,
16/// };
17///
18/// // Start with defaults and customize
19/// let commands = CommandRegistry::with_defaults()
20///     .add(CustomCommand::new("deploy", "Deploy the app", |args, ctx| {
21///         CommandResult::Message(format!("Deploying to {}...", args))
22///     }))
23///     .remove("quit")  // Disable quit command
24///     .build();
25///
26/// // Or build from scratch
27/// let commands = CommandRegistry::new()
28///     .add(HelpCommand)
29///     .add(ClearCommand)
30///     .add(ThemesCommand)
31///     .build();
32/// ```
33pub struct CommandRegistry {
34    commands: Vec<Box<dyn SlashCommand>>,
35}
36
37impl CommandRegistry {
38    /// Create an empty registry with no commands.
39    pub fn new() -> Self {
40        Self {
41            commands: Vec::new(),
42        }
43    }
44
45    /// Create a registry with the default commands.
46    ///
47    /// Default commands include: help, clear, compact, themes, sessions,
48    /// status, version, new-session, and quit.
49    pub fn with_defaults() -> Self {
50        Self {
51            commands: default_commands(),
52        }
53    }
54
55    /// Add a command to the registry.
56    ///
57    /// # Example
58    ///
59    /// ```ignore
60    /// registry.add(ClearCommand).add(HelpCommand);
61    /// ```
62    pub fn add<C: SlashCommand + 'static>(mut self, command: C) -> Self {
63        self.commands.push(Box::new(command));
64        self
65    }
66
67    /// Add a boxed command to the registry.
68    ///
69    /// Use this when you already have a `Box<dyn SlashCommand>`.
70    pub fn add_boxed(mut self, command: Box<dyn SlashCommand>) -> Self {
71        self.commands.push(command);
72        self
73    }
74
75    /// Remove a command by name.
76    ///
77    /// # Example
78    ///
79    /// ```ignore
80    /// // Disable the quit command
81    /// registry.remove("quit");
82    /// ```
83    pub fn remove(mut self, name: &str) -> Self {
84        self.commands.retain(|c| c.name() != name);
85        self
86    }
87
88    /// Build into the final command list.
89    ///
90    /// Consumes the registry and returns the commands.
91    pub fn build(self) -> Vec<Box<dyn SlashCommand>> {
92        self.commands
93    }
94
95    /// Get commands as a slice (for inspection without consuming).
96    pub fn commands(&self) -> &[Box<dyn SlashCommand>] {
97        &self.commands
98    }
99}
100
101impl Default for CommandRegistry {
102    fn default() -> Self {
103        Self::with_defaults()
104    }
105}