[codex] Move tool specs onto handlers (#21461)

## Why

This is the next stacked step after deleting the tool-handler kind
indirection. Specs should come from the registered handlers themselves
so registry construction has a single source of truth for handler
behavior and exposed tool definitions.

## What changed

- Added `ToolHandler::spec()` plus handler-provided parallel/code-mode
metadata, and made `ToolRegistryBuilder::register_handler` automatically
collect specs from registered handlers.
- Moved builtin tool spec construction into the corresponding handlers
and their adjacent `_spec` modules, including shell, unified exec, apply
patch, view image, request plugin install, tool search, MCP resource,
goals, planning, permissions, agent jobs, and multi-agent tools.
- Reworked configurable handlers to receive their tool-building options
through constructors, with non-optional handler options where the
handler is always spec-backed. Shell fallback handlers keep an explicit
no-spec mode because they are also registered as hidden dispatch
aliases.
- Kept `CodeModeExecuteHandler` on the explicit configured wrapper so
the code-mode exec spec can still be built from the nested registry.

## Verification

- `cargo check -p codex-core`
- `cargo test -p codex-core tools::spec_plan::tests`
- `cargo test -p codex-core tools::spec::tests`
- `cargo test -p codex-core tools::handlers::multi_agents_spec::tests`
- `RUST_MIN_STACK=16777216 cargo test -p codex-core
tools::handlers::multi_agents::tests`
- `cargo test -p codex-core tools::handlers::apply_patch::tests`
- `cargo test -p codex-core tools::handlers::unified_exec::tests`
- `just fix -p codex-core`
- `git diff --check`
This commit is contained in:
pakrym-oai
2026-05-07 10:48:36 -07:00
committed by GitHub
Unverified
parent eb0462f2af
commit 566f2cb612
51 changed files with 722 additions and 397 deletions
@@ -323,7 +323,7 @@ async fn guardian_allows_shell_additional_permissions_requests_past_policy_valid
arg0: None,
};
let handler = ShellHandler;
let handler = ShellHandler::default();
let resp = handler
.handle(ToolInvocation {
session: Arc::clone(&session),
@@ -437,7 +437,7 @@ async fn strict_auto_review_turn_grant_forces_guardian_for_shell_policy_skip() {
let session = Arc::new(session);
let turn_context = Arc::new(turn_context_raw);
let handler = ShellHandler;
let handler = ShellHandler::default();
let command = if cfg!(windows) {
vec![
"cmd.exe".to_string(),
@@ -498,7 +498,7 @@ async fn guardian_allows_unified_exec_additional_permissions_requests_past_polic
let turn_context = Arc::new(turn_context_raw);
let tracker = Arc::new(tokio::sync::Mutex::new(TurnDiffTracker::new()));
let handler = ExecCommandHandler;
let handler = ExecCommandHandler::default();
let resp = handler
.handle(ToolInvocation {
session: Arc::clone(&session),
@@ -615,7 +615,7 @@ async fn shell_handler_allows_sticky_turn_permissions_without_inline_request_per
let session = Arc::new(session);
let turn_context = Arc::new(turn_context_raw);
let handler = ShellHandler;
let handler = ShellHandler::default();
let resp = handler
.handle(ToolInvocation {
session: Arc::clone(&session),