From 46d53a2430595cc5c8759c429f2a2a76a29b5dc6 Mon Sep 17 00:00:00 2001 From: jimmyfraiture Date: Wed, 1 Oct 2025 09:16:27 +0100 Subject: [PATCH] Fix otel race condition --- codex-rs/core/src/tools/registry.rs | 49 +++++++++++++++++++++++------ codex-rs/exec/src/lib.rs | 2 +- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/codex-rs/core/src/tools/registry.rs b/codex-rs/core/src/tools/registry.rs index 23e712b34c..24b62445fa 100644 --- a/codex-rs/core/src/tools/registry.rs +++ b/codex-rs/core/src/tools/registry.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::sync::Arc; +use std::time::Duration; use async_trait::async_trait; use codex_protocol::models::ResponseInputItem; @@ -61,19 +62,40 @@ impl ToolRegistry { invocation: ToolInvocation<'a>, ) -> Result { let tool_name = invocation.tool_name.clone(); - let handler = self.handler(tool_name.as_ref()).ok_or_else(|| { - FunctionCallError::RespondToModel(format!("unsupported call: {tool_name}")) - })?; - - if !handler.matches_kind(&invocation.payload) { - return Err(FunctionCallError::RespondToModel(format!( - "tool {tool_name} invoked with incompatible payload" - ))); - } - let call_id_owned = invocation.call_id.clone(); let otel = invocation.turn.client.get_otel_event_manager(); let log_payload = invocation.payload.log_payload().into_owned(); + + let handler = match self.handler(tool_name.as_ref()) { + Some(handler) => handler, + None => { + let message = + unsupported_tool_call_message(&invocation.payload, tool_name.as_ref()); + otel.tool_result( + tool_name.as_ref(), + &call_id_owned, + &log_payload, + Duration::ZERO, + false, + &message, + ); + return Err(FunctionCallError::RespondToModel(message)); + } + }; + + if !handler.matches_kind(&invocation.payload) { + let message = format!("tool {tool_name} invoked with incompatible payload"); + otel.tool_result( + tool_name.as_ref(), + &call_id_owned, + &log_payload, + Duration::ZERO, + false, + &message, + ); + return Err(FunctionCallError::RespondToModel(message)); + } + let output_cell = std::sync::Mutex::new(None); let result = otel @@ -156,3 +178,10 @@ impl ToolRegistryBuilder { ToolRegistry::new(self.handlers) } } + +fn unsupported_tool_call_message(payload: &ToolPayload, tool_name: &str) -> String { + match payload { + ToolPayload::Custom { .. } => format!("unsupported custom tool call: {tool_name}"), + _ => format!("unsupported call: {tool_name}"), + } +} diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs index bdf0365026..6aaba3734f 100644 --- a/codex-rs/exec/src/lib.rs +++ b/codex-rs/exec/src/lib.rs @@ -172,7 +172,7 @@ pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option) -> any codex_linux_sandbox_exe, base_instructions: None, include_plan_tool: Some(include_plan_tool), - include_apply_patch_tool: None, + include_apply_patch_tool: Some(true), include_view_image_tool: None, show_raw_agent_reasoning: oss.then_some(true), tools_web_search_request: None,