mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Use standalone tools for Responses Lite (#26490)
## Summary Responses Lite does not execute hosted Responses tools, so models using it must route web search and image generation through Codex-owned executors & standalone Response's API endpoints. This PR is stacked on #26487. ## Validation - `cargo test -p codex-core responses_lite_ --lib` - `cargo test -p codex-core standalone_executors_remain_hidden_without_flags_or_responses_lite --lib` - `cargo test -p codex-core hosted_tools_follow_provider_auth_model_and_config_gates --lib` - `cargo test -p codex-web-search-extension -p codex-image-generation-extension` - `cargo test -p codex-app-server --test all standalone_` - `cargo fmt --all -- --check`
This commit is contained in:
committed by
GitHub
Unverified
parent
4f655bc3b7
commit
ffe90cb5c3
@@ -56,6 +56,7 @@ use crate::tools::router::ToolRouterParams;
|
||||
use codex_features::Feature;
|
||||
use codex_login::AuthManager;
|
||||
use codex_mcp::ToolInfo;
|
||||
use codex_protocol::config_types::WebSearchMode;
|
||||
use codex_protocol::dynamic_tools::DynamicToolSpec;
|
||||
use codex_protocol::openai_models::ConfigShellToolType;
|
||||
use codex_protocol::openai_models::InputModality;
|
||||
@@ -246,22 +247,31 @@ fn spec_for_model_request(
|
||||
|
||||
fn hosted_model_tool_specs(context: &CoreToolPlanContext<'_>) -> Vec<ToolSpec> {
|
||||
let turn_context = context.turn_context;
|
||||
// Responses Lite accepts schemas for client-executed tools, not hosted Responses tools.
|
||||
if turn_context.model_info.use_responses_lite {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut specs = Vec::new();
|
||||
let provider_capabilities = turn_context.provider.capabilities();
|
||||
let web_search_mode = (!standalone_web_run_available(context.extension_tool_executors)
|
||||
&& provider_capabilities.web_search)
|
||||
let standalone_web_search_available = standalone_web_search_enabled(turn_context)
|
||||
&& context
|
||||
.extension_tool_executors
|
||||
.iter()
|
||||
.any(|executor| executor.tool_name() == ToolName::namespaced("web", "run"));
|
||||
// `Some(Cached/Live/Disabled)` are the options for mode when standalone search is unavailable
|
||||
// and the provider supports hosted search. `None` prevents emitting a hosted search tool.
|
||||
let web_search_mode = (!standalone_web_search_available
|
||||
&& turn_context.provider.capabilities().web_search)
|
||||
.then_some(turn_context.config.web_search_mode.value());
|
||||
let web_search_config = if provider_capabilities.web_search {
|
||||
turn_context.config.web_search_config.as_ref()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(web_search_tool) = create_web_search_tool(WebSearchToolOptions {
|
||||
let web_search_config = web_search_mode
|
||||
.as_ref()
|
||||
.and(turn_context.config.web_search_config.as_ref());
|
||||
if let Some(hosted_web_search_tool) = create_web_search_tool(WebSearchToolOptions {
|
||||
web_search_mode,
|
||||
web_search_config,
|
||||
web_search_tool_type: turn_context.model_info.web_search_tool_type,
|
||||
}) {
|
||||
specs.push(web_search_tool);
|
||||
specs.push(hosted_web_search_tool);
|
||||
}
|
||||
// TODO: Remove hosted image generation once the standalone extension is ready.
|
||||
if image_generation_tool_enabled(turn_context)
|
||||
@@ -336,9 +346,15 @@ fn image_generation_runtime_enabled(turn_context: &TurnContext) -> bool {
|
||||
}
|
||||
|
||||
fn standalone_image_generation_model_visible(turn_context: &TurnContext) -> bool {
|
||||
image_generation_runtime_enabled(turn_context)
|
||||
&& turn_context.features.get().enabled(Feature::ImageGenExt)
|
||||
&& namespace_tools_enabled(turn_context)
|
||||
if !image_generation_runtime_enabled(turn_context) || !namespace_tools_enabled(turn_context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if turn_context.model_info.use_responses_lite {
|
||||
return true;
|
||||
}
|
||||
|
||||
turn_context.features.get().enabled(Feature::ImageGenExt)
|
||||
}
|
||||
|
||||
fn standalone_image_generation_available(
|
||||
@@ -554,13 +570,13 @@ fn add_tool_sources(context: &CoreToolPlanContext<'_>, planned_tools: &mut Plann
|
||||
}
|
||||
}
|
||||
|
||||
fn standalone_web_run_available(
|
||||
extension_tools: &[Arc<dyn ToolExecutor<ExtensionToolCall>>],
|
||||
) -> bool {
|
||||
let web_run = ToolName::namespaced("web", "run");
|
||||
extension_tools
|
||||
.iter()
|
||||
.any(|executor| executor.tool_name() == web_run)
|
||||
fn standalone_web_search_enabled(turn_context: &TurnContext) -> bool {
|
||||
namespace_tools_enabled(turn_context)
|
||||
&& (turn_context.model_info.use_responses_lite
|
||||
|| turn_context
|
||||
.features
|
||||
.get()
|
||||
.enabled(Feature::StandaloneWebSearch))
|
||||
}
|
||||
|
||||
fn add_shell_tools(context: &CoreToolPlanContext<'_>, planned_tools: &mut PlannedTools) {
|
||||
@@ -883,8 +899,16 @@ fn append_extension_tool_executors(
|
||||
reserved_tool_names.insert(ToolName::plain(TOOL_SEARCH_TOOL_NAME));
|
||||
}
|
||||
|
||||
let standalone_web_search_enabled = standalone_web_search_enabled(turn_context);
|
||||
let web_search_mode_on = turn_context.config.web_search_mode.value() != WebSearchMode::Disabled;
|
||||
|
||||
for executor in executors.iter().cloned() {
|
||||
let tool_name = executor.tool_name();
|
||||
if tool_name == ToolName::namespaced("web", "run")
|
||||
&& (!standalone_web_search_enabled || !web_search_mode_on)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if tool_name == ToolName::namespaced(IMAGE_GEN_NAMESPACE, IMAGEGEN_TOOL_NAME)
|
||||
&& !standalone_image_generation_model_visible(turn_context)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user