chore: refactor tool handling (#4510)
# Tool System Refactor - Centralizes tool definitions and execution in `core/src/tools/*`: specs (`spec.rs`), handlers (`handlers/*`), router (`router.rs`), registry/dispatch (`registry.rs`), and shared context (`context.rs`). One registry now builds the model-visible tool list and binds handlers. - Router converts model responses to tool calls; Registry dispatches with consistent telemetry via `codex-rs/otel` and unified error handling. Function, Local Shell, MCP, and experimental `unified_exec` all flow through this path; legacy shell aliases still work. - Rationale: reduce per‑tool boilerplate, keep spec/handler in sync, and make adding tools predictable and testable. Example: `read_file` - Spec: `core/src/tools/spec.rs` (see `create_read_file_tool`, registered by `build_specs`). - Handler: `core/src/tools/handlers/read_file.rs` (absolute `file_path`, 1‑indexed `offset`, `limit`, `L#: ` prefixes, safe truncation). - E2E test: `core/tests/suite/read_file.rs` validates the tool returns the requested lines. ## Next steps: - Decompose `handle_container_exec_with_params` - Add parallel tool calls
This commit is contained in:
@@ -14,6 +14,7 @@ use eventsource_stream::EventStreamError as StreamError;
|
||||
use reqwest::Error;
|
||||
use reqwest::Response;
|
||||
use serde::Serialize;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Display;
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
@@ -366,10 +367,10 @@ impl OtelEventManager {
|
||||
call_id: &str,
|
||||
arguments: &str,
|
||||
f: F,
|
||||
) -> Result<String, E>
|
||||
) -> Result<(String, bool), E>
|
||||
where
|
||||
F: FnOnce() -> Fut,
|
||||
Fut: Future<Output = Result<String, E>>,
|
||||
Fut: Future<Output = Result<(String, bool), E>>,
|
||||
E: Display,
|
||||
{
|
||||
let start = Instant::now();
|
||||
@@ -377,10 +378,12 @@ impl OtelEventManager {
|
||||
let duration = start.elapsed();
|
||||
|
||||
let (output, success) = match &result {
|
||||
Ok(content) => (content, true),
|
||||
Err(error) => (&error.to_string(), false),
|
||||
Ok((preview, success)) => (Cow::Borrowed(preview.as_str()), *success),
|
||||
Err(error) => (Cow::Owned(error.to_string()), false),
|
||||
};
|
||||
|
||||
let success_str = if success { "true" } else { "false" };
|
||||
|
||||
tracing::event!(
|
||||
tracing::Level::INFO,
|
||||
event.name = "codex.tool_result",
|
||||
@@ -396,7 +399,8 @@ impl OtelEventManager {
|
||||
call_id = %call_id,
|
||||
arguments = %arguments,
|
||||
duration_ms = %duration.as_millis(),
|
||||
success = %success,
|
||||
success = %success_str,
|
||||
// `output` is truncated by the tool layer before reaching telemetry.
|
||||
output = %output,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user