agent-Specialization/.playwright-mcp/page-2026-04-27T09-03-36-472Z.yml
JOJO e2bbd767f7 feat(host-security+ui): unify host execution/approval behavior, runtime notices, and approval overlay UX
This commit consolidates a large set of host-mode security and UX fixes across backend and frontend.

Security / execution model:
- Make permission/execution mode switches apply immediately (no deferred pending-only behavior).
- Keep runtime mode change notices durable and visible via user-message guidance path.
- Add explicit runtime message source taxonomy support and persistence:
  user / presend / guidance / notify / sub_agent / background_command.
- Ensure guidance/notify insertion is batched per tool-cycle so mid-run inserts are committed together.
- Separate notify from guidance semantics for mode-change notices.
- Add direct-mode auto-fallback handling visibility on frontend.

Approval and command gating:
- Align run_command approval pre-check logic with docker behavior for approval/auto_approval modes in host execution paths.
- Keep approval retry flow and final-result semantics intact when permission errors trigger approval.
- Externalize forbidden command keyword list into JSON config:
  config/forbidden_commands.json.
- Update forbidden command rejection message to user-facing wording:
  用户不允许执行包含“... ”的指令.

Prompt/runtime guidance:
- Refine execution-mode runtime rule text to avoid endless workaround loops:
  one safe alternative first, then request switching to direct mode when truly required.

Chat rendering / message UX:
- Prevent injected guidance/notify user-messages from incorrectly triggering assistant work header/timer chain.
- Restore correct visibility after history reload while preserving runtime-source behavior.
- Update user-header icon/label rendering by message source:
  - guidance -> 引导 + navigation icon
  - notify/sub_agent/background_command -> 通知 + bell icon
  - user/presend -> keep normal user header.
- Add new icons: static/icons/navigation.svg, static/icons/bell.svg.

Approval panel UX:
- Convert desktop approval panel from layout-compress sidebar to overlay + blur sheet.
- Fix panel transition behavior (remove unintended vertical motion; use dedicated desktop overlay transition).
- Improve approval result display:
  - decision and reason split lines,
  - green/red status styling,
  - multiline reason rendering,
  - auto-collapse delay adjusted to 3s.

Execution mode TTL feedback:
- When direct mode auto-expires to sandbox, frontend menu state is updated from status snapshot.
- Show non-auto-dismiss warning toast to explicitly notify auto-fallback.

Misc consistency updates:
- Execution mode label text cleanup in composer.
- Runtime notice wording normalization (权限模式修改为..., 执行环境修改为...).

Build/test notes:
- Frontend rebuilt after UI changes.
- Smoke tests passed for server refactor path.
2026-05-12 19:16:38 +08:00

117 lines
11 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

- generic [ref=e4]:
- complementary [ref=e5]:
- generic [ref=e7]:
- button "展开对话记录" [ref=e8] [cursor=pointer]:
- generic [ref=e9]: 展开对话记录
- img [ref=e11]
- button "新建对话" [ref=e13] [cursor=pointer]:
- generic [ref=e14]: 新建对话
- img [ref=e16]
- button "隐藏工作区" [ref=e19] [cursor=pointer]:
- generic [ref=e20]: 隐藏工作区
- button "虚拟显示器" [ref=e22] [cursor=pointer]:
- generic [ref=e23]: 虚拟显示器
- button "个人页面" [ref=e27] [cursor=pointer]:
- generic [ref=e28]: 个人页面
- img [ref=e29]
- complementary [ref=e32]:
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e38]
- generic [ref=e54]: AI Agent
- generic [ref=e55]:
- button "思考模式(点击切换)" [ref=e56] [cursor=pointer]
- generic "未连接" [ref=e58]
- generic [ref=e60]:
- generic [ref=e61]:
- button "切换侧边栏" [ref=e63] [cursor=pointer]
- button "管理" [ref=e65] [cursor=pointer]
- heading "项目文件" [level=3] [ref=e66]:
- generic [ref=e69]: 项目文件
- generic [ref=e72]: 暂无文件
- main [ref=e74]:
- generic [ref=e75]:
- button "Kimi-k2.5 · 思考模式" [disabled] [ref=e76]:
- generic [ref=e77]:
- generic [ref=e78]: Kimi-k2.5
- generic [ref=e79]: ·
- generic [ref=e80]: 思考模式
- img [ref=e81]
- generic [ref=e83]: 新对话
- generic [ref=e85]:
- generic [ref=e87]:
- generic [ref=e90]: 用户
- generic [ref=e92]: ok你来试一下访问网址使用宿主机模式登陆这个网址就是咱们现在正在对话的网页看看套娃会发生什么 http://localhost:8091/20260427_170002_430
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e97]: AI Assistant
- generic [ref=e98]: 工作中 00:00
- generic [ref=e100]:
- generic [ref=e101] [cursor=pointer]:
- generic [ref=e102]:
- generic [ref=e106]: 思考过程
- generic [ref=e107]: 用户在要求我访问本地运行的网页 http://localhost:8091/20260427_170002_430这是我们正在对话的网页界面。用户想看看"套娃"会发生什么——即在这个对话界面内打开同一个对话的网页,看看会有什么有趣的现象。 让我用 Playwright 浏览器工具来导航到这个地址。 我需要: 1. 先打开浏览器并导航到该 URL 2. 查看页面快照,看看发生了什么 这是一个有趣的实验!让我试试看。 首先,我需要检查一下个人设置: - 自称小A ✅ - 展示html时禁止写实际文件 ✅ 现在用 Playwright 来导航。
- paragraph [ref=e112]: 哈哈,这个"套娃"实验有意思!让我用 Playwright 打开咱们正在聊天的网页,看看会发生什么~
- generic [ref=e113]:
- generic:
- img "展开" [ref=e114] [cursor=pointer]
- generic [ref=e115] [cursor=pointer]:
- generic [ref=e116]: 更多
- generic [ref=e117]: 0 个步骤折叠
- generic [ref=e119]:
- generic [ref=e121]:
- generic [ref=e122] [cursor=pointer]:
- generic [ref=e123]:
- generic [ref=e126]: browser_navigate 执行完成
- generic [ref=e129]: "{ \"content\": [ { \"text\": \"### Ran Playwright code\\n```js\\nawait page.goto('http://localhost:8091/20260427_170002_430');\\n```\\n### Open tabs\\n- 0: (current) [登录 - AI Agent](http://localhost:8091/login)\\n- 1: [登录 - AI Agent](http://localhost:8091/login)\\n### Page\\n- Page URL: http://localhost:8091/login\\n- Page Title: 登录 - AI Agent\\n### Snapshot\\n- [Snapshot](.playwright-mcp/page-2026-04-27T09-03-14-740Z.yml)\\n### Events\\n- New console entries: .playwright-mcp/console-2026-04-27T09-03-14-557Z.log#L1-L2\", \"type\": \"text\" } ], \"elapsed_ms\": 186, \"is_error\": false, \"message\": \"### Ran Playwright code\\n```js\\nawait page.goto('http://localhost:8091/20260427_170002_430');\\n```\\n### Open tabs\\n- 0: (current) [登录 - AI Agent](http://localhost:8091/login)\\n- 1: [登录 - AI Agent](http://localhost:8091/login)\\n### Page\\n- Page URL: http://localhost:8091/login\\n- Page Title: 登录 - AI Agent\\n### Snapshot\\n- [Snapshot](.playwright-mcp/page-2026-04-27T09-03-14-740Z.yml)\\n### Events\\n- New console entries: .playwright-mcp/console-2026-04-27T09-03-14-557Z.log#L1-L2\", \"preview\": \"### Ran Playwright code\\n```js\\nawait page.goto('http://localhost:8091/20260427_170002_430');\\n```\\n### Open tabs\\n- 0: (current) [登录 - AI Agent](http://localhost:8091/login)\\n- 1: [登录 - AI Agent](http://localhost:8091/login)\\n### Page\\n- Page URL: http://localhost:8091/login\\n- Page Title: 登录 - AI Agent\\n###\", \"raw_result\": { \"content\": [ { \"text\": \"### Ran Playwright code\\n```js\\nawait page.goto('http://localhost:8091/20260427_170002_430');\\n```\\n### Open tabs\\n- 0: (current) [登录 - AI Agent](http://localhost:8091/login)\\n- 1: [登录 - AI Agent](http://localhost:8091/login)\\n### Page\\n- Page URL: http://localhost:8091/login\\n- Page Title: 登录 - AI Agent\\n### Snapshot\\n- [Snapshot](.playwright-mcp/page-2026-04-27T09-03-14-740Z.yml)\\n### Events\\n- New console entries: .playwright-mcp/console-2026-04-27T09-03-14-557Z.log#L1-L2\", \"type\": \"text\" } ] }, \"server_id\": \"playwright\", \"server_name\": \"Playwright MCP\", \"structured_content\": null, \"success\": true, \"tool_alias\": \"mcp__playwright__browser_navigate\", \"tool_name\": \"browser_navigate\", \"transport\": \"stdio\" }"
- generic [ref=e131]:
- generic [ref=e132] [cursor=pointer]:
- generic [ref=e133]:
- generic [ref=e137]: 思考过程
- generic [ref=e138]: "导航后,页面被重定向到了登录页面 `http://localhost:8091/login`。这说明需要登录才能访问对话页面。我们在对话界面中,这是需要认证的。 让我看看这个登录页面的快照,了解一下有什么内容。"
- paragraph [ref=e143]: 有趣!它把我重定向到了登录页面。让我看看登录页长什么样~
- generic [ref=e144]:
- generic:
- img "展开" [ref=e145] [cursor=pointer]
- generic [ref=e146] [cursor=pointer]:
- generic [ref=e147]: 更多
- generic [ref=e148]: 0 个步骤折叠
- generic [ref=e150]:
- generic [ref=e152]:
- generic [ref=e153] [cursor=pointer]:
- generic [ref=e154]:
- generic [ref=e157]: browser_snapshot 执行完成
- generic [ref=e160]: "{ \"content\": [ { \"text\": \"### Open tabs\\n- 0: (current) [登录 - AI Agent](http://localhost:8091/login)\\n- 1: [登录 - AI Agent](http://localhost:8091/login)\\n### Page\\n- Page URL: http://localhost:8091/login\\n- Page Title: 登录 - AI Agent\\n### Snapshot\\n```yaml\\n- main [ref=e3]:\\n - generic [ref=e4]:\\n - heading \\\"AI Agent 登录\\\" [level=1] [ref=e5]\\n - paragraph [ref=e6]: 使用账号继续访问工作台\\n - generic [ref=e7]:\\n - generic [ref=e8]: 邮箱\\n - textbox \\\"邮箱\\\" [ref=e9]\\n - generic [ref=e10]:\\n - generic [ref=e11]: 密码\\n - textbox \\\"密码\\\" [ref=e12]\\n - button \\\"登录\\\" [ref=e13] [cursor=pointer]\\n - button \\\"宿主机模式(免登录)\\\" [ref=e14] [cursor=pointer]\\n - generic [ref=e16]:\\n - text: 还没有账号?\\n - link \\\"点击注册\\\" [ref=e17] [cursor=pointer]:\\n - /url: /register\\n```\", \"type\": \"text\" } ], \"elapsed_ms\": 13, \"is_error\": false, \"message\": \"### Open tabs\\n- 0: (current) [登录 - AI Agent](http://localhost:8091/login)\\n- 1: [登录 - AI Agent](http://localhost:8091/login)\\n### Page\\n- Page URL: http://localhost:8091/login\\n- Page Title: 登录 - AI Agent\\n### Snapshot\\n```yaml\\n- main [ref=e3]:\\n - generic [ref=e4]:\\n - heading \\\"AI Agent 登录\\\" [level=1] [ref=e5]\\n - paragraph [ref=e6]: 使用账号继续访问工作台\\n - generic [ref=e7]:\\n - generic [ref=e8]: 邮箱\\n - textbox \\\"邮箱\\\" [ref=e9]\\n - generic [ref=e10]:\\n - generic [ref=e11]: 密码\\n - textbox \", \"preview\": \"### Open tabs\\n- 0: (current) [登录 - AI Agent](http://localhost:8091/login)\\n- 1: [登录 - AI Agent](http://localhost:8091/login)\\n### Page\\n- Page URL: http://localhost:8091/login\\n- Page Title: 登录 - AI Agent\\n### Snapshot\\n```yaml\\n- main [ref=e3]:\\n - generic [ref=e4]:\\n - heading \\\"AI Agent 登录\\\" [level=1] [\", \"raw_result\": { \"content\": [ { \"text\": \"### Open tabs\\n- 0: (current) [登录 - AI Agent](http://localhost:8091/login)\\n- 1: [登录 - AI Agent](http://localhost:8091/login)\\n### Page\\n- Page URL: http://localhost:8091/login\\n- Page Title: 登录 - AI Agent\\n### Snapshot\\n```yaml\\n- main [ref=e3]:\\n - generic [ref=e4]:\\n - heading \\\"AI Agent 登录\\\" [level=1] [ref=e5]\\n - paragraph [ref=e6]: 使用账号继续访问工作台\\n - generic [ref=e7]:\\n - generic [ref=e8]: 邮箱\\n - textbox \\\"邮箱\\\" [ref=e9]\\n - generic [ref=e10]:\\n - generic [ref=e11]: 密码\\n - textbox \\\"密码\\\" [ref=e12]\\n - button \\\"登录\\\" [ref=e13] [cursor=pointer]\\n - button \\\"宿主机模式(免登录)\\\" [ref=e14] [cursor=pointer]\\n - generic [ref=e16]:\\n - text: 还没有账号?\\n - link \\\"点击注册\\\" [ref=e17] [cursor=pointer]:\\n - /url: /register\\n```\", \"type\": \"text\" } ] }, \"server_id\": \"playwright\", \"server_name\": \"Playwright MCP\", \"structured_content\": null, \"success\": true, \"tool_alias\": \"mcp__playwright__browser_snapshot\", \"tool_name\": \"browser_snapshot\", \"transport\": \"stdio\" }"
- generic [ref=e162]:
- generic [ref=e163] [cursor=pointer]:
- generic [ref=e164]:
- generic [ref=e168]: 思考过程
- generic [ref=e169]: 页面有一个"宿主机模式(免登录)"按钮!用户说了"使用宿主机模式登陆",我应该点击这个按钮。 让我点击 ref=e14 这个按钮。
- paragraph [ref=e174]: 看到了!有一个「宿主机模式(免登录)」按钮。点击它~
- generic [ref=e176]:
- generic [ref=e177] [cursor=pointer]:
- generic [ref=e178]:
- generic [ref=e181]: mcp__playwright__browser_click
- generic [ref=e184]: "{ \"element\": \"宿主机模式(免登录)按钮\", \"ref\": \"e14\" }"
- button [ref=e186] [cursor=pointer]:
- img [ref=e187]
- generic [ref=e190]:
- generic [ref=e193]:
- button "+" [disabled] [ref=e194]
- textbox "输入消息... (Ctrl+Enter 发送)" [disabled] [ref=e195]
- button [disabled] [ref=e196]
- generic [ref=e198]:
- button "版本控制:关闭" [disabled] [ref=e199]:
- generic [ref=e200]: 版本控制:关闭
- button "权限:无限制 " [disabled] [ref=e202]:
- generic [ref=e203]: 权限:无限制
- generic [ref=e204]:
- generic [ref=e205]:
- button [disabled] [ref=e206]
- generic:
- generic: 0%已用
- generic: 0/--
- complementary:
- generic:
- heading "工具审批 (0)" [level=3]
- button "关闭审批面板": ×