Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
重构所有代码和文档中的项目名称,将OpenFang统一更新为ZCLAW。包括: - 配置文件中的项目名称 - 代码注释和文档引用 - 环境变量和路径 - 类型定义和接口名称 - 测试用例和模拟数据 同时优化部分代码结构,移除未使用的模块,并更新相关依赖项。
427 lines
16 KiB
Markdown
427 lines
16 KiB
Markdown
# ZCLAW OpenViking 深度集成方案
|
||
|
||
## Context
|
||
|
||
**背景**:ZCLAW 项目基于 ZCLAW 定制开发,目标是结合 ZCLAW、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 完善和测试
|
||
|
||
**核心原则**: 最大化利用现有成熟工具,最小化自建代码量,只在必要时补充缺失功能。
|