Skip to main content

objectiveai_sdk/cli/command/laboratories/config/
mod.rs

1pub mod addresses;
2pub mod local;
3
4#[derive(clap::Subcommand)]
5pub enum Command {
6    /// The daemon addresses the laboratory host connects to, each with
7    /// an optional signature.
8    Addresses {
9        #[command(subcommand)]
10        command: addresses::Command,
11    },
12    /// Whether the host connects to the LOCAL daemon on spawn
13    /// (default true).
14    Local {
15        #[command(subcommand)]
16        command: local::Command,
17    },
18}
19
20#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
21#[serde(untagged)]
22#[schemars(rename = "cli.command.laboratories.config.Request")]
23pub enum Request {
24    #[schemars(title = "Addresses")]
25    Addresses(addresses::Request),
26    #[schemars(title = "Local")]
27    Local(local::Request),
28}
29
30// Exempt from json-schema coverage: tier aggregate (see the root
31// `ResponseItem` in command.rs - TS7056).
32#[objectiveai_sdk_macros::json_schema_ignore]
33#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
34#[schemars(rename = "cli.command.laboratories.config.Response")]
35#[serde(untagged)]
36pub enum Response {
37    #[schemars(title = "Addresses")]
38    Addresses(addresses::Response),
39    #[schemars(title = "Local")]
40    Local(local::Response),
41}
42
43#[cfg(feature = "mcp")]
44impl crate::cli::command::CommandResponse for Response {
45    fn into_mcp(self) -> crate::cli::command::McpResponseItem {
46        match self {
47            Response::Addresses(v) => v.into_mcp(),
48            Response::Local(v) => v.into_mcp(),
49        }
50    }
51}
52
53impl TryFrom<Command> for Request {
54    type Error = crate::cli::command::FromArgsError;
55    fn try_from(command: Command) -> Result<Self, Self::Error> {
56        match command {
57            Command::Addresses { command } => {
58                Ok(Request::Addresses(addresses::Request::try_from(command)?))
59            }
60            Command::Local { command } => {
61                Ok(Request::Local(local::Request::try_from(command)?))
62            }
63        }
64    }
65}
66
67impl crate::cli::command::CommandRequest for Request {
68    fn request_base(&self) -> &crate::cli::command::RequestBase {
69        match self {
70            Request::Addresses(inner) => inner.request_base(),
71            Request::Local(inner) => inner.request_base(),
72        }
73    }
74
75    fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
76        match self {
77            Request::Addresses(inner) => inner.request_base_mut(),
78            Request::Local(inner) => inner.request_base_mut(),
79        }
80    }
81}
82
83#[cfg(feature = "cli-executor")]
84pub async fn execute<E: crate::cli::command::CommandExecutor>(
85    executor: &E,
86    request: Request,
87
88        agent_arguments: Option<&crate::cli::command::AgentArguments>,
89    ) -> Result<
90    std::pin::Pin<Box<dyn futures::Stream<Item = Result<Response, E::Error>> + Send>>,
91    E::Error,
92> {
93    use futures::StreamExt;
94    let stream: std::pin::Pin<Box<dyn futures::Stream<Item = Result<Response, E::Error>> + Send>> =
95        match request {
96            Request::Addresses(req) => {
97                let inner = addresses::execute(executor, req, agent_arguments).await?;
98                Box::pin(inner.map(|r| r.map(Response::Addresses)))
99            }
100            Request::Local(req) => {
101                let inner = local::execute(executor, req, agent_arguments).await?;
102                Box::pin(inner.map(|r| r.map(Response::Local)))
103            }
104        };
105    Ok(stream)
106}
107
108#[cfg(feature = "cli-executor")]
109pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
110    executor: &E,
111    request: Request,
112    transform: crate::cli::command::Transform,
113
114        agent_arguments: Option<&crate::cli::command::AgentArguments>,
115    ) -> Result<
116    std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>>,
117    E::Error,
118> {
119    let stream: std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>> =
120        match request {
121            Request::Addresses(req) => {
122                let inner = addresses::execute_transform(executor, req, transform, agent_arguments).await?;
123                Box::pin(inner)
124            }
125            Request::Local(req) => {
126                let inner = local::execute_transform(executor, req, transform, agent_arguments).await?;
127                Box::pin(inner)
128            }
129        };
130    Ok(stream)
131}
132
133/// `/listen` mirror of [`Request`]: one variant per child, wrapping
134/// its `ListenerExecution`. See [`crate::cli::broadcast_listener`].
135#[cfg(feature = "cli-listener")]
136pub enum ListenerExecution {
137    Addresses(addresses::ListenerExecution),
138    Local(local::ListenerExecution),
139}