Skip to main content

unified_agent_sdk/
log.rs

1//! Provider log normalization primitives.
2//!
3//! Executors emit provider-specific raw output. A [`LogNormalizer`] converts that
4//! output into [`NormalizedLog`] values so the rest of the SDK can operate on one
5//! stable event model.
6
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9
10use crate::types::{Role, ToolStatus};
11
12/// Provider-agnostic log entry produced by a [`LogNormalizer`].
13///
14/// Normalized logs are an intermediate representation between raw provider output
15/// and higher-level [`crate::event::AgentEvent`] values. The enum is intentionally
16/// non-exhaustive for forward compatibility.
17#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(tag = "type")]
19#[non_exhaustive]
20pub enum NormalizedLog {
21    /// Message emitted by user/assistant/system.
22    Message {
23        /// Message role.
24        role: Role,
25        /// Message content.
26        content: String,
27    },
28    /// Tool invocation state update.
29    ToolCall {
30        /// Tool name.
31        name: String,
32        /// Tool arguments or raw payload.
33        args: Value,
34        /// Tool execution status.
35        status: ToolStatus,
36        /// Unified high-level action metadata.
37        action: ActionType,
38    },
39    /// Assistant reasoning/thinking content.
40    Thinking {
41        /// Reasoning text.
42        content: String,
43    },
44    /// Token usage signal.
45    TokenUsage {
46        /// Total tokens consumed.
47        total: u32,
48        /// Token limit (if available).
49        limit: u32,
50    },
51    /// Error signal emitted by the source normalizer.
52    Error {
53        /// Stable error category.
54        error_type: String,
55        /// Human-readable error message.
56        message: String,
57    },
58}
59
60/// Best-effort classification of the action a tool update represents.
61///
62/// This metadata is useful when downstream consumers want to distinguish file,
63/// command, web, or MCP activity without parsing provider-specific payloads. The
64/// enum is intentionally non-exhaustive for forward compatibility.
65#[derive(Debug, Clone, Serialize, Deserialize)]
66#[serde(tag = "action")]
67#[non_exhaustive]
68pub enum ActionType {
69    /// File read operation.
70    FileRead {
71        /// Target path.
72        path: String,
73    },
74    /// File edit/write operation.
75    FileEdit {
76        /// Target path.
77        path: String,
78    },
79    /// Shell command execution.
80    CommandRun {
81        /// Raw command string.
82        command: String,
83    },
84    /// Web search operation.
85    WebSearch {
86        /// Search query.
87        query: String,
88    },
89    /// MCP tool invocation.
90    McpTool {
91        /// Tool identifier.
92        tool: String,
93    },
94    /// Explicit "ask user" interaction point.
95    AskUser,
96}
97
98/// Trait implemented by provider adapters that translate raw output into [`NormalizedLog`] values.
99///
100/// Normalizers may buffer partial chunks internally. Call [`LogNormalizer::flush`]
101/// when the raw stream ends to emit any trailing state.
102pub trait LogNormalizer: Send {
103    /// Processes one raw output chunk and returns any normalized records derived from it.
104    fn normalize(&mut self, chunk: &[u8]) -> Vec<NormalizedLog>;
105
106    /// Flushes any buffered state after the upstream raw stream has ended.
107    fn flush(&mut self) -> Vec<NormalizedLog>;
108}