From 372c069d9d8b44a38949551453e8d57c9ecb2228 Mon Sep 17 00:00:00 2001 From: Roy Han Date: Wed, 25 Mar 2026 15:43:15 -0700 Subject: [PATCH 1/2] move up source data fetching --- codex-rs/core/src/codex.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 68b6a296e6..46472e9c8e 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -639,6 +639,8 @@ impl Codex { let initialization_mode = initialization_mode(&conversation_history); let thread_session_source = session_configuration.session_source.clone(); + let subagent_source = session_source_subagent_source(&thread_session_source); + let parent_thread_id = session_source_parent_thread_id(&thread_session_source); let thread_initialized_configuration = session_configuration.clone(); // Generate a unique ID for the lifetime of this Codex session. @@ -688,8 +690,8 @@ impl Codex { .ephemeral, session_source: thread_session_source, initialization_mode, - subagent_source: session_source_subagent_source(&thread_session_source), - parent_thread_id: session_source_parent_thread_id(&thread_session_source), + subagent_source, + parent_thread_id, }, }); From 71d88a63c21d7c3629b7665cba3311f336d976dd Mon Sep 17 00:00:00 2001 From: Roy Han Date: Wed, 25 Mar 2026 18:10:36 -0700 Subject: [PATCH 2/2] strengthen naming --- codex-rs/analytics/src/analytics_client.rs | 88 ++++++------------- .../analytics/src/analytics_client_tests.rs | 72 ++++++++------- codex-rs/analytics/src/lib.rs | 1 - .../{thread_metadata.rs => analytics.rs} | 0 codex-rs/core/tests/suite/mod.rs | 2 +- 5 files changed, 68 insertions(+), 95 deletions(-) rename codex-rs/core/tests/suite/{thread_metadata.rs => analytics.rs} (100%) diff --git a/codex-rs/analytics/src/analytics_client.rs b/codex-rs/analytics/src/analytics_client.rs index 30d679ef4a..5df326fb85 100644 --- a/codex-rs/analytics/src/analytics_client.rs +++ b/codex-rs/analytics/src/analytics_client.rs @@ -26,18 +26,6 @@ pub struct TrackEventsContext { pub turn_id: String, } -#[derive(Clone)] -pub struct CodexThreadInitializedEvent { - pub thread_id: String, - pub model: String, - pub ephemeral: bool, - pub session_source: SessionSource, - pub initialization_mode: InitializationMode, - pub subagent_source: Option, - pub parent_thread_id: Option, - pub created_at: u64, -} - #[derive(Clone)] pub struct CodexThreadInitializedInput { pub thread_id: String, @@ -98,7 +86,7 @@ pub struct AppInvocation { } pub enum AnalyticsInput { - ThreadInitialized(CodexThreadInitializedInput), + CodexThreadInitialized(CodexThreadInitializedInput), SkillInvoked(SkillInvokedInput), AppMentioned(AppMentionedInput), AppUsed(AppUsedInput), @@ -145,7 +133,7 @@ pub struct AnalyticsReducer { } struct ThreadState { - _initialized_event: CodexThreadInitializedEvent, + _initialized_input: CodexThreadInitializedInput, } #[derive(Clone)] @@ -243,7 +231,7 @@ impl AnalyticsEventsClient { } pub fn track_thread_initialized(&self, input: CodexThreadInitializedInput) { - self.record(AnalyticsInput::ThreadInitialized(input)); + self.record(AnalyticsInput::CodexThreadInitialized(input)); } pub fn track_app_mentioned(&self, tracking: TrackEventsContext, mentions: Vec) { @@ -330,7 +318,7 @@ struct TrackEventsRequest { #[serde(untagged)] enum TrackEventRequest { SkillInvocation(SkillInvocationEventRequest), - ThreadInitialized(CodexThreadInitializedEventRequest), + CodexThreadInitialized(CodexThreadInitializedEvent), AppMentioned(CodexAppMentionedEventRequest), AppUsed(CodexAppUsedEventRequest), PluginUsed(CodexPluginUsedEventRequest), @@ -372,7 +360,7 @@ struct CodexThreadInitializedEventParams { } #[derive(Serialize)] -struct CodexThreadInitializedEventRequest { +struct CodexThreadInitializedEvent { event_type: &'static str, event_params: CodexThreadInitializedEventParams, } @@ -435,7 +423,7 @@ struct CodexPluginUsedEventRequest { impl AnalyticsReducer { async fn ingest(&mut self, input: AnalyticsInput, out: &mut Vec) { match input { - AnalyticsInput::ThreadInitialized(input) => { + AnalyticsInput::CodexThreadInitialized(input) => { self.ingest_thread_initialized(input, out); } AnalyticsInput::SkillInvoked(input) => { @@ -461,25 +449,14 @@ impl AnalyticsReducer { input: CodexThreadInitializedInput, out: &mut Vec, ) { - let product_client_id = input.product_client_id.clone(); - let event = CodexThreadInitializedEvent { - thread_id: input.thread_id, - model: input.model, - ephemeral: input.thread_context.ephemeral, - session_source: input.thread_context.session_source, - initialization_mode: input.thread_context.initialization_mode, - subagent_source: input.thread_context.subagent_source, - parent_thread_id: input.thread_context.parent_thread_id, - created_at: input.created_at, - }; self.threads.insert( - event.thread_id.clone(), + input.thread_id.clone(), ThreadState { - _initialized_event: event.clone(), + _initialized_input: input.clone(), }, ); - out.push(TrackEventRequest::ThreadInitialized( - codex_thread_initialized_event_request(product_client_id, event), + out.push(TrackEventRequest::CodexThreadInitialized( + codex_thread_initialized_event_request(input), )); } @@ -599,40 +576,31 @@ fn codex_app_metadata(tracking: &TrackEventsContext, app: AppInvocation) -> Code } } -#[cfg(test)] -fn codex_thread_initialized_event_params( - thread_event: CodexThreadInitializedEvent, -) -> CodexThreadInitializedEventParams { - codex_thread_initialized_event_params_with_product_client_id(originator().value, thread_event) -} - fn codex_thread_initialized_event_request( - product_client_id: String, - thread_event: CodexThreadInitializedEvent, -) -> CodexThreadInitializedEventRequest { - CodexThreadInitializedEventRequest { + input: CodexThreadInitializedInput, +) -> CodexThreadInitializedEvent { + CodexThreadInitializedEvent { event_type: "codex_thread_initialized", - event_params: codex_thread_initialized_event_params_with_product_client_id( - product_client_id, - thread_event, - ), + event_params: codex_thread_initialized_event_params(input), } } -fn codex_thread_initialized_event_params_with_product_client_id( - product_client_id: String, - thread_event: CodexThreadInitializedEvent, +fn codex_thread_initialized_event_params( + input: CodexThreadInitializedInput, ) -> CodexThreadInitializedEventParams { CodexThreadInitializedEventParams { - thread_id: thread_event.thread_id, - product_client_id, - model: thread_event.model, - ephemeral: thread_event.ephemeral, - session_source: session_source_name(&thread_event.session_source), - initialization_mode: thread_event.initialization_mode, - subagent_source: thread_event.subagent_source.map(subagent_source_name), - parent_thread_id: thread_event.parent_thread_id, - created_at: thread_event.created_at, + thread_id: input.thread_id, + product_client_id: input.product_client_id, + model: input.model, + ephemeral: input.thread_context.ephemeral, + session_source: session_source_name(&input.thread_context.session_source), + initialization_mode: input.thread_context.initialization_mode, + subagent_source: input + .thread_context + .subagent_source + .map(subagent_source_name), + parent_thread_id: input.thread_context.parent_thread_id, + created_at: input.created_at, } } diff --git a/codex-rs/analytics/src/analytics_client_tests.rs b/codex-rs/analytics/src/analytics_client_tests.rs index eaac08430f..5e83c2aaf5 100644 --- a/codex-rs/analytics/src/analytics_client_tests.rs +++ b/codex-rs/analytics/src/analytics_client_tests.rs @@ -4,8 +4,8 @@ use super::CodexAppMentionedEventRequest; use super::CodexAppUsedEventRequest; use super::CodexPluginEventRequest; use super::CodexPluginUsedEventRequest; -use super::CodexThreadInitializedEvent; -use super::CodexThreadInitializedEventRequest; +use super::CodexThreadContext; +use super::CodexThreadInitializedInput; use super::InitializationMode; use super::InvocationType; use super::TrackEventRequest; @@ -13,7 +13,7 @@ use super::TrackEventsContext; use super::codex_app_metadata; use super::codex_plugin_metadata; use super::codex_plugin_used_metadata; -use super::codex_thread_initialized_event_params; +use super::codex_thread_initialized_event_request; use super::normalize_path_for_skill_id; use codex_login::default_client::originator; use codex_plugin::AppConnectorId; @@ -194,19 +194,21 @@ fn app_used_dedupe_is_keyed_by_turn_and_connector() { #[test] fn thread_initialized_event_serializes_expected_shape() { - let event = TrackEventRequest::ThreadInitialized(CodexThreadInitializedEventRequest { - event_type: "codex_thread_initialized", - event_params: codex_thread_initialized_event_params(CodexThreadInitializedEvent { + let event = TrackEventRequest::CodexThreadInitialized(codex_thread_initialized_event_request( + CodexThreadInitializedInput { thread_id: "thread-0".to_string(), model: "gpt-5".to_string(), - ephemeral: true, - session_source: SessionSource::Exec, - initialization_mode: InitializationMode::New, - subagent_source: None, - parent_thread_id: None, + product_client_id: originator().value, created_at: 1_716_000_000, - }), - }); + thread_context: CodexThreadContext { + ephemeral: true, + session_source: SessionSource::Exec, + initialization_mode: InitializationMode::New, + subagent_source: None, + parent_thread_id: None, + }, + }, + )); let payload = serde_json::to_value(&event).expect("serialize thread initialized event"); @@ -231,19 +233,21 @@ fn thread_initialized_event_serializes_expected_shape() { #[test] fn thread_initialized_event_serializes_subagent_source() { - let event = TrackEventRequest::ThreadInitialized(CodexThreadInitializedEventRequest { - event_type: "codex_thread_initialized", - event_params: codex_thread_initialized_event_params(CodexThreadInitializedEvent { + let event = TrackEventRequest::CodexThreadInitialized(codex_thread_initialized_event_request( + CodexThreadInitializedInput { thread_id: "thread-1".to_string(), model: "gpt-5".to_string(), - ephemeral: false, - session_source: SessionSource::SubAgent(SubAgentSource::Review), - initialization_mode: InitializationMode::New, - subagent_source: Some(SubAgentSource::Review), - parent_thread_id: None, + product_client_id: originator().value, created_at: 1, - }), - }); + thread_context: CodexThreadContext { + ephemeral: false, + session_source: SessionSource::SubAgent(SubAgentSource::Review), + initialization_mode: InitializationMode::New, + subagent_source: Some(SubAgentSource::Review), + parent_thread_id: None, + }, + }, + )); let payload = serde_json::to_value(&event).expect("serialize subagent thread initialized event"); @@ -253,19 +257,21 @@ fn thread_initialized_event_serializes_subagent_source() { #[test] fn thread_initialized_event_omits_non_user_non_subagent_session_source() { - let event = TrackEventRequest::ThreadInitialized(CodexThreadInitializedEventRequest { - event_type: "codex_thread_initialized", - event_params: codex_thread_initialized_event_params(CodexThreadInitializedEvent { + let event = TrackEventRequest::CodexThreadInitialized(codex_thread_initialized_event_request( + CodexThreadInitializedInput { thread_id: "thread-2".to_string(), model: "gpt-5".to_string(), - ephemeral: false, - session_source: SessionSource::Mcp, - initialization_mode: InitializationMode::New, - subagent_source: None, - parent_thread_id: None, + product_client_id: originator().value, created_at: 1, - }), - }); + thread_context: CodexThreadContext { + ephemeral: false, + session_source: SessionSource::Mcp, + initialization_mode: InitializationMode::New, + subagent_source: None, + parent_thread_id: None, + }, + }, + )); let payload = serde_json::to_value(&event).expect("serialize mcp thread initialized event"); assert_eq!( diff --git a/codex-rs/analytics/src/lib.rs b/codex-rs/analytics/src/lib.rs index 4ce20a0079..16f3d75ac6 100644 --- a/codex-rs/analytics/src/lib.rs +++ b/codex-rs/analytics/src/lib.rs @@ -7,7 +7,6 @@ pub use analytics_client::AppInvocation; pub use analytics_client::AppMentionedInput; pub use analytics_client::AppUsedInput; pub use analytics_client::CodexThreadContext; -pub use analytics_client::CodexThreadInitializedEvent; pub use analytics_client::CodexThreadInitializedInput; pub use analytics_client::InitializationMode; pub use analytics_client::InvocationType; diff --git a/codex-rs/core/tests/suite/thread_metadata.rs b/codex-rs/core/tests/suite/analytics.rs similarity index 100% rename from codex-rs/core/tests/suite/thread_metadata.rs rename to codex-rs/core/tests/suite/analytics.rs diff --git a/codex-rs/core/tests/suite/mod.rs b/codex-rs/core/tests/suite/mod.rs index 4011e692a8..ff2da246fc 100644 --- a/codex-rs/core/tests/suite/mod.rs +++ b/codex-rs/core/tests/suite/mod.rs @@ -58,6 +58,7 @@ pub static CODEX_ALIASES_TEMP_DIR: TestCodexAliasesGuard = unsafe { mod abort_tasks; mod agent_jobs; mod agent_websocket; +mod analytics; mod apply_patch_cli; #[cfg(not(target_os = "windows"))] mod approvals; @@ -127,7 +128,6 @@ mod stream_error_allows_next_turn; mod stream_no_completed; mod subagent_notifications; mod text_encoding_fix; -mod thread_metadata; mod tool_harness; mod tool_parallelism; mod tool_suggest;