mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex-analytics] rework thread_source for thread analytics (#20949)
## Summary - make `thread_source` an explicit optional thread-level field on `thread/start`, `thread/fork`, and returned thread payloads - persist `thread_source` in rollout/session metadata so resumed live threads retain the original value - replace the old best-effort `session_source` -> `thread_source` mapping with an explicit caller-supplied analytics classification ## Why Before this change, analytics `thread_source` was populated by a best-effort mapping from `session_source`. `session_source` describes the runtime/client surface, not the actual thread-level origin, so that projection was not accurate enough to distinguish cases such as `user`, `subagent`, `memory_consolidation`, and future thread origins reliably. Making `thread_source` explicit keeps one thread-level analytics field while letting callers provide the real classification directly instead of recovering it indirectly from `session_source`. ## Impact For new analytics events, `thread_source` now reflects the explicit thread-level classification supplied by the caller rather than an inferred value derived from `session_source`. Existing protocol fields remain optional; callers that omit `threadSource` now produce `null` instead of a best-effort inferred value. ## Validation - `just write-app-server-schema` - `cargo test -p codex-analytics -p codex-core -p codex-app-server-protocol --no-run` - `cargo test -p codex-app-server-protocol generated_ts_optional_nullable_fields_only_in_params` - `cargo test -p codex-analytics thread_initialized_event_serializes_expected_shape` - `cargo test -p codex-core resume_stopped_thread_from_rollout_preserves_thread_source`
This commit is contained in:
committed by
GitHub
Unverified
parent
94db03d5af
commit
b3d4f1a9f0
@@ -746,6 +746,7 @@ impl ThreadRequestProcessor {
|
||||
personality,
|
||||
ephemeral,
|
||||
session_start_source,
|
||||
thread_source,
|
||||
environments,
|
||||
persist_extended_history,
|
||||
} = params;
|
||||
@@ -799,6 +800,7 @@ impl ThreadRequestProcessor {
|
||||
typesafe_overrides,
|
||||
dynamic_tools,
|
||||
session_start_source,
|
||||
thread_source.map(Into::into),
|
||||
environment_selections,
|
||||
service_name,
|
||||
experimental_raw_events,
|
||||
@@ -882,6 +884,7 @@ impl ThreadRequestProcessor {
|
||||
typesafe_overrides: ConfigOverrides,
|
||||
dynamic_tools: Option<Vec<ApiDynamicToolSpec>>,
|
||||
session_start_source: Option<codex_app_server_protocol::ThreadStartSource>,
|
||||
thread_source: Option<codex_protocol::protocol::ThreadSource>,
|
||||
environments: Option<Vec<TurnEnvironmentSelection>>,
|
||||
service_name: Option<String>,
|
||||
experimental_raw_events: bool,
|
||||
@@ -998,6 +1001,7 @@ impl ThreadRequestProcessor {
|
||||
codex_app_server_protocol::ThreadStartSource::Clear => InitialHistory::Cleared,
|
||||
},
|
||||
session_source: None,
|
||||
thread_source,
|
||||
dynamic_tools: core_dynamic_tools,
|
||||
persist_extended_history: false,
|
||||
metrics_service_name: service_name,
|
||||
@@ -2382,6 +2386,11 @@ impl ThreadRequestProcessor {
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
thread.thread_source = codex_thread
|
||||
.config_snapshot()
|
||||
.await
|
||||
.thread_source
|
||||
.map(Into::into);
|
||||
|
||||
self.thread_watch_manager
|
||||
.upsert_thread(thread.clone())
|
||||
@@ -2869,6 +2878,7 @@ impl ThreadRequestProcessor {
|
||||
base_instructions,
|
||||
developer_instructions,
|
||||
ephemeral,
|
||||
thread_source,
|
||||
exclude_turns,
|
||||
persist_extended_history,
|
||||
} = params;
|
||||
@@ -2959,6 +2969,7 @@ impl ThreadRequestProcessor {
|
||||
history: history_items.clone(),
|
||||
rollout_path: source_thread.rollout_path.clone(),
|
||||
}),
|
||||
thread_source.map(Into::into),
|
||||
/*persist_extended_history*/ false,
|
||||
self.request_trace_context(&request_id).await,
|
||||
)
|
||||
@@ -3018,6 +3029,11 @@ impl ThreadRequestProcessor {
|
||||
}
|
||||
thread
|
||||
};
|
||||
thread.thread_source = forked_thread
|
||||
.config_snapshot()
|
||||
.await
|
||||
.thread_source
|
||||
.map(Into::into);
|
||||
|
||||
self.thread_watch_manager
|
||||
.upsert_thread_silently(thread.clone())
|
||||
@@ -3620,6 +3636,7 @@ pub(crate) fn thread_from_stored_thread(
|
||||
agent_nickname: source.get_nickname(),
|
||||
agent_role: source.get_agent_role(),
|
||||
source: source.into(),
|
||||
thread_source: thread.thread_source.map(Into::into),
|
||||
git_info,
|
||||
name: thread.name,
|
||||
turns: Vec::new(),
|
||||
@@ -3682,6 +3699,7 @@ fn summary_from_state_db_metadata(
|
||||
cwd: PathBuf,
|
||||
cli_version: String,
|
||||
source: String,
|
||||
_thread_source: Option<codex_protocol::protocol::ThreadSource>,
|
||||
agent_nickname: Option<String>,
|
||||
agent_role: Option<String>,
|
||||
git_sha: Option<String>,
|
||||
@@ -3732,6 +3750,7 @@ fn summary_from_thread_metadata(metadata: &ThreadMetadata) -> ConversationSummar
|
||||
metadata.cwd.clone(),
|
||||
metadata.cli_version.clone(),
|
||||
metadata.source.clone(),
|
||||
metadata.thread_source,
|
||||
metadata.agent_nickname.clone(),
|
||||
metadata.agent_role.clone(),
|
||||
metadata.git_sha.clone(),
|
||||
@@ -3815,6 +3834,7 @@ fn build_thread_from_snapshot(
|
||||
agent_nickname: config_snapshot.session_source.get_nickname(),
|
||||
agent_role: config_snapshot.session_source.get_agent_role(),
|
||||
source: config_snapshot.session_source.clone().into(),
|
||||
thread_source: config_snapshot.thread_source.map(Into::into),
|
||||
git_info: None,
|
||||
name: None,
|
||||
turns: Vec::new(),
|
||||
|
||||
Reference in New Issue
Block a user