Skip to main content

codex_rollout_trace/
raw_event.rs

1//! Append-only raw trace events.
2
3use crate::model::AgentThreadId;
4use crate::model::CodeCellRuntimeStatus;
5use crate::model::CodexTurnId;
6use crate::model::CompactionId;
7use crate::model::CompactionRequestId;
8use crate::model::EdgeId;
9use crate::model::ExecutionStatus;
10use crate::model::InferenceCallId;
11use crate::model::McpCallId;
12use crate::model::ModelVisibleCallId;
13use crate::model::RolloutStatus;
14use crate::model::ToolCallId;
15use crate::model::ToolCallKind;
16use crate::model::ToolCallSummary;
17use crate::payload::RawPayloadRef;
18use serde::Deserialize;
19use serde::Serialize;
20use serde_json::Value;
21
22/// Monotonic sequence number assigned by the raw trace writer.
23pub type RawEventSeq = u64;
24
25/// Current raw event envelope schema version.
26pub(crate) const RAW_TRACE_EVENT_SCHEMA_VERSION: u32 = 1;
27
28/// One append-only raw trace event.
29///
30/// Every event uses the same envelope so partial replay and corruption checks
31/// can run before the reducer understands the event-specific payload.
32#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
33pub struct RawTraceEvent {
34    pub schema_version: u32,
35    /// Contiguous writer-assigned order inside one rollout event log.
36    pub seq: RawEventSeq,
37    /// Unix wall-clock timestamp in milliseconds. Use for display/latency.
38    pub wall_time_unix_ms: i64,
39    pub rollout_id: String,
40    pub thread_id: Option<AgentThreadId>,
41    pub codex_turn_id: Option<CodexTurnId>,
42    pub payload: RawTraceEventPayload,
43}
44
45/// Writer-supplied context that appears in the raw event envelope.
46#[derive(Debug, Clone, Default, PartialEq, Eq)]
47pub struct RawTraceEventContext {
48    pub thread_id: Option<AgentThreadId>,
49    pub codex_turn_id: Option<CodexTurnId>,
50}
51
52/// Runtime requester as observed at the raw tool boundary.
53///
54/// This intentionally uses runtime-local identifiers. The reducer is the only
55/// place that maps these handles to graph identities such as `CodeCellId`.
56#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
57#[serde(rename_all = "snake_case", tag = "type")]
58pub enum RawToolCallRequester {
59    Model,
60    CodeCell {
61        /// Runtime-local code-mode cell handle.
62        runtime_cell_id: String,
63    },
64}
65
66/// Typed payload for a raw trace event.
67#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
68#[serde(rename_all = "snake_case", tag = "type")]
69pub enum RawTraceEventPayload {
70    RolloutStarted {
71        trace_id: String,
72        root_thread_id: AgentThreadId,
73    },
74    RolloutEnded {
75        status: RolloutStatus,
76    },
77    ThreadStarted {
78        thread_id: AgentThreadId,
79        /// Stable agent path.
80        agent_path: String,
81        metadata_payload: Option<RawPayloadRef>,
82    },
83    ThreadEnded {
84        thread_id: AgentThreadId,
85        status: RolloutStatus,
86    },
87    CodexTurnStarted {
88        codex_turn_id: CodexTurnId,
89        thread_id: AgentThreadId,
90    },
91    CodexTurnEnded {
92        codex_turn_id: CodexTurnId,
93        status: ExecutionStatus,
94    },
95    InferenceStarted {
96        inference_call_id: InferenceCallId,
97        thread_id: AgentThreadId,
98        codex_turn_id: CodexTurnId,
99        model: String,
100        provider_name: String,
101        request_payload: RawPayloadRef,
102    },
103    InferenceCompleted {
104        inference_call_id: InferenceCallId,
105        /// Responses API `response.id`; used by `previous_response_id`.
106        response_id: Option<String>,
107        /// Provider transport request id, such as `x-request-id`.
108        upstream_request_id: Option<String>,
109        response_payload: RawPayloadRef,
110    },
111    InferenceFailed {
112        inference_call_id: InferenceCallId,
113        /// Provider transport request id, such as `x-request-id`, when the
114        /// provider returned one before the stream failed.
115        upstream_request_id: Option<String>,
116        error: String,
117        /// Partial response payload, when stream events arrived before failure.
118        partial_response_payload: Option<RawPayloadRef>,
119    },
120    InferenceCancelled {
121        inference_call_id: InferenceCallId,
122        /// Provider transport request id, such as `x-request-id`, when observed
123        /// before Codex stopped consuming the stream.
124        upstream_request_id: Option<String>,
125        /// Why Codex stopped consuming the provider stream before a terminal response event.
126        reason: String,
127        /// Completed output items observed before cancellation, if any.
128        partial_response_payload: Option<RawPayloadRef>,
129    },
130    ToolCallStarted {
131        tool_call_id: ToolCallId,
132        /// Protocol/model call ID when this runtime call came from model output.
133        model_visible_call_id: Option<String>,
134        /// Code-mode runtime bridge ID when model-authored code issued this call.
135        code_mode_runtime_tool_id: Option<String>,
136        /// Runtime requester that caused this tool lifecycle.
137        requester: RawToolCallRequester,
138        kind: ToolCallKind,
139        summary: ToolCallSummary,
140        invocation_payload: Option<RawPayloadRef>,
141    },
142    /// Bridge correlation UUID assigned only when a tool reaches an MCP backend.
143    McpToolCallCorrelationAssigned {
144        tool_call_id: ToolCallId,
145        mcp_call_id: McpCallId,
146    },
147    ToolCallRuntimeStarted {
148        tool_call_id: ToolCallId,
149        /// Runtime/protocol observation for how Codex began executing the tool.
150        runtime_payload: RawPayloadRef,
151    },
152    ToolCallRuntimeEnded {
153        tool_call_id: ToolCallId,
154        status: ExecutionStatus,
155        /// Runtime/protocol observation for how Codex finished executing the tool.
156        runtime_payload: RawPayloadRef,
157    },
158    ToolCallEnded {
159        tool_call_id: ToolCallId,
160        status: ExecutionStatus,
161        result_payload: Option<RawPayloadRef>,
162    },
163    CodeCellStarted {
164        /// Runtime-local handle allocated by code mode for waits and nested tools.
165        runtime_cell_id: String,
166        /// Custom tool call id on the model-visible `exec` item.
167        model_visible_call_id: ModelVisibleCallId,
168        /// JavaScript source after the public `exec` wrapper has been parsed.
169        source_js: String,
170    },
171    CodeCellInitialResponse {
172        /// Runtime-local handle, matching `CodeCellStarted`.
173        runtime_cell_id: String,
174        status: CodeCellRuntimeStatus,
175        response_payload: Option<RawPayloadRef>,
176    },
177    CodeCellEnded {
178        /// Runtime-local handle, matching `CodeCellStarted`.
179        runtime_cell_id: String,
180        status: CodeCellRuntimeStatus,
181        response_payload: Option<RawPayloadRef>,
182    },
183    CompactionRequestStarted {
184        compaction_id: CompactionId,
185        compaction_request_id: CompactionRequestId,
186        thread_id: AgentThreadId,
187        codex_turn_id: CodexTurnId,
188        model: String,
189        provider_name: String,
190        request_payload: RawPayloadRef,
191    },
192    CompactionRequestCompleted {
193        compaction_id: CompactionId,
194        compaction_request_id: CompactionRequestId,
195        response_payload: RawPayloadRef,
196    },
197    CompactionRequestFailed {
198        compaction_id: CompactionId,
199        compaction_request_id: CompactionRequestId,
200        error: String,
201    },
202    /// Checkpoint installation event for remote-compacted replacement history.
203    CompactionInstalled {
204        compaction_id: CompactionId,
205        /// Trace-only checkpoint payload. Do not route this through public UI protocol.
206        checkpoint_payload: RawPayloadRef,
207    },
208    /// Multi-agent v2 child-to-parent completion delivery.
209    AgentResultObserved {
210        edge_id: EdgeId,
211        child_thread_id: AgentThreadId,
212        child_codex_turn_id: CodexTurnId,
213        parent_thread_id: AgentThreadId,
214        message: String,
215        /// Raw notification payload. This is evidence for the runtime delivery,
216        /// not the parent-side model-visible item.
217        carried_payload: Option<RawPayloadRef>,
218    },
219    /// Existing UI/protocol event wrapped into trace format.
220    ProtocolEventObserved {
221        event_type: String,
222        event_payload: RawPayloadRef,
223    },
224    /// Structured payload for early instrumentation before a dedicated variant exists.
225    Other {
226        kind: String,
227        summary: String,
228        payloads: Vec<RawPayloadRef>,
229        /// Small structured metadata. Large data belongs in `payloads`.
230        metadata: Value,
231    },
232}
233
234impl RawTraceEventPayload {
235    /// Raw payload refs that must exist before this raw event is appended.
236    pub(crate) fn raw_payload_refs(&self) -> Vec<&RawPayloadRef> {
237        match self {
238            RawTraceEventPayload::RolloutStarted { .. }
239            | RawTraceEventPayload::RolloutEnded { .. }
240            | RawTraceEventPayload::ThreadEnded { .. }
241            | RawTraceEventPayload::CodexTurnStarted { .. }
242            | RawTraceEventPayload::CodexTurnEnded { .. }
243            | RawTraceEventPayload::CompactionRequestFailed { .. }
244            | RawTraceEventPayload::CodeCellStarted { .. }
245            | RawTraceEventPayload::McpToolCallCorrelationAssigned { .. }
246            | RawTraceEventPayload::AgentResultObserved {
247                carried_payload: None,
248                ..
249            } => Vec::new(),
250            RawTraceEventPayload::ThreadStarted {
251                metadata_payload, ..
252            } => metadata_payload.iter().collect(),
253            RawTraceEventPayload::InferenceStarted {
254                request_payload, ..
255            }
256            | RawTraceEventPayload::InferenceCompleted {
257                response_payload: request_payload,
258                ..
259            }
260            | RawTraceEventPayload::CompactionRequestStarted {
261                request_payload, ..
262            }
263            | RawTraceEventPayload::CompactionRequestCompleted {
264                response_payload: request_payload,
265                ..
266            }
267            | RawTraceEventPayload::CompactionInstalled {
268                checkpoint_payload: request_payload,
269                ..
270            }
271            | RawTraceEventPayload::ProtocolEventObserved {
272                event_payload: request_payload,
273                ..
274            } => vec![request_payload],
275            RawTraceEventPayload::InferenceFailed {
276                partial_response_payload,
277                ..
278            }
279            | RawTraceEventPayload::InferenceCancelled {
280                partial_response_payload,
281                ..
282            }
283            | RawTraceEventPayload::ToolCallStarted {
284                invocation_payload: partial_response_payload,
285                ..
286            }
287            | RawTraceEventPayload::ToolCallEnded {
288                result_payload: partial_response_payload,
289                ..
290            }
291            | RawTraceEventPayload::CodeCellInitialResponse {
292                response_payload: partial_response_payload,
293                ..
294            }
295            | RawTraceEventPayload::CodeCellEnded {
296                response_payload: partial_response_payload,
297                ..
298            } => partial_response_payload.iter().collect(),
299            RawTraceEventPayload::AgentResultObserved {
300                carried_payload: Some(carried_payload),
301                ..
302            } => vec![carried_payload],
303            RawTraceEventPayload::ToolCallRuntimeStarted {
304                runtime_payload, ..
305            }
306            | RawTraceEventPayload::ToolCallRuntimeEnded {
307                runtime_payload, ..
308            } => vec![runtime_payload],
309            RawTraceEventPayload::Other { payloads, .. } => payloads.iter().collect(),
310        }
311    }
312}