fix(presentation): 修复 presentation 模块类型错误和语法问题
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

- 创建 types.ts 定义完整的类型系统
- 重写 DocumentRenderer.tsx 修复语法错误
- 重写 QuizRenderer.tsx 修复语法错误
- 重写 PresentationContainer.tsx 添加类型守卫
- 重写 TypeSwitcher.tsx 修复类型引用
- 更新 index.ts 移除不存在的 ChartRenderer 导出

审计结果:
- 类型检查: 通过
- 单元测试: 222 passed
- 构建: 成功
This commit is contained in:
iven
2026-03-26 17:19:28 +08:00
parent d0c6319fc1
commit b7f3d94950
71 changed files with 15896 additions and 1133 deletions

View File

@@ -0,0 +1,307 @@
# 开箱即用的上下文记忆库方案 (简化版)
## 一、背景与目标
### 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