Files
codex/codex-rs/core/src/tools/hosted_spec.rs
T
Winston Howes 3a2712ea14 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.
2026-06-19 05:35:57 -07:00

57 lines
1.9 KiB
Rust

use codex_protocol::config_types::WebSearchConfig;
use codex_protocol::config_types::WebSearchMode;
use codex_protocol::openai_models::WebSearchToolType;
use codex_tools::ToolSpec;
const WEB_SEARCH_TEXT_AND_IMAGE_CONTENT_TYPES: [&str; 2] = ["text", "image"];
pub struct WebSearchToolOptions<'a> {
pub web_search_mode: Option<WebSearchMode>,
pub web_search_config: Option<&'a WebSearchConfig>,
pub web_search_tool_type: WebSearchToolType,
}
pub fn create_image_generation_tool(output_format: &str) -> ToolSpec {
ToolSpec::ImageGeneration {
output_format: output_format.to_string(),
}
}
pub fn create_web_search_tool(options: WebSearchToolOptions<'_>) -> Option<ToolSpec> {
let (external_web_access, index_gated_web_access) = match options.web_search_mode {
Some(WebSearchMode::Cached) => (false, None),
Some(WebSearchMode::Indexed) => (true, Some(true)),
Some(WebSearchMode::Live) => (true, None),
Some(WebSearchMode::Disabled) | None => return None,
};
let search_content_types = match options.web_search_tool_type {
WebSearchToolType::Text => None,
WebSearchToolType::TextAndImage => Some(
WEB_SEARCH_TEXT_AND_IMAGE_CONTENT_TYPES
.into_iter()
.map(str::to_string)
.collect(),
),
};
Some(ToolSpec::WebSearch {
external_web_access: Some(external_web_access),
index_gated_web_access,
filters: options
.web_search_config
.and_then(|config| config.filters.clone().map(Into::into)),
user_location: options
.web_search_config
.and_then(|config| config.user_location.clone().map(Into::into)),
search_context_size: options
.web_search_config
.and_then(|config| config.search_context_size),
search_content_types,
})
}
#[cfg(test)]
#[path = "hosted_spec_tests.rs"]
mod tests;