Skip to main content

objectiveai_sdk/cli/command/agents/logs/
mod.rs

1//! `agents logs` — persisted log tier. Leaves:
2//!
3//! - `open --id <id>` — look up a single logged row by its
4//!   `logs.messages."index"`.
5//! - `list --all | --pending` — stream logged rows for the targets:
6//!   `--all` is every row, `--pending` is the unfinalized rows only.
7//! - `subscribe` — long-lived stream of new rows as they land.
8
9use crate::cli::command::CommandRequest;
10
11pub mod list;
12pub mod open;
13pub mod subscribe;
14
15#[derive(clap::Subcommand)]
16pub enum Command {
17    /// Look up a single logged row by its `logs.messages."index"`.
18    Open(open::Command),
19    /// Stream logged rows for the targets (`--all` / `--pending`).
20    List(list::Command),
21    /// Subscribe to live updates for the given agents.
22    Subscribe(subscribe::Command),
23}
24
25#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
26#[serde(untagged)]
27#[schemars(rename = "cli.command.agents.logs.Request")]
28pub enum Request {
29    #[schemars(title = "Open")]
30    Open(open::Request),
31    #[schemars(title = "OpenRequestSchema")]
32    OpenRequestSchema(open::request_schema::Request),
33    #[schemars(title = "OpenResponseSchema")]
34    OpenResponseSchema(open::response_schema::Request),
35    #[schemars(title = "List")]
36    List(list::Request),
37    #[schemars(title = "ListRequestSchema")]
38    ListRequestSchema(list::request_schema::Request),
39    #[schemars(title = "ListResponseSchema")]
40    ListResponseSchema(list::response_schema::Request),
41    #[schemars(title = "Subscribe")]
42    Subscribe(subscribe::Request),
43    #[schemars(title = "SubscribeRequestSchema")]
44    SubscribeRequestSchema(subscribe::request_schema::Request),
45    #[schemars(title = "SubscribeResponseSchema")]
46    SubscribeResponseSchema(subscribe::response_schema::Request),
47}
48
49// Exempt from json-schema coverage: tier aggregate (see the root
50// `ResponseItem` in command.rs - TS7056).
51#[objectiveai_sdk_macros::json_schema_ignore]
52#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
53#[schemars(rename = "cli.command.agents.logs.ResponseItem")]
54#[serde(untagged)]
55pub enum ResponseItem {
56    #[schemars(title = "Open")]
57    Open(open::Response),
58    #[schemars(title = "OpenRequestSchema")]
59    OpenRequestSchema(open::request_schema::Response),
60    #[schemars(title = "OpenResponseSchema")]
61    OpenResponseSchema(open::response_schema::Response),
62    #[schemars(title = "List")]
63    List(list::ResponseItem),
64    #[schemars(title = "ListRequestSchema")]
65    ListRequestSchema(list::request_schema::Response),
66    #[schemars(title = "ListResponseSchema")]
67    ListResponseSchema(list::response_schema::Response),
68    #[schemars(title = "Subscribe")]
69    Subscribe(subscribe::ResponseItem),
70    #[schemars(title = "SubscribeRequestSchema")]
71    SubscribeRequestSchema(subscribe::request_schema::Response),
72    #[schemars(title = "SubscribeResponseSchema")]
73    SubscribeResponseSchema(subscribe::response_schema::Response),
74}
75
76#[cfg(feature = "mcp")]
77impl crate::cli::command::CommandResponse for ResponseItem {
78    fn into_mcp(self) -> crate::cli::command::McpResponseItem {
79        match self {
80            ResponseItem::Open(v) => v.into_mcp(),
81            ResponseItem::OpenRequestSchema(v) => v.into_mcp(),
82            ResponseItem::OpenResponseSchema(v) => v.into_mcp(),
83            ResponseItem::List(v) => v.into_mcp(),
84            ResponseItem::ListRequestSchema(v) => v.into_mcp(),
85            ResponseItem::ListResponseSchema(v) => v.into_mcp(),
86            ResponseItem::Subscribe(v) => v.into_mcp(),
87            ResponseItem::SubscribeRequestSchema(v) => v.into_mcp(),
88            ResponseItem::SubscribeResponseSchema(v) => v.into_mcp(),
89        }
90    }
91}
92
93impl TryFrom<Command> for Request {
94    type Error = crate::cli::command::FromArgsError;
95    fn try_from(command: Command) -> Result<Self, Self::Error> {
96        match command {
97            Command::Open(cmd) => match cmd.schema {
98                None => Ok(Request::Open(open::Request::try_from(cmd.args)?)),
99                Some(open::Schema::RequestSchema(args)) => Ok(
100                    Request::OpenRequestSchema(open::request_schema::Request::try_from(args)?),
101                ),
102                Some(open::Schema::ResponseSchema(args)) => Ok(
103                    Request::OpenResponseSchema(open::response_schema::Request::try_from(args)?),
104                ),
105            },
106            Command::List(cmd) => match cmd.schema {
107                None => Ok(Request::List(list::Request::try_from(cmd.args)?)),
108                Some(list::Schema::RequestSchema(args)) => Ok(
109                    Request::ListRequestSchema(list::request_schema::Request::try_from(args)?),
110                ),
111                Some(list::Schema::ResponseSchema(args)) => Ok(
112                    Request::ListResponseSchema(list::response_schema::Request::try_from(args)?),
113                ),
114            },
115            Command::Subscribe(cmd) => match cmd.schema {
116                None => Ok(Request::Subscribe(subscribe::Request::try_from(cmd.args)?)),
117                Some(subscribe::Schema::RequestSchema(args)) => Ok(
118                    Request::SubscribeRequestSchema(subscribe::request_schema::Request::try_from(args)?),
119                ),
120                Some(subscribe::Schema::ResponseSchema(args)) => Ok(
121                    Request::SubscribeResponseSchema(subscribe::response_schema::Request::try_from(args)?),
122                ),
123            },
124        }
125    }
126}
127
128impl CommandRequest for Request {
129    fn request_base(&self) -> &crate::cli::command::RequestBase {
130        match self {
131            Request::Open(inner) => inner.request_base(),
132            Request::OpenRequestSchema(inner) => inner.request_base(),
133            Request::OpenResponseSchema(inner) => inner.request_base(),
134            Request::List(inner) => inner.request_base(),
135            Request::ListRequestSchema(inner) => inner.request_base(),
136            Request::ListResponseSchema(inner) => inner.request_base(),
137            Request::Subscribe(inner) => inner.request_base(),
138            Request::SubscribeRequestSchema(inner) => inner.request_base(),
139            Request::SubscribeResponseSchema(inner) => inner.request_base(),
140        }
141    }
142
143    fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
144        match self {
145            Request::Open(inner) => inner.request_base_mut(),
146            Request::OpenRequestSchema(inner) => inner.request_base_mut(),
147            Request::OpenResponseSchema(inner) => inner.request_base_mut(),
148            Request::List(inner) => inner.request_base_mut(),
149            Request::ListRequestSchema(inner) => inner.request_base_mut(),
150            Request::ListResponseSchema(inner) => inner.request_base_mut(),
151            Request::Subscribe(inner) => inner.request_base_mut(),
152            Request::SubscribeRequestSchema(inner) => inner.request_base_mut(),
153            Request::SubscribeResponseSchema(inner) => inner.request_base_mut(),
154        }
155    }
156}
157
158#[cfg(feature = "cli-executor")]
159pub async fn execute<E: crate::cli::command::CommandExecutor>(
160    executor: &E,
161    request: Request,
162    agent_arguments: Option<&crate::cli::command::AgentArguments>,
163) -> Result<
164    std::pin::Pin<Box<dyn futures::Stream<Item = Result<ResponseItem, E::Error>> + Send>>,
165    E::Error,
166> {
167    use futures::StreamExt;
168    let stream: std::pin::Pin<
169        Box<dyn futures::Stream<Item = Result<ResponseItem, E::Error>> + Send>,
170    > = match request {
171        Request::Open(req) => {
172            let value = open::execute(executor, req, agent_arguments).await?;
173            Box::pin(crate::cli::command::StreamOnce::new(Ok(
174                ResponseItem::Open(value),
175            )))
176        }
177        Request::OpenRequestSchema(req) => {
178            let value = open::request_schema::execute(executor, req, agent_arguments).await?;
179            Box::pin(crate::cli::command::StreamOnce::new(Ok(
180                ResponseItem::OpenRequestSchema(value),
181            )))
182        }
183        Request::OpenResponseSchema(req) => {
184            let value = open::response_schema::execute(executor, req, agent_arguments).await?;
185            Box::pin(crate::cli::command::StreamOnce::new(Ok(
186                ResponseItem::OpenResponseSchema(value),
187            )))
188        }
189        Request::List(req) => {
190            let inner = list::execute(executor, req, agent_arguments).await?;
191            Box::pin(inner.map(|r| r.map(ResponseItem::List)))
192        }
193        Request::ListRequestSchema(req) => {
194            let value = list::request_schema::execute(executor, req, agent_arguments).await?;
195            Box::pin(crate::cli::command::StreamOnce::new(Ok(
196                ResponseItem::ListRequestSchema(value),
197            )))
198        }
199        Request::ListResponseSchema(req) => {
200            let value = list::response_schema::execute(executor, req, agent_arguments).await?;
201            Box::pin(crate::cli::command::StreamOnce::new(Ok(
202                ResponseItem::ListResponseSchema(value),
203            )))
204        }
205        Request::Subscribe(req) => {
206            let inner = subscribe::execute(executor, req, agent_arguments).await?;
207            Box::pin(inner.map(|r| r.map(ResponseItem::Subscribe)))
208        }
209        Request::SubscribeRequestSchema(req) => {
210            let value = subscribe::request_schema::execute(executor, req, agent_arguments).await?;
211            Box::pin(crate::cli::command::StreamOnce::new(Ok(
212                ResponseItem::SubscribeRequestSchema(value),
213            )))
214        }
215        Request::SubscribeResponseSchema(req) => {
216            let value = subscribe::response_schema::execute(executor, req, agent_arguments).await?;
217            Box::pin(crate::cli::command::StreamOnce::new(Ok(
218                ResponseItem::SubscribeResponseSchema(value),
219            )))
220        }
221    };
222    Ok(stream)
223}
224
225#[cfg(feature = "cli-executor")]
226pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
227    executor: &E,
228    request: Request,
229    transform: crate::cli::command::Transform,
230    agent_arguments: Option<&crate::cli::command::AgentArguments>,
231) -> Result<
232    std::pin::Pin<Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>>,
233    E::Error,
234> {
235    let stream: std::pin::Pin<
236        Box<dyn futures::Stream<Item = Result<serde_json::Value, E::Error>> + Send>,
237    > = match request {
238        Request::Open(req) => {
239            let value = open::execute_transform(executor, req, transform, agent_arguments).await?;
240            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
241        }
242        Request::OpenRequestSchema(req) => {
243            let value =
244                open::request_schema::execute_transform(executor, req, transform, agent_arguments).await?;
245            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
246        }
247        Request::OpenResponseSchema(req) => {
248            let value =
249                open::response_schema::execute_transform(executor, req, transform, agent_arguments).await?;
250            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
251        }
252        Request::List(req) => {
253            let inner = list::execute_transform(executor, req, transform, agent_arguments).await?;
254            Box::pin(inner)
255        }
256        Request::ListRequestSchema(req) => {
257            let value =
258                list::request_schema::execute_transform(executor, req, transform, agent_arguments).await?;
259            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
260        }
261        Request::ListResponseSchema(req) => {
262            let value =
263                list::response_schema::execute_transform(executor, req, transform, agent_arguments).await?;
264            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
265        }
266        Request::Subscribe(req) => {
267            let inner = subscribe::execute_transform(executor, req, transform, agent_arguments).await?;
268            Box::pin(inner)
269        }
270        Request::SubscribeRequestSchema(req) => {
271            let value =
272                subscribe::request_schema::execute_transform(executor, req, transform, agent_arguments).await?;
273            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
274        }
275        Request::SubscribeResponseSchema(req) => {
276            let value =
277                subscribe::response_schema::execute_transform(executor, req, transform, agent_arguments).await?;
278            Box::pin(crate::cli::command::StreamOnce::new(Ok(value)))
279        }
280    };
281    Ok(stream)
282}