mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
permissions: expose active profile metadata (#20095)
This commit is contained in:
@@ -317,6 +317,59 @@ pub enum PermissionProfile {
|
||||
External { network: NetworkSandboxPolicy },
|
||||
}
|
||||
|
||||
/// Metadata for the named or implicit built-in permissions profile that
|
||||
/// produced the active `PermissionProfile`.
|
||||
///
|
||||
/// The runtime must honor `PermissionProfile`; this sidecar exists so clients
|
||||
/// can display stable profile identity without trying to reverse-engineer a
|
||||
/// name from the compiled permissions.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
|
||||
pub struct ActivePermissionProfile {
|
||||
/// Profile identifier from `default_permissions` or the implicit built-in
|
||||
/// default, such as `:workspace` or a user-defined `[permissions.<id>]`
|
||||
/// profile.
|
||||
pub id: String,
|
||||
|
||||
/// Optional parent profile identifier once permissions profiles support
|
||||
/// inheritance. This is always `None` until that config feature exists.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub extends: Option<String>,
|
||||
|
||||
/// Bounded user-requested modifications applied on top of the named
|
||||
/// profile, if any.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub modifications: Vec<ActivePermissionProfileModification>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
#[ts(tag = "type")]
|
||||
pub enum ActivePermissionProfileModification {
|
||||
/// Additional concrete directory that should be writable.
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[ts(rename_all = "snake_case")]
|
||||
AdditionalWritableRoot { path: AbsolutePathBuf },
|
||||
}
|
||||
|
||||
impl ActivePermissionProfile {
|
||||
pub fn new(id: impl Into<String>) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
extends: None,
|
||||
modifications: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_modifications(
|
||||
mut self,
|
||||
modifications: Vec<ActivePermissionProfileModification>,
|
||||
) -> Self {
|
||||
self.modifications = modifications;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PermissionProfile {
|
||||
fn default() -> Self {
|
||||
Self::Managed {
|
||||
|
||||
@@ -33,6 +33,7 @@ use crate::mcp::ResourceTemplate as McpResourceTemplate;
|
||||
use crate::mcp::Tool as McpTool;
|
||||
use crate::memory_citation::MemoryCitation;
|
||||
use crate::message_history::HistoryEntry;
|
||||
use crate::models::ActivePermissionProfile;
|
||||
use crate::models::BaseInstructions;
|
||||
use crate::models::ContentItem;
|
||||
use crate::models::MessagePhase;
|
||||
@@ -479,6 +480,12 @@ pub enum Op {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
permission_profile: Option<PermissionProfile>,
|
||||
|
||||
/// Named or built-in profile that produced `permission_profile`, if
|
||||
/// the update selected a profile rather than supplying raw
|
||||
/// permissions.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
active_permission_profile: Option<ActivePermissionProfile>,
|
||||
|
||||
/// Updated Windows sandbox mode for tool execution.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
windows_sandbox_level: Option<WindowsSandboxLevel>,
|
||||
@@ -3508,6 +3515,12 @@ pub struct SessionConfiguredEvent {
|
||||
/// Canonical effective permissions for commands executed in the session.
|
||||
pub permission_profile: PermissionProfile,
|
||||
|
||||
/// Named or implicit built-in profile that produced `permission_profile`,
|
||||
/// when known.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub active_permission_profile: Option<ActivePermissionProfile>,
|
||||
|
||||
/// Working directory that should be treated as the *root* of the
|
||||
/// session.
|
||||
pub cwd: AbsolutePathBuf,
|
||||
@@ -3559,6 +3572,8 @@ impl<'de> Deserialize<'de> for SessionConfiguredEvent {
|
||||
// and immediately project it into the canonical `permission_profile`.
|
||||
sandbox_policy: Option<SandboxPolicy>,
|
||||
permission_profile: Option<PermissionProfile>,
|
||||
#[serde(default)]
|
||||
active_permission_profile: Option<ActivePermissionProfile>,
|
||||
cwd: AbsolutePathBuf,
|
||||
reasoning_effort: Option<ReasoningEffortConfig>,
|
||||
history_log_id: u64,
|
||||
@@ -3590,6 +3605,7 @@ impl<'de> Deserialize<'de> for SessionConfiguredEvent {
|
||||
approval_policy: wire.approval_policy,
|
||||
approvals_reviewer: wire.approvals_reviewer,
|
||||
permission_profile,
|
||||
active_permission_profile: wire.active_permission_profile,
|
||||
cwd: wire.cwd,
|
||||
reasoning_effort: wire.reasoning_effort,
|
||||
history_log_id: wire.history_log_id,
|
||||
@@ -5124,6 +5140,7 @@ mod tests {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
permission_profile: permission_profile.clone(),
|
||||
active_permission_profile: None,
|
||||
cwd: test_path_buf("/home/user/project").abs(),
|
||||
reasoning_effort: Some(ReasoningEffortConfig::default()),
|
||||
history_log_id: 0,
|
||||
|
||||
Reference in New Issue
Block a user