[codex] Split tool handlers by tool name (#20687)

## Why

Tool registration used to bind a tool name to a handler externally,
which left ownership split between the registry plan and the handler
implementation. Some built-in handlers also multiplexed multiple in-core
tools by switching on the invoked tool name internally.

This moves the registry identity onto the handler itself and makes
built-in multi-tool areas use separate concrete handlers, so each
registered handler instance owns exactly one tool name and one dispatch
path.

## What Changed

- Added `ToolHandler::tool_name()` and changed
`ToolRegistryBuilder::register_handler` to derive the registry key from
the handler.
- Split built-in multiplexed handlers into concrete per-tool handlers
for unified exec, shell/local shell/container exec, MCP resources, goal
tools, and agent job tools.
- Kept name-carrying handler instances only where the runtime target is
inherently external or dynamic, such as MCP tools, dynamic tools, and
unavailable placeholders.
- Updated `ToolHandlerKind` and registry-plan construction so plan
entries map directly to concrete handler registrations.

## Verification

- `cargo test -p codex-tools tool_registry_plan`
- `cargo test -p codex-core --lib tools::registry_tests`
- `just fix -p codex-tools`
- `just fix -p codex-core`
This commit is contained in:
pakrym-oai
2026-05-05 13:46:45 -07:00
committed by GitHub
parent 9cbef243b5
commit f593323ef1
43 changed files with 1383 additions and 952 deletions
@@ -4,6 +4,7 @@ use crate::tools::context::ToolInvocation;
use crate::tools::context::ToolPayload;
use crate::tools::registry::ToolHandler;
use crate::tools::registry::ToolKind;
use codex_tools::ToolName;
use super::ExecContext;
use super::PUBLIC_TOOL_NAME;
@@ -78,6 +79,10 @@ impl CodeModeExecuteHandler {
impl ToolHandler for CodeModeExecuteHandler {
type Output = FunctionToolOutput;
fn tool_name(&self) -> ToolName {
ToolName::plain(PUBLIC_TOOL_NAME)
}
fn kind(&self) -> ToolKind {
ToolKind::Function
}
@@ -6,6 +6,7 @@ use crate::tools::context::ToolInvocation;
use crate::tools::context::ToolPayload;
use crate::tools::registry::ToolHandler;
use crate::tools::registry::ToolKind;
use codex_tools::ToolName;
use super::DEFAULT_WAIT_YIELD_TIME_MS;
use super::ExecContext;
@@ -41,6 +42,10 @@ where
impl ToolHandler for CodeModeWaitHandler {
type Output = FunctionToolOutput;
fn tool_name(&self) -> ToolName {
ToolName::plain(WAIT_TOOL_NAME)
}
fn kind(&self) -> ToolKind {
ToolKind::Function
}