mirror of
https://github.com/openai/codex.git
synced 2026-10-24 18:18:41 +00:00
## What changed - Record time spent waiting for each stream event in `codex.response.receive_wait_ms` on the existing `handle_responses` span. - Add trace spans for startup prewarm consumption, turn-start lifecycle callbacks, assistant text flushing, and response stream error handling. - Include the turn ID and lifecycle phase on the turn-start span and the request type on the error-handling span. GitOrigin-RevId: 7792508c830ef05b03aed01eb840ca7e6577ad0b
127 lines
4.8 KiB
Rust
127 lines
4.8 KiB
Rust
use std::sync::Arc;
|
|
|
|
use codex_analytics::TurnAnalyticsMetadata;
|
|
use codex_extension_api::ExtensionData;
|
|
use codex_extension_api::ThreadIdleCause;
|
|
use codex_extension_api::TurnStartPhase;
|
|
use codex_protocol::error::CodexErrorDetails;
|
|
use codex_protocol::protocol::CodexErrorInfo;
|
|
use codex_protocol::protocol::TokenUsage;
|
|
use codex_protocol::protocol::TurnAbortReason;
|
|
|
|
use crate::session::session::Session;
|
|
use crate::session::turn_context::TurnContext;
|
|
|
|
impl Session {
|
|
#[tracing::instrument(level = "trace", skip_all, fields(turn_id = %turn_context.sub_id, phase = ?phase))]
|
|
pub(super) async fn emit_turn_start_lifecycle(
|
|
self: &Arc<Self>,
|
|
turn_context: &TurnContext,
|
|
token_usage_at_turn_start: Option<&TokenUsage>,
|
|
phase: TurnStartPhase,
|
|
) {
|
|
let metadata: Arc<dyn TurnAnalyticsMetadata> = turn_context.turn_metadata_state.clone();
|
|
turn_context.extension_data.insert(metadata);
|
|
turn_context
|
|
.extension_data
|
|
.insert(turn_context.session_telemetry.clone());
|
|
let collaboration_mode = turn_context.collaboration_mode();
|
|
for contributor in self.services.extensions.turn_lifecycle_contributors() {
|
|
if contributor.turn_start_phase(&self.services.thread_extension_data) != phase {
|
|
continue;
|
|
}
|
|
if phase == TurnStartPhase::RegularTaskStart
|
|
&& contributor.requires_mcp_runtime(&self.services.thread_extension_data)
|
|
{
|
|
self.refresh_mcp_if_dirty().await;
|
|
}
|
|
contributor
|
|
.on_turn_start(codex_extension_api::TurnStartInput {
|
|
turn_id: turn_context.sub_id.as_str(),
|
|
collaboration_mode: &collaboration_mode,
|
|
token_usage_at_turn_start,
|
|
session_store: &self.services.session_extension_data,
|
|
thread_store: &self.services.thread_extension_data,
|
|
turn_store: turn_context.extension_data.as_ref(),
|
|
})
|
|
.await;
|
|
}
|
|
}
|
|
|
|
pub(super) async fn emit_turn_stop_lifecycle(&self, turn_store: &ExtensionData) {
|
|
for contributor in self.services.extensions.turn_lifecycle_contributors() {
|
|
contributor
|
|
.on_turn_stop(codex_extension_api::TurnStopInput {
|
|
session_store: &self.services.session_extension_data,
|
|
thread_store: &self.services.thread_extension_data,
|
|
turn_store,
|
|
})
|
|
.await;
|
|
}
|
|
}
|
|
|
|
pub(crate) async fn emit_thread_idle_lifecycle_if_idle(&self, cause: ThreadIdleCause) {
|
|
let cause = {
|
|
let active_turn = self.active_turn.lock().await;
|
|
if active_turn.is_some() {
|
|
return;
|
|
}
|
|
if self.is_interrupted() {
|
|
ThreadIdleCause::Interrupted
|
|
} else {
|
|
cause
|
|
}
|
|
};
|
|
if self.input_queue.has_trigger_turn_mailbox_items().await {
|
|
return;
|
|
}
|
|
|
|
for contributor in self.services.extensions.thread_lifecycle_contributors() {
|
|
contributor
|
|
.on_thread_idle(codex_extension_api::ThreadIdleInput {
|
|
cause,
|
|
session_store: &self.services.session_extension_data,
|
|
thread_store: &self.services.thread_extension_data,
|
|
})
|
|
.await;
|
|
}
|
|
}
|
|
|
|
pub(super) async fn emit_turn_abort_lifecycle(
|
|
&self,
|
|
reason: TurnAbortReason,
|
|
turn_store: &ExtensionData,
|
|
) {
|
|
for contributor in self.services.extensions.turn_lifecycle_contributors() {
|
|
contributor
|
|
.on_turn_abort(codex_extension_api::TurnAbortInput {
|
|
reason: reason.clone(),
|
|
session_store: &self.services.session_extension_data,
|
|
thread_store: &self.services.thread_extension_data,
|
|
turn_store,
|
|
})
|
|
.await;
|
|
}
|
|
}
|
|
|
|
pub(crate) async fn emit_turn_error_lifecycle(
|
|
&self,
|
|
turn_context: &TurnContext,
|
|
error: CodexErrorInfo,
|
|
error_details: &CodexErrorDetails,
|
|
) {
|
|
for contributor in self.services.extensions.turn_lifecycle_contributors() {
|
|
contributor
|
|
.on_turn_error(codex_extension_api::TurnErrorInput {
|
|
turn_id: turn_context.sub_id.as_str(),
|
|
error: error.clone(),
|
|
error_details,
|
|
session_store: &self.services.session_extension_data,
|
|
thread_store: &self.services.thread_extension_data,
|
|
turn_store: turn_context.extension_data.as_ref(),
|
|
})
|
|
.await;
|
|
}
|
|
}
|
|
}
|