objectiveai_sdk/cli/command/agents/message/
mod.rs1use crate::agent::completions::message::RichContent;
13use crate::cli::command::CommandRequest;
14use crate::cli::command::agents::selector::AgentSelector;
15
16#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
17#[schemars(rename = "cli.command.agents.message.Request")]
18pub struct Request {
19 pub path_type: Path,
20 pub agent: AgentSelector,
27 pub message: RequestMessage,
31 #[serde(default, skip_serializing_if = "Option::is_none")]
32 #[schemars(extend("omitempty" = true))]
33 pub dangerous_advanced: Option<RequestDangerousAdvanced>,
34 #[serde(flatten)]
35 pub base: crate::cli::command::RequestBase,
36}
37
38#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
39#[schemars(rename = "cli.command.agents.message.Path")]
40pub enum Path {
41 #[serde(rename = "agents/message")]
42 AgentsMessage,
43}
44
45#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
46#[schemars(rename = "cli.command.agents.message.RequestMessage")]
47pub enum RequestMessage {
48 #[schemars(title = "Inline")]
49 Inline(RichContent),
50 #[schemars(title = "Simple")]
51 Simple(String),
52 #[schemars(title = "File")]
53 File(std::path::PathBuf),
54 #[schemars(title = "PythonInline")]
55 PythonInline(String),
56 #[schemars(title = "PythonFile")]
57 PythonFile(std::path::PathBuf),
58}
59
60impl RequestMessage {
61 pub fn push_flags(&self, out: &mut Vec<String>) {
67 match self {
68 RequestMessage::Inline(rich) => {
69 out.push("--inline".to_string());
70 out.push(
71 serde_json::to_string(rich)
72 .expect("RichContent serializes to JSON cleanly"),
73 );
74 }
75 RequestMessage::Simple(s) => {
76 out.push("--simple".to_string());
77 out.push(s.clone());
78 }
79 RequestMessage::File(p) => {
80 out.push("--file".to_string());
81 out.push(p.to_string_lossy().into_owned());
82 }
83 RequestMessage::PythonInline(code) => {
84 out.push("--python-inline".to_string());
85 out.push(code.clone());
86 }
87 RequestMessage::PythonFile(p) => {
88 out.push("--python-file".to_string());
89 out.push(p.to_string_lossy().into_owned());
90 }
91 }
92 }
93}
94
95#[derive(Debug, Clone, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
96#[schemars(rename = "cli.command.agents.message.RequestDangerousAdvanced")]
97pub struct RequestDangerousAdvanced {
98 #[serde(default, skip_serializing_if = "Option::is_none")]
103 #[schemars(extend("omitempty" = true))]
104 pub seed: Option<i64>,
105}
106
107impl CommandRequest for Request {
108 fn into_command(&self) -> Vec<String> {
109 let mut argv = vec!["agents".to_string(), "message".to_string()];
110 self.agent.push_flags(&mut argv);
111 self.message.push_flags(&mut argv);
112 if let Some(advanced) = &self.dangerous_advanced {
113 argv.push("--dangerous-advanced".to_string());
114 argv.push(
115 serde_json::to_string(advanced)
116 .expect("RequestDangerousAdvanced serializes"),
117 );
118 }
119 self.base.push_flags(&mut argv);
120 argv
121 }
122
123 fn request_base(&self) -> &crate::cli::command::RequestBase {
124 &self.base
125 }
126
127 fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
128 Some(&mut self.base)
129 }
130}
131
132#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
136#[serde(tag = "type", rename_all = "snake_case")]
137#[schemars(rename = "cli.command.agents.message.Response")]
138pub enum Response {
139 #[schemars(title = "Delivered")]
143 Delivered,
144 #[schemars(title = "Id")]
149 Id { agent_instance_hierarchy: String },
150}
151
152#[derive(clap::Args)]
153pub struct Args {
154 #[command(flatten)]
155 pub agent: crate::cli::command::agents::selector::AgentSelectorArgs,
156 #[command(flatten)]
157 pub message: MessageArgs,
158 #[arg(long)]
161 pub dangerous_advanced: Option<String>,
162 #[command(flatten)]
163 pub base: crate::cli::command::RequestBaseArgs,
164}
165
166#[derive(clap::Args)]
167#[group(required = true, multiple = false)]
168pub struct MessageArgs {
169 #[arg(long)]
171 pub simple: Option<String>,
172 #[arg(long)]
174 pub inline: Option<String>,
175 #[arg(long)]
177 pub file: Option<std::path::PathBuf>,
178 #[arg(long)]
180 pub python_inline: Option<String>,
181 #[arg(long)]
183 pub python_file: Option<std::path::PathBuf>,
184}
185
186#[derive(clap::Args)]
187#[command(args_conflicts_with_subcommands = true)]
188pub struct Command {
189 #[command(flatten)]
190 pub args: Args,
191 #[command(subcommand)]
192 pub schema: Option<Schema>,
193}
194
195#[derive(clap::Subcommand)]
196pub enum Schema {
197 RequestSchema(request_schema::Args),
199 ResponseSchema(response_schema::Args),
201}
202
203impl TryFrom<Args> for Request {
204 type Error = crate::cli::command::FromArgsError;
205 fn try_from(args: Args) -> Result<Self, Self::Error> {
206 let message = if let Some(s) = args.message.simple {
207 RequestMessage::Simple(s)
208 } else if let Some(s) = args.message.inline {
209 let mut de = serde_json::Deserializer::from_str(&s);
210 let v = serde_path_to_error::deserialize(&mut de).map_err(|source| {
211 crate::cli::command::FromArgsError {
212 field: "inline",
213 source: source.into(),
214 }
215 })?;
216 RequestMessage::Inline(v)
217 } else if let Some(p) = args.message.file {
218 RequestMessage::File(p)
219 } else if let Some(s) = args.message.python_inline {
220 RequestMessage::PythonInline(s)
221 } else {
222 RequestMessage::PythonFile(args.message.python_file.unwrap())
225 };
226 let agent = AgentSelector::try_from(args.agent)?;
227 let dangerous_advanced: Option<RequestDangerousAdvanced> =
228 if let Some(s) = args.dangerous_advanced {
229 let mut de = serde_json::Deserializer::from_str(&s);
230 let v = serde_path_to_error::deserialize(&mut de).map_err(|source| {
231 crate::cli::command::FromArgsError {
232 field: "dangerous_advanced",
233 source: source.into(),
234 }
235 })?;
236 Some(v)
237 } else {
238 None
239 };
240 Ok(Self {
241 path_type: Path::AgentsMessage,
242 agent,
243 message,
244 dangerous_advanced,
245 base: args.base.into(),
246 })
247 }
248}
249
250#[cfg(feature = "cli-executor")]
251pub async fn execute<E: crate::cli::command::CommandExecutor>(
252 executor: &E,
253 mut request: Request,
254
255 agent_arguments: Option<&crate::cli::command::AgentArguments>,
256 ) -> Result<Response, E::Error> {
257 request.base.clear_transform();
258 executor.execute_one(request, agent_arguments).await
259}
260
261#[cfg(feature = "cli-executor")]
262pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
263 executor: &E,
264 mut request: Request,
265 transform: crate::cli::command::Transform,
266
267 agent_arguments: Option<&crate::cli::command::AgentArguments>,
268 ) -> Result<serde_json::Value, E::Error> {
269 request.base.set_transform(transform);
270 executor.execute_one(request, agent_arguments).await
271}
272
273#[cfg(feature = "mcp")]
274impl crate::cli::command::CommandResponse for Response {
275 fn into_mcp(self) -> crate::cli::command::McpResponseItem {
276 crate::cli::command::McpResponseItem::JSONL(serde_json::to_value(self).unwrap())
277 }
278}
279
280pub mod request_schema;
281
282
283pub mod response_schema;