Add root turn IDs to turn and tool analytics (#40486)

## Why

Analytics need to associate subagent activity with the top-level turn that
caused it, while avoiding a stale association when steering makes that origin
ambiguous.

## What changed

- Add `root_turn_id` to turn and tool-item analytics events.
- Read the root from live turn metadata when each event is built, reporting
  `null` when the root is unknown or ambiguous.
- Propagate the metadata through control-tool and code-mode completion facts so
  correlated and background tool events retain the correct root.

## Testing

- Cover root IDs for top-level turns, subagent turns, correlated code-mode
  calls, and tool events emitted after turn completion.
- Verify that queued and subsequent events report `null` after the live root is
  invalidated.

GitOrigin-RevId: 42fd76541c3c716cec74787d47b50adb2d22e6d2
This commit is contained in:
Eddie Chen authored and copyberry committed 2026-08-24 22:30:59 +00:00
1 parent 0280d73c1e
commit 49880081fe
13 files changed
+439 -30

No files matched your search

@@ -168,6 +168,7 @@ impl CodeModeExecuteHandler {
session.services.analytics_events_client.clone(),
session.thread_id.to_string(),
turn.sub_id.clone(),
turn.turn_metadata_state.clone(),
call_id.clone(),
PUBLIC_TOOL_NAME,
);
@@ -1,11 +1,14 @@
use codex_analytics::AnalyticsEventsClient;
use codex_analytics::CodeModeToolCallFact;
use codex_analytics::CodeModeToolCallStatus;
use codex_analytics::TurnAnalyticsMetadata;
use std::sync::Arc;
pub(super) struct CodeModeToolCallGuard {
analytics: AnalyticsEventsClient,
thread_id: String,
turn_id: String,
turn_metadata: Arc<dyn TurnAnalyticsMetadata>,
call_id: String,
pub(super) cell_id: Option<String>,
tool_name: &'static str,
@@ -18,6 +21,7 @@ impl CodeModeToolCallGuard {
analytics: AnalyticsEventsClient,
thread_id: String,
turn_id: String,
turn_metadata: Arc<dyn TurnAnalyticsMetadata>,
call_id: String,
tool_name: &'static str,
) -> Self {
@@ -25,6 +29,7 @@ impl CodeModeToolCallGuard {
analytics,
thread_id,
turn_id,
turn_metadata,
call_id,
cell_id: None,
tool_name,
@@ -48,6 +53,7 @@ impl Drop for CodeModeToolCallGuard {
.track_code_mode_tool_call(CodeModeToolCallFact::Completed {
thread_id: self.thread_id.clone(),
turn_id: self.turn_id.clone(),
turn_metadata: self.turn_metadata.clone(),
call_id: self.call_id.clone(),
cell_id: self.cell_id.clone(),
tool_name: self.tool_name.to_string(),
@@ -77,6 +77,7 @@ impl CodeModeWaitHandler {
session.services.analytics_events_client.clone(),
session.thread_id.to_string(),
turn.sub_id.clone(),
turn.turn_metadata_state.clone(),
call_id.clone(),
WAIT_TOOL_NAME,
);