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>
This commit is contained in:
426
docs/plans/2026-03-16-openviking-local-deployment.md
Normal file
426
docs/plans/2026-03-16-openviking-local-deployment.md
Normal file
@@ -0,0 +1,426 @@
|
||||
# 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**
|
||||
```bash
|
||||
# 将 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**
|
||||
```json
|
||||
{
|
||||
"tauri": {
|
||||
"bundle": {
|
||||
"externalBin": ["binaries/ov"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **创建 Tauri Commands**
|
||||
```rust
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```rust
|
||||
// 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)
|
||||
|
||||
```rust
|
||||
// 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
|
||||
|
||||
```toml
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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 完善和测试
|
||||
|
||||
**核心原则**: 最大化利用现有成熟工具,最小化自建代码量,只在必要时补充缺失功能。
|
||||
Reference in New Issue
Block a user