Files
zclaw_openfang/plans/nifty-wondering-kahn.md
iven b7f3d94950
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
fix(presentation): 修复 presentation 模块类型错误和语法问题
- 创建 types.ts 定义完整的类型系统
- 重写 DocumentRenderer.tsx 修复语法错误
- 重写 QuizRenderer.tsx 修复语法错误
- 重写 PresentationContainer.tsx 添加类型守卫
- 重写 TypeSwitcher.tsx 修复类型引用
- 更新 index.ts 移除不存在的 ChartRenderer 导出

审计结果:
- 类型检查: 通过
- 单元测试: 222 passed
- 构建: 成功
2026-03-26 17:19:28 +08:00

308 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 开箱即用的上下文记忆库方案 (简化版)
## 一、背景与目标
### 1.1 问题
当前 ZCLAW 的 OpenViking 集成需要用户独立安装 Python 包 (`pip install openviking`),不是开箱即用的。
### 1.2 关键发现 ⚠️
经过深入分析,发现 **zclaw-growth crate 已经实现了核心功能**
| 组件 | 文件 | 状态 |
|------|------|------|
| `VikingStorage` trait | `viking_adapter.rs` | ✅ 已实现 |
| `SqliteStorage` | `storage/sqlite.rs` | ⚠️ 只用内存缓存 |
| `SemanticScorer` (TF-IDF) | `retrieval/semantic.rs` | ✅ 已实现 |
| `MemoryExtractor` | `extractor.rs` | ✅ 已实现 |
| `MemoryRetriever` | `retriever.rs` | ✅ 已实现 |
| `PromptInjector` | `injector.rs` | ✅ 已实现 |
**问题**`SqliteStorage` 虽然名字是 SQLite但实际只用内存缓存`storage/sqlite.rs:96-99`)。
### 1.3 修订目标
- **完善现有实现**:让 `SqliteStorage` 真正持久化到 SQLite
- **集成 TF-IDF**:使用已有的 `SemanticScorer` 提供语义搜索
- **替换外部依赖**Tauri 命令使用 `SqliteStorage` 而非 Python 进程
- **无需 LanceDB**:现有 TF-IDF 方案已足够
## 二、简化方案
### 2.1 核心改动
| 改动 | 工作量 | 说明 |
|------|--------|------|
| 完善 `SqliteStorage` | 中 | 添加真正的 SQLite 持久化 |
| 集成 `SemanticScorer` | 小 | 替换简单的相似度计算 |
| 修改 `viking_commands.rs` | 中 | 使用 `SqliteStorage` 替代 Python 调用 |
| 删除 `viking_server.rs` | 小 | 不再需要服务器管理 |
### 2.2 架构对比
**当前架构** (需要外部 Python):
```
前端 → viking-client.ts → Tauri Commands → Python OpenViking 进程
```
**目标架构** (纯 Rust):
```
前端 → viking-client.ts → Tauri Commands → SqliteStorage (Rust)
→ SemanticScorer (TF-IDF)
→ ~/.zclaw/memories.db
```
## 三、架构设计
### 3.1 整体架构
```
┌─────────────────────────────────────────────────────────────────┐
│ ZCLAW Desktop (Tauri) │
│ │
│ ┌─────────────────┐ │
│ │ viking-client.ts│ (前端 API 保持不变) │
│ └────────┬────────┘ │
│ │ invoke() │
│ ┌────────▼────────────────────────────────────────────────────┐│
│ │ viking_commands.rs ││
│ │ (Tauri 命令层 - 接口不变,实现改为调用 zclaw-growth) ││
│ └────────┬────────────────────────────────────────────────────┘│
│ │ │
│ ┌────────▼────────────────────────────────────────────────────┐│
│ │ zclaw-growth (已存在) ││
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ ││
│ │ │SqliteStorage│ │SemanticScorer│ │ MemoryExtractor │ ││
│ │ │ (完善持久化)│ │ (TF-IDF) │ │ MemoryRetriever │ ││
│ │ └─────────────┘ └─────────────┘ │ PromptInjector │ ││
│ │ └─────────────────────┘ ││
│ └────────┬────────────────────────────────────────────────────┘│
│ │ │
│ ┌────────▼────────────────────────────────────────────────────┐│
│ │ 本地存储层 ││
│ │ ~/.zclaw/ ││
│ │ ├── memories.db (SQLite 持久化) ││
│ │ └── growth.json (成长指标) ││
│ └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
```
### 3.2 模块变更
| 模块 | 位置 | 变更 |
|------|------|------|
| `SqliteStorage` | `crates/zclaw-growth/src/storage/sqlite.rs` | **完善**:添加真正的 SQLite 持久化 |
| `viking_commands.rs` | `desktop/src-tauri/src/viking_commands.rs` | **修改**:使用 SqliteStorage |
| `viking_server.rs` | `desktop/src-tauri/src/viking_server.rs` | **删除**:不再需要 |
### 3.3 数据模型 (已存在)
```rust
// crates/zclaw-growth/src/types.rs
pub struct MemoryEntry {
pub uri: String, // agent://{agent_id}/{type}/{category}
pub memory_type: MemoryType,
pub content: String,
pub keywords: Vec<String>,
pub importance: u8, // 1-10
pub access_count: u32,
pub created_at: DateTime<Utc>,
pub last_accessed: DateTime<Utc>,
}
pub enum MemoryType {
Preference, // 用户偏好
Knowledge, // 知识积累
Experience, // 技能经验
Session, // 会话历史
}
```
## 四、接口设计
### 4.1 保持兼容的 Tauri 命令
| 命令 | 功能 | 变化 |
|------|------|------|
| `viking_status` | 检查状态 | 返回 `available: true` (始终可用) |
| `viking_add` | 添加资源 | 内部使用 SqliteStorage |
| `viking_find` | 语义搜索 | 使用 TF-IDF + SQLite FTS |
| `viking_grep` | 模式搜索 | 使用 SQLite FTS |
| `viking_ls` | 列出资源 | 从 SQLite 读取 |
| `viking_read` | 读取内容 | 从 SQLite 读取 |
| `viking_remove` | 删除资源 | 从 SQLite 删除 |
| `viking_tree` | 资源树 | 从 SQLite 构建 |
### 4.2 移除的命令
| 命令 | 原因 |
|------|------|
| `viking_server_start` | 无需服务器 |
| `viking_server_stop` | 无需服务器 |
| `viking_server_status` | 无需服务器 |
## 五、实施计划
### Phase 1: 完善 SqliteStorage (1-2 天)
**任务 1.1: 添加 sqlx 依赖**
```toml
# crates/zclaw-growth/Cargo.toml
[dependencies]
sqlx = { workspace = true, features = ["runtime-tokio", "sqlite"] }
```
**任务 1.2: 实现真正的 SQLite 持久化**
- 文件: `crates/zclaw-growth/src/storage/sqlite.rs`
- 改动:
```rust
pub struct SqliteStorage {
pool: SqlitePool, // 替换 RwLock<HashMap>
scorer: SemanticScorer, // 添加语义评分器
}
```
- 功能:
- `initialize_schema()` - 创建 memories 表和 FTS5 索引
- `store()` - 写入 SQLite
- `get()` - 从 SQLite 读取
- `find()` - 使用 SemanticScorer + FTS
**任务 1.3: 集成 SemanticScorer**
- 替换 `compute_similarity()` 简单实现
- 使用已有的 TF-IDF 算法
### Phase 2: 修改 Tauri 命令 (1 天)
**任务 2.1: 修改 viking_commands.rs**
```rust
// 替换
async fn viking_find(...) {
let cli = get_viking_cli_path()?;
let output = Command::new(&cli).arg("find")...
}
// 为
lazy_static! {
static ref STORAGE: SqliteStorage = ...;
}
async fn viking_find(...) {
STORAGE.find(query, options).await
}
```
**任务 2.2: 删除 viking_server.rs**
- 移除服务器管理相关命令
- 更新 `lib.rs` 移除模块引用
**任务 2.3: 初始化存储**
- 在 `lib.rs` 的 `run()` 函数中初始化 `SqliteStorage`
- 存储路径: `~/.zclaw/memories.db`
### Phase 3: 测试与验证 (1 天)
**任务 3.1: 单元测试**
- 完善 `SqliteStorage` 测试
- 测试持久化和恢复
**任务 3.2: 集成测试**
- 端到端测试: 前端 → Tauri → SqliteStorage
- 验证 `viking_find` 返回语义相关结果
**任务 3.3: 验收测试**
- 启动 Tauri 后无需配置即可使用
- 打包体积无显著增加
## 六、文件变更清单
### 修改文件
| 文件 | 变更 |
|------|------|
| `crates/zclaw-growth/src/storage/sqlite.rs` | 添加真正的 SQLite 持久化 |
| `crates/zclaw-growth/Cargo.toml` | 添加 sqlx 依赖 |
| `desktop/src-tauri/src/viking_commands.rs` | 使用 SqliteStorage |
| `desktop/src-tauri/src/lib.rs` | 移除 viking_server 模块,初始化存储 |
### 删除文件
| 文件 | 原因 |
|------|------|
| `desktop/src-tauri/src/viking_server.rs` | 不再需要服务器管理 |
### 保持不变
| 文件 | 原因 |
|------|------|
| `desktop/src/lib/viking-client.ts` | API 兼容 |
| `desktop/src/components/VikingPanel.tsx` | UI 不变 |
| `crates/zclaw-growth/src/viking_adapter.rs` | 接口不变 |
| `crates/zclaw-growth/src/retrieval/semantic.rs` | TF-IDF 已实现 |
## 七、风险与缓解
| 风险 | 影响 | 缓解措施 |
|------|------|----------|
| SQLite FTS5 中文支持 | 搜索质量 | 使用 `unicode61` tokenizer |
| TF-IDF 语义理解有限 | 搜索精度 | 可选:后续添加 embedding API |
| 数据迁移 | 用户数据丢失 | localStorage 降级保留 |
## 八、验收标准
- [ ] 启动 Tauri 后无需任何配置即可使用记忆功能
- [ ] `viking_status` 返回 `available: true`
- [ ] `viking_find` 返回语义相关结果(基于 TF-IDF
- [ ] 数据持久化到 `~/.zclaw/memories.db`
- [ ] 打包体积无显著增加(< 1MB
- [ ] 所有现有测试通过
- [ ] 前端 API (`viking-client.ts`) 无需修改
## 九、与现有设计文档的关系
本方案是对 `docs/superpowers/specs/2026-03-26-agent-growth-design.md` 的**简化实现**
| 设计文档要求 | 本方案实现 |
|-------------|-----------|
| OpenViking 作为完整记忆层 | SqliteStorage (实现 VikingStorage trait) |
| 语义搜索 | TF-IDF (SemanticScorer) |
| L0/L1/L2 分层 | 已有实现,保持不变 |
| 记忆提取 | 已有 MemoryExtractor保持不变 |
**核心差异**:设计文档说用 OpenViking Python 包,本方案用纯 Rust 实现替代,保持接口兼容。
## 十、对系统架构的影响分析
### 10.1 正面影响
| 影响 | 说明 |
|------|------|
| **消除外部依赖** | 不再需要 Python 环境 |
| **降低复杂度** | 移除进程管理代码 |
| **提高可靠性** | 无进程启动失败风险 |
| **减少打包体积** | 无需打包 Python |
### 10.2 潜在风险
| 风险 | 影响 | 缓解措施 |
|------|------|----------|
| TF-IDF 语义理解不如 embedding | 搜索精度降低 | 后续可选添加 embedding API |
| 大量记忆时性能下降 | 查询变慢 | 添加分页、索引优化 |
### 10.3 功能完整性
| 功能 | 原方案 (OpenViking) | 新方案 (SqliteStorage) |
|------|---------------------|------------------------|
| 存储记忆 | ✅ | ✅ |
| 语义搜索 | ✅ embedding | ⚠️ TF-IDF (可接受) |
| URI 寻址 | ✅ | ✅ |
| L0/L1/L2 分层 | ✅ | ✅ 已有实现 |
| 记忆提取 | ✅ | ✅ 已有实现 |
| 记忆检索 | ✅ | ✅ 已有实现 |
| Prompt 注入 | ✅ | ✅ 已有实现 |
### 10.4 结论
**推荐采用简化方案**
1. 工作量小3-4 天 vs 7+ 天)
2. 风险低(复用现有代码)
3. 满足"开箱即用"核心需求
4. 后续可渐进增强(添加 embedding