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,327 @@
# ZCLAW Agent 成长功能设计方案
## 一、上下文
### 1.1 背景与目标
**问题**ZCLAW 的学习系统存在**前后端分离问题**——前端有完整的学习逻辑,但与后端执行系统完全隔离,导致 Agent 无法真正"成长"。
**目标**:设计并实现完整的 Agent 成长功能,让 Agent 像个人管家一样持续学习和进化。
### 1.2 需求总结
| 维度 | 决策 |
|------|------|
| 成长维度 | 偏好记忆 + 知识积累 + 技能掌握(全部) |
| 整合策略 | 完全后端化Rust 重写学习系统 |
| 存储架构 | OpenViking 作为完整记忆层 |
| 学习触发 | 对话后自动 + 用户显式触发 |
| 行为影响 | 智能检索 + 动态注入Token 预算控制) |
---
## 二、系统现状分析
### 2.1 Agent 核心架构
| 组件 | 位置 | 职责 |
|------|------|------|
| AgentConfig | `crates/zclaw-types/src/agent.rs` | Agent 静态配置 |
| AgentRegistry | `crates/zclaw-kernel/src/registry.rs` | 运行时注册管理 |
| AgentLoop | `crates/zclaw-runtime/src/loop_runner.rs` | LLM 执行循环 |
| Kernel | `crates/zclaw-kernel/src/kernel.rs` | 协调层 |
**关键问题**`AgentConfig` 是静态配置,没有成长相关字段。
### 2.2 记忆系统现状
| 能力 | 状态 | 说明 |
|------|------|------|
| 短期记忆 (Session) | ✅ 已实现 | SQLite sessions + messages 表 |
| KV 存储 | ✅ 已实现 | 未被学习系统使用 |
| 长期记忆检索 | ❌ 缺失 | 历史会话无法智能召回 |
| 语义检索 | ❌ 缺失 | 无向量嵌入或相似度搜索 |
| 智能摘要 | ❌ 缺失 | compact() 仅简单丢弃旧消息 |
### 2.3 现有资源
**OpenViking**(字节跳动开源的上下文数据库):
- 位置:`docs/features/03-context-database/00-openviking-integration.md`
- 能力L0/L1/L2 分层存储、语义搜索、本地部署
- 状态:已集成,成熟度 L4
---
## 三、设计方案
### 3.1 整体架构
```
┌─────────────────────────────────────────────────────────────────┐
│ ZCLAW Agent 成长系统 │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ zclaw-growth (新 Crate) │ │
│ │ ────────────────────────────────────────────────────── │ │
│ │ • MemoryExtractor - 从对话中提取偏好/知识/经验 │ │
│ │ • MemoryRetriever - 语义检索相关记忆 │ │
│ │ • PromptInjector - 动态构建 system_prompt │ │
│ │ • GrowthTracker - 追踪成长指标和演化 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ OpenViking (记忆层) │ │
│ │ ────────────────────────────────────────────────────── │ │
│ │ URI 结构: │ │
│ │ • agent://{id}/preferences/{category} - 用户偏好 │ │
│ │ • agent://{id}/knowledge/{domain} - 知识积累 │ │
│ │ • agent://{id}/experience/{skill} - 技能经验 │ │
│ │ • agent://{id}/sessions/{sid} - 对话历史 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ zclaw-runtime (修改) │ │
│ │ ────────────────────────────────────────────────────── │ │
│ │ AgentLoop 集成: │ │
│ │ 1. 对话前 → MemoryRetriever 检索相关记忆 │ │
│ │ 2. 构建请求 → PromptInjector 注入记忆 │ │
│ │ 3. 对话后 → MemoryExtractor 提取新记忆 │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### 3.2 数据流
```
用户输入
┌─────────────────────────────────────────┐
│ 1. 记忆检索 │
│ • 用当前输入查询 OpenViking │
│ • 召回 Top-5 相关记忆 │
│ • Token 预算控制 (500 tokens) │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 2. Prompt 构建 │
│ system_prompt = base + │
│ "## 用户偏好\n" + preferences + │
│ "## 相关知识\n" + knowledge │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 3. LLM 对话 │
│ • 正常的 AgentLoop 执行 │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 4. 记忆提取 (对话后) │
│ • 分析对话内容 │
│ • 提取偏好/知识/经验 │
│ • 写入 OpenViking (L0/L1/L2) │
└─────────────────────────────────────────┘
```
### 3.3 OpenViking URI 结构
```
agent://{agent_id}/
├── preferences/
│ ├── communication-style # 沟通风格偏好
│ ├── response-format # 回复格式偏好
│ ├── language-preference # 语言偏好
│ └── topic-interests # 主题兴趣
├── knowledge/
│ ├── user-facts # 用户相关事实
│ ├── domain-knowledge # 领域知识
│ └── lessons-learned # 经验教训
├── experience/
│ ├── skill-{id} # 技能使用经验
│ └── hand-{id} # Hand 使用经验
└── sessions/
└── {session_id}/ # 对话历史
├── raw # 原始对话 (L0)
├── summary # 摘要 (L1)
└── keywords # 关键词 (L2)
```
---
## 四、详细设计
### 4.1 新 Crate 结构
```
crates/zclaw-growth/
├── Cargo.toml
├── src/
│ ├── lib.rs # 入口和公共 API
│ ├── extractor.rs # 记忆提取器
│ ├── retriever.rs # 记忆检索器
│ ├── injector.rs # Prompt 注入器
│ ├── tracker.rs # 成长追踪器
│ ├── types.rs # 类型定义
│ └── viking_adapter.rs # OpenViking 适配器
```
### 4.2 核心数据结构
```rust
// types.rs
/// 记忆类型
pub enum MemoryType {
Preference, // 偏好
Knowledge, // 知识
Experience, // 经验
Session, // 对话
}
/// 记忆条目
pub struct MemoryEntry {
pub uri: String,
pub memory_type: MemoryType,
pub content: String,
pub keywords: Vec<String>,
pub importance: u8,
pub access_count: u32,
pub created_at: DateTime<Utc>,
pub last_accessed: DateTime<Utc>,
}
/// 检索配置
pub struct RetrievalConfig {
pub max_tokens: usize, // 默认 500
pub preference_budget: usize, // 默认 200
pub knowledge_budget: usize, // 默认 200
pub experience_budget: usize, // 默认 100
pub min_similarity: f32, // 默认 0.7
pub max_results: usize, // 默认 10
}
```
### 4.3 核心接口
```rust
// extractor.rs
pub struct MemoryExtractor {
llm_driver: Arc<dyn LlmDriver>,
}
impl MemoryExtractor {
pub async fn extract(
&self,
messages: &[Message],
config: &ExtractionConfig,
) -> Result<Vec<ExtractedMemory>>;
}
// retriever.rs
pub struct MemoryRetriever {
viking: Arc<VikingAdapter>,
}
impl MemoryRetriever {
pub async fn retrieve(
&self,
agent_id: &AgentId,
query: &str,
config: &RetrievalConfig,
) -> Result<RetrievalResult>;
}
// injector.rs
pub struct PromptInjector {
config: RetrievalConfig,
}
impl PromptInjector {
pub fn inject(
&self,
base_prompt: &str,
memories: &RetrievalResult,
) -> String;
}
```
### 4.4 AgentLoop 集成
修改 `crates/zclaw-runtime/src/loop_runner.rs`
```rust
pub struct AgentLoop {
// ... 现有字段
memory_retriever: Arc<MemoryRetriever>, // 新增
memory_extractor: Arc<MemoryExtractor>, // 新增
prompt_injector: PromptInjector, // 新增
growth_enabled: bool, // 新增
}
```
### 4.5 前端变化
- 新增组件:`desktop/src/components/GrowthPanel.tsx`
- 修改 Store`desktop/src/store/agentStore.ts` 添加成长状态
---
## 五、执行计划
### 5.1 知识库文档(本次任务)
创建以下文档到 `docs/knowledge-base/`
1. **agent-growth-analysis.md** - Agent 成长功能深度分析
2. **system-architecture-deep-dive.md** - 系统架构深度剖析
3. **growth-improvement-roadmap.md** - 成长功能改进路线图
### 5.2 实现阶段(后续任务)
| 阶段 | 内容 | 预估 |
|------|------|------|
| Phase 1 | zclaw-growth crate 骨架 + 类型定义 | 1-2 天 |
| Phase 2 | MemoryRetriever + VikingAdapter | 2-3 天 |
| Phase 3 | PromptInjector + AgentLoop 集成 | 2-3 天 |
| Phase 4 | MemoryExtractor (LLM 驱动) | 3-4 天 |
| Phase 5 | 前端 UI + 状态管理 | 2-3 天 |
| Phase 6 | 测试 + 优化 | 2-3 天 |
---
## 六、关键文件路径
### 核心类型
- `crates/zclaw-types/src/agent.rs` - AgentConfig
- `crates/zclaw-types/src/message.rs` - Message
- `crates/zclaw-types/src/id.rs` - AgentId, SessionId
### 存储层
- `crates/zclaw-memory/src/store.rs` - MemoryStore
- `crates/zclaw-memory/src/schema.rs` - SQLite Schema
### 运行时
- `crates/zclaw-runtime/src/loop_runner.rs` - AgentLoop
### OpenViking 集成
- `desktop/src/lib/viking-client.ts` - 前端客户端
- `desktop/src-tauri/src/viking_commands.rs` - Tauri 命令
- `docs/features/03-context-database/00-openviking-integration.md` - 文档
### 前端学习系统(将被后端化)
- `desktop/src/lib/active-learning.ts`
- `desktop/src/lib/memory-extractor.ts`
- `desktop/src/store/activeLearningStore.ts`
---
## 七、验证方式
1. **文档完整性**:确保所有章节内容完整,代码路径准确
2. **架构验证**:通过阅读代码确认流程图准确性
3. **可行性评估**:评估技术方案的实现难度和依赖

View File

@@ -0,0 +1,712 @@
# Pipeline 2.0 重构计划
> **目标**: 学习 OpenMAIC 输入→产出→展示流程,重构 ZCLAW Pipeline 系统
> **日期**: 2026-03-26
---
## 一、背景与问题
### 1.1 当前痛点
| 痛点 | 描述 |
|------|------|
| **输入体验差** | YAML 配置繁琐,不够自然语言化 |
| **输出展示单一** | 结果只是文本/文件,缺少丰富的交互式展示 |
### 1.2 学习目标
OpenMAIC 的核心流程:
```
输入 (自然语言/文档) → 生成 (多阶段 Pipeline) → 展示 (幻灯片/白板/测验/图表)
```
### 1.3 设计决策
| 决策点 | 用户选择 |
|--------|---------|
| **输入模式** | 混合式 - 简单任务对话,复杂任务表单 |
| **展示优先级** | P0: 图表+测验 → P1: 幻灯片+白板 |
| **展示决策** | LLM 推荐 + 用户可切换 |
---
## 二、整体架构
```
┌─────────────────────────────────────────────────────────────────┐
│ 用户界面层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 💬 对话入口 │ │ 📋 快捷入口 │ │ ⚙️ 高级入口 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────┬───────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 🧠 智能入口层 (Intent Router) │
│ │
│ 职责: │
│ • 意图识别 - 理解用户想做什么 │
│ • Pipeline 匹配 - 找到合适的 Pipeline │
│ • 模式决策 - conversation / form / hybrid │
│ • 参数收集 - 对话收集或表单填充 │
└─────────────────────────────┬───────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ ⚡ 执行引擎层 (Engine v2) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ StageRunner │ │ ParallelMap │ │ Conditional │ │
│ │ (顺序阶段) │ │ (并行映射) │ │ (条件分支) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ 能力调用LLM / Skill / Hand / Tool │
└─────────────────────────────┬───────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 🎨 智能展示层 (Presentation) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 展示分析器 │ │ 渲染器注册表 │ │ 切换控制器 │ │
│ │ (LLM 推荐) │ │ (多类型) │ │ (用户干预) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ 渲染器Slideshow / Quiz / Chart / Whiteboard / Document │
└─────────────────────────────┬───────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 数据持久层 │
│ │
│ • 执行历史 • 生成结果 • 用户偏好 • 模板缓存 │
└─────────────────────────────────────────────────────────────────┘
```
---
## 三、Pipeline 2.0 格式设计
### 3.1 新格式示例
```yaml
# pipelines/education/course-generator.yaml
apiVersion: zclaw/v2
kind: Pipeline
metadata:
name: course-generator
displayName: 课程生成器
description: 根据主题生成完整的互动课程
category: education
icon: 🎓
# 触发条件 - 支持自然语言匹配
trigger:
patterns:
- "帮我做*课程"
- "生成*教程"
- "我想学习{topic}"
keywords: [课程, 教程, 学习, 培训]
# 输入模式决策
input:
mode: auto # conversation | form | auto
# auto 模式:简单任务用对话,复杂任务用表单
complexity_threshold: 3 # 参数超过3个用表单
# 参数定义
params:
- name: topic
type: string
required: true
label: 课程主题
description: 你想学习什么内容?
placeholder: 例如机器学习基础、Python 入门
- name: level
type: select
label: 难度级别
options: [入门, 中级, 高级]
default: 入门
- name: duration
type: number
label: 预计时长(分钟)
default: 30
# 生成流程
stages:
- id: outline
type: llm
description: 生成课程大纲
prompt: |
为"{params.topic}"创建一个{params.level}级别的课程大纲。
预计学习时长:{params.duration}分钟。
输出 JSON 格式:
{
"title": "课程标题",
"sections": [
{"id": "s1", "title": "章节标题", "duration": 10}
]
}
output_schema: outline_schema
- id: content
type: parallel
description: 并行生成各章节内容
each: "${stages.outline.sections}"
stage:
type: llm
prompt: |
为章节"${item.title}"生成详细内容。
包含:讲解内容、示例、互动问题。
output_schema: section_schema
- id: assemble
type: compose
description: 组装完整课程
template: |
{
"title": "${stages.outline.title}",
"sections": ${stages.content},
"metadata": {
"level": "${params.level}",
"duration": ${params.duration}
}
}
# 输出定义
output:
type: dynamic # LLM 决定展示方式
allow_switch: true # 用户可切换
supported_types:
- slideshow # 幻灯片
- quiz # 测验
- document # 文档
- whiteboard # 白板
default_type: slideshow
```
### 3.2 格式对比
| 特性 | Pipeline v1 | Pipeline v2 |
|------|-------------|-------------|
| **触发方式** | 手动选择 | 自然语言匹配 |
| **输入模式** | 固定表单 | 对话/表单/自动 |
| **执行流程** | steps 数组 | stages + 类型 |
| **输出类型** | 文本/文件 | 动态展示组件 |
| **并行支持** | parallel action | parallel stage |
| **条件分支** | condition action | conditional stage |
---
## 四、智能入口层设计
### 4.1 触发器定义格式
```yaml
# Pipeline 中的 trigger 定义
trigger:
# 快速匹配 - 关键词
keywords: [课程, 教程, 学习, 培训]
# 快速匹配 - 正则模式
patterns:
- "帮我做*课程"
- "生成*教程"
- "我想学习{topic}"
# 语义匹配提示(用于 LLM 理解)
description: "根据用户主题生成完整的互动课程内容"
# 示例(帮助 LLM 匹配)
examples:
- "帮我做一个 Python 入门课程"
- "生成机器学习基础教程"
```
### 4.2 意图路由流程
```rust
pub async fn route(user_input: &str) -> RouteResult {
// Step 1: 快速匹配 (本地,< 10ms)
if let Some(pipeline) = quick_match(user_input) {
return prepare(pipeline, extracted_params);
}
// Step 2: 语义匹配 (LLM, ~200ms)
let intent = llm.analyze_intent(user_input).await;
let matched = semantic_match(&intent);
// Step 3: 模式决策
let mode = decide_mode(&matched);
RouteResult {
pipeline_id: matched.id,
mode, // conversation | form
params: intent.extracted_params,
confidence: intent.confidence,
}
}
```
### 4.3 参数收集模式
**对话模式** (简单任务,参数 ≤ 3):
```
用户: 帮我做一个 Python 入门课程
系统: 好的!课程预计多长时间学习?(默认 30 分钟)
用户: 1 小时吧
系统: 明白了,开始生成...
```
**表单模式** (复杂任务,参数 > 3):
```
系统检测到 Pipeline 有 5 个参数,自动显示表单:
┌─────────────────────────────────┐
│ 📚 课程生成器 │
├─────────────────────────────────┤
│ 课程主题: [Python 入门________] │
│ 难度级别: [▼ 入门] │
│ 预计时长: [60] 分钟 │
│ 目标受众: [________________] │
│ 特殊要求: [________________] │
│ │
│ [开始生成] │
└─────────────────────────────────┘
```
---
## 五、执行引擎层设计
### 5.1 Stage 类型体系
```rust
pub enum StageType {
/// LLM 生成阶段
Llm {
prompt: String, // 支持变量插值 {params.topic}
model: Option<String>, // 可选模型覆盖
temperature: Option<f32>,
output_schema: Option<JsonSchema>, // 结构化输出
},
/// 并行执行 - 遍历数组,每个元素执行子阶段
Parallel {
each: Expression, // 如 "${stages.outline.sections}"
stage: Box<StageType>, // 子阶段模板
max_workers: usize, // 并发数限制 (默认 3)
},
/// 顺序子阶段
Sequential {
stages: Vec<StageType>,
},
/// 条件分支
Conditional {
condition: Expression, // 如 "${params.level} == '高级'"
branches: HashMap<String, StageType>,
default: Option<Box<StageType>>,
},
/// 组合结果 - 模板拼接
Compose {
template: String, // JSON 模板
},
/// 调用 Skill
Skill {
skill_id: String,
input: HashMap<String, Expression>,
},
/// 调用 Hand
Hand {
hand_id: String,
action: String,
params: HashMap<String, Expression>,
},
}
```
### 5.2 执行上下文
```rust
pub struct ExecutionContext {
// 输入参数 (来自用户)
params: HashMap<String, Value>,
// 阶段输出 (累积)
stages: HashMap<String, Value>,
// 循环上下文 (Parallel 内部)
loop_context: Option<LoopContext>,
// 变量 (中间计算)
vars: HashMap<String, Value>,
// 执行状态
status: ExecutionStatus,
current_stage: Option<String>,
progress: f32,
}
pub struct LoopContext {
item: Value, // 当前元素
index: usize, // 索引
array: Vec<Value>,// 原数组
}
```
### 5.3 表达式系统
```yaml
# 支持的表达式语法
"${params.topic}" # 参数引用
"${stages.outline.sections}" # 阶段输出引用
"${item.title}" # 循环元素
"${index}" # 循环索引
"${vars.customVar}" # 变量引用
```
### 5.4 执行流程示例
```yaml
# 课程生成 Pipeline 执行流程
# Stage 1: outline (Llm)
输入: { params: { topic: "Python", level: "入门" } }
输出: { stages.outline: { title: "...", sections: [...] } }
# Stage 2: content (Parallel)
遍历: stages.outline.sections (假设 5 个章节)
并发: 3 个 worker
每个执行: Llm 生成章节内容
输出: { stages.content: [{...}, {...}, ...] }
# Stage 3: assemble (Compose)
模板: 组装完整课程 JSON
输出: 最终结果
```
### 5.5 进度回调
```rust
pub enum ExecutionEvent {
StageStart { stage_id: String },
StageProgress { stage_id: String, progress: f32 },
StageComplete { stage_id: String, output: Value },
ParallelProgress { completed: usize, total: usize },
Error { stage_id: String, message: String },
}
```
---
## 六、智能展示层设计
### 6.1 核心架构
```
Pipeline 执行结果
┌─────────────────────────────────────┐
│ Presentation Analyzer │
│ │
│ 1. 结构检测 (快速路径, < 5ms) │
│ 2. LLM 分析 (语义理解, ~300ms) │
│ 3. 推荐排序 (置信度排序) │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Renderer Registry │
│ │
│ • Slideshow (幻灯片) │
│ • Quiz (测验) │
│ • Chart (图表) │
│ • Document (文档) │
│ • Whiteboard (白板) │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Type Switcher │
│ │
│ 当前: [📊 图表] [📝 文档] [🎓 测验] │
│ 点击可切换展示方式 │
└─────────────────────────────────────┘
```
### 6.2 结构检测规则
```typescript
// 快速路径 - 基于数据结构自动判断
const detectionRules = [
// 幻灯片: 有 slides 数组
{
type: 'slideshow',
test: (data) => Array.isArray(data.slides) ||
(Array.isArray(data.sections) && data.sections.every(s => s.title && s.content))
},
// 测验: 有 quiz.questions 或 questions 数组
{
type: 'quiz',
test: (data) => data.quiz?.questions ||
(Array.isArray(data.questions) && data.questions[0]?.options)
},
// 图表: 有 chart/data 数组且元素是数值型
{
type: 'chart',
test: (data) => data.chart ||
(Array.isArray(data.data) && typeof data.data[0] === 'number') ||
data.xAxis || data.yAxis
},
// 白板: 有 canvas/elements/strokes
{
type: 'whiteboard',
test: (data) => data.canvas || data.strokes || data.elements
},
// 文档: 默认兜底
{ type: 'document', test: () => true }
];
```
### 6.3 LLM 分析提示词
```
分析以下 Pipeline 输出数据,推荐最佳展示方式。
数据结构: {json_structure}
数据摘要: {data_summary}
可选展示类型:
- slideshow: 分页展示,适合课程、汇报
- quiz: 互动测验,适合教育场景
- chart: 数据可视化,适合分析结果
- document: 文档阅读,适合长文本
- whiteboard: 实时标注,适合讲解
返回 JSON:
{
"primary": "推荐类型",
"confidence": 0.85,
"reason": "推荐原因",
"alternatives": ["其他适合的类型"]
}
```
### 6.4 渲染器接口
```typescript
export interface PresentationRenderer {
type: PresentationType;
name: string;
icon: string;
// 检查是否能渲染 (用于快速路径)
canRender(data: unknown): boolean;
// 渲染 React 组件
render(data: unknown): React.ReactNode;
// 导出格式支持
exportFormats?: ExportFormat[];
}
export type PresentationType =
| 'slideshow' // 幻灯片
| 'quiz' // 测验
| 'chart' // 图表
| 'document' // 文档
| 'whiteboard';// 白板
```
### 6.5 渲染器实现优先级
| 优先级 | 渲染器 | 技术方案 | 工作量 |
|--------|--------|---------|--------|
| **P0** | 📊 Chart | ECharts / Chart.js | 3 天 |
| **P0** | ✅ Quiz | 自定义表单组件 | 3 天 |
| **P1** | 📄 Document | Markdown 渲染 | 2 天 |
| **P1** | 🎨 Slideshow | reveal.js / Swiper | 5 天 |
| **P1** | 📝 Whiteboard | SVG Canvas | 7 天 |
### 6.6 用户切换流程
```
1. Pipeline 执行完成
2. Analyzer 推荐展示类型 (如 slideshow)
3. 渲染 slideshow
4. 显示切换器: [📊 幻灯片✓] [📝 文档] [🎓 测验]
5. 用户点击 "文档"
6. 立即切换到 DocumentRenderer
7. 记录用户偏好 (可选)
```
---
## 七、前端组件设计
### 7.1 新增组件
```
desktop/src/
├── components/
│ ├── pipeline/
│ │ ├── IntentInput.tsx # 智能输入组件
│ │ ├── ConversationCollector.tsx # 对话式参数收集
│ │ ├── PipelineSelector.tsx # Pipeline 选择器
│ │ └── ExecutionProgress.tsx # 执行进度
│ │
│ └── presentation/
│ ├── PresentationContainer.tsx # 展示容器
│ ├── TypeSwitcher.tsx # 类型切换器
│ ├── renderers/
│ │ ├── SlideshowRenderer.tsx
│ │ ├── QuizRenderer.tsx
│ │ ├── ChartRenderer.tsx
│ │ ├── WhiteboardRenderer.tsx
│ │ └── DocumentRenderer.tsx
│ └── analyzer/
│ └── PresentationAnalyzer.ts
├── store/
│ ├── pipelineStore.ts # Pipeline 状态
│ └── presentationStore.ts # 展示状态
└── lib/
├── intent-router.ts # 前端意图路由
└── presentation/
└── renderer-registry.ts # 渲染器注册表
```
### 7.2 UI 流程
```
用户输入 → IntentInput
意图分析 (显示推荐 Pipeline)
参数收集 (对话 or 表单)
执行 → ExecutionProgress
结果 → PresentationContainer
展示分析 → 推荐渲染器
渲染 + 切换器
```
---
## 八、实现计划
### Phase 1: 智能入口层 (1 周)
**目标**: 实现自然语言触发 Pipeline
| 任务 | 文件 | 说明 |
|------|------|------|
| Intent Router | `crates/zclaw-pipeline/src/intent.rs` | 意图识别和路由 |
| Trigger Parser | `crates/zclaw-pipeline/src/trigger.rs` | 触发模式解析 |
| IntentInput 组件 | `desktop/src/components/pipeline/IntentInput.tsx` | 前端输入组件 |
### Phase 2: Pipeline v2 格式 (1 周)
**目标**: 支持新格式定义
| 任务 | 文件 | 说明 |
|------|------|------|
| v2 Parser | `crates/zclaw-pipeline/src/parser_v2.rs` | 新格式解析 |
| Stage Engine | `crates/zclaw-pipeline/src/engine/stage.rs` | 阶段执行器 |
| Context v2 | `crates/zclaw-pipeline/src/engine/context.rs` | 执行上下文 |
### Phase 3: 智能展示层 - P0 (1 周)
**目标**: 实现图表和测验渲染器
| 任务 | 文件 | 说明 |
|------|------|------|
| Presentation Analyzer | `crates/zclaw-pipeline/src/presentation/` | 展示分析 |
| Chart Renderer | `desktop/src/components/presentation/renderers/ChartRenderer.tsx` | 图表渲染 |
| Quiz Renderer | `desktop/src/components/presentation/renderers/QuizRenderer.tsx` | 测验渲染 |
| Type Switcher | `desktop/src/components/presentation/TypeSwitcher.tsx` | 类型切换 |
### Phase 4: 智能展示层 - P1 (2 周)
**目标**: 实现幻灯片和白板渲染器
| 任务 | 文件 | 说明 |
|------|------|------|
| Slideshow Renderer | `desktop/src/components/presentation/renderers/SlideshowRenderer.tsx` | 幻灯片 |
| Whiteboard Renderer | `desktop/src/components/presentation/renderers/WhiteboardRenderer.tsx` | 白板 |
---
## 九、关键文件清单
### 9.1 需要修改的文件
| 文件 | 修改内容 |
|------|---------|
| `crates/zclaw-pipeline/src/lib.rs` | 导出新模块 |
| `crates/zclaw-pipeline/src/types.rs` | 添加 v2 类型 |
| `crates/zclaw-pipeline/src/executor.rs` | 支持 Stage 执行 |
| `desktop/src-tauri/src/pipeline_commands.rs` | 添加新命令 |
| `desktop/src/components/PipelinesPanel.tsx` | 集成新组件 |
### 9.2 需要新增的文件
| 文件 | 说明 |
|------|------|
| `crates/zclaw-pipeline/src/intent.rs` | 意图路由 |
| `crates/zclaw-pipeline/src/trigger.rs` | 触发器解析 |
| `crates/zclaw-pipeline/src/engine/stage.rs` | 阶段执行 |
| `crates/zclaw-pipeline/src/presentation/` | 展示层 |
| `desktop/src/components/pipeline/IntentInput.tsx` | 智能输入 |
| `desktop/src/components/presentation/` | 展示组件 |
---
## 十、验证方案
### 10.1 单元测试
```bash
# Pipeline v2 格式解析
cargo test -p zclaw-pipeline parser_v2
# 意图路由
cargo test -p zclaw-pipeline intent_router
# 阶段执行
cargo test -p zclaw-pipeline stage_engine
```
### 10.2 集成测试
```bash
# 端到端流程
1. 用户输入 "帮我做一个 Python 入门课程"
2. 系统识别意图 → 匹配 course-generator
3. 对话收集参数 (主题: Python, 难度: 入门)
4. 执行 Pipeline
5. 输出展示为幻灯片
6. 用户切换到文档模式
```
### 10.3 手动验证清单
- [ ] 自然语言触发 Pipeline
- [ ] 对话式参数收集
- [ ] 表单式参数输入
- [ ] 执行进度实时显示
- [ ] 图表正确渲染
- [ ] 测验交互正常
- [ ] 展示类型切换

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