mirror of
https://github.com/openai/codex.git
synced 2026-11-08 20:40:33 +00:00
## Why Standalone web search errors currently abort the turn as fatal failures, preventing the model from responding to them. ## What changed Return client setup errors to the model and represent failed search requests as unsuccessful tool outputs. Failed requests still emit search completion events and retain external-context handling. Limit error messages to 1,024 bytes, truncating at a UTF-8 character boundary with a truncation marker. ## Testing Add coverage for failure status reporting and UTF-8-safe error truncation. Extend workspace routing tests to verify that a rejected redirect returns a bounded diagnostic to the model, allows the turn to complete, emits search lifecycle events, and marks thread memory as polluted. GitOrigin-RevId: 9fb308990afa2ce0db5d9beed9bc66d9c1500418
66 lines
1.8 KiB
Rust
66 lines
1.8 KiB
Rust
use codex_extension_api::ToolOutput;
|
|
use codex_extension_api::ToolPayload;
|
|
use codex_protocol::models::FunctionCallOutputContentItem;
|
|
use codex_protocol::models::FunctionCallOutputPayload;
|
|
use codex_protocol::models::ResponseInputItem;
|
|
|
|
pub(crate) struct SearchOutput {
|
|
payload: FunctionCallOutputPayload,
|
|
}
|
|
|
|
impl SearchOutput {
|
|
pub(crate) fn new(result: Result<String, String>) -> Self {
|
|
let payload = match result {
|
|
Ok(text) => FunctionCallOutputPayload::from_content_items(vec![
|
|
FunctionCallOutputContentItem::InputText { text },
|
|
]),
|
|
Err(error) => FunctionCallOutputPayload {
|
|
success: Some(false),
|
|
..FunctionCallOutputPayload::from_text(error)
|
|
},
|
|
};
|
|
Self { payload }
|
|
}
|
|
}
|
|
|
|
impl ToolOutput for SearchOutput {
|
|
fn log_output(&self) -> String {
|
|
"[standalone web search output]".to_string()
|
|
}
|
|
|
|
fn success_for_logging(&self) -> bool {
|
|
self.payload.success.unwrap_or(true)
|
|
}
|
|
|
|
fn contains_external_context(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn to_response_item(&self, call_id: &str, _payload: &ToolPayload) -> ResponseInputItem {
|
|
ResponseInputItem::FunctionCallOutput {
|
|
call_id: call_id.to_string(),
|
|
output: self.payload.clone(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use pretty_assertions::assert_eq;
|
|
|
|
use super::SearchOutput;
|
|
use super::ToolOutput;
|
|
|
|
#[test]
|
|
fn reports_search_status_for_logging_and_downstream_handling() {
|
|
for (result, success) in [
|
|
(Ok("found".into()), None),
|
|
(Err("failed".into()), Some(false)),
|
|
] {
|
|
let output = SearchOutput::new(result);
|
|
assert_eq!(output.payload.success, success);
|
|
assert_eq!(output.success_for_logging(), success.unwrap_or(true));
|
|
}
|
|
}
|
|
}
|