Files
codex/codex-rs/ext/extension-api/src/contributors/tools.rs
T
jif-oai 9c5dfa7b1a Refactor extension tools onto shared ToolExecutor (#22369)
## Why

Extension tools were split across two public runtime contracts:
`codex-tool-api` exposed `ToolBundle` plus its own call/spec/error
types, while core native tools used `codex_tools::ToolExecutor`. That
made contributed tool specs and execution behavior easy to drift apart
and added another crate boundary for what should be one executable-tool
seam.

This PR makes `ToolExecutor` the single runtime contract and keeps
extension-specific pinning in `codex-extension-api`.

## Remaining todo

https://github.com/openai/codex/pull/22369/changes#diff-b935ea8245c3ce568a30cff660175fa6390b66b872ae409e1e2e965738250741R5
Either generic `Invocation` or sub-extract the `ToolCall` and clean
`ToolInvocation`

## What changed

- Removed the `codex-tool-api` workspace crate and its dependencies from
core and `codex-extension-api`.
- Made `codex_tools::ToolExecutor` object-safe with `async_trait` so
extension contributors can return a dyn executor.
- Added the extension-facing aliases under
`ext/extension-api/src/contributors/tools.rs`, including
`ExtensionToolExecutor = dyn ToolExecutor<ToolCall, Output =
ExtensionToolOutput>`.
- Changed `ToolContributor::tools` to return extension executors
directly instead of `ToolBundle`s.
- Updated core’s extension tool handler/registry/router path to adapt
those extension executors into the existing native `ToolInvocation`
runtime path.
- Added focused coverage for extension tools being registered,
model-visible, dispatchable, and not replacing built-in tools.

## Verification

- `cargo test -p codex-tools`
- `cargo test -p codex-extension-api`
2026-05-13 12:12:06 +02:00

33 lines
1.1 KiB
Rust

use std::future::Future;
use std::pin::Pin;
use codex_tools::FunctionCallError;
use codex_tools::JsonToolOutput;
use codex_tools::ToolCall;
use codex_tools::ToolName;
use codex_tools::ToolSpec;
/// Model-facing output returned by extension-owned tools.
pub type ExtensionToolOutput = JsonToolOutput;
/// Future returned by extension-owned tool execution.
pub type ExtensionToolFuture<'a> =
Pin<Box<dyn Future<Output = Result<ExtensionToolOutput, FunctionCallError>> + Send + 'a>>;
/// Object-safe runtime contract for extension-owned model-visible tools.
///
/// Implementations keep an extension tool's model-visible spec attached to the
/// executable runtime that handles calls for that tool.
pub trait ExtensionToolExecutor: Send + Sync {
/// The concrete tool name handled by this extension runtime.
fn tool_name(&self) -> ToolName;
/// The model-visible spec for this extension tool.
fn spec(&self) -> Option<ToolSpec> {
None
}
/// Execute one extension tool invocation.
fn handle(&self, call: ToolCall) -> ExtensionToolFuture<'_>;
}