1pub mod standard;
2pub mod swiss_system;
3
4#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
16#[serde(untagged)]
17#[schemars(rename = "cli.command.functions.execute.FunctionSpec")]
18pub enum FunctionSpec {
19 #[schemars(title = "Resolved")]
20 Resolved(crate::functions::FullInlineFunctionOrRemoteCommitOptional),
21 #[schemars(title = "File")]
22 File(std::path::PathBuf),
23 #[schemars(title = "PythonInline")]
24 PythonInline(String),
25 #[schemars(title = "PythonFile")]
26 PythonFile(std::path::PathBuf),
27}
28
29#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
33#[serde(untagged)]
34#[schemars(rename = "cli.command.functions.execute.ProfileSpec")]
35pub enum ProfileSpec {
36 #[schemars(title = "Resolved")]
37 Resolved(crate::functions::InlineProfileOrRemoteCommitOptional),
38 #[schemars(title = "File")]
39 File(std::path::PathBuf),
40 #[schemars(title = "PythonInline")]
41 PythonInline(String),
42 #[schemars(title = "PythonFile")]
43 PythonFile(std::path::PathBuf),
44}
45
46impl FunctionSpec {
47 pub fn push_flags(&self, out: &mut Vec<String>) {
50 use crate::cli::command::path_ref::remote_path_to_arg_string;
51 use crate::functions::FullInlineFunctionOrRemoteCommitOptional;
52 match self {
53 FunctionSpec::Resolved(FullInlineFunctionOrRemoteCommitOptional::Remote(p)) => {
54 out.push("--function".to_string());
55 out.push(remote_path_to_arg_string(p));
56 }
57 FunctionSpec::Resolved(inline @ FullInlineFunctionOrRemoteCommitOptional::Inline(_)) => {
58 out.push("--function-inline".to_string());
59 out.push(serde_json::to_string(inline).expect("function serializes"));
60 }
61 FunctionSpec::File(p) => {
62 out.push("--function-file".to_string());
63 out.push(p.to_string_lossy().into_owned());
64 }
65 FunctionSpec::PythonInline(code) => {
66 out.push("--function-python-inline".to_string());
67 out.push(code.clone());
68 }
69 FunctionSpec::PythonFile(p) => {
70 out.push("--function-python-file".to_string());
71 out.push(p.to_string_lossy().into_owned());
72 }
73 }
74 }
75}
76
77impl ProfileSpec {
78 pub fn push_flags(&self, out: &mut Vec<String>) {
81 use crate::cli::command::path_ref::remote_path_to_arg_string;
82 use crate::functions::InlineProfileOrRemoteCommitOptional;
83 match self {
84 ProfileSpec::Resolved(InlineProfileOrRemoteCommitOptional::Remote(p)) => {
85 out.push("--profile".to_string());
86 out.push(remote_path_to_arg_string(p));
87 }
88 ProfileSpec::Resolved(inline @ InlineProfileOrRemoteCommitOptional::Inline(_)) => {
89 out.push("--profile-inline".to_string());
90 out.push(serde_json::to_string(inline).expect("profile serializes"));
91 }
92 ProfileSpec::File(p) => {
93 out.push("--profile-file".to_string());
94 out.push(p.to_string_lossy().into_owned());
95 }
96 ProfileSpec::PythonInline(code) => {
97 out.push("--profile-python-inline".to_string());
98 out.push(code.clone());
99 }
100 ProfileSpec::PythonFile(p) => {
101 out.push("--profile-python-file".to_string());
102 out.push(p.to_string_lossy().into_owned());
103 }
104 }
105 }
106}
107
108#[derive(clap::Args)]
117#[group(id = "function_group", required = true, multiple = false)]
118pub struct FunctionArgs {
119 #[arg(long, group = "function_group")]
122 pub function: Option<String>,
123 #[arg(long, group = "function_group")]
125 pub function_inline: Option<String>,
126 #[arg(long, group = "function_group")]
128 pub function_file: Option<std::path::PathBuf>,
129 #[arg(long, group = "function_group")]
131 pub function_python_inline: Option<String>,
132 #[arg(long, group = "function_group")]
134 pub function_python_file: Option<std::path::PathBuf>,
135}
136
137#[derive(clap::Args)]
140#[group(id = "profile_group", required = true, multiple = false)]
141pub struct ProfileArgs {
142 #[arg(long, group = "profile_group")]
145 pub profile: Option<String>,
146 #[arg(long, group = "profile_group")]
148 pub profile_inline: Option<String>,
149 #[arg(long, group = "profile_group")]
151 pub profile_file: Option<std::path::PathBuf>,
152 #[arg(long, group = "profile_group")]
154 pub profile_python_inline: Option<String>,
155 #[arg(long, group = "profile_group")]
157 pub profile_python_file: Option<std::path::PathBuf>,
158}
159
160impl TryFrom<FunctionArgs> for FunctionSpec {
161 type Error = crate::cli::command::FromArgsError;
162 fn try_from(args: FunctionArgs) -> Result<Self, Self::Error> {
163 use crate::functions::FullInlineFunctionOrRemoteCommitOptional;
164 if let Some(s) = args.function {
165 let path: crate::RemotePathCommitOptional = s
166 .parse()
167 .map_err(|e| crate::cli::command::FromArgsError::path_parse("function", e))?;
168 Ok(FunctionSpec::Resolved(
169 FullInlineFunctionOrRemoteCommitOptional::Remote(path),
170 ))
171 } else if let Some(s) = args.function_inline {
172 let mut de = serde_json::Deserializer::from_str(&s);
173 let v = serde_path_to_error::deserialize(&mut de)
174 .map_err(|e| crate::cli::command::FromArgsError::json("function_inline", e))?;
175 Ok(FunctionSpec::Resolved(v))
176 } else if let Some(p) = args.function_file {
177 Ok(FunctionSpec::File(p))
178 } else if let Some(s) = args.function_python_inline {
179 Ok(FunctionSpec::PythonInline(s))
180 } else {
181 Ok(FunctionSpec::PythonFile(args.function_python_file.unwrap()))
182 }
183 }
184}
185
186impl TryFrom<ProfileArgs> for ProfileSpec {
187 type Error = crate::cli::command::FromArgsError;
188 fn try_from(args: ProfileArgs) -> Result<Self, Self::Error> {
189 use crate::functions::InlineProfileOrRemoteCommitOptional;
190 if let Some(s) = args.profile {
191 let path: crate::RemotePathCommitOptional = s
192 .parse()
193 .map_err(|e| crate::cli::command::FromArgsError::path_parse("profile", e))?;
194 Ok(ProfileSpec::Resolved(
195 InlineProfileOrRemoteCommitOptional::Remote(path),
196 ))
197 } else if let Some(s) = args.profile_inline {
198 let mut de = serde_json::Deserializer::from_str(&s);
199 let v = serde_path_to_error::deserialize(&mut de)
200 .map_err(|e| crate::cli::command::FromArgsError::json("profile_inline", e))?;
201 Ok(ProfileSpec::Resolved(v))
202 } else if let Some(p) = args.profile_file {
203 Ok(ProfileSpec::File(p))
204 } else if let Some(s) = args.profile_python_inline {
205 Ok(ProfileSpec::PythonInline(s))
206 } else {
207 Ok(ProfileSpec::PythonFile(args.profile_python_file.unwrap()))
208 }
209 }
210}
211
212#[derive(clap::Subcommand)]
213pub enum Command {
214 Standard(standard::Command),
215 SwissSystem(swiss_system::Command),
216}
217
218#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
219#[serde(untagged)]
220#[schemars(rename = "cli.command.functions.execute.Request")]
221pub enum Request {
222 #[schemars(title = "Standard")]
223 Standard(standard::Request),
224 #[schemars(title = "StandardRequestSchema")]
225 StandardRequestSchema(standard::request_schema::Request),
226 #[schemars(title = "StandardResponseSchema")]
227 StandardResponseSchema(standard::response_schema::Request),
228 #[schemars(title = "SwissSystem")]
229 SwissSystem(swiss_system::Request),
230 #[schemars(title = "SwissSystemRequestSchema")]
231 SwissSystemRequestSchema(swiss_system::request_schema::Request),
232 #[schemars(title = "SwissSystemResponseSchema")]
233 SwissSystemResponseSchema(swiss_system::response_schema::Request),
234}
235
236#[objectiveai_sdk_macros::json_schema_ignore]
239#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
240#[schemars(rename = "cli.command.functions.execute.ResponseItem")]
241#[serde(untagged)]
242pub enum ResponseItem {
243 #[schemars(title = "Standard")]
244 Standard(standard::ResponseItem),
245 #[schemars(title = "StandardRequestSchema")]
246 StandardRequestSchema(standard::request_schema::Response),
247 #[schemars(title = "StandardResponseSchema")]
248 StandardResponseSchema(standard::response_schema::Response),
249 #[schemars(title = "SwissSystem")]
250 SwissSystem(swiss_system::ResponseItem),
251 #[schemars(title = "SwissSystemRequestSchema")]
252 SwissSystemRequestSchema(swiss_system::request_schema::Response),
253 #[schemars(title = "SwissSystemResponseSchema")]
254 SwissSystemResponseSchema(swiss_system::response_schema::Response),
255}
256
257#[cfg(feature = "mcp")]
258impl crate::cli::command::CommandResponse for ResponseItem {
259 fn into_mcp(self) -> crate::cli::command::McpResponseItem {
260 match self {
261 ResponseItem::Standard(v) => v.into_mcp(),
262 ResponseItem::StandardRequestSchema(v) => v.into_mcp(),
263 ResponseItem::StandardResponseSchema(v) => v.into_mcp(),
264 ResponseItem::SwissSystem(v) => v.into_mcp(),
265 ResponseItem::SwissSystemRequestSchema(v) => v.into_mcp(),
266 ResponseItem::SwissSystemResponseSchema(v) => v.into_mcp(),
267 }
268 }
269}
270
271impl TryFrom<Command> for Request {
272 type Error = crate::cli::command::FromArgsError;
273 fn try_from(command: Command) -> Result<Self, Self::Error> {
274 match command {
275 Command::Standard(cmd) => match cmd.schema {
276 None => Ok(Request::Standard(standard::Request::try_from(cmd.args)?)),
277 Some(standard::Schema::RequestSchema(args)) =>
278 Ok(Request::StandardRequestSchema(standard::request_schema::Request::try_from(args)?)),
279 Some(standard::Schema::ResponseSchema(args)) =>
280 Ok(Request::StandardResponseSchema(standard::response_schema::Request::try_from(args)?)),
281 },
282 Command::SwissSystem(cmd) => match cmd.schema {
283 None => Ok(Request::SwissSystem(swiss_system::Request::try_from(cmd.args)?)),
284 Some(swiss_system::Schema::RequestSchema(args)) =>
285 Ok(Request::SwissSystemRequestSchema(swiss_system::request_schema::Request::try_from(args)?)),
286 Some(swiss_system::Schema::ResponseSchema(args)) =>
287 Ok(Request::SwissSystemResponseSchema(swiss_system::response_schema::Request::try_from(args)?)),
288 },
289 }
290 }
291}
292
293impl crate::cli::command::CommandRequest for Request {
294 fn into_command(&self) -> Vec<String> {
295 match self {
296 Request::Standard(inner) => inner.into_command(),
297 Request::StandardRequestSchema(inner) => inner.into_command(),
298 Request::StandardResponseSchema(inner) => inner.into_command(),
299 Request::SwissSystem(inner) => inner.into_command(),
300 Request::SwissSystemRequestSchema(inner) => inner.into_command(),
301 Request::SwissSystemResponseSchema(inner) => inner.into_command(),
302 }
303 }
304
305 fn request_base(&self) -> &crate::cli::command::RequestBase {
306 match self {
307 Request::Standard(inner) => inner.request_base(),
308 Request::StandardRequestSchema(inner) => inner.request_base(),
309 Request::StandardResponseSchema(inner) => inner.request_base(),
310 Request::SwissSystem(inner) => inner.request_base(),
311 Request::SwissSystemRequestSchema(inner) => inner.request_base(),
312 Request::SwissSystemResponseSchema(inner) => inner.request_base(),
313 }
314 }
315
316 fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
317 match self {
318 Request::Standard(inner) => inner.request_base_mut(),
319 Request::StandardRequestSchema(inner) => inner.request_base_mut(),
320 Request::StandardResponseSchema(inner) => inner.request_base_mut(),
321 Request::SwissSystem(inner) => inner.request_base_mut(),
322 Request::SwissSystemRequestSchema(inner) => inner.request_base_mut(),
323 Request::SwissSystemResponseSchema(inner) => inner.request_base_mut(),
324 }
325 }
326}
327
328#[cfg(feature = "cli-executor")]
329pub async fn execute<E: crate::cli::command::CommandExecutor>(
330 executor: &E,
331 request: Request,
332
333 agent_arguments: Option<&crate::cli::command::AgentArguments>,
334 ) -> Result<
335 std::pin::Pin<Box<dyn futures::Stream<Item = Result<ResponseItem, E::Error>> + Send>>,
336 E::Error,
337> {
338 use futures::StreamExt;
339 let stream: std::pin::Pin<Box<dyn futures::Stream<Item = Result<ResponseItem, E::Error>> + Send>> =
340 match request {
341 Request::Standard(req) => {
342 let want_streaming = req
343 .dangerous_advanced
344 .as_ref()
345 .and_then(|a| a.stream)
346 .unwrap_or(false);
347 if want_streaming {
348 let inner = standard::execute_streaming(executor, req, agent_arguments).await?;
349 Box::pin(inner.map(|r| r.map(ResponseItem::Standard)))
350 } else {
351 let value = standard::execute(executor, req, agent_arguments).await?;
352 Box::pin(crate::cli::command::StreamOnce::new(Ok(
353 ResponseItem::Standard(standard::ResponseItem::Id(value)),
354 )))
355 }
356 }
357 Request::StandardRequestSchema(req) => {
358 let value = standard::request_schema::execute(executor, req, agent_arguments).await?;
359 Box::pin(crate::cli::command::StreamOnce::new(Ok(
360 ResponseItem::StandardRequestSchema(value),
361 )))
362 }
363 Request::StandardResponseSchema(req) => {
364 let value = standard::response_schema::execute(executor, req, agent_arguments).await?;
365 Box::pin(crate::cli::command::StreamOnce::new(Ok(
366 ResponseItem::StandardResponseSchema(value),
367 )))
368 }
369 Request::SwissSystem(req) => {
370 let want_streaming = req
371 .dangerous_advanced
372 .as_ref()
373 .and_then(|a| a.stream)
374 .unwrap_or(false);
375 if want_streaming {
376 let inner = swiss_system::execute_streaming(executor, req, agent_arguments).await?;
377 Box::pin(inner.map(|r| r.map(ResponseItem::SwissSystem)))
378 } else {
379 let value = swiss_system::execute(executor, req, agent_arguments).await?;
380 Box::pin(crate::cli::command::StreamOnce::new(Ok(
381 ResponseItem::SwissSystem(swiss_system::ResponseItem::Id(value)),
382 )))
383 }
384 }
385 Request::SwissSystemRequestSchema(req) => {
386 let value = swiss_system::request_schema::execute(executor, req, agent_arguments).await?;
387 Box::pin(crate::cli::command::StreamOnce::new(Ok(
388 ResponseItem::SwissSystemRequestSchema(value),
389 )))
390 }
391 Request::SwissSystemResponseSchema(req) => {
392 let value = swiss_system::response_schema::execute(executor, req, agent_arguments).await?;
393 Box::pin(crate::cli::command::StreamOnce::new(Ok(
394 ResponseItem::SwissSystemResponseSchema(value),
395 )))
396 }
397 };
398 Ok(stream)
399}
400
401#[cfg(feature = "cli-executor")]
402pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
403 executor: &E,
404 request: Request,
405 transform: crate::cli::command::Transform,
406
407 agent_arguments: Option<&crate::cli::command::AgentArguments>,
408 ) -> Result<
409 std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>>,
410 E::Error,
411> {
412 let stream: std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>> =
413 match request {
414 Request::Standard(req) => {
415 let want_streaming = req
416 .dangerous_advanced
417 .as_ref()
418 .and_then(|a| a.stream)
419 .unwrap_or(false);
420 if want_streaming {
421 let inner = standard::execute_streaming_transform(executor, req, transform, agent_arguments).await?;
422 Box::pin(inner)
423 } else {
424 let value = standard::execute_transform(executor, req, transform, agent_arguments).await?;
425 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
426 }
427 }
428 Request::StandardRequestSchema(req) => {
429 let value = standard::request_schema::execute_transform(executor, req, transform, agent_arguments).await?;
430 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
431 }
432 Request::StandardResponseSchema(req) => {
433 let value = standard::response_schema::execute_transform(executor, req, transform, agent_arguments).await?;
434 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
435 }
436 Request::SwissSystem(req) => {
437 let want_streaming = req
438 .dangerous_advanced
439 .as_ref()
440 .and_then(|a| a.stream)
441 .unwrap_or(false);
442 if want_streaming {
443 let inner = swiss_system::execute_streaming_transform(executor, req, transform, agent_arguments).await?;
444 Box::pin(inner)
445 } else {
446 let value = swiss_system::execute_transform(executor, req, transform, agent_arguments).await?;
447 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
448 }
449 }
450 Request::SwissSystemRequestSchema(req) => {
451 let value = swiss_system::request_schema::execute_transform(executor, req, transform, agent_arguments).await?;
452 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
453 }
454 Request::SwissSystemResponseSchema(req) => {
455 let value = swiss_system::response_schema::execute_transform(executor, req, transform, agent_arguments).await?;
456 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
457 }
458 };
459 Ok(stream)
460}