mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
stop blocking unified_exec on Windows (#19435)
## Summary - remove the Windows-specific unified-exec environment block from tool selection - keep `unified_exec` default-off on Windows unless the feature is explicitly enabled - normalize model-provided `shell_type = unified_exec` to `shell_command` when the feature is disabled - drop obsolete tests tied to the removed environment gate and keep the feature-flag regression coverage ## Why Now that the session/long-lived process backend is implemented for the Windows sandbox, we don't need to hard disable it anymore. We will be rolling out slowly using a feature gate. ## Impact This allows manual Windows opt-in in CLI and app-backed flows while preserving the existing default-off behavior for Windows users. --------- Co-authored-by: canvrno-oai <kbond@openai.com> Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
8de2a7a16d
commit
13dbcda28f
@@ -298,31 +298,6 @@ fn build_specs_with_unavailable_tools(
|
||||
)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn model_provided_unified_exec_is_blocked_for_windows_sandboxed_policies() {
|
||||
let mut model_info = model_info_from_models_json("gpt-5.4").await;
|
||||
model_info.shell_type = ConfigShellToolType::UnifiedExec;
|
||||
let features = Features::with_defaults();
|
||||
let available_models = Vec::new();
|
||||
let config = ToolsConfig::new(&ToolsConfigParams {
|
||||
model_info: &model_info,
|
||||
available_models: &available_models,
|
||||
features: &features,
|
||||
image_generation_tool_auth_allowed: true,
|
||||
web_search_mode: Some(WebSearchMode::Cached),
|
||||
session_source: SessionSource::Cli,
|
||||
permission_profile: &PermissionProfile::workspace_write(),
|
||||
windows_sandbox_level: WindowsSandboxLevel::RestrictedToken,
|
||||
});
|
||||
|
||||
let expected_shell_type = if cfg!(target_os = "windows") {
|
||||
ConfigShellToolType::ShellCommand
|
||||
} else {
|
||||
ConfigShellToolType::UnifiedExec
|
||||
};
|
||||
assert_eq!(config.shell_type, expected_shell_type);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_memory_requires_feature_flag() {
|
||||
let config = test_config().await;
|
||||
|
||||
@@ -136,8 +136,7 @@ impl ToolsConfig {
|
||||
image_generation_tool_auth_allowed,
|
||||
web_search_mode,
|
||||
session_source,
|
||||
permission_profile,
|
||||
windows_sandbox_level,
|
||||
..
|
||||
} = params;
|
||||
let include_apply_patch_tool = features.enabled(Feature::ApplyPatchFreeform);
|
||||
let include_code_mode = features.enabled(Feature::CodeMode);
|
||||
@@ -167,26 +166,25 @@ impl ToolsConfig {
|
||||
} else {
|
||||
ShellCommandBackendConfig::Classic
|
||||
};
|
||||
let unified_exec_allowed = unified_exec_allowed_in_environment(
|
||||
cfg!(target_os = "windows"),
|
||||
permission_profile,
|
||||
*windows_sandbox_level,
|
||||
);
|
||||
let unified_exec_enabled = features.enabled(Feature::UnifiedExec);
|
||||
let model_shell_type = match model_info.shell_type {
|
||||
ConfigShellToolType::UnifiedExec if !unified_exec_enabled => {
|
||||
ConfigShellToolType::ShellCommand
|
||||
}
|
||||
other => other,
|
||||
};
|
||||
let shell_type = if !features.enabled(Feature::ShellTool) {
|
||||
ConfigShellToolType::Disabled
|
||||
} else if features.enabled(Feature::ShellZshFork) {
|
||||
ConfigShellToolType::ShellCommand
|
||||
} else if features.enabled(Feature::UnifiedExec) && unified_exec_allowed {
|
||||
} else if unified_exec_enabled {
|
||||
if codex_utils_pty::conpty_supported() {
|
||||
ConfigShellToolType::UnifiedExec
|
||||
} else {
|
||||
ConfigShellToolType::ShellCommand
|
||||
}
|
||||
} else if model_info.shell_type == ConfigShellToolType::UnifiedExec && !unified_exec_allowed
|
||||
{
|
||||
ConfigShellToolType::ShellCommand
|
||||
} else {
|
||||
model_info.shell_type
|
||||
model_shell_type
|
||||
};
|
||||
|
||||
let apply_patch_tool_type = match model_info.apply_patch_tool_type {
|
||||
@@ -353,23 +351,6 @@ fn supports_image_generation(model_info: &ModelInfo) -> bool {
|
||||
model_info.input_modalities.contains(&InputModality::Image)
|
||||
}
|
||||
|
||||
fn unified_exec_allowed_in_environment(
|
||||
is_windows: bool,
|
||||
permission_profile: &PermissionProfile,
|
||||
windows_sandbox_level: WindowsSandboxLevel,
|
||||
) -> bool {
|
||||
let managed_sandbox_required = match permission_profile {
|
||||
PermissionProfile::Managed {
|
||||
file_system,
|
||||
network,
|
||||
} => !file_system.to_sandbox_policy().has_full_disk_write_access() || !network.is_enabled(),
|
||||
PermissionProfile::Disabled | PermissionProfile::External { .. } => false,
|
||||
};
|
||||
!(is_windows
|
||||
&& windows_sandbox_level != WindowsSandboxLevel::Disabled
|
||||
&& managed_sandbox_required)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tool_config_tests.rs"]
|
||||
mod tests;
|
||||
|
||||
@@ -3,12 +3,10 @@ use codex_features::Feature;
|
||||
use codex_features::Features;
|
||||
use codex_protocol::config_types::WebSearchMode;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::models::ManagedFileSystemPermissions;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::openai_models::ConfigShellToolType;
|
||||
use codex_protocol::openai_models::InputModality;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
@@ -52,42 +50,50 @@ fn model_info() -> ModelInfo {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unified_exec_is_blocked_for_windows_managed_profiles_only() {
|
||||
assert!(!unified_exec_allowed_in_environment(
|
||||
/*is_windows*/ true,
|
||||
&PermissionProfile::read_only(),
|
||||
WindowsSandboxLevel::RestrictedToken,
|
||||
));
|
||||
assert!(!unified_exec_allowed_in_environment(
|
||||
/*is_windows*/ true,
|
||||
&PermissionProfile::workspace_write(),
|
||||
WindowsSandboxLevel::RestrictedToken,
|
||||
));
|
||||
assert!(unified_exec_allowed_in_environment(
|
||||
/*is_windows*/ true,
|
||||
&PermissionProfile::Disabled,
|
||||
WindowsSandboxLevel::RestrictedToken,
|
||||
));
|
||||
assert!(unified_exec_allowed_in_environment(
|
||||
/*is_windows*/ true,
|
||||
&PermissionProfile::External {
|
||||
network: Default::default(),
|
||||
},
|
||||
WindowsSandboxLevel::RestrictedToken,
|
||||
));
|
||||
assert!(unified_exec_allowed_in_environment(
|
||||
/*is_windows*/ true,
|
||||
&PermissionProfile::Managed {
|
||||
file_system: ManagedFileSystemPermissions::Unrestricted,
|
||||
network: NetworkSandboxPolicy::Enabled,
|
||||
},
|
||||
WindowsSandboxLevel::RestrictedToken,
|
||||
));
|
||||
assert!(unified_exec_allowed_in_environment(
|
||||
/*is_windows*/ true,
|
||||
&PermissionProfile::Disabled,
|
||||
WindowsSandboxLevel::Disabled,
|
||||
));
|
||||
fn model_provided_unified_exec_requires_feature_flag() {
|
||||
let model_info = model_info();
|
||||
let mut features = Features::with_defaults();
|
||||
features.disable(Feature::UnifiedExec);
|
||||
|
||||
let available_models = Vec::new();
|
||||
let tools_config = ToolsConfig::new(&ToolsConfigParams {
|
||||
model_info: &model_info,
|
||||
available_models: &available_models,
|
||||
features: &features,
|
||||
image_generation_tool_auth_allowed: true,
|
||||
web_search_mode: Some(WebSearchMode::Cached),
|
||||
session_source: SessionSource::Cli,
|
||||
permission_profile: &PermissionProfile::Disabled,
|
||||
windows_sandbox_level: WindowsSandboxLevel::Disabled,
|
||||
});
|
||||
|
||||
assert_eq!(tools_config.shell_type, ConfigShellToolType::ShellCommand);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unified_exec_can_be_enabled_for_restricted_token_workspace_write() {
|
||||
let model_info = model_info();
|
||||
let mut features = Features::with_defaults();
|
||||
features.enable(Feature::UnifiedExec);
|
||||
|
||||
let available_models = Vec::new();
|
||||
let tools_config = ToolsConfig::new(&ToolsConfigParams {
|
||||
model_info: &model_info,
|
||||
available_models: &available_models,
|
||||
features: &features,
|
||||
image_generation_tool_auth_allowed: true,
|
||||
web_search_mode: Some(WebSearchMode::Cached),
|
||||
session_source: SessionSource::Cli,
|
||||
permission_profile: &PermissionProfile::workspace_write(),
|
||||
windows_sandbox_level: WindowsSandboxLevel::RestrictedToken,
|
||||
});
|
||||
|
||||
let expected_shell_type = if codex_utils_pty::conpty_supported() {
|
||||
ConfigShellToolType::UnifiedExec
|
||||
} else {
|
||||
ConfigShellToolType::ShellCommand
|
||||
};
|
||||
assert_eq!(tools_config.shell_type, expected_shell_type);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user