Files
zclaw_openfang/plans/nifty-inventing-valiant.md
iven 3ff08faa56 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>
2026-03-24 03:24:24 +08:00

9.0 KiB
Raw Blame History

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

问题: updateMemoryStats 使用 camelCase 参数,但 Rust 后端期望 snake_case

修改位置: 第 989-1011 行

// 修改前
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

问题: 记忆统计仅在启动时同步一次,之后数据可能陈旧

修改位置: 第 213 行后heartbeat.start 之后)

// 添加周期性同步(每 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

问题: 当缓存为空时,检查函数直接跳过,无告警

修改: 在 check_pending_taskscheck_memory_health 中添加缓存缺失告警

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

问题: 前端使用 totalEntries,后端返回 total_memories

修改: 更新接口定义以匹配后端

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 中的转换函数

Fix 2.2: 增强提案审批错误处理 10分钟

文件: IdentityChangeProposal.tsx

添加错误解析函数:

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

添加最后交互时间追踪:

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 命令:

#[tauri::command]
pub async fn heartbeat_record_interaction(agent_id: String) -> Result<(), String>

Phase 3: 修复 LOW 优先级问题(可选)

Fix 3.1: localStorage fallback 存储大小计算

文件: intelligence-client.ts

// 在 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 API 参数命名、类型转换、存储大小计算
App.tsx 周期性记忆统计同步
heartbeat.rs 缓存容错、空闲问候
intelligence-backend.ts 类型定义统一
IdentityChangeProposal.tsx 错误处理增强
lib.rs 注册新 Tauri 命令(如实现 Fix 2.3

验证方法

Fix 1.1 验证

# 启动应用,检查控制台
pnpm start:dev
# 观察 Tauri invoke 调用参数是否正确

Fix 1.2 验证

# 启动后等待 5 分钟,检查控制台
# 应看到 "[App] Memory stats synced (periodic)" 日志

Fix 1.3 验证

# 清除缓存后触发心跳
# 应看到 "记忆统计未同步" 告警

全量验证

# TypeScript 类型检查
pnpm tsc --noEmit

# 运行测试
pnpm vitest run

# 启动开发环境
pnpm start:dev

人工验证清单

  • 应用启动无错误
  • 心跳引擎正常初始化
  • 记忆统计同步正常(启动 + 周期)
  • 提案审批流程正常
  • 错误信息清晰可读