mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat(core) Persist request_permission data across turns (#14009)
## Summary request_permissions flows should support persisting results for the session. Open Question: Still deciding if we need within-turn approvals - this adds complexity but I could see it being useful ## Testing - [x] Updated unit tests --------- Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -901,12 +901,13 @@ The built-in `request_permissions` tool sends an `item/permissions/requestApprov
|
||||
}
|
||||
```
|
||||
|
||||
The client responds with `result.permissions`, which should be the granted subset of the requested permission profile:
|
||||
The client responds with `result.permissions`, which should be the granted subset of the requested permission profile. It may also set `result.scope` to `"session"` to make the grant persist for later turns in the same session; omitted or `"turn"` keeps the existing turn-scoped behavior:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 61,
|
||||
"result": {
|
||||
"scope": "session",
|
||||
"permissions": {
|
||||
"fileSystem": {
|
||||
"write": [
|
||||
|
||||
@@ -120,6 +120,7 @@ use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_protocol::protocol::ReviewOutputEvent;
|
||||
use codex_protocol::protocol::TokenCountEvent;
|
||||
use codex_protocol::protocol::TurnDiffEvent;
|
||||
use codex_protocol::request_permissions::PermissionGrantScope as CorePermissionGrantScope;
|
||||
use codex_protocol::request_permissions::RequestPermissionsResponse as CoreRequestPermissionsResponse;
|
||||
use codex_protocol::request_user_input::RequestUserInputAnswer as CoreRequestUserInputAnswer;
|
||||
use codex_protocol::request_user_input::RequestUserInputResponse as CoreRequestUserInputResponse;
|
||||
@@ -718,6 +719,7 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
);
|
||||
let empty = CoreRequestPermissionsResponse {
|
||||
permissions: Default::default(),
|
||||
scope: CorePermissionGrantScope::Turn,
|
||||
};
|
||||
if let Err(err) = conversation
|
||||
.submit(Op::RequestPermissionsResponse {
|
||||
@@ -2219,12 +2221,14 @@ fn request_permissions_response_from_client_result(
|
||||
error!("request failed with client error: {err:?}");
|
||||
return Some(CoreRequestPermissionsResponse {
|
||||
permissions: Default::default(),
|
||||
scope: CorePermissionGrantScope::Turn,
|
||||
});
|
||||
}
|
||||
Err(err) => {
|
||||
error!("request failed: {err:?}");
|
||||
return Some(CoreRequestPermissionsResponse {
|
||||
permissions: Default::default(),
|
||||
scope: CorePermissionGrantScope::Turn,
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -2234,6 +2238,7 @@ fn request_permissions_response_from_client_result(
|
||||
error!("failed to deserialize PermissionsRequestApprovalResponse: {err}");
|
||||
PermissionsRequestApprovalResponse {
|
||||
permissions: V2GrantedPermissionProfile::default(),
|
||||
scope: codex_app_server_protocol::PermissionGrantScope::Turn,
|
||||
}
|
||||
});
|
||||
Some(CoreRequestPermissionsResponse {
|
||||
@@ -2241,6 +2246,7 @@ fn request_permissions_response_from_client_result(
|
||||
requested_permissions,
|
||||
response.permissions.into(),
|
||||
),
|
||||
scope: response.scope.to_core(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2766,11 +2772,32 @@ mod tests {
|
||||
response,
|
||||
CoreRequestPermissionsResponse {
|
||||
permissions: expected_permissions,
|
||||
scope: CorePermissionGrantScope::Turn,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_permissions_response_preserves_session_scope() {
|
||||
let response = request_permissions_response_from_client_result(
|
||||
CorePermissionProfile::default(),
|
||||
Ok(Ok(serde_json::json!({
|
||||
"scope": "session",
|
||||
"permissions": {},
|
||||
}))),
|
||||
)
|
||||
.expect("response should be accepted");
|
||||
|
||||
assert_eq!(
|
||||
response,
|
||||
CoreRequestPermissionsResponse {
|
||||
permissions: CorePermissionProfile::default(),
|
||||
scope: CorePermissionGrantScope::Session,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collab_resume_begin_maps_to_item_started_resume_agent() {
|
||||
let event = CollabResumeBeginEvent {
|
||||
|
||||
@@ -6,6 +6,7 @@ use app_test_support::create_request_permissions_sse_response;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::PermissionGrantScope;
|
||||
use codex_app_server_protocol::PermissionsRequestApprovalResponse;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_app_server_protocol::ServerRequest;
|
||||
@@ -95,6 +96,7 @@ async fn request_permissions_round_trip() -> Result<()> {
|
||||
}),
|
||||
macos: None,
|
||||
},
|
||||
scope: PermissionGrantScope::Turn,
|
||||
})?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Reference in New Issue
Block a user