Skip to main content

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

1//! `agents laboratories` — attach/detach/list laboratory ids on an
2//! agent target (a tag, or an instance hierarchy). Each laboratory id
3//! is recorded against the target in the CLI's database.
4
5use crate::cli::command::CommandRequest;
6
7pub mod attach;
8pub mod detach;
9pub mod list;
10
11#[derive(clap::Subcommand)]
12pub enum Command {
13    /// Attach a laboratory id to an agent target.
14    Attach(attach::Command),
15    /// Detach a laboratory id from an agent target.
16    Detach(detach::Command),
17    /// List the laboratory ids attached to an agent target.
18    List(list::Command),
19}
20
21#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
22#[serde(untagged)]
23#[schemars(rename = "cli.command.agents.laboratories.Request")]
24pub enum Request {
25    #[schemars(title = "Attach")]
26    Attach(attach::Request),
27    #[schemars(title = "AttachRequestSchema")]
28    AttachRequestSchema(attach::request_schema::Request),
29    #[schemars(title = "AttachResponseSchema")]
30    AttachResponseSchema(attach::response_schema::Request),
31    #[schemars(title = "Detach")]
32    Detach(detach::Request),
33    #[schemars(title = "DetachRequestSchema")]
34    DetachRequestSchema(detach::request_schema::Request),
35    #[schemars(title = "DetachResponseSchema")]
36    DetachResponseSchema(detach::response_schema::Request),
37    #[schemars(title = "List")]
38    List(list::Request),
39    #[schemars(title = "ListRequestSchema")]
40    ListRequestSchema(list::request_schema::Request),
41    #[schemars(title = "ListResponseSchema")]
42    ListResponseSchema(list::response_schema::Request),
43}
44
45// Exempt from json-schema coverage: tier aggregate (see the root
46// `ResponseItem` in command.rs - TS7056).
47#[objectiveai_sdk_macros::json_schema_ignore]
48#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
49#[schemars(rename = "cli.command.agents.laboratories.ResponseItem")]
50#[serde(untagged)]
51pub enum ResponseItem {
52    #[schemars(title = "Attach")]
53    Attach(attach::Response),
54    #[schemars(title = "AttachRequestSchema")]
55    AttachRequestSchema(attach::request_schema::Response),
56    #[schemars(title = "AttachResponseSchema")]
57    AttachResponseSchema(attach::response_schema::Response),
58    #[schemars(title = "Detach")]
59    Detach(detach::Response),
60    #[schemars(title = "DetachRequestSchema")]
61    DetachRequestSchema(detach::request_schema::Response),
62    #[schemars(title = "DetachResponseSchema")]
63    DetachResponseSchema(detach::response_schema::Response),
64    #[schemars(title = "List")]
65    List(list::ResponseItem),
66    #[schemars(title = "ListRequestSchema")]
67    ListRequestSchema(list::request_schema::Response),
68    #[schemars(title = "ListResponseSchema")]
69    ListResponseSchema(list::response_schema::Response),
70}
71
72#[cfg(feature = "mcp")]
73impl crate::cli::command::CommandResponse for ResponseItem {
74    fn into_mcp(self) -> crate::cli::command::McpResponseItem {
75        match self {
76            ResponseItem::Attach(v) => v.into_mcp(),
77            ResponseItem::AttachRequestSchema(v) => v.into_mcp(),
78            ResponseItem::AttachResponseSchema(v) => v.into_mcp(),
79            ResponseItem::Detach(v) => v.into_mcp(),
80            ResponseItem::DetachRequestSchema(v) => v.into_mcp(),
81            ResponseItem::DetachResponseSchema(v) => v.into_mcp(),
82            ResponseItem::List(v) => v.into_mcp(),
83            ResponseItem::ListRequestSchema(v) => v.into_mcp(),
84            ResponseItem::ListResponseSchema(v) => v.into_mcp(),
85        }
86    }
87}
88
89impl TryFrom<Command> for Request {
90    type Error = crate::cli::command::FromArgsError;
91    fn try_from(command: Command) -> Result<Self, Self::Error> {
92        match command {
93            Command::Attach(cmd) => match cmd.schema {
94                None => Ok(Request::Attach(attach::Request::try_from(cmd.args)?)),
95                Some(attach::Schema::RequestSchema(args)) => Ok(Request::AttachRequestSchema(
96                    attach::request_schema::Request::try_from(args)?,
97                )),
98                Some(attach::Schema::ResponseSchema(args)) => Ok(Request::AttachResponseSchema(
99                    attach::response_schema::Request::try_from(args)?,
100                )),
101            },
102            Command::Detach(cmd) => match cmd.schema {
103                None => Ok(Request::Detach(detach::Request::try_from(cmd.args)?)),
104                Some(detach::Schema::RequestSchema(args)) => Ok(Request::DetachRequestSchema(
105                    detach::request_schema::Request::try_from(args)?,
106                )),
107                Some(detach::Schema::ResponseSchema(args)) => Ok(Request::DetachResponseSchema(
108                    detach::response_schema::Request::try_from(args)?,
109                )),
110            },
111            Command::List(cmd) => match cmd.schema {
112                None => Ok(Request::List(list::Request::try_from(cmd.args)?)),
113                Some(list::Schema::RequestSchema(args)) => Ok(Request::ListRequestSchema(
114                    list::request_schema::Request::try_from(args)?,
115                )),
116                Some(list::Schema::ResponseSchema(args)) => Ok(Request::ListResponseSchema(
117                    list::response_schema::Request::try_from(args)?,
118                )),
119            },
120        }
121    }
122}
123
124impl CommandRequest for Request {
125    fn request_base(&self) -> &crate::cli::command::RequestBase {
126        match self {
127            Request::Attach(inner) => inner.request_base(),
128            Request::AttachRequestSchema(inner) => inner.request_base(),
129            Request::AttachResponseSchema(inner) => inner.request_base(),
130            Request::Detach(inner) => inner.request_base(),
131            Request::DetachRequestSchema(inner) => inner.request_base(),
132            Request::DetachResponseSchema(inner) => inner.request_base(),
133            Request::List(inner) => inner.request_base(),
134            Request::ListRequestSchema(inner) => inner.request_base(),
135            Request::ListResponseSchema(inner) => inner.request_base(),
136        }
137    }
138
139    fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
140        match self {
141            Request::Attach(inner) => inner.request_base_mut(),
142            Request::AttachRequestSchema(inner) => inner.request_base_mut(),
143            Request::AttachResponseSchema(inner) => inner.request_base_mut(),
144            Request::Detach(inner) => inner.request_base_mut(),
145            Request::DetachRequestSchema(inner) => inner.request_base_mut(),
146            Request::DetachResponseSchema(inner) => inner.request_base_mut(),
147            Request::List(inner) => inner.request_base_mut(),
148            Request::ListRequestSchema(inner) => inner.request_base_mut(),
149            Request::ListResponseSchema(inner) => inner.request_base_mut(),
150        }
151    }
152}
153
154#[cfg(feature = "cli-executor")]
155pub async fn execute<E: crate::cli::command::CommandExecutor>(
156    executor: &E,
157    request: Request,
158    agent_arguments: Option<&crate::cli::command::AgentArguments>,
159) -> Result<
160    std::pin::Pin<Box<dyn futures::Stream<Item = Result<ResponseItem, E::Error>> + Send>>,
161    E::Error,
162> {
163    use futures::StreamExt as _;
164    let stream: std::pin::Pin<
165        Box<dyn futures::Stream<Item = Result<ResponseItem, E::Error>> + Send>,
166    > = match request {
167        Request::Attach(req) => {
168            let value = attach::execute(executor, req, agent_arguments).await?;
169            Box::pin(crate::cli::command::StreamOnce::new(Ok(
170                ResponseItem::Attach(value),
171            )))
172        }
173        Request::AttachRequestSchema(req) => {
174            let value = attach::request_schema::execute(executor, req, agent_arguments).await?;
175            Box::pin(crate::cli::command::StreamOnce::new(Ok(
176                ResponseItem::AttachRequestSchema(value),
177            )))
178        }
179        Request::AttachResponseSchema(req) => {
180            let value = attach::response_schema::execute(executor, req, agent_arguments).await?;
181            Box::pin(crate::cli::command::StreamOnce::new(Ok(
182                ResponseItem::AttachResponseSchema(value),
183            )))
184        }
185        Request::Detach(req) => {
186            let value = detach::execute(executor, req, agent_arguments).await?;
187            Box::pin(crate::cli::command::StreamOnce::new(Ok(
188                ResponseItem::Detach(value),
189            )))
190        }
191        Request::DetachRequestSchema(req) => {
192            let value = detach::request_schema::execute(executor, req, agent_arguments).await?;
193            Box::pin(crate::cli::command::StreamOnce::new(Ok(
194                ResponseItem::DetachRequestSchema(value),
195            )))
196        }
197        Request::DetachResponseSchema(req) => {
198            let value = detach::response_schema::execute(executor, req, agent_arguments).await?;
199            Box::pin(crate::cli::command::StreamOnce::new(Ok(
200                ResponseItem::DetachResponseSchema(value),
201            )))
202        }
203        Request::List(req) => {
204            let inner = list::execute(executor, req, agent_arguments).await?;
205            Box::pin(inner.map(|r| r.map(ResponseItem::List)))
206        }
207        Request::ListRequestSchema(req) => {
208            let value = list::request_schema::execute(executor, req, agent_arguments).await?;
209            Box::pin(crate::cli::command::StreamOnce::new(Ok(
210                ResponseItem::ListRequestSchema(value),
211            )))
212        }
213        Request::ListResponseSchema(req) => {
214            let value = list::response_schema::execute(executor, req, agent_arguments).await?;
215            Box::pin(crate::cli::command::StreamOnce::new(Ok(
216                ResponseItem::ListResponseSchema(value),
217            )))
218        }
219    };
220    Ok(stream)
221}
222
223#[cfg(feature = "cli-executor")]
224pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
225    executor: &E,
226    request: Request,
227    transform: crate::cli::command::Transform,
228    agent_arguments: Option<&crate::cli::command::AgentArguments>,
229) -> Result<
230    std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>>,
231    E::Error,
232> {
233    let stream: std::pin::Pin<
234        Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>,
235    > = match request {
236        Request::Attach(req) => {
237            let value = attach::execute_transform(executor, req, transform, agent_arguments).await?;
238            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
239        }
240        Request::AttachRequestSchema(req) => {
241            let value = attach::request_schema::execute_transform(
242                executor,
243                req,
244                transform,
245                agent_arguments,
246            )
247            .await?;
248            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
249        }
250        Request::AttachResponseSchema(req) => {
251            let value = attach::response_schema::execute_transform(
252                executor,
253                req,
254                transform,
255                agent_arguments,
256            )
257            .await?;
258            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
259        }
260        Request::Detach(req) => {
261            let value = detach::execute_transform(executor, req, transform, agent_arguments).await?;
262            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
263        }
264        Request::DetachRequestSchema(req) => {
265            let value = detach::request_schema::execute_transform(
266                executor,
267                req,
268                transform,
269                agent_arguments,
270            )
271            .await?;
272            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
273        }
274        Request::DetachResponseSchema(req) => {
275            let value = detach::response_schema::execute_transform(
276                executor,
277                req,
278                transform,
279                agent_arguments,
280            )
281            .await?;
282            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
283        }
284        Request::List(req) => {
285            let inner = list::execute_transform(executor, req, transform, agent_arguments).await?;
286            Box::pin(inner)
287        }
288        Request::ListRequestSchema(req) => {
289            let value = list::request_schema::execute_transform(
290                executor,
291                req,
292                transform,
293                agent_arguments,
294            )
295            .await?;
296            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
297        }
298        Request::ListResponseSchema(req) => {
299            let value = list::response_schema::execute_transform(
300                executor,
301                req,
302                transform,
303                agent_arguments,
304            )
305            .await?;
306            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
307        }
308    };
309    Ok(stream)
310}