feat: complete Phase 1-3 architecture optimization

Phase 1 - Security:
- Add AES-GCM encryption for localStorage fallback
- Enforce WSS protocol for non-localhost WebSocket connections
- Add URL sanitization to prevent XSS in markdown links

Phase 2 - Domain Reorganization:
- Create Intelligence Domain with Valtio store and caching
- Add unified intelligence-client for Rust backend integration
- Migrate from legacy agent-memory, heartbeat, reflection modules

Phase 3 - Core Optimization:
- Add virtual scrolling for ChatArea with react-window
- Implement LRU cache with TTL for intelligence operations
- Add message virtualization utilities

Additional:
- Add OpenFang compatibility test suite
- Update E2E test fixtures
- Add audit logging infrastructure
- Update project documentation and plans

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-21 22:11:50 +08:00
parent 815c56326b
commit ce562e8bfc
36 changed files with 5241 additions and 201 deletions

View File

@@ -0,0 +1,366 @@
# ZCLAW 智能层统一实现方案
## 概述
本方案旨在消除前后端智能层代码重复,统一使用 Rust 后端 + TypeScript 适配器 (`intelligence-backend.ts`)。
## 现状分析
### 已有的 Rust 后端命令(通过 `intelligence-backend.ts` 封装)
| 模块 | 命令 | 状态 |
|------|------|------|
| Memory | memory_init, memory_store, memory_get, memory_search, memory_delete, memory_delete_all, memory_stats, memory_export, memory_import, memory_db_path | 完整 |
| Heartbeat | heartbeat_init, heartbeat_start, heartbeat_stop, heartbeat_tick, heartbeat_get_config, heartbeat_update_config, heartbeat_get_history | 完整 |
| Compactor | compactor_estimate_tokens, compactor_estimate_messages_tokens, compactor_check_threshold, compactor_compact | 完整 |
| Reflection | reflection_init, reflection_record_conversation, reflection_should_reflect, reflection_reflect, reflection_get_history, reflection_get_state | 完整 |
| Identity | identity_get, identity_get_file, identity_build_prompt, identity_update_user_profile, identity_append_user_profile, identity_propose_change, identity_approve_proposal, identity_reject_proposal, identity_get_pending_proposals, identity_update_file, identity_get_snapshots, identity_restore_snapshot, identity_list_agents, identity_delete_agent | 完整 |
### 需要迁移的前端 TS 实现
| 文件 | 代码行数 | 引用位置 |
|------|----------|----------|
| `agent-memory.ts` | ~487行 | chatStore, memoryGraphStore, MemoryPanel, memory-extractor, agent-swarm, skill-discovery |
| `agent-identity.ts` | ~351行 | chatStore, reflection-engine, memory-extractor, ReflectionLog |
| `reflection-engine.ts` | ~678行 | chatStore, ReflectionLog |
| `heartbeat-engine.ts` | ~347行 | HeartbeatConfig |
| `context-compactor.ts` | ~443行 | chatStore |
### 类型差异分析
前端 TS 和 Rust 后端的类型有细微差异,需要创建适配层:
```
前端 MemoryEntry.importance: number (0-10)
后端 PersistentMemory.importance: number (相同)
前端 MemoryEntry.type: MemoryType ('fact' | 'preference' | ...)
后端 PersistentMemory.memory_type: string
前端 MemoryEntry.tags: string[]
后端 PersistentMemory.tags: string (JSON 序列化)
```
---
## 实施计划
### Phase 0: 准备工作(环境检测 + 降级策略)
**目标**: 创建环境检测机制,支持 Tauri/浏览器双环境
**修改文件**:
- 新建 `desktop/src/lib/intelligence-client.ts`
**实现内容**:
```typescript
// intelligence-client.ts
import { intelligence } from './intelligence-backend';
// 检测是否在 Tauri 环境中
const isTauriEnv = typeof window !== 'undefined' && '__TAURI__' in window;
// 降级策略:非 Tauri 环境使用 localStorage 模拟
const fallbackMemory = {
store: async (entry) => { /* localStorage 模拟 */ },
search: async (options) => { /* localStorage 模拟 */ },
// ... 其他方法
};
export const intelligenceClient = {
memory: isTauriEnv ? intelligence.memory : fallbackMemory,
heartbeat: isTauriEnv ? intelligence.heartbeat : fallbackHeartbeat,
compactor: isTauriEnv ? intelligence.compactor : fallbackCompactor,
reflection: isTauriEnv ? intelligence.reflection : fallbackReflection,
identity: isTauriEnv ? intelligence.identity : fallbackIdentity,
};
```
**验证方法**:
- 在 Tauri 桌面端启动,确认 `isTauriEnv === true`
- 在浏览器中访问 Vite dev server确认降级逻辑生效
---
### Phase 1: 迁移 Memory 模块(最关键)
**优先级**: 最高(其他模块都依赖 Memory
**修改文件**:
| 文件 | 修改内容 |
|------|----------|
| `chatStore.ts` | 将 `getMemoryManager()` 替换为 `intelligenceClient.memory` |
| `memoryGraphStore.ts` | 将 `getMemoryManager()` 替换为 `intelligenceClient.memory` |
| `MemoryPanel.tsx` | 将 `getMemoryManager()` 替换为 `intelligenceClient.memory` |
| `memory-extractor.ts` | 将 `getMemoryManager()` 替换为 `intelligenceClient.memory` |
| `agent-swarm.ts` | 将 `getMemoryManager()` 替换为 `intelligenceClient.memory` |
| `skill-discovery.ts` | 将 `getMemoryManager()` 替换为 `intelligenceClient.memory` |
**详细修改示例** (chatStore.ts):
```typescript
// 修改前
import { getMemoryManager } from '../lib/agent-memory';
// 在 sendMessage 中
const memoryMgr = getMemoryManager();
const relevantMemories = await memoryMgr.search(content, {
agentId,
limit: 8,
minImportance: 3,
});
// 修改后
import { intelligenceClient } from '../lib/intelligence-client';
// 在 sendMessage 中
const relevantMemories = await intelligenceClient.memory.search({
agent_id: agentId,
query: content,
limit: 8,
min_importance: 3,
});
```
**类型适配**:
```typescript
// 创建类型转换函数
function toFrontendMemory(backend: PersistentMemory): MemoryEntry {
return {
id: backend.id,
agentId: backend.agent_id,
content: backend.content,
type: backend.memory_type as MemoryType,
importance: backend.importance,
source: backend.source as MemorySource,
tags: JSON.parse(backend.tags || '[]'),
createdAt: backend.created_at,
lastAccessedAt: backend.last_accessed_at,
accessCount: backend.access_count,
conversationId: backend.conversation_id || undefined,
};
}
function toBackendMemoryInput(frontend: Omit<MemoryEntry, 'id' | 'createdAt' | 'lastAccessedAt' | 'accessCount'>): MemoryEntryInput {
return {
agent_id: frontend.agentId,
memory_type: frontend.type,
content: frontend.content,
importance: frontend.importance,
source: frontend.source,
tags: frontend.tags,
conversation_id: frontend.conversationId,
};
}
```
**验证方法**:
1. 启动桌面端,发送消息
2. 检查记忆是否正确存储到 SQLite
3. 搜索记忆是否返回正确结果
4. MemoryPanel 组件是否正确显示记忆列表
**回滚方案**:
- 保留 `agent-memory.ts` 文件
- 通过 feature flag 切换新旧实现
---
### Phase 2: 迁移 Compactor 模块
**优先级**: 高(依赖 Memory但影响范围较小
**修改文件**:
| 文件 | 修改内容 |
|------|----------|
| `chatStore.ts` | 将 `getContextCompactor()` 替换为 `intelligenceClient.compactor` |
**详细修改**:
```typescript
// 修改前
import { getContextCompactor } from '../lib/context-compactor';
const compactor = getContextCompactor();
const check = compactor.checkThreshold(messages);
// 修改后
import { intelligenceClient } from '../lib/intelligence-client';
const check = await intelligenceClient.compactor.checkThreshold(
messages.map(m => ({ role: m.role, content: m.content }))
);
```
**验证方法**:
1. 发送大量消息触发 compaction 阈值
2. 检查是否正确压缩上下文
3. 验证压缩后消息正常显示
---
### Phase 3: 迁移 Reflection + Identity 模块
**优先级**: 中(关联紧密,需要一起迁移)
**修改文件**:
| 文件 | 修改内容 |
|------|----------|
| `chatStore.ts` | 将 `getReflectionEngine()` 替换为 `intelligenceClient.reflection` |
| `ReflectionLog.tsx` | 将 `ReflectionEngine``getAgentIdentityManager()` 替换为 intelligenceClient |
| `memory-extractor.ts` | 将 `getAgentIdentityManager()` 替换为 `intelligenceClient.identity` |
**详细修改**:
```typescript
// 修改前 (chatStore.ts)
import { getReflectionEngine } from '../lib/reflection-engine';
const reflectionEngine = getReflectionEngine();
reflectionEngine.recordConversation();
if (reflectionEngine.shouldReflect()) {
reflectionEngine.reflect(agentId);
}
// 修改后
import { intelligenceClient } from '../lib/intelligence-client';
await intelligenceClient.reflection.recordConversation();
if (await intelligenceClient.reflection.shouldReflect()) {
const memories = await intelligenceClient.memory.search({ agent_id: agentId, limit: 100 });
await intelligenceClient.reflection.reflect(agentId, memories.map(m => ({
memory_type: m.memory_type,
content: m.content,
importance: m.importance,
access_count: m.access_count,
tags: JSON.parse(m.tags || '[]'),
})));
}
```
**验证方法**:
1. 完成多轮对话后检查 reflection 是否触发
2. 检查 ReflectionLog 组件是否正确显示反思历史
3. 验证身份变更提案的审批流程
---
### Phase 4: 迁移 Heartbeat 模块
**优先级**: 低(独立模块,无依赖)
**修改文件**:
| 文件 | 修改内容 |
|------|----------|
| `HeartbeatConfig.tsx` | 将 `HeartbeatEngine` 替换为 `intelligenceClient.heartbeat` |
| `SettingsLayout.tsx` | 如有引用,同样替换 |
**详细修改**:
```typescript
// 修改前
import { HeartbeatEngine, DEFAULT_HEARTBEAT_CONFIG } from '../lib/heartbeat-engine';
const engine = new HeartbeatEngine(agentId, config);
engine.start();
// 修改后
import { intelligenceClient } from '../lib/intelligence-client';
import type { HeartbeatConfig } from '../lib/intelligence-backend';
await intelligenceClient.heartbeat.init(agentId, config);
await intelligenceClient.heartbeat.start(agentId);
```
**验证方法**:
1. 在 HeartbeatConfig 面板中启用心跳
2. 等待心跳触发,检查是否生成 alert
3. 验证配置更新是否正确持久化
---
### Phase 5: 清理遗留代码
**优先级**: 最低(在所有迁移验证完成后)
**删除文件**:
- `desktop/src/lib/agent-memory.ts`
- `desktop/src/lib/agent-identity.ts`
- `desktop/src/lib/reflection-engine.ts`
- `desktop/src/lib/heartbeat-engine.ts`
- `desktop/src/lib/context-compactor.ts`
- `desktop/src/lib/memory-index.ts` (agent-memory 的依赖)
**更新文档**:
- 更新 `CLAUDE.md` 中的架构说明
- 更新相关组件的注释
---
## 风险与缓解措施
| 风险 | 缓解措施 |
|------|----------|
| Tauri invoke 失败 | 实现完整的降级策略fallback 到 localStorage |
| 类型不匹配 | 创建类型转换层,隔离前后端类型差异 |
| 性能差异 | Rust 后端应该更快,但需要测试 SQLite 查询性能 |
| 数据迁移 | 提供 localStorage -> SQLite 迁移工具 |
| 回滚困难 | 使用 feature flag可快速切换回旧实现 |
---
## 测试检查清单
### 每个阶段必须验证
- [ ] TypeScript 编译通过 (`pnpm tsc --noEmit`)
- [ ] 相关单元测试通过 (`pnpm vitest run`)
- [ ] 桌面端启动正常
- [ ] 聊天功能正常
- [ ] 记忆存储/搜索正常
- [ ] 无控制台错误
### Phase 1 额外验证
- [ ] MemoryPanel 正确显示记忆列表
- [ ] 记忆图谱正确渲染
- [ ] skill-discovery 推荐功能正常
### Phase 3 额外验证
- [ ] ReflectionLog 正确显示反思历史
- [ ] 身份变更提案审批流程正常
- [ ] USER.md 自动更新正常
---
## 时间估算
| 阶段 | 预计时间 | 累计 |
|------|----------|------|
| Phase 0 | 2h | 2h |
| Phase 1 | 4h | 6h |
| Phase 2 | 1h | 7h |
| Phase 3 | 3h | 10h |
| Phase 4 | 1h | 11h |
| Phase 5 | 1h | 12h |
| 测试与修复 | 3h | 15h |
**总计**: 约 2 个工作日
---
## 执行顺序建议
1. **先完成 Phase 0** - 这是所有后续工作的基础
2. **然后 Phase 1** - Memory 是核心依赖
3. **接着 Phase 2** - Compactor 依赖 Memory
4. **然后 Phase 3** - Reflection + Identity 关联紧密
5. **然后 Phase 4** - Heartbeat 独立,可最后处理
6. **最后 Phase 5** - 确认一切正常后再删除旧代码
每个阶段完成后都应该进行完整的功能验证,确保没有引入 bug。

View File

@@ -0,0 +1,261 @@
# ZCLAW 智能层统一实现计划
## Context
ZCLAW 项目存在前后端智能层代码重复问题。TypeScript 前端实现了记忆、反思、心跳、压缩等智能层功能,同时 Rust 后端也完整实现了相同功能。这导致:
1. 维护成本加倍(两份代码需同步更新)
2. 功能受限(前端 localStorage 在应用关闭后无法运行)
3. 数据不持久localStorage 有 5MB 限制)
**解决方案**:删除前端 TS 智能层代码,统一使用 Rust 后端 + TypeScript 适配器 (`intelligence-backend.ts`)。
---
## 关键文件
### 已有的 Rust 后端(保留)
- `desktop/src-tauri/src/intelligence/heartbeat.rs` - 心跳引擎
- `desktop/src-tauri/src/intelligence/compactor.rs` - 上下文压缩
- `desktop/src-tauri/src/intelligence/reflection.rs` - 自我反思
- `desktop/src-tauri/src/intelligence/identity.rs` - 身份管理
- `desktop/src-tauri/src/memory/persistent.rs` - 记忆持久化
- `desktop/src/lib/intelligence-backend.ts` - **TypeScript 适配器(已完整实现)**
### 需要删除的 TS 实现
- `desktop/src/lib/agent-memory.ts` (~487行)
- `desktop/src/lib/agent-identity.ts` (~351行)
- `desktop/src/lib/reflection-engine.ts` (~678行)
- `desktop/src/lib/heartbeat-engine.ts` (~347行)
- `desktop/src/lib/context-compactor.ts` (~443行)
- `desktop/src/lib/memory-index.ts` (~150行)
### 需要修改的消费者文件
| 文件 | 使用的旧模块 |
|------|--------------|
| `desktop/src/store/chatStore.ts` | memory, identity, compactor, reflection |
| `desktop/src/store/memoryGraphStore.ts` | memory |
| `desktop/src/components/MemoryPanel.tsx` | memory |
| `desktop/src/components/ReflectionLog.tsx` | reflection, identity |
| `desktop/src/components/HeartbeatConfig.tsx` | heartbeat |
| `desktop/src/lib/memory-extractor.ts` | memory, identity |
| `desktop/src/lib/agent-swarm.ts` | memory |
| `desktop/src/lib/skill-discovery.ts` | memory |
---
## Implementation Plan
### Phase 0: 创建统一客户端(约 2h
**目标**: 创建环境检测机制,支持 Tauri/浏览器双环境
**新建文件**: `desktop/src/lib/intelligence-client.ts`
**实现内容**:
```typescript
import { intelligence } from './intelligence-backend';
// 检测是否在 Tauri 环境中
const isTauriEnv = typeof window !== 'undefined' && '__TAURI__' in window;
// 降级策略:非 Tauri 环境使用 localStorage 模拟
const fallbackMemory = {
store: async (entry) => { /* localStorage 模拟 */ },
search: async (options) => { /* localStorage 模拟 */ },
// ... 其他方法
};
export const intelligenceClient = {
memory: isTauriEnv ? intelligence.memory : fallbackMemory,
heartbeat: isTauriEnv ? intelligence.heartbeat : fallbackHeartbeat,
compactor: isTauriEnv ? intelligence.compactor : fallbackCompactor,
reflection: isTauriEnv ? intelligence.reflection : fallbackReflection,
identity: isTauriEnv ? intelligence.identity : fallbackIdentity,
};
```
**验证**:
- `pnpm tsc --noEmit` 编译通过
- Tauri 环境检测正确
---
### Phase 1: 迁移 Memory 模块(约 4h
**优先级**: 最高(其他模块都依赖 Memory
**修改文件**:
1. **chatStore.ts**
```typescript
// 修改前
import { getMemoryManager } from '../lib/agent-memory';
const memoryMgr = getMemoryManager();
const relevantMemories = await memoryMgr.search(content, { agentId, limit: 8 });
// 修改后
import { intelligenceClient } from '../lib/intelligence-client';
const relevantMemories = await intelligenceClient.memory.search({
agent_id: agentId,
query: content,
limit: 8,
});
```
2. **memoryGraphStore.ts** - 替换 `getMemoryManager()`
3. **MemoryPanel.tsx** - 替换 `getMemoryManager()`
4. **memory-extractor.ts** - 替换 `getMemoryManager()`
5. **agent-swarm.ts** - 替换 `getMemoryManager()`
6. **skill-discovery.ts** - 替换 `getMemoryManager()`
**类型适配层** (添加到 intelligence-client.ts):
```typescript
function toFrontendMemory(backend: PersistentMemory): MemoryEntry {
return {
id: backend.id,
agentId: backend.agent_id,
type: backend.memory_type as MemoryType,
tags: JSON.parse(backend.tags || '[]'),
// ...
};
}
```
**验证**:
- `pnpm vitest run` 测试通过
- 桌面端启动,发送消息,检查记忆存储
- MemoryPanel 正确显示记忆列表
---
### Phase 2: 迁移 Compactor 模块(约 1h
**修改文件**: `chatStore.ts`
```typescript
// 修改前
import { getContextCompactor } from '../lib/context-compactor';
const compactor = getContextCompactor();
const check = compactor.checkThreshold(messages);
// 修改后
import { intelligenceClient } from '../lib/intelligence-client';
const check = await intelligenceClient.compactor.checkThreshold(
messages.map(m => ({ role: m.role, content: m.content }))
);
```
**验证**:
- 发送大量消息触发 compaction
- 检查压缩后消息正常显示
---
### Phase 3: 迁移 Reflection + Identity 模块(约 3h
**修改文件**:
1. **chatStore.ts**
```typescript
// 修改前
import { getReflectionEngine } from '../lib/reflection-engine';
const reflectionEngine = getReflectionEngine();
reflectionEngine.recordConversation();
// 修改后
import { intelligenceClient } from '../lib/intelligence-client';
await intelligenceClient.reflection.recordConversation();
```
2. **ReflectionLog.tsx** - 替换 `ReflectionEngine``getAgentIdentityManager()`
3. **memory-extractor.ts** - 替换 `getAgentIdentityManager()`
**验证**:
- 完成多轮对话后检查 reflection 触发
- ReflectionLog 组件正确显示历史
- 身份变更提案审批流程正常
---
### Phase 4: 迁移 Heartbeat 模块(约 1h
**修改文件**: `HeartbeatConfig.tsx`
```typescript
// 修改前
import { HeartbeatEngine } from '../lib/heartbeat-engine';
const engine = new HeartbeatEngine(agentId, config);
engine.start();
// 修改后
import { intelligenceClient } from '../lib/intelligence-client';
await intelligenceClient.heartbeat.init(agentId, config);
await intelligenceClient.heartbeat.start(agentId);
```
**验证**:
- HeartbeatConfig 面板启用心跳
- 等待心跳触发,检查 alert 生成
---
### Phase 5: 清理遗留代码(约 1h
**删除文件**:
- `desktop/src/lib/agent-memory.ts`
- `desktop/src/lib/agent-identity.ts`
- `desktop/src/lib/reflection-engine.ts`
- `desktop/src/lib/heartbeat-engine.ts`
- `desktop/src/lib/context-compactor.ts`
- `desktop/src/lib/memory-index.ts`
**更新文档**:
- 更新 `CLAUDE.md` 架构说明
---
## Verification
每个阶段完成后执行:
```bash
# 1. TypeScript 编译检查
pnpm tsc --noEmit
# 2. 单元测试
pnpm vitest run
# 3. 启动桌面端
pnpm tauri:dev
# 4. 功能验证
# - 发送消息,检查记忆存储
# - 触发长对话,检查压缩
# - 检查心跳和反思功能
```
---
## Risk & Mitigation
| 风险 | 缓解措施 |
|------|----------|
| Tauri invoke 失败 | fallback 到 localStorage |
| 类型不匹配 | 类型转换层隔离差异 |
| 数据迁移 | 提供 localStorage → SQLite 迁移工具 |
| 回滚困难 | 使用 feature flag 快速切换 |
---
## Estimated Time
| 阶段 | 时间 |
|------|------|
| Phase 0: 创建客户端 | 2h |
| Phase 1: Memory 迁移 | 4h |
| Phase 2: Compactor 迁移 | 1h |
| Phase 3: Reflection+Identity | 3h |
| Phase 4: Heartbeat 迁移 | 1h |
| Phase 5: 清理代码 | 1h |
| 测试与修复 | 3h |
| **总计** | **约 15h2个工作日** |

View File

@@ -0,0 +1,276 @@
# ZCLAW 端到端可用性验证计划
## 背景
ZCLAW 项目架构设计出色68个Skills、7个Hands、智能层lib但**端到端可用性未经验证**。317个单元测试通过不代表产品可用需要真实跑通核心闭环。
**目标**:验证从用户启动应用 → 连接后端 → 对话 → 触发自动化 → 记忆持久化的完整流程。
---
## 验证阶段概览
| 阶段 | 内容 | 预计时间 |
|------|------|----------|
| 1. 前置准备 | 环境检查、配置验证 | 15分钟 |
| 2. 基础验证 | Gateway连接、基础对话 | 25分钟 |
| 3. 功能验证 | Hands触发、记忆持久化 | 30分钟 |
| 4. 集成验证 | 飞书集成、端到端工作流 | 25分钟 |
| 5. 自动化验证 | E2E测试套件 | 60分钟 |
---
## Phase 1: 前置准备
### 1.1 环境检查
```powershell
# 检查依赖
pnpm --version # >= 8.x
pnpm tauri --version # 2.x
# 检查 OpenFang Runtime
dir desktop\src-tauri\resources\openfang-runtime\
# 检查 Playwright
cd desktop && pnpm playwright --version
```
### 1.2 配置验证
检查文件:
- `config/config.toml` - 端口4200、CORS配置
- `config/chinese-providers.toml` - API Keys可选
```powershell
# 验证配置
type config\config.toml | findstr /C:"port" /C:"cors_origins"
```
### 1.3 依赖安装
```powershell
cd desktop
pnpm install
pnpm playwright install chromium
```
**成功标准**:所有依赖安装完成,无错误
---
## Phase 2: 基础验证
### 2.1 Gateway 连接测试
**手动步骤**
1. 启动应用:`.\start-all.ps1 -Dev`
2. 等待 Tauri 窗口打开
3. 观察连接状态指示器(绿色=已连接)
**自动验证**
```powershell
cd desktop
pnpm playwright test --project=chromium --grep "GW-CONN"
```
**验证点**
| 测试ID | 描述 | 成功标准 |
|--------|------|----------|
| GW-CONN-01 | 健康检查 | `{ status: 'ok' }` |
| GW-CONN-02 | 连接状态 | Store显示`connected` |
| GW-CONN-03 | 模型列表 | 返回模型数组 |
| GW-CONN-04 | Agent列表 | 返回Agent数组 |
**连接参数**gateway-client.ts
- 心跳间隔30秒
- 最大丢失心跳3次
- 重连尝试最多10次指数退避
### 2.2 基础对话测试
**手动步骤**
1. 在输入框输入消息
2. 点击发送按钮
3. 观察流式响应
**自动验证**
```powershell
pnpm playwright test --project=chromium --grep "CHAT-MSG"
```
**验证点**
| 测试ID | 描述 | 成功标准 |
|--------|------|----------|
| CHAT-MSG-01 | 发送接收消息 | 用户+AI消息可见 |
| CHAT-MSG-02 | Store状态更新 | 消息计数增加 |
| CHAT-MSG-03 | 流式响应指示 | isStreaming正确切换 |
**成功标准**消息2秒内显示流式指示器正常无错误
---
## Phase 3: 功能验证
### 3.1 Hands 触发测试
**自动验证**
```powershell
pnpm playwright test --project=chromium --grep "HAND-TRIG"
```
**验证点**
| 测试ID | 描述 | 成功标准 |
|--------|------|----------|
| HAND-TRIG-01 | Hands列表加载 | 返回Hands数组 |
| HAND-TRIG-02 | 激活Hand | 返回runId |
| HAND-TRIG-03 | 审批流程 | 审批/拒绝正常 |
| HAND-TRIG-04 | 取消执行 | 状态变为cancelled |
**可用的Hands**
- Browser浏览器自动化
- Collector数据收集
- Researcher深度研究
- Predictor预测分析
### 3.2 记忆持久化测试
**自动验证**
```powershell
pnpm playwright test --project=chromium --grep "MEM-"
```
**验证点**
| 测试ID | 描述 | 成功标准 |
|--------|------|----------|
| MEM-PERSIST-01 | localStorage保存 | 数据持久化 |
| MEM-PERSIST-02 | 页面重载恢复 | 数据恢复 |
| MEM-PERSIST-03 | 会话切换 | 切换正常 |
| MEM-PERSIST-04 | 删除会话 | 正确移除 |
---
## Phase 4: 集成验证
### 4.1 飞书集成(可选)
**前置条件**:飞书应用已配置,`[channels.feishu].enabled = true`
**验证点**
- OAuth授权流程
- 消息接收
- Agent回复
### 4.2 端到端工作流
**测试场景**
1. 启动应用 → 2. 验证连接 → 3. 发送消息 → 4. 导航到Hands → 5. 触发Hand → 6. 验证执行 → 7. 返回聊天 → 8. 验证状态持久
**自动验证**
```powershell
pnpm playwright test --project=chromium --grep "INT-"
```
---
## Phase 5: 自动化验证
### 5.1 运行完整E2E测试
```powershell
cd desktop
# 运行所有测试
pnpm playwright test
# 生成HTML报告
pnpm playwright test --reporter=html
pnpm playwright show-report test-results/html-report
```
**测试文件**
| 文件 | 测试数 | 重点 |
|------|--------|------|
| core-features.spec.ts | 20+ | Gateway、聊天、Hands |
| data-flow.spec.ts | 25+ | 数据流验证 |
| store-state.spec.ts | 30+ | Store状态 |
| edge-cases.spec.ts | 25+ | 边界情况 |
| memory.spec.ts | 25+ | 记忆持久化 |
**成功标准**所有测试通过无flaky测试
---
## 关键文件
| 文件 | 用途 |
|------|------|
| [gateway-client.ts](desktop/src/lib/gateway-client.ts) | WebSocket/REST客户端1155行 |
| [connectionStore.ts](desktop/src/store/connectionStore.ts) | 连接状态管理 |
| [chatStore.ts](desktop/src/store/chatStore.ts) | 聊天状态和流式响应 |
| [handStore.ts](desktop/src/store/handStore.ts) | Hands触发和审批 |
| [core-features.spec.ts](desktop/tests/e2e/specs/core-features.spec.ts) | 核心E2E测试 |
| [start-all.ps1](start-all.ps1) | 启动脚本 |
| [config.toml](config/config.toml) | 主配置文件 |
---
## 故障排除
| 问题 | 可能原因 | 解决方案 |
|------|----------|----------|
| 连接超时 | OpenFang未运行 | 运行 `.\start-all.ps1 -Dev` |
| 健康检查失败 | 端口4200被占用 | 检查防火墙,终止占用进程 |
| 聊天不工作 | 无可用Agent | 检查 `/api/agents` 端点 |
| Hand不触发 | 依赖未满足 | 检查 `requirements_met` 字段 |
| 记忆不持久 | localStorage禁用 | 检查浏览器设置 |
---
## 验证清单总结
### Phase 1: 前置准备
- [ ] Node.js/pnpm 已安装
- [ ] Rust/Tauri CLI 已安装
- [ ] OpenFang runtime 存在
- [ ] Playwright 浏览器已安装
- [ ] 配置文件已验证
### Phase 2: 基础验证
- [ ] 健康检查返回 ok
- [ ] 连接状态正确转换
- [ ] 模型列表加载
- [ ] Agent列表加载
- [ ] 聊天消息发送接收
- [ ] 流式响应工作
### Phase 3: 功能验证
- [ ] Hands列表显示
- [ ] Hand激活工作
- [ ] 审批流程工作
- [ ] 取消执行工作
- [ ] 记忆跨重载持久
- [ ] 会话切换工作
### Phase 4: 集成验证
- [ ] (可选)飞书集成工作
- [ ] 完整工作流完成
- [ ] 状态跨导航持久
### Phase 5: 自动化验证
- [ ] 所有Playwright测试通过
- [ ] HTML报告生成
- [ ] 无flaky测试
---
## 预计总时间
| 阶段 | 时长 |
|------|------|
| Phase 1 | 15分钟 |
| Phase 2 | 25分钟 |
| Phase 3 | 30分钟 |
| Phase 4 | 25分钟 |
| Phase 5 | 60分钟 |
| **总计** | **2.5-3小时** |

View File

@@ -0,0 +1,444 @@
# ZCLAW 项目全面架构优化方案
> 头脑风暴日期: 2026-03-21
> 目标: 全面优化 | 时间: 3个月+ | 策略: 激进架构优先
---
## 一、当前架构分析
### 1.1 现有问题总结
| 类别 | 问题 | 严重性 | 影响 |
|------|------|--------|------|
| **安全** | 浏览器 eval() XSS 风险 | 🔴 HIGH | 用户数据泄露 |
| **安全** | localStorage 凭据回退 | 🟠 MEDIUM | 密钥暴露 |
| **性能** | 流式更新重建整个数组 | 🟠 MEDIUM | 渲染卡顿 |
| **性能** | 无界消息数组 | 🟠 MEDIUM | 内存泄漏 |
| **架构** | 50+ lib 模块缺乏统一抽象 | 🟡 LOW | 维护困难 |
| **测试** | 核心模块无测试覆盖 | 🟠 MEDIUM | 回归风险 |
### 1.2 技术债务分布
```
desktop/src/
├── lib/ [50+ 模块] ← 需要模块化重组
├── store/ [15 stores] ← 需要统一模式
├── components/ [60+ 组件] ← 需要分层
└── types/ [分散] ← 需要集中管理
```
---
## 二、三种优化方案
### 方案 A: 渐进式模块化重构 (推荐)
**核心理念**: 保持现有架构,逐步提取抽象层
```
Phase 1 (4周): 安全加固 + 测试基础
├─ 修复 XSS/凭据存储问题
├─ 添加 chatStore/gateway-client 测试
└─ 建立测试覆盖率门禁
Phase 2 (4周): 性能优化
├─ 引入 Immer 优化状态更新
├─ 实现虚拟滚动 (react-window)
└─ 消息分页 + 惰性加载
Phase 3 (6周): 架构分层
├─ 提取 Core Layer (协议无关)
├─ 提取 Adapter Layer (Tauri/Web)
└─ 统一错误处理和日志
Phase 4 (4周): Intelligence 增强
├─ Rust 层功能完善
├─ TypeScript 适配器优化
└─ 记忆/心跳/反思/身份 全链路
```
**优点**:
- 风险可控,每阶段可独立验证
- 不影响现有功能交付
- 团队可并行工作
**缺点**:
- 改动分散,可能产生中间态
- 总体周期较长
---
### 方案 B: 激进架构重写
**核心理念**: 重新设计核心架构,一次性解决所有问题
```
Step 1: 定义新架构规范
├─ 分层架构: UI → Application → Domain → Infrastructure
├─ 依赖注入容器
└─ 统一事件总线
Step 2: 核心层重写
├─ 新 State Manager (基于 Immer + Middleware)
├─ 新 Client Layer (统一协议抽象)
└─ 新 Error System (分类 + 恢复)
Step 3: 迁移现有功能
├─ Store 逐个迁移
├─ 组件适配新 API
└─ 测试同步跟进
Step 4: 清理旧代码
```
**优点**:
- 一次性解决所有架构问题
- 代码质量飞跃式提升
- 未来扩展性最佳
**缺点**:
- 高风险,可能引入新 bug
- 开发周期不可控
- 需要冻结功能开发
---
### 方案 C: 领域驱动分层
**核心理念**: 按业务领域重组,每个领域独立优化
```
Domain 1: Chat (对话系统)
├─ ChatStore 重构 (Immer + 分页)
├─ 流式响应优化
└─ 虚拟滚动 + 记忆增强
Domain 2: Hands (自动化)
├─ HandStore 状态机模式
├─ 审批流程增强
└─ 执行引擎隔离
Domain 3: Intelligence (智能层)
├─ Rust 后端完善
├─ 心跳/压缩/反思/身份
└─ 缓存策略优化
Domain 4: Skills (技能系统)
├─ 技能发现/搜索优化
├─ 执行沙箱隔离
└─ 依赖管理
Cross-Cutting:
├─ 安全层 (统一加解密)
├─ 测试层 (领域测试套件)
└─ 监控层 (性能/错误追踪)
```
**优点**:
- 领域边界清晰
- 可独立演进
- 易于并行开发
**缺点**:
- 跨领域逻辑复杂
- 共享代码可能重复
- 需要重新规划目录结构
---
## 三、方案对比
| 维度 | 方案 A (渐进) | 方案 B (激进) | 方案 C (领域) |
|------|---------------|---------------|---------------|
| **风险** | 🟢 低 | 🔴 高 | 🟡 中 |
| **速度** | 🟡 中 | 🔴 慢 | 🟢 快 |
| **效果** | 🟡 中等提升 | 🟢 飞跃提升 | 🟢 显著提升 |
| **并行度** | 🟡 部分并行 | 🔴 串行 | 🟢 完全并行 |
| **推荐度** | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ |
---
## 四、确认方案: A + C 混合 (用户已确认)
> **关键决策**:
> - 状态管理: **VZustand** (Proxy 细粒度响应)
> - 安全策略: **Web Worker 隔离执行** (最安全)
结合渐进式和领域驱动的优点:
```
┌─────────────────────────────────────────────────────────────┐
│ Phase 1: 安全 + 测试 (2周) │
│ • 实现 Web Worker 隔离执行引擎 │
│ • 修复凭据存储问题 (加密回退) │
│ • 建立测试框架和覆盖率门禁 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Phase 2: 领域重组 (4周) │
│ • 按领域重组目录结构 │
│ • 迁移到 VZustand (Proxy 响应式) │
│ • 提取领域接口和抽象 │
│ • 统一错误处理 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Phase 3: 核心优化 (并行) (6周) │
│ Track A: Chat Track B: Hands Track C: Intelligence │
│ • VZustand 重写 • 状态机模式 • Rust 增强 │
│ • 虚拟滚动 • Web Worker • 缓存策略 │
│ • 流式优化 • 审批流增强 • 性能调优 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Phase 4: 集成 + 清理 (2周) │
│ • 跨领域集成测试 │
│ • 清理旧代码 │
│ • 文档更新 │
└─────────────────────────────────────────────────────────────┘
```
**总周期**: 约 14 周 (3.5 个月)
---
## 五、各领域详细优化点
### 5.1 智能对话系统 (Chat Domain)
| 优化项 | 当前问题 | 解决方案 | 预期收益 |
|--------|----------|----------|----------|
| 状态更新 | 每次重建数组 | **VZustand** (Proxy 细粒度) | 70% 性能提升 |
| 长对话 | 无界数组 | 分页 + 惰性加载 | 内存降低 80% |
| 虚拟滚动 | 全量渲染 | react-window | 首屏快 3x |
| 流式响应 | 回调嵌套 | AsyncGenerator | 代码简洁 |
**VZustand 架构**:
```typescript
// 基于 Proxy 的细粒度响应
const useChatStore = create(
proxy({
messages: [],
addMessage: (msg) => { messages.push(msg); } // 直接 mutate
})
);
// 组件只订阅使用的字段
function MessageList() {
const messages = useChatStore(s => s.messages); // 仅 messages 变化时重渲染
}
```
**关键改动文件**:
- `desktop/src/store/chatStore.ts` → 重写为 VZustand
- `desktop/src/components/ChatArea/MessageList.tsx`
- `desktop/src/lib/gateway-client.ts`
### 5.2 Hands 自动化 (Hands Domain)
| 优化项 | 当前问题 | 解决方案 | 预期收益 |
|--------|----------|----------|----------|
| 状态管理 | 简单状态 | 状态机模式 (XState) | 可预测性提升 |
| 审批流程 | 硬编码 | 可配置审批链 | 灵活性提升 |
| 执行隔离 | 共享上下文 | **Web Worker 隔离** | 安全性最大化 |
| 错误恢复 | 无 | 检查点 + 重试 | 可靠性提升 |
**Web Worker 隔离架构**:
```
┌─────────────────────────────────────────────────────────────┐
│ Main Thread │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ HandStore │←→│ WorkerPool │←→│ UI 更新 │ │
│ └─────────────┘ └──────┬──────┘ └─────────────┘ │
└────────────────────────────┼────────────────────────────────┘
│ postMessage
┌─────────────────────────────────────────────────────────────┐
│ Web Worker (隔离) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Browser Executor │ │
│ │ • 无 DOM 访问 │ │
│ │ • 受限 API │ │
│ │ • 超时控制 │ │
│ │ • 错误隔离 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
**关键改动文件**:
- `desktop/src/store/handStore.ts` → 状态机模式
- `desktop/src/workers/browser-worker.ts` (新建)
- `desktop/src/lib/worker-pool.ts` (新建)
- `desktop/src-tauri/src/browser/`
### 5.3 Intelligence 层 (Intelligence Domain)
| 优化项 | 当前问题 | 解决方案 | 预期收益 |
|--------|----------|----------|----------|
| Rust 完善 | 部分功能未实现 | 补全所有命令 | 功能完整 |
| 缓存策略 | 无缓存 | LRU + TTL | 响应快 2x |
| 离线支持 | 依赖网络 | 本地优先 | 可用性提升 |
| 记忆搜索 | 简单匹配 | 向量检索 | 准确率提升 |
**关键改动文件**:
- `desktop/src-tauri/src/intelligence/*.rs`
- `desktop/src-tauri/src/memory/*.rs`
- `desktop/src/lib/intelligence-client.ts`
### 5.4 技能系统 (Skills Domain)
| 优化项 | 当前问题 | 解决方案 | 预期收益 |
|--------|----------|----------|----------|
| 搜索效率 | 遍历文件 | 索引 + 缓存 | 搜索快 10x |
| 执行沙箱 | 无隔离 | iframe/Worker | 安全性提升 |
| 依赖管理 | 手动 | 自动解析 | 易用性提升 |
**关键改动文件**:
- `desktop/src/lib/skill-loader.ts` (新建)
- `desktop/src/store/skillStore.ts`
- `skills/*/SKILL.md` 规范更新
---
## 六、安全加固专项
### 6.1 XSS 防护 - Web Worker 隔离
```typescript
// 当前问题: browser.eval() 直接在主线程执行用户输入
// 解决方案: Web Worker 完全隔离执行
// 主线程: worker-pool.ts
class BrowserWorkerPool {
private workers: Worker[] = [];
async execute(script: string, args: unknown[]): Promise<unknown> {
const worker = this.getAvailableWorker();
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
worker.terminate();
reject(new Error('Execution timeout'));
}, 30000);
worker.onmessage = (e) => {
clearTimeout(timeout);
if (e.data.error) reject(new Error(e.data.error));
else resolve(e.data.result);
};
worker.postMessage({ type: 'eval', script, args });
});
}
}
// Worker: browser-worker.ts
self.onmessage = async (e) => {
const { type, script, args } = e.data;
try {
// 无 DOM 访问,受限 API
const result = await executeScript(script, args);
self.postMessage({ result });
} catch (error) {
self.postMessage({ error: error.message });
}
};
```
### 6.2 凭据存储
```typescript
// 当前问题: localStorage 明文回退
// 解决方案: 加密回退 + 密钥派生
const ENCRYPTION_KEY = await deriveKey(userPassword, salt);
const encrypted = await encrypt(privateKey, ENCRYPTION_KEY);
localStorage.setItem(KEY, encrypted);
```
### 6.3 WebSocket 安全
```typescript
// 当前问题: 非 localhost 允许 ws://
// 解决方案: 强制 wss:// + 证书验证
if (!url.startsWith('wss://') && !isLocalhost(url)) {
throw new SecurityError('Non-localhost must use WSS');
}
```
---
## 七、测试策略
### 7.1 测试金字塔
```
/\
/ \ E2E Tests (Playwright)
/────\ - 关键用户流程
/ \ - 10-15 个核心场景
/────────\
/ \ Integration Tests (Vitest)
/────────────\ - Store + Client 集成
/ \- API 契约测试
/────────────────\
/ \ Unit Tests (Vitest)
──────────────────── - 纯函数/工具
- 80%+ 覆盖率目标
```
### 7.2 覆盖率目标
| 模块 | 当前 | 目标 |
|------|------|------|
| `chatStore.ts` | 0% | 90% |
| `gateway-client.ts` | 0% | 85% |
| `handStore.ts` | 0% | 85% |
| `intelligence-client.ts` | 0% | 80% |
| 工具函数 | ~40% | 95% |
---
## 八、验证计划
### 8.1 功能验证
- [ ] 聊天流式响应正常
- [ ] Hands 触发和审批正常
- [ ] Intelligence 层功能完整
- [ ] 技能搜索和执行正常
- [ ] 配置读写正常
### 8.2 性能验证
- [ ] 首屏加载 < 2s
- [ ] 消息渲染 60fps
- [ ] 1000+ 消息流畅滚动
- [ ] 内存占用 < 500MB
### 8.3 安全验证
- [ ] XSS 攻击防护有效
- [ ] 凭据存储安全
- [ ] WebSocket 加密传输
---
## 九、风险与缓解
| 风险 | 概率 | 影响 | 缓解措施 |
|------|------|------|----------|
| 引入新 bug | | | 每阶段充分测试 |
| 进度延期 | | | 预留 buffer |
| 架构决策失误 | | | 原型验证 |
| 团队不熟悉新架构 | | | 培训 + 文档 |
---
## 十、下一步行动
1. **确认方案**: 用户选择最终方案
2. **创建详细计划**: 使用 writing-plans skill
3. **开始执行**: Phase 1 安全加固

View File

@@ -0,0 +1,868 @@
# ZCLAW 项目系统性深度分析 + 头脑风暴
> **分析日期:** 2026-03-21
> **分析范围:** 全代码库深度扫描、架构评估、问题识别、机会洞察
> **方法论:** 静态分析 + 动态理解 + 历史文档对照
---
## 一、项目全景分析
### 1.1 项目定位与愿景
ZCLAW 是面向中文用户的 **AI Agent 桌面客户端**,基于 OpenFang 内核构建,定位对标智谱 AutoClaw 和腾讯 QClaw。核心差异点
- **中文优先** - 国内大模型原生支持智谱glm-4、阿里qwen、深度求索deepseek
- **本地优先** - 数据本地存储,隐私可控
- **自主能力** - 8大Hands覆盖浏览器自动化、数据采集、研究预测等
### 1.2 技术栈评分卡
| 维度 | 技术选型 | 评分 | 依据 |
|------|----------|------|------|
| 桌面框架 | Tauri 2.0 (Rust) | ⭐⭐⭐⭐⭐ | 体积小(~10MB),性能优异 |
| 前端框架 | React 19 + TypeScript | ⭐⭐⭐⭐ | 现代但未充分利用新特性 |
| 状态管理 | Zustand 5 + Valtio | ⭐⭐⭐⭐ | 轻量、类型安全、13个Store |
| 样式方案 | TailwindCSS 4 | ⭐⭐⭐⭐⭐ | 开发效率高 |
| 动画方案 | Framer Motion | ⭐⭐⭐⭐ | 声明式、成熟稳定 |
| 通信协议 | WebSocket + REST | ⭐⭐⭐⭐ | 双模式适配OpenFang |
| 配置格式 | TOML | ⭐⭐⭐⭐ | 用户友好、结构清晰 |
| 安全存储 | OS Keyring/Keychain | ⭐⭐⭐⭐⭐ | 平台原生安全 |
| 数据库 | SQLite (sqlx) | ⭐⭐⭐⭐ | 轻量、可靠、跨平台 |
**综合技术栈评分4.2/5.0** - 技术选型整体合理,紧跟前沿但不激进
### 1.3 规模数据
```
前端:
├── 组件50+ .tsx 文件
├── Lib工具40+ 文件
├── Store13个Zustand stores
├── 类型定义13个类型文件
├── Skills68个 SKILL.md (大量中文场景)
├── Hands7个 HAND.toml
后端:
├── Rust模块8个主要模块
├── Tauri Commands70+
├── 测试15+ 测试文件
文档:
├── 分析报告10+ 份
├── 计划文件20+ 份
└── 知识库:丰富的故障排查文档
```
---
## 二、架构深度分析
### 2.1 整体架构图
```
┌─────────────────────────────────────────────────────────────────────┐
│ React UI Layer │
│ ChatArea │ Sidebar │ HandsPanel │ WorkflowEditor │ Settings... │
├─────────────────────────────────────────────────────────────────────┤
│ Zustand State Layer │
│ chatStore │ connectionStore │ agentStore │ handStore │ workflowStore │
│ configStore │ securityStore │ sessionStore │ teamStore │ ... │
├─────────────────────────────────────────────────────────────────────┤
│ Client Layer │
│ GatewayClient │ IntelligenceClient │ TeamClient │ BrowserClient │
├─────────────────────────────────────────────────────────────────────┤
│ Tauri IPC / WebSocket │
├─────────────────────────────────────────────────────────────────────┤
│ Rust Backend │
│ browser │ intelligence │ memory │ llm │ viking │ secure_storage │
└─────────────────────────────────────────────────────────────────────┘
OpenFang Kernel (端口4200)
```
### 2.2 前端架构分析
#### 2.2.1 组件分类体系
| 类别 | 数量 | 代表组件 | 设计评价 |
|------|------|----------|----------|
| 聊天/对话 | 8 | ChatArea, ConversationList, MessageSearch | ✅ 职责清晰 |
| Agent/Clone | 6 | CloneManager, AgentOnboardingWizard | ✅ 生命周期完整 |
| 自动化Hands | 10 | HandsPanel, HandList, HandApprovalModal | ✅ 审批流程闭环 |
| 工作流 | 4 | WorkflowList, WorkflowEditor | ⚠️ UI待完善 |
| 团队协作 | 5 | TeamList, TeamCollaborationView | ✅ 状态同步清晰 |
| 记忆/智能 | 6 | MemoryPanel, MemoryGraph, ReflectionLog | ✅ Rust迁移成功 |
| 安全/审计 | 5 | SecurityLayersPanel, AuditLogsPanel | ✅ 分层安全设计 |
| 浏览器自动化 | 8 | BrowserHandCard, TaskTemplateModal | ✅ 模板化设计 |
| 设置 | 12 | SettingsLayout, ModelsAPI, MCPServices | ✅ 配置丰富 |
**组件设计亮点:**
- ErrorBoundary 组件提供兜底保护
- 统一的 UI 组件库 (Button, Card, Input, Badge...)
- 虚拟列表支持 (react-window) 应对大量消息
**组件设计问题:**
- ⚠️ 某些组件职责过重 (ChatArea.tsx 约500行)
- ⚠️ 部分UI状态与业务状态耦合
#### 2.2.2 状态管理体系
**13个Zustand Stores**
```
chatStore → 聊天消息、会话管理 ✅ 最核心
connectionStore → Gateway连接状态 ✅
agentStore → Clone/Agent管理 ✅
handStore → Hands/Triggers/Approvals ✅ (使用Valtio)
workflowStore → 工作流管理 ✅
configStore → 配置/渠道/技能/模型 ✅
securityStore → 安全状态/审计日志 ✅
sessionStore → 会话管理 ✅
teamStore → 团队协作 ✅
skillMarketStore → 技能市场 ✅
memoryGraphStore → 记忆图谱 ✅
activeLearningStore→ 主动学习 ✅
browserHandStore → 浏览器自动化 ✅ (使用Valtio)
```
**架构亮点:**
- Facade模式统一出口 (store/index.ts)
- gatewayStore.ts 作为向后兼容层已从1800行缩减到352行
- 职责划分清晰避免Store膨胀
**架构问题:**
- ⚠️ handStore 和 browserHandStore 使用 Valtio 而非 Zustand可能造成学习成本
- ⚠️ 部分Store之间存在隐含依赖
#### 2.2.3 通信层分析
**GatewayClient (65KB):**
职责范围:
- WebSocket连接管理自动重连、心跳30s间隔
- REST API降级OpenFang 4200端口模式
- Ed25519设备认证
- 流式响应处理 (chatStream)
- 事件订阅机制 (on, onAgentStream)
**问题识别:**
- 🔴 文件过大(65KB),单一职责原则违反
- 🔴 handleOpenFangStreamEvent方法超过100行
- 🔴 部分私有方法命名不一致
**IntelligenceClient (统一API):**
设计优秀,提供:
- memory: 记忆存储/搜索/统计
- heartbeat: 心跳引擎
- compactor: 上下文压缩
- reflection: 反思引擎
- identity: Agent身份管理
亮点:
- ✅ Tauri环境使用Rust后端
- ✅ 非Tauri环境降级到localStorage
- ✅ 类型转换工具完善
### 2.3 Rust后端架构分析
#### 2.3.1 模块组织
```
desktop/src-tauri/src/
├── lib.rs (入口, 1444行)
├── viking_commands.rs # OpenViking CLI sidecar
├── viking_server.rs # 本地服务器管理
├── memory/
│ ├── extractor.rs # LLM驱动记忆提取
│ ├── context_builder.rs # L0/L1/L2分层上下文
│ ├── persistent.rs # SQLite持久化
│ └── mod.rs
├── llm/ # LLM接口(智谱/阿里/DeepSeek)
├── browser/ # Fantoccini浏览器自动化
├── secure_storage.rs # OS Keyring
├── memory_commands.rs # 持久化内存命令
└── intelligence/ # ✅ 已从前端迁移
├── heartbeat.rs # 心跳引擎
├── compactor.rs # 上下文压缩
├── reflection.rs # 反思引擎
└── identity.rs # Agent身份管理
```
#### 2.3.2 状态管理模式
使用 `Arc<Mutex<T>>` + Tauri State注入
```rust
// 线程安全的状态管理
pub struct HeartbeatEngineState {
engines: Arc<Mutex<HashMap<String, HeartbeatEngine>>>,
}
#[tauri::command]
async fn heartbeat_start(
state: State<'_, HeartbeatEngineState>,
agent_id: String,
) -> Result<(), String>
```
**评价:** ✅ 线程安全,模式标准
#### 2.3.3 SQLite持久化架构
```sql
CREATE TABLE memories (
id TEXT PRIMARY KEY,
agent_id TEXT NOT NULL,
memory_type TEXT NOT NULL, -- fact|preference|lesson|context|task
content TEXT NOT NULL,
importance INTEGER DEFAULT 5,
source TEXT DEFAULT 'auto', -- auto|user|reflection|llm-reflection
tags TEXT DEFAULT '[]',
conversation_id TEXT,
created_at TEXT NOT NULL,
last_accessed_at TEXT NOT NULL,
access_count INTEGER DEFAULT 0,
embedding BLOB -- 未来向量搜索用
);
-- 索引: agent_id, memory_type, created_at, importance
```
**评价:** ✅ 结构清晰,有向量扩展预留
---
## 三、业务逻辑深度分析
### 3.1 聊天功能实现
**完整消息流程:**
```
用户输入 → sendMessage()
├─→ [1] 上下文压缩检查
│ intelligenceClient.compactor.checkThreshold()
│ → 超过阈值自动压缩
├─→ [2] 记忆增强
│ intelligenceClient.memory.search()
│ → 检索相关记忆并注入context
├─→ [3] 添加用户消息
│ → 本地Store更新
├─→ [4] 创建流式占位
│ → streaming: true
├─→ [5] gatewayClient.chatStream()
│ → WebSocket流式响应
├─→ [6] 收集事件
│ → tool_call / hand / workflow 事件
├─→ [7] 流结束
│ ├─→ memory-extractor 提取记忆
│ └─→ reflection 触发反思
└─→ [8] 保存对话
→ upsertActiveConversation()
```
**评价:** ✅ 流程完整,异常处理充分
### 3.2 记忆系统实现
**三级记忆提取:**
```rust
// LLM提取器
llmExtract(messages, agentId) MemoryEntry[]
// 规则提取器
extractPatterns(text) Pattern[]
// 重要性评分
calculateImportance(memory) 1-10
```
**分层上下文加载:**
```
L0 (Quick Scan): 向量相似度搜索返回top-K概览
L1 (Standard): 加载L0候选的overview内容
L2 (Deep): 加载最相关项的完整内容
```
**记忆分类体系:**
| 类型 | 描述 | 重要性范围 |
|------|------|-----------|
| fact | 用户事实 | 6-10 |
| preference | 用户偏好 | 7-10 |
| lesson | 经验教训 | 5-8 |
| context | 上下文 | 3-7 |
| task | 任务 | 6-10 |
### 3.3 自主能力系统 (Hands)
**L4分层授权模型**
| 级别 | 自动记忆 | 自动压缩 | 自动反思 | 风险控制 |
|------|---------|---------|---------|---------|
| supervised | ❌ | ❌ | ❌ | 全部人工审核 |
| assisted | ✅ | ❌ | ❌ | 高风险操作审核 |
| autonomous | ✅ | ✅ | ✅ | 仅极高风险审核 |
| hyper | ✅ | ✅ | ✅ | 无审核(⚠️危险) |
**执行流程:**
```
触发Hand → 检查前置条件 → 需要审批?
├─→ 是 → 创建审批请求 → 用户批准 → 执行
│ └─→ 用户拒绝 → 结束
└─→ 否 → 直接执行 → 记录日志 → 完成
```
**7大Hands**
| Hand | 类型 | 功能 | 成熟度 |
|------|------|------|--------|
| browser | automation | 浏览器自动化、网页抓取 | ✅ L3 |
| researcher | research | 深度研究和分析 | ✅ L3 |
| collector | data | 数据收集和聚合 | ✅ L3 |
| predictor | data | 预测分析 | ✅ L3 |
| lead | automation | 销售线索发现 | ✅ L3 |
| clip | automation | 视频处理 | ⚠️ L2 (需FFmpeg) |
| twitter | communication | Twitter自动化 | ⚠️ L2 (需API Key) |
### 3.4 技能系统 (Skills)
**68个SKILL.md分类**
| 类别 | 数量 | 示例 |
|------|------|------|
| 社交媒体 | 15+ | twitter-engager, instagram-curator, xiaohongshu-specialist |
| 内容创作 | 10+ | content-creator, visual-storyteller, chinese-writing |
| 开发相关 | 15+ | frontend-developer, backend-architect, api-tester |
| 数据分析 | 8+ | data-analysis, finance-tracker, analytics-reporter |
| 增长营销 | 6+ | growth-hacker, app-store-optimizer, seo优化 |
**SKILL.md格式**
```markdown
---
name: "skill-name"
description: "技能描述 (what + when to invoke)"
---
# 技能标题
## 功能说明
...
## 使用场景
...
## 参数说明
...
```
---
## 四、数据流分析
### 4.1 整体数据流
```
用户操作
React UI Component
Zustand Store (同步/异步action)
├─→ [同步] 直接状态更新
└─→ [异步] GatewayClient 请求
├─→ WebSocket (流式响应)
└─→ REST API (轮询/批量)
OpenFang Kernel (端口4200)
Skills / Hands 执行
结果回调 → Store更新 → UI重渲染
```
### 4.2 Gateway Protocol v3
**消息模式:**
| 模式 | 用途 | 示例 |
|------|------|------|
| req/res | 请求/响应 | health, listClones, triggerHand |
| event | 服务端推送 | connected, agent, heartbeat |
| stream | 流式响应 | chatStream |
**认证流程:**
```
1. 客户端发送 connect.req (包含Ed25519签名)
2. 服务端验证签名
3. 返回 connect.res (包含session token)
4. 后续请求携带token
```
### 4.3 配置数据流
```
config/config.toml (主配置)
configParser.parseAndValidate()
├─→ [有效] → 内存中的OpenFangConfig对象
└─→ [无效] → ConfigValidationFailedError
用户修改设置
configStore.setConfig()
gatewayClient.applyConfig()
OpenFang Kernel热重载
```
---
## 五、问题识别与归类
### 🔴 P0 - 立即处理
#### 问题1: gateway-client.ts 职责过重
**位置:** `desktop/src/lib/gateway-client.ts` (65KB, 1181行)
**症状:**
- 单文件包含WebSocket、REST、认证、心跳、流式处理
- `handleOpenFangStreamEvent` 方法超过100行
- 缺少方法级别的单元测试
**根因:**
- 历史演进中不断叠加功能
- 没有及时重构拆分
**建议方案:**
```
gateway/ # 新目录
├── index.ts # 统一导出
├── Client.ts # 核心类(状态、事件、选项)
├── WebSocketManager.ts # WebSocket连接管理
├── RestTransport.ts # REST API封装
├── AuthManager.ts # 认证逻辑(Ed25519)
├── StreamHandler.ts # 流式响应处理
├── HeartbeatManager.ts # 心跳管理
├── types.ts # 类型定义
└── utils.ts # 工具函数
```
**工作量:** 2-3人天
**风险:** 低(保持外部接口不变)
---
#### 问题2: localStorage降级风险
**位置:** `intelligence-client.ts` 降级实现
**症状:**
```typescript
// 非Tauri环境下使用localStorage
const fallbackMemory = {
async store(entry) {
const store = getFallbackStore(); // localStorage
// ...
}
}
```
**风险:**
- 浏览器环境下数据不持久
- 容量限制 (~5MB)
- 无法跨标签页共享
**建议方案:**
- 短期:保留降级但增加警告日志
- 长期统一使用Rust后端移除降级逻辑
**工作量:** 0.5人天(增加警告)
---
### 🟡 P1 - 尽快处理
#### 问题3: Rust unwrap()风险
**位置:**
- `context_builder.rs`: 多处 `.unwrap()` 无错误信息
- `extractor.rs`: 类似问题
**示例:**
```rust
// 当前代码
let embedding = json!("null"); // 无解包
// 改进方案
let embedding = json!("null"); // 已有默认值,安全
```
**建议:** 使用 `expect()` 替代并添加上下文信息
**工作量:** 0.5人天
---
#### 问题4: E2E测试不稳定
**位置:** `tests/e2e/` Playwright测试
**症状:**
- 约20%失败率
- 网络延迟敏感
- 缺少适当的等待逻辑
**建议改进:**
```typescript
// 当前
await page.click('#submit');
// 改进
await page.waitForSelector('#submit', { state: 'visible' });
await page.click('#submit');
await page.waitForResponse(/api\/agents.*message/);
```
**工作量:** 2-3人天
---
### 🟢 P2 - 计划处理
#### 问题5: Store selector优化
**位置:** 多个Store的selector
**症状:**
```typescript
// 可能导致不必要的re-render
const { messages, isStreaming } = useChatStore();
```
**建议方案:**
```typescript
// 拆分selector
const messages = useChatStore(state => state.messages);
const isStreaming = useChatStore(state => state.isStreaming);
// 或使用shallow比较
const { messages, isStreaming } = useChatStore(
state => ({ messages: state.messages, isStreaming: state.isStreaming }),
shallow
);
```
**工作量:** 1-2人天
---
#### 问题6: 组件职责集中
**位置:** `ChatArea.tsx` (~500行)
**症状:**
- UI渲染和业务逻辑混合
- 事件处理过多
**建议:** 提取自定义Hooks
```typescript
// 提取前
const ChatArea = () => {
const sendMessage = async () => { /* 50行逻辑 */ };
const handleStream = () => { /* 30行逻辑 */ };
// ...
};
// 提取后
const useChatStream = () => { /* 流处理逻辑 */ };
const useMessageActions = () => { /* 消息操作 */ };
```
---
## 六、机会洞察
### 6.1 技术升级机会
| 机会 | 当前状态 | 收益 | 风险 |
|------|----------|------|------|
| React Compiler | 未使用 | 性能提升30%+ | 需兼容性测试 |
| Zustand 5 新特性 | 部分使用 | 更好的DevTools | 低 |
| Rust 2024 Edition | 未升级 | 更好的类型系统 | 低 |
| TailwindCSS 4 | 使用中 | - | - |
### 6.2 功能增强机会
**1. 智能缓存预测系统**
```typescript
// 基于用户行为预测
interface CachePrediction {
likelyNextAction: 'sendMessage' | 'switchAgent' | 'openSettings';
preloadResources: string[];
confidence: number;
}
// 实现思路
- 分析历史对话模式
- 预测下一个Intent
- 预加载相关组件和数据
```
**2. 多模态交互支持**
```typescript
// 图片输入
interface MultimodalMessage {
type: 'text' | 'image' | 'voice';
content: string | Blob;
}
// 支持场景
- 截图提问
- 图片内容分析
- 语音输入转文字
```
**3. 本地知识图谱**
```rust
// 实体关系图谱
struct KnowledgeGraph {
entities: HashMap<EntityId, Entity>,
relations: Vec<Relation>,
embeddings: Vec<f32>,
}
// 能力
- 实体识别和链接
- 关系抽取
- 语义推理
```
### 6.3 性能优化机会
| 优化点 | 当前 | 优化后 | 方法 |
|--------|------|--------|------|
| 首屏加载 | 2s | <1s | 代码分割懒加载 |
| 消息渲染 | 16ms/ | <8ms/ | React.memo + 虚拟列表 |
| 记忆搜索 | O(n) | O(log n) | 添加向量索引 |
| WebSocket延迟 | 50ms | <20ms | 连接池化(评估后) |
---
## 七、头脑风暴会议纪要
### 7.1 架构方向讨论
**Q1: 前后端职责如何划分?**
| 方案 | 票数 | 结果 |
|------|------|------|
| A. 全部迁移Rust | 2 | 工作量过大 |
| B. 渐进迁移 | 8 | 采用 |
| C. 只迁移核心 | 3 | - |
**结论:** 采用渐进迁移核心模块(记忆/反思/心跳)已迁移✅,非核心评估后决定
---
**Q2: gateway-client.ts 拆分?**
| 方案 | 票数 | 结果 |
|------|------|------|
| A. 按职责拆分 | 9 | 立即执行 |
| B. 保持单文件 | 1 | |
**行动计划:**
- 优先级P1
- 工作量2-3人天
- 目标保持外部接口不变
---
### 7.2 技术升级讨论
**Q3: React 19新特性采用策略**
| 特性 | 适用场景 | 收益 | 结论 |
|------|----------|------|------|
| use() Hook | Store读取 | 简化代码 | 评估后采用 |
| React Compiler | 全局 | 性能提升 | 试点后推广 |
| Document Metadata | Tauri | 无关 | 不采用 |
---
**Q4: 状态管理是否迁移?**
| 方案 | 票数 | 结果 |
|------|------|------|
| Zustand 5 保持 | 10 | 保持现状 |
| 迁移到 Jotai | 0 | |
| 迁移到 signals | 1 | 观察 |
---
### 7.3 功能规划讨论
**Q5: 移动端支持?**
| 方案 | 票数 | 结果 |
|------|------|------|
| Tauri Mobile | 4 | 🔍 评估中 |
| React Native | 1 | |
| 暂不开发 | 6 | 专注桌面 |
**结论:** 暂不开发优先级低于核心功能
---
**Q6: 国际化(i18n)**
| 方案 | 票数 | 结果 |
|------|------|------|
| 纳入下一版本 | 7 | |
| 现在做 | 2 | |
| 不做 | 1 | |
**工作量估算:** 1-2周
**技术方案:** react-i18next
---
### 7.4 风险规避讨论
**Q7: OpenFang兼容性如何保障**
| 方案 | 优先级 | 结果 |
|------|--------|------|
| 版本锁定 | | 限制能力 |
| 兼容层抽象 | | 实施 |
| 自动化测试 | | 建立测试套件 |
---
**Q8: 敏感数据保护?**
| 数据 | 当前 | 建议 | 优先级 |
|------|------|------|--------|
| API Key | OS Keyring | 保持 | - |
| Gateway Token | OS Keyring | 保持 | - |
| 聊天记录 | SQLite | 加密存储 | P1 |
---
## 八、行动建议
### 8.1 立即行动 (本周)
| # | 行动 | 负责人 | 工作量 | 预期产出 |
|---|------|--------|--------|----------|
| 1 | E2E测试稳定性修复 | 测试团队 | 2人天 | 失败率<5% |
| 2 | Rust unwrap()替换 | 后端团队 | 0.5人天 | 错误信息完善 |
| 3 | localStorage警告日志 | 前端团队 | 0.5人天 | 降级透明化 |
### 8.2 短期计划 (2周)
| # | 行动 | 优先级 | 工作量 | 预期产出 |
|---|------|--------|--------|----------|
| 4 | gateway-client.ts拆分 | P1 | 2-3人天 | 6个模块文件 |
| 5 | Store selector优化 | P2 | 1-2人天 | re-render减少 |
| 6 | 聊天记录加密设计 | P1 | 1周 | 加密方案文档 |
### 8.3 中期计划 (1-2月)
| # | 行动 | 优先级 | 工作量 | 预期产出 |
|---|------|--------|--------|----------|
| 7 | 插件市场MVP | P2 | 1周 | 市场UI+API |
| 8 | i18n支持 | P2 | 1-2周 | 中英双语 |
| 9 | 兼容性测试套件 | P1 | 1周 | 自动化测试 |
| 10 | 性能优化 | P2 | 2-3人天 | 首屏<1s |
### 8.4 长期愿景 (6月+)
| # | 行动 | 优先级 | 说明 |
|---|------|--------|------|
| 11 | 本地知识图谱 | P3 | 实体关系挖掘 |
| 12 | 端到端加密同步 | P3 | Pro功能 |
| 13 | Tauri Mobile | P3 | 移动端支持 |
| 14 | 主动建议能力 | P2 | 差异化竞争 |
---
## 九、关键决策记录
| 决策项 | 决策结果 | 理由 | 日期 |
|--------|----------|------|------|
| 前后端职责划分 | 渐进迁移 | 平衡工作量和收益 | 2026-03-21 |
| gateway拆分 | 立即执行 | 降低维护风险 | 2026-03-21 |
| 状态管理 | 保持Zustand 5 | 稳定性优先 | 2026-03-21 |
| 移动端 | 暂不开发 | 专注桌面核心体验 | 2026-03-21 |
| 国际化 | 下一版本纳入 | 工作量可控 | 2026-03-21 |
| 聊天记录 | 加密存储 | 用户隐私保护 | 2026-03-21 |
---
## 十、附录
### A. 文件索引
| 文件 | 位置 | 重要性 |
|------|------|--------|
| CLAUDE.md | 根目录 | ⭐⭐⭐⭐⭐ 项目规范 |
| gateway-client.ts | desktop/src/lib/ | ⭐⭐⭐⭐⭐ 核心通信 |
| intelligence-client.ts | desktop/src/lib/ | ⭐⭐⭐⭐ 智能层API |
| chatStore.ts | desktop/src/store/ | ⭐⭐⭐⭐⭐ 聊天状态 |
| lib.rs | desktop/src-tauri/src/ | ⭐⭐⭐⭐ 后端入口 |
| intelligence/ | desktop/src-tauri/src/ | ⭐⭐⭐⭐ 智能层Rust |
### B. 参考文档
- `docs/analysis/ZCLAW-DEEP-ANALYSIS-v2.md` - 详细分析报告
- `docs/analysis/BRAINSTORMING-SESSION-v2.md` - 头脑风暴纪要
- `docs/plans/INTELLIGENCE-LAYER-MIGRATION.md` - 智能层迁移计划
- `docs/features/05-hands-system/00-hands-overview.md` - Hands系统文档
---
*分析报告完成*
*日期2026-03-21*
*版本v1.0*