mirror of
https://github.com/openai/codex.git
synced 2026-10-30 19:18:49 +00:00
Always put Code Mode tool descriptions before namespace descriptions (#57462)
## What changed Make tool descriptions precede namespace descriptions in Code Mode execution and tool search. Mark `code_mode_tool_description_first` as removed and simplify cached definitions to depend only on the input schema budget. ## Testing Update Code Mode integration assertions and catalog snapshots to expect tool descriptions before namespace descriptions. GitOrigin-RevId: 1344d4c264d1d2b18ee0388a064b6813ca81f770
This commit is contained in:
@@ -4,7 +4,6 @@ use crate::tools::context::ToolPayload;
|
||||
use crate::tools::context::boxed_tool_output;
|
||||
use crate::tools::registry::CoreToolRuntime;
|
||||
use crate::tools::registry::ToolExecutor;
|
||||
use codex_features::Feature;
|
||||
use codex_prompts::ResolvedModelMessages;
|
||||
use codex_tools::IndirectNamespacePrefixes;
|
||||
use codex_tools::ToolName;
|
||||
@@ -56,18 +55,12 @@ impl CodeModeExecuteHandler {
|
||||
.config
|
||||
.code_mode
|
||||
.tool_input_schema_max_bytes;
|
||||
let tool_description_first = step_context
|
||||
.turn
|
||||
.config
|
||||
.features
|
||||
.enabled(Feature::CodeModeToolDescriptionFirst);
|
||||
let mut enabled_tools = Vec::with_capacity(self.nested_tool_specs.len());
|
||||
for (spec, cached_runtime) in &self.nested_tool_specs {
|
||||
let definitions = prepare_code_mode_tool_definitions(
|
||||
cached_runtime.as_deref(),
|
||||
|| Cow::Borrowed(spec.as_ref()),
|
||||
code_mode_input_schema_max_bytes,
|
||||
tool_description_first,
|
||||
);
|
||||
match definitions {
|
||||
Cow::Borrowed(definitions) => enabled_tools.extend_from_slice(definitions),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//! Prepares nested tool definitions for execution and search.
|
||||
//! Cached definitions stay borrowed; rendered schemas are dropped after augmentation.
|
||||
//! Description order follows the session-static feature setting.
|
||||
|
||||
use crate::tools::registry::CoreToolRuntime;
|
||||
use codex_code_mode::ToolDefinition;
|
||||
@@ -11,12 +10,10 @@ pub(crate) fn prepare_code_mode_tool_definitions<'a>(
|
||||
runtime: Option<&'a dyn CoreToolRuntime>,
|
||||
spec: impl FnOnce() -> Cow<'a, ToolSpec>,
|
||||
code_mode_input_schema_max_bytes: Option<usize>,
|
||||
tool_description_first: bool,
|
||||
) -> Cow<'a, [ToolDefinition]> {
|
||||
if let Some(definitions) = runtime.and_then(|runtime| {
|
||||
runtime
|
||||
.cached_code_mode_definitions(code_mode_input_schema_max_bytes, tool_description_first)
|
||||
}) {
|
||||
if let Some(definitions) = runtime
|
||||
.and_then(|runtime| runtime.cached_code_mode_definitions(code_mode_input_schema_max_bytes))
|
||||
{
|
||||
return Cow::Borrowed(definitions);
|
||||
}
|
||||
|
||||
@@ -24,7 +21,6 @@ pub(crate) fn prepare_code_mode_tool_definitions<'a>(
|
||||
let mut definitions = codex_tools::collect_code_mode_tool_definitions(
|
||||
std::iter::once(spec.as_ref()),
|
||||
code_mode_input_schema_max_bytes,
|
||||
tool_description_first,
|
||||
);
|
||||
for definition in &mut definitions {
|
||||
definition.input_schema = None;
|
||||
|
||||
@@ -90,8 +90,7 @@ impl McpHandlerDefinition {
|
||||
|
||||
pub struct McpHandler {
|
||||
definition: Arc<McpHandlerDefinition>,
|
||||
code_mode_tool_definitions:
|
||||
OnceLock<(Option<usize>, bool, Vec<codex_code_mode::ToolDefinition>)>,
|
||||
code_mode_tool_definitions: OnceLock<(Option<usize>, Vec<codex_code_mode::ToolDefinition>)>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -330,29 +329,19 @@ impl CoreToolRuntime for McpHandler {
|
||||
fn cached_code_mode_definitions(
|
||||
&self,
|
||||
code_mode_input_schema_max_bytes: Option<usize>,
|
||||
tool_description_first: bool,
|
||||
) -> Option<&[codex_code_mode::ToolDefinition]> {
|
||||
let (cached_budget, cached_tool_description_first, definitions) =
|
||||
self.code_mode_tool_definitions.get_or_init(|| {
|
||||
let mut definitions = codex_tools::collect_code_mode_tool_definitions(
|
||||
std::iter::once(self.definition.spec.as_ref()),
|
||||
code_mode_input_schema_max_bytes,
|
||||
tool_description_first,
|
||||
);
|
||||
for definition in &mut definitions {
|
||||
definition.input_schema = None;
|
||||
definition.output_schema = None;
|
||||
}
|
||||
(
|
||||
code_mode_input_schema_max_bytes,
|
||||
tool_description_first,
|
||||
definitions,
|
||||
)
|
||||
});
|
||||
// Reuse definitions only when both rendering inputs match.
|
||||
(*cached_budget == code_mode_input_schema_max_bytes
|
||||
&& *cached_tool_description_first == tool_description_first)
|
||||
.then_some(definitions.as_slice())
|
||||
let (cached_budget, definitions) = self.code_mode_tool_definitions.get_or_init(|| {
|
||||
let mut definitions = codex_tools::collect_code_mode_tool_definitions(
|
||||
std::iter::once(self.definition.spec.as_ref()),
|
||||
code_mode_input_schema_max_bytes,
|
||||
);
|
||||
for definition in &mut definitions {
|
||||
definition.input_schema = None;
|
||||
definition.output_schema = None;
|
||||
}
|
||||
(code_mode_input_schema_max_bytes, definitions)
|
||||
});
|
||||
(*cached_budget == code_mode_input_schema_max_bytes).then_some(definitions.as_slice())
|
||||
}
|
||||
|
||||
fn wait_until_ready<'a>(&'a self, session: &'a Arc<Session>) -> Option<BoxFuture<'a, ()>> {
|
||||
@@ -905,36 +894,17 @@ mod tests {
|
||||
));
|
||||
|
||||
let first = handler
|
||||
.cached_code_mode_definitions(
|
||||
/*code_mode_input_schema_max_bytes*/ None,
|
||||
/*tool_description_first*/ false,
|
||||
)
|
||||
.cached_code_mode_definitions(/*code_mode_input_schema_max_bytes*/ None)
|
||||
.expect("MCP definitions should be cached");
|
||||
assert_eq!(first.len(), 1);
|
||||
assert!(first[0].input_schema.is_none());
|
||||
assert!(first[0].output_schema.is_none());
|
||||
|
||||
assert!(
|
||||
handler
|
||||
.cached_code_mode_definitions(
|
||||
/*code_mode_input_schema_max_bytes*/ None,
|
||||
/*tool_description_first*/ true,
|
||||
)
|
||||
.is_none()
|
||||
);
|
||||
|
||||
let second = handler
|
||||
.cached_code_mode_definitions(
|
||||
/*code_mode_input_schema_max_bytes*/ None,
|
||||
/*tool_description_first*/ false,
|
||||
)
|
||||
.cached_code_mode_definitions(/*code_mode_input_schema_max_bytes*/ None)
|
||||
.expect("MCP definitions should be cached");
|
||||
assert!(std::ptr::eq(first, second));
|
||||
assert!(
|
||||
handler
|
||||
.cached_code_mode_definitions(Some(32_000), /*tool_description_first*/ false)
|
||||
.is_none()
|
||||
);
|
||||
assert!(handler.cached_code_mode_definitions(Some(32_000)).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -15,7 +15,6 @@ use bm25::Embedder;
|
||||
use bm25::EmbedderBuilder;
|
||||
use bm25::Language;
|
||||
use bm25::Scorer;
|
||||
use codex_features::Feature;
|
||||
use codex_prompts::ResolvedModelMessages;
|
||||
use codex_tools::IndirectNamespacePrefixes;
|
||||
use codex_tools::JsonToolOutput;
|
||||
@@ -260,11 +259,6 @@ impl ToolSearchHandler {
|
||||
.config
|
||||
.code_mode
|
||||
.tool_input_schema_max_bytes,
|
||||
step_context
|
||||
.turn
|
||||
.config
|
||||
.features
|
||||
.enabled(Feature::CodeModeToolDescriptionFirst),
|
||||
&indirect_prefixes,
|
||||
);
|
||||
return Ok(boxed_tool_output(JsonToolOutput::new(serde_json::json!({
|
||||
@@ -292,7 +286,6 @@ impl ToolSearchHandler {
|
||||
limit: usize,
|
||||
router: &ToolRouter,
|
||||
code_mode_input_schema_max_bytes: Option<usize>,
|
||||
tool_description_first: bool,
|
||||
indirect_prefixes: &IndirectNamespacePrefixes<'_>,
|
||||
) -> Vec<CodeModeSearchResult> {
|
||||
let mut tools = Vec::new();
|
||||
@@ -320,7 +313,6 @@ impl ToolSearchHandler {
|
||||
tool.cached_runtime().map(Arc::as_ref),
|
||||
|| Cow::Owned(Arc::unwrap_or_clone(tool.spec())),
|
||||
code_mode_input_schema_max_bytes,
|
||||
tool_description_first,
|
||||
);
|
||||
let Some(definition) = definitions.iter().find(|definition| {
|
||||
definition.tool_name.clone().with_default_namespace() == candidate_name
|
||||
|
||||
@@ -84,11 +84,10 @@ pub(crate) trait CoreToolRuntime: ToolExecutor<ToolInvocation> {
|
||||
|
||||
/// Returns lazily cached, augmented Code Mode definitions owned by this runtime.
|
||||
/// Input and output schemas must be cleared after rendering their declarations.
|
||||
/// Return None when the requested rendering inputs differ from the cached inputs.
|
||||
/// Return None when the requested schema budget differs from the cached budget.
|
||||
fn cached_code_mode_definitions(
|
||||
&self,
|
||||
_code_mode_input_schema_max_bytes: Option<usize>,
|
||||
_tool_description_first: bool,
|
||||
) -> Option<&[codex_code_mode::ToolDefinition]> {
|
||||
None
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user