mirror of
https://github.com/openai/codex.git
synced 2026-10-31 19:28:49 +00:00
## Why MCP completion events can truncate large results and omit content removed for model consumption. Rollout traces need the original response, including content and metadata, as well as results for calls denied before reaching the backend. ## What changed - Record MCP runtime results before callbacks, content filtering, and UI truncation, and record skipped calls as failures. - Stop deriving MCP runtime completion records from protocol events to avoid duplicate records. - Treat MCP runtime payloads as opaque results when reducing agent interactions. - Buffer JSON trace writes and explicitly flush them. ## Testing Extend app-server tests to verify that traces retain oversized MCP text, audio, structured content, and metadata while UI results remain truncated, and that denied calls produce exactly one failed runtime result with the denial reason. GitOrigin-RevId: 57880770545eb5869420d7dc6fa4a15e481cae9d
573 lines
23 KiB
Rust
573 lines
23 KiB
Rust
//! Mapping from Codex protocol events into raw rollout-trace events.
|
|
//!
|
|
//! The session layer already emits protocol events for turn lifecycle, terminal
|
|
//! sessions, patch application, MCP calls, and collaboration tools. Rollout
|
|
//! tracing reuses those observations where they preserve the original payload.
|
|
//! MCP results are recorded before protocol-event truncation instead. This module
|
|
//! translates protocol events into the smaller trace vocabulary.
|
|
//!
|
|
//! The long explicit `EventMsg` matches are intentional. Most protocol events
|
|
//! are not trace runtime boundaries, but spelling them out makes new protocol
|
|
//! variants a compile-time prompt to decide whether the trace should capture
|
|
//! them.
|
|
|
|
use codex_protocol::protocol::EventMsg;
|
|
use codex_protocol::protocol::ExecCommandBeginEvent;
|
|
use codex_protocol::protocol::ExecCommandEndEvent;
|
|
use codex_protocol::protocol::ExecCommandSource;
|
|
use codex_protocol::protocol::ExecCommandStatus;
|
|
use codex_protocol::protocol::McpToolCallBeginEvent;
|
|
use codex_protocol::protocol::PatchApplyBeginEvent;
|
|
use codex_protocol::protocol::PatchApplyEndEvent;
|
|
use codex_protocol::protocol::PatchApplyStatus;
|
|
use codex_protocol::protocol::SubAgentActivityEvent;
|
|
use codex_protocol::protocol::SubAgentActivityKind;
|
|
use codex_protocol::protocol::TurnAbortReason;
|
|
use serde::Serialize;
|
|
use std::time::Duration;
|
|
|
|
use crate::AgentThreadId;
|
|
use crate::CodexTurnId;
|
|
use crate::ExecutionStatus;
|
|
use crate::RawTraceEventPayload;
|
|
use crate::ToolCallKind;
|
|
|
|
pub(crate) struct CodexTurnTraceEvent {
|
|
pub context_turn_id: CodexTurnId,
|
|
pub payload: RawTraceEventPayload,
|
|
}
|
|
|
|
pub(crate) fn codex_turn_trace_event(
|
|
thread_id: AgentThreadId,
|
|
default_turn_id: &str,
|
|
event: &EventMsg,
|
|
) -> Option<CodexTurnTraceEvent> {
|
|
match event {
|
|
EventMsg::TurnStarted(event) => {
|
|
let codex_turn_id = event.turn_id.clone();
|
|
Some(CodexTurnTraceEvent {
|
|
context_turn_id: codex_turn_id.clone(),
|
|
payload: RawTraceEventPayload::CodexTurnStarted {
|
|
codex_turn_id,
|
|
thread_id,
|
|
},
|
|
})
|
|
}
|
|
EventMsg::TurnComplete(event) => {
|
|
let codex_turn_id = event.turn_id.clone();
|
|
Some(CodexTurnTraceEvent {
|
|
context_turn_id: codex_turn_id.clone(),
|
|
payload: RawTraceEventPayload::CodexTurnEnded {
|
|
codex_turn_id,
|
|
status: if event.error.is_some() {
|
|
ExecutionStatus::Failed
|
|
} else {
|
|
ExecutionStatus::Completed
|
|
},
|
|
},
|
|
})
|
|
}
|
|
EventMsg::TurnAborted(event) => {
|
|
let codex_turn_id = event
|
|
.turn_id
|
|
.clone()
|
|
.unwrap_or_else(|| default_turn_id.to_string());
|
|
Some(CodexTurnTraceEvent {
|
|
context_turn_id: codex_turn_id.clone(),
|
|
payload: RawTraceEventPayload::CodexTurnEnded {
|
|
codex_turn_id,
|
|
status: execution_status_for_abort_reason(&event.reason),
|
|
},
|
|
})
|
|
}
|
|
EventMsg::RawResponseItem(event) => Some(CodexTurnTraceEvent {
|
|
context_turn_id: default_turn_id.to_string(),
|
|
payload: RawTraceEventPayload::HistoryItemAccepted {
|
|
item_id: event.item.id()?.to_string(),
|
|
},
|
|
}),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub(crate) enum ToolRuntimeTraceEvent<'a> {
|
|
Started {
|
|
tool_call_id: &'a str,
|
|
kind: ToolCallKind,
|
|
payload: ToolRuntimePayload<'a>,
|
|
},
|
|
Ended {
|
|
tool_call_id: &'a str,
|
|
status: ExecutionStatus,
|
|
payload: ToolRuntimePayload<'a>,
|
|
},
|
|
}
|
|
|
|
/// Borrowed protocol payload that should be persisted as tool runtime data.
|
|
///
|
|
/// The trace wants the exact protocol payload shape for E2E debugging, while
|
|
/// reducers consume the surrounding typed trace events. This enum lets the
|
|
/// recorder serialize the original event by reference, without first cloning it
|
|
/// or converting it through `serde_json::Value`.
|
|
pub(crate) enum ToolRuntimePayload<'a> {
|
|
ExecCommandBegin(&'a ExecCommandBeginEvent),
|
|
ExecCommandEnd(&'a ExecCommandEndEvent),
|
|
PatchApplyBegin(&'a PatchApplyBeginEvent),
|
|
PatchApplyEnd(&'a PatchApplyEndEvent),
|
|
McpToolCallBegin(&'a McpToolCallBeginEvent),
|
|
CollabAgentSpawnBegin(&'a codex_protocol::protocol::CollabAgentSpawnBeginEvent),
|
|
CollabAgentSpawnEnd(&'a codex_protocol::protocol::CollabAgentSpawnEndEvent),
|
|
CollabAgentInteractionBegin(&'a codex_protocol::protocol::CollabAgentInteractionBeginEvent),
|
|
CollabAgentInteractionEnd(&'a codex_protocol::protocol::CollabAgentInteractionEndEvent),
|
|
CollabWaitingBegin(&'a codex_protocol::protocol::CollabWaitingBeginEvent),
|
|
CollabWaitingEnd(&'a codex_protocol::protocol::CollabWaitingEndEvent),
|
|
CollabCloseBegin(&'a codex_protocol::protocol::CollabCloseBeginEvent),
|
|
CollabCloseEnd(&'a codex_protocol::protocol::CollabCloseEndEvent),
|
|
SubAgentActivity(&'a SubAgentActivityEvent),
|
|
}
|
|
|
|
impl Serialize for ToolRuntimePayload<'_> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: serde::Serializer,
|
|
{
|
|
match self {
|
|
ToolRuntimePayload::ExecCommandBegin(event) => {
|
|
ExecCommandBeginTracePayload::from(*event).serialize(serializer)
|
|
}
|
|
ToolRuntimePayload::ExecCommandEnd(event) => {
|
|
ExecCommandEndTracePayload::from(*event).serialize(serializer)
|
|
}
|
|
ToolRuntimePayload::PatchApplyBegin(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::PatchApplyEnd(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::McpToolCallBegin(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::CollabAgentSpawnBegin(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::CollabAgentSpawnEnd(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::CollabAgentInteractionBegin(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::CollabAgentInteractionEnd(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::CollabWaitingBegin(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::CollabWaitingEnd(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::CollabCloseBegin(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::CollabCloseEnd(event) => event.serialize(serializer),
|
|
ToolRuntimePayload::SubAgentActivity(event) => event.serialize(serializer),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Rollout-trace representation of an exec begin event.
|
|
///
|
|
/// Rollout traces share the rollout compatibility requirement that paths remain path-flavored
|
|
/// strings on disk, even though live events carry `PathUri` internally.
|
|
#[derive(Serialize)]
|
|
struct ExecCommandBeginTracePayload<'a> {
|
|
call_id: &'a str,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
plugin_id: Option<&'a str>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
script_path: Option<&'a str>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
process_id: Option<&'a str>,
|
|
turn_id: &'a str,
|
|
started_at_ms: i64,
|
|
command: &'a [String],
|
|
cwd: String,
|
|
parsed_cmd: &'a [codex_protocol::parse_command::ParsedCommand],
|
|
source: ExecCommandSource,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
interaction_input: Option<&'a str>,
|
|
}
|
|
|
|
impl<'a> From<&'a ExecCommandBeginEvent> for ExecCommandBeginTracePayload<'a> {
|
|
fn from(event: &'a ExecCommandBeginEvent) -> Self {
|
|
let ExecCommandBeginEvent {
|
|
call_id,
|
|
plugin_id,
|
|
script_path,
|
|
process_id,
|
|
turn_id,
|
|
started_at_ms,
|
|
command,
|
|
cwd,
|
|
parsed_cmd,
|
|
source,
|
|
interaction_input,
|
|
} = event;
|
|
Self {
|
|
call_id,
|
|
plugin_id: plugin_id.as_deref(),
|
|
script_path: script_path.as_deref(),
|
|
process_id: process_id.as_deref(),
|
|
turn_id,
|
|
started_at_ms: *started_at_ms,
|
|
command,
|
|
cwd: cwd.inferred_native_path_string(),
|
|
parsed_cmd,
|
|
source: *source,
|
|
interaction_input: interaction_input.as_deref(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Rollout-trace representation of an exec end event.
|
|
///
|
|
/// Like [`ExecCommandBeginTracePayload`], this renders `cwd` as an inferred native path to preserve
|
|
/// the on-disk format rather than serializing the internal `PathUri`.
|
|
#[derive(Serialize)]
|
|
struct ExecCommandEndTracePayload<'a> {
|
|
call_id: &'a str,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
plugin_id: Option<&'a str>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
script_path: Option<&'a str>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
process_id: Option<&'a str>,
|
|
turn_id: &'a str,
|
|
completed_at_ms: i64,
|
|
command: &'a [String],
|
|
cwd: String,
|
|
parsed_cmd: &'a [codex_protocol::parse_command::ParsedCommand],
|
|
source: ExecCommandSource,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
interaction_input: Option<&'a str>,
|
|
aggregated_output: &'a str,
|
|
exit_code: i32,
|
|
duration: Duration,
|
|
status: &'a ExecCommandStatus,
|
|
}
|
|
|
|
impl<'a> From<&'a ExecCommandEndEvent> for ExecCommandEndTracePayload<'a> {
|
|
fn from(event: &'a ExecCommandEndEvent) -> Self {
|
|
let ExecCommandEndEvent {
|
|
call_id,
|
|
plugin_id,
|
|
script_path,
|
|
process_id,
|
|
turn_id,
|
|
completed_at_ms,
|
|
command,
|
|
cwd,
|
|
parsed_cmd,
|
|
source,
|
|
interaction_input,
|
|
aggregated_output,
|
|
exit_code,
|
|
duration,
|
|
status,
|
|
} = event;
|
|
Self {
|
|
call_id,
|
|
plugin_id: plugin_id.as_deref(),
|
|
script_path: script_path.as_deref(),
|
|
process_id: process_id.as_deref(),
|
|
turn_id,
|
|
completed_at_ms: *completed_at_ms,
|
|
command,
|
|
cwd: cwd.inferred_native_path_string(),
|
|
parsed_cmd,
|
|
source: *source,
|
|
interaction_input: interaction_input.as_deref(),
|
|
aggregated_output,
|
|
exit_code: *exit_code,
|
|
duration: *duration,
|
|
status,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn tool_runtime_trace_event(event: &EventMsg) -> Option<ToolRuntimeTraceEvent<'_>> {
|
|
match event {
|
|
EventMsg::ExecCommandBegin(event) if event.source != ExecCommandSource::UserShell => {
|
|
Some(ToolRuntimeTraceEvent::Started {
|
|
tool_call_id: &event.call_id,
|
|
kind: match event.source {
|
|
ExecCommandSource::UnifiedExecInteraction => ToolCallKind::WriteStdin,
|
|
ExecCommandSource::Agent
|
|
| ExecCommandSource::UserShell
|
|
| ExecCommandSource::UnifiedExecStartup => ToolCallKind::ExecCommand,
|
|
},
|
|
payload: ToolRuntimePayload::ExecCommandBegin(event),
|
|
})
|
|
}
|
|
EventMsg::ExecCommandEnd(event) if event.source != ExecCommandSource::UserShell => {
|
|
Some(ToolRuntimeTraceEvent::Ended {
|
|
tool_call_id: &event.call_id,
|
|
status: event.status.trace_execution_status(),
|
|
payload: ToolRuntimePayload::ExecCommandEnd(event),
|
|
})
|
|
}
|
|
EventMsg::PatchApplyBegin(event) => Some(ToolRuntimeTraceEvent::Started {
|
|
tool_call_id: &event.call_id,
|
|
kind: ToolCallKind::ApplyPatch,
|
|
payload: ToolRuntimePayload::PatchApplyBegin(event),
|
|
}),
|
|
EventMsg::PatchApplyEnd(event) => Some(ToolRuntimeTraceEvent::Ended {
|
|
tool_call_id: &event.call_id,
|
|
status: event.status.trace_execution_status(),
|
|
payload: ToolRuntimePayload::PatchApplyEnd(event),
|
|
}),
|
|
EventMsg::McpToolCallBegin(event) => Some(ToolRuntimeTraceEvent::Started {
|
|
tool_call_id: &event.call_id,
|
|
kind: ToolCallKind::Mcp {
|
|
server: event.invocation.server.clone(),
|
|
tool: event.invocation.tool.clone(),
|
|
},
|
|
payload: ToolRuntimePayload::McpToolCallBegin(event),
|
|
}),
|
|
// The full backend result is recorded before this UI event can truncate it.
|
|
EventMsg::McpToolCallEnd(_) => None,
|
|
EventMsg::CollabAgentSpawnBegin(event) => Some(ToolRuntimeTraceEvent::Started {
|
|
tool_call_id: &event.call_id,
|
|
kind: ToolCallKind::SpawnAgent,
|
|
payload: ToolRuntimePayload::CollabAgentSpawnBegin(event),
|
|
}),
|
|
EventMsg::CollabAgentSpawnEnd(event) => Some(ToolRuntimeTraceEvent::Ended {
|
|
tool_call_id: &event.call_id,
|
|
// A spawn end without a child thread id means the runtime boundary
|
|
// finished without creating the requested child thread.
|
|
status: if event.new_thread_id.is_some() {
|
|
ExecutionStatus::Completed
|
|
} else {
|
|
ExecutionStatus::Failed
|
|
},
|
|
payload: ToolRuntimePayload::CollabAgentSpawnEnd(event),
|
|
}),
|
|
EventMsg::CollabAgentInteractionBegin(event) => Some(ToolRuntimeTraceEvent::Started {
|
|
tool_call_id: &event.call_id,
|
|
kind: ToolCallKind::SendMessage,
|
|
payload: ToolRuntimePayload::CollabAgentInteractionBegin(event),
|
|
}),
|
|
EventMsg::CollabAgentInteractionEnd(event) => Some(ToolRuntimeTraceEvent::Ended {
|
|
tool_call_id: &event.call_id,
|
|
status: ExecutionStatus::Completed,
|
|
payload: ToolRuntimePayload::CollabAgentInteractionEnd(event),
|
|
}),
|
|
EventMsg::CollabWaitingBegin(event) => Some(ToolRuntimeTraceEvent::Started {
|
|
tool_call_id: &event.call_id,
|
|
kind: ToolCallKind::WaitAgent,
|
|
payload: ToolRuntimePayload::CollabWaitingBegin(event),
|
|
}),
|
|
EventMsg::CollabWaitingEnd(event) => Some(ToolRuntimeTraceEvent::Ended {
|
|
tool_call_id: &event.call_id,
|
|
status: ExecutionStatus::Completed,
|
|
payload: ToolRuntimePayload::CollabWaitingEnd(event),
|
|
}),
|
|
EventMsg::CollabCloseBegin(event) => Some(ToolRuntimeTraceEvent::Started {
|
|
tool_call_id: &event.call_id,
|
|
kind: ToolCallKind::CloseAgent,
|
|
payload: ToolRuntimePayload::CollabCloseBegin(event),
|
|
}),
|
|
EventMsg::CollabCloseEnd(event) => Some(ToolRuntimeTraceEvent::Ended {
|
|
tool_call_id: &event.call_id,
|
|
status: ExecutionStatus::Completed,
|
|
payload: ToolRuntimePayload::CollabCloseEnd(event),
|
|
}),
|
|
EventMsg::SubAgentActivity(event) if event.kind != SubAgentActivityKind::Completed => {
|
|
Some(ToolRuntimeTraceEvent::Ended {
|
|
tool_call_id: &event.event_id,
|
|
status: ExecutionStatus::Completed,
|
|
payload: ToolRuntimePayload::SubAgentActivity(event),
|
|
})
|
|
}
|
|
EventMsg::SubAgentActivity(_) => None,
|
|
EventMsg::Error(_)
|
|
| EventMsg::Warning(_)
|
|
| EventMsg::AuthRecoveryStarted(_)
|
|
| EventMsg::AuthRecoveryCompleted(_)
|
|
| EventMsg::GuardianWarning(_)
|
|
| EventMsg::SafetyBuffering(_)
|
|
| EventMsg::RealtimeConversationStarted(_)
|
|
| EventMsg::RealtimeConversationRealtime(_)
|
|
| EventMsg::RealtimeConversationClosed(_)
|
|
| EventMsg::RealtimeConversationSdp(_)
|
|
| EventMsg::ModelReroute(_)
|
|
| EventMsg::ModelVerification(_)
|
|
| EventMsg::TurnModerationMetadata(_)
|
|
| EventMsg::ContextCompacted(_)
|
|
| EventMsg::ThreadRolledBack(_)
|
|
| EventMsg::ThreadGoalUpdated(_)
|
|
| EventMsg::ThreadQueueChanged(_)
|
|
| EventMsg::TurnStarted(_)
|
|
| EventMsg::ThreadSettingsApplied(_)
|
|
| EventMsg::TurnComplete(_)
|
|
| EventMsg::TokenCount(_)
|
|
| EventMsg::AgentMessage(_)
|
|
| EventMsg::UserMessage(_)
|
|
| EventMsg::AgentReasoning(_)
|
|
| EventMsg::AgentReasoningRawContent(_)
|
|
| EventMsg::AgentReasoningSectionBreak(_)
|
|
| EventMsg::SessionConfigured(_)
|
|
| EventMsg::EnvironmentConnected(_)
|
|
| EventMsg::EnvironmentDisconnected(_)
|
|
| EventMsg::McpStartupUpdate(_)
|
|
| EventMsg::McpStartupComplete(_)
|
|
| EventMsg::WebSearchBegin(_)
|
|
| EventMsg::WebSearchEnd(_)
|
|
| EventMsg::ImageGenerationBegin(_)
|
|
| EventMsg::ImageGenerationEnd(_)
|
|
| EventMsg::ViewImageToolCall(_)
|
|
| EventMsg::ExecCommandBegin(_)
|
|
| EventMsg::ExecCommandOutputDelta(_)
|
|
| EventMsg::TerminalInteraction(_)
|
|
| EventMsg::ExecCommandEnd(_)
|
|
| EventMsg::ExecApprovalRequest(_)
|
|
| EventMsg::RequestPermissions(_)
|
|
| EventMsg::RequestUserInput(_)
|
|
| EventMsg::DynamicToolCallRequest(_)
|
|
| EventMsg::DynamicToolCallResponse(_)
|
|
| EventMsg::ElicitationRequest(_)
|
|
| EventMsg::ElicitationAbandoned(_)
|
|
| EventMsg::ApplyPatchApprovalRequest(_)
|
|
| EventMsg::GuardianAssessment(_)
|
|
| EventMsg::DeprecationNotice(_)
|
|
| EventMsg::StreamError(_)
|
|
| EventMsg::PatchApplyUpdated(_)
|
|
| EventMsg::TurnDiff(_)
|
|
| EventMsg::RealtimeConversationListVoicesResponse(_)
|
|
| EventMsg::PlanUpdate(_)
|
|
| EventMsg::TurnAborted(_)
|
|
| EventMsg::ShutdownComplete
|
|
| EventMsg::EnteredReviewMode(_)
|
|
| EventMsg::ExitedReviewMode(_)
|
|
| EventMsg::PrivateSessionEvent(_)
|
|
| EventMsg::RawResponseItem(_)
|
|
| EventMsg::RawResponseCompleted(_)
|
|
| EventMsg::ItemStarted(_)
|
|
| EventMsg::ItemCompleted(_)
|
|
| EventMsg::HookStarted(_)
|
|
| EventMsg::HookCompleted(_)
|
|
| EventMsg::AgentMessageContentDelta(_)
|
|
| EventMsg::PlanDelta(_)
|
|
| EventMsg::ReasoningContentDelta(_)
|
|
| EventMsg::ReasoningRawContentDelta(_)
|
|
| EventMsg::CollabResumeBegin(_)
|
|
| EventMsg::CollabResumeEnd(_) => None,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn wrapped_protocol_event_type(event: &EventMsg) -> Option<&'static str> {
|
|
match event {
|
|
EventMsg::SessionConfigured(_) => Some("session_configured"),
|
|
EventMsg::TurnStarted(_) => Some("turn_started"),
|
|
EventMsg::TurnComplete(_) => Some("turn_complete"),
|
|
EventMsg::TurnAborted(_) => Some("turn_aborted"),
|
|
EventMsg::ThreadRolledBack(_) => Some("thread_rolled_back"),
|
|
EventMsg::Error(_) => Some("error"),
|
|
EventMsg::Warning(_) => Some("warning"),
|
|
EventMsg::ShutdownComplete => Some("shutdown_complete"),
|
|
EventMsg::AuthRecoveryStarted(_)
|
|
| EventMsg::AuthRecoveryCompleted(_)
|
|
| EventMsg::GuardianWarning(_)
|
|
| EventMsg::SafetyBuffering(_)
|
|
| EventMsg::RealtimeConversationStarted(_)
|
|
| EventMsg::RealtimeConversationRealtime(_)
|
|
| EventMsg::RealtimeConversationClosed(_)
|
|
| EventMsg::RealtimeConversationSdp(_)
|
|
| EventMsg::ModelReroute(_)
|
|
| EventMsg::ModelVerification(_)
|
|
| EventMsg::TurnModerationMetadata(_)
|
|
| EventMsg::ContextCompacted(_)
|
|
| EventMsg::ThreadSettingsApplied(_)
|
|
| EventMsg::EnvironmentConnected(_)
|
|
| EventMsg::EnvironmentDisconnected(_)
|
|
| EventMsg::TokenCount(_)
|
|
| EventMsg::AgentMessage(_)
|
|
| EventMsg::UserMessage(_)
|
|
| EventMsg::AgentReasoning(_)
|
|
| EventMsg::AgentReasoningRawContent(_)
|
|
| EventMsg::AgentReasoningSectionBreak(_)
|
|
| EventMsg::ThreadGoalUpdated(_)
|
|
| EventMsg::ThreadQueueChanged(_)
|
|
| EventMsg::McpStartupUpdate(_)
|
|
| EventMsg::McpStartupComplete(_)
|
|
| EventMsg::McpToolCallBegin(_)
|
|
| EventMsg::McpToolCallEnd(_)
|
|
| EventMsg::WebSearchBegin(_)
|
|
| EventMsg::WebSearchEnd(_)
|
|
| EventMsg::ImageGenerationBegin(_)
|
|
| EventMsg::ImageGenerationEnd(_)
|
|
| EventMsg::ViewImageToolCall(_)
|
|
| EventMsg::ExecCommandBegin(_)
|
|
| EventMsg::ExecCommandOutputDelta(_)
|
|
| EventMsg::TerminalInteraction(_)
|
|
| EventMsg::ExecCommandEnd(_)
|
|
| EventMsg::ExecApprovalRequest(_)
|
|
| EventMsg::RequestPermissions(_)
|
|
| EventMsg::RequestUserInput(_)
|
|
| EventMsg::DynamicToolCallRequest(_)
|
|
| EventMsg::DynamicToolCallResponse(_)
|
|
| EventMsg::ElicitationRequest(_)
|
|
| EventMsg::ElicitationAbandoned(_)
|
|
| EventMsg::ApplyPatchApprovalRequest(_)
|
|
| EventMsg::GuardianAssessment(_)
|
|
| EventMsg::DeprecationNotice(_)
|
|
| EventMsg::StreamError(_)
|
|
| EventMsg::PatchApplyBegin(_)
|
|
| EventMsg::PatchApplyUpdated(_)
|
|
| EventMsg::PatchApplyEnd(_)
|
|
| EventMsg::TurnDiff(_)
|
|
| EventMsg::RealtimeConversationListVoicesResponse(_)
|
|
| EventMsg::PlanUpdate(_)
|
|
| EventMsg::EnteredReviewMode(_)
|
|
| EventMsg::ExitedReviewMode(_)
|
|
| EventMsg::PrivateSessionEvent(_)
|
|
| EventMsg::RawResponseItem(_)
|
|
| EventMsg::RawResponseCompleted(_)
|
|
| EventMsg::ItemStarted(_)
|
|
| EventMsg::ItemCompleted(_)
|
|
| EventMsg::HookStarted(_)
|
|
| EventMsg::HookCompleted(_)
|
|
| EventMsg::AgentMessageContentDelta(_)
|
|
| EventMsg::PlanDelta(_)
|
|
| EventMsg::ReasoningContentDelta(_)
|
|
| EventMsg::ReasoningRawContentDelta(_)
|
|
| EventMsg::CollabAgentSpawnBegin(_)
|
|
| EventMsg::CollabAgentSpawnEnd(_)
|
|
| EventMsg::CollabAgentInteractionBegin(_)
|
|
| EventMsg::CollabAgentInteractionEnd(_)
|
|
| EventMsg::CollabWaitingBegin(_)
|
|
| EventMsg::CollabWaitingEnd(_)
|
|
| EventMsg::CollabCloseBegin(_)
|
|
| EventMsg::CollabCloseEnd(_)
|
|
| EventMsg::CollabResumeBegin(_)
|
|
| EventMsg::CollabResumeEnd(_)
|
|
| EventMsg::SubAgentActivity(_) => None,
|
|
}
|
|
}
|
|
|
|
trait TraceExecutionStatus {
|
|
fn trace_execution_status(&self) -> ExecutionStatus;
|
|
}
|
|
|
|
impl TraceExecutionStatus for ExecCommandStatus {
|
|
fn trace_execution_status(&self) -> ExecutionStatus {
|
|
match self {
|
|
ExecCommandStatus::Completed => ExecutionStatus::Completed,
|
|
ExecCommandStatus::Failed => ExecutionStatus::Failed,
|
|
ExecCommandStatus::Declined => ExecutionStatus::Cancelled,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TraceExecutionStatus for PatchApplyStatus {
|
|
fn trace_execution_status(&self) -> ExecutionStatus {
|
|
match self {
|
|
PatchApplyStatus::Completed => ExecutionStatus::Completed,
|
|
PatchApplyStatus::Failed => ExecutionStatus::Failed,
|
|
PatchApplyStatus::Declined => ExecutionStatus::Cancelled,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn execution_status_for_abort_reason(reason: &TurnAbortReason) -> ExecutionStatus {
|
|
match reason {
|
|
TurnAbortReason::Interrupted
|
|
| TurnAbortReason::Replaced
|
|
| TurnAbortReason::ReviewEnded
|
|
| TurnAbortReason::BudgetLimited => ExecutionStatus::Cancelled,
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "protocol_event_tests.rs"]
|
|
mod tests;
|