mirror of
https://github.com/openai/codex.git
synced 2026-04-28 16:45:54 +00:00
add web_search_cached flag (#8795)
Add `web_search_cached` feature to config. Enables `web_search` tool with access only to cached/indexed results (see [docs](https://platform.openai.com/docs/guides/tools-web-search#live-internet-access)). This takes precedence over the existing `web_search_request`, which continues to enable `web_search` over live results as it did before. `web_search_cached` is disabled for review mode, as `web_search_request` is.
This commit is contained in:
@@ -65,3 +65,4 @@ mod unified_exec;
|
||||
mod user_notification;
|
||||
mod user_shell_cmd;
|
||||
mod view_image;
|
||||
mod web_search_cached;
|
||||
|
||||
87
codex-rs/core/tests/suite/web_search_cached.rs
Normal file
87
codex-rs/core/tests/suite/web_search_cached.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use codex_core::features::Feature;
|
||||
use core_test_support::load_sse_fixture_with_id;
|
||||
use core_test_support::responses;
|
||||
use core_test_support::responses::start_mock_server;
|
||||
use core_test_support::skip_if_no_network;
|
||||
use core_test_support::test_codex::test_codex;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::Value;
|
||||
|
||||
fn sse_completed(id: &str) -> String {
|
||||
load_sse_fixture_with_id("tests/fixtures/completed_template.json", id)
|
||||
}
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
fn find_web_search_tool(body: &Value) -> &Value {
|
||||
body["tools"]
|
||||
.as_array()
|
||||
.expect("request body should include tools array")
|
||||
.iter()
|
||||
.find(|tool| tool.get("type").and_then(Value::as_str) == Some("web_search"))
|
||||
.expect("tools should include a web_search tool")
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn web_search_cached_sets_external_web_access_false_in_request_body() {
|
||||
skip_if_no_network!();
|
||||
|
||||
let server = start_mock_server().await;
|
||||
let sse = sse_completed("resp-1");
|
||||
let resp_mock = responses::mount_sse_once(&server, sse).await;
|
||||
|
||||
let mut builder = test_codex()
|
||||
.with_model("gpt-5-codex")
|
||||
.with_config(|config| {
|
||||
config.features.enable(Feature::WebSearchCached);
|
||||
});
|
||||
let test = builder
|
||||
.build(&server)
|
||||
.await
|
||||
.expect("create test Codex conversation");
|
||||
|
||||
test.submit_turn("hello cached web search")
|
||||
.await
|
||||
.expect("submit turn");
|
||||
|
||||
let body = resp_mock.single_request().body_json();
|
||||
let tool = find_web_search_tool(&body);
|
||||
assert_eq!(
|
||||
tool.get("external_web_access").and_then(Value::as_bool),
|
||||
Some(false),
|
||||
"web_search_cached should force external_web_access=false"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn web_search_cached_takes_precedence_over_web_search_request_in_request_body() {
|
||||
skip_if_no_network!();
|
||||
|
||||
let server = start_mock_server().await;
|
||||
let sse = sse_completed("resp-1");
|
||||
let resp_mock = responses::mount_sse_once(&server, sse).await;
|
||||
|
||||
let mut builder = test_codex()
|
||||
.with_model("gpt-5-codex")
|
||||
.with_config(|config| {
|
||||
config.features.enable(Feature::WebSearchRequest);
|
||||
config.features.enable(Feature::WebSearchCached);
|
||||
});
|
||||
let test = builder
|
||||
.build(&server)
|
||||
.await
|
||||
.expect("create test Codex conversation");
|
||||
|
||||
test.submit_turn("hello cached+live flags")
|
||||
.await
|
||||
.expect("submit turn");
|
||||
|
||||
let body = resp_mock.single_request().body_json();
|
||||
let tool = find_web_search_tool(&body);
|
||||
assert_eq!(
|
||||
tool.get("external_web_access").and_then(Value::as_bool),
|
||||
Some(false),
|
||||
"web_search_cached should win over web_search_request"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user