objectiveai_cli/command/functions/execute/
standard.rs1use std::pin::Pin;
14
15use futures::Stream;
16use futures::StreamExt;
17use objectiveai_sdk::cli::command::functions::execute::standard::{
18 Request, RequestDangerousAdvanced, RequestInput, ResponseItem,
19};
20use objectiveai_sdk::cli::command::{BinaryExecutor, CommandExecutor};
21use objectiveai_sdk::functions::executions::request::{
22 FunctionExecutionCreateParams, Strategy,
23};
24
25use crate::context::Context;
26use crate::error::Error;
27
28type ItemStream = Pin<Box<dyn Stream<Item = Result<ResponseItem, Error>> + Send>>;
29
30pub async fn execute(ctx: &Context, request: Request) -> Result<ItemStream, Error> {
31 let want_stream = request
32 .dangerous_advanced
33 .as_ref()
34 .and_then(|a| a.stream)
35 .unwrap_or(false);
36 if want_stream {
37 execute_streaming(ctx, request).await
38 } else {
39 execute_detached(request).await
40 }
41}
42
43async fn execute_streaming(
44 ctx: &Context,
45 request: Request,
46) -> Result<ItemStream, Error> {
47 let (function, profile) = tokio::try_join!(
48 super::resolve_function(ctx, request.function),
49 super::resolve_profile(ctx, request.profile),
50 )?;
51 let input = match request.input {
52 RequestInput::Inline(v) => v,
53 RequestInput::File(path) => super::resolve_input_file(path)?,
54 RequestInput::PythonInline(code) => super::resolve_input_python_inline(ctx, code).await?,
55 RequestInput::PythonFile(path) => super::resolve_input_python_file(ctx, path).await?,
56 };
57 let seed = request.dangerous_advanced.as_ref().and_then(|a| a.seed);
58 let params = FunctionExecutionCreateParams {
59 function,
60 profile,
61 reasoning: None,
62 strategy: Some(Strategy::Default),
63 input,
64 split: if request.split { Some(true) } else { None },
65 invert: if request.invert { Some(true) } else { None },
66 provider: None,
67 seed,
68 stream: Some(true),
69 continuation: request.continuation,
70 };
71 let inner = super::runner::run(ctx.clone(), params);
72 Ok(Box::pin(inner.map(|r| {
73 r.map(|ev| match ev {
74 super::runner::Event::Id(id) => ResponseItem::Id(id),
75 super::runner::Event::Chunk(c) => ResponseItem::Chunk(c),
76 })
77 })))
78}
79
80async fn execute_detached(request: Request) -> Result<ItemStream, Error> {
85 let mut child_request = request;
86 match child_request.dangerous_advanced.as_mut() {
87 Some(adv) => adv.stream = Some(true),
88 None => {
89 child_request.dangerous_advanced = Some(RequestDangerousAdvanced {
90 stream: Some(true),
91 ..Default::default()
92 })
93 }
94 }
95 crate::command::reexec::strip_inherited(&mut child_request.base);
97 let exe = std::env::current_exe()
98 .map_err(|e| Error::Spawn("current_exe".into(), e))?;
99 let executor = BinaryExecutor::from_path(exe).detach(true);
100 let mut stream = executor
101 .execute::<Request, ResponseItem>(child_request, None)
102 .await
103 .map_err(|e| Error::Instance(format!(
104 "self-respawn for functions execute standard: {e}"
105 )))?;
106 let first = stream
107 .next()
108 .await
109 .ok_or(Error::EmptyStream)?
110 .map_err(|e| Error::Instance(format!(
111 "self-respawn for functions execute standard: {e}"
112 )))?;
113 Ok(Box::pin(
114 objectiveai_sdk::cli::command::StreamOnce::new(Ok(first)),
115 ))
116}
117
118pub mod request_schema {
119 use objectiveai_sdk::cli::command::functions::execute::standard as sdk;
120 use objectiveai_sdk::cli::command::functions::execute::standard::request_schema::{Request, Response};
121
122 use crate::context::Context;
123 use crate::error::Error;
124
125 pub async fn execute(_ctx: &Context, _request: Request) -> Result<Response, Error> {
126 Ok(objectiveai_sdk::cli::command::ResponseSchema(schemars::schema_for!(sdk::Request)))
127 }
128}
129
130pub mod response_schema {
131 use objectiveai_sdk::cli::command::functions::execute::standard as sdk;
132 use objectiveai_sdk::cli::command::functions::execute::standard::response_schema::{Request, Response};
133
134 use crate::context::Context;
135 use crate::error::Error;
136
137 pub async fn execute(_ctx: &Context, _request: Request) -> Result<Response, Error> {
138 Ok(objectiveai_sdk::cli::command::ResponseSchema(schemars::schema_for!(sdk::Response)))
139 }
140}