1use crate::cli::command::CommandRequest;
6
7pub mod attach;
8pub mod detach;
9pub mod list;
10
11#[derive(clap::Subcommand)]
12pub enum Command {
13 Attach(attach::Command),
15 Detach(detach::Command),
17 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#[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}
311
312#[cfg(feature = "cli-listener")]
315pub enum ListenerExecution {
316 Attach(attach::ListenerExecution),
317 AttachRequestSchema(attach::request_schema::ListenerExecution),
318 AttachResponseSchema(attach::response_schema::ListenerExecution),
319 Detach(detach::ListenerExecution),
320 DetachRequestSchema(detach::request_schema::ListenerExecution),
321 DetachResponseSchema(detach::response_schema::ListenerExecution),
322 List(list::ListenerExecution),
323 ListRequestSchema(list::request_schema::ListenerExecution),
324 ListResponseSchema(list::response_schema::ListenerExecution),
325}