minimal-agent 0.8.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -12
- package/package.json +34 -1
- package/plugins/cron-runner/.claude-plugin/plugin.json +5 -0
- package/plugins/cron-runner/commands/cron.md +26 -0
- package/plugins/cron-runner/commands/crons.md +7 -0
- package/plugins/cron-runner/plugin.js +34 -0
- package/plugins/cron-runner/src/commands.js +348 -0
- package/plugins/cron-runner/src/cronTime.js +148 -0
- package/plugins/cron-runner/src/lock.js +68 -0
- package/plugins/cron-runner/src/runs.js +89 -0
- package/plugins/cron-runner/src/scheduleEngine.js +72 -0
- package/plugins/cron-runner/src/scheduler.js +355 -0
- package/plugins/cron-runner/src/schema.js +140 -0
- package/plugins/cron-runner/src/service.js +167 -0
- package/plugins/cron-runner/src/store.js +298 -0
- package/plugins/cron-runner/src/types.js +1 -0
- package/plugins/workflow-runner/commands/workflow.md +4 -4
- package/plugins/workflow-runner/commands/workflows.md +1 -1
- package/plugins/workflow-runner/plugin.js +3 -1
- package/plugins/workflow-runner/src/agentCommon.js +249 -51
- package/plugins/workflow-runner/src/dslManifest.js +72 -0
- package/plugins/workflow-runner/src/expressions.js +198 -15
- package/plugins/workflow-runner/src/index.js +40 -8
- package/plugins/workflow-runner/src/jsonPayload.js +1 -1
- package/plugins/workflow-runner/src/loader.js +286 -72
- package/plugins/workflow-runner/src/multimodal.js +37 -0
- package/plugins/workflow-runner/src/recovery.js +49 -39
- package/plugins/workflow-runner/src/runner.js +802 -287
- package/plugins/workflow-runner/src/stepExecutors/agent.js +157 -39
- package/plugins/workflow-runner/src/stepExecutors/assert.js +16 -3
- package/plugins/workflow-runner/src/stepExecutors/llm.js +60 -111
- package/plugins/workflow-runner/src/stepExecutors/skill.js +47 -47
- package/plugins/workflow-runner/src/stepExecutors/tool.js +76 -10
- package/plugins/workflow-runner/src/stepExecutors/verify.js +27 -10
- package/plugins/workflow-runner/src/taskIdentity.js +296 -0
- package/plugins/workflow-runner/src/types.js +19 -9
- package/plugins/workflow-runner/src/workflowState.js +516 -33
- package/skills/adversarial-review/SKILL.md +0 -1
- package/skills/ai-image/SKILL.md +89 -0
- package/skills/ai-image/scripts/generate.mjs +497 -0
- package/skills/ai-image/scripts/generate_from_plan.mjs +469 -0
- package/skills/ai-image/scripts/generate_from_plan_test.mjs +223 -0
- package/skills/ai-image/scripts/generate_test.mjs +74 -0
- package/skills/browser-automation/SKILL.md +47 -0
- package/skills/docx/SKILL.md +25 -3
- package/skills/docx/scripts/office/helpers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/helpers/__pycache__/merge_runs.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/helpers/__pycache__/simplify_redlines.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/base.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/docx.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/pptx.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/redlining.cpython-314.pyc +0 -0
- package/skills/docx/scripts/opc_check.py +253 -0
- package/skills/image-gen-openrouter/SKILL.md +10 -2
- package/skills/image-stats/SKILL.md +65 -0
- package/skills/image-stats/scripts/__pycache__/image_stats.cpython-314.pyc +0 -0
- package/skills/image-stats/scripts/__pycache__/image_stats_test.cpython-314.pyc +0 -0
- package/skills/image-stats/scripts/image_stats.py +368 -0
- package/skills/image-stats/scripts/image_stats_test.py +181 -0
- package/skills/pptx/SKILL.md +123 -95
- package/skills/pptx/design.md +82 -0
- package/skills/pptx/examples/README.md +29 -0
- package/skills/pptx/examples/hybrid_example.mjs +107 -0
- package/skills/pptx/examples/hybrid_example.pptx +0 -0
- package/skills/pptx/pptxgenjs.md +41 -0
- package/skills/pptx/scripts/deck_helpers.mjs +224 -0
- package/skills/pptx/scripts/layout_lint.py +293 -0
- package/skills/pptx/scripts/layout_lint_test.py +160 -0
- package/skills/pptx/scripts/opc_check.py +339 -0
- package/skills/pptx/scripts/svg_fallback.mjs +145 -0
- package/skills/pptx/svg.md +67 -0
- package/skills/tts-zh/SKILL.md +19 -2
- package/skills/ui-design/SKILL.md +158 -0
- package/skills/ui-design/claude_design.md +309 -0
- package/skills/ui-design/evals/evals.json +254 -0
- package/skills/ui-design/references/aesthetic-direction.md +83 -0
- package/skills/ui-design/references/claude-design-protocol.md +36 -0
- package/skills/ui-design/references/design-context.md +53 -0
- package/skills/ui-design/references/design-execution-playbook.md +82 -0
- package/skills/ui-design/references/export-pptx.md +124 -0
- package/skills/ui-design/references/layout-composition.md +654 -0
- package/skills/ui-design/references/preview-feedback.md +37 -0
- package/skills/ui-design/references/source-image-layout.md +189 -0
- package/skills/ui-design/references/starter-components.md +78 -0
- package/skills/ui-design/references/vi-aegis-vector.md +144 -0
- package/skills/ui-design/references/vi-amber-prism.md +133 -0
- package/skills/ui-design/references/vi-aqua-glass.md +200 -0
- package/skills/ui-design/references/vi-comfort-vision.md +147 -0
- package/skills/ui-design/references/vi-ember-prism.md +140 -0
- package/skills/ui-design/references/vi-nebula-console.md +151 -0
- package/skills/ui-design/references/vi-obsidian-optics.md +139 -0
- package/skills/ui-design/references/vi-obsidian-xui.md +143 -0
- package/skills/ui-design/references/vi-precision-horizon-dark.md +117 -0
- package/skills/ui-design/references/vi-precision-horizon.md +215 -0
- package/skills/ui-design/references/vi-solar-relay.md +130 -0
- package/skills/ui-design/references/vi-template-workflow.md +48 -0
- package/skills/ui-design/references/vi-verdant-grid.md +141 -0
- package/skills/ui-design/references/vi-violet-meridian.md +172 -0
- package/skills/ui-design/scripts/__pycache__/assemble_material.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/assemble_material_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/chart_sanity_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_language_policy.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_ui_artifact.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_ui_artifact_pptx_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_pages_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_pages_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_visual_style_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_visual_style_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_budget_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_budget_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_repair_hints.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_repair_hints_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_style_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_style_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/draft_coverage_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/extract_source_assets.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/extract_source_assets_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/generated_image_review_collect.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/generated_image_review_collect_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_plan_lint.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_plan_lint_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/layout_balance.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/layout_balance_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/normalize_design_json.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/normalize_design_json_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/plan_source_layout.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/plan_source_layout_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_hint.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_hint_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_input.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_input_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/scaffold_ui_artifact.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/source_usage_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/source_usage_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/text_readability_pixel.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/visual_quality_gate.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/visual_quality_gate_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/assemble_material.py +217 -0
- package/skills/ui-design/scripts/assemble_material_test.py +149 -0
- package/skills/ui-design/scripts/browser_check_ui_artifact.mjs +221 -0
- package/skills/ui-design/scripts/chart_sanity_check.py +261 -0
- package/skills/ui-design/scripts/chart_sanity_check_test.py +165 -0
- package/skills/ui-design/scripts/check_language_policy.py +351 -0
- package/skills/ui-design/scripts/check_ui_artifact.py +435 -0
- package/skills/ui-design/scripts/check_ui_artifact_pptx_test.py +251 -0
- package/skills/ui-design/scripts/deck_pages_check.py +158 -0
- package/skills/ui-design/scripts/deck_pages_check_test.py +134 -0
- package/skills/ui-design/scripts/deck_visual_style_check.py +767 -0
- package/skills/ui-design/scripts/deck_visual_style_check_test.py +713 -0
- package/skills/ui-design/scripts/design_budget_check.py +271 -0
- package/skills/ui-design/scripts/design_budget_check_test.py +183 -0
- package/skills/ui-design/scripts/design_repair_hints.py +162 -0
- package/skills/ui-design/scripts/design_repair_hints_test.py +54 -0
- package/skills/ui-design/scripts/design_style_check.py +397 -0
- package/skills/ui-design/scripts/design_style_check_test.py +233 -0
- package/skills/ui-design/scripts/draft_coverage_check.py +184 -0
- package/skills/ui-design/scripts/draft_coverage_check_test.py +131 -0
- package/skills/ui-design/scripts/export_pptx_from_html.mjs +2367 -0
- package/skills/ui-design/scripts/extract_source_assets.py +607 -0
- package/skills/ui-design/scripts/extract_source_assets_test.py +256 -0
- package/skills/ui-design/scripts/generated_image_review_collect.py +206 -0
- package/skills/ui-design/scripts/generated_image_review_collect_test.py +91 -0
- package/skills/ui-design/scripts/image_plan_lint.py +571 -0
- package/skills/ui-design/scripts/image_plan_lint_test.py +515 -0
- package/skills/ui-design/scripts/image_prompt_rewrite.py +713 -0
- package/skills/ui-design/scripts/image_prompt_rewrite_test.py +966 -0
- package/skills/ui-design/scripts/layout_balance.py +881 -0
- package/skills/ui-design/scripts/layout_balance_test.py +927 -0
- package/skills/ui-design/scripts/normalize_design_json.py +272 -0
- package/skills/ui-design/scripts/normalize_design_json_test.py +119 -0
- package/skills/ui-design/scripts/plan_source_layout.py +1450 -0
- package/skills/ui-design/scripts/plan_source_layout_test.py +1136 -0
- package/skills/ui-design/scripts/resolve_source_input.py +270 -0
- package/skills/ui-design/scripts/resolve_source_input_test.py +98 -0
- package/skills/ui-design/scripts/scaffold_ui_artifact.py +377 -0
- package/skills/ui-design/scripts/source_usage_check.py +581 -0
- package/skills/ui-design/scripts/source_usage_check_test.py +427 -0
- package/skills/ui-design/scripts/text_readability_pixel.py +340 -0
- package/skills/ui-design/scripts/text_readability_pixel_test.py +219 -0
- package/skills/ui-design/scripts/visual_quality_gate.py +301 -0
- package/skills/ui-design/scripts/visual_quality_gate_test.py +233 -0
- package/skills/ui-design/tests/e2e/prompts/deck.md +19 -0
- package/skills/ui-design/tests/e2e/prompts/webpage.md +17 -0
- package/skills/ui-design/tests/e2e/render_check.mjs +101 -0
- package/skills/ui-design/tests/e2e/rubric.json +54 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/language-check.txt +12 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/static-check.txt +15 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/outputs/index.html +837 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/prompt.md +12 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/review.md +21 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/outputs/homepage.html +373 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/outputs/platform.html +378 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/review.md +26 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/outputs/index.html +656 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/prompt.md +12 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/render_check.mjs +67 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/outputs/index.html +587 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/prompt.md +12 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/review.md +36 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/language-check.txt +8 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/static-check.txt +16 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/outputs/index.html +739 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/prompt.md +11 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/review.md +22 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/checks/browser-check.json +52 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/outputs/index.html +641 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/outputs/index.html +467 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/outputs/homepage.html +373 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/outputs/platform.html +378 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/review.md +26 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/language-check.txt +4 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/execution_notes.md +10 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/outputs/index.html +587 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/prompt.md +14 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/review.md +13 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/checks/browser-check.json +24 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/execution_notes.md +21 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/outputs/deck.html +451 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/screenshots/slide-01.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/screenshots/slide-02.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/review.md +79 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/checks/browser-check.json +26 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/execution_notes.md +20 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/outputs/index.html +534 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/browser-check.json +64 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/language-check.txt +7 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/static-console.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/static-homepage.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/outputs/console.html +600 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/outputs/homepage.html +556 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/prompt.md +29 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/review.md +57 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/console-desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/console-mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/homepage-desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/homepage-mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/browser-check.json +33 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/language-check.txt +6 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/outputs/index.html +682 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/review.md +59 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/outputs/page-01.html +466 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/outputs/page-02.html +433 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/language-check.txt +3 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/execution_notes.md +24 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/outputs/index.html +723 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/prompt.md +15 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/review.md +26 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/browser-dark.json +49 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/browser-light.json +49 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/language-check.txt +11 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/static-dark.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/static-light.txt +3 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/execution_notes.md +23 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/outputs/dark.html +392 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/outputs/light.html +476 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/prompt.md +23 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/review.md +41 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/dark/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/dark/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/light/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/light/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/browser-check.json +54 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/language-check.txt +5 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/outputs/index.html +765 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/prompt.md +15 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/review.md +59 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/outputs/index.html +508 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/browser-check.json +54 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/language-check.txt +6 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/outputs/index.html +788 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/prompt.md +14 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/review.md +60 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/screenshots/mobile.png +0 -0
- package/skills/video-compose/SKILL.md +8 -1
- package/skills/web-crawler/SKILL.md +70 -0
- package/skills/web-crawler/scripts/crawl.mjs +538 -0
- package/skills/web-crawler/scripts/crawl.test.mjs +204 -0
- package/skills/xlsx/SKILL.md +12 -0
- package/skills/xlsx/scripts/opc_check.py +253 -0
- package/src/advisorState.js +22 -0
- package/src/askBridge.js +97 -3
- package/src/bootstrap/workingDir.js +12 -1
- package/src/cli/args.js +17 -1
- package/src/cli/configMenu.js +236 -0
- package/src/cli/configWizard.js +7 -5
- package/src/cli/print.js +37 -4
- package/src/cli/streamJson.js +77 -24
- package/src/cli/wizards/advisorWizard.js +147 -0
- package/src/cli/wizards/fieldForm.js +149 -0
- package/src/cli/wizards/imageWizard.js +60 -0
- package/src/cli/wizards/openRouterWizard.js +23 -0
- package/src/cli/wizards/providerPresets.js +95 -0
- package/src/cli/wizards/providerWizard.js +219 -0
- package/src/cli/wizards/searchWizard.js +23 -0
- package/src/cli/wizards/ttsWizard.js +34 -0
- package/src/config/configFile.js +441 -83
- package/src/config/configService.js +446 -0
- package/src/config.js +24 -64
- package/src/context/agentHome.js +9 -0
- package/src/context/archive.js +7 -2
- package/src/context/compact.js +8 -5
- package/src/context/contextLock.js +81 -0
- package/src/context/persistContext.js +30 -11
- package/src/context/reactiveCompact.js +4 -2
- package/src/context/recentDirs.js +21 -61
- package/src/context/sessionPath.js +97 -23
- package/src/context/sessionRegistry.js +303 -24
- package/src/context/tokenCounter.js +18 -0
- package/src/context/workspaceIndex.js +731 -0
- package/src/infra/verification.js +28 -15
- package/src/llm/client.js +394 -159
- package/src/llm/providers/anthropicFormat.js +241 -0
- package/src/llm/providers/openaiFormat.js +190 -0
- package/src/loop.js +219 -32
- package/src/main.js +61 -11
- package/src/messageQueue.js +97 -0
- package/src/multimodal.js +203 -0
- package/src/plugin-sdk.js +15 -0
- package/src/plugins/commandRouter.js +3 -0
- package/src/plugins/hookEngine.js +5 -1
- package/src/plugins/pluginLifecycle.js +28 -0
- package/src/plugins/pluginLoader.js +2 -1
- package/src/plugins/pluginRunner.js +49 -21
- package/src/plugins/transcript.js +4 -3
- package/src/prompts/pluginList.js +5 -5
- package/src/prompts/projectInstructions.js +3 -3
- package/src/prompts/promptAssembly.js +133 -144
- package/src/prompts/skillList.js +12 -22
- package/src/prompts/system.js +0 -1
- package/src/session/runAgentTurn.js +70 -0
- package/src/session/runTurn.js +41 -6
- package/src/toolGate.js +17 -0
- package/src/tools/advisor/advisor.js +379 -0
- package/src/tools/agent/agent.js +555 -0
- package/src/tools/agent/agentTypes.js +59 -0
- package/src/tools/agent/coordinator.js +93 -0
- package/src/tools/agent/worktree.js +270 -0
- package/src/tools/ask/ask.js +7 -2
- package/src/tools/bash/bash.js +112 -18
- package/src/tools/download/download.js +144 -0
- package/src/tools/edit/edit.js +1 -0
- package/src/tools/edit/multi-edit.js +1 -0
- package/src/tools/genimage/genimage.js +242 -0
- package/src/tools/genspeech/genspeech.js +67 -0
- package/src/tools/glob/glob.js +1 -0
- package/src/tools/grep/grep.js +3 -0
- package/src/tools/grep/rgPath.js +2 -0
- package/src/tools/index.js +25 -2
- package/src/tools/read/read.js +1 -0
- package/src/tools/shared/killTree.js +52 -0
- package/src/tools/toolProgressBridge.js +48 -0
- package/src/tools/webbrowser/agentBrowserPath.js +258 -0
- package/src/tools/webbrowser/browser.js +59 -42
- package/src/tools/webbrowser/browserControl.js +118 -0
- package/src/tools/webbrowser/browserDaemon.js +97 -0
- package/src/tools/webbrowser/browserService.js +27 -0
- package/src/tools/webbrowser/browserStream.js +119 -0
- package/src/tools/webbrowser/webbrowser.js +699 -130
- package/src/tools/webfetch/webfetch.js +1 -0
- package/src/tools/websearch/websearch.js +134 -51
- package/src/tools/write/write.js +1 -0
- package/src/ui/App.js +249 -22
- package/src/ui/AskQuestion.js +29 -10
- package/src/ui/InputBox.js +104 -12
- package/src/ui/LiveArea.js +112 -19
- package/src/ui/MessageList.js +100 -14
- package/src/ui/ModelPicker.js +56 -0
- package/src/ui/QueuedMessagesBanner.js +14 -0
- package/src/ui/Root.js +18 -10
- package/src/ui/SessionPicker.js +102 -0
- package/src/ui/StatusLine.js +13 -4
- package/src/ui/WorkspacePicker.js +55 -0
- package/src/ui/figures.js +44 -0
- package/src/ui/hooks/askSlot.js +82 -0
- package/src/ui/hooks/useChat.js +358 -64
- package/src/ui/hooks/usePasteHandler.js +11 -1
- package/src/ui/hooks/useTextBuffer.js +1 -3
- package/src/ui/liveViewport.js +5 -1
- package/src/ui/markdown.js +206 -0
- package/src/ui/textBuffer.js +0 -7
- package/src/ui/theme.js +32 -0
- package/src/utils/debugLog.js +0 -4
- package/src/utils/resourcePaths.js +2 -2
- package/src/utils/stripThink.js +50 -0
- package/src/web/browserBridge.js +447 -0
- package/src/web/protocol.js +19 -0
- package/workflows/adaptive-research.yaml +13 -5
- package/workflows/book-review-short.yaml +36 -10
- package/workflows/e2e-write-greet.yaml +6 -2
- package/workflows/illustrate.yaml +227 -0
- package/workflows/plan.yaml +460 -179
- package/workflows/ppt.yaml +1659 -0
- package/workflows/ralph-loop.yaml +199 -0
- package/workflows/schema.json +81 -23
- package/workflows/webppt.yaml +496 -0
- package/workflows/word.yaml +710 -0
- package/workflows/youtube-shorts.yaml +46 -15
- package/MINIMAL-TRACE.md +0 -77
- package/plugins/HOW-TO-WRITE-A-PLUGIN.md +0 -186
- package/plugins/ralph-wiggum/.claude-plugin/plugin.json +0 -9
- package/plugins/ralph-wiggum/README.md +0 -197
- package/plugins/ralph-wiggum/commands/cancel-ralph.md +0 -18
- package/plugins/ralph-wiggum/commands/help.md +0 -137
- package/plugins/ralph-wiggum/commands/ralph-loop.md +0 -85
- package/plugins/ralph-wiggum/hooks/hooks.json +0 -15
- package/plugins/ralph-wiggum/hooks/stop-hook.sh +0 -191
- package/plugins/ralph-wiggum/plugin.js +0 -280
- package/plugins/ralph-wiggum/src/goalState.js +0 -258
- package/plugins/ralph-wiggum/src/sentinels.js +0 -76
- package/plugins/ralph-wiggum/src/stopHookRunner.js +0 -104
- package/plugins/ralph-wiggum/src/verificationGate.js +0 -202
- package/plugins/workflow-runner/src/miniReAct.js +0 -223
- package/plugins/workflow-runner/src/voteHelpers.js +0 -110
- package/skills/config/SKILL.md +0 -123
- package/skills/frontend-design/LICENSE.txt +0 -177
- package/skills/frontend-design/SKILL.md +0 -42
- package/src/ui/ProgressPanel.js +0 -54
- package/src/ui/StreamingBlock.js +0 -11
- package/src/ui/ToolStatus.js +0 -11
|
@@ -2,54 +2,172 @@
|
|
|
2
2
|
* ============================================================
|
|
3
3
|
* plugins/workflow-runner/src/stepExecutors/agent.ts —— agent 步骤执行器
|
|
4
4
|
* ------------------------------------------------------------
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* v0.9 重构:不再使用独立 miniReAct 子循环,而是委托主 TAOR 引擎
|
|
6
|
+
* (runQuery / src/loop.ts)执行。这样做的好处:
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* 1. 上下文自然积累:每步的完整对话(user→assistant→tool→...)
|
|
9
|
+
* 都写入共享 history,后续步骤和用户对话都能看到
|
|
10
|
+
* 2. 工具/skills/插件信息来自系统提示词(history[0]),无需重复组装
|
|
11
|
+
* 3. 压缩自动生效:history 增长时 autoCompact / reactiveCompact 自动触发
|
|
12
|
+
* 4. Token 消耗透明:TUI status 行实时显示真实 token 数
|
|
13
|
+
* 5. 中断后上下文完整:已完成的步骤全在 history 里,可继续/调整
|
|
14
|
+
*
|
|
15
|
+
* 与 llm 步的区别:
|
|
16
|
+
* - agent 有 maxTurns 上限(默认 25),允许多轮工具调用
|
|
17
|
+
* - agent 的产出经过验证闸门(interpretMiniReActResult)
|
|
18
|
+
* - llm 只跑单轮 chat(maxTurns=1)
|
|
12
19
|
* ============================================================
|
|
13
20
|
*/
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
21
|
+
import { describeCaptureContract, describeLlmFailure, describeMaxTurnsCutoff, effectiveGoalAnchor, interpretMiniReActResult, runStepQuery, } from '../agentCommon.js';
|
|
22
|
+
import { evalExpr, interpolate } from '../expressions.js';
|
|
23
|
+
import { resolveWorkflowMultimodalOptions } from '../multimodal.js';
|
|
17
24
|
/**
|
|
18
|
-
* 执行一个 agent
|
|
25
|
+
* 执行一个 agent 步骤:构造 step prompt → 委托 runQuery(TAOR) → 提取结果。
|
|
19
26
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* - Plugin 列表(含命令和描述)
|
|
26
|
-
* 这解决了之前 workflow 模式下模型不知道有 pptx/pdf 等 skill 的问题。
|
|
27
|
+
* runQuery 会:
|
|
28
|
+
* 1. 把 prompt 作为 user message push 进 ctx.history
|
|
29
|
+
* 2. 跑 TAOR 循环(调 LLM → 执行工具 → 喂回 → 直到模型不调工具)
|
|
30
|
+
* 3. 把所有 assistant / tool 消息 push 进 ctx.history
|
|
31
|
+
* 4. yield UI 事件(text_delta / tool_start / tool_end / ...)
|
|
27
32
|
*/
|
|
28
33
|
export async function* execAgentStep(step, vars, ctx) {
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
//
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
34
|
+
// 默认 25(与 skill 步 skill.ts 对齐)。agent 步本就是「开放多工具任务」执行器,
|
|
35
|
+
// 弱模型常一轮只调一个工具(Read/Grep/Glob 各占一轮),旧默认 12 对探索类步骤
|
|
36
|
+
// (如 plan.yaml stage1_research)太紧——12 轮还没收集完就撞顶截断、误判失败。
|
|
37
|
+
// 这是安全阀不是性能阀;要更紧的步显式写小值即可。
|
|
38
|
+
const maxTurns = step.maxTurns ?? 25;
|
|
39
|
+
// 未定义变量插值可见化(裸 ${goal} 这类拼写/命名空间错的病根,静默空串会坑死下游)
|
|
40
|
+
const missing = [];
|
|
41
|
+
const iopts = { onMissing: (e) => missing.push(e) };
|
|
42
|
+
// 构造用户提示:包含步骤指令 + 变量 + capture 约束 + 内部标记防护
|
|
43
|
+
const userPrompt = `${interpolate(step.agent ?? '', vars, iopts)}${describeCaptureContract(step)}${step.input ? `\n\n上下文变量:${interpolate(step.input, vars, iopts)}` : ''}\n\n⚠️ 输出规范:直接输出你的工作成果即可,不要在输出中包含任何类似「放弃」、「GIVEUP」、「__AGENT__」或「[wf-internal」的内部标记文本。`;
|
|
44
|
+
// 如果有 output_schema,把 schema 约束嵌入 prompt(runQuery 不原生支持 responseFormat)
|
|
45
|
+
const schemaHint = step.output_schema
|
|
46
|
+
? `\n\n【结构化输出约束】请严格按照以下 JSON Schema 输出结果(不要包裹在 markdown 代码块中):\n${JSON.stringify(step.output_schema, null, 2)}`
|
|
47
|
+
: '';
|
|
48
|
+
const fullPrompt = userPrompt + schemaHint;
|
|
49
|
+
// 通用目标锚定(原始目标 + 累积的用户补充要求),前置注入 prompt。
|
|
50
|
+
// 确保每步 LLM 都能看到用户原始目标与运行中的补充要求,
|
|
51
|
+
// 避免长上下文 / fresh_context 导致目标被稀释或遗忘。
|
|
52
|
+
const anchor = effectiveGoalAnchor(ctx);
|
|
53
|
+
const effectivePrompt = anchor ? `${anchor}\n\n${fullPrompt}` : fullPrompt;
|
|
54
|
+
const multimodal = resolveWorkflowMultimodalOptions(step, vars, ctx, (e) => missing.push(e));
|
|
55
|
+
if (missing.length > 0) {
|
|
56
|
+
yield {
|
|
57
|
+
type: 'warning',
|
|
58
|
+
message: `step "${step.id}": 模板变量未定义,已按空串插值:${[...new Set(missing)].map((m) => `\${${m}}`).join('、')}(裸名请用 inputs.<name> 或先 capture/set)`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// 委托 TAOR 引擎执行(共享消费层 runStepQuery:携带 sessionState 以启用上下文压缩,
|
|
62
|
+
// 并统一侦测终结错误——runQuery 遇 LLM 失败是 yield error 后 return 不 throw)。
|
|
63
|
+
const { rawText, sawToolCall, toolNames, toolOkCount, toolFailCount, aborted, sawLlmError, sawMaxTurns, llmErrorDetail, } = yield* runStepQuery(effectivePrompt, step, ctx, {
|
|
64
|
+
maxTurns,
|
|
65
|
+
...multimodal,
|
|
50
66
|
});
|
|
51
|
-
const
|
|
67
|
+
const stepResult = {
|
|
68
|
+
raw: { text: rawText, result: rawText },
|
|
69
|
+
preview: rawText.length > 200 ? `${rawText.slice(0, 200)}...` : rawText,
|
|
70
|
+
};
|
|
71
|
+
// 用户中断导致的空产出:不过验证闸门(否则会误抛「放弃: 没有产出任何结果」),
|
|
72
|
+
// 直接返回当前(可能为空的)结果,由 runner 据 signal.aborted 收口(不当作可重试失败)。
|
|
73
|
+
if (aborted)
|
|
74
|
+
return stepResult;
|
|
75
|
+
// P0-1(同 llm.ts / skill.ts):LLM 失败(超时/网络错)且本步无任何产出 →
|
|
76
|
+
// 抛「可重试失败」交给 runner 的 in-run retry。必须在验证闸门之前——
|
|
77
|
+
// 否则 provider 故障会被闸门误归因为「agent 步骤放弃: 没有产出任何结果」,
|
|
78
|
+
// 混淆「provider 失败(该重试)」与「模型真放弃/空答(诚实 halt)」。
|
|
79
|
+
if (!rawText.trim() && sawLlmError) {
|
|
80
|
+
// 抛错文案附带 provider 真实报错(经 runner 落 progress.md,刷屏后仍可排障)
|
|
81
|
+
throw new Error(describeLlmFailure(step.id, llmErrorDetail));
|
|
82
|
+
}
|
|
83
|
+
// 撞 maxTurns 截断:截断时刻的文本是半截工作叙述,不是可信交付——
|
|
84
|
+
// 即使非空也不能过闸门(曾被静默当成功:半成品 PPTX 被整条链当真交付)。
|
|
85
|
+
// 抛可重试失败 → in-run retry 在共享 history 上续作(模型看到已有进度接着干)。
|
|
86
|
+
if (sawMaxTurns) {
|
|
87
|
+
throw new Error(describeMaxTurnsCutoff(step.id, maxTurns));
|
|
88
|
+
}
|
|
89
|
+
// done_when 验收兜底(K3/A2):弱模型常「宣告要干活」却不调工具就 end_turn
|
|
90
|
+
//(announce-not-do,2026-06-12 plan 工作流实跑事故的执行步烂尾根因之一)。
|
|
91
|
+
// yaml 作者声明确定性完成条件(如 fileExists('./doc/x.pptx')),不满足时
|
|
92
|
+
// 引擎自动 nudge 同一 agent 在共享 history 上继续干(看得到自己刚才的半截工作),
|
|
93
|
+
// 把「对抗模型不可靠」从每个 yaml 的 prompt 工程收回引擎单点。
|
|
94
|
+
if (step.done_when) {
|
|
95
|
+
const NUDGES = 2; // 提醒上限:超过说明模型真干不动,交给 onError/max_retries
|
|
96
|
+
let result = resultIfTextLooksDeliverable(step, rawText);
|
|
97
|
+
let lastOutcome = {
|
|
98
|
+
rawText,
|
|
99
|
+
sawToolCall,
|
|
100
|
+
toolNames,
|
|
101
|
+
toolOkCount,
|
|
102
|
+
toolFailCount,
|
|
103
|
+
};
|
|
104
|
+
for (let n = 0;; n++) {
|
|
105
|
+
if (evalDoneWhen(step, vars)) {
|
|
106
|
+
return result ?? doneWhenSatisfiedResult(step);
|
|
107
|
+
}
|
|
108
|
+
if (n >= NUDGES) {
|
|
109
|
+
throw new Error(`agent 步骤 "${step.id}" 完成条件未满足(done_when: ${step.done_when}),已提醒 ${NUDGES} 次仍未达成。${describeAttemptForDoneWhen(lastOutcome)}`);
|
|
110
|
+
}
|
|
111
|
+
yield {
|
|
112
|
+
type: 'warning',
|
|
113
|
+
message: `⏩ step "${step.id}" 完成条件未满足(${step.done_when}),提醒 agent 继续执行(第 ${n + 1}/${NUDGES} 次)。${describeAttemptForDoneWhen(lastOutcome)}`,
|
|
114
|
+
};
|
|
115
|
+
const nudge = yield* runStepQuery(`检查发现这一步还没有真正完成:完成条件 \`${step.done_when}\` 仍不成立。不要解释、不要宣告计划——继续实际执行(调用工具落盘/操作),直到完成条件成立,然后给出简短完成报告。`, step, ctx, { maxTurns });
|
|
116
|
+
if (nudge.aborted)
|
|
117
|
+
return result ?? stepResult;
|
|
118
|
+
if (!nudge.rawText.trim() && nudge.sawLlmError) {
|
|
119
|
+
throw new Error(describeLlmFailure(step.id, nudge.llmErrorDetail));
|
|
120
|
+
}
|
|
121
|
+
if (nudge.sawMaxTurns) {
|
|
122
|
+
throw new Error(describeMaxTurnsCutoff(step.id, maxTurns));
|
|
123
|
+
}
|
|
124
|
+
lastOutcome = nudge;
|
|
125
|
+
if (nudge.rawText.trim()) {
|
|
126
|
+
result = resultIfTextLooksDeliverable(step, nudge.rawText) ?? result;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// 验证闸门:判断结果是"真交付"还是"放弃"。注意:带 done_when 的步骤已在上方
|
|
131
|
+
// 由确定性条件验收,避免"文件已落盘但最终空文本"或"还没落盘但空文本"绕过 nudge。
|
|
132
|
+
const outcome = interpretMiniReActResult(stepResult, !!step.output_schema);
|
|
52
133
|
if (!outcome.ok)
|
|
53
134
|
throw new Error(`agent 步骤放弃: ${outcome.reason}`);
|
|
54
135
|
return outcome.value;
|
|
55
136
|
}
|
|
137
|
+
function evalDoneWhen(step, vars) {
|
|
138
|
+
try {
|
|
139
|
+
return Boolean(evalExpr(step.done_when ?? '', vars));
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
// 表达式坏了是 yaml 作者错误:响亮失败(同 max_iterations 解析失败哲学),
|
|
143
|
+
// 不能静默当 false 把好结果 nudge 死、也不能静默当 true 放走烂尾。
|
|
144
|
+
throw new Error(`step "${step.id}" 的 done_when 表达式求值失败: ${e.message}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function doneWhenSatisfiedResult(step) {
|
|
148
|
+
const text = `完成条件已满足:${step.done_when}`;
|
|
149
|
+
return { raw: { text, result: text, content: text }, preview: text };
|
|
150
|
+
}
|
|
151
|
+
function resultIfTextLooksDeliverable(step, text) {
|
|
152
|
+
if (!text.trim())
|
|
153
|
+
return null;
|
|
154
|
+
const outcome = interpretMiniReActResult({
|
|
155
|
+
raw: { text, result: text },
|
|
156
|
+
preview: text.length > 200 ? `${text.slice(0, 200)}...` : text,
|
|
157
|
+
}, !!step.output_schema);
|
|
158
|
+
return outcome.ok ? outcome.value : null;
|
|
159
|
+
}
|
|
160
|
+
function describeAttemptForDoneWhen(outcome) {
|
|
161
|
+
const textState = outcome.rawText.trim()
|
|
162
|
+
? '本轮有文本报告'
|
|
163
|
+
: '本轮没有文本报告';
|
|
164
|
+
if (!outcome.sawToolCall) {
|
|
165
|
+
return `${textState},且没有观察到工具调用;请不要只宣告计划,必须调用工具完成产物。`;
|
|
166
|
+
}
|
|
167
|
+
const names = outcome.toolNames.length ? outcome.toolNames.join('、') : '未知工具';
|
|
168
|
+
const wrote = outcome.toolNames.some((name) => ['Write', 'Edit', 'MultiEdit', 'Bash'].includes(name));
|
|
169
|
+
const writeHint = wrote
|
|
170
|
+
? '已观察到写入类工具调用,但完成条件仍未满足,请检查路径或实际写入结果'
|
|
171
|
+
: '未观察到写入类工具调用,请立即调用 Write/Edit/Bash 落盘产物';
|
|
172
|
+
return `${textState};本轮工具调用:${names}(成功 ${outcome.toolOkCount},失败 ${outcome.toolFailCount})。${writeHint}。`;
|
|
173
|
+
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ============================================================
|
|
3
|
-
* src/
|
|
3
|
+
* plugins/workflow-runner/src/stepExecutors/assert.ts —— assert step 执行
|
|
4
4
|
* ------------------------------------------------------------
|
|
5
5
|
* evalExpr(condition) → 真值通过;假值抛错(带 onFail 自定义信息)。
|
|
6
|
+
*
|
|
7
|
+
* v0.9.3(上下文统一修复):assert 步骤通过后也写入 ctx.history,
|
|
8
|
+
* 让后续 LLM 步骤能看到验证通过的信息(如"文件已存在""变量值符合预期"等)。
|
|
6
9
|
* ============================================================
|
|
7
10
|
*/
|
|
8
11
|
import { evalExpr, interpolate } from '../expressions.js';
|
|
9
|
-
export function execAssertStep(step, vars) {
|
|
12
|
+
export function execAssertStep(step, vars, ctx) {
|
|
10
13
|
if (typeof step.condition !== 'string') {
|
|
11
14
|
throw new Error(`step ${step.id}: assert 缺少 condition`);
|
|
12
15
|
}
|
|
13
16
|
let ok;
|
|
14
17
|
try {
|
|
15
|
-
// P2:表达式上下文直接 evalExpr(${} 由引擎原生处理),不再"先插值再 eval"。
|
|
16
18
|
ok = Boolean(evalExpr(step.condition, vars));
|
|
17
19
|
}
|
|
18
20
|
catch (e) {
|
|
@@ -24,5 +26,16 @@ export function execAssertStep(step, vars) {
|
|
|
24
26
|
: `assertion failed: ${step.condition}`;
|
|
25
27
|
throw new Error(msg);
|
|
26
28
|
}
|
|
29
|
+
// ════ v0.9.3:上下文统一 —— assert 通过也留痕 ════
|
|
30
|
+
// 让后续 LLM 步骤知道某个前置条件/不变量已确认满足。
|
|
31
|
+
// ctx 必填(签名强制,runner 唯一调用点 dispatchActionStep 始终传),直接访问 history。
|
|
32
|
+
if (ctx.history) {
|
|
33
|
+
ctx.history.push({
|
|
34
|
+
role: 'assistant',
|
|
35
|
+
content: `[workflow:${step.id}] ✅ 断言通过:${step.condition}`,
|
|
36
|
+
timestamp: Date.now(),
|
|
37
|
+
id: crypto.randomUUID(),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
27
40
|
return { raw: { ok: true }, preview: 'assert passed' };
|
|
28
41
|
}
|
|
@@ -1,132 +1,81 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ============================================================
|
|
3
|
-
* plugins/workflow-runner/src/stepExecutors/llm.ts —— llm
|
|
3
|
+
* plugins/workflow-runner/src/stepExecutors/llm.ts —— llm 步骤执行器
|
|
4
4
|
* ------------------------------------------------------------
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* - 自带独立 system + user 两条消息,不污染主 history
|
|
8
|
-
* - AsyncGenerator:非 schema 模式把 text_delta 流式 yield 给 UI(答案是主角,
|
|
9
|
-
* 消除 TUI"无声"),最终仍 return StepResult;schema 模式静默累积 JSON 不回显。
|
|
10
|
-
* reasoning 字段在这里忽略;只关心最终文本
|
|
5
|
+
* v0.9 重构:不再使用独立 miniReAct 子循环或裸 chat(),而是委托主 TAOR 引擎
|
|
6
|
+
* (runQuery / src/loop.ts)执行。
|
|
11
7
|
*
|
|
12
|
-
*
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
*
|
|
8
|
+
* 与 agent 步的区别:
|
|
9
|
+
* - llm 默认单轮(maxTurns=1),不下发工具
|
|
10
|
+
* - 有 context_files 或 allowed_tools 时允许少量轮次读取文件后输出
|
|
11
|
+
* - output_schema 嵌入 prompt 作为结构化约束
|
|
12
|
+
* - 不经过 interpretMiniReActResult 验证闸门(直接信任 LLM 输出)
|
|
16
13
|
*
|
|
17
14
|
* capture:
|
|
18
|
-
* - `{ text: var_name }`
|
|
19
|
-
* - `{
|
|
20
|
-
* - `{ <field>: var_name }` 当 output_schema 命中时按 raw 上的字段名取
|
|
21
|
-
*
|
|
22
|
-
* ADR-05: 当 step.output_schema 存在 → 走 provider-native structured output:
|
|
23
|
-
* - 通过 chat() 的 responseFormat 参数下发 JSON Schema
|
|
24
|
-
* - 收到的文本必须解析为 JSON 对象,整对象作为 raw 暴露给 capture
|
|
25
|
-
* - system prompt 切换为严格 JSON 模式,禁止 markdown 代码块包裹
|
|
15
|
+
* - `{ text: var_name }` 绑生成文本
|
|
16
|
+
* - `{ <field>: var_name }` 当 output_schema 存在时按 JSON 字段取值
|
|
26
17
|
* ============================================================
|
|
27
18
|
*/
|
|
28
|
-
import {
|
|
19
|
+
import { describeLlmFailure, describeMaxTurnsCutoff, effectiveGoalAnchor, runStepQuery, } from '../agentCommon.js';
|
|
29
20
|
import { interpolate } from '../expressions.js';
|
|
30
21
|
import { extractJsonPayload } from '../jsonPayload.js';
|
|
31
|
-
import {
|
|
32
|
-
import { assembleCapabilityHint } from '../../../../src/prompts/promptAssembly.js';
|
|
33
|
-
const LLM_STEP_SYSTEM_PLAIN = '你正在被一个 workflow 调用。只输出本步骤要求的内容本身,不要寒暄、不要列要求复述、不要工具调用语法。';
|
|
34
|
-
const LLM_STEP_SYSTEM_SCHEMA = `你正在被一个 workflow 调用。
|
|
35
|
-
要求:
|
|
36
|
-
1. 严格按指定 JSON Schema 输出有效 JSON,**不要 markdown 代码块包裹**(不要 \`\`\`json 也不要 \`\`\`)
|
|
37
|
-
2. 不要寒暄、不要解释、不要额外字段
|
|
38
|
-
3. 字段缺失或类型不符会导致 workflow 失败
|
|
39
|
-
4. 字符串内特殊字符必须正确转义(双引号 \\", 反斜杠 \\\\, 换行 \\n)`;
|
|
40
|
-
const LLM_STEP_SYSTEM_WITH_TOOLS = `你正在被一个 workflow 调用。你被授予了有限的工具(通常是 Read)以查询提供的上下文文件。
|
|
41
|
-
|
|
42
|
-
工作流程:
|
|
43
|
-
1. 先用 Read 工具读取你需要的文件(按需读取,**不要全部读完再思考**——大文件分段读、按 hint 选读)
|
|
44
|
-
2. 基于读到的内容生成最终回答
|
|
45
|
-
3. 不要寒暄、不要复述要求、不要解释你的推理过程
|
|
46
|
-
4. 完成后**不要**再调用工具,直接输出最终回答
|
|
47
|
-
|
|
48
|
-
如果 workflow 要求结构化输出,请在最终回答里严格遵循 JSON Schema(无 markdown 代码块包裹)。`;
|
|
22
|
+
import { resolveWorkflowMultimodalOptions } from '../multimodal.js';
|
|
49
23
|
export async function* execLlmStep(step, vars, ctx) {
|
|
50
24
|
if (typeof step.llm !== 'string')
|
|
51
25
|
throw new Error(`step ${step.id}: 缺少 llm 字段`);
|
|
52
|
-
|
|
53
|
-
|
|
26
|
+
// 未定义变量插值可见化(静默空串是下游 prompt 留白的病根)
|
|
27
|
+
const missing = [];
|
|
28
|
+
const iopts = { onMissing: (e) => missing.push(e) };
|
|
29
|
+
const prompt = interpolate(step.llm, vars, iopts);
|
|
30
|
+
// 有 context_files → 在 prompt 中附上文件列表,runQuery 的 TAOR 循环中
|
|
31
|
+
// 模型可自主用 Read 工具读取(ALL_TOOLS 全量可用)
|
|
32
|
+
let fullPrompt = prompt;
|
|
54
33
|
if (step.context_files && step.context_files.length > 0) {
|
|
55
34
|
const fileList = step.context_files
|
|
56
|
-
.map((f) => `- ${interpolate(f.path, vars)}${f.hint ? ` — ${f.hint}` : ''}`)
|
|
35
|
+
.map((f) => `- ${interpolate(f.path, vars, iopts)}${f.hint ? ` — ${f.hint}` : ''}`)
|
|
57
36
|
.join('\n');
|
|
58
|
-
|
|
59
|
-
const allowedNames = step.allowed_tools ?? ['Read'];
|
|
60
|
-
const allowedTools = ALL_TOOLS.filter((t) => allowedNames.includes(t.name));
|
|
61
|
-
if (allowedTools.length === 0) {
|
|
62
|
-
throw new Error(`step ${step.id}: context_files 启用但 allowed_tools=${JSON.stringify(allowedNames)} 没有匹配的可用工具`);
|
|
63
|
-
}
|
|
64
|
-
return yield* runMiniReAct({
|
|
65
|
-
messages: [
|
|
66
|
-
{ role: 'system', content: LLM_STEP_SYSTEM_WITH_TOOLS },
|
|
67
|
-
{ role: 'user', content: augmented },
|
|
68
|
-
],
|
|
69
|
-
tools: allowedTools,
|
|
70
|
-
output_schema: step.output_schema,
|
|
71
|
-
provider: ctx.provider,
|
|
72
|
-
signal: ctx.signal,
|
|
73
|
-
maxTurns: step.maxTurns ?? 10,
|
|
74
|
-
});
|
|
37
|
+
fullPrompt = `${prompt}\n\n**以下上下文文件可用,请用 Read 工具按需读取**:\n${fileList}`;
|
|
75
38
|
}
|
|
76
|
-
//
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
// response_format.json_schema(火山 GLM 等不支持、会被 client.ts 退化掉 response_format),
|
|
80
|
-
// 模型都知道确切字段名与结构 —— 退化路径也能产出正确形状的 JSON,而非瞎猜字段。
|
|
81
|
-
const schemaHint = useSchema
|
|
82
|
-
? `\n\n最终只输出匹配以下 JSON Schema 的 JSON 对象本身(不要解释、不要 markdown 代码块):\n${JSON.stringify(step.output_schema)}`
|
|
39
|
+
// output_schema 约束嵌入 prompt
|
|
40
|
+
const schemaHint = step.output_schema
|
|
41
|
+
? `\n\n【结构化输出约束】请严格按照以下 JSON Schema 输出有效 JSON 对象本身(不要 markdown 代码块包裹):\n${JSON.stringify(step.output_schema, null, 2)}`
|
|
83
42
|
: '';
|
|
84
|
-
|
|
85
|
-
//
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// schema 模式输出是原始 JSON,不当"答案文本"回显,避免屏幕闪 JSON。
|
|
117
|
-
if (!useSchema)
|
|
118
|
-
yield { type: 'text', delta: ev.delta };
|
|
119
|
-
}
|
|
120
|
-
if (ev.type === 'done' && ev.stopReason === 'aborted') {
|
|
121
|
-
throw new Error('用户中断');
|
|
122
|
-
}
|
|
43
|
+
fullPrompt += schemaHint;
|
|
44
|
+
// 通用目标锚定(原始目标 + 补充要求):同 agent.ts,确保每步 LLM 不偏离
|
|
45
|
+
const anchor = effectiveGoalAnchor(ctx);
|
|
46
|
+
const effectivePrompt = anchor ? `${anchor}\n\n${fullPrompt}` : fullPrompt;
|
|
47
|
+
const needsTools = !!step.context_files?.length || step.allowed_tools !== undefined;
|
|
48
|
+
const queryStep = needsTools ? step : { ...step, allowed_tools: [] };
|
|
49
|
+
// llm 步默认单轮;需要工具时允许多轮(读文件→输出)
|
|
50
|
+
const maxTurns = step.maxTurns ?? (step.context_files?.length ? 10 : 1);
|
|
51
|
+
const multimodal = resolveWorkflowMultimodalOptions(step, vars, ctx, (e) => missing.push(e));
|
|
52
|
+
if (missing.length > 0) {
|
|
53
|
+
yield {
|
|
54
|
+
type: 'warning',
|
|
55
|
+
message: `step "${step.id}": 模板变量未定义,已按空串插值:${[...new Set(missing)].map((m) => `\${${m}}`).join('、')}(裸名请用 inputs.<name> 或先 capture/set)`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// 委托 TAOR 引擎执行(共享消费层 runStepQuery:携带 sessionState 以启用上下文压缩,
|
|
59
|
+
// 并统一侦测终结错误——runQuery 遇 LLM 失败是 yield error 后 return 不 throw,
|
|
60
|
+
// 直透会让本步静默返回空文本、runner 的 in-run retry 不触发 → 产出空如空 PLAN.md)。
|
|
61
|
+
const { rawText, aborted, sawLlmError, sawMaxTurns, llmErrorDetail } = yield* runStepQuery(effectivePrompt, queryStep, ctx, {
|
|
62
|
+
maxTurns,
|
|
63
|
+
...multimodal,
|
|
64
|
+
});
|
|
65
|
+
const trimmed = rawText.trim();
|
|
66
|
+
// P0-1:LLM 失败(超时/网络错)且本步无任何产出 → 抛异常,触发 runner 的 max_retries 重跑。
|
|
67
|
+
// 必须放在 output_schema 解析之前(空文本本就无法解析),且只在 !aborted 时抛
|
|
68
|
+
// (用户中断不该被当成可重试失败;aborted 时按现状返回空结果即可)。
|
|
69
|
+
if (!trimmed && sawLlmError && !aborted) {
|
|
70
|
+
throw new Error(describeLlmFailure(step.id, llmErrorDetail));
|
|
71
|
+
}
|
|
72
|
+
// 撞 maxTurns 截断 → 截断时产出不可信,抛可重试失败(续作语义,同 agent.ts)
|
|
73
|
+
if (sawMaxTurns && !aborted) {
|
|
74
|
+
throw new Error(describeMaxTurnsCutoff(step.id, maxTurns));
|
|
123
75
|
}
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
// 思考型模型即便在 strict 下仍会把 think…</think 写进 content(见 jsonPayload.ts
|
|
128
|
-
// 头注与 src/llm/client.ts:200),故先剥思维链/前后散文再 parse;报错仍带原文便于排查。
|
|
129
|
-
const payload = extractJsonPayload(text);
|
|
76
|
+
// 结构化输出模式:解析 JSON
|
|
77
|
+
if (step.output_schema) {
|
|
78
|
+
const payload = extractJsonPayload(trimmed);
|
|
130
79
|
let parsed;
|
|
131
80
|
try {
|
|
132
81
|
parsed = JSON.parse(payload);
|
|
@@ -142,7 +91,7 @@ export async function* execLlmStep(step, vars, ctx) {
|
|
|
142
91
|
preview: `[json] ${trimmed.slice(0, 180)}${trimmed.length > 180 ? '...' : ''}`,
|
|
143
92
|
};
|
|
144
93
|
}
|
|
145
|
-
//
|
|
94
|
+
// 裸文本模式
|
|
146
95
|
return {
|
|
147
96
|
raw: { text: trimmed, result: trimmed },
|
|
148
97
|
preview: trimmed.length > 200 ? `${trimmed.slice(0, 200)}...` : trimmed,
|
|
@@ -1,28 +1,24 @@
|
|
|
1
|
-
// NOTE: output_schema 不支持 skill 节点——loader 现已直接拒绝 skill+output_schema 组合
|
|
2
|
-
// (见 loader.ts validateSteps,P3 修复:静默 no-op 改为加载期报错)。
|
|
3
|
-
// 仅 llm 节点支持 provider-native structured output;vote 通过 runVoter 调 execLlmStep(llm 虚拟步骤)。
|
|
4
1
|
/**
|
|
5
2
|
* ============================================================
|
|
6
|
-
* plugins/workflow-runner/src/stepExecutors/skill.ts —— skill
|
|
3
|
+
* plugins/workflow-runner/src/stepExecutors/skill.ts —— skill 步骤执行器
|
|
7
4
|
* ------------------------------------------------------------
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* v0.9 重构:不再使用独立 subHistory 隔离子循环,而是委托主 TAOR 引擎
|
|
6
|
+
* (runQuery / src/loop.ts)在共享 ctx.history 上执行。
|
|
10
7
|
*
|
|
11
8
|
* 实现要点:
|
|
12
|
-
* - 双源查找:cwd/skills/<name>/SKILL.md 优先,packageRoot/skills/ fallback
|
|
13
|
-
*
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
16
|
-
* -
|
|
17
|
-
* - 收集 text 事件累计为 raw.text,供 capture 绑变量使用
|
|
18
|
-
* - maxTurns 可在 step 里覆盖,默认走 runQuery 自带(50)
|
|
9
|
+
* - 双源查找:cwd/skills/<name>/SKILL.md 优先,packageRoot/skills/ fallback
|
|
10
|
+
* - SKILL.md body 作为用户提示的一部分(系统提示词已在 history[0])
|
|
11
|
+
* - 执行结果直接写入共享 ctx.history,上下文自然积累
|
|
12
|
+
* - 流式转发:runQuery yield 的事件直接透传给 UI
|
|
13
|
+
* - maxTurns 可在 step 里覆盖(默认 25)
|
|
19
14
|
*
|
|
20
15
|
* capture:{ text: var_name } / { result: var_name }
|
|
21
16
|
* ============================================================
|
|
22
17
|
*/
|
|
23
18
|
import { readdir, readFile } from 'node:fs/promises';
|
|
24
19
|
import { join } from 'node:path';
|
|
25
|
-
import { getResourceSearchPaths
|
|
20
|
+
import { getResourceSearchPaths } from '../../../../src/plugin-sdk.js';
|
|
21
|
+
import { describeLlmFailure, describeMaxTurnsCutoff, effectiveGoalAnchor, runStepQuery, } from '../agentCommon.js';
|
|
26
22
|
import { interpolate } from '../expressions.js';
|
|
27
23
|
function stripFrontmatter(content) {
|
|
28
24
|
return content.replace(/^---\n[\s\S]*?\n---\n?/, '');
|
|
@@ -36,8 +32,8 @@ function parseFrontmatterName(content) {
|
|
|
36
32
|
return null;
|
|
37
33
|
return nm[1].trim().replace(/^["']|["']$/g, '');
|
|
38
34
|
}
|
|
39
|
-
async function findSkillFile(skillName) {
|
|
40
|
-
const roots = getResourceSearchPaths('skills', import.meta.url);
|
|
35
|
+
async function findSkillFile(skillName, cwd) {
|
|
36
|
+
const roots = getResourceSearchPaths('skills', import.meta.url, cwd);
|
|
41
37
|
for (const root of roots) {
|
|
42
38
|
let entries;
|
|
43
39
|
try {
|
|
@@ -58,7 +54,7 @@ async function findSkillFile(skillName) {
|
|
|
58
54
|
return skillFile;
|
|
59
55
|
}
|
|
60
56
|
catch {
|
|
61
|
-
|
|
57
|
+
continue;
|
|
62
58
|
}
|
|
63
59
|
}
|
|
64
60
|
}
|
|
@@ -68,43 +64,47 @@ export async function* execSkillStep(step, vars, ctx) {
|
|
|
68
64
|
if (!step.skill)
|
|
69
65
|
throw new Error(`step ${step.id}: 缺少 skill 字段`);
|
|
70
66
|
const skillName = interpolate(step.skill, vars);
|
|
71
|
-
const skillFile = await findSkillFile(skillName);
|
|
67
|
+
const skillFile = await findSkillFile(skillName, ctx.cwd);
|
|
72
68
|
if (!skillFile) {
|
|
73
69
|
throw new Error(`step ${step.id}: 未找到 skill "${skillName}"(cwd/skills/ 与 packageRoot/skills/ 双源均未命中)`);
|
|
74
70
|
}
|
|
75
71
|
const md = await readFile(skillFile, 'utf8');
|
|
76
72
|
const body = stripFrontmatter(md).trim();
|
|
73
|
+
// 构造用户提示:skill 指令 + 步骤 input
|
|
74
|
+
// 系统提示词已在 history[0] 中(含完整 skill 列表和描述),
|
|
75
|
+
// 这里不需要再拼 system message——把 SKILL.md body 作为操作指令即可
|
|
76
|
+
const missing = [];
|
|
77
77
|
const userInput = step.input
|
|
78
|
-
? interpolate(step.input, vars)
|
|
79
|
-
:
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
78
|
+
? interpolate(step.input, vars, { onMissing: (e) => missing.push(e) })
|
|
79
|
+
: `请按以下 SKILL "${skillName}" 的指示完成任务。`;
|
|
80
|
+
const fullPrompt = `【执行 Skill:${skillName}】\n\n${body}\n\n---\n\n当前任务:\n${userInput}`;
|
|
81
|
+
// 通用目标锚定(原始目标 + 补充要求):确保 skill 执行时也不偏离
|
|
82
|
+
const anchor = effectiveGoalAnchor(ctx);
|
|
83
|
+
const effectivePrompt = anchor ? `${anchor}\n\n${fullPrompt}` : fullPrompt;
|
|
84
|
+
const maxTurns = step.maxTurns ?? 25;
|
|
85
|
+
if (missing.length > 0) {
|
|
86
|
+
yield {
|
|
87
|
+
type: 'warning',
|
|
88
|
+
message: `step "${step.id}": 模板变量未定义,已按空串插值:${[...new Set(missing)].map((m) => `\${${m}}`).join('、')}(裸名请用 inputs.<name> 或先 capture/set)`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// 委托 TAOR 引擎在共享 history 上执行(共享消费层 runStepQuery)。
|
|
92
|
+
// suppressTurnDone:turn_done 是 runQuery 单次调用的终结标记,不是 workflow 终结,
|
|
93
|
+
// 外泄会导致 gateway broker / -p json 模式误判 workflow 中途结束。
|
|
94
|
+
const { rawText, aborted, sawLlmError, sawMaxTurns, llmErrorDetail } = yield* runStepQuery(effectivePrompt, step, ctx, {
|
|
95
|
+
maxTurns,
|
|
96
|
+
suppressTurnDone: true,
|
|
97
|
+
});
|
|
98
|
+
const trimmed = rawText.trim();
|
|
99
|
+
// P0-1:LLM 失败(超时/网络错)且本步无任何产出 → 抛异常,触发 runner 的 max_retries 重跑。
|
|
100
|
+
// 用户中断(aborted)不该被当成可重试失败,按现状返回空结果即可。
|
|
101
|
+
if (!trimmed && sawLlmError && !aborted) {
|
|
102
|
+
throw new Error(describeLlmFailure(step.id, llmErrorDetail));
|
|
103
|
+
}
|
|
104
|
+
// 撞 maxTurns 截断 → 截断时产出不可信,抛可重试失败(续作语义,同 agent.ts)
|
|
105
|
+
if (sawMaxTurns && !aborted) {
|
|
106
|
+
throw new Error(describeMaxTurnsCutoff(step.id, maxTurns));
|
|
106
107
|
}
|
|
107
|
-
const trimmed = text.trim();
|
|
108
108
|
return {
|
|
109
109
|
raw: { text: trimmed, result: trimmed },
|
|
110
110
|
preview: trimmed.length > 200 ? `${trimmed.slice(0, 200)}...` : trimmed,
|