objectiveai_sdk/cli/command/tasks/schedule/
mod.rs1use crate::cli::command::CommandRequest;
17
18#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
19#[schemars(rename = "cli.command.tasks.schedule.Request")]
20pub struct Request {
21 pub path_type: Path,
22 pub name: String,
28 pub command: Vec<String>,
30 pub description: String,
34 #[serde(default, skip_serializing_if = "Option::is_none")]
40 #[schemars(extend("omitempty" = true))]
41 pub interval_seconds: Option<u64>,
42 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
48 pub overwrite: bool,
49 #[serde(flatten)]
50 pub base: crate::cli::command::RequestBase,
51}
52
53#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
54#[schemars(rename = "cli.command.tasks.schedule.Path")]
55pub enum Path {
56 #[serde(rename = "tasks/schedule")]
57 AgentsTasksSchedule,
58}
59
60impl CommandRequest for Request {
61 fn into_command(&self) -> Vec<String> {
62 let mut argv = vec![
63 "tasks".to_string(),
64 "schedule".to_string(),
65 ];
66 argv.push("--name".to_string());
67 argv.push(self.name.clone());
68 argv.push("--description".to_string());
69 argv.push(self.description.clone());
70 match self.interval_seconds {
71 Some(secs) => {
72 argv.push("--interval".to_string());
73 argv.push(
77 humantime::format_duration(std::time::Duration::from_secs(secs))
78 .to_string(),
79 );
80 }
81 None => argv.push("--oneshot".to_string()),
82 }
83 if self.overwrite {
84 argv.push("--overwrite".to_string());
85 }
86 self.base.push_flags(&mut argv);
87 argv.push("--".to_string());
90 argv.extend(self.command.iter().cloned());
91 argv
92 }
93
94 fn request_base(&self) -> &crate::cli::command::RequestBase {
95 &self.base
96 }
97
98 fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
99 Some(&mut self.base)
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
109#[schemars(rename = "cli.command.tasks.schedule.Response")]
110pub struct Response {
111 pub name: String,
112 pub agent_instance_hierarchy: String,
113 pub version: u64,
114}
115
116#[derive(clap::Args)]
117#[command(group(
118 clap::ArgGroup::new("schedule_kind")
119 .required(true)
120 .multiple(false)
121 .args(["interval", "oneshot"])
122))]
123pub struct Args {
124 #[arg(long)]
129 pub interval: Option<String>,
130 #[arg(long)]
133 pub name: String,
134 #[arg(long)]
137 pub description: String,
138 #[arg(long)]
141 pub oneshot: bool,
142 #[arg(long)]
147 pub overwrite: bool,
148 #[command(flatten)]
149 pub base: crate::cli::command::RequestBaseArgs,
150 #[arg(trailing_var_arg = true, allow_hyphen_values = true, num_args = 1..)]
155 pub command: Vec<String>,
156}
157
158#[derive(clap::Args)]
159#[command(args_conflicts_with_subcommands = true)]
160pub struct Command {
161 #[command(flatten)]
162 pub args: Args,
163 #[command(subcommand)]
164 pub schema: Option<Schema>,
165}
166
167#[derive(clap::Subcommand)]
168pub enum Schema {
169 RequestSchema(request_schema::Args),
171 ResponseSchema(response_schema::Args),
173}
174
175impl TryFrom<Args> for Request {
176 type Error = crate::cli::command::FromArgsError;
177 fn try_from(args: Args) -> Result<Self, Self::Error> {
178 let interval_seconds = match (args.interval, args.oneshot) {
181 (Some(interval), false) => {
182 let parsed =
183 humantime::parse_duration(&interval).map_err(|source| {
184 crate::cli::command::FromArgsError {
185 field: "interval",
186 source: source.to_string().into(),
187 }
188 })?;
189 Some(parsed.as_secs())
190 }
191 (None, true) => None,
192 _ => unreachable!(
193 "clap group `schedule_kind` enforces exactly one of `--interval` | `--oneshot`"
194 ),
195 };
196 if args.command.is_empty() {
197 return Err(crate::cli::command::FromArgsError {
198 field: "command",
199 source: "schedule requires at least one positional argument (the command)"
200 .to_string()
201 .into(),
202 });
203 }
204 Ok(Self {
205 path_type: Path::AgentsTasksSchedule,
206 name: args.name,
207 command: args.command,
208 description: args.description,
209 interval_seconds,
210 overwrite: args.overwrite,
211 base: args.base.into(),
212 })
213 }
214}
215
216#[cfg(feature = "cli-executor")]
217pub async fn execute<E: crate::cli::command::CommandExecutor>(
218 executor: &E,
219 mut request: Request,
220 agent_arguments: Option<&crate::cli::command::AgentArguments>,
221) -> Result<Response, E::Error> {
222 request.base.clear_transform();
223 executor.execute_one(request, agent_arguments).await
224}
225
226#[cfg(feature = "cli-executor")]
227pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
228 executor: &E,
229 mut request: Request,
230 transform: crate::cli::command::Transform,
231 agent_arguments: Option<&crate::cli::command::AgentArguments>,
232) -> Result<serde_json::Value, E::Error> {
233 request.base.set_transform(transform);
234 executor.execute_one(request, agent_arguments).await
235}
236
237#[cfg(feature = "mcp")]
238impl crate::cli::command::CommandResponse for Response {
239 fn into_mcp(self) -> crate::cli::command::McpResponseItem {
240 crate::cli::command::McpResponseItem::JSONL(serde_json::to_value(self).unwrap())
241 }
242}
243
244pub mod request_schema;
245
246pub mod response_schema;