mirror of
https://github.com/openai/codex.git
synced 2026-04-25 07:05:38 +00:00
fix: handle all web_search actions and in progress invocations (#9960)
### Summary - Parse all `web_search` tool actions (`search`, `find_in_page`, `open_page`). - Previously we only parsed + displayed `search`, which made the TUI appear to pause when the other actions were being used. - Show in progress `web_search` calls as `Searching the web` - Previously we only showed completed tool calls <img width="308" height="149" alt="image" src="https://github.com/user-attachments/assets/90a4e8ff-b06a-48ff-a282-b57b31121845" /> ### Tests Added + updated tests, tested locally ### Follow ups Update VSCode extension to display these as well
This commit is contained in:
@@ -20,6 +20,7 @@ use codex_core::protocol::PatchApplyEndEvent;
|
||||
use codex_core::protocol::SandboxPolicy;
|
||||
use codex_core::protocol::SessionConfiguredEvent;
|
||||
use codex_core::protocol::WarningEvent;
|
||||
use codex_core::protocol::WebSearchBeginEvent;
|
||||
use codex_core::protocol::WebSearchEndEvent;
|
||||
use codex_exec::event_processor_with_jsonl_output::EventProcessorWithJsonOutput;
|
||||
use codex_exec::exec_events::AgentMessageItem;
|
||||
@@ -54,6 +55,7 @@ use codex_exec::exec_events::TurnStartedEvent;
|
||||
use codex_exec::exec_events::Usage;
|
||||
use codex_exec::exec_events::WebSearchItem;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::models::WebSearchAction;
|
||||
use codex_protocol::plan_tool::PlanItemArg;
|
||||
use codex_protocol::plan_tool::StepStatus;
|
||||
use codex_protocol::plan_tool::UpdatePlanArgs;
|
||||
@@ -124,11 +126,15 @@ fn task_started_produces_turn_started_event() {
|
||||
fn web_search_end_emits_item_completed() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let query = "rust async await".to_string();
|
||||
let action = WebSearchAction::Search {
|
||||
query: Some(query.clone()),
|
||||
};
|
||||
let out = ep.collect_thread_events(&event(
|
||||
"w1",
|
||||
EventMsg::WebSearchEnd(WebSearchEndEvent {
|
||||
call_id: "call-123".to_string(),
|
||||
query: query.clone(),
|
||||
action: action.clone(),
|
||||
}),
|
||||
));
|
||||
|
||||
@@ -137,12 +143,82 @@ fn web_search_end_emits_item_completed() {
|
||||
vec![ThreadEvent::ItemCompleted(ItemCompletedEvent {
|
||||
item: ThreadItem {
|
||||
id: "item_0".to_string(),
|
||||
details: ThreadItemDetails::WebSearch(WebSearchItem { query }),
|
||||
details: ThreadItemDetails::WebSearch(WebSearchItem {
|
||||
id: "call-123".to_string(),
|
||||
query,
|
||||
action,
|
||||
}),
|
||||
},
|
||||
})]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn web_search_begin_emits_item_started() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let out = ep.collect_thread_events(&event(
|
||||
"w0",
|
||||
EventMsg::WebSearchBegin(WebSearchBeginEvent {
|
||||
call_id: "call-0".to_string(),
|
||||
}),
|
||||
));
|
||||
|
||||
assert_eq!(out.len(), 1);
|
||||
let ThreadEvent::ItemStarted(ItemStartedEvent { item }) = &out[0] else {
|
||||
panic!("expected ItemStarted");
|
||||
};
|
||||
assert!(item.id.starts_with("item_"));
|
||||
assert_eq!(
|
||||
item.details,
|
||||
ThreadItemDetails::WebSearch(WebSearchItem {
|
||||
id: "call-0".to_string(),
|
||||
query: String::new(),
|
||||
action: WebSearchAction::Other,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn web_search_begin_then_end_reuses_item_id() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let begin = ep.collect_thread_events(&event(
|
||||
"w0",
|
||||
EventMsg::WebSearchBegin(WebSearchBeginEvent {
|
||||
call_id: "call-1".to_string(),
|
||||
}),
|
||||
));
|
||||
let ThreadEvent::ItemStarted(ItemStartedEvent { item: started_item }) = &begin[0] else {
|
||||
panic!("expected ItemStarted");
|
||||
};
|
||||
let action = WebSearchAction::Search {
|
||||
query: Some("rust async await".to_string()),
|
||||
};
|
||||
let end = ep.collect_thread_events(&event(
|
||||
"w1",
|
||||
EventMsg::WebSearchEnd(WebSearchEndEvent {
|
||||
call_id: "call-1".to_string(),
|
||||
query: "rust async await".to_string(),
|
||||
action: action.clone(),
|
||||
}),
|
||||
));
|
||||
let ThreadEvent::ItemCompleted(ItemCompletedEvent {
|
||||
item: completed_item,
|
||||
}) = &end[0]
|
||||
else {
|
||||
panic!("expected ItemCompleted");
|
||||
};
|
||||
|
||||
assert_eq!(completed_item.id, started_item.id);
|
||||
assert_eq!(
|
||||
completed_item.details,
|
||||
ThreadItemDetails::WebSearch(WebSearchItem {
|
||||
id: "call-1".to_string(),
|
||||
query: "rust async await".to_string(),
|
||||
action,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plan_update_emits_todo_list_started_updated_and_completed() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
|
||||
Reference in New Issue
Block a user