# L2 — 核心模块与接口契约层

**文档版本**: 2.1<br>
**适用项目**: sgClaw（ZeroClaw 重构版）<br>
**编制日期**: 2026-03-29

**读者**: 架构工程师、实现工程师、联调工程师

---

## 1. 模块地图

当前仓库中的有效模块结构如下：

```
src/
├── main.rs
├── lib.rs
├── agent/
├── compat/
├── config/
├── llm/
├── pipe/
└── security/
```

模块边界按职责划分为五层：

| 层级 | 模块 | 责任 |
|---|---|---|
| 传输层 | `pipe` | 定义消息、握手、序列号、收发与命令等待 |
| 安全层 | `security`、`resources/rules.json` | 域名、动作与 pipe 命令边界控制 |
| 运行时入口层 | `lib.rs`、`agent` | 接收任务、选择执行路径、回传日志与结果 |
| 适配层 | `compat`、`config` | 把 sgClaw 宿主环境映射到 zeroclaw 运行时；当前仍带有过渡性限制 |
| 核心能力层 | `third_party/zeroclaw` | prompt、skills、memory、tool loop、provider 抽象 |

本轮冻结后还需要一组跨仓统一术语：

- `host`
  指 SuperRPA 浏览器宿主，只拥有安全边界、进程托管和展示装配权。
- `launch config`
  指由 `host` 读取的启动描述文件。
- `runtime config`
  指由 sgClaw 读取的运行时策略文件。
- `frontend bundle`
  指由 `host` 装载的前端展示资源。
- `planner-first`
  指 sgClaw / zeroclaw 先产生计划、前端先展示计划、随后再执行的运行时行为。

---

## 2. 核心模块职责

### 2.1 `src/lib.rs`

[`src/lib.rs`](/home/zyl/projects/sgClaw/claw/src/lib.rs) 是运行时总装入口，负责：

- 创建 `StdioTransport`。
- 调用 `perform_handshake`。
- 加载默认规则文件 `resources/rules.json`。
- 构造 `BrowserPipeTool`。
- 进入长循环，接收浏览器消息并交给 `agent::handle_browser_message`。

这里没有业务 UI、任务队列或调度中心逻辑，只有最小可运行闭环。

### 2.2 `src/agent/mod.rs`

[`src/agent/mod.rs`](/home/zyl/projects/sgClaw/claw/src/agent/mod.rs) 当前决定执行路径：

- 收到 `BrowserMessage::SubmitTask` 时优先尝试读取 `SgClawSettings`。
- 环境配置存在，则走 `compat::runtime::execute_task_with_sgclaw_settings`。
- 环境配置不存在，则直接返回“未配置大语言模型”，而不是再把生产 submit 流量导回旧 planner。

这就是当前系统的“路由器”。但文档上应把它理解为过渡性 runtime selector，而不是最终产品架构中心。长期看，`planner-first`、provider 选择与 backend 选择都应由 `runtime config` 显式驱动。

### 2.3 `src/agent/runtime.rs`

该文件现在应被视为 `legacy/dev-only` 模块，只保留仓库内的轻量 LLM/tool 调用逻辑用于局部验证，核心特点：

- 工具名固定为 `browser_action`。
- schema 只允许 `click/type/navigate/getText`。
- 每次工具调用前后发送 `log_entry`。
- 结果失败时直接返回 `PipeError::Protocol`。
- 不参与当前生产浏览器 submit 路由。

### 2.4 `src/compat/runtime.rs`

[`src/compat/runtime.rs`](/home/zyl/projects/sgClaw/claw/src/compat/runtime.rs) 是当前 ZeroClaw 接入的关键模块：

- 负责构造 ZeroClaw config。
- 负责创建 provider。
- 负责把 `BrowserPipeTool` 包装成 ZeroClaw Tool。
- 负责消费 ZeroClaw `TurnEvent` 并桥接为 `log_entry`。

重要事实：

- 当前 compat 层只向 ZeroClaw 注册一个工具。
- `allowed_tools` 被收敛到 `browser_action`。
- 这意味着当前代码还没有把 sgClaw 做成 zeroclaw-first runtime。
- 这是一种实现限制，不应被文档提升为产品原则。

### 2.7 host / launch config / runtime config 契约

跨仓接口收口后，`host` 与 sgClaw 的最小契约应为：

| 对象 | 读取方 | 责任 | 失败时兜底 |
|---|---|---|---|
| `launch config` | `host` | 解析 `binary`、`args`、`env`、`working_dir`、`runtime_config_path`、`frontend_bundle_dir` | 回退到浏览器内置默认启动策略 |
| `runtime config` | sgClaw | 解析 provider、model、planner mode、backend、skills policy | 回退到 sgClaw 默认运行时配置 |
| `frontend bundle` | `host` | 提供浮窗/面板展示资源 | 回退到浏览器内置 WebUI 资源 |

这里的关键点是：`host` 只负责校验和装配，不负责决定 planner、model routing 或 business behavior。

### 2.8 launch config 文件路径与回退规则

设计冻结口径如下：

- profile-local `launch config` 路径：`<profile>/superrpa/sgclaw_launch_config.json`
- profile-local `runtime config` 路径：`<profile>/superrpa/sgclaw_config.json`
- profile-local hooks / rules 仍沿用：
  - `<profile>/superrpa/hooks.json`
  - `<profile>/superrpa/rules.json`

`launch config` 的回退规则必须保持稳定：

1. 优先读取 `<profile>/superrpa/sgclaw_launch_config.json`
2. 缺失或解析失败时，回退到当前浏览器内置默认启动参数
3. `runtime_config_path` 缺失时，回退到 `<profile>/superrpa/sgclaw_config.json`
4. `frontend_bundle_dir` 缺失、无效或校验失败时，回退到 bundled frontend resources

### 2.9 frontend bundle 与 planner-first 契约

`frontend bundle` 只能消费这些由 `host` 转发的运行时状态：

- 当前状态与日志
- planner 输出
- 会话消息
- 最终执行结果

`frontend bundle` 不能直接拥有：

- provider 切换决策权
- planner 开关控制权
- executor 旁路能力

因此 `planner-first` 的契约应是：

1. sgClaw / zeroclaw 产生计划
2. `frontend bundle` 先展示计划
3. 经运行时确认后再执行

这是一条 runtime contract，不是一条前端内部约定。

### 2.5 `src/pipe/browser_tool.rs`

该模块承担真实浏览器命令发送职责，也是当前系统中最重要的特权工具面桥接层：

- 为每个命令分配 `seq`。
- 计算 HMAC。
- 发送 `AgentMessage::Command`。
- 阻塞等待对应 `BrowserMessage::Response`。
- 在超时、响应错配、校验失败时返回错误。

它是 Rust 侧最重要的协议执行点。架构上应把它理解为“privileged browser surface adapter”，而不是“整个 runtime 本体”。

### 2.6 `src/security/mac_policy.rs`

安全策略只认规则文件与 pipe contract，不认模型意图。
规则来源为 [`resources/rules.json`](/home/zyl/projects/sgClaw/claw/resources/rules.json)，当前默认约束是：

- 允许域名：`oa.example.com`、`erp.example.com`、`hr.example.com` 及 demo 域名。
- 允许动作：`click`、`type`、`navigate`、`getText`。
- 显式阻断：`eval`、`executeJsInPage`。

---

## 3. 协议契约

### 3.1 消息类型

[`src/pipe/protocol.rs`](/home/zyl/projects/sgClaw/claw/src/pipe/protocol.rs) 定义了三类浏览器到 Rust 的消息：

```rust
BrowserMessage::Init
BrowserMessage::SubmitTask
BrowserMessage::Response
```

以及四类 Rust 到浏览器的消息：

```rust
AgentMessage::InitAck
AgentMessage::LogEntry
AgentMessage::TaskComplete
AgentMessage::Command
```

### 3.2 `Init` / `InitAck`

握手字段：

- `version`
- `hmac_seed`
- `capabilities`

Rust 返回：

- `version`
- `agent_id`
- `supported_actions`

注意：`supported_actions` 是协议枚举能力，不等于当前策略白名单。

### 3.3 `Command`

命令消息结构：

```json
{
  "seq": 1,
  "type": "command",
  "action": "click",
  "params": { "selector": "#submit" },
  "security": {
    "expected_domain": "erp.example.com",
    "hmac": "<hex>"
  }
}
```

契约重点：

- `seq` 必须单调递增。
- `action` 必须是协议枚举之一。
- `expected_domain` 必须参与安全校验。
- `hmac` 必须由当前会话密钥计算。

### 3.4 `Response`

浏览器回包结构：

```json
{
  "seq": 1,
  "type": "response",
  "success": true,
  "data": {},
  "aom_snapshot": [],
  "timing": {
    "queue_ms": 0,
    "exec_ms": 12
  }
}
```

Rust 侧依赖此消息完成工具调用闭环。  
`seq` 不匹配、超时或缺失都应视为协议错误。

### 3.5 与浏览器对接标准的关系

[`docs/浏览器对接标准.md`](/home/zyl/projects/sgClaw/claw/docs/浏览器对接标准.md) 是联调规范。  
L2 是产品内核视角的契约说明。两者关系如下：

- L2 负责解释“为什么有这些字段、这些模块如何依赖它们”。
- 对接标准负责约束“浏览器宿主必须如何实现 wire contract”。

---

## 4. 动作契约

### 4.1 协议枚举

协议层已经定义了以下动作枚举：

- `click`
- `type`
- `navigate`
- `getText`
- `getHtml`
- `waitForSelector`
- `pageScreenshot`
- `select`
- `scrollTo`
- `getAomSnapshot`
- `storageSet`
- `storageGet`
- `zombieSpawn`
- `zombieKill`

### 4.2 当前生效动作

当前文档、规则和工具 schema 必须以“生效动作”为准，而不是“预留枚举”为准。  
生效动作只有 4 个：

- `click`
- `type`
- `navigate`
- `getText`

约束来源有三处，三者必须一致：

1. `resources/rules.json`
2. `src/agent/runtime.rs` 的 tool definition
3. `src/compat/browser_tool_adapter.rs` 的 `parameters_schema` 与 `parse_action`

这三者表达的是“当前特权浏览器工具面”的开放范围，而不是 sgClaw 整体 runtime 的长期能力上限。

---

## 5. `browser_action` 工具契约

### 5.1 工具名

固定为：

```text
browser_action
```

### 5.2 参数 schema

当前有效参数：

- `action`
- `expected_domain`
- `selector`
- `text`
- `url`
- `clear_first`

其中：

- `click` 通常需要 `selector`
- `type` 通常需要 `selector` 与 `text`
- `navigate` 通常需要 `url`
- `getText` 通常需要 `selector`

### 5.3 失败语义

工具执行失败分两类：

1. 参数级失败  
说明：缺少必填字段、动作不支持、参数类型错误。

2. 协议级失败  
说明：MAC 不通过、浏览器回包 `success=false`、响应超时、序列号异常。

这两类失败最终都会转为任务失败并通过 `task_complete` 回传。

---

## 6. 接口演进原则

L2 之后的扩展应遵守以下原则：

- 新增动作先进入协议枚举，再补规则白名单，再开放给 tool schema。
- 不允许只改文档或只改提示词就宣称动作可用。
- 兼容层与 fallback 路径必须对外保持同一工具名和同一主契约。
- 浏览器宿主联调时以 wire contract 为最高优先级，不把模型行为假设写进协议。
