Skip to main content

objectiveai_sdk/cli/command/
command.rs

1//! Root-level clap `Command` plus the matching typed `Request` /
2//! `ResponseItem` aggregators and conversions, mirroring the same
3//! pattern every tier `mod.rs` follows for its own subcommands.
4
5#[derive(clap::Subcommand)]
6pub enum Subcommand {
7    Agents {
8        #[command(subcommand)]
9        command: super::agents::Command,
10    },
11    Api {
12        #[command(subcommand)]
13        command: super::api::Command,
14    },
15    Daemon {
16        #[command(subcommand)]
17        command: super::daemon::Command,
18    },
19    Db {
20        #[command(subcommand)]
21        command: super::db::Command,
22    },
23    Functions {
24        #[command(subcommand)]
25        command: super::functions::Command,
26    },
27    Laboratories {
28        #[command(subcommand)]
29        command: super::laboratories::Command,
30    },
31    Mcp {
32        #[command(subcommand)]
33        command: super::mcp::Command,
34    },
35    Plugins {
36        #[command(subcommand)]
37        command: super::plugins::Command,
38    },
39    /// Run a Python snippet and return its output as JSON.
40    Python(super::python::Command),
41    Swarms {
42        #[command(subcommand)]
43        command: super::swarms::Command,
44    },
45    Tools {
46        #[command(subcommand)]
47        command: super::tools::Command,
48    },
49    Update(super::update::Command),
50    User {
51        #[command(subcommand)]
52        command: super::user::Command,
53    },
54    Viewer {
55        #[command(subcommand)]
56        command: super::viewer::Command,
57    },
58}
59
60#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
61#[serde(untagged)]
62#[schemars(rename = "cli.command.Request")]
63pub enum Request {
64    #[schemars(title = "Agents")]
65    Agents(super::agents::Request),
66    #[schemars(title = "Api")]
67    Api(super::api::Request),
68    #[schemars(title = "Daemon")]
69    Daemon(super::daemon::Request),
70    #[schemars(title = "Db")]
71    Db(super::db::Request),
72    #[schemars(title = "Functions")]
73    Functions(super::functions::Request),
74    #[schemars(title = "Laboratories")]
75    Laboratories(super::laboratories::Request),
76    #[schemars(title = "Mcp")]
77    Mcp(super::mcp::Request),
78    #[schemars(title = "Plugins")]
79    Plugins(super::plugins::Request),
80    #[schemars(title = "Python")]
81    Python(super::python::Request),
82    #[schemars(title = "PythonRequestSchema")]
83    PythonRequestSchema(super::python::request_schema::Request),
84    #[schemars(title = "PythonResponseSchema")]
85    PythonResponseSchema(super::python::response_schema::Request),
86    #[schemars(title = "Swarms")]
87    Swarms(super::swarms::Request),
88    #[schemars(title = "Tools")]
89    Tools(super::tools::Request),
90    #[schemars(title = "Update")]
91    Update(super::update::Request),
92    #[schemars(title = "UpdateRequestSchema")]
93    UpdateRequestSchema(super::update::request_schema::Request),
94    #[schemars(title = "UpdateResponseSchema")]
95    UpdateResponseSchema(super::update::response_schema::Request),
96    #[schemars(title = "User")]
97    User(super::user::Request),
98    #[schemars(title = "Viewer")]
99    Viewer(super::viewer::Request),
100}
101
102// Exempt from json-schema coverage: the aggregate's transitive
103// expansion spans the whole command tree, which downstream
104// generated TypeScript cannot emit declarations for (TS7056), and
105// no consumer uses the aggregate schema — leaf schemas cover the
106// wire.
107#[objectiveai_sdk_macros::json_schema_ignore]
108#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
109#[schemars(rename = "cli.command.ResponseItem")]
110#[serde(untagged)]
111pub enum ResponseItem {
112    #[schemars(title = "Agents")]
113    Agents(super::agents::ResponseItem),
114    #[schemars(title = "Api")]
115    Api(super::api::Response),
116    #[schemars(title = "Daemon")]
117    Daemon(super::daemon::ResponseItem),
118    #[schemars(title = "Db")]
119    Db(super::db::ResponseItem),
120    #[schemars(title = "Functions")]
121    Functions(super::functions::ResponseItem),
122    #[schemars(title = "Laboratories")]
123    Laboratories(super::laboratories::ResponseItem),
124    #[schemars(title = "Mcp")]
125    Mcp(super::mcp::Response),
126    #[schemars(title = "Plugins")]
127    Plugins(super::plugins::ResponseItem),
128    #[schemars(title = "Python")]
129    Python(serde_json::Value),
130    #[schemars(title = "PythonRequestSchema")]
131    PythonRequestSchema(super::python::request_schema::Response),
132    #[schemars(title = "PythonResponseSchema")]
133    PythonResponseSchema(super::python::response_schema::Response),
134    #[schemars(title = "Swarms")]
135    Swarms(super::swarms::ResponseItem),
136    #[schemars(title = "Tools")]
137    Tools(super::tools::ResponseItem),
138    #[schemars(title = "Update")]
139    Update(super::update::ResponseItem),
140    #[schemars(title = "UpdateRequestSchema")]
141    UpdateRequestSchema(super::update::request_schema::Response),
142    #[schemars(title = "UpdateResponseSchema")]
143    UpdateResponseSchema(super::update::response_schema::Response),
144    #[schemars(title = "User")]
145    User(super::user::Response),
146    #[schemars(title = "Viewer")]
147    Viewer(super::viewer::Response),
148}
149
150#[cfg(feature = "mcp")]
151impl super::CommandResponse for ResponseItem {
152    fn into_mcp(self) -> super::McpResponseItem {
153        match self {
154            ResponseItem::Agents(v) => v.into_mcp(),
155            ResponseItem::Api(v) => v.into_mcp(),
156            ResponseItem::Daemon(v) => v.into_mcp(),
157            ResponseItem::Db(v) => v.into_mcp(),
158            ResponseItem::Functions(v) => v.into_mcp(),
159            ResponseItem::Laboratories(v) => v.into_mcp(),
160            ResponseItem::Mcp(v) => v.into_mcp(),
161            ResponseItem::Plugins(v) => v.into_mcp(),
162            ResponseItem::Python(v) => v.into_mcp(),
163            ResponseItem::PythonRequestSchema(v) => v.into_mcp(),
164            ResponseItem::PythonResponseSchema(v) => v.into_mcp(),
165            ResponseItem::Swarms(v) => v.into_mcp(),
166            ResponseItem::Tools(v) => v.into_mcp(),
167            ResponseItem::Update(v) => v.into_mcp(),
168            ResponseItem::UpdateRequestSchema(v) => v.into_mcp(),
169            ResponseItem::UpdateResponseSchema(v) => v.into_mcp(),
170            ResponseItem::User(v) => v.into_mcp(),
171            ResponseItem::Viewer(v) => v.into_mcp(),
172        }
173    }
174}
175
176impl TryFrom<Subcommand> for Request {
177    type Error = super::FromArgsError;
178    fn try_from(command: Subcommand) -> Result<Self, Self::Error> {
179        match command {
180            Subcommand::Agents { command } =>
181                Ok(Request::Agents(super::agents::Request::try_from(command)?)),
182            Subcommand::Api { command } =>
183                Ok(Request::Api(super::api::Request::try_from(command)?)),
184            Subcommand::Daemon { command } =>
185                Ok(Request::Daemon(super::daemon::Request::try_from(command)?)),
186            Subcommand::Db { command } =>
187                Ok(Request::Db(super::db::Request::try_from(command)?)),
188            Subcommand::Functions { command } =>
189                Ok(Request::Functions(super::functions::Request::try_from(command)?)),
190            Subcommand::Laboratories { command } =>
191                Ok(Request::Laboratories(super::laboratories::Request::try_from(command)?)),
192            Subcommand::Mcp { command } =>
193                Ok(Request::Mcp(super::mcp::Request::try_from(command)?)),
194            Subcommand::Plugins { command } =>
195                Ok(Request::Plugins(super::plugins::Request::try_from(command)?)),
196            Subcommand::Python(cmd) => match cmd.schema {
197                None => Ok(Request::Python(super::python::Request::try_from(cmd.args)?)),
198                Some(super::python::Schema::RequestSchema(args)) =>
199                    Ok(Request::PythonRequestSchema(super::python::request_schema::Request::try_from(args)?)),
200                Some(super::python::Schema::ResponseSchema(args)) =>
201                    Ok(Request::PythonResponseSchema(super::python::response_schema::Request::try_from(args)?)),
202            },
203            Subcommand::Swarms { command } =>
204                Ok(Request::Swarms(super::swarms::Request::try_from(command)?)),
205            Subcommand::Tools { command } =>
206                Ok(Request::Tools(super::tools::Request::try_from(command)?)),
207            Subcommand::Update(cmd) => match cmd.schema {
208                None => Ok(Request::Update(super::update::Request::try_from(cmd.args)?)),
209                Some(super::update::Schema::RequestSchema(args)) =>
210                    Ok(Request::UpdateRequestSchema(super::update::request_schema::Request::try_from(args)?)),
211                Some(super::update::Schema::ResponseSchema(args)) =>
212                    Ok(Request::UpdateResponseSchema(super::update::response_schema::Request::try_from(args)?)),
213            },
214            Subcommand::User { command } =>
215                Ok(Request::User(super::user::Request::try_from(command)?)),
216            Subcommand::Viewer { command } =>
217                Ok(Request::Viewer(super::viewer::Request::try_from(command)?)),
218        }
219    }
220}
221
222impl TryFrom<Command> for Request {
223    type Error = super::FromArgsError;
224    fn try_from(command: Command) -> Result<Self, Self::Error> {
225        match (command.request, command.command) {
226            // `--request <json>`: deserialize straight into the aggregate
227            // Request (serde-tagged on `path_type`) — the same wire shape the
228            // SDKs already serialize. Mutually exclusive with a subcommand
229            // (clap enforces it), so the `_` arm can't carry a command.
230            (Some(json), _) => {
231                let de = &mut serde_json::Deserializer::from_str(&json);
232                serde_path_to_error::deserialize(de)
233                    .map_err(|e| super::FromArgsError::json("request", e))
234            }
235            (None, Some(subcommand)) => Request::try_from(subcommand),
236            // Unreachable in practice: `arg_required_else_help` turns a bare
237            // invocation into a clap help error before conversion.
238            (None, None) => Err(super::FromArgsError::path_parse(
239                "command",
240                "a command path or --request is required".to_string(),
241            )),
242        }
243    }
244}
245
246impl super::CommandRequest for Request {
247    fn request_base(&self) -> &crate::cli::command::RequestBase {
248        match self {
249            Request::Agents(inner) => inner.request_base(),
250            Request::Api(inner) => inner.request_base(),
251            Request::Daemon(inner) => inner.request_base(),
252            Request::Db(inner) => inner.request_base(),
253            Request::Functions(inner) => inner.request_base(),
254            Request::Laboratories(inner) => inner.request_base(),
255            Request::Mcp(inner) => inner.request_base(),
256            Request::Plugins(inner) => inner.request_base(),
257            Request::Python(inner) => inner.request_base(),
258            Request::PythonRequestSchema(inner) => inner.request_base(),
259            Request::PythonResponseSchema(inner) => inner.request_base(),
260            Request::Swarms(inner) => inner.request_base(),
261            Request::Tools(inner) => inner.request_base(),
262            Request::Update(inner) => inner.request_base(),
263            Request::UpdateRequestSchema(inner) => inner.request_base(),
264            Request::UpdateResponseSchema(inner) => inner.request_base(),
265            Request::User(inner) => inner.request_base(),
266            Request::Viewer(inner) => inner.request_base(),
267        }
268    }
269
270    fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
271        match self {
272            Request::Agents(inner) => inner.request_base_mut(),
273            Request::Api(inner) => inner.request_base_mut(),
274            Request::Daemon(inner) => inner.request_base_mut(),
275            Request::Db(inner) => inner.request_base_mut(),
276            Request::Functions(inner) => inner.request_base_mut(),
277            Request::Laboratories(inner) => inner.request_base_mut(),
278            Request::Mcp(inner) => inner.request_base_mut(),
279            Request::Plugins(inner) => inner.request_base_mut(),
280            Request::Python(inner) => inner.request_base_mut(),
281            Request::PythonRequestSchema(inner) => inner.request_base_mut(),
282            Request::PythonResponseSchema(inner) => inner.request_base_mut(),
283            Request::Swarms(inner) => inner.request_base_mut(),
284            Request::Tools(inner) => inner.request_base_mut(),
285            Request::Update(inner) => inner.request_base_mut(),
286            Request::UpdateRequestSchema(inner) => inner.request_base_mut(),
287            Request::UpdateResponseSchema(inner) => inner.request_base_mut(),
288            Request::User(inner) => inner.request_base_mut(),
289            Request::Viewer(inner) => inner.request_base_mut(),
290        }
291    }
292}
293
294#[cfg(feature = "cli-executor")]
295pub async fn execute<E: super::CommandExecutor>(
296    executor: &E,
297    request: Request,
298
299        agent_arguments: Option<&crate::cli::command::AgentArguments>,
300    ) -> Result<
301    std::pin::Pin<Box<dyn futures::Stream<Item = Result<ResponseItem, E::Error>> + Send>>,
302    E::Error,
303> {
304    use futures::StreamExt;
305    let stream: std::pin::Pin<Box<dyn futures::Stream<Item = Result<ResponseItem, E::Error>> + Send>> =
306        match request {
307            Request::Agents(req) => {
308                let inner = super::agents::execute(executor, req, agent_arguments).await?;
309                Box::pin(inner.map(|r| r.map(ResponseItem::Agents)))
310            }
311            Request::Api(req) => {
312                let inner = super::api::execute(executor, req, agent_arguments).await?;
313                Box::pin(inner.map(|r| r.map(ResponseItem::Api)))
314            }
315            Request::Daemon(req) => {
316                let inner = super::daemon::execute(executor, req, agent_arguments).await?;
317                Box::pin(inner.map(|r| r.map(ResponseItem::Daemon)))
318            }
319            Request::Db(req) => {
320                let inner = super::db::execute(executor, req, agent_arguments).await?;
321                Box::pin(inner.map(|r| r.map(ResponseItem::Db)))
322            }
323            Request::Functions(req) => {
324                let inner = super::functions::execute(executor, req, agent_arguments).await?;
325                Box::pin(inner.map(|r| r.map(ResponseItem::Functions)))
326            }
327            Request::Laboratories(req) => {
328                let inner = super::laboratories::execute(executor, req, agent_arguments).await?;
329                Box::pin(inner.map(|r| r.map(ResponseItem::Laboratories)))
330            }
331            Request::Mcp(req) => {
332                let inner = super::mcp::execute(executor, req, agent_arguments).await?;
333                Box::pin(inner.map(|r| r.map(ResponseItem::Mcp)))
334            }
335            Request::Plugins(req) => {
336                let inner = super::plugins::execute(executor, req, agent_arguments).await?;
337                Box::pin(inner.map(|r| r.map(ResponseItem::Plugins)))
338            }
339            Request::Python(req) => {
340                let value = super::python::execute(executor, req, agent_arguments).await?;
341                Box::pin(super::StreamOnce::new(Ok(ResponseItem::Python(value))))
342            }
343            Request::PythonRequestSchema(req) => {
344                let value = super::python::request_schema::execute(executor, req, agent_arguments).await?;
345                Box::pin(super::StreamOnce::new(Ok(ResponseItem::PythonRequestSchema(value))))
346            }
347            Request::PythonResponseSchema(req) => {
348                let value = super::python::response_schema::execute(executor, req, agent_arguments).await?;
349                Box::pin(super::StreamOnce::new(Ok(ResponseItem::PythonResponseSchema(value))))
350            }
351            Request::Swarms(req) => {
352                let inner = super::swarms::execute(executor, req, agent_arguments).await?;
353                Box::pin(inner.map(|r| r.map(ResponseItem::Swarms)))
354            }
355            Request::Tools(req) => {
356                let inner = super::tools::execute(executor, req, agent_arguments).await?;
357                Box::pin(inner.map(|r| r.map(ResponseItem::Tools)))
358            }
359            Request::Update(req) => {
360                let inner = super::update::execute(executor, req, agent_arguments).await?;
361                Box::pin(inner.map(|r| r.map(ResponseItem::Update)))
362            }
363            Request::UpdateRequestSchema(req) => {
364                let value = super::update::request_schema::execute(executor, req, agent_arguments).await?;
365                Box::pin(super::StreamOnce::new(Ok(ResponseItem::UpdateRequestSchema(value))))
366            }
367            Request::UpdateResponseSchema(req) => {
368                let value = super::update::response_schema::execute(executor, req, agent_arguments).await?;
369                Box::pin(super::StreamOnce::new(Ok(ResponseItem::UpdateResponseSchema(value))))
370            }
371            Request::User(req) => {
372                let inner = super::user::execute(executor, req, agent_arguments).await?;
373                Box::pin(inner.map(|r| r.map(ResponseItem::User)))
374            }
375            Request::Viewer(req) => {
376                let inner = super::viewer::execute(executor, req, agent_arguments).await?;
377                Box::pin(inner.map(|r| r.map(ResponseItem::Viewer)))
378            }
379        };
380    Ok(stream)
381}
382
383#[cfg(feature = "cli-executor")]
384pub async fn execute_transform<E: super::CommandExecutor>(
385    executor: &E,
386    request: Request,
387    transform: crate::cli::command::Transform,
388
389        agent_arguments: Option<&crate::cli::command::AgentArguments>,
390    ) -> Result<
391    std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>>,
392    E::Error,
393> {
394    let stream: std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>> =
395        match request {
396            Request::Agents(req) => {
397                let inner = super::agents::execute_transform(executor, req, transform, agent_arguments).await?;
398                Box::pin(inner)
399            }
400            Request::Api(req) => {
401                let inner = super::api::execute_transform(executor, req, transform, agent_arguments).await?;
402                Box::pin(inner)
403            }
404            Request::Daemon(req) => {
405                let inner = super::daemon::execute_transform(executor, req, transform, agent_arguments).await?;
406                Box::pin(inner)
407            }
408            Request::Db(req) => {
409                let inner = super::db::execute_transform(executor, req, transform, agent_arguments).await?;
410                Box::pin(inner)
411            }
412            Request::Functions(req) => {
413                let inner = super::functions::execute_transform(executor, req, transform, agent_arguments).await?;
414                Box::pin(inner)
415            }
416            Request::Laboratories(req) => {
417                let inner = super::laboratories::execute_transform(executor, req, transform, agent_arguments).await?;
418                Box::pin(inner)
419            }
420            Request::Mcp(req) => {
421                let inner = super::mcp::execute_transform(executor, req, transform, agent_arguments).await?;
422                Box::pin(inner)
423            }
424            Request::Plugins(req) => {
425                let inner = super::plugins::execute_transform(executor, req, transform, agent_arguments).await?;
426                Box::pin(inner)
427            }
428            Request::Python(req) => {
429                let value = super::python::execute_transform(executor, req, transform, agent_arguments).await?;
430                Box::pin(super::StreamOnce::new(Ok(value)))
431            }
432            Request::PythonRequestSchema(req) => {
433                let value = super::python::request_schema::execute_transform(executor, req, transform, agent_arguments).await?;
434                Box::pin(super::StreamOnce::new(Ok(value)))
435            }
436            Request::PythonResponseSchema(req) => {
437                let value = super::python::response_schema::execute_transform(executor, req, transform, agent_arguments).await?;
438                Box::pin(super::StreamOnce::new(Ok(value)))
439            }
440            Request::Swarms(req) => {
441                let inner = super::swarms::execute_transform(executor, req, transform, agent_arguments).await?;
442                Box::pin(inner)
443            }
444            Request::Tools(req) => {
445                let inner = super::tools::execute_transform(executor, req, transform, agent_arguments).await?;
446                Box::pin(inner)
447            }
448            Request::Update(req) => {
449                let inner = super::update::execute_transform(executor, req, transform, agent_arguments).await?;
450                Box::pin(inner)
451            }
452            Request::UpdateRequestSchema(req) => {
453                let value = super::update::request_schema::execute_transform(executor, req, transform, agent_arguments).await?;
454                Box::pin(super::StreamOnce::new(Ok(value)))
455            }
456            Request::UpdateResponseSchema(req) => {
457                let value = super::update::response_schema::execute_transform(executor, req, transform, agent_arguments).await?;
458                Box::pin(super::StreamOnce::new(Ok(value)))
459            }
460            Request::User(req) => {
461                let inner = super::user::execute_transform(executor, req, transform, agent_arguments).await?;
462                Box::pin(inner)
463            }
464            Request::Viewer(req) => {
465                let inner = super::viewer::execute_transform(executor, req, transform, agent_arguments).await?;
466                Box::pin(inner)
467            }
468        };
469    Ok(stream)
470}
471
472/// Parse an argv slice into a typed [`Request`]. Accepts either
473/// shape:
474///
475/// - With a program-name prefix (`["objectiveai", "agents", "list"]`)
476///   — matches `std::env::args()` and binary entry-point usage.
477/// - Without one (`["agents", "list"]`) — matches
478///   [`super::CommandRequest::into_command`]'s output shape and the
479///   "command-only" shape MCP callers send.
480///
481/// If `args[0]` is `"objectiveai"` we pass it straight through;
482/// otherwise we prepend so clap (which always treats argv[0] as the
483/// program name) sees a well-formed argv. Hides clap behind the SDK
484/// boundary so downstream crates can dispatch arbitrary argv without
485/// taking a clap dep themselves.
486pub fn parse_request(args: &[String]) -> Result<Request, ParseError> {
487    let command = if args.first().map(String::as_str) == Some("objectiveai") {
488        <Command as clap::Parser>::try_parse_from(args)?
489    } else {
490        let argv = std::iter::once("objectiveai".to_string())
491            .chain(args.iter().cloned());
492        <Command as clap::Parser>::try_parse_from(argv)?
493    };
494    Ok(Request::try_from(command)?)
495}
496
497/// Top-level CLI parser: a command path, OR `--request <json>` to execute a
498/// JSON `CliCommandRequest` directly. The two are mutually exclusive
499/// (`args_conflicts_with_subcommands`, enforced natively by clap); a bare
500/// invocation prints help (`arg_required_else_help`). `--request` is a
501/// legitimate but unadvertised programmatic entry point.
502#[derive(clap::Parser)]
503#[command(
504    name = "objectiveai",
505    version,
506    args_conflicts_with_subcommands = true,
507    arg_required_else_help = true
508)]
509pub struct Command {
510    /// Execute this JSON `CliCommandRequest` instead of a command path.
511    /// Mutually exclusive with any command.
512    #[arg(long, value_name = "JSON")]
513    pub request: Option<String>,
514    #[command(subcommand)]
515    pub command: Option<Subcommand>,
516}
517
518/// Error from [`parse_request`]. Either clap rejected the argv
519/// ([`ParseError::Clap`] — `--help`, unknown subcommand, missing
520/// required arg, etc.) or the typed `Command` couldn't be lowered
521/// into a `Request` ([`ParseError::FromArgs`] — inline body JSON
522/// failed to parse, etc.).
523#[derive(Debug)]
524pub enum ParseError {
525    Clap(clap::Error),
526    FromArgs(super::FromArgsError),
527}
528
529impl std::fmt::Display for ParseError {
530    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
531        match self {
532            ParseError::Clap(e) => write!(f, "{e}"),
533            ParseError::FromArgs(e) => write!(f, "{e}"),
534        }
535    }
536}
537
538impl std::error::Error for ParseError {}
539
540impl From<clap::Error> for ParseError {
541    fn from(e: clap::Error) -> Self {
542        ParseError::Clap(e)
543    }
544}
545
546impl From<super::FromArgsError> for ParseError {
547    fn from(e: super::FromArgsError) -> Self {
548        ParseError::FromArgs(e)
549    }
550}
551
552/// `/listen` mirror of [`Request`] — the root of the distributed
553/// `ListenerExecution` tree ([`crate::cli::broadcast_listener`]'s
554/// stream item): one variant per child wrapping its
555/// `ListenerExecution`. The broadcast always carries the typed
556/// PRE-transform items (the producer tee sits below the CLI's
557/// jq/python transform), so every execution lands on its typed
558/// variant. Executions whose `path_type` this build's types predate
559/// are skipped by the listener, so there is no unknown fallback.
560#[cfg(feature = "cli-listener")]
561pub enum ListenerExecution {
562    Agents(super::agents::ListenerExecution),
563    Api(super::api::ListenerExecution),
564    Daemon(super::daemon::ListenerExecution),
565    Db(super::db::ListenerExecution),
566    Functions(super::functions::ListenerExecution),
567    Laboratories(super::laboratories::ListenerExecution),
568    Mcp(super::mcp::ListenerExecution),
569    Plugins(super::plugins::ListenerExecution),
570    Python(super::python::ListenerExecution),
571    PythonRequestSchema(super::python::request_schema::ListenerExecution),
572    PythonResponseSchema(super::python::response_schema::ListenerExecution),
573    Swarms(super::swarms::ListenerExecution),
574    Tools(super::tools::ListenerExecution),
575    Update(super::update::ListenerExecution),
576    UpdateRequestSchema(super::update::request_schema::ListenerExecution),
577    UpdateResponseSchema(super::update::response_schema::ListenerExecution),
578    User(super::user::ListenerExecution),
579    Viewer(super::viewer::ListenerExecution),
580}