mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Scope runtime workspace roots to execution environments (#32952)
## Why Multi-environment turns can run against different filesystems, so a single thread-wide workspace-root list cannot accurately describe every selected environment. ## What changed - Add optional `runtimeWorkspaceRoots` to each app-server environment selection. Omitted roots default to that environment's `cwd`, while an empty list selects no roots. - Carry environment-native roots through turn selection, model-visible context, permission materialization, and tool sandboxing. - Keep the top-level `runtimeWorkspaceRoots` field as a compatibility input when constructing default environment selections; explicit selections use their own roots. ## Testing - Cover thread and turn API defaults, overrides, empty roots, and schema round-tripping. - Verify foreign roots remain model-visible and remote execution applies the target environment's roots before sandbox selection. GitOrigin-RevId: c6e7a62883c45c676c153055f46a55ee15a323a4
This commit is contained in:
1 parent
b019a5577c
commit
393f64565a
62 files changed
+769
-446
No files matched your search
@@ -46,6 +46,7 @@ pub(crate) struct TurnEnvironment {
|
||||
pub(crate) environment_id: String,
|
||||
pub(crate) environment: Arc<Environment>,
|
||||
cwd: PathUri,
|
||||
workspace_roots: Vec<PathUri>,
|
||||
pub(crate) shell: Option<shell::Shell>,
|
||||
pub(crate) shell_snapshot: ShellSnapshotTask,
|
||||
}
|
||||
@@ -55,12 +56,14 @@ impl TurnEnvironment {
|
||||
environment_id: String,
|
||||
environment: Arc<Environment>,
|
||||
cwd: PathUri,
|
||||
workspace_roots: Vec<PathUri>,
|
||||
shell: Option<shell::Shell>,
|
||||
) -> Self {
|
||||
Self {
|
||||
environment_id,
|
||||
environment,
|
||||
cwd,
|
||||
workspace_roots,
|
||||
shell,
|
||||
shell_snapshot: futures::future::ready(None).boxed().shared(),
|
||||
}
|
||||
@@ -80,10 +83,15 @@ impl TurnEnvironment {
|
||||
&self.cwd
|
||||
}
|
||||
|
||||
pub(crate) fn workspace_roots(&self) -> &[PathUri] {
|
||||
&self.workspace_roots
|
||||
}
|
||||
|
||||
pub(crate) fn selection(&self) -> TurnEnvironmentSelection {
|
||||
TurnEnvironmentSelection {
|
||||
environment_id: self.environment_id.clone(),
|
||||
cwd: self.cwd.clone(),
|
||||
workspace_roots: self.workspace_roots.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,6 +102,7 @@ impl std::fmt::Debug for TurnEnvironment {
|
||||
.field("environment_id", &self.environment_id)
|
||||
.field("environment", &self.environment)
|
||||
.field("cwd", &self.cwd)
|
||||
.field("workspace_roots", &self.workspace_roots)
|
||||
.field("shell", &self.shell)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
@@ -317,10 +326,11 @@ impl TurnContext {
|
||||
pub(crate) fn file_system_sandbox_context(
|
||||
&self,
|
||||
additional_permissions: Option<AdditionalPermissionProfile>,
|
||||
cwd: &PathUri,
|
||||
environment: &TurnEnvironment,
|
||||
) -> FileSystemSandboxContext {
|
||||
let permission_profile = self.config.permissions.permission_profile();
|
||||
let (base_file_system_sandbox_policy, base_network_sandbox_policy) =
|
||||
self.permission_profile.to_runtime_permissions();
|
||||
permission_profile.to_runtime_permissions();
|
||||
let file_system_sandbox_policy = effective_file_system_sandbox_policy(
|
||||
&base_file_system_sandbox_policy,
|
||||
additional_permissions.as_ref(),
|
||||
@@ -330,19 +340,14 @@ impl TurnContext {
|
||||
additional_permissions.as_ref(),
|
||||
);
|
||||
let permissions = PermissionProfile::from_runtime_permissions_with_enforcement(
|
||||
self.permission_profile.enforcement(),
|
||||
permission_profile.enforcement(),
|
||||
&file_system_sandbox_policy,
|
||||
network_sandbox_policy,
|
||||
);
|
||||
FileSystemSandboxContext {
|
||||
permissions: permissions.into(),
|
||||
cwd: Some(cwd.clone()),
|
||||
workspace_roots: self
|
||||
.config
|
||||
.effective_workspace_roots()
|
||||
.iter()
|
||||
.map(PathUri::from_abs_path)
|
||||
.collect(),
|
||||
cwd: Some(environment.cwd().clone()),
|
||||
workspace_roots: environment.workspace_roots().to_vec(),
|
||||
windows_sandbox_level: self.windows_sandbox_level,
|
||||
windows_sandbox_private_desktop: self
|
||||
.config
|
||||
@@ -438,10 +443,11 @@ impl Session {
|
||||
let config = session_configuration.original_config_do_not_use.clone();
|
||||
let mut per_turn_config = (*config).clone();
|
||||
per_turn_config.cwd = cwd;
|
||||
per_turn_config.workspace_roots = session_configuration.workspace_roots.clone();
|
||||
let workspace_roots = session_configuration.primary_workspace_roots();
|
||||
per_turn_config.workspace_roots = workspace_roots.clone();
|
||||
per_turn_config
|
||||
.permissions
|
||||
.set_workspace_roots(session_configuration.workspace_roots.clone());
|
||||
.set_workspace_roots(workspace_roots);
|
||||
per_turn_config.model_reasoning_effort =
|
||||
session_configuration.collaboration_mode.reasoning_effort();
|
||||
per_turn_config.model_reasoning_summary = session_configuration.model_reasoning_summary;
|
||||
@@ -476,10 +482,6 @@ impl Session {
|
||||
Self::build_per_turn_config(session_configuration, session_configuration.cwd().clone());
|
||||
config.model = Some(session_configuration.collaboration_mode.model().to_string());
|
||||
config.permissions.approval_policy = session_configuration.approval_policy.clone();
|
||||
config.workspace_roots = session_configuration.workspace_roots.clone();
|
||||
config
|
||||
.permissions
|
||||
.set_workspace_roots(session_configuration.workspace_roots.clone());
|
||||
config
|
||||
}
|
||||
|
||||
@@ -531,6 +533,7 @@ impl Session {
|
||||
per_turn_config.features.enabled(Feature::FastMode),
|
||||
&model_info,
|
||||
);
|
||||
let permission_profile = per_turn_config.permissions.effective_permission_profile();
|
||||
let per_turn_config = Arc::new(per_turn_config);
|
||||
let turn_metadata_state = Arc::new(TurnMetadataState::new(
|
||||
session_id.to_string(),
|
||||
@@ -541,7 +544,7 @@ impl Session {
|
||||
session_configuration.thread_source.clone(),
|
||||
sub_id.clone(),
|
||||
cwd.clone(),
|
||||
&session_configuration.permission_profile(),
|
||||
&permission_profile,
|
||||
session_configuration.windows_sandbox_level,
|
||||
network.is_some(),
|
||||
));
|
||||
@@ -578,7 +581,7 @@ impl Session {
|
||||
multi_agent_version,
|
||||
personality: session_configuration.personality,
|
||||
approval_policy: session_configuration.approval_policy.clone(),
|
||||
permission_profile: session_configuration.permission_profile(),
|
||||
permission_profile,
|
||||
network,
|
||||
windows_sandbox_level: session_configuration.windows_sandbox_level,
|
||||
available_models,
|
||||
@@ -702,7 +705,7 @@ impl Session {
|
||||
multi_agent_runtime: TurnMultiAgentRuntime,
|
||||
) -> Arc<TurnContext> {
|
||||
let turn_environments = self.services.turn_environments.snapshot().await;
|
||||
let primary_turn_environment = turn_environments.primary().cloned();
|
||||
let primary_turn_environment = turn_environments.primary();
|
||||
// TODO(anp): Migrate per-turn config and legacy TurnContext cwd consumers to PathUri so
|
||||
// a foreign primary environment does not fall back to the session's host cwd.
|
||||
let cwd = primary_turn_environment
|
||||
|
||||
Reference in new issue
Block a user