Add in-memory shell snapshots to unified exec (#39957)

## What changed

- Add the under-development `shell_snapshot_v2` feature and advertise executor support through environment capabilities.
- Use executor-managed, in-memory snapshots for eligible direct `bash`, `zsh`, and `sh` login commands, while applying the configured shell environment policy and avoiding duplicate automatic startup-file effects.
- Keep file-backed snapshots available for user-shell commands and fall back to the existing execution path when in-memory snapshots are unsupported or inapplicable.

## Testing

- Cover policy filtering, snapshot reuse without snapshot files, automatic startup files, local and remote execution, and legacy user-shell snapshots.

GitOrigin-RevId: 4ad6cdf13824913ac8c393ba38b9844230677579
This commit is contained in:
jif
2026-08-21 15:24:56 +00:00
committed by copyberry
parent d446960657
commit 3882ced09c
17 changed files with 299 additions and 34 deletions
+15 -1
View File
@@ -1164,7 +1164,21 @@ impl Session {
} else {
shell::default_user_shell()
};
let shell_snapshot = if config.features.enabled(Feature::ShellSnapshot) {
let use_executor_shell_snapshots = config.features.enabled(Feature::ShellSnapshotV2)
&& config.features.enabled(Feature::ShellTool)
&& config.features.enabled(Feature::UnifiedExec)
&& matches!(
codex_tools::UnifiedExecShellMode::for_session(
config.features.get(),
crate::tools::tool_user_shell_type(&default_shell),
config.zsh_path.as_ref(),
config.main_execve_wrapper_exe.as_ref(),
),
codex_tools::UnifiedExecShellMode::Direct
);
let shell_snapshot = if config.features.enabled(Feature::ShellSnapshot)
&& !use_executor_shell_snapshots
{
ShellSnapshot::new(
config.codex_home.clone(),
thread_id,
@@ -42,6 +42,7 @@ pub(crate) struct TurnEnvironment {
pub(crate) environment: Arc<Environment>,
pub(crate) shell: Option<shell::Shell>,
pub(crate) shell_snapshot: ShellSnapshotTask,
pub(crate) shell_snapshot_v2_supported: bool,
}
impl TurnEnvironment {
@@ -58,6 +59,7 @@ impl TurnEnvironment {
environment,
shell,
shell_snapshot: futures::future::ready(None).boxed().shared(),
shell_snapshot_v2_supported: false,
}
}