mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
refactor(protocol): isolate legacy item fanout (#30956)
## Stack 1. [#30956](https://github.com/openai/codex/pull/30956) — isolate legacy item fanout ← **this PR** 2. [#30283](https://github.com/openai/codex/pull/30283) — emit canonical `TurnItem` lifecycle 3. [#30188](https://github.com/openai/codex/pull/30188) — persist canonical items for paginated threads ## Description Move legacy `EventMsg` projection code out of the canonical item and protocol schema modules into `protocol/src/legacy_events.rs`. This is a behavior-neutral extraction. It keeps the existing `HasLegacyEvent` API and the existing legacy projections unchanged, while giving compatibility fanout a single home. ## Why Canonical `TurnItem` types and wire event schemas should not own the implementation details for legacy compatibility projections. Isolating that code makes the boundary explicit and keeps follow-up canonical lifecycle work easier to review.
This commit is contained in:
@@ -10,26 +10,12 @@ use crate::models::ResponseItem;
|
||||
use crate::models::WebSearchAction;
|
||||
use crate::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use crate::parse_command::ParsedCommand;
|
||||
use crate::protocol::AgentMessageEvent;
|
||||
use crate::protocol::AgentReasoningEvent;
|
||||
use crate::protocol::AgentReasoningRawContentEvent;
|
||||
use crate::protocol::AgentStatus;
|
||||
use crate::protocol::CollabAgentRef;
|
||||
use crate::protocol::ContextCompactedEvent;
|
||||
use crate::protocol::EventMsg;
|
||||
use crate::protocol::ExecCommandSource;
|
||||
use crate::protocol::FileChange;
|
||||
use crate::protocol::ImageGenerationEndEvent;
|
||||
use crate::protocol::McpInvocation;
|
||||
use crate::protocol::McpToolCallBeginEvent;
|
||||
use crate::protocol::McpToolCallEndEvent;
|
||||
use crate::protocol::PatchApplyBeginEvent;
|
||||
use crate::protocol::PatchApplyEndEvent;
|
||||
use crate::protocol::PatchApplyStatus;
|
||||
use crate::protocol::SubAgentActivityKind;
|
||||
use crate::protocol::UserMessageEvent;
|
||||
use crate::protocol::ViewImageToolCallEvent;
|
||||
use crate::protocol::WebSearchEndEvent;
|
||||
use crate::user_input::ByteRange;
|
||||
use crate::user_input::TextElement;
|
||||
use crate::user_input::UserInput;
|
||||
@@ -387,10 +373,6 @@ impl ContextCompactionItem {
|
||||
id: uuid::Uuid::new_v4().to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_legacy_event(&self) -> EventMsg {
|
||||
EventMsg::ContextCompacted(ContextCompactedEvent {})
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ContextCompactionItem {
|
||||
@@ -408,20 +390,6 @@ impl UserMessageItem {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_legacy_event(&self) -> EventMsg {
|
||||
// Legacy user-message events flatten only text inputs into `message` and
|
||||
// rebase text element ranges onto that concatenated text.
|
||||
EventMsg::UserMessage(UserMessageEvent {
|
||||
client_id: self.client_id.clone(),
|
||||
message: self.message(),
|
||||
images: Some(self.image_urls()),
|
||||
image_details: self.image_details(),
|
||||
local_images: self.local_image_paths(),
|
||||
local_image_details: self.local_image_details(),
|
||||
text_elements: self.text_elements(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn message(&self) -> String {
|
||||
self.content
|
||||
.iter()
|
||||
@@ -609,134 +577,6 @@ impl AgentMessageItem {
|
||||
memory_citation: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_legacy_events(&self) -> Vec<EventMsg> {
|
||||
self.content
|
||||
.iter()
|
||||
.map(|c| match c {
|
||||
AgentMessageContent::Text { text } => EventMsg::AgentMessage(AgentMessageEvent {
|
||||
message: text.clone(),
|
||||
phase: self.phase.clone(),
|
||||
memory_citation: self.memory_citation.clone(),
|
||||
}),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl ReasoningItem {
|
||||
pub fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg> {
|
||||
let mut events = Vec::new();
|
||||
for summary in &self.summary_text {
|
||||
events.push(EventMsg::AgentReasoning(AgentReasoningEvent {
|
||||
text: summary.clone(),
|
||||
}));
|
||||
}
|
||||
|
||||
if show_raw_agent_reasoning {
|
||||
for entry in &self.raw_content {
|
||||
events.push(EventMsg::AgentReasoningRawContent(
|
||||
AgentReasoningRawContentEvent {
|
||||
text: entry.clone(),
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
events
|
||||
}
|
||||
}
|
||||
|
||||
impl WebSearchItem {
|
||||
pub fn as_legacy_event(&self) -> EventMsg {
|
||||
EventMsg::WebSearchEnd(WebSearchEndEvent {
|
||||
call_id: self.id.clone(),
|
||||
query: self.query.clone(),
|
||||
action: self.action.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ImageGenerationItem {
|
||||
pub fn as_legacy_event(&self) -> EventMsg {
|
||||
EventMsg::ImageGenerationEnd(ImageGenerationEndEvent {
|
||||
call_id: self.id.clone(),
|
||||
status: self.status.clone(),
|
||||
revised_prompt: self.revised_prompt.clone(),
|
||||
result: self.result.clone(),
|
||||
saved_path: self.saved_path.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FileChangeItem {
|
||||
pub fn as_legacy_begin_event(&self, turn_id: String) -> EventMsg {
|
||||
EventMsg::PatchApplyBegin(PatchApplyBeginEvent {
|
||||
call_id: self.id.clone(),
|
||||
turn_id,
|
||||
auto_approved: self.auto_approved.unwrap_or(false),
|
||||
changes: self.changes.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn as_legacy_end_event(&self, turn_id: String) -> Option<EventMsg> {
|
||||
let status = self.status.clone()?;
|
||||
Some(EventMsg::PatchApplyEnd(PatchApplyEndEvent {
|
||||
call_id: self.id.clone(),
|
||||
turn_id,
|
||||
stdout: self.stdout.clone().unwrap_or_default(),
|
||||
stderr: self.stderr.clone().unwrap_or_default(),
|
||||
success: status == PatchApplyStatus::Completed,
|
||||
changes: self.changes.clone(),
|
||||
status,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl McpToolCallItem {
|
||||
pub fn as_legacy_begin_event(&self) -> EventMsg {
|
||||
EventMsg::McpToolCallBegin(McpToolCallBeginEvent {
|
||||
call_id: self.id.clone(),
|
||||
invocation: McpInvocation {
|
||||
server: self.server.clone(),
|
||||
tool: self.tool.clone(),
|
||||
arguments: (!self.arguments.is_null()).then(|| self.arguments.clone()),
|
||||
},
|
||||
connector_id: self.connector_id.clone(),
|
||||
mcp_app_resource_uri: self.mcp_app_resource_uri.clone(),
|
||||
link_id: self.link_id.clone(),
|
||||
app_name: self.app_name.clone(),
|
||||
template_id: self.template_id.clone(),
|
||||
action_name: self.action_name.clone(),
|
||||
plugin_id: self.plugin_id.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn as_legacy_end_event(&self) -> Option<EventMsg> {
|
||||
let result = match (&self.result, &self.error) {
|
||||
(Some(result), _) => Ok(result.clone()),
|
||||
(None, Some(error)) => Err(error.message.clone()),
|
||||
(None, None) => return None,
|
||||
};
|
||||
|
||||
Some(EventMsg::McpToolCallEnd(McpToolCallEndEvent {
|
||||
call_id: self.id.clone(),
|
||||
invocation: McpInvocation {
|
||||
server: self.server.clone(),
|
||||
tool: self.tool.clone(),
|
||||
arguments: (!self.arguments.is_null()).then(|| self.arguments.clone()),
|
||||
},
|
||||
mcp_app_resource_uri: self.mcp_app_resource_uri.clone(),
|
||||
connector_id: self.connector_id.clone(),
|
||||
link_id: self.link_id.clone(),
|
||||
app_name: self.app_name.clone(),
|
||||
template_id: self.template_id.clone(),
|
||||
action_name: self.action_name.clone(),
|
||||
plugin_id: self.plugin_id.clone(),
|
||||
duration: self.duration?,
|
||||
result,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl TurnItem {
|
||||
@@ -760,35 +600,6 @@ impl TurnItem {
|
||||
TurnItem::ContextCompaction(item) => item.id.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg> {
|
||||
match self {
|
||||
TurnItem::UserMessage(item) => vec![item.as_legacy_event()],
|
||||
TurnItem::HookPrompt(_) => Vec::new(),
|
||||
TurnItem::AgentMessage(item) => item.as_legacy_events(),
|
||||
TurnItem::Plan(_) => Vec::new(),
|
||||
TurnItem::CommandExecution(_)
|
||||
| TurnItem::DynamicToolCall(_)
|
||||
| TurnItem::CollabAgentToolCall(_) => Vec::new(),
|
||||
TurnItem::SubAgentActivity(_) => Vec::new(),
|
||||
TurnItem::WebSearch(item) => vec![item.as_legacy_event()],
|
||||
TurnItem::ImageView(item) => {
|
||||
vec![EventMsg::ViewImageToolCall(ViewImageToolCallEvent {
|
||||
call_id: item.id.clone(),
|
||||
path: item.path.clone(),
|
||||
})]
|
||||
}
|
||||
TurnItem::Sleep(_) => Vec::new(),
|
||||
TurnItem::ImageGeneration(item) => vec![item.as_legacy_event()],
|
||||
TurnItem::FileChange(item) => item
|
||||
.as_legacy_end_event(String::new())
|
||||
.into_iter()
|
||||
.collect(),
|
||||
TurnItem::McpToolCall(item) => item.as_legacy_end_event().into_iter().collect(),
|
||||
TurnItem::Reasoning(item) => item.as_legacy_events(show_raw_agent_reasoning),
|
||||
TurnItem::ContextCompaction(item) => vec![item.as_legacy_event()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
use crate::items::AgentMessageContent;
|
||||
use crate::items::AgentMessageItem;
|
||||
use crate::items::ContextCompactionItem;
|
||||
use crate::items::FileChangeItem;
|
||||
use crate::items::ImageGenerationItem;
|
||||
use crate::items::McpToolCallItem;
|
||||
use crate::items::ReasoningItem;
|
||||
use crate::items::TurnItem;
|
||||
use crate::items::UserMessageItem;
|
||||
use crate::items::WebSearchItem;
|
||||
use crate::protocol::AgentMessageContentDeltaEvent;
|
||||
use crate::protocol::AgentMessageEvent;
|
||||
use crate::protocol::AgentReasoningEvent;
|
||||
use crate::protocol::AgentReasoningRawContentEvent;
|
||||
use crate::protocol::ContextCompactedEvent;
|
||||
use crate::protocol::EventMsg;
|
||||
use crate::protocol::ImageGenerationBeginEvent;
|
||||
use crate::protocol::ImageGenerationEndEvent;
|
||||
use crate::protocol::ItemCompletedEvent;
|
||||
use crate::protocol::ItemStartedEvent;
|
||||
use crate::protocol::McpInvocation;
|
||||
use crate::protocol::McpToolCallBeginEvent;
|
||||
use crate::protocol::McpToolCallEndEvent;
|
||||
use crate::protocol::PatchApplyBeginEvent;
|
||||
use crate::protocol::PatchApplyEndEvent;
|
||||
use crate::protocol::PatchApplyStatus;
|
||||
use crate::protocol::ReasoningContentDeltaEvent;
|
||||
use crate::protocol::ReasoningRawContentDeltaEvent;
|
||||
use crate::protocol::UserMessageEvent;
|
||||
use crate::protocol::ViewImageToolCallEvent;
|
||||
use crate::protocol::WebSearchBeginEvent;
|
||||
use crate::protocol::WebSearchEndEvent;
|
||||
|
||||
/// Converts canonical item lifecycle events back into the legacy raw event stream used by
|
||||
/// compatibility consumers that have not migrated to `TurnItem`.
|
||||
pub trait HasLegacyEvent {
|
||||
fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg>;
|
||||
}
|
||||
|
||||
impl ContextCompactionItem {
|
||||
pub fn as_legacy_event(&self) -> EventMsg {
|
||||
EventMsg::ContextCompacted(ContextCompactedEvent {})
|
||||
}
|
||||
}
|
||||
|
||||
impl UserMessageItem {
|
||||
pub fn as_legacy_event(&self) -> EventMsg {
|
||||
// Legacy user-message events flatten only text inputs into `message` and
|
||||
// rebase text element ranges onto that concatenated text.
|
||||
EventMsg::UserMessage(UserMessageEvent {
|
||||
client_id: self.client_id.clone(),
|
||||
message: self.message(),
|
||||
images: Some(self.image_urls()),
|
||||
image_details: self.image_details(),
|
||||
local_images: self.local_image_paths(),
|
||||
local_image_details: self.local_image_details(),
|
||||
text_elements: self.text_elements(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AgentMessageItem {
|
||||
pub fn as_legacy_events(&self) -> Vec<EventMsg> {
|
||||
self.content
|
||||
.iter()
|
||||
.map(|c| match c {
|
||||
AgentMessageContent::Text { text } => EventMsg::AgentMessage(AgentMessageEvent {
|
||||
message: text.clone(),
|
||||
phase: self.phase.clone(),
|
||||
memory_citation: self.memory_citation.clone(),
|
||||
}),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl ReasoningItem {
|
||||
pub fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg> {
|
||||
let mut events = Vec::new();
|
||||
for summary in &self.summary_text {
|
||||
events.push(EventMsg::AgentReasoning(AgentReasoningEvent {
|
||||
text: summary.clone(),
|
||||
}));
|
||||
}
|
||||
|
||||
if show_raw_agent_reasoning {
|
||||
for entry in &self.raw_content {
|
||||
events.push(EventMsg::AgentReasoningRawContent(
|
||||
AgentReasoningRawContentEvent {
|
||||
text: entry.clone(),
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
events
|
||||
}
|
||||
}
|
||||
|
||||
impl WebSearchItem {
|
||||
pub fn as_legacy_event(&self) -> EventMsg {
|
||||
EventMsg::WebSearchEnd(WebSearchEndEvent {
|
||||
call_id: self.id.clone(),
|
||||
query: self.query.clone(),
|
||||
action: self.action.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ImageGenerationItem {
|
||||
pub fn as_legacy_event(&self) -> EventMsg {
|
||||
EventMsg::ImageGenerationEnd(ImageGenerationEndEvent {
|
||||
call_id: self.id.clone(),
|
||||
status: self.status.clone(),
|
||||
revised_prompt: self.revised_prompt.clone(),
|
||||
result: self.result.clone(),
|
||||
saved_path: self.saved_path.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FileChangeItem {
|
||||
pub fn as_legacy_begin_event(&self, turn_id: String) -> EventMsg {
|
||||
EventMsg::PatchApplyBegin(PatchApplyBeginEvent {
|
||||
call_id: self.id.clone(),
|
||||
turn_id,
|
||||
auto_approved: self.auto_approved.unwrap_or(false),
|
||||
changes: self.changes.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn as_legacy_end_event(&self, turn_id: String) -> Option<EventMsg> {
|
||||
let status = self.status.clone()?;
|
||||
Some(EventMsg::PatchApplyEnd(PatchApplyEndEvent {
|
||||
call_id: self.id.clone(),
|
||||
turn_id,
|
||||
stdout: self.stdout.clone().unwrap_or_default(),
|
||||
stderr: self.stderr.clone().unwrap_or_default(),
|
||||
success: status == PatchApplyStatus::Completed,
|
||||
changes: self.changes.clone(),
|
||||
status,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl McpToolCallItem {
|
||||
pub fn as_legacy_begin_event(&self) -> EventMsg {
|
||||
EventMsg::McpToolCallBegin(McpToolCallBeginEvent {
|
||||
call_id: self.id.clone(),
|
||||
invocation: McpInvocation {
|
||||
server: self.server.clone(),
|
||||
tool: self.tool.clone(),
|
||||
arguments: (!self.arguments.is_null()).then(|| self.arguments.clone()),
|
||||
},
|
||||
connector_id: self.connector_id.clone(),
|
||||
mcp_app_resource_uri: self.mcp_app_resource_uri.clone(),
|
||||
link_id: self.link_id.clone(),
|
||||
app_name: self.app_name.clone(),
|
||||
template_id: self.template_id.clone(),
|
||||
action_name: self.action_name.clone(),
|
||||
plugin_id: self.plugin_id.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn as_legacy_end_event(&self) -> Option<EventMsg> {
|
||||
let result = match (&self.result, &self.error) {
|
||||
(Some(result), _) => Ok(result.clone()),
|
||||
(None, Some(error)) => Err(error.message.clone()),
|
||||
(None, None) => return None,
|
||||
};
|
||||
|
||||
Some(EventMsg::McpToolCallEnd(McpToolCallEndEvent {
|
||||
call_id: self.id.clone(),
|
||||
invocation: McpInvocation {
|
||||
server: self.server.clone(),
|
||||
tool: self.tool.clone(),
|
||||
arguments: (!self.arguments.is_null()).then(|| self.arguments.clone()),
|
||||
},
|
||||
mcp_app_resource_uri: self.mcp_app_resource_uri.clone(),
|
||||
connector_id: self.connector_id.clone(),
|
||||
link_id: self.link_id.clone(),
|
||||
app_name: self.app_name.clone(),
|
||||
template_id: self.template_id.clone(),
|
||||
action_name: self.action_name.clone(),
|
||||
plugin_id: self.plugin_id.clone(),
|
||||
duration: self.duration?,
|
||||
result,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl TurnItem {
|
||||
pub fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg> {
|
||||
match self {
|
||||
TurnItem::UserMessage(item) => vec![item.as_legacy_event()],
|
||||
TurnItem::HookPrompt(_) => Vec::new(),
|
||||
TurnItem::AgentMessage(item) => item.as_legacy_events(),
|
||||
TurnItem::Plan(_) => Vec::new(),
|
||||
TurnItem::CommandExecution(_)
|
||||
| TurnItem::DynamicToolCall(_)
|
||||
| TurnItem::CollabAgentToolCall(_) => Vec::new(),
|
||||
TurnItem::SubAgentActivity(_) => Vec::new(),
|
||||
TurnItem::WebSearch(item) => vec![item.as_legacy_event()],
|
||||
TurnItem::ImageView(item) => {
|
||||
vec![EventMsg::ViewImageToolCall(ViewImageToolCallEvent {
|
||||
call_id: item.id.clone(),
|
||||
path: item.path.clone(),
|
||||
})]
|
||||
}
|
||||
TurnItem::Sleep(_) => Vec::new(),
|
||||
TurnItem::ImageGeneration(item) => vec![item.as_legacy_event()],
|
||||
TurnItem::FileChange(item) => item
|
||||
.as_legacy_end_event(String::new())
|
||||
.into_iter()
|
||||
.collect(),
|
||||
TurnItem::McpToolCall(item) => item.as_legacy_end_event().into_iter().collect(),
|
||||
TurnItem::Reasoning(item) => item.as_legacy_events(show_raw_agent_reasoning),
|
||||
TurnItem::ContextCompaction(item) => vec![item.as_legacy_event()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for ItemStartedEvent {
|
||||
fn as_legacy_events(&self, _: bool) -> Vec<EventMsg> {
|
||||
match &self.item {
|
||||
TurnItem::WebSearch(item) => vec![EventMsg::WebSearchBegin(WebSearchBeginEvent {
|
||||
call_id: item.id.clone(),
|
||||
})],
|
||||
TurnItem::ImageView(_) => Vec::new(),
|
||||
TurnItem::ImageGeneration(item) => {
|
||||
vec![EventMsg::ImageGenerationBegin(ImageGenerationBeginEvent {
|
||||
call_id: item.id.clone(),
|
||||
})]
|
||||
}
|
||||
TurnItem::FileChange(item) => vec![item.as_legacy_begin_event(self.turn_id.clone())],
|
||||
TurnItem::McpToolCall(item) => vec![item.as_legacy_begin_event()],
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for ItemCompletedEvent {
|
||||
fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg> {
|
||||
match &self.item {
|
||||
TurnItem::FileChange(item) => item
|
||||
.as_legacy_end_event(self.turn_id.clone())
|
||||
.into_iter()
|
||||
.collect(),
|
||||
_ => self.item.as_legacy_events(show_raw_agent_reasoning),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for AgentMessageContentDeltaEvent {
|
||||
fn as_legacy_events(&self, _: bool) -> Vec<EventMsg> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for ReasoningContentDeltaEvent {
|
||||
fn as_legacy_events(&self, _: bool) -> Vec<EventMsg> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for ReasoningRawContentDeltaEvent {
|
||||
fn as_legacy_events(&self, _: bool) -> Vec<EventMsg> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for EventMsg {
|
||||
fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg> {
|
||||
match self {
|
||||
EventMsg::ItemStarted(event) => event.as_legacy_events(show_raw_agent_reasoning),
|
||||
EventMsg::ItemCompleted(event) => event.as_legacy_events(show_raw_agent_reasoning),
|
||||
EventMsg::AgentMessageContentDelta(event) => {
|
||||
event.as_legacy_events(show_raw_agent_reasoning)
|
||||
}
|
||||
EventMsg::ReasoningContentDelta(event) => {
|
||||
event.as_legacy_events(show_raw_agent_reasoning)
|
||||
}
|
||||
EventMsg::ReasoningRawContentDelta(event) => {
|
||||
event.as_legacy_events(show_raw_agent_reasoning)
|
||||
}
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ pub mod dynamic_tools;
|
||||
pub mod error;
|
||||
pub mod exec_output;
|
||||
pub mod items;
|
||||
mod legacy_events;
|
||||
pub mod mcp;
|
||||
pub mod mcp_approval_meta;
|
||||
pub mod memory_citation;
|
||||
|
||||
@@ -84,6 +84,7 @@ pub use crate::approvals::NetworkApprovalContext;
|
||||
pub use crate::approvals::NetworkApprovalProtocol;
|
||||
pub use crate::approvals::NetworkPolicyAmendment;
|
||||
pub use crate::approvals::NetworkPolicyRuleAction;
|
||||
pub use crate::legacy_events::HasLegacyEvent;
|
||||
pub use crate::permissions::FileSystemAccessMode;
|
||||
pub use crate::permissions::FileSystemPath;
|
||||
pub use crate::permissions::FileSystemSandboxEntry;
|
||||
@@ -1794,25 +1795,6 @@ pub struct ItemStartedEvent {
|
||||
pub started_at_ms: i64,
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for ItemStartedEvent {
|
||||
fn as_legacy_events(&self, _: bool) -> Vec<EventMsg> {
|
||||
match &self.item {
|
||||
TurnItem::WebSearch(item) => vec![EventMsg::WebSearchBegin(WebSearchBeginEvent {
|
||||
call_id: item.id.clone(),
|
||||
})],
|
||||
TurnItem::ImageView(_) => Vec::new(),
|
||||
TurnItem::ImageGeneration(item) => {
|
||||
vec![EventMsg::ImageGenerationBegin(ImageGenerationBeginEvent {
|
||||
call_id: item.id.clone(),
|
||||
})]
|
||||
}
|
||||
TurnItem::FileChange(item) => vec![item.as_legacy_begin_event(self.turn_id.clone())],
|
||||
TurnItem::McpToolCall(item) => vec![item.as_legacy_begin_event()],
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
pub struct ItemCompletedEvent {
|
||||
pub thread_id: ThreadId,
|
||||
@@ -1829,22 +1811,6 @@ const fn default_item_completed_at_ms() -> i64 {
|
||||
0
|
||||
}
|
||||
|
||||
pub trait HasLegacyEvent {
|
||||
fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg>;
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for ItemCompletedEvent {
|
||||
fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg> {
|
||||
match &self.item {
|
||||
TurnItem::FileChange(item) => item
|
||||
.as_legacy_end_event(self.turn_id.clone())
|
||||
.into_iter()
|
||||
.collect(),
|
||||
_ => self.item.as_legacy_events(show_raw_agent_reasoning),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
pub struct AgentMessageContentDeltaEvent {
|
||||
pub thread_id: String,
|
||||
@@ -1853,12 +1819,6 @@ pub struct AgentMessageContentDeltaEvent {
|
||||
pub delta: String,
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for AgentMessageContentDeltaEvent {
|
||||
fn as_legacy_events(&self, _: bool) -> Vec<EventMsg> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
pub struct PlanDeltaEvent {
|
||||
pub thread_id: String,
|
||||
@@ -1878,12 +1838,6 @@ pub struct ReasoningContentDeltaEvent {
|
||||
pub summary_index: i64,
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for ReasoningContentDeltaEvent {
|
||||
fn as_legacy_events(&self, _: bool) -> Vec<EventMsg> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
pub struct ReasoningRawContentDeltaEvent {
|
||||
pub thread_id: String,
|
||||
@@ -1895,31 +1849,6 @@ pub struct ReasoningRawContentDeltaEvent {
|
||||
pub content_index: i64,
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for ReasoningRawContentDeltaEvent {
|
||||
fn as_legacy_events(&self, _: bool) -> Vec<EventMsg> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasLegacyEvent for EventMsg {
|
||||
fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg> {
|
||||
match self {
|
||||
EventMsg::ItemStarted(event) => event.as_legacy_events(show_raw_agent_reasoning),
|
||||
EventMsg::ItemCompleted(event) => event.as_legacy_events(show_raw_agent_reasoning),
|
||||
EventMsg::AgentMessageContentDelta(event) => {
|
||||
event.as_legacy_events(show_raw_agent_reasoning)
|
||||
}
|
||||
EventMsg::ReasoningContentDelta(event) => {
|
||||
event.as_legacy_events(show_raw_agent_reasoning)
|
||||
}
|
||||
EventMsg::ReasoningRawContentDelta(event) => {
|
||||
event.as_legacy_events(show_raw_agent_reasoning)
|
||||
}
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)]
|
||||
pub struct ExitedReviewModeEvent {
|
||||
pub review_output: Option<ReviewOutputEvent>,
|
||||
@@ -5386,6 +5315,7 @@ mod tests {
|
||||
let event = serde_json::from_value::<ItemCompletedEvent>(value).unwrap();
|
||||
assert_eq!(event.completed_at_ms, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rollback_failed_error_does_not_affect_turn_status() {
|
||||
let event = ErrorEvent {
|
||||
|
||||
Reference in New Issue
Block a user