a4phone 在 AI 助手请求执行敏感操作(运行命令、读写文件、修改代码等)时,把权限请求推送到手机:外出模式下手机端显示 Approve / Deny / Always Approve 三个决策按钮,点选后决策回传会话,AI 按你的选择继续执行或中止。功能覆盖 Claude Code、Codex、ZCode 的 PermissionRequest 事件与 DSH 的 approval/request 事件,推送正文按工具类型格式化——Bash 显示待执行命令,Read/Write/Edit 显示目标文件路径;当请求附带权限建议时提供 Always Approve 按钮批量授权,后续同类操作不再逐次询问。手机超时未决策或推送失败时自动回退终端原生审批,计划确认类请求的超时时长更长。本文章介绍权限请求的触发范围、消息格式化、决策按钮与回传机制。

1. 功能概述

维度 说明
触发事件 Claude Code / Codex / ZCode:PermissionRequest;DSH:approval/request
拦截方式 Claude Code / Codex / ZCode:PermissionRequest Hook;DSH:approval/request 事件拦截
决策选项 Approve(允许)/ Deny(拒绝)/ Always Approve(总是允许,按建议批量授权)
生效模式 仅外出模式(a4p out);桌面提醒两种模式均触发
超时回退 手机超时未决策自动回退终端审批
适用版本 ZCode 支持自 1.6.0 起

1.1 事件流程

graph LR A[AI 请求权限
PermissionRequest] --> B{当前模式} B -->|终端优先| C[终端原生审批] B -->|外出模式| D{工具类型} D -->|AskUserQuestion| E[直接放行
提问由提问功能处理] D -->|其他工具| F[格式化请求内容] F --> G[推送手机
Approve / Deny] G --> H{存在权限建议} H -->|是| I[附加 Always Approve
按钮] H -->|否| J[仅两个按钮] I --> K[手机点选决策] J --> K K --> L[决策回传会话] L --> M[AI 继续或中止] style A fill:#e8f4f8,stroke:#1a6b8a,stroke-width:2px style B fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style C fill:#fdebd0,stroke:#b7950b,stroke-width:2px style D fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style E fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style F fill:#d6eaf8,stroke:#1a6b8a,stroke-width:2px style G fill:#fadbd8,stroke:#c0392b,stroke-width:2px style H fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style I fill:#fdebd0,stroke:#b7950b,stroke-width:2px style J fill:#fdebd0,stroke:#b7950b,stroke-width:2px style K fill:#e8f4f8,stroke:#1a6b8a,stroke-width:2px style L fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style M fill:#ffecd6,stroke:#e67e22,stroke-width:2px

2. 请求内容格式化

推送标题为 {Agent}: {工具名}(如 Claude Code: Bash),正文按工具类型格式化展示请求内容:

工具类型 展示内容
ExitPlanMode 计划全文(截断到 1000 字符)
Bash 要执行的命令
Read / Write / Edit 目标文件路径
其他工具 工具输入的 JSON 序列化

请求内容超过 1000 字符时截断并添加省略号,避免超出 ntfy 推送上限。

3. 决策按钮

按钮 行为
Approve 允许本次操作(decision.behavior = "allow"
Deny 拒绝本次操作(decision.behavior = "deny"
Always Approve 允许本次操作,并批量授权工具返回的所有权限建议(仅当请求携带 permission_suggestions 时出现)

当工具的权限请求附带建议列表(如 Bash 工具建议的一批可执行命令)时,推送会插入 Always Approve 按钮,点击后 a4phone 把建议写入 updatedPermissions,AI 后续同类操作不再逐次询问。

4. 特殊处理

4.1 AskUserQuestion 直接放行

AskUserQuestion(Claude Code / ZCode 的提问工具)触发的权限请求不推送手机、也不弹桌面通知——提问的完整交互由AI提问交互功能负责,a4phone 直接返回 allow 放行(ZCode 对一次提问会同时触发 PreToolUse 与 PermissionRequest 两次 Hook,跳过弹窗避免重复通知)。

4.2 计划审批超时更长

ExitPlanMode(计划确认)使用独立的 planTimeout(默认 300 秒),比普通权限请求的 timeout(默认 60 秒)更长,给离开电脑的用户更充足的决策时间。

5. 超时与失败回退

场景 处理方式
手机超时未决策 等待超时后回退终端原生审批
推送失败 回退终端原生审批
终端优先模式 不推送手机,直接走终端审批(桌面弹窗仍提示"有权限请求需要处理")
DSH 手机决策 Approve 映射为 allowed-once,Deny 映射为 rejected

权限请求的桌面弹窗在两种模式下都会触发(1.5.0 起);1.6.0 起弹窗由守护进程从 ~/.a4phone/notify-queue/ 代发。