[search] allow explicitly disabling web search (#9249)

moving `web_search` rollout serverside, so need a way to explicitly
disable search + signal eligibility from the client.

- Add `x‑oai‑web‑search‑eligible` header that signifies whether the
request can have web search.
- Only attach the `web_search` tool when the resolved `WebSearchMode` is
`Live` or `Cached`.
This commit is contained in:
sayan-oai
2026-01-15 11:28:57 -08:00
committed by GitHub
parent 42fa4c237f
commit 169201b1b5
11 changed files with 139 additions and 60 deletions

View File

@@ -9,15 +9,18 @@ use codex_core::ModelProviderInfo;
use codex_core::Prompt;
use codex_core::ResponseEvent;
use codex_core::ResponseItem;
use codex_core::WEB_SEARCH_ELIGIBLE_HEADER;
use codex_core::WireApi;
use codex_core::models_manager::manager::ModelsManager;
use codex_otel::OtelManager;
use codex_protocol::ThreadId;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::config_types::WebSearchMode;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::SubAgentSource;
use core_test_support::load_default_config_for_test;
use core_test_support::responses;
use core_test_support::test_codex::test_codex;
use futures::StreamExt;
use tempfile::TempDir;
use wiremock::matchers::header;
@@ -213,6 +216,66 @@ async fn responses_stream_includes_subagent_header_on_other() {
);
}
#[tokio::test]
async fn responses_stream_includes_web_search_eligible_header_true_by_default() {
core_test_support::skip_if_no_network!();
let server = responses::start_mock_server().await;
let response_body = responses::sse(vec![
responses::ev_response_created("resp-1"),
responses::ev_completed("resp-1"),
]);
let request_recorder = responses::mount_sse_once_match(
&server,
header(WEB_SEARCH_ELIGIBLE_HEADER, "true"),
response_body,
)
.await;
let test = test_codex().build(&server).await.expect("build test codex");
test.submit_turn("hello").await.expect("submit test prompt");
let request = request_recorder.single_request();
assert_eq!(
request.header(WEB_SEARCH_ELIGIBLE_HEADER).as_deref(),
Some("true")
);
}
#[tokio::test]
async fn responses_stream_includes_web_search_eligible_header_false_when_disabled() {
core_test_support::skip_if_no_network!();
let server = responses::start_mock_server().await;
let response_body = responses::sse(vec![
responses::ev_response_created("resp-1"),
responses::ev_completed("resp-1"),
]);
let request_recorder = responses::mount_sse_once_match(
&server,
header(WEB_SEARCH_ELIGIBLE_HEADER, "false"),
response_body,
)
.await;
let test = test_codex()
.with_config(|config| {
config.web_search_mode = Some(WebSearchMode::Disabled);
})
.build(&server)
.await
.expect("build test codex");
test.submit_turn("hello").await.expect("submit test prompt");
let request = request_recorder.single_request();
assert_eq!(
request.header(WEB_SEARCH_ELIGIBLE_HEADER).as_deref(),
Some("false")
);
}
#[tokio::test]
async fn responses_respects_model_info_overrides_from_config() {
core_test_support::skip_if_no_network!();