mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
core: expose permission profile picker metadata (#22928)
## Why The `/permissions` picker needs a config-level way to distinguish legacy anonymous presets from named permission-profile mode. That signal cannot be inferred reliably in the TUI, especially for the edge case where `default_permissions = ":workspace"` is present without a `[permissions]` table. ## What changed - Expose whether the merged config is explicitly in permission-profile mode. - Expose the configured custom permission profile IDs alongside the built-in profile semantics. - Add regression coverage for profile mode detection and custom profile metadata, including the `default_permissions = ":workspace"` case. - Update the thread-manager sample config literal to match the expanded config shape. ## Stack 1. **This PR**: config metadata needed by downstream permission-profile consumers. 2. [#22931](https://github.com/openai/codex/pull/22931): refresh active permission profiles through runtime/session/network state. 3. [#21559](https://github.com/openai/codex/pull/21559): switch `/permissions` to the profile-aware TUI picker. ## Verification - `cargo check -p codex-thread-manager-sample` - `cargo test -p codex-core default_permissions_can_select_builtin_profile_without_permissions_table` - `cargo test -p codex-core permissions_profiles_allow_direct_write_roots_outside_workspace_root`
This commit is contained in:
committed by
GitHub
Unverified
parent
1dd9bf9a74
commit
3009e23644
@@ -1822,6 +1822,8 @@ async fn default_permissions_can_select_builtin_profile_without_permissions_tabl
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert!(config.explicit_permission_profile_mode);
|
||||
assert!(config.custom_permission_profile_ids.is_empty());
|
||||
let policy = config.permissions.file_system_sandbox_policy();
|
||||
assert_eq!(
|
||||
config
|
||||
@@ -2377,6 +2379,10 @@ async fn permissions_profiles_allow_direct_write_roots_outside_workspace_root()
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_eq!(
|
||||
config.custom_permission_profile_ids,
|
||||
vec!["workspace".to_string()]
|
||||
);
|
||||
let memories_root = AbsolutePathBuf::from_absolute_path(std::fs::canonicalize(
|
||||
codex_home.path().join("memories"),
|
||||
)?)?;
|
||||
@@ -7721,6 +7727,8 @@ async fn test_precedence_fixture_with_o3_profile() -> std::io::Result<()> {
|
||||
windows_sandbox_mode: None,
|
||||
windows_sandbox_private_desktop: true,
|
||||
},
|
||||
explicit_permission_profile_mode: false,
|
||||
custom_permission_profile_ids: Vec::new(),
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
enforce_residency: Constrained::allow_any(/*initial_value*/ None),
|
||||
user_instructions: None,
|
||||
@@ -8172,6 +8180,8 @@ async fn test_precedence_fixture_with_gpt3_profile() -> std::io::Result<()> {
|
||||
windows_sandbox_mode: None,
|
||||
windows_sandbox_private_desktop: true,
|
||||
},
|
||||
explicit_permission_profile_mode: false,
|
||||
custom_permission_profile_ids: Vec::new(),
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
enforce_residency: Constrained::allow_any(/*initial_value*/ None),
|
||||
user_instructions: None,
|
||||
@@ -8337,6 +8347,8 @@ async fn test_precedence_fixture_with_zdr_profile() -> std::io::Result<()> {
|
||||
windows_sandbox_mode: None,
|
||||
windows_sandbox_private_desktop: true,
|
||||
},
|
||||
explicit_permission_profile_mode: false,
|
||||
custom_permission_profile_ids: Vec::new(),
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
enforce_residency: Constrained::allow_any(/*initial_value*/ None),
|
||||
user_instructions: None,
|
||||
@@ -8487,6 +8499,8 @@ async fn test_precedence_fixture_with_gpt5_profile() -> std::io::Result<()> {
|
||||
windows_sandbox_mode: None,
|
||||
windows_sandbox_private_desktop: true,
|
||||
},
|
||||
explicit_permission_profile_mode: false,
|
||||
custom_permission_profile_ids: Vec::new(),
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
enforce_residency: Constrained::allow_any(/*initial_value*/ None),
|
||||
user_instructions: None,
|
||||
|
||||
@@ -539,6 +539,13 @@ pub struct Config {
|
||||
/// Effective permission configuration for shell tool execution.
|
||||
pub permissions: Permissions,
|
||||
|
||||
/// Whether config explicitly selected named permissions profiles instead
|
||||
/// of the legacy `sandbox_mode` syntax.
|
||||
pub explicit_permission_profile_mode: bool,
|
||||
|
||||
/// User-defined permission profile IDs available from effective config.
|
||||
pub custom_permission_profile_ids: Vec<String>,
|
||||
|
||||
/// Configures who approval requests are routed to for review once they have
|
||||
/// been escalated. This does not disable separate safety checks such as
|
||||
/// ARC.
|
||||
@@ -2604,6 +2611,17 @@ impl Config {
|
||||
Some(PermissionConfigSyntax::Profiles)
|
||||
)
|
||||
|| permission_config_syntax.is_none();
|
||||
let explicit_permission_profile_mode = default_permissions_override.is_some()
|
||||
|| matches!(
|
||||
permission_config_syntax,
|
||||
Some(PermissionConfigSyntax::Profiles)
|
||||
);
|
||||
let custom_permission_profile_ids = cfg
|
||||
.permissions
|
||||
.as_ref()
|
||||
.map_or_else(Vec::new, |permissions| {
|
||||
permissions.entries.keys().cloned().collect()
|
||||
});
|
||||
let using_implicit_builtin_profile =
|
||||
permission_config_syntax.is_none() && default_permissions.is_none();
|
||||
let should_seed_legacy_workspace_roots = default_permissions.is_none()
|
||||
@@ -3371,6 +3389,8 @@ impl Config {
|
||||
windows_sandbox_mode,
|
||||
windows_sandbox_private_desktop,
|
||||
},
|
||||
explicit_permission_profile_mode,
|
||||
custom_permission_profile_ids,
|
||||
approvals_reviewer: constrained_approvals_reviewer.value(),
|
||||
enforce_residency: enforce_residency.value,
|
||||
notify: cfg.notify,
|
||||
|
||||
@@ -175,6 +175,8 @@ fn new_config(model: Option<String>, arg0_paths: Arg0DispatchPaths) -> anyhow::R
|
||||
Constrained::allow_any(AskForApproval::Never),
|
||||
Constrained::allow_any(PermissionProfile::read_only()),
|
||||
)?,
|
||||
explicit_permission_profile_mode: false,
|
||||
custom_permission_profile_ids: Vec::new(),
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
enforce_residency: Constrained::allow_any(/*initial_value*/ None),
|
||||
hide_agent_reasoning: false,
|
||||
|
||||
Reference in New Issue
Block a user