Prewarm shell snapshots for eligible turns (#42137)

## Why

Shell Snapshot V2 previously captured the login-shell environment lazily when a
command started, adding that work to the command path.

## What changed

- Start one asynchronous snapshot capture after turn hooks accept the turn, so
  eligible local `exec_command` calls can reuse it without blocking the model.
- Use the turn's resolved tools, permissions, sandbox, environment, and shell
  configuration, and skip prewarming for unsupported or network-managed cases.
- Cancel outstanding prewarming during shutdown. Keep failed speculative
  captures retryable by real commands without consuming their retry budget.

## Testing

Added coverage for non-blocking capture and reuse, failure recovery, sandbox and
permission isolation, shutdown cancellation, hook-stopped turns, eligibility
gates, and concurrent capture retries.

GitOrigin-RevId: ff24a4f0328c06653e09d03fd0a3db1eccd65030
This commit is contained in:
jif authored and copyberry committed 2026-09-01 21:16:12 +00:00
1 parent c5b5fa8089
commit 612e6491d5
13 files changed
+783 -50

No files matched your search

+5
View File
@@ -405,6 +405,11 @@ pub(super) async fn shutdown_session_runtime(sess: &Arc<Session>) {
}
let _ = sess.conversation.shutdown().await;
sess.abort_all_tasks(TurnAbortReason::Interrupted).await;
let shell_snapshot_prewarm = sess.state.lock().await.shell_snapshot_prewarm.take();
if let Some(shell_snapshot_prewarm) = shell_snapshot_prewarm {
shell_snapshot_prewarm.abort();
let _ = shell_snapshot_prewarm.await;
}
sess.hooks().shutdown().await;
sess.async_hook_results.close();
while sess.async_hook_results.try_recv().is_ok() {}
+9
View File
@@ -269,6 +269,15 @@ pub(crate) async fn run_turn(
return Ok(None);
}
// Only speculate after hooks accept the turn, using its finalized tools and permissions.
{
let mut state = sess.state.lock().await;
if state.shell_snapshot_prewarm.is_none() {
state.shell_snapshot_prewarm =
sess.prewarm_shell_snapshots(first_step_context.as_ref());
}
}
sess.merge_connector_selection(explicitly_enabled_connectors.clone())
.await;
sess.set_previous_turn_settings(Some(PreviousTurnSettings {