Add environmentId to request_permissions (#25858)

## Stack

1. #25850 - Key request-permission grants by environment: stores and
applies sticky permission grants per environment id.
2. This PR (#25858) - Add `environmentId` to `request_permissions`: lets
the model target a selected environment and resolves relative permission
paths against it.
3. #25862 - Propagate permission approval environment id: carries the
selected environment id through approval events, app-server requests,
TUI prompts, and delegate forwarding.
4. #25867 - Add remote request permissions integration coverage:
verifies the selected remote environment across request, approval, grant
reuse, and exec.

This PR is stacked on #25850; #25862 and #25867 are stacked on this PR.

## Why

PR1 made request-permission grants internally environment-keyed, but the
model-facing `request_permissions` tool could still only target the
primary environment. For CCA and multi-environment turns, the tool needs
an explicit way to bind a permission request to a selected attached
environment before resolving relative paths.

## What Changed

- Added optional `environmentId` to `RequestPermissionsArgs`, with
`environment_id` accepted as an alias.
- Exposed `environmentId` in the `request_permissions` tool schema and
description.
- Resolve the selected environment before parsing filesystem permission
paths, so relative paths bind to the selected environment cwd.
- Route validated tool calls through
`request_permissions_for_environment` directly instead of duplicating
environment lookup in `Session::request_permissions`.
- Reject unknown environment ids with a model-facing error.
- Updated focused request-permissions and Guardian call sites for the
new optional field.

## Testing

Not run locally per instruction.
This commit is contained in:
jif
2026-06-02 20:51:25 +02:00
committed by GitHub
parent 8e4b92d294
commit e29071e4c9
8 changed files with 119 additions and 33 deletions
@@ -48,6 +48,14 @@ impl From<AdditionalPermissionProfile> for RequestPermissionProfile {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
pub struct RequestPermissionsArgs {
#[serde(
default,
rename = "environment_id",
alias = "environmentId",
skip_serializing_if = "Option::is_none"
)]
#[ts(optional)]
pub environment_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
pub permissions: RequestPermissionProfile,