Files
claw/docs/superpowers/specs/2026-04-16-multi-scene-kind-generator-design.md
木炎 af8f261b79 docs: add multi-scene-kind generator design spec
Design for extending sg_scene_generate to support multiple scene kinds
(report_collection, monitoring) with manual type selection in Web UI,
relaxing the requirement for meta tags in third-party scene directories.

🤖 Generated with [Qoder][https://qoder.com]
2026-04-16 23:22:08 +08:00

310 lines
11 KiB
Markdown
Raw 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.
# Multi-Scene-Kind Generator Design
> **Status:** Draft
> **Date:** 2026-04-16
> **Author:** Qoder
## Problem Statement
`sg_scene_generate` 当前只支持 `report_collection` 类型的场景,强制要求场景目录的 `index.html` 包含 `sgclaw-scene-kind``sgclaw-tool-kind` meta 标签。
**现实情况**
- 400+ 第三方场景目录**没有** meta 标签
- 场景类型不单一:既有**报表收集类**(查询数据导出 Excel也有**监测类**(定时检查状态、监控告警)
- 不可能要求所有第三方场景添加 meta 标签
**结果**:当前 `sg_scene_generate` 对真实场景目录完全无法使用。
## Goal
扩展 `sg_scene_generate` 支持多种场景类型,让用户在 Web UI 上**手动选择场景类型**,而不是依赖场景目录中的 meta 标签。
## Non-Goals
- 不实现 LLM 自动识别场景类型(后续增强)
- 不实现运行时自动推断场景类型
- 不修改 `registry.rs` 的运行时校验逻辑V1 仍只支持已注册的类型)
- 不实现完整的监测类参数解析器(生成简化模板,用户手动编辑)
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ Web UI (HTML) │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ 场景路径输入 │ │ 场景类型下拉框│ │ 分析/生成按钮 │ │
│ └─────────────┘ └──────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Node.js Server │
│ /analyze → LLM 提取 scene-id, scene-name │
│ /generate → 调用 cargo run传递 --scene-kind 参数 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ sg_scene_generate (Rust CLI) │
│ --scene-kind report_collection | monitoring │
│ │
│ analyzer.rs → 放宽 meta 校验,接受用户指定类型 │
│ generator.rs → 根据类型选择不同模板 │
└─────────────────────────────────────────────────────────────┘
```
## Implementation Details
### 1. analyzer.rs — 放宽校验逻辑
**当前行为**
- 强制要求 `sgclaw-scene-kind` meta 标签 = `report_collection`
- 强制要求 `sgclaw-tool-kind` meta 标签 = `browser_script`
- 缺失则报错退出
**新行为**
- meta 标签**可选**
- 如果缺失,使用用户通过 `--scene-kind` 参数指定的类型
- 如果用户未指定,默认为 `report_collection`
- `sgclaw-tool-kind` 默认为 `browser_script`V1 只支持这一种)
**枚举扩展**
```rust
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SceneKind {
ReportCollection,
Monitoring,
}
impl SceneKind {
pub fn from_str(s: &str) -> Option<Self> {
match s {
"report_collection" => Some(Self::ReportCollection),
"monitoring" => Some(Self::Monitoring),
_ => None,
}
}
}
```
**函数签名变更**
```rust
// 改动前
pub fn analyze_scene_source(source_dir: &Path) -> Result<SceneSourceAnalysis, AnalyzeSceneError>;
// 改动后
pub fn analyze_scene_source(
source_dir: &Path,
scene_kind_hint: Option<SceneKind>,
) -> Result<SceneSourceAnalysis, AnalyzeSceneError>;
```
### 2. generator.rs — 多模板支持
**函数签名变更**
```rust
// 改动前
fn scene_toml(request: &GenerateSceneRequest, tool_name: &str, expected_domain: &str, target_url: &str) -> String;
// 改动后
fn scene_toml(request: &GenerateSceneRequest, analysis: &SceneSourceAnalysis, tool_name: &str) -> String;
```
**模板路由**
```rust
fn scene_toml(request: &GenerateSceneRequest, analysis: &SceneSourceAnalysis, tool_name: &str) -> String {
match analysis.scene_kind {
SceneKind::ReportCollection => scene_toml_report_collection(request, analysis, tool_name),
SceneKind::Monitoring => scene_toml_monitoring(request, analysis, tool_name),
}
}
```
### 3. sg_scene_generate.rs — 新增 CLI 参数
**新增参数**
```
--scene-kind <report_collection|monitoring>
场景类型,默认 report_collection
- report_collection: 报表收集类(查询数据导出报表)
- monitoring: 监测类(定时检查状态、监控告警)
```
**用法示例**
```bash
# 报表类(默认)
cargo run --bin sg_scene_generate -- \
--source-dir "D:/desk/场景/营销报表" \
--scene-id marketing-report \
--scene-name "营销报表" \
--output-root "./out" \
--lessons "docs/superpowers/references/tq-lineloss-lessons-learned.toml"
# 监测类
cargo run --bin sg_scene_generate -- \
--source-dir "D:/desk/场景/设备监测" \
--scene-id device-monitor \
--scene-name "设备监测" \
--scene-kind monitoring \
--output-root "./out" \
--lessons "docs/superpowers/references/tq-lineloss-lessons-learned.toml"
```
### 4. 监测类模板设计
监测类场景差异较大,生成**简化模板**,用户后续手动编辑:
```toml
[scene]
id = "<scene-id>"
skill = "<scene-id>"
tool = "monitor_<scene-id>"
kind = "browser_script"
version = "0.1.0"
category = "monitoring"
[manifest]
schema_version = "1"
[bootstrap]
expected_domain = "<从 analyzer 提取或空>"
target_url = "<从 analyzer 提取或空>"
requires_target_page = true
[deterministic]
suffix = "。。。"
include_keywords = ["<scene-name>"]
exclude_keywords = []
# 参数部分留空,用户手动编辑
# [[params]]
# name = "xxx"
# resolver = "literal_passthrough"
[artifact]
type = "monitoring-status"
success_status = ["ok", "running"]
failure_status = ["error", "timeout"]
# 后处理留空,用户手动编辑
```
### 5. Web UI 改动
**新增控件**
```html
<div class="form-group">
<label>场景类型</label>
<select id="sceneKind">
<option value="report_collection" selected>报表收集类</option>
<option value="monitoring">监测类</option>
</select>
<span class="hint">报表类:查询数据导出 Excel监测类定时检查状态</span>
</div>
```
**JavaScript 改动**
```javascript
// generate() 函数增加 sceneKind 参数
const sceneKind = document.getElementById('sceneKind').value;
const response = await fetch('/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sourceDir,
sceneId,
sceneName,
sceneKind, // 新增
outputRoot,
lessons
})
});
```
### 6. Node.js Server 改动
**/generate 接口**
```javascript
async function handleGenerate(req, res) {
const { sourceDir, sceneId, sceneName, sceneKind, outputRoot, lessons } = body;
// ...
const args = [
"run", "--bin", "sg_scene_generate", "--",
"--source-dir", normalize(sourceDir),
"--scene-id", sceneId,
"--scene-name", sceneName,
"--scene-kind", sceneKind || "report_collection", // 新增
"--output-root", normalize(outputRoot),
"--lessons", normalize(lessons),
];
// ...
}
```
## Compatibility Matrix
| 场景目录 | meta 标签 | 用户选择 | 最终类型 |
|---------|----------|---------|---------|
| 有 meta | `report_collection` | 未选择 | `report_collection` |
| 有 meta | `report_collection` | `report_collection` | `report_collection` |
| 有 meta | `report_collection` | `monitoring` | `monitoring`(用户优先) |
| 无 meta | 无 | 未选择 | `report_collection`(默认) |
| 无 meta | 无 | `monitoring` | `monitoring` |
**用户选择优先于 meta 标签**:因为用户比静态 meta 标签更了解场景的实际用途。
## File Changes Summary
| 文件 | 改动类型 | 改动量 |
|------|---------|-------|
| `src/generated_scene/analyzer.rs` | 修改 | ~30 行 |
| `src/generated_scene/generator.rs` | 修改 | ~50 行 |
| `src/bin/sg_scene_generate.rs` | 修改 | ~20 行 |
| `frontend/scene-generator/sg_scene_generator.html` | 修改 | ~15 行 |
| `frontend/scene-generator/server.js` | 修改 | ~5 行 |
| `frontend/scene-generator/generator-runner.js` | 修改 | ~5 行 |
| `tests/scene_generator_test.rs` | 修改 | ~30 行 |
| `tests/fixtures/generated_scene/monitoring/index.html` | 新增 | ~20 行 |
**总计**~175 行改动8 个文件。
## Testing Strategy
### 单元测试
1. `analyzer_accepts_missing_meta_with_hint` — 缺失 meta 标签时,使用 hint 参数
2. `analyzer_uses_meta_when_present` — 有 meta 标签时,使用 meta 值
3. `generator_emits_report_collection_template` — 报表类模板正确
4. `generator_emits_monitoring_template` — 监测类模板正确
### 集成测试
1. 无 meta 标签的场景目录 + `--scene-kind report_collection` → 生成成功
2. 无 meta 标签的场景目录 + `--scene-kind monitoring` → 生成成功
3. Web UI 选择监测类 → 生成的 scene.toml 包含 `category = "monitoring"`
### 手动验证
1. 真实场景目录 `D:\desk\智能体资料\场景\营销2.0零度户报表数据生成` → 选择报表类 → 生成成功
2. 真实监测类场景 → 选择监测类 → 生成成功
## Risks and Mitigations
| 风险 | 影响 | 缓解措施 |
|------|------|---------|
| 监测类模板过于简化 | 用户需要大量手动编辑 | 文档说明 + 后续迭代优化 |
| 用户选错类型 | 生成错误模板 | UI 上提供清晰说明 |
| registry.rs 不支持 monitoring | 生成的包无法注册 | V1 只生成,运行时支持后续迭代 |
## Open Questions
1. 监测类场景的 `artifact.type` 应该是什么?当前设计为 `monitoring-status`,是否合适?
2. 监测类是否需要新的 resolver 类型?
3. 是否需要在前端 UI 显示更多类型说明?
## References
- `docs/superpowers/plans/2026-04-15-generated-scene-skill-platform-plan.md` — 原实现计划
- `src/generated_scene/analyzer.rs` — 当前分析器
- `src/generated_scene/generator.rs` — 当前生成器