Skip to main content

objectiveai_sdk/cli/command/api/
mod.rs

1pub mod config;
2
3#[derive(clap::Subcommand)]
4pub enum Command {
5    Config {
6        #[command(subcommand)]
7        command: config::Command,
8    },
9}
10
11#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
12#[serde(untagged)]
13#[schemars(rename = "cli.command.api.Request")]
14pub enum Request {
15    // No variant-level #[schemars(title)]: on a SINGLE-variant enum
16    // schemars hoists it over the enum's own title, tripping the
17    // json-schema builder's normalization assertion (the
18    // ClientLaboratoryType rule). Single-variant since the api
19    // spawn/kill retirement left only `config`.
20    Config(config::Request),
21}
22
23// Exempt from json-schema coverage: tier aggregate (see the root
24// `ResponseItem` in command.rs - TS7056).
25#[objectiveai_sdk_macros::json_schema_ignore]
26#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
27#[schemars(rename = "cli.command.api.Response")]
28#[serde(untagged)]
29pub enum Response {
30    #[schemars(title = "Config")]
31    Config(config::Response),
32}
33
34#[cfg(feature = "mcp")]
35impl crate::cli::command::CommandResponse for Response {
36    fn into_mcp(self) -> crate::cli::command::McpResponseItem {
37        match self {
38            Response::Config(v) => v.into_mcp(),
39        }
40    }
41}
42
43impl TryFrom<Command> for Request {
44    type Error = crate::cli::command::FromArgsError;
45    fn try_from(command: Command) -> Result<Self, Self::Error> {
46        match command {
47            Command::Config { command } =>
48                Ok(Request::Config(config::Request::try_from(command)?)),
49        }
50    }
51}
52
53impl crate::cli::command::CommandRequest for Request {
54    fn request_base(&self) -> &crate::cli::command::RequestBase {
55        match self {
56            Request::Config(inner) => inner.request_base(),
57        }
58    }
59
60    fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
61        match self {
62            Request::Config(inner) => inner.request_base_mut(),
63        }
64    }
65}
66
67#[cfg(feature = "cli-executor")]
68pub async fn execute<E: crate::cli::command::CommandExecutor>(
69    executor: &E,
70    request: Request,
71
72        agent_arguments: Option<&crate::cli::command::AgentArguments>,
73    ) -> Result<
74    std::pin::Pin<Box<dyn futures::Stream<Item = Result<Response, E::Error>> + Send>>,
75    E::Error,
76> {
77    use futures::StreamExt;
78    let stream: std::pin::Pin<Box<dyn futures::Stream<Item = Result<Response, E::Error>> + Send>> =
79        match request {
80            Request::Config(req) => {
81                let inner = config::execute(executor, req, agent_arguments).await?;
82                Box::pin(inner.map(|r| r.map(Response::Config)))
83            }
84        };
85    Ok(stream)
86}
87
88#[cfg(feature = "cli-executor")]
89pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
90    executor: &E,
91    request: Request,
92    transform: crate::cli::command::Transform,
93
94        agent_arguments: Option<&crate::cli::command::AgentArguments>,
95    ) -> Result<
96    std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>>,
97    E::Error,
98> {
99    let stream: std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>> =
100        match request {
101            Request::Config(req) => {
102                let inner = config::execute_transform(executor, req, transform, agent_arguments).await?;
103                Box::pin(inner)
104            }
105        };
106    Ok(stream)
107}
108
109/// `/listen` mirror of [`Request`]: one variant per child, wrapping
110/// its `ListenerExecution`. See [`crate::cli::broadcast_listener`].
111#[cfg(feature = "cli-listener")]
112pub enum ListenerExecution {
113    Config(config::ListenerExecution),
114}