mirror of
https://github.com/openai/codex.git
synced 2026-08-23 13:09:46 +00:00
Expose structured standalone web search results (#32898)
## Why Standalone web search can return structured result DTOs separately from its model-facing text output. App-server clients need access to that data without coupling Codex to every result type or field. ## What changed - Preserve the optional `results` array from `/v1/alpha/search` as opaque JSON through web-search completion events, thread history, and app-server `webSearch` items. - Keep responses from older endpoints compatible when `results` is absent, and allow clients to ignore result types and fields they do not understand. - Regenerate the protocol schemas and TypeScript definitions for the optional field. ## Testing - Cover responses with missing, empty, and forward-compatible result payloads. - Verify standalone web-search results round-trip through app-server item notifications and thread-item conversion. GitOrigin-RevId: 739ef5694ece5733f7b8749ec41d6bfa3f33c8c5
This commit is contained in:
@@ -139,6 +139,12 @@ mod tests {
|
||||
serde_json::to_vec(&json!({
|
||||
"encrypted_output": "ciphertext",
|
||||
"output": "search result",
|
||||
"results": [{
|
||||
"type": "text_result",
|
||||
"ref_id": "turn0search0",
|
||||
"url": "https://example.com/result",
|
||||
"future_field": {"preserved": true},
|
||||
}],
|
||||
}))
|
||||
.expect("serialize response"),
|
||||
);
|
||||
@@ -209,6 +215,12 @@ mod tests {
|
||||
SearchResponse {
|
||||
encrypted_output: Some("ciphertext".to_string()),
|
||||
output: "search result".to_string(),
|
||||
results: Some(vec![json!({
|
||||
"type": "text_result",
|
||||
"ref_id": "turn0search0",
|
||||
"url": "https://example.com/result",
|
||||
"future_field": {"preserved": true},
|
||||
})]),
|
||||
}
|
||||
);
|
||||
|
||||
@@ -267,4 +279,40 @@ mod tests {
|
||||
})
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn search_response_defaults_missing_results_for_older_endpoints() {
|
||||
let response: SearchResponse = serde_json::from_value(json!({
|
||||
"encrypted_output": null,
|
||||
"output": "search result",
|
||||
}))
|
||||
.expect("response without results should deserialize");
|
||||
|
||||
assert_eq!(
|
||||
response,
|
||||
SearchResponse {
|
||||
encrypted_output: None,
|
||||
output: "search result".to_string(),
|
||||
results: None,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn search_response_preserves_supported_empty_results() {
|
||||
let response: SearchResponse = serde_json::from_value(json!({
|
||||
"encrypted_output": null,
|
||||
"output": "search result",
|
||||
"results": [],
|
||||
}))
|
||||
.expect("response with empty results should deserialize");
|
||||
|
||||
assert_eq!(
|
||||
response,
|
||||
SearchResponse {
|
||||
encrypted_output: None,
|
||||
output: "search result".to_string(),
|
||||
results: Some(Vec::new()),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use codex_protocol::models::ResponseItem;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, PartialEq)]
|
||||
pub struct SearchRequest {
|
||||
@@ -297,4 +298,8 @@ pub enum AllowedCaller {
|
||||
pub struct SearchResponse {
|
||||
pub encrypted_output: Option<String>,
|
||||
pub output: String,
|
||||
/// Structured result DTOs are passed to clients out-of-band from `output`.
|
||||
/// Keep them opaque here so newer result variants remain forward-compatible.
|
||||
#[serde(default)]
|
||||
pub results: Option<Vec<JsonValue>>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user