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.
117 lines
11 KiB
YAML
117 lines
11 KiB
YAML
- 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 "关闭审批面板": × |