Files
codex/codex-rs/tools/src/tool_executor.rs
T
jif-oai fdda59c00b Introduce tool exposure for deferred registration (#22489)
## Why

Deferred tools were tracked with separate side-channel filtering after
tool specs had already been assembled. That made the registry
responsible for executing tools while the router/spec planner separately
decided whether those same tools should be exposed to the model up
front.

This PR makes exposure part of the tool handler contract so direct
versus deferred availability travels with the executable tool
registration.

Next step will be to simplify registration

## What Changed

- Adds `ToolExposure` to `codex-tools` and exposes it through
`ToolExecutor`, defaulting tools to `Direct`.
- Teaches dynamic tools and MCP handlers to mark deferred tools as
`Deferred` at construction time.
- Renames the registry object-safe wrapper from `AnyToolHandler` to
`RegisteredTool` and uses `ToolExposure` when deciding whether to
include a handler's spec in the initial model-visible tool list.
- Refactors tool spec planning to derive direct specs and deferred
search entries from registered handlers, removing the router's
special-case deferred dynamic tool filtering.

## Verification

- Not run.
2026-05-13 18:16:51 +02:00

44 lines
1.1 KiB
Rust

use std::future::Future;
use crate::FunctionCallError;
use crate::ToolName;
use crate::ToolOutput;
use crate::ToolSpec;
/// Controls whether a tool is exposed in the initial model-visible tool list
/// or registered for later discovery.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ToolExposure {
Direct,
Deferred,
}
/// Shared runtime contract for model-visible tools.
///
/// Implementations keep the model-visible spec tied to the executable runtime.
/// Host crates can layer routing, hooks, telemetry, or other orchestration on
/// top without reopening the spec/runtime split.
pub trait ToolExecutor<Invocation>: Send + Sync {
type Output: ToolOutput + 'static;
/// The concrete tool name handled by this runtime instance.
fn tool_name(&self) -> ToolName;
fn spec(&self) -> Option<ToolSpec> {
None
}
fn exposure(&self) -> ToolExposure {
ToolExposure::Direct
}
fn supports_parallel_tool_calls(&self) -> bool {
false
}
fn handle(
&self,
invocation: Invocation,
) -> impl Future<Output = Result<Self::Output, FunctionCallError>> + Send;
}