mirror of
https://github.com/openai/codex.git
synced 2026-10-29 16:09:06 +00:00
## 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`
114 lines
4.3 KiB
Rust
114 lines
4.3 KiB
Rust
use crate::shell::Shell;
|
|
use crate::shell::ShellType;
|
|
use crate::tools::flat_tool_name;
|
|
use crate::tools::handlers::multi_agents_common::DEFAULT_WAIT_TIMEOUT_MS;
|
|
use crate::tools::handlers::multi_agents_common::MAX_WAIT_TIMEOUT_MS;
|
|
use crate::tools::handlers::multi_agents_common::MIN_WAIT_TIMEOUT_MS;
|
|
use crate::tools::handlers::multi_agents_spec::WaitAgentTimeoutOptions;
|
|
use crate::tools::registry::ToolRegistryBuilder;
|
|
use crate::tools::spec_plan::build_tool_registry_builder;
|
|
use crate::tools::spec_plan_types::ToolRegistryBuildParams;
|
|
use codex_mcp::ToolInfo;
|
|
use codex_protocol::dynamic_tools::DynamicToolSpec;
|
|
use codex_tool_api::ToolBundle as ExtensionToolBundle;
|
|
use codex_tools::AdditionalProperties;
|
|
use codex_tools::DiscoverableTool;
|
|
use codex_tools::JsonSchema;
|
|
use codex_tools::ResponsesApiTool;
|
|
use codex_tools::ToolName;
|
|
use codex_tools::ToolUserShellType;
|
|
use codex_tools::ToolsConfig;
|
|
use std::collections::HashSet;
|
|
use std::sync::Arc;
|
|
|
|
pub(crate) fn tool_user_shell_type(user_shell: &Shell) -> ToolUserShellType {
|
|
match user_shell.shell_type {
|
|
ShellType::Zsh => ToolUserShellType::Zsh,
|
|
ShellType::Bash => ToolUserShellType::Bash,
|
|
ShellType::PowerShell => ToolUserShellType::PowerShell,
|
|
ShellType::Sh => ToolUserShellType::Sh,
|
|
ShellType::Cmd => ToolUserShellType::Cmd,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn build_specs_with_discoverable_tools(
|
|
config: &ToolsConfig,
|
|
mcp_tools: Option<Vec<ToolInfo>>,
|
|
deferred_mcp_tools: Option<Vec<ToolInfo>>,
|
|
unavailable_called_tools: Vec<ToolName>,
|
|
discoverable_tools: Option<Vec<DiscoverableTool>>,
|
|
extension_tool_bundles: &[ExtensionToolBundle],
|
|
dynamic_tools: &[DynamicToolSpec],
|
|
) -> ToolRegistryBuilder {
|
|
use crate::tools::handlers::UnavailableToolHandler;
|
|
use crate::tools::handlers::unavailable_tool_message;
|
|
|
|
let default_agent_type_description =
|
|
crate::agent::role::spawn_tool_spec::build(&std::collections::BTreeMap::new());
|
|
let min_wait_timeout_ms = if config.multi_agent_v2 {
|
|
config
|
|
.wait_agent_min_timeout_ms
|
|
.unwrap_or(MIN_WAIT_TIMEOUT_MS)
|
|
.clamp(1, MAX_WAIT_TIMEOUT_MS)
|
|
} else {
|
|
MIN_WAIT_TIMEOUT_MS
|
|
};
|
|
let default_wait_timeout_ms =
|
|
DEFAULT_WAIT_TIMEOUT_MS.clamp(min_wait_timeout_ms, MAX_WAIT_TIMEOUT_MS);
|
|
let mut builder = build_tool_registry_builder(
|
|
config,
|
|
ToolRegistryBuildParams {
|
|
mcp_tools: mcp_tools.as_deref(),
|
|
deferred_mcp_tools: deferred_mcp_tools.as_deref(),
|
|
discoverable_tools: discoverable_tools.as_deref(),
|
|
extension_tool_bundles,
|
|
dynamic_tools,
|
|
default_agent_type_description: &default_agent_type_description,
|
|
wait_agent_timeouts: WaitAgentTimeoutOptions {
|
|
default_timeout_ms: default_wait_timeout_ms,
|
|
min_timeout_ms: min_wait_timeout_ms,
|
|
max_timeout_ms: MAX_WAIT_TIMEOUT_MS,
|
|
},
|
|
},
|
|
);
|
|
let mut existing_spec_names = builder
|
|
.specs()
|
|
.iter()
|
|
.map(|configured_tool| configured_tool.name().to_string())
|
|
.collect::<HashSet<_>>();
|
|
|
|
for unavailable_tool in unavailable_called_tools {
|
|
let tool_name = flat_tool_name(&unavailable_tool).into_owned();
|
|
if existing_spec_names.insert(tool_name.clone()) {
|
|
let spec = codex_tools::ToolSpec::Function(ResponsesApiTool {
|
|
name: tool_name.clone(),
|
|
description: unavailable_tool_message(
|
|
&tool_name,
|
|
"Calling this placeholder returns an error explaining that the tool is unavailable.",
|
|
),
|
|
strict: false,
|
|
parameters: JsonSchema::object(
|
|
Default::default(),
|
|
/*required*/ None,
|
|
Some(AdditionalProperties::Boolean(false)),
|
|
),
|
|
output_schema: None,
|
|
defer_loading: None,
|
|
});
|
|
builder.register_handler(Arc::new(UnavailableToolHandler::new(
|
|
unavailable_tool,
|
|
spec,
|
|
)));
|
|
} else {
|
|
builder.register_handler(Arc::new(UnavailableToolHandler::without_spec(
|
|
unavailable_tool,
|
|
)));
|
|
}
|
|
}
|
|
builder
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "spec_tests.rs"]
|
|
mod tests;
|