feat: 新增技能编排引擎和工作流构建器组件
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

refactor: 统一Hands系统常量到单个源文件
refactor: 更新Hands中文名称和描述

fix: 修复技能市场在连接状态变化时重新加载
fix: 修复身份变更提案的错误处理逻辑

docs: 更新多个功能文档的验证状态和实现位置
docs: 更新Hands系统文档

test: 添加测试文件验证工作区路径
This commit is contained in:
iven
2026-03-25 08:27:25 +08:00
parent 9c781f5f2a
commit aa6a9cbd84
110 changed files with 12384 additions and 1337 deletions

View File

@@ -0,0 +1,644 @@
# Pipeline DSL 架构设计
> **目标**: 在 ZCLAW 中实现 OpenMagic 类教育功能,支持多步骤自动化工作流
> **原则**: 用户只看到 PipelineHands/Skills 作为内部实现被隐藏
---
## 1. 背景
### 1.1 问题
当前 Hands + Skills 架构存在以下局限:
- **流程编排**: Skills 是静态提示模板,无法定义执行流程
- **状态管理**: 复杂场景需要跨多个步骤传递状态
- **可扩展性**: 不同行业需要不同的生成流程
- **前端绑定**: Hands 动作无法直接映射到 UI 组件
### 1.2 需求
- 输入课题 → 自动生成大纲 → 并行生成场景 → 渲染预览 → 导出文件
- 支持垂直扩展(不同学科)和水平扩展(跨行业)
- 内部播放预览 + 文件导出PPTX/HTML/PDF
---
## 2. 架构设计
### 2.1 分层架构
```
┌─────────────────────────────────────────────────────────┐
│ User Interface │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ Pipeline List│ │ Pipeline Run│ │ Result Preview │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ Pipeline Engine (新增) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ DSL Parser │ │ Executor │ │ State Manager │ │
│ │ YAML/TOML │ │ DAG Runner │ │ Context Store │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────┐ ┌─────────────────┐
│ Skills (隐藏) │ │ Hands (隐藏)│ │ Exporters │
│ prompt templates│ │ executors │ │ pptx/html/pdf │
└─────────────────┘ └─────────────┘ └─────────────────┘
```
### 2.2 核心组件
#### A. Pipeline DSL (声明式配置)
```yaml
# pipelines/education/classroom.yaml
apiVersion: zclaw/v1
kind: Pipeline
metadata:
name: classroom-generator
displayName: 互动课堂生成器
category: education
description: 输入课题,自动生成完整互动课堂
spec:
inputs:
- name: topic
type: string
required: true
label: 课题名称
placeholder: 例如:牛顿第二定律
- name: difficulty
type: select
options: [初级, 中级, 高级]
default: 中级
- name: export_formats
type: multi-select
options: [pptx, html, pdf]
default: [pptx, html]
steps:
# Step 1: 解析输入
- id: parse_input
action: llm.generate
template: skills/classroom-generator/parse.md
input:
topic: ${inputs.topic}
difficulty: ${inputs.difficulty}
output: parsed_data
# Step 2: 生成大纲
- id: generate_outline
action: llm.generate
template: skills/classroom-generator/outline.md
input: ${steps.parse_input.output}
output: outline
# Step 3: 并行生成场景
- id: generate_scenes
action: parallel
each: ${steps.generate_outline.output.items}
max_workers: 4
step:
action: llm.generate
template: skills/classroom-generator/scene.md
input:
item: ${item}
index: ${index}
output: scenes[]
# Step 4: 渲染课堂
- id: render
action: classroom.render
input:
outline: ${steps.generate_outline.output}
scenes: ${steps.generate_scenes.output}
output: classroom_data
# Step 5: 导出文件
- id: export
action: file.export
formats: ${inputs.export_formats}
input: ${steps.render.output}
output: export_paths
outputs:
classroom_id: ${steps.render.output.id}
preview_url: /classroom/${steps.render.output.id}
export_files: ${steps.export.output}
```
#### B. Pipeline Executor (执行引擎)
```rust
// crates/zclaw-pipeline/src/executor.rs
pub struct PipelineExecutor {
skill_registry: Arc<SkillRegistry>,
hand_registry: Arc<HandRegistry>,
llm_driver: Arc<dyn LlmDriver>,
state: PipelineState,
}
impl PipelineExecutor {
pub async fn execute(&self, pipeline: &Pipeline, inputs: Value) -> Result<PipelineOutput> {
let mut context = ExecutionContext::new(inputs);
for step in &pipeline.spec.steps {
match &step.action {
Action::LlmGenerate { template, input } => {
let prompt = self.render_template(template, &context)?;
let response = self.llm_driver.generate(prompt).await?;
context.set_output(&step.id, response);
}
Action::Parallel { each, step, max_workers } => {
let items = context.resolve(each)?;
let results = self.execute_parallel(step, items, *max_workers).await?;
context.set_output(&step.id, results);
}
Action::ClassroomRender { input } => {
let data = context.resolve(input)?;
let classroom = self.render_classroom(data).await?;
context.set_output(&step.id, classroom);
}
Action::FileExport { formats, input } => {
let paths = self.export_files(formats, input).await?;
context.set_output(&step.id, paths);
}
}
}
Ok(context.extract_outputs(&pipeline.outputs))
}
}
```
#### C. State Manager (状态管理)
```rust
// crates/zclaw-pipeline/src/state.rs
pub struct ExecutionContext {
inputs: Value,
steps_output: HashMap<String, Value>,
variables: HashMap<String, Value>,
}
impl ExecutionContext {
// 解析表达式 ${steps.generate_outline.output.items}
pub fn resolve(&self, expr: &str) -> Result<Value> {
// 支持的表达式:
// ${inputs.topic} - 输入参数
// ${steps.xxx.output} - 步骤输出
// ${item} - 循环变量
// ${index} - 循环索引
}
pub fn set_output(&mut self, step_id: &str, value: Value) {
self.steps_output.insert(step_id.to_string(), value);
}
}
```
---
## 3. 文件结构
### 3.1 新增 Crate
```
crates/zclaw-pipeline/
├── Cargo.toml
├── src/
│ ├── lib.rs
│ ├── parser.rs # YAML/TOML DSL 解析
│ ├── executor.rs # 执行引擎
│ ├── state.rs # 状态管理
│ ├── actions/ # 内置动作
│ │ ├── mod.rs
│ │ ├── llm.rs # LLM 调用
│ │ ├── parallel.rs # 并行执行
│ │ ├── render.rs # 渲染
│ │ └── export.rs # 导出
│ └── types.rs # 类型定义
```
### 3.2 Pipeline 配置目录
```
pipelines/
├── education/ # 教育类
│ ├── classroom.yaml # 互动课堂
│ ├── quiz-generator.yaml # 测验生成
│ └── flashcard.yaml # 闪卡生成
├── marketing/ # 营销类
│ ├── campaign.yaml # 营销方案
│ └── content-calendar.yaml # 内容日历
├── legal/ # 法律类
│ └── contract-review.yaml # 合同审查
└── _templates/ # 模板
└── base.yaml
```
### 3.3 隐藏 Skills/Hands
Skills 和 Hands 文件保留,但:
- 不在 UI 中直接展示
- 只通过 Pipeline DSL 引用
- 作为内部实现细节
---
## 4. 前端集成
### 4.0 设计原则
- **Pipeline 页面** - 类似 Hands 页面,展示所有可用 Pipeline
- **双触发入口** - 页面直接触发 + 对话中 Agent 引导触发
- **Agent 智能推荐** - 识别用户意图,推荐合适的 Pipeline
### 4.1 Pipeline 页面 (新增)
#### 页面布局 (参考 Hands 页面)
```
┌─────────────────────────────────────────────────────────────┐
│ Pipelines [+ 新建] │
├─────────────────────────────────────────────────────────────┤
│ [全部] [教育] [营销] [法律] [研发] [更多...] │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 📚 互动课堂生成 │ │ 📝 测验生成器 │ │
│ │ │ │ │ │
│ │ 输入课题,自动 │ │ 根据内容生成 │ │
│ │ 生成完整课堂 │ │ 选择题/填空题 │ │
│ │ │ │ │ │
│ │ [开始生成] │ │ [开始生成] │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 📊 营销方案生成 │ │ ⚖️ 合同审查 │ │
│ │ │ │ │ │
│ │ 输入产品信息, │ │ 上传合同文档, │ │
│ │ 生成营销策略 │ │ 自动审查风险点 │ │
│ │ │ │ │ │
│ │ [开始生成] │ │ [开始生成] │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
```
#### Pipeline 卡片组件
```typescript
interface PipelineCard {
id: string;
icon: string; // emoji 或图标
displayName: string;
description: string;
category: string;
tags: string[];
usage_count: number; // 使用次数(用于排序推荐)
last_used?: Date;
}
```
#### Pipeline 运行对话框
```
┌─────────────────────────────────────────┐
│ 互动课堂生成器 [×] │
├─────────────────────────────────────────┤
│ │
│ 课题名称 * │
│ ┌───────────────────────────────────┐ │
│ │ 牛顿第二定律 │ │
│ └───────────────────────────────────┘ │
│ │
│ 难度等级 │
│ ○ 初级 ● 中级 ○ 高级 │
│ │
│ 导出格式 │
│ ☑ PPTX ☑ HTML ☐ PDF │
│ │
│ [取消] [开始生成] │
└─────────────────────────────────────────┘
```
### 4.2 对话中触发 (Agent 引导)
#### Agent 系统提示词注入
```typescript
// 在 Agent 系统提示词中注入 Pipeline 信息
const systemPrompt = `
你是一个智能助手。用户可能会描述一些任务需求,你可以推荐使用合适的 Pipeline 工具。
可用的 Pipeline 工具:
${pipelines.map(p => `- ${p.displayName}: ${p.description}`).join('\n')}
当用户的需求匹配某个 Pipeline 时:
1. 简要说明该 Pipeline 能做什么
2. 询问用户是否要使用
3. 如果用户同意,调用 run_pipeline 工具启动
示例:
用户: "帮我做一个关于光合作用的课件"
你: "我可以使用【互动课堂生成器】为你自动生成完整课件,包括幻灯片、讲解和测验。需要开始吗?"
`;
```
#### Agent 推荐行为模式
**主动推荐策略**(需求模糊时也推荐):
```typescript
// Agent 识别潜在需求的模式
const intentPatterns = [
// 教育类
{ keywords: ["准备.*课", "备课", "教案", "教学"], pipeline: "classroom-generator", confidence: 0.7 },
{ keywords: ["学生.*测验", "出题", "考试"], pipeline: "quiz-generator", confidence: 0.8 },
// 营销类
{ keywords: ["推广.*方案", "营销计划", "宣传"], pipeline: "marketing-campaign", confidence: 0.75 },
{ keywords: ["内容.*日历", "发布.*计划"], pipeline: "content-calendar", confidence: 0.7 },
// 法律类
{ keywords: ["合同.*审查", "条款.*风险", "法律.*检查"], pipeline: "contract-review", confidence: 0.8 },
];
// Agent 行为:
// 1. 监听用户对话内容
// 2. 匹配潜在需求模式
// 3. 当 confidence > 0.6 时,主动询问
// 4. 用户确认后启动 Pipeline
```
#### 对话触发流程
**场景 1: 需求明确**
```
用户: 帮我做一个关于牛顿第二定律的课件
┌─────────────────────────────────────┐
│ Agent 分析意图 │
│ - 关键词: 课件、牛顿第二定律 │
│ - 匹配 Pipeline: classroom-generator │
│ - confidence: 0.95 (直接推荐) │
└─────────────────────────────────────┘
```
**场景 2: 需求模糊(主动推荐)**
```
用户: 我在准备下周的物理课,讲力学部分
┌─────────────────────────────────────┐
│ Agent 分析意图 │
│ - 关键词: 准备课、物理、力学 │
│ - 匹配 Pipeline: classroom-generator │
│ - confidence: 0.72 (主动询问) │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Agent 回复 │
│ "物理课准备啊!力学是个重要主题。 │
│ │
│ 我可以帮你:【互动课堂生成器】 │
│ • 自动生成力学课件大纲 │
│ • 创建互动幻灯片 │
│ • 生成课后测验 │
│ │
│ 要试试吗?课题就是'力学基础'" │
└─────────────────────────────────────┘
```
┌─────────────────────────────────────┐
│ Agent 回复 │
│ "我可以使用【互动课堂生成器】为你 │
│ 自动生成完整课件,包括: │
│ • 结构化大纲 │
│ • 互动幻灯片 │
│ • AI 老师讲解 │
│ • 课后测验 │
│ │
│ 需要开始生成吗?" │
└─────────────────────────────────────┘
▼ (用户: 好的)
┌─────────────────────────────────────┐
│ Agent 调用工具 │
│ run_pipeline( │
│ id: "classroom-generator", │
│ inputs: { │
│ topic: "牛顿第二定律", │
│ difficulty: "中级" │
│ } │
│ ) │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Pipeline 执行 & 进度反馈 │
│ Agent: "正在生成课堂大纲..." │
│ Agent: "正在生成第 3/8 个场景..." │
│ Agent: "课堂生成完成!" │
│ [预览课堂] [下载 PPTX] │
└─────────────────────────────────────┘
```
### 4.3 API 设计
```typescript
// kernel-client.ts 扩展
// 列出 Pipelines
async listPipelines(options?: {
category?: string;
search?: string;
}): Promise<Pipeline[]>
// 获取 Pipeline 详情
async getPipeline(id: string): Promise<PipelineDetail>
// 运行 Pipeline
async runPipeline(request: {
pipelineId: string;
inputs: Record<string, any>;
}): Promise<{ runId: string }>
// 获取运行进度
async getPipelineProgress(runId: string): Promise<{
status: 'running' | 'completed' | 'failed';
currentStep: string;
percentage: number;
message: string;
}>
// 获取运行结果
async getPipelineResult(runId: string): Promise<{
outputs: Record<string, any>;
files: { name: string; url: string; size: number }[];
}>
// 订阅进度事件
onPipelineProgress(runId: string, callback: (progress) => void): () => void
```
### 4.4 结果预览页
- 白板/幻灯片渲染器
- Agent 授课播放器
- 测验交互组件
- 导出文件下载
### 4.5 路由结构
```typescript
// 新增路由
/pipelines // Pipeline 列表页
/pipelines/:id // Pipeline 详情/运行页
/pipelines/run/:runId // 运行结果/进度页
/classroom/:id // 课堂预览页 (Pipeline 产出)
```
---
## 5. 实现步骤
### Phase 1: Pipeline 基础 (1 周)
1. 创建 `zclaw-pipeline` crate
2. 实现 DSL Parser (YAML → Pipeline struct)
3. 实现 ExecutionContext 状态管理
4. 实现基础 Executor (顺序执行)
### Phase 2: 核心动作 (1 周)
1. 实现 `llm.generate` 动作
2. 实现 `parallel` 动作
3. 实现 `classroom.render` 动作
4. 实现 `file.export` 动作
### Phase 3: 前端集成 (1 周)
1. Pipeline 列表 API
2. Pipeline 运行 API
3. 进度订阅
4. 结果获取
### Phase 4: 教育模板 (1 周)
1. classroom-generator.yaml
2. 前端预览组件
3. 测试验证
---
## 6. 验证方案
### 6.1 单元测试
```rust
#[test]
fn test_pipeline_parse() {
let yaml = r#"
apiVersion: zclaw/v1
kind: Pipeline
...
"#;
let pipeline = PipelineParser::parse(yaml).unwrap();
assert_eq!(pipeline.metadata.name, "classroom-generator");
}
#[test]
fn test_expression_resolve() {
let ctx = ExecutionContext::new(json!({
"inputs": {"topic": "test"},
"steps": {"parse": {"output": {"items": [1, 2, 3]}}}
}));
let value = ctx.resolve("${steps.parse.output.items}").unwrap();
assert_eq!(value, json!([1, 2, 3]));
}
```
### 6.2 集成测试
```bash
# 启动 Pipeline
curl -X POST http://localhost:50051/pipelines/classroom-generator/run \
-d '{"topic": "牛顿第二定律", "difficulty": "中级"}'
# 检查进度
curl http://localhost:50051/pipelines/runs/{run_id}/progress
# 获取结果
curl http://localhost:50051/pipelines/runs/{run_id}/result
```
### 6.3 E2E 测试
1. 在 UI 中选择 "互动课堂生成器"
2. 输入课题,点击生成
3. 观察进度条,等待完成
4. 预览生成的课堂
5. 下载 PPTX/HTML 文件
---
## 7. 扩展性设计
### 7.1 添加新 Pipeline
只需创建新的 YAML 文件:
```yaml
# pipelines/marketing/campaign.yaml
apiVersion: zclaw/v1
kind: Pipeline
metadata:
name: marketing-campaign
category: marketing
spec:
steps:
- id: analyze_brand
action: llm.generate
template: skills/marketing/brand-analysis.md
# ...
```
### 7.2 添加新 Action
```rust
// 在 actions/ 目录添加新动作
pub struct CustomAction;
impl ActionExecutor for CustomAction {
async fn execute(&self, ctx: &ExecutionContext, config: &Value) -> Result<Value> {
// 实现自定义逻辑
}
}
```
### 7.3 条件分支 (未来)
```yaml
steps:
- id: check_type
action: condition
branches:
- when: ${inputs.type == 'video'}
then: generate_video
- when: ${inputs.type == 'text'}
then: generate_text
```