use std::sync::Arc; use async_trait::async_trait; use tokio_util::sync::CancellationToken; use crate::codex::TurnContext; use crate::codex::run_turn; use crate::protocol::EventMsg; use crate::protocol::TurnStartedEvent; use crate::session_startup_prewarm::SessionStartupPrewarmResolution; use crate::state::TaskKind; use codex_protocol::user_input::UserInput; use tracing::Instrument; use tracing::trace_span; use super::SessionTask; use super::SessionTaskContext; #[derive(Default)] pub(crate) struct RegularTask; impl RegularTask { pub(crate) fn new() -> Self { Self } } #[async_trait] impl SessionTask for RegularTask { fn kind(&self) -> TaskKind { TaskKind::Regular } fn span_name(&self) -> &'static str { "session_task.turn" } async fn run( self: Arc, session: Arc, ctx: Arc, input: Vec, cancellation_token: CancellationToken, ) -> Option { let sess = session.clone_session(); let run_turn_span = trace_span!("run_turn"); // Regular turns emit `TurnStarted` inline so first-turn lifecycle does // not wait on startup prewarm resolution. let event = EventMsg::TurnStarted(TurnStartedEvent { turn_id: ctx.sub_id.clone(), model_context_window: ctx.model_context_window(), collaboration_mode_kind: ctx.collaboration_mode.mode, }); sess.send_event(ctx.as_ref(), event).await; sess.set_server_reasoning_included(/*included*/ false).await; let prewarmed_client_session = match sess .consume_startup_prewarm_for_regular_turn(&cancellation_token) .await { SessionStartupPrewarmResolution::Cancelled => return None, SessionStartupPrewarmResolution::Unavailable { .. } => None, SessionStartupPrewarmResolution::Ready(prewarmed_client_session) => { Some(*prewarmed_client_session) } }; let mut next_input = input; let mut prewarmed_client_session = prewarmed_client_session; loop { let last_agent_message = run_turn( Arc::clone(&sess), Arc::clone(&ctx), next_input, prewarmed_client_session.take(), cancellation_token.child_token(), ) .instrument(run_turn_span.clone()) .await; if !sess.has_pending_input().await { return last_agent_message; } next_input = Vec::new(); } } }