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 request_base(&self) -> &crate::cli::command::RequestBase {
295 match self {
296 Request::Standard(inner) => inner.request_base(),
297 Request::StandardRequestSchema(inner) => inner.request_base(),
298 Request::StandardResponseSchema(inner) => inner.request_base(),
299 Request::SwissSystem(inner) => inner.request_base(),
300 Request::SwissSystemRequestSchema(inner) => inner.request_base(),
301 Request::SwissSystemResponseSchema(inner) => inner.request_base(),
302 }
303 }
304
305 fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
306 match self {
307 Request::Standard(inner) => inner.request_base_mut(),
308 Request::StandardRequestSchema(inner) => inner.request_base_mut(),
309 Request::StandardResponseSchema(inner) => inner.request_base_mut(),
310 Request::SwissSystem(inner) => inner.request_base_mut(),
311 Request::SwissSystemRequestSchema(inner) => inner.request_base_mut(),
312 Request::SwissSystemResponseSchema(inner) => inner.request_base_mut(),
313 }
314 }
315}
316
317#[cfg(feature = "cli-executor")]
318pub async fn execute<E: crate::cli::command::CommandExecutor>(
319 executor: &E,
320 request: Request,
321
322 agent_arguments: Option<&crate::cli::command::AgentArguments>,
323 ) -> Result<
324 std::pin::Pin<Box<dyn futures::Stream<Item = Result<ResponseItem, E::Error>> + Send>>,
325 E::Error,
326> {
327 use futures::StreamExt;
328 let stream: std::pin::Pin<Box<dyn futures::Stream<Item = Result<ResponseItem, E::Error>> + Send>> =
329 match request {
330 Request::Standard(req) => {
331 let want_streaming = req
332 .dangerous_advanced
333 .as_ref()
334 .and_then(|a| a.stream)
335 .unwrap_or(false);
336 if want_streaming {
337 let inner = standard::execute_streaming(executor, req, agent_arguments).await?;
338 Box::pin(inner.map(|r| r.map(ResponseItem::Standard)))
339 } else {
340 let value = standard::execute(executor, req, agent_arguments).await?;
341 Box::pin(crate::cli::command::StreamOnce::new(Ok(
342 ResponseItem::Standard(standard::ResponseItem::Id(value)),
343 )))
344 }
345 }
346 Request::StandardRequestSchema(req) => {
347 let value = standard::request_schema::execute(executor, req, agent_arguments).await?;
348 Box::pin(crate::cli::command::StreamOnce::new(Ok(
349 ResponseItem::StandardRequestSchema(value),
350 )))
351 }
352 Request::StandardResponseSchema(req) => {
353 let value = standard::response_schema::execute(executor, req, agent_arguments).await?;
354 Box::pin(crate::cli::command::StreamOnce::new(Ok(
355 ResponseItem::StandardResponseSchema(value),
356 )))
357 }
358 Request::SwissSystem(req) => {
359 let want_streaming = req
360 .dangerous_advanced
361 .as_ref()
362 .and_then(|a| a.stream)
363 .unwrap_or(false);
364 if want_streaming {
365 let inner = swiss_system::execute_streaming(executor, req, agent_arguments).await?;
366 Box::pin(inner.map(|r| r.map(ResponseItem::SwissSystem)))
367 } else {
368 let value = swiss_system::execute(executor, req, agent_arguments).await?;
369 Box::pin(crate::cli::command::StreamOnce::new(Ok(
370 ResponseItem::SwissSystem(swiss_system::ResponseItem::Id(value)),
371 )))
372 }
373 }
374 Request::SwissSystemRequestSchema(req) => {
375 let value = swiss_system::request_schema::execute(executor, req, agent_arguments).await?;
376 Box::pin(crate::cli::command::StreamOnce::new(Ok(
377 ResponseItem::SwissSystemRequestSchema(value),
378 )))
379 }
380 Request::SwissSystemResponseSchema(req) => {
381 let value = swiss_system::response_schema::execute(executor, req, agent_arguments).await?;
382 Box::pin(crate::cli::command::StreamOnce::new(Ok(
383 ResponseItem::SwissSystemResponseSchema(value),
384 )))
385 }
386 };
387 Ok(stream)
388}
389
390#[cfg(feature = "cli-executor")]
391pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
392 executor: &E,
393 request: Request,
394 transform: crate::cli::command::Transform,
395
396 agent_arguments: Option<&crate::cli::command::AgentArguments>,
397 ) -> Result<
398 std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>>,
399 E::Error,
400> {
401 let stream: std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>> =
402 match request {
403 Request::Standard(req) => {
404 let want_streaming = req
405 .dangerous_advanced
406 .as_ref()
407 .and_then(|a| a.stream)
408 .unwrap_or(false);
409 if want_streaming {
410 let inner = standard::execute_streaming_transform(executor, req, transform, agent_arguments).await?;
411 Box::pin(inner)
412 } else {
413 let value = standard::execute_transform(executor, req, transform, agent_arguments).await?;
414 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
415 }
416 }
417 Request::StandardRequestSchema(req) => {
418 let value = standard::request_schema::execute_transform(executor, req, transform, agent_arguments).await?;
419 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
420 }
421 Request::StandardResponseSchema(req) => {
422 let value = standard::response_schema::execute_transform(executor, req, transform, agent_arguments).await?;
423 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
424 }
425 Request::SwissSystem(req) => {
426 let want_streaming = req
427 .dangerous_advanced
428 .as_ref()
429 .and_then(|a| a.stream)
430 .unwrap_or(false);
431 if want_streaming {
432 let inner = swiss_system::execute_streaming_transform(executor, req, transform, agent_arguments).await?;
433 Box::pin(inner)
434 } else {
435 let value = swiss_system::execute_transform(executor, req, transform, agent_arguments).await?;
436 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
437 }
438 }
439 Request::SwissSystemRequestSchema(req) => {
440 let value = swiss_system::request_schema::execute_transform(executor, req, transform, agent_arguments).await?;
441 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
442 }
443 Request::SwissSystemResponseSchema(req) => {
444 let value = swiss_system::response_schema::execute_transform(executor, req, transform, agent_arguments).await?;
445 Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
446 }
447 };
448 Ok(stream)
449}