Skip to main content

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

1//! `agents logs read id` — fetch one logged row by its
2//! `logs.messages."index"` BIGSERIAL. The handler resolves the row's
3//! target table via the `logs.message_table` discriminator and
4//! returns a typed [`Response`] variant carrying that table's
5//! payload — no `serde_json::Value` anywhere in the public shape.
6//!
7//! The 17 underlying `logs.*` tables collapse into 10 variants:
8//!
9//! 1. **Request-blob tiers (3)** — agent / vector / function
10//!    request bodies. The JSONB column round-trips through the
11//!    matching SDK `…CreateParams` type so callers see a proper
12//!    typed object, not a raw blob.
13//! 2. **`ToolCall`** — one assistant tool-call slot
14//!    (`tool_call_id` + `arguments` + indices).
15//! 3. **`ToolResponse`** — the per-message tool-response container
16//!    row (`tool_call_id` + index).
17//! 4. **Content payloads (5)** — `Text` / `Image` / `Audio` /
18//!    `Video` / `File`. The `Text` variant subsumes all text-bearing
19//!    rows (refusal, reasoning, assistant content text, tool
20//!    content text); media variants carry the SDK media type
21//!    directly so MCP rendering routes through the existing
22//!    `ContentBlock` projections.
23
24use crate::agent::completions::message::{File, ImageUrl, InputAudio, VideoUrl};
25use crate::agent::completions::request::AgentCompletionCreateParams;
26use crate::cli::command::CommandRequest;
27use crate::functions::executions::request::FunctionExecutionCreateParams;
28use crate::vector::completions::request::VectorCompletionCreateParams;
29
30#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
31#[schemars(rename = "cli.command.agents.logs.read.id.Request")]
32pub struct Request {
33    pub path_type: Path,
34    pub id: i64,
35    #[serde(flatten)]
36    pub base: crate::cli::command::RequestBase,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
40#[schemars(rename = "cli.command.agents.logs.read.id.Path")]
41pub enum Path {
42    #[serde(rename = "agents/logs/read/id")]
43    AgentsLogsReadId,
44}
45
46impl CommandRequest for Request {
47    fn into_command(&self) -> Vec<String> {
48        let mut argv = vec![
49            "agents".to_string(),
50            "logs".to_string(),
51            "read".to_string(),
52            "id".to_string(),
53            self.id.to_string(),
54        ];
55        self.base.push_flags(&mut argv);
56        argv
57    }
58
59    fn request_base(&self) -> &crate::cli::command::RequestBase {
60        &self.base
61    }
62
63    fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
64        Some(&mut self.base)
65    }
66}
67
68/// Resolved payload for one `logs.messages."index"`. Tagged by
69/// `type`, snake_case discriminant. The MCP projection in
70/// [`CommandResponse::into_mcp`] hands media variants over as
71/// [`ContentBlock`]s and text as a bare JSON string — matching the
72/// existing `agents queue read id` projection of `RichContentPart`.
73/// The five non-content variants render as JSONL with their full
74/// typed body so callers can introspect request-blob /
75/// tool-response / tool-call metadata.
76///
77/// [`ContentBlock`]: crate::mcp::tool::ContentBlock
78#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
79#[serde(tag = "type", rename_all = "snake_case")]
80#[schemars(rename = "cli.command.agents.logs.read.id.Response")]
81pub enum Response {
82    #[schemars(title = "AgentCompletionRequest")]
83    AgentCompletionRequest {
84        response_id: String,
85        sender_agent_instance_hierarchy: String,
86        body: AgentCompletionCreateParams,
87        created_at: i64,
88    },
89    #[schemars(title = "VectorCompletionRequest")]
90    VectorCompletionRequest {
91        response_id: String,
92        sender_agent_instance_hierarchy: String,
93        body: VectorCompletionCreateParams,
94        created_at: i64,
95    },
96    #[schemars(title = "FunctionExecutionRequest")]
97    FunctionExecutionRequest {
98        response_id: String,
99        sender_agent_instance_hierarchy: String,
100        body: FunctionExecutionCreateParams,
101        created_at: i64,
102    },
103    #[schemars(title = "ToolCall")]
104    ToolCall {
105        response_id: String,
106        index: i64,
107        tool_call_index: i64,
108        tool_call_id: String,
109        /// Function name from the openai tool_call payload
110        /// (`tool_calls[i].function.name`).
111        function_name: String,
112        arguments: String,
113    },
114    #[schemars(title = "ToolResponse")]
115    ToolResponse {
116        response_id: String,
117        index: i64,
118        tool_call_id: String,
119    },
120    #[schemars(title = "Text")]
121    Text { text: String },
122    #[schemars(title = "Image")]
123    Image(ImageUrl),
124    #[schemars(title = "Audio")]
125    Audio(InputAudio),
126    #[schemars(title = "Video")]
127    Video(VideoUrl),
128    #[schemars(title = "File")]
129    File(File),
130}
131
132#[derive(clap::Args)]
133pub struct Args {
134    /// `logs.messages."index"` — the BIGSERIAL position of the
135    /// event in the cross-agent history.
136    pub id: i64,
137    #[command(flatten)]
138    pub base: crate::cli::command::RequestBaseArgs,
139}
140
141#[derive(clap::Args)]
142#[command(args_conflicts_with_subcommands = true)]
143pub struct Command {
144    #[command(flatten)]
145    pub args: Args,
146    #[command(subcommand)]
147    pub schema: Option<Schema>,
148}
149
150#[derive(clap::Subcommand)]
151pub enum Schema {
152    /// Emit the JSON Schema for this leaf's `Request` type and exit.
153    RequestSchema(request_schema::Args),
154    /// Emit the JSON Schema for this leaf's `Response` type and exit.
155    ResponseSchema(response_schema::Args),
156}
157
158impl TryFrom<Args> for Request {
159    type Error = crate::cli::command::FromArgsError;
160    fn try_from(args: Args) -> Result<Self, Self::Error> {
161        Ok(Self {
162            path_type: Path::AgentsLogsReadId,
163            id: args.id,
164            base: args.base.into(),
165        })
166    }
167}
168
169#[cfg(feature = "mcp")]
170impl crate::cli::command::CommandResponse for Response {
171    fn into_mcp(self) -> crate::cli::command::McpResponseItem {
172        use crate::cli::command::CommandResponse;
173        match self {
174            // Content payloads delegate to the existing inner-type
175            // projections so they ride MCP exactly the way bare
176            // `RichContentPart` does today.
177            Response::Text { text } => text.into_mcp(),
178            Response::Image(image_url) => image_url.into_mcp(),
179            Response::Audio(input_audio) => input_audio.into_mcp(),
180            Response::Video(video_url) => video_url.into_mcp(),
181            Response::File(file) => file.into_mcp(),
182            // Everything else: the full typed variant rides as JSONL.
183            other => crate::cli::command::McpResponseItem::JSONL(
184                serde_json::to_value(other).unwrap(),
185            ),
186        }
187    }
188}
189
190#[cfg(feature = "cli-executor")]
191pub async fn execute<E: crate::cli::command::CommandExecutor>(
192    executor: &E,
193    mut request: Request,
194
195        agent_arguments: Option<&crate::cli::command::AgentArguments>,
196    ) -> Result<Response, E::Error> {
197    request.base.clear_transform();
198    executor.execute_one(request, agent_arguments).await
199}
200
201#[cfg(feature = "cli-executor")]
202pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
203    executor: &E,
204    mut request: Request,
205    transform: crate::cli::command::Transform,
206
207        agent_arguments: Option<&crate::cli::command::AgentArguments>,
208    ) -> Result<serde_json::Value, E::Error> {
209    request.base.set_transform(transform);
210    executor.execute_one(request, agent_arguments).await
211}
212
213pub mod request_schema;
214
215
216pub mod response_schema;