[codex] Hide deferred tools from code mode prompt (#23605)

## Why

`code_mode_only_guides_all_tools_search_and_calls_deferred_app_tools`
was failing because code-mode prompt generation used the same nested
tool spec list for both the model-visible `exec` guide and the runtime
`ALL_TOOLS` surface. That allowed deferred MCP/app tools, such as
`calendar_timezone_option_99`, to leak into the `exec` description even
though they should only be discoverable through `ALL_TOOLS` at runtime.

## What changed

Split code-mode nested tool planning into two sets in
`core/src/tools/spec_plan.rs`:

- runtime nested tool specs still include deferred tools, so
`tools[...]` and `ALL_TOOLS` can call them
- `exec` prompt docs only render non-deferred tools, so deferred app
tools stay out of the model-visible guide

## Validation

- `cargo test -p codex-core --test all
code_mode_only_guides_all_tools_search_and_calls_deferred_app_tools --
--nocapture`
- looped the same focused test 5 additional times with `cargo test -q -p
codex-core --test all
code_mode_only_guides_all_tools_search_and_calls_deferred_app_tools`
This commit is contained in:
pakrym-oai
2026-05-20 08:09:45 -07:00
committed by GitHub
parent 59507b8491
commit a52c91d8b5

View File

@@ -367,19 +367,27 @@ fn build_code_mode_executors(
return vec![];
}
let code_mode_nested_tool_specs = executors
.iter()
.filter_map(|executor| {
if executor.exposure() == ToolExposure::DirectModelOnly {
return None;
}
let mut code_mode_nested_tool_specs = Vec::new();
let mut exec_prompt_tool_specs = Vec::new();
for executor in executors {
let exposure = executor.exposure();
if exposure == ToolExposure::DirectModelOnly {
continue;
}
executor.spec()
})
.collect::<Vec<_>>();
let namespace_descriptions = code_mode_namespace_descriptions(&code_mode_nested_tool_specs);
let Some(spec) = executor.spec() else {
continue;
};
if exposure != ToolExposure::Deferred {
exec_prompt_tool_specs.push(spec.clone());
}
code_mode_nested_tool_specs.push(spec);
}
let namespace_descriptions = code_mode_namespace_descriptions(&exec_prompt_tool_specs);
let mut enabled_tools =
collect_code_mode_exec_prompt_tool_definitions(code_mode_nested_tool_specs.iter());
collect_code_mode_exec_prompt_tool_definitions(exec_prompt_tool_specs.iter());
enabled_tools
.sort_by(|left, right| compare_code_mode_tools(left, right, &namespace_descriptions));