Files
zclaw_openfang/docs/plans/2026-03-16-openviking-local-deployment.md
iven 0eb30c0531 docs: reorganize documentation structure
- Create docs/README.md as documentation index
- Add WORK_SUMMARY_2026-03-16.md for today's work
- Move test reports to docs/test-reports/
- Move completed plans to docs/archive/completed-plans/
- Move research reports to docs/archive/research-reports/
- Move technical reference to docs/knowledge-base/
- Move all plans from root plans/ to docs/plans/

New structure:
docs/
├── README.md                         # Documentation index
├── DEVELOPMENT.md                    # Development guide
├── OPENVIKING_INTEGRATION.md         # OpenViking integration
├── USER_MANUAL.md                    # User manual
├── ZCLAW_AGENT_INTELLIGENCE_EVOLUTION.md
├── archive/                          # Archived documents
├── knowledge-base/                   # Technical knowledge
├── plans/                            # Execution plans
└── test-reports/                     # Test reports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 08:21:01 +08:00

16 KiB
Raw Blame History

ZCLAW OpenViking 深度集成方案

Context

背景ZCLAW 项目基于 OpenFang 定制开发,目标是结合 OpenClaw、NanoClaw、ZeroClaw 等系统的优点。当前 Agent 智能层已超前完成Phase 1-3 完成, Phase 4 部分完成),但 OpenViking 集成依赖外部 Python 服务,用户安装繁琐。

问题:如何深度集成 OpenViking避免 Python 依赖,实现无感安装体验?

目标:以 OpenViking Rust CLI (ov) 为核心,通过 Tauri sidecar 集成让记忆系统成为原生组件。CLI 缺失的功能再自行开发补充。


关键决策总结

基于头脑风暴讨论,确定以下技术决策:

决策点 选择 理由
集成方式 OpenViking Rust CLI + 自建补充 利用成熟工具,减少开发量,缺失功能自行补充
记忆存储 CLI 内置 SQLite + sqlite-vec CLI 已实现,无需重复开发
Embedding 模型 doubao-embedding-vision 中文效果优秀,火山引擎生态
记忆提取 LLM 提取 对话结束后调用 LLM 分析并提取
部署方式 Tauri Sidecar CLI 作为可执行文件随应用分发

Architecture Design

┌─────────────────────────────────────────────────────────────────┐
│                    ZCLAW Desktop (Tauri + React)                │
│                                                                 │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                    React UI Layer                           │ │
│  │  ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌──────────────┐ │ │
│  │  │ ChatArea  │ │MemoryPanel│ │SwarmPanel│ │ SkillMarket │ │ │
│  │  └────┬─────┘ └────┬─────┘ └─────┬─────┘└──────┬───────┘ │ │
│  └───────────┼────────────┼─────────────┼───────────────┼─────┘ │
│              ▼            ▼             ▼               ▼       │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │            TypeScript Integration Layer                     │ │
│  │  ┌──────────────────────────────────────────────────────┐  │ │
│  │  │ VikingAdapter (已存在,保持兼容)                        │  │ │
│  │  └──────────────────────────────────────────────────────┘  │ │
│  └──────────────────────────┬─────────────────────────────────┘ │
│                             │                                   │
│  ┌──────────────────────────▼─────────────────────────────────┐ │
│  │            Tauri Command Layer (Rust)                       │ │
│  │  ┌────────────────────────────────────────────────────────┐│ │
│  │  │ SidecarWrapper: 调用 `ov` CLI                           ││ │
│  │  │ - invoke('viking_add', ...)  → ov add                  ││ │
│  │  │ - invoke('viking_find', ...) → ov find                 ││ │
│  │  │ - invoke('viking_grep', ...) → ov grep                 ││ │
│  │  └────────────────────────────────────────────────────────┘│ │
│  │  ┌────────────────────────────────────────────────────────┐│ │
│  │  │ SupplementalModule: CLI 缺失功能补充                     ││ │
│  │  │ - SessionExtractor (LLM 记忆提取)                       ││ │
│  │  │ - EmbeddingService (doubao API 封装)                    ││ │
│  │  │ - ContextBuilder (L0/L1/L2 分层加载)                    ││ │
│  │  └────────────────────────────────────────────────────────┘│ │
│  └─────────────────────────────────────────────────────────────┘ │
│                             │                                   │
│  ┌──────────────────────────▼─────────────────────────────────┐ │
│  │                    Storage Layer                            │ │
│  │  ┌──────────────────┐ ┌──────────────────────────────────┐ │ │
│  │  │ OpenViking CLI   │ │ AppData (配置)                    │ │ │
│  │  │ ~/.viking/       │ │ ~/.zclaw/config.toml              │ │ │
│  │  │ - SQLite + vec   │ │                                   │ │ │
│  │  │ - 向量索引        │ │                                   │ │ │
│  │  └──────────────────┘ └──────────────────────────────────┘ │ │
│  └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

OpenViking Rust CLI 能力分析

CLI 已实现功能 (直接使用)

命令 功能 状态
ov add <uri> 添加资源到索引 可用
ov find <query> 语义搜索 可用
ov grep <pattern> 正则搜索 可用
ov ls <path> 列出资源 可用
ov tree <path> 目录树 可用
ov chat 交互式对话 可用

CLI 缺失功能 (需要自建)

功能 说明 优先级
Session Extraction 对话后 LLM 提取记忆
L0/L1/L2 分层加载 Token 优化上下文构建
Embedding 批量生成 doubao API 封装
记忆老化/清理 低重要性记忆自动清理
多 Agent 隔离 agent_id 维度隔离

Implementation Phases

Phase 1: Sidecar 集成 (Week 1)

Goal: 将 OpenViking CLI 集成为 Tauri sidecar

Steps

  1. 下载并嵌入 CLI

    # 将 ov 二进制放入 src-tauri/binaries/
    # Windows: ov-x86_64-pc-windows-msvc.exe
    # macOS: ov-x86_64-apple-darwin
    # Linux: ov-x86_64-unknown-linux-gnu
    
  2. 配置 tauri.conf.json

    {
      "tauri": {
        "bundle": {
          "externalBin": ["binaries/ov"]
        }
      }
    }
    
  3. 创建 Tauri Commands

    // src-tauri/src/viking_commands.rs
    
    #[tauri::command]
    pub async fn viking_add(uri: String, content: String) -> Result<String, String> {
        let sidecar = Command::new_sidecar("ov")
            .map_err(|e| e.to_string())?;
        let output = sidecar
            .args(["add", &uri])
            .output()
            .await
            .map_err(|e| e.to_string())?;
        Ok(String::from_utf8_lossy(&output.stdout).to_string())
    }
    
    #[tauri::command]
    pub async fn viking_find(query: String, limit: usize) -> Result<Vec<FindResult>, String> {
        let sidecar = Command::new_sidecar("ov")
            .map_err(|e| e.to_string())?;
        let output = sidecar
            .args(["find", "--json", &query, "--limit", &limit.to_string()])
            .output()
            .await
            .map_err(|e| e.to_string())?;
    
        serde_json::from_slice(&output.stdout)
            .map_err(|e| e.to_string())
    }
    

Files to Create

File Purpose
src-tauri/src/viking_commands.rs Tauri 命令封装
src-tauri/binaries/ov-* Sidecar 二进制

Files to Modify

File Changes
src-tauri/src/lib.rs 注册 viking 模块
src-tauri/tauri.conf.json 添加 externalBin 配置
desktop/src/lib/viking-adapter.ts 添加 invoke() 调用

Phase 2: TypeScript 适配层 (Week 1-2)

Goal: 更新 VikingAdapter 使用 Tauri 命令

Key Changes

// desktop/src/lib/viking-adapter.ts

import { invoke } from '@tauri-apps/api/tauri';

export class VikingAdapter {
  private mode: 'sidecar' | 'remote' = 'sidecar';

  async addResource(uri: string, content: string): Promise<void> {
    if (this.mode === 'sidecar') {
      await invoke('viking_add', { uri, content });
    } else {
      // Remote fallback
      await this.httpClient.addResource(uri, content);
    }
  }

  async find(query: string, options?: FindOptions): Promise<FindResult[]> {
    if (this.mode === 'sidecar') {
      return await invoke('viking_find', {
        query,
        limit: options?.limit || 10
      });
    } else {
      return this.httpClient.find(query, options);
    }
  }
}

Phase 3: 补充模块开发 (Week 2-3)

Goal: 实现 CLI 缺失的功能

3.1 Session Extractor

// src-tauri/src/memory/extractor.rs

pub struct SessionExtractor {
    llm_client: LlmClient,
}

impl SessionExtractor {
    /// Extract memories from conversation
    pub async fn extract(
        &self,
        messages: Vec<ChatMessage>,
        agent_id: &str,
    ) -> Result<Vec<ExtractedMemory>, Error> {
        let prompt = self.build_extraction_prompt(&messages);
        let response = self.llm_client.complete(&prompt).await?;
        self.parse_extraction(&response, agent_id)
    }
}

3.2 Context Builder (L0/L1/L2)

// src-tauri/src/memory/context_builder.rs

pub struct ContextBuilder {
    viking: VikingSidecar,
}

impl ContextBuilder {
    /// Build layered context for token efficiency
    pub async fn build_context(
        &self,
        query: &str,
        agent_id: &str,
        max_tokens: usize,
    ) -> Result<EnhancedContext, Error> {
        // L0: Quick scan - top 50 by similarity
        let l0_results = self.viking.find(query, 50).await?;

        // L1: Load overview for top 10
        let l1_items = self.load_overviews(&l0_results[..10]).await?;

        // L2: Full content for top 3
        let l2_items = self.load_full_content(&l0_results[..3]).await?;

        Ok(EnhancedContext { l1_items, l2_items })
    }
}

Files to Create

File Purpose
src-tauri/src/memory/mod.rs 模块入口
src-tauri/src/memory/extractor.rs LLM 记忆提取
src-tauri/src/memory/context_builder.rs L0/L1/L2 分层加载
src-tauri/src/llm/client.rs doubao API 客户端

Phase 4: UI 集成 (Week 3-4)

Goal: 完善记忆面板 UI

Files to Modify

File Changes
desktop/src/components/MemoryPanel.tsx 集成 sidecar 模式
desktop/src/components/RetrievalTrace.tsx 显示 L0/L1/L2 检索轨迹
desktop/src/store/chatStore.ts 使用新的 VikingAdapter

Critical Files

Existing Files (Reuse)

File Path Purpose
VikingAdapter desktop/src/lib/viking-adapter.ts 保持兼容,添加 sidecar 模式
VikingHttpClient desktop/src/lib/viking-client.ts 远程模式时使用
AgentMemory desktop/src/lib/agent-memory.ts 现有记忆接口
MemoryPanel desktop/src/components/MemoryPanel.tsx 现有 UI

New Files (Create)

File Path Purpose
VikingCommands src-tauri/src/viking_commands.rs Sidecar 命令封装
SessionExtractor src-tauri/src/memory/extractor.rs LLM 提取 (CLI 缺失)
ContextBuilder src-tauri/src/memory/context_builder.rs 分层加载 (CLI 缺失)
LlmClient src-tauri/src/llm/client.rs doubao API 封装

Dependencies to Add

# src-tauri/Cargo.toml
[dependencies]
tauri = { version = "2", features = ["process-command-api"] }
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.11" }  # For LLM API calls
serde = { version = "1", features = ["derive"] }
serde_json = "1"

Verification Plan

Unit Tests

# Run Rust tests
cargo test --manifest-path=src-tauri/Cargo.toml

# Run TypeScript tests
pnpm vitest run tests/desktop/memory*.test.ts

Integration Tests

  1. Sidecar 启动: CLI 能正确作为 sidecar 运行
  2. Memory Save/Load: 通过 Tauri 命令保存和检索记忆
  3. Vector Search: 语义搜索返回相关结果
  4. Session Extraction: 对话结束后正确提取记忆
  5. Context Building: L0/L1/L2 分层加载正常工作
  6. UI Integration: MemoryPanel 正确显示数据

Manual Testing

  1. 启动应用,验证 CLI sidecar 自动启动
  2. 发送消息,检查记忆是否保存
  3. 发送新消息,验证 Agent 能回忆之前的信息
  4. 测试记忆搜索功能
  5. 验证无 Python 依赖

Migration Path

From Current State

Current:                              Target:

viking-client.ts ─────────────► Tauri Command
(HTTP to Python server)            (Sidecar wrapper)
     │
     ▼
viking-adapter.ts ──────────────► Dual mode: sidecar + remote fallback

Data Compatibility

  • OpenViking CLI 使用 ~/.viking/ 目录存储数据
  • 与 Python Server 版本数据格式兼容
  • 可无缝迁移现有数据

Success Criteria

  • OpenViking CLI 作为 sidecar 正确运行
  • Tauri 命令可调用 CLI 功能
  • 记忆保存和检索功能正常
  • 语义搜索返回相关结果
  • LLM 记忆提取正常工作 (自建模块)
  • L0/L1/L2 分层加载正常工作 (自建模块)
  • MemoryPanel UI 正确显示
  • 所有测试通过
  • 无需 Python 依赖

Risks and Mitigations

Risk Mitigation
CLI 二进制兼容性 提供多平台预编译版本
CLI 功能不足 自建补充模块填补空白
Embedding API 限流 实现本地缓存
LLM 提取失败 保留规则提取作为 fallback
Sidecar 启动失败 优雅降级到远程模式

Timeline

Week Phase Deliverables
1 Sidecar 集成 CLI 嵌入 + Tauri 命令 + TypeScript 适配
2 补充模块 SessionExtractor + ContextBuilder
3 LLM 集成 doubao API 客户端 + 提取逻辑
4 UI 集成 MemoryPanel + RetrievalTrace
5 测试完善 集成测试 + 文档

开发策略总结

  1. Phase 1: 直接集成 OpenViking Rust CLI 作为 sidecar
  2. Phase 2: 检测 CLI 功能覆盖度
  3. Phase 3: 自行开发 CLI 缺失的功能 (Session Extraction, Context Builder)
  4. Phase 4: UI 完善和测试

核心原则: 最大化利用现有成熟工具,最小化自建代码量,只在必要时补充缺失功能。