release(v0.2.0): streaming, MCP protocol, Browser Hand, security enhancements

## Major Features

### Streaming Response System
- Implement LlmDriver trait with `stream()` method returning async Stream
- Add SSE parsing for Anthropic and OpenAI API streaming
- Integrate Tauri event system for frontend streaming (`stream:chunk` events)
- Add StreamChunk types: Delta, ToolStart, ToolEnd, Complete, Error

### MCP Protocol Implementation
- Add MCP JSON-RPC 2.0 types (mcp_types.rs)
- Implement stdio-based MCP transport (mcp_transport.rs)
- Support tool discovery, execution, and resource operations

### Browser Hand Implementation
- Complete browser automation with Playwright-style actions
- Support Navigate, Click, Type, Scrape, Screenshot, Wait actions
- Add educational Hands: Whiteboard, Slideshow, Speech, Quiz

### Security Enhancements
- Implement command whitelist/blacklist for shell_exec tool
- Add SSRF protection with private IP blocking
- Create security.toml configuration file

## Test Improvements
- Fix test import paths (security-utils, setup)
- Fix vi.mock hoisting issues with vi.hoisted()
- Update test expectations for validateUrl and sanitizeFilename
- Add getUnsupportedLocalGatewayStatus mock

## Documentation Updates
- Update architecture documentation
- Improve configuration reference
- Add quick-start guide updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-24 03:24:24 +08:00
parent e49ba4460b
commit 3ff08faa56
78 changed files with 29575 additions and 1682 deletions

View File

@@ -0,0 +1,303 @@
# ZCLAW 自我进化系统审查与修复计划
## 背景
自我进化系统是 ZCLAW 的核心能力,包括四个组件:
- **心跳引擎** - 定期主动检查
- **反思引擎** - 分析模式并生成改进建议
- **身份管理** - 管理人格文件和变更提案
- **记忆存储** - 持久化对话和经验
---
## 审查结果摘要
### 实现状态
| 组件 | 函数/功能 | 状态 |
|------|----------|------|
| **心跳引擎** | check_pending_tasks | ✅ 完整 |
| | check_memory_health | ✅ 完整 |
| | check_correction_patterns | ✅ 完整 |
| | check_learning_opportunities | ✅ 完整 |
| | check_idle_greeting | ⚠️ 占位符 |
| **反思引擎** | analyze_patterns | ✅ 完整 |
| | generate_improvements | ✅ 完整 |
| | propose_identity_changes | ✅ 完整 |
| **身份管理** | 提案处理 | ✅ 完整 |
| | 持久化 | ✅ 完整 |
| **前端** | Intelligence Client | ✅ 完整 |
| | IdentityChangeProposal UI | ✅ 完整 |
| | 提案通知系统 | ✅ 存在 |
### 发现的问题
| 优先级 | 问题 | 影响 |
|--------|------|------|
| HIGH | MemoryStatsCache 同步问题 | 心跳检查依赖前端主动更新,可能跳过检查 |
| HIGH | API 命名不一致 | `updateMemoryStats` 参数名不匹配camelCase vs snake_case |
| MEDIUM | check_idle_greeting 占位符 | 空闲问候功能不可用 |
| MEDIUM | 类型定义不一致 | `totalEntries` vs `total_memories` 命名不统一 |
| MEDIUM | 提案审批错误处理 | 缺少详细的错误反馈 |
| LOW | storageSizeBytes fallback 为 0 | localStorage 模式下无法计算 |
| LOW | 硬编码配置值 | 历史限制、快照数量不可配置 |
---
## 修复计划
### Phase 1: 修复 HIGH 优先级问题
#### Fix 1.1: API 参数命名修正 ⚡ 5分钟
**文件**: [intelligence-client.ts](desktop/src/lib/intelligence-client.ts)
**问题**: `updateMemoryStats` 使用 camelCase 参数,但 Rust 后端期望 snake_case
**修改位置**: 第 989-1011 行
```typescript
// 修改前
await invoke('heartbeat_update_memory_stats', {
agentId,
taskCount,
totalEntries,
storageSizeBytes,
});
// 修改后
await invoke('heartbeat_update_memory_stats', {
agent_id: agentId,
task_count: taskCount,
total_entries: totalEntries,
storage_size_bytes: storageSizeBytes,
});
```
#### Fix 1.2: 添加周期性记忆统计同步 ⚡ 15分钟
**文件**: [App.tsx](desktop/src/App.tsx)
**问题**: 记忆统计仅在启动时同步一次,之后数据可能陈旧
**修改位置**: 第 213 行后heartbeat.start 之后)
```typescript
// 添加周期性同步(每 5 分钟)
const MEMORY_STATS_SYNC_INTERVAL = 5 * 60 * 1000;
const statsSyncInterval = setInterval(async () => {
try {
const stats = await intelligenceClient.memory.stats();
const taskCount = stats.byType?.['task'] || 0;
await intelligenceClient.heartbeat.updateMemoryStats(
defaultAgentId,
taskCount,
stats.totalEntries,
stats.storageSizeBytes
);
console.log('[App] Memory stats synced (periodic)');
} catch (err) {
console.warn('[App] Periodic memory stats sync failed:', err);
}
}, MEMORY_STATS_SYNC_INTERVAL);
```
#### Fix 1.3: 心跳检查容错处理 ⚡ 20分钟
**文件**: [heartbeat.rs](desktop/src-tauri/src/intelligence/heartbeat.rs)
**问题**: 当缓存为空时,检查函数直接跳过,无告警
**修改**: 在 `check_pending_tasks``check_memory_health` 中添加缓存缺失告警
```rust
fn check_pending_tasks(agent_id: &str) -> Option<HeartbeatAlert> {
match get_cached_memory_stats(agent_id) {
Some(stats) if stats.task_count >= 5 => { /* 现有逻辑 */ },
Some(_) => None,
None => Some(HeartbeatAlert {
title: "记忆统计未同步".to_string(),
content: "心跳引擎未能获取记忆统计信息,部分检查被跳过".to_string(),
urgency: Urgency::Low,
source: "pending-tasks".to_string(),
timestamp: chrono::Utc::now().to_rfc3339(),
}),
}
}
```
### Phase 2: 修复 MEDIUM 优先级问题
#### Fix 2.1: 统一类型定义命名 ⚡ 10分钟
**文件**: [intelligence-backend.ts](desktop/src/lib/intelligence-backend.ts)
**问题**: 前端使用 `totalEntries`,后端返回 `total_memories`
**修改**: 更新接口定义以匹配后端
```typescript
export interface MemoryStats {
total_entries: number; // 匹配后端
by_type: Record<string, number>;
by_agent: Record<string, number>;
oldest_entry: string | null;
newest_entry: string | null;
storage_size_bytes: number;
}
```
**同时更新** [intelligence-client.ts](desktop/src/lib/intelligence-client.ts) 中的转换函数
#### Fix 2.2: 增强提案审批错误处理 ⚡ 10分钟
**文件**: [IdentityChangeProposal.tsx](desktop/src/components/IdentityChangeProposal.tsx)
**添加错误解析函数**:
```typescript
function parseProposalError(err: unknown, operation: 'approval' | 'rejection' | 'restore'): string {
const errorMessage = err instanceof Error ? err.message : String(err);
if (errorMessage.includes('not found')) {
return `提案不存在或已被处理`;
}
if (errorMessage.includes('not pending')) {
return '该提案已被处理,请刷新页面';
}
if (errorMessage.includes('network') || errorMessage.includes('fetch')) {
return '网络连接失败,请检查网络后重试';
}
return `${operation === 'approval' ? '审批' : operation === 'rejection' ? '拒绝' : '恢复'}失败: ${errorMessage}`;
}
```
#### Fix 2.3: 实现 check_idle_greeting可选⚡ 30分钟
**文件**: [heartbeat.rs](desktop/src-tauri/src/intelligence/heartbeat.rs)
**添加最后交互时间追踪**:
```rust
static LAST_INTERACTION: OnceLock<RwLock<StdHashMap<String, String>>> = OnceLock::new();
pub fn record_interaction(agent_id: &str) {
let map = get_last_interaction_map();
if let Ok(mut map) = map.write() {
map.insert(agent_id.to_string(), chrono::Utc::now().to_rfc3339());
}
}
fn check_idle_greeting(agent_id: &str) -> Option<HeartbeatAlert> {
let map = get_last_interaction_map();
let last_interaction = map.read().ok()?.get(agent_id).cloned()?;
let last_time = chrono::DateTime::parse_from_rfc3339(&last_interaction).ok()?;
let idle_hours = (chrono::Utc::now() - last_time).num_hours();
if idle_hours >= 24 {
Some(HeartbeatAlert {
title: "用户长时间未互动".to_string(),
content: format!("距离上次互动已过去 {} 小时", idle_hours),
urgency: Urgency::Low,
source: "idle-greeting".to_string(),
timestamp: chrono::Utc::now().to_rfc3339(),
})
} else {
None
}
}
```
**同时添加 Tauri 命令**:
```rust
#[tauri::command]
pub async fn heartbeat_record_interaction(agent_id: String) -> Result<(), String>
```
### Phase 3: 修复 LOW 优先级问题(可选)
#### Fix 3.1: localStorage fallback 存储大小计算
**文件**: [intelligence-client.ts](desktop/src/lib/intelligence-client.ts)
```typescript
// 在 fallbackMemory.stats() 中添加
let storageSizeBytes = 0;
try {
const serialized = JSON.stringify(store.memories);
storageSizeBytes = new Blob([serialized]).size;
} catch { /* ignore */ }
```
---
## 实现顺序
| 顺序 | 修复项 | 优先级 | 预估时间 |
|------|--------|--------|----------|
| 1 | Fix 1.1 - API 参数命名 | HIGH | 5 分钟 |
| 2 | Fix 1.2 - 周期性同步 | HIGH | 15 分钟 |
| 3 | Fix 1.3 - 心跳容错 | HIGH | 20 分钟 |
| 4 | Fix 2.1 - 类型统一 | MEDIUM | 10 分钟 |
| 5 | Fix 2.2 - 错误处理 | MEDIUM | 10 分钟 |
| 6 | Fix 2.3 - 空闲问候 | MEDIUM | 30 分钟 |
| 7 | Fix 3.1 - 存储大小 | LOW | 5 分钟 |
**总计**: 约 1.5 小时(不含可选项)
---
## 关键文件
| 文件 | 修改内容 |
|------|----------|
| [intelligence-client.ts](desktop/src/lib/intelligence-client.ts) | API 参数命名、类型转换、存储大小计算 |
| [App.tsx](desktop/src/App.tsx) | 周期性记忆统计同步 |
| [heartbeat.rs](desktop/src-tauri/src/intelligence/heartbeat.rs) | 缓存容错、空闲问候 |
| [intelligence-backend.ts](desktop/src/lib/intelligence-backend.ts) | 类型定义统一 |
| [IdentityChangeProposal.tsx](desktop/src/components/IdentityChangeProposal.tsx) | 错误处理增强 |
| [lib.rs](desktop/src-tauri/src/lib.rs) | 注册新 Tauri 命令(如实现 Fix 2.3 |
---
## 验证方法
### Fix 1.1 验证
```bash
# 启动应用,检查控制台
pnpm start:dev
# 观察 Tauri invoke 调用参数是否正确
```
### Fix 1.2 验证
```bash
# 启动后等待 5 分钟,检查控制台
# 应看到 "[App] Memory stats synced (periodic)" 日志
```
### Fix 1.3 验证
```bash
# 清除缓存后触发心跳
# 应看到 "记忆统计未同步" 告警
```
### 全量验证
```bash
# TypeScript 类型检查
pnpm tsc --noEmit
# 运行测试
pnpm vitest run
# 启动开发环境
pnpm start:dev
```
### 人工验证清单
- [ ] 应用启动无错误
- [ ] 心跳引擎正常初始化
- [ ] 记忆统计同步正常(启动 + 周期)
- [ ] 提案审批流程正常
- [ ] 错误信息清晰可读