mirror of
https://github.com/openai/codex.git
synced 2026-10-19 17:28:46 +00:00
Allow idle threads to prewarm and repair WebSocket connections (#47701)
## Why A previously used WebSocket can close while a thread is idle. Hosts need a way to prepare the connection before the next turn without repeating warmup on a healthy connection. ## What changed - Expose `CodexThread::prewarm()` using the existing startup warmup and next-turn handoff. - Reuse healthy connections and pending warmups, retry failed warmups, and repair closed connections. Treat a finished WebSocket reader task as a closed connection. - Skip scheduling during an active turn or shutdown, and stop warmup admission before shutdown takes the pending task. - Expose `active_turn_environment_selections()` so hosts can inspect the environments captured by the active turn, including those still starting or failed, when authorizing steering. ## Testing Add regression coverage for repeated idle prewarm calls, healthy connection reuse with preserved response continuation, reconnection with `generate: false`, and warmup rejection after shutdown. Update delayed MCP discovery coverage to verify prewarm repairs an eagerly closed socket and the first turn reuses it. GitOrigin-RevId: aa164b91a399de2375eda3bf28397725439fce93
This commit is contained in:
@@ -239,6 +239,13 @@ impl CodexThread {
|
||||
self.session.services.session_telemetry.clone()
|
||||
}
|
||||
|
||||
/// Schedule the same background model warmup used at startup for an idle thread.
|
||||
/// The next turn consumes the warmup through the existing startup handoff.
|
||||
/// Call after installing host services such as the thread's attestation routing.
|
||||
pub async fn prewarm(&self) {
|
||||
self.session.schedule_startup_prewarm().await;
|
||||
}
|
||||
|
||||
/// Whether analytics is enabled for this thread after configuration and host overrides.
|
||||
pub fn analytics_enabled(&self) -> bool {
|
||||
self.session.services.analytics_events_client.is_enabled()
|
||||
@@ -525,6 +532,17 @@ impl CodexThread {
|
||||
self.session.inject_if_running(items).await
|
||||
}
|
||||
|
||||
/// Environment selections captured by the active turn, before later settings updates.
|
||||
/// Includes environments that are still starting or have failed. Hosts use this snapshot
|
||||
/// to authorize steering against every executor that the active turn selected.
|
||||
pub async fn active_turn_environment_selections(
|
||||
&self,
|
||||
) -> Option<Vec<TurnEnvironmentSelection>> {
|
||||
let active = self.session.active_turn.lock().await;
|
||||
let task = active.as_ref()?.task.as_ref()?;
|
||||
Some(task.turn_context.initial_environments.all_selections())
|
||||
}
|
||||
|
||||
/// Captures a regular turn only after its input is recorded. The caller must flush the rollout.
|
||||
pub async fn interrupted_turn(
|
||||
&self,
|
||||
|
||||
Reference in New Issue
Block a user