diff --git a/codex-rs/exec/src/experimental_event_processor_with_json_output.rs b/codex-rs/exec/src/experimental_event_processor_with_json_output.rs index 164ebece..01c439ed 100644 --- a/codex-rs/exec/src/experimental_event_processor_with_json_output.rs +++ b/codex-rs/exec/src/experimental_event_processor_with_json_output.rs @@ -29,6 +29,7 @@ use crate::exec_events::TurnCompletedEvent; use crate::exec_events::TurnFailedEvent; use crate::exec_events::TurnStartedEvent; use crate::exec_events::Usage; +use crate::exec_events::WebSearchItem; use codex_core::config::Config; use codex_core::plan_tool::StepStatus; use codex_core::plan_tool::UpdatePlanArgs; @@ -46,6 +47,7 @@ use codex_core::protocol::PatchApplyEndEvent; use codex_core::protocol::SessionConfiguredEvent; use codex_core::protocol::TaskCompleteEvent; use codex_core::protocol::TaskStartedEvent; +use codex_core::protocol::WebSearchEndEvent; use tracing::error; use tracing::warn; @@ -106,6 +108,8 @@ impl ExperimentalEventProcessorWithJsonOutput { EventMsg::McpToolCallEnd(ev) => self.handle_mcp_tool_call_end(ev), EventMsg::PatchApplyBegin(ev) => self.handle_patch_apply_begin(ev), EventMsg::PatchApplyEnd(ev) => self.handle_patch_apply_end(ev), + EventMsg::WebSearchBegin(_) => Vec::new(), + EventMsg::WebSearchEnd(ev) => self.handle_web_search_end(ev), EventMsg::TokenCount(ev) => { if let Some(info) = &ev.info { self.last_total_token_usage = Some(info.total_token_usage.clone()); @@ -143,6 +147,17 @@ impl ExperimentalEventProcessorWithJsonOutput { })] } + fn handle_web_search_end(&self, ev: &WebSearchEndEvent) -> Vec { + let item = ThreadItem { + id: self.get_next_item_id(), + details: ThreadItemDetails::WebSearch(WebSearchItem { + query: ev.query.clone(), + }), + }; + + vec![ThreadEvent::ItemCompleted(ItemCompletedEvent { item })] + } + fn handle_agent_message(&self, payload: &AgentMessageEvent) -> Vec { let item = ThreadItem { id: self.get_next_item_id(), diff --git a/codex-rs/exec/tests/event_processor_with_json_output.rs b/codex-rs/exec/tests/event_processor_with_json_output.rs index c4628797..8ab5f3b2 100644 --- a/codex-rs/exec/tests/event_processor_with_json_output.rs +++ b/codex-rs/exec/tests/event_processor_with_json_output.rs @@ -12,6 +12,7 @@ use codex_core::protocol::McpToolCallEndEvent; use codex_core::protocol::PatchApplyBeginEvent; use codex_core::protocol::PatchApplyEndEvent; use codex_core::protocol::SessionConfiguredEvent; +use codex_core::protocol::WebSearchEndEvent; use codex_exec::exec_events::AssistantMessageItem; use codex_exec::exec_events::CommandExecutionItem; use codex_exec::exec_events::CommandExecutionStatus; @@ -34,6 +35,7 @@ use codex_exec::exec_events::TurnCompletedEvent; use codex_exec::exec_events::TurnFailedEvent; use codex_exec::exec_events::TurnStartedEvent; use codex_exec::exec_events::Usage; +use codex_exec::exec_events::WebSearchItem; use codex_exec::experimental_event_processor_with_json_output::ExperimentalEventProcessorWithJsonOutput; use mcp_types::CallToolResult; use pretty_assertions::assert_eq; @@ -89,6 +91,29 @@ fn task_started_produces_turn_started_event() { assert_eq!(out, vec![ThreadEvent::TurnStarted(TurnStartedEvent {})]); } +#[test] +fn web_search_end_emits_item_completed() { + let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let query = "rust async await".to_string(); + let out = ep.collect_thread_events(&event( + "w1", + EventMsg::WebSearchEnd(WebSearchEndEvent { + call_id: "call-123".to_string(), + query: query.clone(), + }), + )); + + assert_eq!( + out, + vec![ThreadEvent::ItemCompleted(ItemCompletedEvent { + item: ThreadItem { + id: "item_0".to_string(), + details: ThreadItemDetails::WebSearch(WebSearchItem { query }), + }, + })] + ); +} + #[test] fn plan_update_emits_todo_list_started_updated_and_completed() { use codex_core::plan_tool::PlanItemArg;