Merge branch 'rhan/oob-thread-metadata' into rhan/oob-turn-metadata

This commit is contained in:
rhan-oai
2026-03-25 15:00:32 -07:00
committed by GitHub
4 changed files with 0 additions and 241 deletions
@@ -4,14 +4,6 @@ use codex_login::AuthManager;
use codex_login::default_client::create_client;
use codex_login::default_client::originator;
use codex_plugin::PluginTelemetryMetadata;
use codex_protocol::config_types::ApprovalsReviewer;
use codex_protocol::config_types::ModeKind;
use codex_protocol::config_types::Personality;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::config_types::ServiceTier;
use codex_protocol::openai_models::ReasoningEffort;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::SandboxPolicy;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::SkillScope;
use codex_protocol::protocol::SubAgentSource;
@@ -51,16 +43,6 @@ pub struct CodexTurnEvent {
pub struct CodexThreadInitializedEvent {
pub thread_id: String,
pub model: String,
pub model_provider: String,
pub reasoning_effort: Option<ReasoningEffort>,
pub reasoning_summary: Option<ReasoningSummary>,
pub service_tier: Option<ServiceTier>,
pub approval_policy: AskForApproval,
pub approvals_reviewer: ApprovalsReviewer,
pub sandbox_policy: SandboxPolicy,
pub sandbox_network_access: bool,
pub collaboration_mode: ModeKind,
pub personality: Option<Personality>,
pub ephemeral: bool,
pub session_source: SessionSource,
pub initialization_mode: InitializationMode,
@@ -406,16 +388,6 @@ struct CodexThreadInitializedEventParams {
thread_id: String,
product_client_id: String,
model: String,
model_provider: String,
reasoning_effort: Option<String>,
reasoning_summary: Option<String>,
service_tier: String,
approval_policy: String,
approvals_reviewer: String,
sandbox_policy: &'static str,
sandbox_network_access: bool,
collaboration_mode: &'static str,
personality: Option<String>,
ephemeral: bool,
session_source: Option<&'static str>,
initialization_mode: InitializationMode,
@@ -937,21 +909,6 @@ fn codex_thread_initialized_event_params(
thread_id: thread_event.thread_id,
product_client_id: originator().value,
model: thread_event.model,
model_provider: thread_event.model_provider,
reasoning_effort: thread_event.reasoning_effort.map(|value| value.to_string()),
reasoning_summary: thread_event
.reasoning_summary
.map(|value| value.to_string()),
service_tier: thread_event
.service_tier
.map(|value| value.to_string())
.unwrap_or_else(|| "default".to_string()),
approval_policy: thread_event.approval_policy.to_string(),
approvals_reviewer: thread_event.approvals_reviewer.to_string(),
sandbox_policy: sandbox_policy_mode(&thread_event.sandbox_policy),
sandbox_network_access: thread_event.sandbox_network_access,
collaboration_mode: collaboration_mode_mode(thread_event.collaboration_mode),
personality: thread_event.personality.map(|value| value.to_string()),
ephemeral: thread_event.ephemeral,
session_source: session_source_name(&thread_event.session_source),
initialization_mode: thread_event.initialization_mode,
@@ -23,14 +23,6 @@ use codex_plugin::AppConnectorId;
use codex_plugin::PluginCapabilitySummary;
use codex_plugin::PluginId;
use codex_plugin::PluginTelemetryMetadata;
use codex_protocol::config_types::ApprovalsReviewer;
use codex_protocol::config_types::ModeKind;
use codex_protocol::config_types::Personality;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::config_types::ServiceTier;
use codex_protocol::openai_models::ReasoningEffort;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::SandboxPolicy;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::SubAgentSource;
use pretty_assertions::assert_eq;
@@ -266,16 +258,6 @@ fn thread_initialized_event_serializes_expected_shape() {
event_params: codex_thread_initialized_event_params(CodexThreadInitializedEvent {
thread_id: "thread-0".to_string(),
model: "gpt-5".to_string(),
model_provider: "openai".to_string(),
reasoning_effort: Some(ReasoningEffort::High),
reasoning_summary: Some(ReasoningSummary::Detailed),
service_tier: Some(ServiceTier::Flex),
approval_policy: AskForApproval::OnRequest,
approvals_reviewer: ApprovalsReviewer::GuardianSubagent,
sandbox_policy: SandboxPolicy::new_read_only_policy(),
sandbox_network_access: false,
collaboration_mode: ModeKind::Plan,
personality: Some(Personality::Friendly),
ephemeral: true,
session_source: SessionSource::Exec,
initialization_mode: InitializationMode::New,
@@ -295,16 +277,6 @@ fn thread_initialized_event_serializes_expected_shape() {
"thread_id": "thread-0",
"product_client_id": originator().value,
"model": "gpt-5",
"model_provider": "openai",
"reasoning_effort": "high",
"reasoning_summary": "detailed",
"service_tier": "flex",
"approval_policy": "on-request",
"approvals_reviewer": "guardian_subagent",
"sandbox_policy": "read_only",
"sandbox_network_access": false,
"collaboration_mode": "plan",
"personality": "friendly",
"ephemeral": true,
"session_source": "user",
"initialization_mode": "new",
@@ -323,16 +295,6 @@ fn thread_initialized_event_serializes_subagent_source() {
event_params: codex_thread_initialized_event_params(CodexThreadInitializedEvent {
thread_id: "thread-1".to_string(),
model: "gpt-5".to_string(),
model_provider: "openai".to_string(),
reasoning_effort: None,
reasoning_summary: None,
service_tier: None,
approval_policy: AskForApproval::OnRequest,
approvals_reviewer: ApprovalsReviewer::User,
sandbox_policy: SandboxPolicy::new_read_only_policy(),
sandbox_network_access: false,
collaboration_mode: ModeKind::Default,
personality: None,
ephemeral: false,
session_source: SessionSource::SubAgent(SubAgentSource::Review),
initialization_mode: InitializationMode::New,
@@ -355,16 +317,6 @@ fn thread_initialized_event_omits_non_user_non_subagent_session_source() {
event_params: codex_thread_initialized_event_params(CodexThreadInitializedEvent {
thread_id: "thread-2".to_string(),
model: "gpt-5".to_string(),
model_provider: "openai".to_string(),
reasoning_effort: None,
reasoning_summary: None,
service_tier: None,
approval_policy: AskForApproval::OnRequest,
approvals_reviewer: ApprovalsReviewer::User,
sandbox_policy: SandboxPolicy::new_read_only_policy(),
sandbox_network_access: false,
collaboration_mode: ModeKind::Default,
personality: None,
ephemeral: false,
session_source: SessionSource::Mcp,
initialization_mode: InitializationMode::New,
-20
View File
@@ -678,26 +678,6 @@ impl Codex {
.collaboration_mode
.model()
.to_string(),
model_provider: thread_initialized_configuration
.original_config_do_not_use
.model_provider_id
.clone(),
reasoning_effort: thread_initialized_configuration
.collaboration_mode
.reasoning_effort(),
reasoning_summary: thread_initialized_configuration.model_reasoning_summary,
service_tier: thread_initialized_configuration.service_tier,
approval_policy: thread_initialized_configuration.approval_policy.value(),
approvals_reviewer: thread_initialized_configuration.approvals_reviewer,
sandbox_policy: thread_initialized_configuration
.sandbox_policy
.get()
.clone(),
sandbox_network_access: thread_initialized_configuration
.network_sandbox_policy
.is_enabled(),
collaboration_mode: thread_initialized_configuration.collaboration_mode.mode,
personality: thread_initialized_configuration.personality,
ephemeral: thread_initialized_configuration
.original_config_do_not_use
.ephemeral,
@@ -1,13 +1,6 @@
use anyhow::Result;
use codex_core::CodexAuth;
use codex_core::RolloutRecorder;
use codex_core::config::Constrained;
use codex_protocol::config_types::ApprovalsReviewer;
use codex_protocol::config_types::Personality;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::config_types::ServiceTier;
use codex_protocol::openai_models::ReasoningEffort;
use codex_protocol::protocol::InitialHistory;
use core_test_support::responses::start_mock_server;
use core_test_support::test_codex::test_codex;
use std::time::Duration;
@@ -23,14 +16,9 @@ async fn thread_initialization_tracks_thread_initialized_analytics() -> Result<(
.with_config(move |config| {
config.chatgpt_base_url = chatgpt_base_url;
config.model = Some("gpt-5".to_string());
config.model_reasoning_effort = Some(ReasoningEffort::High);
config.model_reasoning_summary = Some(ReasoningSummary::Detailed);
config.service_tier = Some(ServiceTier::Flex);
config.approvals_reviewer = ApprovalsReviewer::GuardianSubagent;
config.permissions.sandbox_policy = Constrained::allow_any(
codex_protocol::protocol::SandboxPolicy::new_workspace_write_policy(),
);
config.personality = Some(Personality::Friendly);
config.ephemeral = true;
})
.build(&server)
@@ -69,19 +57,6 @@ async fn thread_initialization_tracks_thread_initialized_analytics() -> Result<(
serde_json::json!(codex_core::default_client::originator().value)
);
assert_eq!(event["event_params"]["model"], "gpt-5");
assert_eq!(event["event_params"]["model_provider"], "openai");
assert_eq!(event["event_params"]["reasoning_effort"], "high");
assert_eq!(event["event_params"]["reasoning_summary"], "detailed");
assert_eq!(event["event_params"]["service_tier"], "flex");
assert_eq!(event["event_params"]["approval_policy"], "on-request");
assert_eq!(
event["event_params"]["approvals_reviewer"],
"guardian_subagent"
);
assert_eq!(event["event_params"]["sandbox_policy"], "workspace_write");
assert_eq!(event["event_params"]["sandbox_network_access"], false);
assert_eq!(event["event_params"]["collaboration_mode"], "default");
assert_eq!(event["event_params"]["personality"], "friendly");
assert_eq!(event["event_params"]["ephemeral"], true);
assert_eq!(event["event_params"]["session_source"], "user");
assert_eq!(event["event_params"]["initialization_mode"], "new");
@@ -101,108 +76,3 @@ async fn thread_initialization_tracks_thread_initialized_analytics() -> Result<(
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn resumed_thread_emits_thread_initialized_analytics() -> Result<()> {
let server = start_mock_server().await;
let chatgpt_base_url = server.uri();
let initial = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config({
let chatgpt_base_url = chatgpt_base_url.clone();
move |config| {
config.chatgpt_base_url = chatgpt_base_url;
config.model = Some("gpt-5".to_string());
config.model_reasoning_effort = Some(ReasoningEffort::High);
config.model_reasoning_summary = Some(ReasoningSummary::Detailed);
config.service_tier = Some(ServiceTier::Flex);
config.approvals_reviewer = ApprovalsReviewer::GuardianSubagent;
config.permissions.sandbox_policy = Constrained::allow_any(
codex_protocol::protocol::SandboxPolicy::new_workspace_write_policy(),
);
config.personality = Some(Personality::Friendly);
}
})
.build(&server)
.await?;
let rollout_path = initial
.codex
.rollout_path()
.expect("rollout path for initial thread");
let resume_deadline = Instant::now() + Duration::from_secs(10);
loop {
if matches!(
RolloutRecorder::get_rollout_history(&rollout_path).await?,
InitialHistory::Resumed(_)
) {
break;
}
if Instant::now() >= resume_deadline {
panic!("timed out waiting for rollout to become resumable");
}
tokio::time::sleep(Duration::from_millis(50)).await;
}
let _resumed = 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.model_reasoning_effort = Some(ReasoningEffort::High);
config.model_reasoning_summary = Some(ReasoningSummary::Detailed);
config.service_tier = Some(ServiceTier::Flex);
config.approvals_reviewer = ApprovalsReviewer::GuardianSubagent;
config.permissions.sandbox_policy = Constrained::allow_any(
codex_protocol::protocol::SandboxPolicy::new_workspace_write_policy(),
);
config.personality = Some(Personality::Friendly);
})
.resume(&server, initial.home.clone(), rollout_path)
.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| {
if request.url.path() != "/codex/analytics-events/events" {
return false;
}
let Ok(payload) = serde_json::from_slice::<serde_json::Value>(&request.body) else {
return false;
};
payload["events"]
.as_array()
.into_iter()
.flatten()
.any(|event| {
event["event_type"] == "codex_thread_initialized"
&& event["event_params"]["initialization_mode"] == "resumed"
})
}) {
break request;
}
if Instant::now() >= deadline {
panic!("timed out waiting for resumed 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"
&& event["event_params"]["initialization_mode"] == "resumed"
})
.expect("codex_thread_initialized resumed event should be present");
assert_eq!(event["event_params"]["session_source"], "user");
assert_eq!(event["event_params"]["initialization_mode"], "resumed");
Ok(())
}