mirror of
https://github.com/openai/codex.git
synced 2026-10-22 17:58:46 +00:00
## Why Tool results can be ready before the sampling loop collects them, and code-mode cells can outlive a turn. Separate trace milestones make these timings visible and link nested calls to the turn that dispatches them. ## What changed - Emit `codex.tool_call_received` and `codex.tool_result_ready` events for direct and code-mode calls, using identifiers and tool names without arguments or output. Record readiness before result encoding or collection, including ordinary errors and aborted responses, but excluding fatal errors. - Assign nested call IDs at broker receipt and carry them through dispatch. Trace dispatch and interruptions caused by cancellation, cell closure, or abandonment. - Add code-mode execute and wait handler spans with conversation, turn, call, and cell identifiers and `completed`, `failed`, or `interrupted` outcomes. GitOrigin-RevId: b098a29d8ee030c823665e4b1031a0d67cc09502
89 lines
2.3 KiB
Rust
89 lines
2.3 KiB
Rust
//! Trace milestones for every direct or code-mode tool call handled by core.
|
|
//! These events contain call identifiers and names, never arguments or output.
|
|
//! Code-mode calls reach the broker before the dispatching turn is known.
|
|
|
|
use codex_protocol::DEFAULT_FUNCTION_NAMESPACE;
|
|
use codex_protocol::ThreadId;
|
|
use codex_tools::ToolName;
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub(crate) enum Source {
|
|
Direct,
|
|
CodeMode,
|
|
}
|
|
|
|
impl Source {
|
|
fn as_str(self) -> &'static str {
|
|
match self {
|
|
Self::Direct => "direct",
|
|
Self::CodeMode => "code_mode",
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) enum Receipt<'a> {
|
|
ModelTurn(&'a str),
|
|
CodeModeBroker {
|
|
cell_id: Option<&'a str>,
|
|
runtime_tool_call_id: Option<&'a str>,
|
|
},
|
|
}
|
|
|
|
pub(crate) fn received(
|
|
thread_id: ThreadId,
|
|
tool_name: &ToolName,
|
|
call_id: &str,
|
|
receipt: Receipt<'_>,
|
|
) {
|
|
let (turn_id, source, cell_id, runtime_tool_call_id) = match receipt {
|
|
Receipt::ModelTurn(turn_id) => (Some(turn_id), Source::Direct, None, None),
|
|
Receipt::CodeModeBroker {
|
|
cell_id,
|
|
runtime_tool_call_id,
|
|
} => (None, Source::CodeMode, cell_id, runtime_tool_call_id),
|
|
};
|
|
tracing::event!(
|
|
name: "codex.tool_call_received",
|
|
target: "codex_otel.trace_safe",
|
|
tracing::Level::INFO,
|
|
event.name = "codex.tool_call_received",
|
|
conversation.id = %thread_id,
|
|
turn_id,
|
|
call_id,
|
|
tool_name = tool_name.name.as_str(),
|
|
tool_namespace = namespace(tool_name),
|
|
tool_source = source.as_str(),
|
|
cell.id = cell_id,
|
|
runtime_tool_call_id,
|
|
);
|
|
}
|
|
|
|
pub(crate) fn result_ready(
|
|
thread_id: ThreadId,
|
|
turn_id: &str,
|
|
tool_name: &ToolName,
|
|
call_id: &str,
|
|
source: Source,
|
|
) {
|
|
tracing::event!(
|
|
name: "codex.tool_result_ready",
|
|
target: "codex_otel.trace_safe",
|
|
tracing::Level::INFO,
|
|
event.name = "codex.tool_result_ready",
|
|
conversation.id = %thread_id,
|
|
turn_id,
|
|
call_id,
|
|
tool_name = tool_name.name.as_str(),
|
|
tool_namespace = namespace(tool_name),
|
|
tool_source = source.as_str(),
|
|
);
|
|
}
|
|
|
|
fn namespace(tool_name: &ToolName) -> &str {
|
|
tool_name
|
|
.namespace
|
|
.as_deref()
|
|
.filter(|namespace| !namespace.is_empty())
|
|
.unwrap_or(DEFAULT_FUNCTION_NAMESPACE)
|
|
}
|