Make environment provider snapshots path-free (#21794)

## Summary
- make EnvironmentProvider::snapshot path-free and keep providers
focused on provider-owned remote environments
- let provider snapshots request local inclusion via include_local, with
environments.toml including local and CODEX_EXEC_SERVER_URL excluding
local
- move reserved local environment construction into EnvironmentManager
using ExecServerRuntimePaths

Follow-up to https://github.com/openai/codex/pull/20667

## Testing
- just fmt
- git diff --check
- devbox: bazel build --bes_backend= --bes_results_url=
//codex-rs/exec-server:exec-server
- devbox: bazel test --bes_backend= --bes_results_url=
//codex-rs/exec-server:exec-server-unit-tests

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
starr-openai
2026-05-08 15:30:00 -07:00
committed by GitHub
Unverified
parent 24111790f0
commit dac108f2f1
6 changed files with 187 additions and 206 deletions
+29 -2
View File
@@ -85,6 +85,7 @@ pub(crate) fn resolve_environment_selections(
#[cfg(test)]
mod tests {
use codex_exec_server::ExecServerRuntimePaths;
use codex_exec_server::LOCAL_ENVIRONMENT_ID;
use codex_exec_server::REMOTE_ENVIRONMENT_ID;
use codex_protocol::protocol::TurnEnvironmentSelection;
use codex_utils_absolute_path::AbsolutePathBuf;
@@ -109,15 +110,41 @@ mod tests {
)
.await;
assert_eq!(
default_thread_environment_selections(&manager, &cwd),
vec![TurnEnvironmentSelection {
environment_id: REMOTE_ENVIRONMENT_ID.to_string(),
cwd,
}]
);
}
#[tokio::test]
async fn toml_default_thread_environment_selections_include_local_and_remote() {
let temp_dir = tempfile::tempdir().expect("tempdir");
std::fs::write(
temp_dir.path().join("environments.toml"),
r#"
[[environments]]
id = "remote"
url = "ws://127.0.0.1:8765"
"#,
)
.expect("write environments.toml");
let cwd = AbsolutePathBuf::current_dir().expect("cwd");
let manager = EnvironmentManager::from_codex_home(temp_dir.path(), test_runtime_paths())
.await
.expect("environment manager");
assert_eq!(
default_thread_environment_selections(&manager, &cwd),
vec![
TurnEnvironmentSelection {
environment_id: REMOTE_ENVIRONMENT_ID.to_string(),
environment_id: LOCAL_ENVIRONMENT_ID.to_string(),
cwd: cwd.clone(),
},
TurnEnvironmentSelection {
environment_id: "local".to_string(),
environment_id: REMOTE_ENVIRONMENT_ID.to_string(),
cwd,
},
]
+9 -5
View File
@@ -293,7 +293,7 @@ async fn shutdown_all_threads_bounded_submits_shutdown_to_every_thread() {
}
#[tokio::test]
async fn start_thread_accepts_explicit_environment_when_default_environment_is_disabled() {
async fn start_thread_rejects_explicit_local_environment_when_default_provider_is_disabled() {
let temp_dir = tempdir().expect("tempdir");
let mut config = test_config().await;
config.codex_home = temp_dir.path().join("codex-home").abs();
@@ -319,7 +319,7 @@ async fn start_thread_accepts_explicit_environment_when_default_environment_is_d
environment_manager,
);
let thread = manager
let result = manager
.start_thread_with_options(StartThreadOptions {
config: config.clone(),
initial_history: InitialHistory::New,
@@ -334,10 +334,14 @@ async fn start_thread_accepts_explicit_environment_when_default_environment_is_d
cwd: config.cwd.clone(),
}],
})
.await
.expect("explicit sticky environment should resolve by id");
.await;
let err = match result {
Ok(_) => panic!("explicit local environment should not resolve when provider is disabled"),
Err(err) => err,
};
assert_eq!(manager.list_thread_ids().await, vec![thread.thread_id]);
assert_eq!(err.to_string(), "unknown turn environment id `local`");
assert!(manager.list_thread_ids().await.is_empty());
}
#[tokio::test]