mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
[codex] retain resolved environments across turns (#27955)
## Why Selected execution environments are thread-scoped resources, but startup and turn construction repeatedly resolved their IDs and working directories. That discarded existing environment handles and shell metadata even when a selection had not changed. Session configuration updates also need to affect future turns without changing the resolved environment set already captured by a running turn. ## What changed - Create a `ThreadEnvironments` service inside `Codex` from the spawned `EnvironmentManager` and raw environment selections, then store it on `SessionServices`. - Split service construction from `update_selections`, allowing session configuration updates to mutate the resolved set in place. - Retain an existing `TurnEnvironment` when its environment ID and working directory match; resolve only added or changed selections and remove selections that are no longer present. - Normalize duplicate IDs by keeping the first selection and skip individual selections that fail to resolve instead of rejecting the entire update. - Give each `TurnContext` a cloned `TurnEnvironmentSnapshot`, so later session configuration updates affect future turns without rewriting an active turn. - Reuse the service-owned environment manager and resolved snapshot for startup work, MCP initialization, and child-thread spawning instead of flowing resolved environments through spawn arguments. ## Test plan - `cargo check -p codex-core --tests` - `just test -p codex-core environment_selection` - `just test -p codex-core turn_environments` - `just test -p codex-core session_update_settings_does_not_rewrite_sticky_environment_cwds` - `just test -p codex-core default_turn_does_not_overlay_legacy_fallback_cwd_onto_stored_thread_environments`
This commit is contained in:
1 parent
4c1c9bf327
commit
9728992fab
14 files changed
+405
-240
No files matched your search
@@ -2,7 +2,7 @@ use super::*;
|
||||
use crate::SkillLoadOutcome;
|
||||
use crate::agents_md::LoadedAgentsMd;
|
||||
use crate::config::GhostSnapshotConfig;
|
||||
use crate::environment_selection::ResolvedTurnEnvironments;
|
||||
use crate::environment_selection::TurnEnvironmentSnapshot;
|
||||
use codex_core_skills::HostLoadedSkills;
|
||||
use codex_model_provider::SharedModelProvider;
|
||||
use codex_model_provider::create_model_provider;
|
||||
@@ -102,7 +102,7 @@ pub struct TurnContext {
|
||||
pub(crate) session_source: SessionSource,
|
||||
pub(crate) parent_thread_id: Option<ThreadId>,
|
||||
pub(crate) thread_source: Option<ThreadSource>,
|
||||
pub(crate) environments: ResolvedTurnEnvironments,
|
||||
pub(crate) environments: TurnEnvironmentSnapshot,
|
||||
/// The session's absolute working directory. All relative paths provided
|
||||
/// by the model as well as sandbox policies are resolved against this path
|
||||
/// instead of `std::env::current_dir()`.
|
||||
@@ -502,7 +502,7 @@ impl Session {
|
||||
model_info: ModelInfo,
|
||||
models_manager: &SharedModelsManager,
|
||||
network: Option<NetworkProxy>,
|
||||
environments: ResolvedTurnEnvironments,
|
||||
environments: TurnEnvironmentSnapshot,
|
||||
cwd: AbsolutePathBuf,
|
||||
sub_id: String,
|
||||
skills_outcome: Arc<SkillLoadOutcome>,
|
||||
@@ -635,6 +635,11 @@ impl Session {
|
||||
});
|
||||
let new_config = notify_config_contributors
|
||||
.then(|| Self::build_effective_session_config(&next));
|
||||
if updates.environments.is_some() {
|
||||
self.services
|
||||
.turn_environments
|
||||
.update_selections(next.environment_selections());
|
||||
}
|
||||
state.session_configuration = next.clone();
|
||||
Ok((
|
||||
next,
|
||||
@@ -673,7 +678,6 @@ impl Session {
|
||||
return Err(CodexErr::InvalidRequest(message));
|
||||
}
|
||||
};
|
||||
|
||||
self.emit_config_changed_contributors(previous_config.as_ref(), new_config.as_ref());
|
||||
self.maybe_refresh_shell_snapshot_for_cwd(
|
||||
&previous_cwd,
|
||||
@@ -733,15 +737,7 @@ impl Session {
|
||||
final_output_json_schema: Option<Option<Value>>,
|
||||
multi_agent_runtime: TurnMultiAgentRuntime,
|
||||
) -> Arc<TurnContext> {
|
||||
let turn_environments = crate::environment_selection::resolve_environment_selections(
|
||||
self.services.environment_manager.as_ref(),
|
||||
session_configuration.environment_selections(),
|
||||
)
|
||||
.await
|
||||
.unwrap_or_else(|err| {
|
||||
warn!("failed to resolve turn environments: {err}");
|
||||
ResolvedTurnEnvironments::default()
|
||||
});
|
||||
let turn_environments = self.services.turn_environments.snapshot().await;
|
||||
let primary_turn_environment = turn_environments.primary().cloned();
|
||||
let cwd = primary_turn_environment
|
||||
.as_ref()
|
||||
|
||||
Reference in new issue
Block a user