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 pub jq: Option<String>,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
53#[schemars(rename = "cli.command.tasks.schedule.Path")]
54pub enum Path {
55 #[serde(rename = "tasks/schedule")]
56 AgentsTasksSchedule,
57}
58
59impl CommandRequest for Request {
60 fn into_command(&self) -> Vec<String> {
61 let mut argv = vec![
62 "tasks".to_string(),
63 "schedule".to_string(),
64 ];
65 argv.push("--name".to_string());
66 argv.push(self.name.clone());
67 argv.push("--description".to_string());
68 argv.push(self.description.clone());
69 match self.interval_seconds {
70 Some(secs) => {
71 argv.push("--interval".to_string());
72 argv.push(
76 humantime::format_duration(std::time::Duration::from_secs(secs))
77 .to_string(),
78 );
79 }
80 None => argv.push("--oneshot".to_string()),
81 }
82 if self.overwrite {
83 argv.push("--overwrite".to_string());
84 }
85 if let Some(jq) = &self.jq {
86 argv.push("--jq".to_string());
87 argv.push(jq.clone());
88 }
89 argv.push("--".to_string());
92 argv.extend(self.command.iter().cloned());
93 argv
94 }
95}
96
97#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
103#[schemars(rename = "cli.command.tasks.schedule.Response")]
104pub struct Response {
105 pub name: String,
106 pub agent_instance_hierarchy: String,
107 pub version: u64,
108}
109
110#[derive(clap::Args)]
111#[command(group(
112 clap::ArgGroup::new("schedule_kind")
113 .required(true)
114 .multiple(false)
115 .args(["interval", "oneshot"])
116))]
117pub struct Args {
118 #[arg(long)]
123 pub interval: Option<String>,
124 #[arg(long)]
127 pub name: String,
128 #[arg(long)]
131 pub description: String,
132 #[arg(long)]
135 pub oneshot: bool,
136 #[arg(long)]
141 pub overwrite: bool,
142 #[arg(long)]
144 pub jq: Option<String>,
145 #[arg(trailing_var_arg = true, allow_hyphen_values = true, num_args = 1..)]
150 pub command: Vec<String>,
151}
152
153#[derive(clap::Args)]
154#[command(args_conflicts_with_subcommands = true)]
155pub struct Command {
156 #[command(flatten)]
157 pub args: Args,
158 #[command(subcommand)]
159 pub schema: Option<Schema>,
160}
161
162#[derive(clap::Subcommand)]
163pub enum Schema {
164 RequestSchema(request_schema::Args),
166 ResponseSchema(response_schema::Args),
168}
169
170impl TryFrom<Args> for Request {
171 type Error = crate::cli::command::FromArgsError;
172 fn try_from(args: Args) -> Result<Self, Self::Error> {
173 let interval_seconds = match (args.interval, args.oneshot) {
176 (Some(interval), false) => {
177 let parsed =
178 humantime::parse_duration(&interval).map_err(|source| {
179 crate::cli::command::FromArgsError {
180 field: "interval",
181 source: source.to_string().into(),
182 }
183 })?;
184 Some(parsed.as_secs())
185 }
186 (None, true) => None,
187 _ => unreachable!(
188 "clap group `schedule_kind` enforces exactly one of `--interval` | `--oneshot`"
189 ),
190 };
191 if args.command.is_empty() {
192 return Err(crate::cli::command::FromArgsError {
193 field: "command",
194 source: "schedule requires at least one positional argument (the command)"
195 .to_string()
196 .into(),
197 });
198 }
199 Ok(Self {
200 path_type: Path::AgentsTasksSchedule,
201 name: args.name,
202 command: args.command,
203 description: args.description,
204 interval_seconds,
205 overwrite: args.overwrite,
206 jq: args.jq,
207 })
208 }
209}
210
211#[cfg(feature = "cli-executor")]
212pub async fn execute<E: crate::cli::command::CommandExecutor>(
213 executor: &E,
214 mut request: Request,
215 agent_arguments: Option<&crate::cli::command::AgentArguments>,
216) -> Result<Response, E::Error> {
217 request.jq = None;
218 executor.execute_one(request, agent_arguments).await
219}
220
221#[cfg(feature = "cli-executor")]
222pub async fn execute_jq<E: crate::cli::command::CommandExecutor>(
223 executor: &E,
224 mut request: Request,
225 jq: String,
226 agent_arguments: Option<&crate::cli::command::AgentArguments>,
227) -> Result<serde_json::Value, E::Error> {
228 request.jq = Some(jq);
229 executor.execute_one(request, agent_arguments).await
230}
231
232#[cfg(feature = "mcp")]
233impl crate::cli::command::CommandResponse for Response {
234 fn into_mcp(self) -> crate::cli::command::McpResponseItem {
235 crate::cli::command::McpResponseItem::JSONL(serde_json::to_value(self).unwrap())
236 }
237}
238
239pub mod request_schema;
240
241pub mod response_schema;