mirror of
https://github.com/openai/codex.git
synced 2026-11-14 21:40:39 +00:00
Add support for incremental code mode tool definitions (#60157)
## What changed Render stable entries for nested tool definitions and namespace instructions alongside the full `functions.exec` description. Add optional catalog tracking that emits complete replacements for added or changed entries and explicit notices for removed entries, while keeping the existing exec declaration unchanged. Preserve entry hashes while exec is unavailable, then restore the full catalog and withdraw removed entries when it returns. Keep the existing snapshot format for ordinary tool catalogs. This change provides the rendering and state support; runtime activation remains disabled. ## Testing Add tests for definition rendering and namespace identity, batched additions and changes, removal notices, unchanged catalogs, and full catalog restoration after exec is hidden. GitOrigin-RevId: f472bd3e8e770a8cad9663c72e290abe7d0473be
This commit is contained in:
@@ -9,7 +9,7 @@ use super::MCP_TYPESCRIPT_PREAMBLE;
|
||||
use super::TOOL_SEARCH_GUIDANCE;
|
||||
use super::ToolDefinition;
|
||||
use super::UNIFIED_IMAGE_HELPER_DESCRIPTION;
|
||||
use super::build_exec_tool_description;
|
||||
use super::build_exec_tool_description_and_definitions;
|
||||
use codex_protocol::ToolName;
|
||||
use codex_protocol::openai_models::CodeModeToolMessages;
|
||||
use codex_protocol::openai_models::ToolMessage;
|
||||
@@ -29,7 +29,7 @@ fn exec_override_renders_only_known_literal_placeholders() {
|
||||
UNIFIED_IMAGE_HELPER_DESCRIPTION,
|
||||
),
|
||||
] {
|
||||
let description = build_exec_tool_description(
|
||||
let (description, _) = build_exec_tool_description_and_definitions(
|
||||
&[],
|
||||
&[],
|
||||
&BTreeMap::new(),
|
||||
@@ -37,6 +37,7 @@ fn exec_override_renders_only_known_literal_placeholders() {
|
||||
/*code_mode_only*/ false,
|
||||
image_detail_visibility,
|
||||
DeferredToolDiscovery::Catalog,
|
||||
/*incremental_exec_enabled*/ false,
|
||||
Some(&CodeModeToolMessages {
|
||||
exec: Some(ToolMessage {
|
||||
description: Some(" \nDefaults to 10000 ms. {{ default_exec_yield_time_ms }} ms.\n{{ image_helper }}\n{{ unknown }} {{default_exec_yield_time_ms}}\t ".to_string()),
|
||||
@@ -59,7 +60,7 @@ fn exec_override_renders_only_known_literal_placeholders() {
|
||||
fn exec_override_preserves_empty_and_whitespace_only_text() {
|
||||
for description_override in ["", " \n\t "] {
|
||||
assert_eq!(
|
||||
build_exec_tool_description(
|
||||
build_exec_tool_description_and_definitions(
|
||||
&[],
|
||||
&[],
|
||||
&BTreeMap::new(),
|
||||
@@ -67,6 +68,7 @@ fn exec_override_preserves_empty_and_whitespace_only_text() {
|
||||
/*code_mode_only*/ true,
|
||||
ImageDetailVisibility::Visible,
|
||||
DeferredToolDiscovery::Catalog,
|
||||
/*incremental_exec_enabled*/ false,
|
||||
Some(&CodeModeToolMessages {
|
||||
exec: Some(ToolMessage {
|
||||
description: Some(description_override.to_string()),
|
||||
@@ -78,7 +80,8 @@ fn exec_override_preserves_empty_and_whitespace_only_text() {
|
||||
mcp_typescript_preamble: Some("No MCP tools; omit this.".to_string()),
|
||||
..Default::default()
|
||||
}),
|
||||
),
|
||||
)
|
||||
.0,
|
||||
[
|
||||
description_override,
|
||||
"No deferred tools; omit this.",
|
||||
@@ -150,7 +153,7 @@ fn exec_override_preserves_runtime_sections() {
|
||||
),
|
||||
] {
|
||||
assert_eq!(
|
||||
build_exec_tool_description(
|
||||
build_exec_tool_description_and_definitions(
|
||||
&enabled_tools,
|
||||
&deferred_tools,
|
||||
&BTreeMap::new(),
|
||||
@@ -158,6 +161,7 @@ fn exec_override_preserves_runtime_sections() {
|
||||
code_mode_only,
|
||||
ImageDetailVisibility::Visible,
|
||||
DeferredToolDiscovery::Catalog,
|
||||
/*incremental_exec_enabled*/ false,
|
||||
Some(&CodeModeToolMessages {
|
||||
exec: Some(ToolMessage {
|
||||
description: Some(String::new()),
|
||||
@@ -167,7 +171,8 @@ fn exec_override_preserves_runtime_sections() {
|
||||
mcp_typescript_preamble: preamble.map(str::to_string),
|
||||
..Default::default()
|
||||
}),
|
||||
),
|
||||
)
|
||||
.0,
|
||||
expected,
|
||||
);
|
||||
}
|
||||
@@ -197,7 +202,7 @@ fn ranked_search_guidance_honors_overrides() {
|
||||
(Some(""), String::new()),
|
||||
(Some("Catalog discovery."), "Catalog discovery.".to_string()),
|
||||
] {
|
||||
let description = build_exec_tool_description(
|
||||
let (description, _) = build_exec_tool_description_and_definitions(
|
||||
&[],
|
||||
&deferred_tools,
|
||||
&BTreeMap::new(),
|
||||
@@ -205,6 +210,7 @@ fn ranked_search_guidance_honors_overrides() {
|
||||
code_mode_only,
|
||||
ImageDetailVisibility::Visible,
|
||||
DeferredToolDiscovery::RankedSearch,
|
||||
/*incremental_exec_enabled*/ false,
|
||||
Some(&CodeModeToolMessages {
|
||||
exec: Some(ToolMessage {
|
||||
description: Some(String::new()),
|
||||
@@ -232,7 +238,7 @@ fn mcp_types_stay_stable_when_a_deferred_tool_changes_its_output_schema() {
|
||||
output_schema: None,
|
||||
};
|
||||
let render = |tool: &ToolDefinition, preamble: Option<&str>| {
|
||||
build_exec_tool_description(
|
||||
build_exec_tool_description_and_definitions(
|
||||
&[],
|
||||
std::slice::from_ref(tool),
|
||||
&BTreeMap::new(),
|
||||
@@ -240,11 +246,13 @@ fn mcp_types_stay_stable_when_a_deferred_tool_changes_its_output_schema() {
|
||||
/*code_mode_only*/ true,
|
||||
ImageDetailVisibility::Visible,
|
||||
DeferredToolDiscovery::Catalog,
|
||||
/*incremental_exec_enabled*/ false,
|
||||
Some(&CodeModeToolMessages {
|
||||
mcp_typescript_preamble: preamble.map(str::to_string),
|
||||
..Default::default()
|
||||
}),
|
||||
)
|
||||
.0
|
||||
};
|
||||
// Keep one deferred tool throughout to isolate this from the independent
|
||||
// discovery guidance transition when the entire deferred catalog empties.
|
||||
@@ -275,7 +283,7 @@ fn nested_guidance_survives_catalog_changes_and_respects_overrides() {
|
||||
output_schema: None,
|
||||
}];
|
||||
let render = |tools: &[ToolDefinition], code_mode_only, guidance: Option<&str>| {
|
||||
build_exec_tool_description(
|
||||
build_exec_tool_description_and_definitions(
|
||||
&[],
|
||||
tools,
|
||||
&BTreeMap::new(),
|
||||
@@ -283,6 +291,7 @@ fn nested_guidance_survives_catalog_changes_and_respects_overrides() {
|
||||
code_mode_only,
|
||||
ImageDetailVisibility::Visible,
|
||||
DeferredToolDiscovery::Catalog,
|
||||
/*incremental_exec_enabled*/ false,
|
||||
Some(&CodeModeToolMessages {
|
||||
exec: Some(ToolMessage {
|
||||
description: Some(String::new()),
|
||||
@@ -293,6 +302,7 @@ fn nested_guidance_survives_catalog_changes_and_respects_overrides() {
|
||||
..Default::default()
|
||||
}),
|
||||
)
|
||||
.0
|
||||
};
|
||||
for code_mode_only in [false, true] {
|
||||
for (guidance, expected) in [
|
||||
|
||||
Reference in New Issue
Block a user