Use generic search metadata for dynamic tools (#27356)

## Why

Dynamic tools maintained a separate search-text builder even though the
shared tool search path already derives the same metadata from
`ToolSpec`. Using the shared path removes duplicate behavior before
adding explicit namespaces.

## What changed

- Build dynamic-tool search entries with
`ToolSearchInfo::from_tool_spec`.
- Remove the custom search-text state and its implementation-only unit
test.

The old search text included the tool name, its space-separated form,
description, namespace, and top-level parameter names. The shared
builder preserves all of those terms and also indexes namespace
descriptions and nested schema metadata.

## Test plan

- `just test -p codex-core
tool_search_returns_deferred_dynamic_tool_and_routes_follow_up_call`
This commit is contained in:
sayan-oai
2026-06-10 23:06:34 -07:00
committed by GitHub
Unverified
parent 383708e74e
commit b5a718ef67
2 changed files with 1 additions and 64 deletions
+1 -28
View File
@@ -33,7 +33,6 @@ pub struct DynamicToolHandler {
tool_name: ToolName,
spec: ToolSpec,
exposure: ToolExposure,
search_text: String,
}
impl DynamicToolHandler {
@@ -56,7 +55,6 @@ impl DynamicToolHandler {
} else {
ToolExposure::Direct
},
search_text: build_dynamic_search_text(tool),
})
}
}
@@ -75,8 +73,7 @@ impl ToolExecutor<ToolInvocation> for DynamicToolHandler {
}
fn search_info(&self) -> Option<ToolSearchInfo> {
ToolSearchInfo::from_spec(
self.search_text.clone(),
ToolSearchInfo::from_tool_spec(
self.spec(),
Some(ToolSearchSourceInfo {
name: "Dynamic tools".to_string(),
@@ -217,27 +214,3 @@ async fn request_dynamic_tool(
response
}
fn build_dynamic_search_text(tool: &DynamicToolSpec) -> String {
let mut schema_properties = tool
.input_schema
.get("properties")
.and_then(serde_json::Value::as_object)
.map(|map| map.keys().cloned().collect::<Vec<_>>())
.unwrap_or_default();
schema_properties.sort();
let mut parts = vec![
tool.name.clone(),
tool.name.replace('_', " "),
tool.description.clone(),
];
if let Some(namespace) = &tool.namespace {
parts.push(namespace.clone());
}
parts.extend(schema_properties);
parts.join(" ")
}
#[cfg(test)]
#[path = "dynamic_tests.rs"]
mod tests;
@@ -1,36 +0,0 @@
use super::*;
use codex_tools::ToolSearchSourceInfo;
use pretty_assertions::assert_eq;
use serde_json::json;
#[test]
fn search_info_uses_dynamic_tool_metadata_and_parameter_names() {
let handler = DynamicToolHandler::new(&DynamicToolSpec {
namespace: Some("codex_app".to_string()),
name: "automation_update".to_string(),
description: "Create or update automations.".to_string(),
input_schema: json!({
"type": "object",
"properties": {
"timezone": { "type": "string" },
"mode": { "type": "string" }
}
}),
defer_loading: true,
})
.expect("dynamic handler should be created");
let search_info = handler.search_info().expect("dynamic search info");
assert_eq!(
search_info.entry.search_text,
"automation_update automation update Create or update automations. codex_app mode timezone"
);
assert_eq!(
search_info.source_info,
Some(ToolSearchSourceInfo {
name: "Dynamic tools".to_string(),
description: Some("Tools provided by the current Codex thread.".to_string()),
})
);
}