mirror of
https://github.com/openai/codex.git
synced 2026-11-13 06:45:07 +00:00
Encapsulate tool search entries in handlers (#22261)
## Why This builds on the handler-owned spec refactor by moving deferred tool-search metadata to the same handlers that already own tool specs. The registry builder no longer needs a separate prebuilt `tool_search_entries` path; it can collect searchable entries from deferred handlers directly. ## What changed - Added `search_info()` to tool handlers and implemented it for MCP and dynamic handlers. - Reused handler `spec()` output when constructing tool-search entries, adapting it into the deferred `LoadableToolSpec` shape expected by `tool_search`. - Simplified `build_tool_registry_builder(...)` so `tool_search` registration is based on deferred handlers with search info. - Removed the old standalone search-entry builders and now-unused `codex-tools` discovery helper exports. ## Verification - `cargo test -p codex-core tools::handlers::tool_search::tests:: -- --nocapture` - `cargo test -p codex-core tools::spec_plan::tests::search_tool -- --nocapture` - `cargo test -p codex-core tools::spec::tests:: -- --nocapture` - `cargo test -p codex-core tools::spec_plan::tests:: -- --nocapture` - `cargo test -p codex-tools` - `just fix -p codex-core` - `just fix -p codex-tools`
This commit is contained in:
1 parent
67c8486462
commit
104fc14956
15 files changed
+345
-460
No files matched your search
@@ -1,9 +1,3 @@
|
||||
use crate::LoadableToolSpec;
|
||||
use crate::ResponsesApiNamespace;
|
||||
use crate::ResponsesApiNamespaceTool;
|
||||
use crate::ToolName;
|
||||
use crate::default_namespace_description;
|
||||
use crate::mcp_tool_to_deferred_responses_api_tool;
|
||||
use codex_app_server_protocol::AppInfo;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -19,23 +13,6 @@ pub struct ToolSearchSourceInfo {
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct ToolSearchSource<'a> {
|
||||
pub server_name: &'a str,
|
||||
pub connector_name: Option<&'a str>,
|
||||
pub description: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct ToolSearchResultSource<'a> {
|
||||
pub server_name: &'a str,
|
||||
pub tool_namespace: &'a str,
|
||||
pub tool_name: &'a str,
|
||||
pub tool: &'a rmcp::model::Tool,
|
||||
pub connector_name: Option<&'a str>,
|
||||
pub description: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum DiscoverableToolType {
|
||||
@@ -133,78 +110,6 @@ pub struct RequestPluginInstallEntry {
|
||||
pub app_connector_ids: Vec<String>,
|
||||
}
|
||||
|
||||
pub fn tool_search_result_source_to_loadable_tool_spec(
|
||||
source: ToolSearchResultSource<'_>,
|
||||
) -> Result<LoadableToolSpec, serde_json::Error> {
|
||||
Ok(LoadableToolSpec::Namespace(ResponsesApiNamespace {
|
||||
name: source.tool_namespace.to_string(),
|
||||
description: tool_search_result_source_namespace_description(source),
|
||||
tools: vec![tool_search_result_source_to_namespace_tool(source)?],
|
||||
}))
|
||||
}
|
||||
|
||||
fn tool_search_result_source_namespace_description(source: ToolSearchResultSource<'_>) -> String {
|
||||
source
|
||||
.description
|
||||
.map(str::trim)
|
||||
.filter(|description| !description.is_empty())
|
||||
.map(str::to_string)
|
||||
.or_else(|| {
|
||||
source
|
||||
.connector_name
|
||||
.map(str::trim)
|
||||
.filter(|connector_name| !connector_name.is_empty())
|
||||
.map(|connector_name| format!("Tools for working with {connector_name}."))
|
||||
})
|
||||
.unwrap_or_else(|| default_namespace_description(source.tool_namespace))
|
||||
}
|
||||
|
||||
fn tool_search_result_source_to_namespace_tool(
|
||||
source: ToolSearchResultSource<'_>,
|
||||
) -> Result<ResponsesApiNamespaceTool, serde_json::Error> {
|
||||
let tool_name = ToolName::namespaced(source.tool_namespace, source.tool_name);
|
||||
mcp_tool_to_deferred_responses_api_tool(&tool_name, source.tool)
|
||||
.map(ResponsesApiNamespaceTool::Function)
|
||||
}
|
||||
|
||||
pub fn collect_tool_search_source_infos<'a>(
|
||||
searchable_tools: impl IntoIterator<Item = ToolSearchSource<'a>>,
|
||||
) -> Vec<ToolSearchSourceInfo> {
|
||||
searchable_tools
|
||||
.into_iter()
|
||||
.filter_map(|tool| {
|
||||
if let Some(name) = tool
|
||||
.connector_name
|
||||
.map(str::trim)
|
||||
.filter(|connector_name| !connector_name.is_empty())
|
||||
{
|
||||
return Some(ToolSearchSourceInfo {
|
||||
name: name.to_string(),
|
||||
description: tool
|
||||
.description
|
||||
.map(str::trim)
|
||||
.filter(|description| !description.is_empty())
|
||||
.map(str::to_string),
|
||||
});
|
||||
}
|
||||
|
||||
let name = tool.server_name.trim();
|
||||
if name.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(ToolSearchSourceInfo {
|
||||
name: name.to_string(),
|
||||
description: tool
|
||||
.description
|
||||
.map(str::trim)
|
||||
.filter(|description| !description.is_empty())
|
||||
.map(str::to_string),
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn collect_request_plugin_install_entries(
|
||||
discoverable_tools: &[DiscoverableTool],
|
||||
) -> Vec<RequestPluginInstallEntry> {
|
||||
|
||||
Reference in new issue
Block a user