mirror of
https://github.com/openai/codex.git
synced 2026-11-04 00:24:43 +00:00
Add indexed web search mode (#28489)
## Summary - Add `web_search = "indexed"` alongside `disabled`, `cached`, and `live`. - Use that same resolved mode for both hosted and standalone web search. - For hosted search, send `index_gated_web_access: true` with external web access enabled only when `indexed` is selected. - For standalone search, preserve the existing boolean wire values for existing modes (`cached` maps to `false` and `live` to `true`) and send `"indexed"` only for `indexed`; `disabled` keeps the tool unavailable. - Carry the mode through managed configuration requirements and generated schemas. ## Why Indexed search provides a middle ground between cached-only search and unrestricted live page fetching. Search queries can remain live while direct page fetches are limited to URLs admitted by the server. The existing `web_search` setting remains the single source of truth, so hosted and standalone executors cannot drift into different access modes. Without an explicit `indexed` selection, the existing model-visible tool and request shapes are unchanged. ```toml web_search = "indexed" [features] standalone_web_search = true ``` ## Validation - `just fmt` - `just test -p codex-api` (`126 passed`) - `just test -p codex-web-search-extension` (`7 passed`) - `just test -p codex-core code_mode_can_call_indexed_standalone_web_search` (`1 passed`) - Focused configuration, hosted request, standalone request, and managed-requirement coverage is included in the PR; remaining suites run in CI. The full workspace test suite was not run locally.
This commit is contained in:
1 parent
7951397e4a
commit
3a2712ea14
24 files changed
+204
-23
No files matched your search
@@ -5186,6 +5186,14 @@ fn web_search_mode_disabled_overrides_legacy_request() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn web_search_mode_for_turn_preserves_indexed_for_disabled_permissions() {
|
||||
let web_search_mode = Constrained::allow_any(WebSearchMode::Indexed);
|
||||
let mode = resolve_web_search_mode_for_turn(&web_search_mode, &PermissionProfile::Disabled);
|
||||
|
||||
assert_eq!(mode, WebSearchMode::Indexed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn web_search_mode_for_turn_uses_preference_for_read_only() {
|
||||
let web_search_mode = Constrained::allow_any(WebSearchMode::Cached);
|
||||
@@ -5232,6 +5240,31 @@ fn web_search_mode_for_turn_falls_back_when_live_is_disallowed() -> anyhow::Resu
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn web_search_mode_for_turn_does_not_implicitly_select_indexed() -> anyhow::Result<()> {
|
||||
let allowed = [
|
||||
WebSearchMode::Disabled,
|
||||
WebSearchMode::Cached,
|
||||
WebSearchMode::Indexed,
|
||||
];
|
||||
let web_search_mode = Constrained::new(WebSearchMode::Cached, move |candidate| {
|
||||
if allowed.contains(candidate) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ConstraintError::InvalidValue {
|
||||
field_name: "web_search_mode",
|
||||
candidate: format!("{candidate:?}"),
|
||||
allowed: format!("{allowed:?}"),
|
||||
requirement_source: RequirementSource::Unknown,
|
||||
})
|
||||
}
|
||||
})?;
|
||||
let mode = resolve_web_search_mode_for_turn(&web_search_mode, &PermissionProfile::Disabled);
|
||||
|
||||
assert_eq!(mode, WebSearchMode::Cached);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn project_profiles_are_ignored() -> std::io::Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
@@ -2667,7 +2667,7 @@ pub(crate) fn resolve_web_search_mode_for_turn(
|
||||
let preferred = web_search_mode.value();
|
||||
|
||||
if matches!(permission_profile, PermissionProfile::Disabled)
|
||||
&& preferred != WebSearchMode::Disabled
|
||||
&& !matches!(preferred, WebSearchMode::Disabled | WebSearchMode::Indexed)
|
||||
{
|
||||
for mode in [
|
||||
WebSearchMode::Live,
|
||||
|
||||
Reference in new issue
Block a user