Skip to main content

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

1//! `agents logs read pending` — fetch the unread delta for the
2//! children spawned by a parent AIH, coalesced into [`ResponseItem`]
3//! blocks. Read-and-advance: the per-child watermark
4//! (`logs.messages_queue.read_index`) is bumped to the maximum
5//! returned id in the same SQL statement, never downgraded.
6
7use crate::cli::command::CommandRequest;
8
9#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
10#[schemars(rename = "cli.command.agents.logs.read.pending.Request")]
11pub struct Request {
12    pub path_type: Path,
13    pub targets: Vec<Target>,
14    /// Skip rows with `logs.messages."index" <= after_id`. Composes
15    /// with the per-child watermark (`GREATEST` of the two applies).
16    #[serde(default, skip_serializing_if = "Option::is_none")]
17    #[schemars(extend("omitempty" = true))]
18    pub after_id: Option<i64>,
19    /// Cap on rows scanned per target. `None` = unlimited.
20    #[serde(default, skip_serializing_if = "Option::is_none")]
21    #[schemars(extend("omitempty" = true))]
22    pub limit: Option<i64>,
23    #[serde(flatten)]
24    pub base: crate::cli::command::RequestBase,
25}
26
27#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
28#[schemars(rename = "cli.command.agents.logs.read.pending.Path")]
29pub enum Path {
30    #[serde(rename = "agents/logs/read/pending")]
31    AgentsLogsReadPending,
32}
33
34impl CommandRequest for Request {
35    fn into_command(&self) -> Vec<String> {
36        let mut argv = vec![
37            "agents".to_string(),
38            "logs".to_string(),
39            "read".to_string(),
40            "pending".to_string(),
41        ];
42        for target in &self.targets {
43            argv.push("--target".to_string());
44            argv.push(target.into_arg_string());
45        }
46        if let Some(after_id) = self.after_id {
47            argv.push("--after-id".to_string());
48            argv.push(after_id.to_string());
49        }
50        if let Some(limit) = self.limit {
51            argv.push("--limit".to_string());
52            argv.push(limit.to_string());
53        }
54        self.base.push_flags(&mut argv);
55        argv
56    }
57
58    fn request_base(&self) -> &crate::cli::command::RequestBase {
59        &self.base
60    }
61
62    fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
63        Some(&mut self.base)
64    }
65}
66
67// Share the ResponseItem / part / part-type shapes AND the docker-style
68// `Target` parser with `agents logs read all` — same underlying
69// `logs.messages` rows surfaced as either the full target slice or
70// the watermark-delta slice, same per-target input shape.
71pub use super::all::{
72    AssistantResponsePart, ClientNotificationPart, ClientNotificationPartType, ResponseItem,
73    Target, ToolResponsePart, ToolResponsePartType,
74};
75
76#[derive(clap::Args)]
77pub struct Args {
78    /// One or more `--target instance=L[,parent=P]` entries. `parent`
79    /// defaults to the cli's own `Config.agent_instance_hierarchy`
80    /// when omitted on an individual target. Also accepts
81    /// `--target tag=T` and `--target me` (the caller's own AIH).
82    #[arg(long = "target", required = true)]
83    pub targets: Vec<String>,
84    /// Skip rows with `logs.messages."index" <= after_id` per target.
85    #[arg(long)]
86    pub after_id: Option<i64>,
87    /// Cap on rows scanned per target.
88    #[arg(long)]
89    pub limit: Option<i64>,
90    #[command(flatten)]
91    pub base: crate::cli::command::RequestBaseArgs,
92}
93
94#[derive(clap::Args)]
95#[command(args_conflicts_with_subcommands = true)]
96pub struct Command {
97    #[command(flatten)]
98    pub args: Args,
99    #[command(subcommand)]
100    pub schema: Option<Schema>,
101}
102
103#[derive(clap::Subcommand)]
104pub enum Schema {
105    /// Emit the JSON Schema for this leaf's `Request` type and exit.
106    RequestSchema(request_schema::Args),
107    /// Emit the JSON Schema for this leaf's `Response` type and exit.
108    ResponseSchema(response_schema::Args),
109}
110
111impl TryFrom<Args> for Request {
112    type Error = crate::cli::command::FromArgsError;
113    fn try_from(args: Args) -> Result<Self, Self::Error> {
114        let targets = args
115            .targets
116            .iter()
117            .map(|s| {
118                s.parse::<Target>().map_err(|msg| {
119                    crate::cli::command::FromArgsError::path_parse("target", msg)
120                })
121            })
122            .collect::<Result<Vec<_>, _>>()?;
123        Ok(Self {
124            path_type: Path::AgentsLogsReadPending,
125            targets,
126            after_id: args.after_id,
127            limit: args.limit,
128            base: args.base.into(),
129        })
130    }
131}
132
133#[cfg(feature = "cli-executor")]
134pub async fn execute<E: crate::cli::command::CommandExecutor>(
135    executor: &E,
136    mut request: Request,
137
138        agent_arguments: Option<&crate::cli::command::AgentArguments>,
139    ) -> Result<E::Stream<ResponseItem>, E::Error> {
140    request.base.clear_transform();
141    executor.execute(request, agent_arguments).await
142}
143
144#[cfg(feature = "cli-executor")]
145pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
146    executor: &E,
147    mut request: Request,
148    transform: crate::cli::command::Transform,
149
150        agent_arguments: Option<&crate::cli::command::AgentArguments>,
151    ) -> Result<E::Stream<serde_json::Value>, E::Error> {
152    request.base.set_transform(transform);
153    executor.execute(request, agent_arguments).await
154}
155
156pub mod request_schema;
157
158
159pub mod response_schema;