Files
zn-ai/docs/ClawX-Browser-Automation-Migration-Plan.md
duanshuwen ea1fd18e6f feat: enhance after-pack script to copy OpenClaw runtime dependencies
- Added a new script `bundle-openclaw.mjs` to bundle OpenClaw runtime dependencies.
- Updated `after-pack.cjs` to copy bundled OpenClaw runtime and its node_modules.
- Improved cleanup of unnecessary development files in node_modules.
- Adjusted paths for resources in the packaging process.

style: update loading indicator styles in ChatHistoryPanel

- Changed the border radius and padding for the loading indicator in ChatHistoryPanel.

fix: improve ProvidersSection to handle provider account syncing

- Added logic to sync model configuration to provider accounts.
- Introduced error handling and loading states during the sync process.
- Enhanced vendor resolution and account management logic.

fix: fallback session handling in chat store

- Implemented fallback session logic in loadSessions to ensure a valid session is always available on error.
2026-04-22 21:56:37 +08:00

346 lines
18 KiB
Markdown
Raw 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.

# ClawX 浏览器自动化能力迁移规划
## 1. 背景与结论
- 现象:在 `ClawX` 中发送“打开http://www.baidu.com”模型可以真实驱动浏览器打开页面`zn-ai` 中发送同样内容,当前不会真实操作浏览器。
- 结论问题不在“模型名”或“prompt”本身而在聊天请求最终是否进入了真正的 `OpenClaw runtime / gateway / tool execution loop`
- `ClawX` 目前走的是完整的 `OpenClaw Gateway` 链路,且会在启动前把 `~/.openclaw/openclaw.json``browser.enabled` 等配置补齐。
- `zn-ai` 当前聊天主链路仍是 `in-process provider.chat(...)`,没有真实 `OpenClaw` 子进程、没有 browser config sync、没有 tool execution protocol所以模型只能生成文本不能真实调用浏览器工具。
- `zn-ai` 已经有 `playwright``browser-use-sdk` 依赖,但它们并没有接入当前聊天主链路,因此现在并不构成功能闭环。
这份文档是对 [OpenClaw-Chat-Alignment-Plan.md](./OpenClaw-Chat-Alignment-Plan.md) 的浏览器自动化专题补充,重点回答:
1. 为什么 `ClawX` 能打开浏览器而 `zn-ai` 不能。
2. `zn-ai` 还缺哪些关键文件/能力。
3. 下一步迁移应该按什么顺序做。
## 2. 两个项目的真实执行链路对比
### 2.1 ClawX
`ClawX` 的对话会进入真实 Gateway/Runtime
1. Renderer 发消息:
`ClawX/src/stores/chat/runtime-send-actions.ts:192-218`
通过 `invokeIpc('gateway:rpc', 'chat.send', ...)``chat:sendWithMedia` 发起调用。
2. Main IPC 转发:
`ClawX/electron/main/ipc-handlers.ts:1209-1216`
`ClawX/electron/main/ipc-handlers.ts:1298-1368`
3. Gateway Manager 托管 OpenClaw 子进程、WebSocket、重连、ready 状态:
`ClawX/electron/gateway/manager.ts:1-205`
`ClawX/electron/gateway/process-launcher.ts:91-144`
4. 启动前同步 `openclaw.json`
`ClawX/electron/gateway/config-sync.ts:251-323`
`ClawX/electron/utils/openclaw-auth.ts:1169-1321`
5. `OpenClaw` runtime 真正执行 `tool_use / tool_result`,包括浏览器工具。
6. Renderer 可以展示 thinking、tool card、tool result
`ClawX/src/pages/Chat/message-utils.ts:153-201`
`ClawX/src/stores/chat.ts:1886-2015`
`ClawX/src/pages/Chat/ChatMessage.tsx:1-220`
### 2.2 zn-ai
`zn-ai` 当前对话仍停留在“直接调用模型”:
1. Renderer 发消息:
`zn-ai/src/stores/chat.ts:271-294`
通过 `gatewayRpc('chat.send', ...)` 进入本地 gateway。
2. Main IPC 只做本地转发:
`zn-ai/electron/main.ts:94-97`
3. Gateway Manager 仍是 in-process 模式:
`zn-ai/electron/gateway/manager.ts:53-62`
4. Chat handler 直接取 provider account 后调用:
`zn-ai/electron/gateway/handlers/chat.ts:48-49`
`zn-ai/electron/gateway/handlers/chat.ts:134-161`
5. 当前事件协议只有 `chat:delta/final/error/aborted`
`zn-ai/electron/gateway/types.ts:10-47`
6. 当前消息 UI 只展示普通文本/附件,不展示 tool/thinking 执行过程:
`zn-ai/src/components/chat/ChatMessageList.tsx:23-90`
`zn-ai/src/components/chat/types.ts:15-24`
因此,`zn-ai` 现在收到“打开百度”时,并没有一个真正的浏览器工具执行器可以被模型调用。
## 3. 为什么 ClawX 能打开浏览器
`ClawX` 能成功,不是因为“它装了 Playwright”这么简单而是它把下面这几层都打通了
### 3.1 有真实 OpenClaw Runtime
- `ClawX/electron/gateway/process-launcher.ts` 会通过 `utilityProcess.fork(...)` 启动 Gateway 子进程。
- `ClawX/package.json:39-42,123` 已经引入 `openclaw` 与配套 bundling 脚本。
- `ClawX/electron-builder.yml:16-31` 会把 `build/openclaw/` 打进安装包。
### 3.2 启动前会把浏览器能力写进 openclaw.json
- `ClawX/electron/utils/openclaw-auth.ts:1181-1194` 会确保:
- `browser.enabled = true`
- `browser.defaultProfile = 'openclaw'`
- `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork = true`
- `ClawX/electron/gateway/config-sync.ts:317-320` 会在 Gateway 启动前统一执行这类配置同步。
### 3.3 聊天调用的是 Gateway不是裸模型
- `ClawX` 的聊天发送不是直接 `provider.chat(...)`,而是先进入 `gateway:rpc -> chat.send`
- 这样模型在运行时可以发出 `tool_use`,再由 runtime 真正执行浏览器操作。
### 3.4 前端能消费工具执行过程
- `ClawX` 的消息解析和 UI 会识别 `tool_use` / `tool_result`,所以不仅能执行,也能在界面上看到执行轨迹。
## 4. 为什么 zn-ai 现在不能打开浏览器
### 4.1 当前没有真实 OpenClaw 子进程接入聊天链路
- `zn-ai/electron/gateway/manager.ts` 明确返回 `mode: 'in-process'`
- `zn-ai/electron/gateway/openclaw-process-owner.ts` 目前只是占位实现:
- `prepare()` 只创建目录
- `start()` 只把状态切到 `running`
- 没有真正 `fork` 进程
- 也没有 WebSocket / JSON-RPC / ready 检测
### 4.2 当前聊天处理器直接打模型
- `zn-ai/electron/gateway/handlers/chat.ts` 里核心执行是:
-`provider account`
- 拼消息历史
- `createProvider(accountId)`
- `provider.chat(messages, model, { signal })`
这条链路天然不会触发 OpenClaw 的浏览器工具。
### 4.3 当前没有 browser config sync
- `zn-ai` 虽然已经有 `electron/utils/paths.ts``openclaw-process-owner.ts` 这些雏形,
但没有对应 `ClawX/electron/utils/openclaw-auth.ts``ClawX/electron/gateway/config-sync.ts` 那一整套启动前配置同步逻辑。
- 即使未来把 `openclaw` 包带进来,如果不写入 `browser.enabled`,浏览器能力仍可能不会生效。
### 4.4 当前协议和 UI 也没有完整 tool 语义
- `zn-ai/electron/gateway/types.ts` 目前没有面向 tool execution 的 richer event protocol。
- `zn-ai/src/components/chat/ChatMessageList.tsx` 目前也没有对应 `tool card / thinking / tool result` 的展示结构。
## 5. 缺少哪些文件
这里分成两类:`P0 必需缺失文件``已有但需要重构的文件`
### 5.1 P0 必需缺失文件
这些文件是让“聊天真正能调用浏览器工具”最关键的一批,建议优先迁:
| 能力 | ClawX 参考文件 | zn-ai 当前状态 | 结论 |
| --- | --- | --- | --- |
| OpenClaw 子进程启动 | `ClawX/electron/gateway/process-launcher.ts` | 缺失 | 必需补 |
| Gateway 启动前配置同步 | `ClawX/electron/gateway/config-sync.ts` | 缺失 | 必需补 |
| browser/config 写入 | `ClawX/electron/utils/openclaw-auth.ts` | 缺失 | 必需补 |
| Gateway WebSocket/ready | `ClawX/electron/gateway/ws-client.ts` | 缺失 | 必需补 |
| Gateway 协议定义 | `ClawX/electron/gateway/protocol.ts` | 缺失 | 必需补 |
| Gateway request 跟踪 | `ClawX/electron/gateway/request-store.ts` | 缺失 | 建议补 |
| 启动/重连/生命周期控制 | `ClawX/electron/gateway/lifecycle-controller.ts` `restart-controller.ts` `connection-monitor.ts` | 缺失 | 建议补 |
| 进程守护与诊断 | `ClawX/electron/gateway/supervisor.ts` `startup-orchestrator.ts` `startup-stderr.ts` | 缺失 | 建议补 |
| openclaw 打包脚本 | `ClawX/scripts/bundle-openclaw.mjs` | 缺失 | 必需补 |
| openclaw 插件打包 | `ClawX/scripts/bundle-openclaw-plugins.mjs` | 缺失 | 浏览器最小闭环非必需,但后续强相关 |
| openclaw 安装包资源声明 | `ClawX/electron-builder.yml``build/openclaw -> openclaw` | `zn-ai/electron-builder.yml` 未配置 | 必需补 |
### 5.2 已有但需要重构的文件
这些文件在 `zn-ai` 里已经存在,但当前实现还是过渡态:
| zn-ai 文件 | 当前问题 | 改造方向 |
| --- | --- | --- |
| `electron/gateway/manager.ts` | 仍是 in-process manager | 改成真实 OpenClaw gateway manager负责 start/stop/restart/status/rpc |
| `electron/gateway/openclaw-process-owner.ts` | 只是状态占位,没有真实进程 | 接入 `utilityProcess.fork`、ready 检测、退出处理 |
| `electron/gateway/handlers/chat.ts` | 直接 `provider.chat(...)` | 改成调用真实 Gateway RPC不再直接驱动 provider |
| `electron/main.ts` | 只初始化本地 gateway bridge | 增加 OpenClaw runtime 启动、配置同步、事件注册 |
| `electron/utils/paths.ts` | 已有路径层,但没接 runtime bundling | 继续沿用,作为 runtime/package path 基础设施 |
| `package.json` | 没有 `openclaw` 依赖和 bundling 脚本 | 对齐 `ClawX` 的 runtime 打包入口 |
| `electron-builder.yml` | 没有 `openclaw` extraResources | 把 runtime 资源打进安装包 |
| `scripts/after-pack.cjs` | 只处理 `playwright/chromium-bidi/bytenode` | 增加 openclaw/node_modules/plugins 复制逻辑 |
| `src/stores/chat.ts` | 只消费简化事件 | 增加 tool/thinking/tool_result 流式状态处理 |
| `src/components/chat/ChatMessageList.tsx` | 只渲染简单消息卡片 | 对齐 `ClawX` 的工具执行展示能力 |
| `src/components/chat/types.ts` | message shape 过于简单 | 增加 tool execution 相关 UI 数据结构 |
### 5.3 可后置但建议保留参考的文件
这批不是“打开网址”的最小闭环必需,但如果目标是后续继续向 `ClawX` 对齐,建议一起纳入规划:
- `ClawX/electron/utils/openclaw-proxy.ts`
- `ClawX/electron/utils/openclaw-control-ui.ts`
- `ClawX/electron/utils/openclaw-cli.ts`
- `ClawX/electron/utils/openclaw-doctor.ts`
- `ClawX/electron/gateway/reload-policy.ts`
- `ClawX/electron/gateway/process-policy.ts`
- `ClawX/electron/gateway/restart-governor.ts`
- `ClawX/src/pages/Chat/message-utils.ts`
- `ClawX/src/pages/Chat/ChatMessage.tsx`
## 6. 推荐迁移顺序
### Phase 1先打通最小运行闭环
目标:让 `zn-ai` 的聊天可以真正进入 OpenClaw runtime。
建议优先完成:
1. `package.json` 引入 `openclaw`,补 `bundle-openclaw.mjs`
2. `electron-builder.yml``scripts/after-pack.cjs` 补 runtime 打包。
3. 基于 `electron/utils/paths.ts` 实现真实 `process-launcher + process-owner`
4. 增加 `config-sync.ts + openclaw-auth.ts`,确保 browser 配置被写入 `openclaw.json`
完成标准:
- 开发态和打包态都能找到 `openclaw` 入口。
- `GatewayManager` 能拉起真实 Gateway 子进程。
- `~/.openclaw/openclaw.json` 中出现有效的 `browser.enabled` 配置。
### Phase 2替换聊天执行面
目标:让对话不再直接 `provider.chat(...)`,而是走真实 Gateway。
建议改造:
1. `electron/gateway/manager.ts`
2. `electron/gateway/handlers/chat.ts`
3. `electron/main.ts`
完成标准:
- “打开http://www.baidu.com” 时,请求进入真实 Gateway而不是本地 provider adapter。
- 聊天不再依赖 `provider.chat(...)` 直接生成最终文本。
### Phase 3补齐 tool 事件与前端可视化
目标:不仅能执行,还能在 UI 看见执行过程。
建议改造:
1. `src/stores/chat.ts`
2. `src/components/chat/types.ts`
3. `src/components/chat/ChatMessageList.tsx`
4. 参考 `ClawX/src/pages/Chat/message-utils.ts``ChatMessage.tsx`
完成标准:
- UI 能显示 `thinking / tool_use / tool_result`
- 浏览器执行失败时,前端能展示明确错误,而不是只有空白或文本兜底。
### Phase 4补诊断与运维能力
目标:减少“本地能跑、打包后失效”。
建议纳入:
1. `openclaw doctor`
2. Control UI URL
3. restart / health / ready / diagnostics
4. proxy 同步与 reload policy
## 7. sub-agent 数量估算
### 7.1 推荐编制
- 分析 sub-agent`1`
- 迁移开发 sub-agent`4`
- 集成验收 sub-agent`1`
- 推荐总数:`6`
### 7.2 峰值编制
- 如果希望把 `Phase 4` 的 diagnostics / doctor / control UI 也并行推进,可以临时再拆出 `1` 个运维诊断 sub-agent。
- 峰值总数:`7`
### 7.3 最小可行编制
- 主控 Codex 兼任分析与最终验收
- 保留 `3` 个开发 sub-agent + `1` 个集成角色
- 最小总数:`4`
### 7.4 为什么推荐 6 个
- 这次迁移至少横跨 `Runtime Packaging``Gateway Process & Config Sync``Chat Execution``Renderer Tool UI` 四条主要开发线。
- 这四条线的写集可以基本拆开,适合并行推进。
- 如果开发角色少于 `4`很容易出现“runtime 已经能拉起,但 chat path 还没切完”或者“后端已经有 tool 事件,但前端完全看不见”的串行阻塞。
## 8. sub-agent 分工与推进安排
### 8.1 推荐分工
| 角色 | 数量 | 负责范围 | 文件所有权 |
| --- | --- | --- | --- |
| A1浏览器自动化契约分析 | 1 | 持续对照 `ClawX`,冻结最小闭环契约、补验收 checklist、识别遗漏能力 | 只读分析、文档 |
| M1Runtime Packaging / Paths | 1 | 引入 `openclaw`、补 bundling、after-pack、resources 布局、运行时路径管理 | `package.json` `electron-builder.yml` `scripts/bundle-openclaw.mjs` `scripts/after-pack.cjs` `electron/utils/paths.ts` |
| M2Gateway Process / Config Sync | 1 | 实现真实进程拉起、ready 检测、WebSocket 通信、启动前同步 `openclaw.json` 浏览器配置 | `electron/gateway/process-launcher.ts` `electron/gateway/ws-client.ts` `electron/gateway/config-sync.ts` `electron/gateway/openclaw-process-owner.ts` `electron/utils/openclaw-auth.ts` |
| M3Chat Execution / IPC 集成 | 1 | 把 `chat.send` 从本地 `provider.chat(...)` 切到真实 Gateway补主进程生命周期与状态接口 | `electron/gateway/manager.ts` `electron/gateway/handlers/chat.ts` `electron/gateway/types.ts` `electron/main.ts` `electron/api/routes/gateway.ts` |
| M4Renderer Tool Events / UI | 1 | 接 tool/thinking/tool_result 事件,补消息结构、流式状态与工具执行可视化 | `src/stores/chat.ts` `src/components/chat/types.ts` `src/components/chat/ChatMessageList.tsx` `src/pages/Home/index.tsx` |
| I1联调验收 / 回归收口 | 1 | 维护 smoke checklist、验证开发态/打包态、补文档与测试基线 | 测试、文档、回归记录 |
### 8.2 可选扩编角色
如果要把运维诊断一起提前做,可以额外拆出:
| 角色 | 数量 | 负责范围 | 文件所有权 |
| --- | --- | --- | --- |
| D1Diagnostics / Control UI / Doctor | 1 | 补 OpenClaw 诊断入口、Control UI URL、health diagnostics 展示 | `electron/utils/openclaw-control-ui.ts` `electron/utils/openclaw-cli.ts` `electron/utils/openclaw-doctor.ts` `electron/api/routes/*` 设置/诊断相关前端 |
这个角色建议只在 `M3` 把基础 gateway status 契约稳定后再启动,避免和 `gateway/manager.ts` 产生写冲突。
### 8.3 建议并行波次
| 波次 | 并行角色 | 目标 |
| --- | --- | --- |
| Wave 1 | A1 + M1 | 冻结最小闭环契约,先把 `openclaw` 资源打包和路径层打通 |
| Wave 2 | M2 + M3 | 一边实现真实 Gateway 进程与 config sync一边切换聊天执行面到 Gateway |
| Wave 3 | M4 + I1 | 对接 tool 事件与 UI 展示,同时开始做 smoke 与回归清单 |
| Wave 4 | D1 + 主控 Codex | 可选补 diagnostics / doctor / control UI并做最终跨层收口 |
### 8.4 开工顺序建议
1. 先开 `M1`
- 这是最靠前的阻塞项,因为没有 runtime bundling 和路径层,后面的真实 Gateway 无法稳定拉起。
2. 紧接着开 `M2`
- 它负责把 `openclaw` 真正跑起来,并把 `browser.enabled` 等关键配置写入 `openclaw.json`
3. `M3``M2` 并行
- `M3` 可以先把 `manager/chat/main` 的调用面改成“面向真实 Gateway”的接口再等待 `M2` 落地真实进程。
4. `M4``M3` 暴露稳定事件后接入
- 避免前端先写死一套后端并不会发出的事件结构。
5. `I1``Wave 2` 就开始
- 不要等所有人写完再验,因为开发态和打包态的差异很可能会在中途暴露。
### 8.5 文件冲突规避
- `M1` 不要改 `electron/gateway/manager.ts`
- `M2` 不要改 `src/*`
- `M3` 尽量只拥有 `manager/chat/main/routes`,不要接管 `process-launcher/config-sync`
- `M4` 不要改 `electron/*`
- `I1` 不直接改生产实现,除非主控明确分配
这样拆分后,主要写冲突只会集中在接口边界,而不会集中在同一个文件。
## 9. 最小验收清单
当下面这些都满足时,才算“浏览器自动化已迁成功”:
-`zn-ai` 中发送“打开http://www.baidu.com”时真实浏览器会打开对应页面。
- 聊天链路里能看到 `tool_use` 或等价工具执行痕迹,而不是只有纯文本回复。
- `GatewayManager` 状态不再只是 `mode: 'in-process'`
- 打包后的应用也能执行同样操作,不仅是开发环境可用。
- provider/account 切换后,浏览器能力不需要手动改 `openclaw.json` 才能生效。
## 10. 风险与注意点
- 不建议只尝试“把 Playwright 接到某个单独 service”来修这件事。这样也许能做出一个临时浏览器工具但会绕开 `OpenClaw` 的 tool protocol、会话、history、tool_result、diagnostics后续维护成本更高。
- `zn-ai` 已有的 `openclaw-process-owner.ts``paths.ts` 可以继续复用,不需要完全推翻。
- 如果短期目标只是先实现“打开网址”,可以先不迁全部插件/Control UI`process-launcher + config-sync + browser.enabled + real gateway rpc` 这四块不能省。
## 11. 结论
`zn-ai` 现在不能像 `ClawX` 一样准确打开浏览器,核心原因不是缺某一个浏览器脚本,而是聊天主链路还没有接到真正的 `OpenClaw runtime`
最关键的迁移入口是四块:
1. 引入并打包 `openclaw runtime`
2. 用真实 Gateway 子进程替换当前 in-process chat execution
3. 启动前同步 `openclaw.json` 的 browser 配置
4. 前端补齐 tool execution 的事件消费和展示
按这个顺序推进,推荐以 `6` 个 sub-agent 为常态编制;如果把 diagnostics / doctor 也一起并行推进,峰值可以短时扩到 `7` 个。这样后续浏览器、文件、搜索等工具能力都会比“单点硬接 Playwright”更稳。