Skip to main content

三种权限行为

每一次工具调用,系统都会做出三种裁决之一: 这些行为由 PermissionResult 类型定义(src/utils/permissions/PermissionResult.ts)。

权限规则的来源

规则从 8 个来源汇聚(PERMISSION_RULE_SOURCESpermissions.ts:109),优先级从低到高(后者覆盖前者):
每个来源维护三个数组:alwaysAllowRules[source]alwaysAskRules[source]alwaysDenyRules[source] 规则数据结构为 PermissionRule

规则匹配引擎

三维度匹配

permissions.ts 实现了三种匹配维度: 1. 工具名匹配toolMatchesRule(),第 238 行) 匹配整个工具,仅当规则没有 ruleContent
MCP 工具使用 getToolNameForPermissionCheck() 获取匹配名称,支持有前缀(mcp__server__tool)和无前缀模式。 2. 命令模式匹配(BashTool 的 checkPermissions() BashTool 通过 preparePermissionMatcher()Tool.ts:520)解析命令模式:
命令通过 AST 解析(readOnlyValidation.ts 使用 tree-sitter bash),提取第一个子命令进行匹配。 3. 路径匹配(文件工具的 checkPermissions() Read/Edit/Write 工具通过 getPath() 提取文件路径,与 ruleContent 中的 glob 模式匹配:

权限检查的完整流程

每次工具调用的权限检查(canUseTool()checkPermissions())经过以下步骤:

权限模式

Plan Mode 切换由 EnterPlanModeTool.call() 触发:
退出时由 ExitPlanModeV2Tool 恢复为之前的模式。

Denial Tracking:死循环防护

src/utils/permissions/denialTracking.ts 实现了拒绝追踪机制:
当 AI 被连续拒绝同一类操作达到上限时:
  1. recordDenial() 记录拒绝,增加计数
  2. shouldFallbackToPrompting() 检测到连续拒绝,返回 true
  3. 系统向 AI 注入消息:“Your previous tool call was rejected…”
  4. AI 被迫改变策略,避免”反复请求同一个被拒操作”的死循环
操作成功时调用 recordSuccess() 重置计数。

规则的运行时更新

权限规则可以在运行时动态更新(applyPermissionUpdate()PermissionUpdate.ts):
当用户在 Ask 对话框中选择 “Always allow”,系统调用 persistPermissionUpdates() 将规则写入对应层级的 settings 文件(project/user/managed),同时更新内存中的 toolPermissionContext