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 164ebecefa..01c439edc7 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 c462879767..8ab5f3b263 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; diff --git a/codex-rs/protocol-ts/src/lib.rs b/codex-rs/protocol-ts/src/lib.rs index 848aeb25c7..f6990e4228 100644 --- a/codex-rs/protocol-ts/src/lib.rs +++ b/codex-rs/protocol-ts/src/lib.rs @@ -21,32 +21,34 @@ pub fn generate_ts(out_dir: &Path, prettier: Option<&Path>) -> Result<()> { codex_protocol::mcp_protocol::InputItem::export_all_to(out_dir)?; codex_protocol::mcp_protocol::ClientRequest::export_all_to(out_dir)?; codex_protocol::mcp_protocol::ServerRequest::export_all_to(out_dir)?; + + // Response types for ClientRequest (mirror enum order). codex_protocol::mcp_protocol::InitializeResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::NewConversationResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::ListConversationsResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::ResumeConversationResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::ArchiveConversationResponse::export_all_to(out_dir)?; - codex_protocol::mcp_protocol::AddConversationSubscriptionResponse::export_all_to(out_dir)?; - codex_protocol::mcp_protocol::RemoveConversationSubscriptionResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::SendUserMessageResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::SendUserTurnResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::InterruptConversationResponse::export_all_to(out_dir)?; + codex_protocol::mcp_protocol::AddConversationSubscriptionResponse::export_all_to(out_dir)?; + codex_protocol::mcp_protocol::RemoveConversationSubscriptionResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::GitDiffToRemoteResponse::export_all_to(out_dir)?; - codex_protocol::mcp_protocol::LoginApiKeyParams::export_all_to(out_dir)?; codex_protocol::mcp_protocol::LoginApiKeyResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::LoginChatGptResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::CancelLoginChatGptResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::LogoutChatGptResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::GetAuthStatusResponse::export_all_to(out_dir)?; - codex_protocol::mcp_protocol::ApplyPatchApprovalResponse::export_all_to(out_dir)?; - codex_protocol::mcp_protocol::ExecCommandApprovalResponse::export_all_to(out_dir)?; - codex_protocol::mcp_protocol::FuzzyFileSearchParams::export_all_to(out_dir)?; - codex_protocol::mcp_protocol::FuzzyFileSearchResult::export_all_to(out_dir)?; - codex_protocol::mcp_protocol::FuzzyFileSearchResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::GetUserSavedConfigResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::SetDefaultModelResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::GetUserAgentResponse::export_all_to(out_dir)?; codex_protocol::mcp_protocol::UserInfoResponse::export_all_to(out_dir)?; + codex_protocol::mcp_protocol::FuzzyFileSearchResponse::export_all_to(out_dir)?; + codex_protocol::mcp_protocol::ExecArbitraryCommandResponse::export_all_to(out_dir)?; + + // Response types for ServerRequest (mirror enum order). + codex_protocol::mcp_protocol::ApplyPatchApprovalResponse::export_all_to(out_dir)?; + codex_protocol::mcp_protocol::ExecCommandApprovalResponse::export_all_to(out_dir)?; // All notification types reachable from this enum will be generated by // induction, so they do not need to be listed individually.