core: migrate standalone web search to extension-owned turn items (#31525)

## Description

This PR migrates standalone web search onto the extension-owned
turn-item path introduced in #31283.

Standalone web search now emits `ExtensionItem::WebSearch` through
generic `TurnItem::Extension`, while app-server still exposes the
existing typed `ThreadItem::WebSearch` JSON shape. Hosted Responses API
web search stays on core-owned `TurnItem::WebSearch`.

## What changed

- Added `web_search::WebSearchItem` and `WebSearchAction` to
`codex-extension-items` under the stable `web.search` kind.
- Collapsed `ExtensionTurnItem` to generic `{ item, legacy_events }` now
that no typed extension special cases remain.
- Kept the existing `WebSearchBegin` / `WebSearchEnd` compatibility
events and canonical-first ordering.
- Updated app-server projection/history and generated TypeScript; the
app-server JSON schema is unchanged.
This commit is contained in:
Owen Lin authored and GitHub committed 2026-07-08 09:40:00 -07:00
1 parent e212cc95b0
commit a219b6fdb4
26 files changed
+279 -209

No files matched your search

@@ -19,7 +19,7 @@ use codex_protocol::items::ReasoningItem;
use codex_protocol::items::SubAgentActivityItem;
use codex_protocol::items::TurnItem;
use codex_protocol::items::UserMessageItem;
use codex_protocol::items::WebSearchItem;
use codex_protocol::items::WebSearchItem as CoreWebSearchItem;
use codex_protocol::mcp::CallToolResult;
use codex_protocol::mcp::McpServerInfo;
use codex_protocol::memory_citation::MemoryCitation as CoreMemoryCitation;
@@ -2770,7 +2770,7 @@ fn core_turn_item_into_thread_item_converts_supported_variants() {
}
);
let search_item = TurnItem::WebSearch(WebSearchItem {
let search_item = TurnItem::WebSearch(CoreWebSearchItem {
id: "search-1".to_string(),
query: "docs".to_string(),
action: CoreWebSearchAction::Search {
@@ -2779,16 +2779,24 @@ fn core_turn_item_into_thread_item_converts_supported_variants() {
},
});
let expected_search_item = WebSearchItem {
id: "search-1".to_string(),
query: "docs".to_string(),
action: Some(WebSearchAction::Search {
query: Some("docs".to_string()),
queries: None,
}),
};
assert_eq!(
ThreadItem::from(search_item),
ThreadItem::WebSearch {
id: "search-1".to_string(),
query: "docs".to_string(),
action: Some(WebSearchAction::Search {
query: Some("docs".to_string()),
queries: None,
}),
}
ThreadItem::WebSearch(expected_search_item.clone())
);
assert_eq!(
ThreadItem::from(TurnItem::Extension(
codex_extension_items::ExtensionItem::WebSearch(expected_search_item.clone()),
)),
ThreadItem::WebSearch(expected_search_item)
);
let image_view_item = TurnItem::ImageView(ImageViewItem {