Files
codex/codex-rs/ext/items/src/tests.rs
T
Owen Lin a219b6fdb4 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.
2026-07-08 09:40:00 -07:00

91 lines
2.4 KiB
Rust

use pretty_assertions::assert_eq;
use serde_json::json;
use super::ExtensionItem;
use super::image_generation::ImageGenerationItem;
use super::web_search::WebSearchAction;
use super::web_search::WebSearchItem;
fn completed_image_generation_item() -> ExtensionItem {
ExtensionItem::ImageGeneration(ImageGenerationItem {
id: "image-1".to_string(),
status: "completed".to_string(),
revised_prompt: Some("A blue square".to_string()),
result: "cG5n".to_string(),
saved_path: None,
})
}
#[test]
fn image_generation_item_preserves_stable_wire_shape() {
let item = completed_image_generation_item();
let value = serde_json::to_value(&item).expect("serialize extension item");
assert_eq!(
value,
json!({
"kind": "image_gen.generation",
"id": "image-1",
"status": "completed",
"revisedPrompt": "A blue square",
"result": "cG5n",
})
);
assert_eq!(
serde_json::from_value::<ExtensionItem>(value).expect("deserialize extension item"),
item
);
}
#[test]
fn web_search_item_preserves_stable_wire_shape() {
let item = ExtensionItem::WebSearch(WebSearchItem {
id: "search-1".to_string(),
query: "docs".to_string(),
action: Some(WebSearchAction::Search {
query: Some("docs".to_string()),
queries: None,
}),
});
let value = serde_json::to_value(&item).expect("serialize extension item");
assert_eq!(
value,
json!({
"kind": "web.search",
"id": "search-1",
"query": "docs",
"action": {
"type": "search",
"query": "docs",
"queries": null,
},
})
);
assert_eq!(
serde_json::from_value::<ExtensionItem>(value).expect("deserialize extension item"),
item
);
}
#[test]
fn unknown_extension_kind_is_rejected() {
let value = json!({
"kind": "image_gen.unknown",
"id": "image-1",
});
assert!(serde_json::from_value::<ExtensionItem>(value).is_err());
}
#[test]
fn malformed_known_extension_payload_is_rejected() {
let value = json!({
"kind": "image_gen.generation",
"id": "image-1",
"status": "completed",
});
assert!(serde_json::from_value::<ExtensionItem>(value).is_err());
}