From d99f6b5c6f7833beacaa206483861873ebce9956 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Sat, 1 Nov 2025 18:51:27 -0700 Subject: [PATCH] push --- codex-rs/core/src/client.rs | 2 - codex-rs/core/src/response_processing.rs | 2 - codex-rs/core/tests/suite/client.rs | 99 ++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/codex-rs/core/src/client.rs b/codex-rs/core/src/client.rs index 9fef2cc809..9dfa3a1316 100644 --- a/codex-rs/core/src/client.rs +++ b/codex-rs/core/src/client.rs @@ -26,7 +26,6 @@ use tokio::sync::mpsc; use tokio::time::timeout; use tokio_util::io::ReaderStream; use tracing::debug; -use tracing::error; use tracing::trace; use tracing::warn; @@ -252,7 +251,6 @@ impl ModelClient { prompt_cache_key: Some(self.conversation_id.to_string()), text, }; - error!("payload: {:?}", payload); let mut payload_json = serde_json::to_value(&payload)?; if azure_workaround { diff --git a/codex-rs/core/src/response_processing.rs b/codex-rs/core/src/response_processing.rs index 3c07078bf7..da3aa1e1ee 100644 --- a/codex-rs/core/src/response_processing.rs +++ b/codex-rs/core/src/response_processing.rs @@ -3,7 +3,6 @@ use crate::codex::TurnContext; use codex_protocol::models::FunctionCallOutputPayload; use codex_protocol::models::ResponseInputItem; use codex_protocol::models::ResponseItem; -use tracing::error; use tracing::warn; /// Process streamed `ResponseItem`s from the model into the pair of: @@ -89,7 +88,6 @@ pub(crate) async fn process_items( } (ResponseItem::WebSearchCall { .. }, None) => { items_to_record_in_conversation_history.push(item.clone()); - error!("WebSearchCall: {item:?}"); } _ => { warn!("Unexpected response item: {item:?} with response: {response:?}"); diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index c2c5048dea..566da811d5 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -34,6 +34,7 @@ use core_test_support::test_codex::test_codex; use core_test_support::wait_for_event; use core_test_support::wait_for_event_with_timeout; use futures::StreamExt; +use serde_json::Value; use serde_json::json; use std::io::Write; use std::sync::Arc; @@ -1465,3 +1466,101 @@ async fn history_dedupes_streamed_and_final_messages_across_turns() { "request 3 tail mismatch", ); } + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn preserves_web_search_call_across_turns() { + skip_if_no_network!(); + + let server = responses::start_mock_server().await; + + let web_search_id = "search-1"; + let web_search_query = "rust weather"; + let turn_one_body = responses::sse(vec![ + responses::ev_response_created("resp-turn1"), + responses::ev_web_search_call_added(web_search_id, "in_progress", web_search_query), + responses::ev_web_search_call_done(web_search_id, "completed", web_search_query), + responses::ev_assistant_message("assistant-turn1", "Search finished."), + responses::ev_completed("resp-turn1"), + ]); + let turn_two_body = responses::sse(vec![ + responses::ev_response_created("resp-turn2"), + responses::ev_assistant_message("assistant-turn2", "Continuing conversation."), + responses::ev_completed("resp-turn2"), + ]); + let response_mock = + responses::mount_sse_sequence(&server, vec![turn_one_body, turn_two_body]).await; + + let mut model_provider = built_in_model_providers()["openai"].clone(); + model_provider.base_url = Some(format!("{}/v1", server.uri())); + + let codex_home = TempDir::new().unwrap(); + let mut config = load_default_config_for_test(&codex_home); + config.model_provider = model_provider; + + let conversation_manager = + ConversationManager::with_auth(CodexAuth::from_api_key("Test API Key")); + let NewConversation { + conversation: codex, + .. + } = conversation_manager + .new_conversation(config) + .await + .expect("create new conversation"); + + codex + .submit(Op::UserInput { + items: vec![UserInput::Text { + text: "first turn".into(), + }], + }) + .await + .unwrap(); + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + + codex + .submit(Op::UserInput { + items: vec![UserInput::Text { + text: "second turn".into(), + }], + }) + .await + .unwrap(); + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + + let requests = response_mock.requests(); + assert_eq!( + requests.len(), + 2, + "expected two requests to the responses API" + ); + + let turn_two_input = requests[1].input(); + let web_search_items: Vec = turn_two_input + .into_iter() + .filter(|item| item.get("type").and_then(Value::as_str) == Some("web_search_call")) + .collect(); + assert_eq!( + web_search_items.len(), + 1, + "expected exactly one web_search_call item in the second turn" + ); + + let item = &web_search_items[0]; + assert_eq!( + item.get("id").and_then(Value::as_str), + Some(web_search_id), + "web search id changed between turns" + ); + assert_eq!( + item.get("status").and_then(Value::as_str), + Some("completed"), + "web search status preserved between turns" + ); + assert_eq!( + item.get("action") + .and_then(|action| action.get("query")) + .and_then(Value::as_str), + Some(web_search_query), + "web search query changed between turns" + ); +}