feat(tui): open permission picker for conversational requests

Add a `request_permission_preset` tool that lets the model route user
requests for sandbox or approval mode changes into the existing picker.
The picker opens with the requested preset selected and reports the final
user choice back to the active turn.

Wire the request through protocol, app-server, core, tools, and TUI
handling so accepted picker choices update the effective permissions while
Full Access still uses the existing confirmation flow.
This commit is contained in:
Felipe Coury
2026-04-12 14:20:25 -03:00
parent 46ab9974dc
commit 13bdd524f2
58 changed files with 2416 additions and 26 deletions

View File

@@ -101,6 +101,64 @@
],
"type": "object"
},
"ApprovalsReviewer": {
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
"enum": [
"user",
"guardian_subagent"
],
"type": "string"
},
"AskForApproval": {
"oneOf": [
{
"enum": [
"untrusted",
"on-failure",
"on-request",
"never"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
"mcp_elicitations",
"rules",
"sandbox_approval"
],
"type": "object"
}
},
"required": [
"granular"
],
"title": "GranularAskForApproval",
"type": "object"
}
]
},
"ChatgptAuthTokensRefreshParams": {
"properties": {
"previousAccountId": {
@@ -1187,6 +1245,13 @@
],
"type": "object"
},
"NetworkAccess": {
"enum": [
"restricted",
"enabled"
],
"type": "string"
},
"NetworkApprovalContext": {
"properties": {
"host": {
@@ -1344,6 +1409,64 @@
}
]
},
"PermissionPresetId": {
"enum": [
"auto",
"full-access",
"read-only",
"guardian-approvals"
],
"type": "string"
},
"PermissionPresetRequestApprovalParams": {
"properties": {
"approvalPolicy": {
"$ref": "#/definitions/AskForApproval"
},
"approvalsReviewer": {
"$ref": "#/definitions/ApprovalsReviewer"
},
"description": {
"type": "string"
},
"itemId": {
"type": "string"
},
"label": {
"type": "string"
},
"preset": {
"$ref": "#/definitions/PermissionPresetId"
},
"reason": {
"type": [
"string",
"null"
]
},
"sandboxPolicy": {
"$ref": "#/definitions/SandboxPolicy"
},
"threadId": {
"type": "string"
},
"turnId": {
"type": "string"
}
},
"required": [
"approvalPolicy",
"approvalsReviewer",
"description",
"itemId",
"label",
"preset",
"sandboxPolicy",
"threadId",
"turnId"
],
"type": "object"
},
"PermissionsRequestApprovalParams": {
"properties": {
"itemId": {
@@ -1373,6 +1496,53 @@
],
"type": "object"
},
"ReadOnlyAccess": {
"oneOf": [
{
"properties": {
"includePlatformDefaults": {
"default": true,
"type": "boolean"
},
"readableRoots": {
"default": [],
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": "array"
},
"type": {
"enum": [
"restricted"
],
"title": "RestrictedReadOnlyAccessType",
"type": "string"
}
},
"required": [
"type"
],
"title": "RestrictedReadOnlyAccess",
"type": "object"
},
{
"properties": {
"type": {
"enum": [
"fullAccess"
],
"title": "FullAccessReadOnlyAccessType",
"type": "string"
}
},
"required": [
"type"
],
"title": "FullAccessReadOnlyAccess",
"type": "object"
}
]
},
"RequestId": {
"anyOf": [
{
@@ -1410,6 +1580,125 @@
},
"type": "object"
},
"SandboxPolicy": {
"oneOf": [
{
"properties": {
"type": {
"enum": [
"dangerFullAccess"
],
"title": "DangerFullAccessSandboxPolicyType",
"type": "string"
}
},
"required": [
"type"
],
"title": "DangerFullAccessSandboxPolicy",
"type": "object"
},
{
"properties": {
"access": {
"allOf": [
{
"$ref": "#/definitions/ReadOnlyAccess"
}
],
"default": {
"type": "fullAccess"
}
},
"networkAccess": {
"default": false,
"type": "boolean"
},
"type": {
"enum": [
"readOnly"
],
"title": "ReadOnlySandboxPolicyType",
"type": "string"
}
},
"required": [
"type"
],
"title": "ReadOnlySandboxPolicy",
"type": "object"
},
{
"properties": {
"networkAccess": {
"allOf": [
{
"$ref": "#/definitions/NetworkAccess"
}
],
"default": "restricted"
},
"type": {
"enum": [
"externalSandbox"
],
"title": "ExternalSandboxSandboxPolicyType",
"type": "string"
}
},
"required": [
"type"
],
"title": "ExternalSandboxSandboxPolicy",
"type": "object"
},
{
"properties": {
"excludeSlashTmp": {
"default": false,
"type": "boolean"
},
"excludeTmpdirEnvVar": {
"default": false,
"type": "boolean"
},
"networkAccess": {
"default": false,
"type": "boolean"
},
"readOnlyAccess": {
"allOf": [
{
"$ref": "#/definitions/ReadOnlyAccess"
}
],
"default": {
"type": "fullAccess"
}
},
"type": {
"enum": [
"workspaceWrite"
],
"title": "WorkspaceWriteSandboxPolicyType",
"type": "string"
},
"writableRoots": {
"default": [],
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": "array"
}
},
"required": [
"type"
],
"title": "WorkspaceWriteSandboxPolicy",
"type": "object"
}
]
},
"ThreadId": {
"type": "string"
},
@@ -1621,6 +1910,31 @@
"title": "Item/permissions/requestApprovalRequest",
"type": "object"
},
{
"description": "Request the client to open its permission preset picker.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"item/permissionPreset/requestApproval"
],
"title": "Item/permissionPreset/requestApprovalRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/PermissionPresetRequestApprovalParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Item/permissionPreset/requestApprovalRequest",
"type": "object"
},
{
"description": "Execute a dynamic tool call on the client.",
"properties": {