Major changes: - Add HandList.tsx component for left sidebar - Add HandTaskPanel.tsx for middle content area - Restructure Sidebar tabs: 分身/HANDS/Workflow - Remove Hands tab from RightPanel - Localize all UI text to Chinese - Archive legacy OpenClaw documentation - Add Hands integration lessons document - Update feature checklist with new components UI improvements: - Left sidebar now shows Hands list with status icons - Middle area shows selected Hand's tasks and results - Consistent styling with Tailwind CSS - Chinese status labels and buttons Documentation: - Create docs/archive/openclaw-legacy/ for old docs - Add docs/knowledge-base/hands-integration-lessons.md - Update docs/knowledge-base/feature-checklist.md - Update docs/knowledge-base/README.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
344 lines
12 KiB
Markdown
344 lines
12 KiB
Markdown
# ZClaw 项目深度分析与改进计划
|
||
|
||
## 一、现状分析
|
||
|
||
### 1.1 核心发现
|
||
|
||
基于 `docs/openclaw-deep-dive.md` 的目标与实际代码的对比:
|
||
|
||
| 模块 | 目标状态 | 实际状态 | 差距程度 |
|
||
|------|----------|----------|----------|
|
||
| **Gateway 连接** | 设备认证 + Challenge 签名 | ✅ 完整实现 | 无差距 |
|
||
| **分身系统** | 映射到 OpenClaw `agents.list` | ⚠️ 独立存储在 `zclaw-data.json` | **严重** |
|
||
| **设置页** | OpenClaw Runtime 配置面板 | ⚠️ 大部分是前端本地状态 | **严重** |
|
||
| **右侧面板** | 真实 Agent 身份与状态 | ⚠️ 混合真实数据与硬编码值 | **中等** |
|
||
|
||
### 1.2 关键差距详解
|
||
|
||
#### 差距 1:分身与 Agent 断层(最严重)
|
||
|
||
```
|
||
当前架构:
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ ZClaw 分身系统 (zclaw-data.json) │
|
||
│ clone_1: { name: "程序员", workspaceDir: "...", ... } │
|
||
│ clone_2: { name: "设计师", workspaceDir: "...", ... } │
|
||
└────────────────────────┬────────────────────────────────────┘
|
||
│ ❌ 无同步
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ OpenClaw agents.list (openclaw.json) │
|
||
│ 只有: [{ id: "main", groupChat: {...} }] │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**后果**:
|
||
- 所有分身实际共用同一个 `main` Agent
|
||
- 聊天时不传递 `agentId`,OpenClaw 不知道当前是哪个分身
|
||
- Bootstrap 文件(IDENTITY.md, SOUL.md 等)生成了但未被运行时使用
|
||
|
||
#### 差距 2:设置页是"假状态"
|
||
|
||
| 设置页 | 当前实现 | 应该实现 |
|
||
|--------|----------|----------|
|
||
| 模型选择 | 存在 `chatStore.currentModel`(前端状态) | 调用 `config.patch` 修改 OpenClaw 配置 |
|
||
| MCP 服务 | 存 `quickConfig`,部分同步到 Gateway | 管理 `plugins.load.paths` |
|
||
| 技能目录 | 存 `quickConfig` | 管理 `skills.load.extraDirs` |
|
||
| IM 频道 | 存 `quickConfig`,只显示状态 | 管理 `channels.*` 配置 |
|
||
| 工作区 | 存 `quickConfig` | 管理 `agents.defaults.workspace` |
|
||
| 隐私 | 存 `quickConfig` | 管理 telemetry/优化计划 |
|
||
|
||
**缺失的 RPC 方法**:
|
||
- `config.get` - 读取 OpenClaw 配置
|
||
- `config.patch` - 修改配置
|
||
- `config.apply` - 热更新配置
|
||
|
||
#### 差距 3:右侧面板数据不真实
|
||
|
||
```typescript
|
||
// 硬编码的默认值(RightPanel.tsx)
|
||
const credits = 2268; // 完全假数据
|
||
const defaultUserName = '用户7141'; // 假用户名
|
||
```
|
||
|
||
---
|
||
|
||
## 二、根因分析
|
||
|
||
### 2.1 架构层面的偏差
|
||
|
||
**文档期望**:
|
||
> ZClaw 应该是 OpenClaw Runtime 的控制界面
|
||
|
||
**实际实现**:
|
||
> ZClaw 是一个有自己数据模型的前端应用,与 OpenClaw 是松耦合
|
||
|
||
### 2.2 数据模型的分裂
|
||
|
||
```
|
||
OpenClaw 数据模型:
|
||
openclaw.json → agents.list → Agent workspace → Bootstrap files
|
||
|
||
ZClaw 数据模型:
|
||
zclaw-data.json → clones[] → (独立的) workspace 路径
|
||
```
|
||
|
||
两套数据模型没有桥接,导致:
|
||
1. 分身不能路由到正确的 Agent
|
||
2. 设置不能影响 OpenClaw 行为
|
||
3. Bootstrap 文件与运行时脱节
|
||
|
||
---
|
||
|
||
## 三、头脑风暴:改进方案
|
||
|
||
### 3.1 方案 A:完全对齐 OpenClaw(推荐)
|
||
|
||
**核心思路**:让 ZClaw 分身直接映射到 OpenClaw Agent
|
||
|
||
```
|
||
改进后架构:
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ ZClaw 分身 = OpenClaw Agent │
|
||
│ │
|
||
│ clone_1 ↔ agents.list[0] (id: "programmer") │
|
||
│ clone_2 ↔ agents.list[1] (id: "designer") │
|
||
│ │
|
||
│ 分身 CRUD → 同步修改 agents.list │
|
||
│ 聊天时 → 传递 agentId 到 Gateway │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**优点**:
|
||
- 符合 `openclaw-deep-dive.md` 的设计哲学
|
||
- 分身真正有独立人格、记忆、工具权限
|
||
- 设置页可以直接操作 OpenClaw 配置
|
||
|
||
**缺点**:
|
||
- 改动较大,需要修改多个模块
|
||
- 需要处理数据迁移
|
||
|
||
### 3.2 方案 B:保持独立,增强桥接
|
||
|
||
**核心思路**:保持 `zclaw-data.json`,但增加同步逻辑
|
||
|
||
```
|
||
改进后架构:
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ ZClaw 分身系统 (主) │
|
||
│ zclaw-data.json → clones[] │
|
||
│ │ │
|
||
│ ▼ (单向同步) │
|
||
│ openclaw.json → agents.list (从分身生成) │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**优点**:
|
||
- 改动较小
|
||
- 保持现有分身管理逻辑
|
||
|
||
**缺点**:
|
||
- 数据冗余,需要维护同步
|
||
- 不符合 OpenClaw 的设计哲学
|
||
|
||
### 3.3 方案 C:混合模式
|
||
|
||
**核心思路**:
|
||
- 简单分身:共用 `main` Agent,通过 Bootstrap 文件区分
|
||
- 高级分身:映射到独立 OpenClaw Agent
|
||
|
||
---
|
||
|
||
## 四、推荐实施路线(方案 A)
|
||
|
||
### P0:让分身真正工作(最小可行)
|
||
|
||
**目标**:创建分身时同步到 OpenClaw `agents.list`,聊天时传递 `agentId`
|
||
|
||
**关键修改**:
|
||
|
||
1. **`plugins/zclaw-ui/index.ts`**
|
||
- `createClone` 时调用 OpenClaw API 添加到 `agents.list`
|
||
- `deleteClone` 时从 `agents.list` 移除
|
||
- 新增 `zclaw.agents.sync` 方法
|
||
|
||
2. **`desktop/src/lib/gateway-client.ts`**
|
||
- `chat()` 方法增加 `agentId` 参数
|
||
```typescript
|
||
async chat(message: string, opts?: { agentId?: string; sessionKey?: string }): Promise<...>
|
||
```
|
||
|
||
3. **`desktop/src/store/chatStore.ts`**
|
||
- `sendMessage` 时传递 `currentAgent.id` 作为 `agentId`
|
||
|
||
4. **新增 Gateway RPC**
|
||
- `zclaw.config.get` - 读取 OpenClaw 配置
|
||
- `zclaw.config.patch` - 修改配置
|
||
|
||
**验收标准**:
|
||
- [ ] 创建分身后,`openclaw.json` 的 `agents.list` 包含新 Agent
|
||
- [ ] 切换分身后,聊天请求携带正确的 `agentId`
|
||
- [ ] 每个分身有独立的对话上下文
|
||
|
||
### P1:设置页 Runtime 化
|
||
|
||
**目标**:设置修改直接影响 OpenClaw Runtime
|
||
|
||
**关键修改**:
|
||
|
||
1. **`desktop/src/lib/gateway-client.ts`**
|
||
- 实现 `configGet()`、`configPatch()`、`configApply()` 方法
|
||
|
||
2. **各设置页改造**
|
||
- **模型与 API**:调用 `config.patch` 修改 `agents.defaults.model`
|
||
- **MCP 服务**:管理 `plugins.load.paths`
|
||
- **技能目录**:管理 `skills.load.extraDirs`
|
||
- **工作区**:管理 `agents.defaults.workspace`
|
||
- **隐私**:管理 telemetry 相关配置
|
||
|
||
3. **UI 反馈**
|
||
- 显示配置保存状态
|
||
- 配置变更后显示"需要重启"提示(如需要)
|
||
|
||
**验收标准**:
|
||
- [ ] 模型选择后,`openclaw.json` 的 `agents.defaults.model` 更新
|
||
- [ ] 添加技能目录后,`skills.load.extraDirs` 更新
|
||
- [ ] Gateway 重启后配置生效
|
||
|
||
### P2:完整的 Agent 管理系统
|
||
|
||
**目标**:分身管理 = Agent 全生命周期管理
|
||
|
||
**功能扩展**:
|
||
1. 分身绑定渠道(飞书账号、微信群等)
|
||
2. 分身 Heartbeat 配置
|
||
3. 分身工具权限/沙箱配置
|
||
4. 分身间路由规则
|
||
|
||
**UI 改进**:
|
||
- 右侧面板显示真实 Agent 状态(非硬编码)
|
||
- 分身详情页增加完整配置选项
|
||
|
||
### P3:产品化封装
|
||
|
||
**目标**:开箱即用的桌面体验
|
||
|
||
**功能**:
|
||
1. Tauri sidecar 管理 Gateway 进程
|
||
2. 首次安装配置向导
|
||
3. 错误诊断与自动修复
|
||
4. 一键更新
|
||
|
||
---
|
||
|
||
## 五、关键文件清单
|
||
|
||
| 文件 | 修改内容 |
|
||
|------|----------|
|
||
| `plugins/zclaw-ui/index.ts` | 分身 CRUD 同步到 agents.list |
|
||
| `desktop/src/lib/gateway-client.ts` | 增加 agentId 参数、config RPC |
|
||
| `desktop/src/store/chatStore.ts` | sendMessage 传递 agentId |
|
||
| `desktop/src/store/gatewayStore.ts` | 管理 Agent 配置状态 |
|
||
| `desktop/src/components/CloneManager.tsx` | 显示同步状态 |
|
||
| `desktop/src/components/RightPanel.tsx` | 显示真实 Agent 数据 |
|
||
| `desktop/src/components/Settings/*.tsx` | 改造为 Runtime 配置面板 |
|
||
| `config/openclaw.default.json` | 更新默认 Agent 模板 |
|
||
|
||
---
|
||
|
||
## 六、风险与缓解
|
||
|
||
| 风险 | 缓解措施 |
|
||
|------|----------|
|
||
| 数据迁移复杂 | 提供迁移脚本,保留 `zclaw-data.json` 作为备份 |
|
||
| OpenClaw 版本兼容 | 检测 OpenClaw 版本,低版本降级到兼容模式 |
|
||
| 破坏现有功能 | 灰度发布,支持回滚 |
|
||
| 性能下降 | 懒加载 Agent 配置,缓存 RPC 结果 |
|
||
|
||
---
|
||
|
||
## 七、确认的方案
|
||
|
||
**选择:方案 A - 完全对齐 OpenClaw**
|
||
|
||
理由:
|
||
1. 符合 `openclaw-deep-dive.md` 的设计哲学
|
||
2. 分身真正有独立人格、记忆、工具权限
|
||
3. 设置页可以直接操作 OpenClaw 配置
|
||
4. 长期维护成本最低
|
||
|
||
---
|
||
|
||
## 八、下一步行动(P0 详细任务)
|
||
|
||
### Task 1: 修改 `zclaw-ui` 插件 - 分身同步到 agents.list
|
||
|
||
**文件**: `plugins/zclaw-ui/index.ts`
|
||
|
||
**修改点**:
|
||
1. `createClone` 方法增加:
|
||
- 调用 OpenClaw 内部 API 将分身添加到 `agents.list`
|
||
- 设置 `agentId` 字段关联分身与 Agent
|
||
2. `deleteClone` 方法增加:
|
||
- 从 `agents.list` 移除对应 Agent
|
||
3. `updateClone` 方法增加:
|
||
- 同步更新 Agent 配置
|
||
4. 新增 `zclaw.agents.sync` 方法:
|
||
- 读取当前 `agents.list`
|
||
- 与 `zclaw-data.json` 比对
|
||
- 修复不一致
|
||
|
||
### Task 2: 修改 GatewayClient - 支持 agentId
|
||
|
||
**文件**: `desktop/src/lib/gateway-client.ts`
|
||
|
||
**修改点**:
|
||
1. `chat()` 方法签名改为:
|
||
```typescript
|
||
async chat(message: string, opts?: {
|
||
agentId?: string; // 新增
|
||
sessionKey?: string;
|
||
model?: string;
|
||
}): Promise<{ runId: string; acceptedAt: string }>
|
||
```
|
||
2. `request('agent', ...)` 时传递 `agentId`
|
||
|
||
### Task 3: 修改 chatStore - 传递 agentId
|
||
|
||
**文件**: `desktop/src/store/chatStore.ts`
|
||
|
||
**修改点**:
|
||
1. `sendMessage` 方法调用 `client.chat()` 时传递 `currentAgent.id`
|
||
|
||
### Task 4: 新增配置 RPC 方法
|
||
|
||
**文件**: `desktop/src/lib/gateway-client.ts` + `plugins/zclaw-ui/index.ts`
|
||
|
||
**新增方法**:
|
||
- `zclaw.config.get` - 读取 OpenClaw 配置
|
||
- `zclaw.config.patch` - 修改配置(不重启)
|
||
- `zclaw.config.apply` - 热更新配置(如需重启)
|
||
|
||
### Task 5: 数据迁移脚本
|
||
|
||
**创建**: `scripts/migrate-clones-to-agents.ts`
|
||
|
||
**功能**:
|
||
1. 读取现有 `zclaw-data.json` 中的分身
|
||
2. 为每个分身在 `agents.list` 创建对应条目
|
||
3. 更新分身的 `agentId` 字段
|
||
4. 备份原始文件
|
||
|
||
---
|
||
|
||
## 九、验收标准
|
||
|
||
### P0 完成标准
|
||
|
||
- [ ] 创建分身后,`~/.openclaw/openclaw.json` 的 `agents.list` 包含新 Agent
|
||
- [ ] 删除分身后,对应 Agent 从 `agents.list` 移除
|
||
- [ ] 切换分身后,聊天请求携带正确的 `agentId`
|
||
- [ ] 每个分身有独立的对话上下文(不串聊)
|
||
- [ ] 现有分身数据成功迁移,无数据丢失
|
||
- [ ] 单元测试覆盖新增逻辑 ≥ 80%
|