397 lines
9.5 KiB
Markdown
397 lines
9.5 KiB
Markdown
# sgClaw 浏览器团队开发启动文档
|
||
|
||
**适用对象**:Chromium / C++ 浏览器开发团队(P2)
|
||
**目标**:浏览器团队拿到本文档后即可独立启动开发,并在一个周期后与 sgClaw 项目团队完成 Pipe 联调。
|
||
**协议版本**:`1.0`
|
||
**冻结日期**:`2026-03-24`
|
||
|
||
---
|
||
|
||
## 1. 开发目标
|
||
|
||
浏览器团队本周期只负责浏览器侧 Pipe 接入,不负责 LLM、Skill、Memory、Agent 推理。
|
||
|
||
本周期结束时,浏览器侧必须具备以下能力:
|
||
|
||
1. 能从浏览器主进程启动 `sgclaw` Rust 子进程。
|
||
2. 能通过 `stdin/stdout` 与 `sgclaw` 进行双向 `JSON Line` 通信。
|
||
3. 能解析 sgClaw 发来的 `command` 消息,并路由到现有 `CommandRouter`。
|
||
4. 能执行最小可联调动作:`click`、`type`、`navigate`、`getText`。
|
||
5. 能返回结构化 `response` 消息。
|
||
6. 能在浏览器侧执行域名和 action 白名单校验。
|
||
|
||
本周期不做:
|
||
|
||
1. 不改现有 `CommandRouter` 的核心接口。
|
||
2. 不新造一套浏览器操作 API。
|
||
3. 不改为 HTTP、WebSocket、Named Pipe。
|
||
4. 不实现 Rust 侧逻辑。
|
||
|
||
---
|
||
|
||
## 2. 架构边界
|
||
|
||
浏览器侧是父进程,`sgclaw` 是子进程。浏览器侧新增三个模块:
|
||
|
||
1. `SgClawProcessHost`
|
||
负责子进程启动、停止、状态管理、异常退出处理。
|
||
2. `PipeListener`
|
||
负责异步读取 `sgclaw stdout`,按行解析 JSON 并分发。
|
||
3. `MacWhitelistCheck`
|
||
负责浏览器侧二次安全校验,防止越权 action 落到 `CommandRouter`。
|
||
|
||
浏览器侧数据流固定如下:
|
||
|
||
`Side Panel / UI -> SgClawProcessHost -> STDIO Pipe -> sgclaw`
|
||
|
||
`sgclaw -> STDIO Pipe -> PipeListener -> MacWhitelistCheck -> CommandRouter -> response`
|
||
|
||
---
|
||
|
||
## 3. 浏览器团队负责的交付物
|
||
|
||
本周期交付以下文件或等价模块:
|
||
|
||
1. `sgclaw_process_host.h`
|
||
2. `sgclaw_process_host.cc`
|
||
3. `pipe_listener.h`
|
||
4. `pipe_listener.cc`
|
||
5. `mac_whitelist_check.h`
|
||
6. `mac_whitelist_check.cc`
|
||
7. `rules.json`
|
||
8. `sgclaw_unittests` 中对应单元测试
|
||
|
||
建议目录:
|
||
|
||
```text
|
||
chrome/browser/superrpa/sgclaw/
|
||
sgclaw_process_host.h
|
||
sgclaw_process_host.cc
|
||
pipe_listener.h
|
||
pipe_listener.cc
|
||
mac_whitelist_check.h
|
||
mac_whitelist_check.cc
|
||
test/
|
||
sgclaw_process_host_unittest.cc
|
||
pipe_listener_unittest.cc
|
||
mac_whitelist_check_unittest.cc
|
||
resources/
|
||
rules.json
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 冻结接口
|
||
|
||
### 4.1 传输协议
|
||
|
||
1. 传输层固定为 `STDIO Pipe`。
|
||
2. 编码固定为 `UTF-8`。
|
||
3. 消息边界固定为 `JSON Line`,每行一条完整 JSON。
|
||
4. 单条消息最大 `1 MB`。
|
||
5. `stdout` 只允许输出协议消息,日志必须走 `stderr`。
|
||
|
||
### 4.2 握手协议
|
||
|
||
浏览器发送:
|
||
|
||
```json
|
||
{"type":"init","version":"1.0","hmac_seed":"0123456789abcdef","capabilities":["browser_action"]}
|
||
```
|
||
|
||
sgClaw 返回:
|
||
|
||
```json
|
||
{"type":"init_ack","version":"1.0","agent_id":"uuid-v4","supported_actions":["click","type","navigate","getText","getHtml","waitForSelector","pageScreenshot","select","scrollTo","getAomSnapshot","storageSet","storageGet","zombieSpawn","zombieKill"]}
|
||
```
|
||
|
||
约束:
|
||
|
||
1. 浏览器必须在子进程启动后 `5s` 内发送 `init`。
|
||
2. `5s` 内收不到 `init_ack`,判定启动失败。
|
||
3. `version` 不一致,必须立即终止会话。
|
||
|
||
### 4.3 command 消息格式
|
||
|
||
```json
|
||
{
|
||
"type":"command",
|
||
"seq":12,
|
||
"action":"click",
|
||
"params":{"selector":"#submit","wait_after":300},
|
||
"security":{
|
||
"expected_domain":"oa.example.com",
|
||
"hmac":"<hex>"
|
||
}
|
||
}
|
||
```
|
||
|
||
字段要求:
|
||
|
||
1. `seq` 为正整数,必须唯一。
|
||
2. `action` 必须在白名单内。
|
||
3. `params` 必须是对象。
|
||
4. `security.expected_domain` 和 `security.hmac` 必须存在。
|
||
|
||
### 4.4 response 消息格式
|
||
|
||
成功:
|
||
|
||
```json
|
||
{
|
||
"type":"response",
|
||
"seq":12,
|
||
"success":true,
|
||
"data":{"text":"提交成功"},
|
||
"aom_snapshot":[],
|
||
"timing":{"queue_ms":2,"exec_ms":38}
|
||
}
|
||
```
|
||
|
||
失败:
|
||
|
||
```json
|
||
{
|
||
"type":"response",
|
||
"seq":12,
|
||
"success":false,
|
||
"data":{
|
||
"error":{
|
||
"code":"CMD_SELECTOR_NOT_FOUND",
|
||
"message":"selector '#submit' not found"
|
||
}
|
||
},
|
||
"aom_snapshot":[],
|
||
"timing":{"queue_ms":1,"exec_ms":10}
|
||
}
|
||
```
|
||
|
||
约束:
|
||
|
||
1. 一个 `command.seq` 只能对应一个 `response.seq`。
|
||
2. 失败必须返回结构化错误,不允许只返回字符串。
|
||
3. `timing` 必须始终带上。
|
||
|
||
---
|
||
|
||
## 5. 本周期最小 Action 集
|
||
|
||
联调周期只强制四个动作:
|
||
|
||
1. `click`
|
||
2. `type`
|
||
3. `navigate`
|
||
4. `getText`
|
||
|
||
动作语义:
|
||
|
||
1. `click`
|
||
调用现有点击能力,支持可选 `wait_after`。
|
||
2. `type`
|
||
在目标输入框输入文本,支持 `clear_first`。
|
||
3. `navigate`
|
||
导航到目标 URL。
|
||
4. `getText`
|
||
获取目标节点文本。
|
||
|
||
其余 action 可保留接口但不进入本周期强制验收。
|
||
|
||
---
|
||
|
||
## 6. 浏览器侧实现要求
|
||
|
||
### 6.1 SgClawProcessHost
|
||
|
||
必须实现:
|
||
|
||
1. 单例,避免重复创建多个 `sgclaw` 子进程。
|
||
2. `Start()` 创建匿名管道并启动子进程。
|
||
3. `Stop()` 正常关闭并在超时后强制结束。
|
||
4. `OnProcessCrash()` 记录错误并更新状态。
|
||
5. 状态机至少包含 `Idle -> Starting -> Running -> Stopped / Crashed`。
|
||
|
||
建议接口:
|
||
|
||
```cpp
|
||
class SgClawProcessHost {
|
||
public:
|
||
bool Start();
|
||
void Stop();
|
||
bool IsRunning() const;
|
||
bool SendLine(std::string json_line);
|
||
};
|
||
```
|
||
|
||
### 6.2 PipeListener
|
||
|
||
必须实现:
|
||
|
||
1. 持续读取 `stdout`。
|
||
2. 以换行符切分 `JSON Line`。
|
||
3. 拒绝空行、非 JSON、超过 1MB 的消息。
|
||
4. 能按 `seq` 追踪一次请求的完整生命周期。
|
||
5. 管道断开时通知 `SgClawProcessHost`。
|
||
|
||
### 6.3 CommandRouter 对接
|
||
|
||
必须实现:
|
||
|
||
1. `command.action` 到现有浏览器命令的映射表。
|
||
2. 尽量复用现有 `CommandRouter`。
|
||
3. 不允许在 Pipe 层直接写新的页面控制逻辑。
|
||
4. response 必须从实际执行结果构造,不允许伪造成功。
|
||
|
||
建议映射:
|
||
|
||
1. `click -> CommandRouter.click`
|
||
2. `type -> CommandRouter.type`
|
||
3. `navigate -> CommandRouter.navigate`
|
||
4. `getText -> CommandRouter.getText`
|
||
|
||
### 6.4 MacWhitelistCheck
|
||
|
||
必须实现:
|
||
|
||
1. action 白名单校验。
|
||
2. expected_domain 与当前页面域名比对。
|
||
3. `rules.json` 加载失败时默认拒绝。
|
||
4. 拒绝时返回统一错误码。
|
||
|
||
建议错误码:
|
||
|
||
1. `MAC_ACTION_NOT_ALLOWED`
|
||
2. `MAC_DOMAIN_NOT_ALLOWED`
|
||
3. `MAC_RULES_LOAD_FAILED`
|
||
4. `PIPE_INVALID_JSON`
|
||
5. `PIPE_MESSAGE_TOO_LARGE`
|
||
|
||
---
|
||
|
||
## 7. 浏览器团队开发顺序
|
||
|
||
### Day 1-2
|
||
|
||
1. 完成 `SgClawProcessHost` 骨架。
|
||
2. 用 dummy 子进程验证启动和退出。
|
||
3. 打通 `stdin/stdout` 读写通道。
|
||
|
||
验收:
|
||
|
||
1. 能启动 `echo` 或测试进程。
|
||
2. 能发送一行字符串并收到回写。
|
||
|
||
### Day 3-4
|
||
|
||
1. 完成 `PipeListener`。
|
||
2. 完成 `init -> init_ack` 握手。
|
||
3. 建立 `command` / `response` 解析结构。
|
||
|
||
验收:
|
||
|
||
1. 能与 Rust 侧互发 JSON Line。
|
||
2. 能处理 `seq` 对应关系。
|
||
|
||
### Day 5-6
|
||
|
||
1. 接入 `CommandRouter`。
|
||
2. 完成 4 个最小 action。
|
||
3. 完成 `MacWhitelistCheck`。
|
||
|
||
验收:
|
||
|
||
1. Rust 发起 `click/type/navigate/getText` 时浏览器真实执行。
|
||
2. 非白名单域名被拒绝。
|
||
|
||
### Day 7
|
||
|
||
1. 完成浏览器侧单元测试。
|
||
2. 提供联调分支和运行说明。
|
||
3. 预留半天与项目团队联调。
|
||
|
||
---
|
||
|
||
## 8. 浏览器团队自测清单
|
||
|
||
- [ ] `Start()` 成功启动真实 `sgclaw` 二进制。
|
||
- [ ] `Start()` 重复调用不会启动多个实例。
|
||
- [ ] `Stop()` 能正常关闭进程。
|
||
- [ ] `init -> init_ack` 成功。
|
||
- [ ] 超过 1MB 的 JSON 消息会被拒绝。
|
||
- [ ] 非 JSON 行会被拒绝。
|
||
- [ ] `click/type/navigate/getText` 能成功返回。
|
||
- [ ] 域名不匹配时返回 `MAC_DOMAIN_NOT_ALLOWED`。
|
||
- [ ] `rules.json` 缺失时默认拒绝。
|
||
- [ ] 日志中能按 `seq` 查到请求和响应。
|
||
|
||
---
|
||
|
||
## 9. 联调输入输出样例
|
||
|
||
### 9.1 手动握手
|
||
|
||
浏览器发:
|
||
|
||
```json
|
||
{"type":"init","version":"1.0","hmac_seed":"00112233445566778899aabbccddeeff","capabilities":["browser_action"]}
|
||
```
|
||
|
||
期待 Rust 回:
|
||
|
||
```json
|
||
{"type":"init_ack","version":"1.0","agent_id":"00000000-0000-0000-0000-000000000000","supported_actions":["click","type","navigate","getText","getHtml","waitForSelector","pageScreenshot","select","scrollTo","getAomSnapshot","storageSet","storageGet","zombieSpawn","zombieKill"]}
|
||
```
|
||
|
||
### 9.2 最小 click 联调
|
||
|
||
Rust 发:
|
||
|
||
```json
|
||
{"type":"command","seq":1,"action":"click","params":{"selector":"#login-btn"},"security":{"expected_domain":"oa.example.com","hmac":"<hex>"}}
|
||
```
|
||
|
||
浏览器回:
|
||
|
||
```json
|
||
{"type":"response","seq":1,"success":true,"data":{},"aom_snapshot":[],"timing":{"queue_ms":1,"exec_ms":35}}
|
||
```
|
||
|
||
---
|
||
|
||
## 10. 联调日必须提供的东西
|
||
|
||
浏览器团队在联调前必须准备:
|
||
|
||
1. 可运行的浏览器分支。
|
||
2. `sgclaw` 子进程启动入口。
|
||
3. `rules.json` 默认测试配置。
|
||
4. 最小测试页面,至少包含一个输入框、一个按钮、一个文本节点。
|
||
5. 一份 action 到 `CommandRouter` 的映射表。
|
||
6. 一份错误码表。
|
||
|
||
---
|
||
|
||
## 11. 周期结束验收标准
|
||
|
||
以下全部满足,浏览器团队本周期完成:
|
||
|
||
1. 能在浏览器中稳定启动和停止 `sgclaw`。
|
||
2. `init -> init_ack` 成功率 100%。
|
||
3. `click/type/navigate/getText` 联调通过。
|
||
4. 所有失败场景均返回结构化错误。
|
||
5. 域名和 action 白名单生效。
|
||
6. 与项目团队在同一测试页完成一次端到端演示。
|
||
|
||
---
|
||
|
||
## 12. 依赖与协作方式
|
||
|
||
浏览器团队只依赖以下冻结输入:
|
||
|
||
1. Pipe 协议版本:`1.0`
|
||
2. 消息结构:`init / init_ack / command / response`
|
||
3. 最小 action:`click/type/navigate/getText`
|
||
4. 安全字段:`expected_domain`、`hmac`
|
||
|
||
除以上四项外,本周期内其他细节不应阻塞浏览器侧开发。
|
||
|