mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Keep hosted tools visible in code-only mode (#25890)
## Why `code_mode_only` moved ordinary runtime tools behind `exec`, but it also hid hosted Responses tools. Hosted `web_search` and `image_generation` do not have a nested `exec` runtime path, so code-only sessions lost those capabilities entirely even when their existing provider, auth, model, and configuration gates passed. ## What changed - Keep hosted Responses tools top-level in `code_mode_only` sessions after their existing gates pass. - Preserve the existing nested-tool behavior for ordinary runtimes and the direct-only behavior for multi-agent v2 tools. - Add planner coverage for `code_mode_only` with default multi-agent v2 settings, hosted live web search, and hosted image generation. ## Verification - Added focused regression coverage in `codex-rs/core/src/tools/spec_plan_tests.rs`. - Left execution to CI per repository workflow.
This commit is contained in:
committed by
GitHub
Unverified
parent
e7039f9844
commit
68e2c8ed69
@@ -210,15 +210,7 @@ fn build_model_visible_specs_and_registry(
|
||||
specs.push(spec_for_model_request(turn_context, exposure, spec));
|
||||
}
|
||||
}
|
||||
for spec in hosted_specs {
|
||||
if !is_hidden_by_code_mode_only(
|
||||
turn_context,
|
||||
&ToolName::plain(spec.name()),
|
||||
ToolExposure::Direct,
|
||||
) {
|
||||
specs.push(spec);
|
||||
}
|
||||
}
|
||||
specs.extend(hosted_specs);
|
||||
|
||||
let registry = ToolRegistry::from_tools(runtimes);
|
||||
let model_visible_specs = merge_into_namespaces(specs)
|
||||
@@ -267,6 +259,7 @@ fn hosted_model_tool_specs(context: &CoreToolPlanContext<'_>) -> Vec<ToolSpec> {
|
||||
}) {
|
||||
specs.push(web_search_tool);
|
||||
}
|
||||
// TODO: Remove hosted image generation once the standalone extension is ready.
|
||||
if image_generation_tool_enabled(turn_context)
|
||||
&& !standalone_image_generation_available(turn_context, context.extension_tool_executors)
|
||||
{
|
||||
|
||||
@@ -1167,7 +1167,16 @@ async fn code_mode_only_can_expose_namespaced_multi_agent_v2_as_normal_tools() {
|
||||
})
|
||||
.await;
|
||||
|
||||
assert_eq!(plan.visible_names, vec!["exec", "wait", "agents"]);
|
||||
assert_eq!(
|
||||
plan.visible_names,
|
||||
vec![
|
||||
"exec",
|
||||
"wait",
|
||||
"agents",
|
||||
// Hosted Responses tools.
|
||||
"web_search",
|
||||
]
|
||||
);
|
||||
assert!(
|
||||
!plan
|
||||
.namespace_function_names("agents")
|
||||
@@ -1235,6 +1244,32 @@ async fn hosted_tools_follow_provider_auth_model_and_config_gates() {
|
||||
}
|
||||
);
|
||||
|
||||
let code_mode_only = probe(|turn| {
|
||||
use_chatgpt_auth(turn);
|
||||
set_features(turn, &[Feature::CodeModeOnly, Feature::MultiAgentV2]);
|
||||
set_web_search_mode(turn, WebSearchMode::Live);
|
||||
turn.model_info.input_modalities = vec![InputModality::Image];
|
||||
})
|
||||
.await;
|
||||
assert_eq!(
|
||||
code_mode_only.visible_names,
|
||||
vec![
|
||||
// Code-mode entrypoints.
|
||||
codex_code_mode::PUBLIC_TOOL_NAME,
|
||||
codex_code_mode::WAIT_TOOL_NAME,
|
||||
// Multi-agent v2 tools.
|
||||
"spawn_agent",
|
||||
"send_message",
|
||||
"followup_task",
|
||||
"wait_agent",
|
||||
"close_agent",
|
||||
"list_agents",
|
||||
// Hosted Responses tools.
|
||||
"web_search",
|
||||
"image_generation",
|
||||
]
|
||||
);
|
||||
|
||||
let standalone_web_search_without_web_run = probe(|turn| {
|
||||
set_feature(turn, Feature::StandaloneWebSearch, /*enabled*/ true);
|
||||
set_web_search_mode(turn, WebSearchMode::Live);
|
||||
|
||||
@@ -5,6 +5,7 @@ use codex_login::CodexAuth;
|
||||
use codex_models_manager::manager::RefreshStrategy;
|
||||
use codex_models_manager::manager::SharedModelsManager;
|
||||
use codex_models_manager::model_info::model_info_from_slug;
|
||||
use codex_protocol::openai_models::InputModality;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::openai_models::ModelPreset;
|
||||
use codex_protocol::openai_models::ModelVisibility;
|
||||
@@ -165,12 +166,17 @@ async fn remote_tool_mode_selector_overrides_feature_flags() -> Result<()> {
|
||||
|
||||
let mut code_mode_only_model = remote_model("test-tool-mode-code-mode-only");
|
||||
code_mode_only_model.tool_mode = Some(ToolMode::CodeModeOnly);
|
||||
code_mode_only_model.input_modalities = vec![InputModality::Text, InputModality::Image];
|
||||
let code_mode_only_body = response_body_for_remote_model(code_mode_only_model, |_| {}).await?;
|
||||
assert_eq!(
|
||||
tool_names(&code_mode_only_body),
|
||||
vec![
|
||||
// Code-mode entrypoints.
|
||||
codex_code_mode::PUBLIC_TOOL_NAME.to_string(),
|
||||
codex_code_mode::WAIT_TOOL_NAME.to_string(),
|
||||
// Hosted Responses tools.
|
||||
"web_search".to_string(),
|
||||
"image_generation".to_string(),
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user