mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Add request permissions tool (#13092)
Adds a built-in `request_permissions` tool and wires it through the Codex core, protocol, and app-server layers so a running turn can ask the client for additional permissions instead of relying on a static session policy. The new flow emits a `RequestPermissions` event from core, tracks the pending request by call ID, forwards it through app-server v2 as an `item/permissions/requestApproval` request, and resumes the tool call once the client returns an approved subset of the requested permission profile.
This commit is contained in:
@@ -15,5 +15,6 @@ pub mod parse_command;
|
||||
pub mod permissions;
|
||||
pub mod plan_tool;
|
||||
pub mod protocol;
|
||||
pub mod request_permissions;
|
||||
pub mod request_user_input;
|
||||
pub mod user_input;
|
||||
|
||||
@@ -170,9 +170,13 @@ impl TryFrom<MacOsAutomationPermissionDe> for MacOsAutomationPermission {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default, Hash, Serialize, Deserialize, JsonSchema, TS)]
|
||||
#[serde(default)]
|
||||
pub struct MacOsSeatbeltProfileExtensions {
|
||||
#[serde(alias = "preferences")]
|
||||
pub macos_preferences: MacOsPreferencesPermission,
|
||||
#[serde(alias = "automations")]
|
||||
pub macos_automation: MacOsAutomationPermission,
|
||||
#[serde(alias = "accessibility")]
|
||||
pub macos_accessibility: bool,
|
||||
#[serde(alias = "calendar")]
|
||||
pub macos_calendar: bool,
|
||||
}
|
||||
|
||||
@@ -1504,6 +1508,30 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn macos_seatbelt_profile_extensions_deserializes_tool_schema_aliases() {
|
||||
let permissions =
|
||||
serde_json::from_value::<MacOsSeatbeltProfileExtensions>(serde_json::json!({
|
||||
"preferences": "read_write",
|
||||
"automations": ["com.apple.Notes"],
|
||||
"accessibility": true,
|
||||
"calendar": true
|
||||
}))
|
||||
.expect("deserialize macos permissions");
|
||||
|
||||
assert_eq!(
|
||||
permissions,
|
||||
MacOsSeatbeltProfileExtensions {
|
||||
macos_preferences: MacOsPreferencesPermission::ReadWrite,
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Notes".to_string(),
|
||||
]),
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn macos_automation_permission_deserializes_all_and_none() {
|
||||
let all = serde_json::from_str::<MacOsAutomationPermission>("\"all\"")
|
||||
|
||||
@@ -41,6 +41,8 @@ use crate::num_format::format_with_separators;
|
||||
use crate::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use crate::parse_command::ParsedCommand;
|
||||
use crate::plan_tool::UpdatePlanArgs;
|
||||
use crate::request_permissions::RequestPermissionsEvent;
|
||||
use crate::request_permissions::RequestPermissionsResponse;
|
||||
use crate::request_user_input::RequestUserInputResponse;
|
||||
use crate::user_input::UserInput;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
@@ -69,6 +71,7 @@ pub use crate::permissions::FileSystemSandboxKind;
|
||||
pub use crate::permissions::FileSystemSandboxPolicy;
|
||||
pub use crate::permissions::FileSystemSpecialPath;
|
||||
pub use crate::permissions::NetworkSandboxPolicy;
|
||||
pub use crate::request_permissions::RequestPermissionsArgs;
|
||||
pub use crate::request_user_input::RequestUserInputEvent;
|
||||
|
||||
/// Open/close tags for special user-input blocks. Used across crates to avoid
|
||||
@@ -356,6 +359,14 @@ pub enum Op {
|
||||
response: RequestUserInputResponse,
|
||||
},
|
||||
|
||||
/// Resolve a request_permissions tool call.
|
||||
RequestPermissionsResponse {
|
||||
/// Call id for the in-flight request.
|
||||
id: String,
|
||||
/// User-granted permissions.
|
||||
response: RequestPermissionsResponse,
|
||||
},
|
||||
|
||||
/// Resolve a dynamic tool call request.
|
||||
DynamicToolResponse {
|
||||
/// Call id for the in-flight request.
|
||||
@@ -1144,6 +1155,8 @@ pub enum EventMsg {
|
||||
|
||||
ExecApprovalRequest(ExecApprovalRequestEvent),
|
||||
|
||||
RequestPermissions(RequestPermissionsEvent),
|
||||
|
||||
RequestUserInput(RequestUserInputEvent),
|
||||
|
||||
DynamicToolCallRequest(DynamicToolCallRequest),
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
use crate::models::PermissionProfile;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use ts_rs::TS;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
||||
pub struct RequestPermissionsArgs {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub reason: Option<String>,
|
||||
pub permissions: PermissionProfile,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
||||
pub struct RequestPermissionsResponse {
|
||||
pub permissions: PermissionProfile,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
||||
pub struct RequestPermissionsEvent {
|
||||
/// Responses API call id for the associated tool call, if available.
|
||||
pub call_id: String,
|
||||
/// Turn ID that this request belongs to.
|
||||
/// Uses `#[serde(default)]` for backwards compatibility.
|
||||
#[serde(default)]
|
||||
pub turn_id: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub reason: Option<String>,
|
||||
pub permissions: PermissionProfile,
|
||||
}
|
||||
Reference in New Issue
Block a user