pivot to consuming from app-event stream

This commit is contained in:
Roy Han
2026-03-26 10:56:26 -07:00
parent 71d88a63c2
commit 5567bf4aed
13 changed files with 467 additions and 215 deletions
-60
View File
@@ -5,8 +5,6 @@ use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::atomic::AtomicU64;
use std::time::SystemTime;
use std::time::UNIX_EPOCH;
use crate::AuthManager;
use crate::CodexAuth;
@@ -350,9 +348,6 @@ use crate::util::backoff;
use crate::windows_sandbox::WindowsSandboxLevelExt;
use codex_analytics::AnalyticsEventsClient;
use codex_analytics::AppInvocation;
use codex_analytics::CodexThreadContext;
use codex_analytics::CodexThreadInitializedInput;
use codex_analytics::InitializationMode;
use codex_analytics::InvocationType;
use codex_analytics::build_track_events_context;
use codex_async_utils::OrCancelExt;
@@ -637,12 +632,6 @@ impl Codex {
user_shell_override,
};
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.
let session_source_clone = session_configuration.session_source.clone();
let (agent_status_tx, agent_status_rx) = watch::channel(AgentStatus::PendingInit);
@@ -670,31 +659,6 @@ impl Codex {
})?;
let thread_id = session.conversation_id;
session
.services
.analytics_events_client
.track_thread_initialized(CodexThreadInitializedInput {
thread_id: thread_id.to_string(),
model: thread_initialized_configuration
.collaboration_mode
.model()
.to_string(),
product_client_id: crate::default_client::originator().value,
created_at: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
thread_context: CodexThreadContext {
ephemeral: thread_initialized_configuration
.original_config_do_not_use
.ephemeral,
session_source: thread_session_source,
initialization_mode,
subagent_source,
parent_thread_id,
},
});
// This task will run until Op::Shutdown is received.
let session_for_loop = Arc::clone(&session);
let session_loop_handle = tokio::spawn(async move {
@@ -809,30 +773,6 @@ impl Codex {
}
}
fn initialization_mode(conversation_history: &InitialHistory) -> InitializationMode {
match conversation_history {
InitialHistory::New => InitializationMode::New,
InitialHistory::Forked(_) => InitializationMode::Forked,
InitialHistory::Resumed(_) => InitializationMode::Resumed,
}
}
fn session_source_subagent_source(session_source: &SessionSource) -> Option<SubAgentSource> {
match session_source {
SessionSource::SubAgent(subagent_source) => Some(subagent_source.clone()),
_ => None,
}
}
fn session_source_parent_thread_id(session_source: &SessionSource) -> Option<String> {
match session_source {
SessionSource::SubAgent(SubAgentSource::ThreadSpawn {
parent_thread_id, ..
}) => Some(parent_thread_id.to_string()),
_ => None,
}
}
#[cfg(test)]
pub(crate) fn completed_session_loop_termination() -> SessionLoopTermination {
futures::future::ready(()).boxed().shared()
+2
View File
@@ -136,6 +136,8 @@ pub type CodexConversation = CodexThread;
pub use auth::AuthManager;
pub use auth::CodexAuth;
pub use codex_analytics::AnalyticsEventsClient;
pub use codex_analytics::InitializeInput;
pub use codex_analytics::ThreadInitializeInput;
mod default_client_forwarding;
/// Default Codex HTTP client headers and reqwest construction.
-78
View File
@@ -1,78 +0,0 @@
use anyhow::Result;
use codex_core::CodexAuth;
use codex_core::config::Constrained;
use core_test_support::responses::start_mock_server;
use core_test_support::test_codex::test_codex;
use std::time::Duration;
use std::time::Instant;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn thread_initialization_tracks_thread_initialized_analytics() -> Result<()> {
let server = start_mock_server().await;
let chatgpt_base_url = server.uri();
let test = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(move |config| {
config.chatgpt_base_url = chatgpt_base_url;
config.model = Some("gpt-5".to_string());
config.permissions.sandbox_policy = Constrained::allow_any(
codex_protocol::protocol::SandboxPolicy::new_workspace_write_policy(),
);
config.ephemeral = true;
})
.build(&server)
.await?;
let deadline = Instant::now() + Duration::from_secs(10);
let analytics_request = loop {
let requests = server.received_requests().await.unwrap_or_default();
if let Some(request) = requests
.into_iter()
.find(|request| request.url.path() == "/codex/analytics-events/events")
{
break request;
}
if Instant::now() >= deadline {
panic!("timed out waiting for thread analytics request");
}
tokio::time::sleep(Duration::from_millis(50)).await;
};
let payload: serde_json::Value =
serde_json::from_slice(&analytics_request.body).expect("analytics payload");
let event = payload["events"]
.as_array()
.expect("events array")
.iter()
.find(|event| event["event_type"] == "codex_thread_initialized")
.expect("codex_thread_initialized event should be present");
assert_eq!(
event["event_params"]["thread_id"],
serde_json::json!(test.session_configured.session_id.to_string())
);
assert_eq!(
event["event_params"]["product_client_id"],
serde_json::json!(codex_core::default_client::originator().value)
);
assert_eq!(event["event_params"]["model"], "gpt-5");
assert_eq!(event["event_params"]["ephemeral"], true);
assert_eq!(event["event_params"]["session_source"], "user");
assert_eq!(event["event_params"]["initialization_mode"], "new");
assert_eq!(
event["event_params"]["subagent_source"],
serde_json::Value::Null
);
assert_eq!(
event["event_params"]["parent_thread_id"],
serde_json::Value::Null
);
assert!(
event["event_params"]["created_at"]
.as_u64()
.is_some_and(|timestamp| timestamp > 0)
);
Ok(())
}
-1
View File
@@ -58,7 +58,6 @@ 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;