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:
366
plans/abstract-finding-forest-agent-a5bc2d4e73e72fb27.md
Normal file
366
plans/abstract-finding-forest-agent-a5bc2d4e73e72fb27.md
Normal 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。
|
||||
261
plans/abstract-finding-forest.md
Normal file
261
plans/abstract-finding-forest.md
Normal 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 |
|
||||
| **总计** | **约 15h(2个工作日)** |
|
||||
276
plans/foamy-imagining-sun.md
Normal file
276
plans/foamy-imagining-sun.md
Normal 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小时** |
|
||||
444
plans/prancy-greeting-tarjan.md
Normal file
444
plans/prancy-greeting-tarjan.md
Normal 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 安全加固
|
||||
|
||||
868
plans/project-analysis-and-brainstorming-2026-03-21.md
Normal file
868
plans/project-analysis-and-brainstorming-2026-03-21.md
Normal 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+ 文件
|
||||
├── Store:13个Zustand stores
|
||||
├── 类型定义:13个类型文件
|
||||
├── Skills:68个 SKILL.md (大量中文场景)
|
||||
├── Hands:7个 HAND.toml
|
||||
|
||||
后端:
|
||||
├── Rust模块:8个主要模块
|
||||
├── Tauri Commands:70+
|
||||
├── 测试: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*
|
||||
Reference in New Issue
Block a user