# 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 { match s { "report_collection" => Some(Self::ReportCollection), "monitoring" => Some(Self::Monitoring), _ => None, } } } ``` **函数签名变更**: ```rust // 改动前 pub fn analyze_scene_source(source_dir: &Path) -> Result; // 改动后 pub fn analyze_scene_source( source_dir: &Path, scene_kind_hint: Option, ) -> Result; ``` ### 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 - 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 = "" skill = "" tool = "monitor_" 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 = [""] exclude_keywords = [] # 参数部分留空,用户手动编辑 # [[params]] # name = "xxx" # resolver = "literal_passthrough" [artifact] type = "monitoring-status" success_status = ["ok", "running"] failure_status = ["error", "timeout"] # 后处理留空,用户手动编辑 ``` ### 5. Web UI 改动 **新增控件**: ```html
报表类:查询数据导出 Excel;监测类:定时检查状态
``` **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` — 当前生成器