mirror of
https://github.com/openai/codex.git
synced 2026-02-01 22:47:52 +00:00
add missing fields to WebSearchAction and update app-server types (#10276)
- add `WebSearchAction` to app-server v2 types - add `queries` to `WebSearchAction::Search` type Updated tests.
This commit is contained in:
@@ -2121,7 +2121,11 @@ pub enum ThreadItem {
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
WebSearch { id: String, query: String },
|
||||
WebSearch {
|
||||
id: String,
|
||||
query: String,
|
||||
action: Option<WebSearchAction>,
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
ImageView { id: String, path: String },
|
||||
@@ -2136,6 +2140,42 @@ pub enum ThreadItem {
|
||||
ContextCompaction { id: String },
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[ts(tag = "type", rename_all = "camelCase")]
|
||||
pub enum WebSearchAction {
|
||||
Search {
|
||||
query: Option<String>,
|
||||
queries: Option<Vec<String>>,
|
||||
},
|
||||
OpenPage {
|
||||
url: Option<String>,
|
||||
},
|
||||
FindInPage {
|
||||
url: Option<String>,
|
||||
pattern: Option<String>,
|
||||
},
|
||||
#[serde(other)]
|
||||
Other,
|
||||
}
|
||||
|
||||
impl From<codex_protocol::models::WebSearchAction> for WebSearchAction {
|
||||
fn from(value: codex_protocol::models::WebSearchAction) -> Self {
|
||||
match value {
|
||||
codex_protocol::models::WebSearchAction::Search { query, queries } => {
|
||||
WebSearchAction::Search { query, queries }
|
||||
}
|
||||
codex_protocol::models::WebSearchAction::OpenPage { url } => {
|
||||
WebSearchAction::OpenPage { url }
|
||||
}
|
||||
codex_protocol::models::WebSearchAction::FindInPage { url, pattern } => {
|
||||
WebSearchAction::FindInPage { url, pattern }
|
||||
}
|
||||
codex_protocol::models::WebSearchAction::Other => WebSearchAction::Other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CoreTurnItem> for ThreadItem {
|
||||
fn from(value: CoreTurnItem) -> Self {
|
||||
match value {
|
||||
@@ -2165,6 +2205,7 @@ impl From<CoreTurnItem> for ThreadItem {
|
||||
CoreTurnItem::WebSearch(search) => ThreadItem::WebSearch {
|
||||
id: search.id,
|
||||
query: search.query,
|
||||
action: Some(WebSearchAction::from(search.action)),
|
||||
},
|
||||
CoreTurnItem::ContextCompaction(compaction) => {
|
||||
ThreadItem::ContextCompaction { id: compaction.id }
|
||||
@@ -2818,7 +2859,7 @@ mod tests {
|
||||
use codex_protocol::items::TurnItem;
|
||||
use codex_protocol::items::UserMessageItem;
|
||||
use codex_protocol::items::WebSearchItem;
|
||||
use codex_protocol::models::WebSearchAction;
|
||||
use codex_protocol::models::WebSearchAction as CoreWebSearchAction;
|
||||
use codex_protocol::protocol::NetworkAccess as CoreNetworkAccess;
|
||||
use codex_protocol::user_input::UserInput as CoreUserInput;
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -2934,8 +2975,9 @@ mod tests {
|
||||
let search_item = TurnItem::WebSearch(WebSearchItem {
|
||||
id: "search-1".to_string(),
|
||||
query: "docs".to_string(),
|
||||
action: WebSearchAction::Search {
|
||||
action: CoreWebSearchAction::Search {
|
||||
query: Some("docs".to_string()),
|
||||
queries: None,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2944,6 +2986,10 @@ mod tests {
|
||||
ThreadItem::WebSearch {
|
||||
id: "search-1".to_string(),
|
||||
query: "docs".to_string(),
|
||||
action: Some(WebSearchAction::Search {
|
||||
query: Some("docs".to_string()),
|
||||
queries: None,
|
||||
}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -450,7 +450,7 @@ Today both notifications carry an empty `items` array even when item events were
|
||||
- `fileChange` — `{id, changes, status}` describing proposed edits; `changes` list `{path, kind, diff}` and `status` is `inProgress`, `completed`, `failed`, or `declined`.
|
||||
- `mcpToolCall` — `{id, server, tool, status, arguments, result?, error?}` describing MCP calls; `status` is `inProgress`, `completed`, or `failed`.
|
||||
- `collabToolCall` — `{id, tool, status, senderThreadId, receiverThreadId?, newThreadId?, prompt?, agentStatus?}` describing collab tool calls (`spawn_agent`, `send_input`, `wait`, `close_agent`); `status` is `inProgress`, `completed`, or `failed`.
|
||||
- `webSearch` — `{id, query}` for a web search request issued by the agent.
|
||||
- `webSearch` — `{id, query, action?}` for a web search request issued by the agent; `action` mirrors the Responses API web_search action payload (`search`, `open_page`, `find_in_page`) and may be omitted until completion.
|
||||
- `imageView` — `{id, path}` emitted when the agent invokes the image viewer tool.
|
||||
- `enteredReviewMode` — `{id, review}` sent when the reviewer starts; `review` is a short user-facing label such as `"current changes"` or the requested target description.
|
||||
- `exitedReviewMode` — `{id, review}` emitted when the reviewer finishes; `review` is the full plain-text review (usually, overall notes plus bullet point findings).
|
||||
|
||||
@@ -426,6 +426,7 @@ mod tests {
|
||||
status: Some("completed".to_string()),
|
||||
action: Some(WebSearchAction::Search {
|
||||
query: Some("weather".to_string()),
|
||||
queries: None,
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -439,6 +440,7 @@ mod tests {
|
||||
query: "weather".to_string(),
|
||||
action: WebSearchAction::Search {
|
||||
query: Some("weather".to_string()),
|
||||
queries: None,
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
use codex_protocol::models::WebSearchAction;
|
||||
|
||||
fn search_action_detail(query: &Option<String>, queries: &Option<Vec<String>>) -> String {
|
||||
query.clone().filter(|q| !q.is_empty()).unwrap_or_else(|| {
|
||||
let items = queries.as_ref();
|
||||
let first = items
|
||||
.and_then(|queries| queries.first())
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
if items.is_some_and(|queries| queries.len() > 1) && !first.is_empty() {
|
||||
format!("{first} ...")
|
||||
} else {
|
||||
first
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn web_search_action_detail(action: &WebSearchAction) -> String {
|
||||
match action {
|
||||
WebSearchAction::Search { query } => query.clone().unwrap_or_default(),
|
||||
WebSearchAction::Search { query, queries } => search_action_detail(query, queries),
|
||||
WebSearchAction::OpenPage { url } => url.clone().unwrap_or_default(),
|
||||
WebSearchAction::FindInPage { url, pattern } => match (pattern, url) {
|
||||
(Some(pattern), Some(url)) => format!("'{pattern}' in {url}"),
|
||||
|
||||
@@ -1216,6 +1216,7 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() {
|
||||
status: Some("completed".into()),
|
||||
action: Some(WebSearchAction::Search {
|
||||
query: Some("weather".into()),
|
||||
queries: None,
|
||||
}),
|
||||
});
|
||||
prompt.input.push(ResponseItem::FunctionCall {
|
||||
|
||||
@@ -255,6 +255,7 @@ async fn web_search_item_is_emitted() -> anyhow::Result<()> {
|
||||
completed.action,
|
||||
WebSearchAction::Search {
|
||||
query: Some("weather seattle".to_string()),
|
||||
queries: None,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ fn web_search_end_emits_item_completed() {
|
||||
let query = "rust async await".to_string();
|
||||
let action = WebSearchAction::Search {
|
||||
query: Some(query.clone()),
|
||||
queries: None,
|
||||
};
|
||||
let out = ep.collect_thread_events(&event(
|
||||
"w1",
|
||||
@@ -195,6 +196,7 @@ fn web_search_begin_then_end_reuses_item_id() {
|
||||
};
|
||||
let action = WebSearchAction::Search {
|
||||
query: Some("rust async await".to_string()),
|
||||
queries: None,
|
||||
};
|
||||
let end = ep.collect_thread_events(&event(
|
||||
"w1",
|
||||
|
||||
@@ -620,6 +620,9 @@ pub enum WebSearchAction {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
query: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
queries: Option<Vec<String>>,
|
||||
},
|
||||
OpenPage {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@@ -1132,12 +1135,14 @@ mod tests {
|
||||
"status": "completed",
|
||||
"action": {
|
||||
"type": "search",
|
||||
"query": "weather seattle"
|
||||
"query": "weather seattle",
|
||||
"queries": ["weather seattle", "seattle weather now"]
|
||||
}
|
||||
}"#,
|
||||
None,
|
||||
Some(WebSearchAction::Search {
|
||||
query: Some("weather seattle".into()),
|
||||
queries: Some(vec!["weather seattle".into(), "seattle weather now".into()]),
|
||||
}),
|
||||
Some("completed".into()),
|
||||
true,
|
||||
|
||||
@@ -2469,6 +2469,7 @@ mod tests {
|
||||
query: "find docs".into(),
|
||||
action: WebSearchAction::Search {
|
||||
query: Some("find docs".into()),
|
||||
queries: None,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -2294,7 +2294,10 @@ mod tests {
|
||||
let cell = new_web_search_call(
|
||||
"call-1".to_string(),
|
||||
query.clone(),
|
||||
WebSearchAction::Search { query: Some(query) },
|
||||
WebSearchAction::Search {
|
||||
query: Some(query),
|
||||
queries: None,
|
||||
},
|
||||
);
|
||||
let rendered = render_lines(&cell.display_lines(64)).join("\n");
|
||||
|
||||
@@ -2308,7 +2311,10 @@ mod tests {
|
||||
let cell = new_web_search_call(
|
||||
"call-1".to_string(),
|
||||
query.clone(),
|
||||
WebSearchAction::Search { query: Some(query) },
|
||||
WebSearchAction::Search {
|
||||
query: Some(query),
|
||||
queries: None,
|
||||
},
|
||||
);
|
||||
let rendered = render_lines(&cell.display_lines(64));
|
||||
|
||||
@@ -2327,7 +2333,10 @@ mod tests {
|
||||
let cell = new_web_search_call(
|
||||
"call-1".to_string(),
|
||||
query.clone(),
|
||||
WebSearchAction::Search { query: Some(query) },
|
||||
WebSearchAction::Search {
|
||||
query: Some(query),
|
||||
queries: None,
|
||||
},
|
||||
);
|
||||
let rendered = render_lines(&cell.display_lines(64));
|
||||
|
||||
@@ -2341,7 +2350,10 @@ mod tests {
|
||||
let cell = new_web_search_call(
|
||||
"call-1".to_string(),
|
||||
query.clone(),
|
||||
WebSearchAction::Search { query: Some(query) },
|
||||
WebSearchAction::Search {
|
||||
query: Some(query),
|
||||
queries: None,
|
||||
},
|
||||
);
|
||||
let rendered = render_lines(&cell.transcript_lines(64)).join("\n");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user