minimal-agent 0.9.0 → 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 +11 -8
- 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 +2 -1
- package/plugins/workflow-runner/src/agentCommon.js +172 -9
- package/plugins/workflow-runner/src/dslManifest.js +72 -0
- package/plugins/workflow-runner/src/expressions.js +150 -13
- package/plugins/workflow-runner/src/index.js +39 -8
- package/plugins/workflow-runner/src/loader.js +216 -64
- package/plugins/workflow-runner/src/multimodal.js +37 -0
- package/plugins/workflow-runner/src/recovery.js +26 -24
- package/plugins/workflow-runner/src/runner.js +693 -287
- package/plugins/workflow-runner/src/stepExecutors/agent.js +126 -37
- package/plugins/workflow-runner/src/stepExecutors/assert.js +3 -2
- package/plugins/workflow-runner/src/stepExecutors/llm.js +38 -30
- package/plugins/workflow-runner/src/stepExecutors/skill.js +27 -38
- package/plugins/workflow-runner/src/stepExecutors/tool.js +56 -3
- package/plugins/workflow-runner/src/stepExecutors/verify.js +19 -10
- package/plugins/workflow-runner/src/taskIdentity.js +185 -30
- package/plugins/workflow-runner/src/types.js +18 -7
- package/plugins/workflow-runner/src/workflowState.js +355 -55
- 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 +87 -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 +3 -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 +3 -2
- package/src/llm/client.js +293 -206
- package/src/llm/providers/anthropicFormat.js +241 -0
- package/src/llm/providers/openaiFormat.js +190 -0
- package/src/loop.js +211 -27
- 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/pluginRunner.js +40 -0
- package/src/plugins/transcript.js +4 -3
- package/src/prompts/pluginList.js +2 -2
- package/src/prompts/projectInstructions.js +3 -3
- package/src/prompts/promptAssembly.js +133 -109
- package/src/prompts/skillList.js +12 -22
- 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 +19 -17
- package/src/ui/InputBox.js +34 -9
- 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 +345 -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 +9 -2
- package/workflows/book-review-short.yaml +31 -7
- package/workflows/e2e-write-greet.yaml +3 -0
- package/workflows/illustrate.yaml +227 -0
- package/workflows/plan.yaml +437 -207
- package/workflows/ppt.yaml +1659 -0
- package/workflows/ralph-loop.yaml +142 -112
- package/workflows/schema.json +81 -23
- package/workflows/webppt.yaml +496 -0
- package/workflows/word.yaml +710 -0
- package/workflows/youtube-shorts.yaml +38 -10
- package/MINIMAL-TRACE.md +0 -77
- 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/skills/pptx/scripts/office/__pycache__/soffice.cpython-314.pyc +0 -0
- package/src/ui/ProgressPanel.js +0 -54
- package/src/ui/StreamingBlock.js +0 -11
- package/src/ui/ToolStatus.js +0 -11
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { constants, copyFile, mkdir, readFile, rename, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { cronToHuman } from './cronTime.js';
|
|
6
|
+
import { intervalToHuman, nextScheduleRunMs } from './scheduleEngine.js';
|
|
7
|
+
import { schedulerLockFile } from './lock.js';
|
|
8
|
+
import { appendMissed as appendMissedRecord, appendRun as appendRunRecord, listMissed as listMissedRecords, markMissedRead as markMissedRecordsRead, markRunsRead as markRunRecordsRead, recentRuns as readRecentRuns } from './runs.js';
|
|
9
|
+
import { normalizeTask } from './schema.js';
|
|
10
|
+
function root() {
|
|
11
|
+
return process.env.MINIMAL_AGENT_CRON_RUNNER_HOME
|
|
12
|
+
? join(process.env.MINIMAL_AGENT_CRON_RUNNER_HOME, 'cron-runner')
|
|
13
|
+
: join(homedir(), '.minimal-agent', 'plugins', 'cron-runner');
|
|
14
|
+
}
|
|
15
|
+
function tasksFile() {
|
|
16
|
+
return join(root(), 'tasks.json');
|
|
17
|
+
}
|
|
18
|
+
function runsDir() {
|
|
19
|
+
return join(root(), 'runs');
|
|
20
|
+
}
|
|
21
|
+
function missedFile() {
|
|
22
|
+
return join(root(), 'missed.jsonl');
|
|
23
|
+
}
|
|
24
|
+
let mutationQueue = Promise.resolve();
|
|
25
|
+
const taskChangeListeners = new Set();
|
|
26
|
+
function notifyTaskChanges() {
|
|
27
|
+
for (const listener of taskChangeListeners)
|
|
28
|
+
listener();
|
|
29
|
+
}
|
|
30
|
+
export function subscribeTaskChanges(listener) {
|
|
31
|
+
taskChangeListeners.add(listener);
|
|
32
|
+
return () => taskChangeListeners.delete(listener);
|
|
33
|
+
}
|
|
34
|
+
export function cronDataRoot() {
|
|
35
|
+
return root();
|
|
36
|
+
}
|
|
37
|
+
export function cronLockFile() {
|
|
38
|
+
return schedulerLockFile(root());
|
|
39
|
+
}
|
|
40
|
+
/** Upgrade legacy fresh/hidden-session tasks once, keeping an immutable pre-migration backup. */
|
|
41
|
+
export async function migrateCronTasks() {
|
|
42
|
+
return await enqueueMutation(async () => {
|
|
43
|
+
let raw;
|
|
44
|
+
try {
|
|
45
|
+
raw = await readFile(tasksFile(), 'utf8');
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
let parsed;
|
|
51
|
+
try {
|
|
52
|
+
parsed = JSON.parse(raw);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
if (!Array.isArray(parsed.tasks))
|
|
58
|
+
return false;
|
|
59
|
+
const needsMigration = parsed.tasks.some((value) => {
|
|
60
|
+
const task = value;
|
|
61
|
+
return !task.schedule || !('type' in task.schedule) || !task.runtime?.bindingStatus || task.runtime.sessionMode === 'fresh' || task.runtime.sessionId?.startsWith('cron-');
|
|
62
|
+
});
|
|
63
|
+
if (!needsMigration)
|
|
64
|
+
return false;
|
|
65
|
+
await mkdir(root(), { recursive: true });
|
|
66
|
+
try {
|
|
67
|
+
await copyFile(tasksFile(), join(root(), 'tasks.pre-session-binding.backup.json'), constants.COPYFILE_EXCL);
|
|
68
|
+
}
|
|
69
|
+
catch { /* existing backup is intentionally retained */ }
|
|
70
|
+
const migrated = parsed.tasks.map(normalizeTask).filter((task) => Boolean(task));
|
|
71
|
+
await writeTasksFile(migrated);
|
|
72
|
+
notifyTaskChanges();
|
|
73
|
+
return true;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
async function readTasks(fromMs = Date.now()) {
|
|
77
|
+
try {
|
|
78
|
+
const raw = await readFile(tasksFile(), 'utf8');
|
|
79
|
+
const parsed = JSON.parse(raw);
|
|
80
|
+
return Array.isArray(parsed.tasks)
|
|
81
|
+
? parsed.tasks
|
|
82
|
+
.map(normalizeTask)
|
|
83
|
+
.filter((task) => Boolean(task))
|
|
84
|
+
// 注意:不能写成 .map(refreshNextRun)——Array.map 会把 (element, index, array)
|
|
85
|
+
// 全传进去,第二个实参 index(0,1,2...) 会顶掉 refreshNextRun 的 fromMs=Date.now()
|
|
86
|
+
// 默认值,导致 nextRunAt/expired 全按 Unix 纪元(≈0ms)计算(真机 e2e 抓到
|
|
87
|
+
// nextRunAt 恒为 1970-01-01)。必须用箭头包一层只透传 task。
|
|
88
|
+
.map((task) => refreshNextRun(task, fromMs))
|
|
89
|
+
: [];
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export async function listTasks() {
|
|
96
|
+
return await readTasks();
|
|
97
|
+
}
|
|
98
|
+
async function writeTasksFile(tasks) {
|
|
99
|
+
const file = tasksFile();
|
|
100
|
+
await mkdir(dirname(file), { recursive: true });
|
|
101
|
+
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
102
|
+
await writeFile(tmp, JSON.stringify({ tasks: tasks.map((task) => refreshNextRun(task)) }, null, 2), 'utf8');
|
|
103
|
+
await rename(tmp, file);
|
|
104
|
+
}
|
|
105
|
+
function enqueueMutation(mutate) {
|
|
106
|
+
const operation = mutationQueue.then(mutate, mutate);
|
|
107
|
+
mutationQueue = operation.then(() => undefined, () => undefined);
|
|
108
|
+
return operation;
|
|
109
|
+
}
|
|
110
|
+
export async function writeTasks(tasks) {
|
|
111
|
+
await enqueueMutation(async () => {
|
|
112
|
+
await writeTasksFile(tasks);
|
|
113
|
+
notifyTaskChanges();
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
export async function upsertTask(task) {
|
|
117
|
+
return await enqueueMutation(async () => {
|
|
118
|
+
const tasks = await readTasks();
|
|
119
|
+
const idx = tasks.findIndex((t) => t.id === task.id);
|
|
120
|
+
const saved = refreshNextRun({ ...task, updatedAt: new Date().toISOString() });
|
|
121
|
+
if (idx >= 0)
|
|
122
|
+
tasks[idx] = saved;
|
|
123
|
+
else
|
|
124
|
+
tasks.push(saved);
|
|
125
|
+
await writeTasksFile(tasks);
|
|
126
|
+
notifyTaskChanges();
|
|
127
|
+
return saved;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
export async function updateTask(id, updater) {
|
|
131
|
+
return await enqueueMutation(async () => {
|
|
132
|
+
const tasks = await readTasks();
|
|
133
|
+
const idx = tasks.findIndex((task) => task.id === id);
|
|
134
|
+
if (idx < 0)
|
|
135
|
+
return undefined;
|
|
136
|
+
const saved = refreshNextRun({
|
|
137
|
+
...updater(tasks[idx]),
|
|
138
|
+
updatedAt: new Date().toISOString(),
|
|
139
|
+
});
|
|
140
|
+
tasks[idx] = saved;
|
|
141
|
+
await writeTasksFile(tasks);
|
|
142
|
+
notifyTaskChanges();
|
|
143
|
+
return saved;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
export async function deleteTask(id) {
|
|
147
|
+
return await enqueueMutation(async () => {
|
|
148
|
+
const tasks = await readTasks();
|
|
149
|
+
const next = tasks.filter((t) => t.id !== id);
|
|
150
|
+
if (next.length === tasks.length)
|
|
151
|
+
return false;
|
|
152
|
+
await writeTasksFile(next);
|
|
153
|
+
notifyTaskChanges();
|
|
154
|
+
return true;
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
export async function getTask(idOrPrefix) {
|
|
158
|
+
const tasks = await listTasks();
|
|
159
|
+
return tasks.find((t) => t.id === idOrPrefix) ?? tasks.find((t) => t.id.startsWith(idOrPrefix));
|
|
160
|
+
}
|
|
161
|
+
export async function appendRun(record) {
|
|
162
|
+
await appendRunRecord(runsDir(), record);
|
|
163
|
+
}
|
|
164
|
+
export async function recentRuns(taskId, limit = 5) {
|
|
165
|
+
return await readRecentRuns(runsDir(), taskId, limit);
|
|
166
|
+
}
|
|
167
|
+
export async function markRunsRead(taskId) {
|
|
168
|
+
await markRunRecordsRead(runsDir(), taskId);
|
|
169
|
+
}
|
|
170
|
+
export async function appendMissed(record) {
|
|
171
|
+
await appendMissedRecord(missedFile(), record);
|
|
172
|
+
}
|
|
173
|
+
export async function listMissed(limit = 20) {
|
|
174
|
+
return await listMissedRecords(missedFile(), limit);
|
|
175
|
+
}
|
|
176
|
+
export async function markMissedRead(taskId) {
|
|
177
|
+
await markMissedRecordsRead(missedFile(), taskId);
|
|
178
|
+
}
|
|
179
|
+
export function createTask(input) {
|
|
180
|
+
const now = new Date().toISOString();
|
|
181
|
+
const id = `cron-${randomUUID().slice(0, 8)}`;
|
|
182
|
+
if (!input.cron && !input.intervalMs) {
|
|
183
|
+
throw new Error('createTask requires cron or intervalMs');
|
|
184
|
+
}
|
|
185
|
+
const schedule = input.intervalMs
|
|
186
|
+
? {
|
|
187
|
+
type: 'interval',
|
|
188
|
+
intervalMs: input.intervalMs,
|
|
189
|
+
anchorAt: input.anchorAt ?? now,
|
|
190
|
+
human: intervalToHuman(input.intervalMs),
|
|
191
|
+
jitterMs: input.jitterMs ?? 0,
|
|
192
|
+
}
|
|
193
|
+
: {
|
|
194
|
+
type: 'cron',
|
|
195
|
+
cron: input.cron,
|
|
196
|
+
timezone: input.timezone,
|
|
197
|
+
human: cronToHuman(input.cron),
|
|
198
|
+
jitterMs: input.jitterMs ?? 0,
|
|
199
|
+
};
|
|
200
|
+
return refreshNextRun({
|
|
201
|
+
id,
|
|
202
|
+
name: input.name,
|
|
203
|
+
...(input.description ? { description: input.description } : {}),
|
|
204
|
+
status: 'active',
|
|
205
|
+
kind: input.kind ?? 'recurring',
|
|
206
|
+
...(input.permanent ? { permanent: true } : {}),
|
|
207
|
+
...(input.expiresAt ? { expiresAt: input.expiresAt } : {}),
|
|
208
|
+
...(input.maxRuns ? { maxRuns: input.maxRuns } : {}),
|
|
209
|
+
schedule,
|
|
210
|
+
action: input.action,
|
|
211
|
+
runtime: {
|
|
212
|
+
cwd: input.cwd,
|
|
213
|
+
environment: 'project',
|
|
214
|
+
sessionId: input.sessionId ?? 'default',
|
|
215
|
+
sessionMode: input.sessionMode ?? 'persistent',
|
|
216
|
+
bindingStatus: (!input.sessionId || !input.sessionId.startsWith('cron-')) && input.sessionMode !== 'fresh'
|
|
217
|
+
? 'bound'
|
|
218
|
+
: 'needs_binding',
|
|
219
|
+
...(input.model ? { model: input.model } : {}),
|
|
220
|
+
...(input.maxTurns ? { maxTurns: input.maxTurns } : {}),
|
|
221
|
+
},
|
|
222
|
+
stats: {
|
|
223
|
+
runCount: 0,
|
|
224
|
+
successCount: 0,
|
|
225
|
+
failureCount: 0,
|
|
226
|
+
skippedCount: 0,
|
|
227
|
+
},
|
|
228
|
+
createdAt: now,
|
|
229
|
+
updatedAt: now,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
export function refreshNextRun(task, fromMs = Date.now()) {
|
|
233
|
+
const expired = task.expiresAt && !task.permanent && Date.parse(task.expiresAt) <= fromMs;
|
|
234
|
+
const next = task.status === 'active' && !expired
|
|
235
|
+
? nextScheduleRunMs(task.schedule, fromMs)
|
|
236
|
+
: null;
|
|
237
|
+
return {
|
|
238
|
+
...task,
|
|
239
|
+
...(expired ? { status: 'completed' } : {}),
|
|
240
|
+
schedule: {
|
|
241
|
+
...task.schedule,
|
|
242
|
+
human: task.schedule.type === 'cron'
|
|
243
|
+
? cronToHuman(task.schedule.cron)
|
|
244
|
+
: intervalToHuman(task.schedule.intervalMs),
|
|
245
|
+
jitterMs: typeof task.schedule.jitterMs === 'number' ? task.schedule.jitterMs : 0,
|
|
246
|
+
...(next ? { nextRunAt: new Date(next).toISOString() } : { nextRunAt: undefined }),
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/** Update only user-editable fields while preserving scheduler cursors, stats and creation time. */
|
|
251
|
+
export async function patchTask(patch) {
|
|
252
|
+
return await updateTask(patch.id, (current) => {
|
|
253
|
+
const nextSchedule = patch.schedule
|
|
254
|
+
? patch.schedule.type === 'cron'
|
|
255
|
+
? {
|
|
256
|
+
...current.schedule,
|
|
257
|
+
type: 'cron',
|
|
258
|
+
cron: patch.schedule.cron,
|
|
259
|
+
timezone: patch.schedule.timezone,
|
|
260
|
+
jitterMs: patch.schedule.jitterMs ?? 0,
|
|
261
|
+
human: cronToHuman(patch.schedule.cron),
|
|
262
|
+
}
|
|
263
|
+
: {
|
|
264
|
+
...current.schedule,
|
|
265
|
+
type: 'interval',
|
|
266
|
+
intervalMs: patch.schedule.intervalMs,
|
|
267
|
+
anchorAt: patch.schedule.anchorAt ?? new Date().toISOString(),
|
|
268
|
+
jitterMs: patch.schedule.jitterMs ?? 0,
|
|
269
|
+
human: intervalToHuman(patch.schedule.intervalMs),
|
|
270
|
+
}
|
|
271
|
+
: current.schedule;
|
|
272
|
+
const runtime = patch.runtime
|
|
273
|
+
? {
|
|
274
|
+
...current.runtime,
|
|
275
|
+
...patch.runtime,
|
|
276
|
+
sessionMode: 'persistent',
|
|
277
|
+
bindingStatus: patch.runtime.sessionId && !patch.runtime.sessionId.startsWith('cron-')
|
|
278
|
+
? 'bound'
|
|
279
|
+
: current.runtime.bindingStatus,
|
|
280
|
+
}
|
|
281
|
+
: current.runtime;
|
|
282
|
+
return {
|
|
283
|
+
...current,
|
|
284
|
+
...(patch.name !== undefined ? { name: patch.name.trim() } : {}),
|
|
285
|
+
...(patch.description !== undefined
|
|
286
|
+
? patch.description.trim() ? { description: patch.description.trim() } : { description: undefined }
|
|
287
|
+
: {}),
|
|
288
|
+
...(patch.status !== undefined ? { status: patch.status } : {}),
|
|
289
|
+
...(patch.kind !== undefined ? { kind: patch.kind } : {}),
|
|
290
|
+
...(patch.permanent !== undefined ? { permanent: patch.permanent || undefined } : {}),
|
|
291
|
+
...(patch.expiresAt !== undefined ? { expiresAt: patch.expiresAt || undefined } : {}),
|
|
292
|
+
...(patch.maxRuns !== undefined ? { maxRuns: patch.maxRuns || undefined } : {}),
|
|
293
|
+
schedule: nextSchedule,
|
|
294
|
+
...(patch.action ? { action: patch.action } : {}),
|
|
295
|
+
runtime,
|
|
296
|
+
};
|
|
297
|
+
});
|
|
298
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -45,10 +45,10 @@ steps:
|
|
|
45
45
|
- `allowed_tools: [Read, Write]` —— 收窄它能用的工具;**缺省给全量工具**(要真 agency)。
|
|
46
46
|
- `output_schema: {...}` —— 要求结构化产出(provider-native JSON Schema),按字段 `capture`。
|
|
47
47
|
- `context_files: [{ path, hint }]` —— 列出可读文件让它按需 Read(不 inline 内容)。
|
|
48
|
-
- `maxTurns: <n>` —— 子循环最大轮数,默认
|
|
48
|
+
- `maxTurns: <n>` —— 子循环最大轮数,默认 25。
|
|
49
49
|
- `capture` / `when` / `onError` —— 与其它动作 step 一致(agent 节点也能 `onError: recover` 被再救一次)。
|
|
50
50
|
|
|
51
|
-
`agent` vs `skill`:`agent` 是 **inline
|
|
51
|
+
`agent` vs `skill`:`agent` 是 **inline、一次性**的有界 TAOR 子循环(委托 runQuery,轻、收敛快、产出受验证闸门把关);
|
|
52
52
|
`skill` 是跑一个**外部 SKILL.md 定义、可复用**的完整 agent(runQuery)。需要复用同一套能力用 `skill`,
|
|
53
53
|
临时让某步「自己想办法」用 `agent`。
|
|
54
54
|
|
|
@@ -75,7 +75,7 @@ steps:
|
|
|
75
75
|
|
|
76
76
|
- `recover_hint: "<提示>"` —— 给恢复 agent 的提示(支持 `${var}` 插值),如 `"端口被占就换 3001 重试"`。
|
|
77
77
|
- `allowed_tools: [Read, Bash]` —— 收窄恢复 agent 能用的工具;**缺省给全量工具**。
|
|
78
|
-
- `maxTurns: <n>` —— 恢复子循环最大轮数,默认
|
|
78
|
+
- `maxTurns: <n>` —— 恢复子循环最大轮数,默认 25(够「诊断 + 探查 + 动手 + 验证」一圈)。
|
|
79
79
|
|
|
80
80
|
示例:
|
|
81
81
|
|
|
@@ -91,7 +91,7 @@ steps:
|
|
|
91
91
|
|
|
92
92
|
注意事项:
|
|
93
93
|
|
|
94
|
-
- `onError` **只作用于动作 step**。控制流节点(branch / loop
|
|
94
|
+
- `onError` **只作用于动作 step**。控制流节点(branch / loop 的条件或结构错误、
|
|
95
95
|
以及 `when` 表达式错误)**始终 halt** —— 那类是「作者写错了」,不是「运行期意外」,不走恢复。
|
|
96
96
|
- `continue` vs `recover`:前者「放弃这步、盲目往下」,后者「想办法把这步做成、保住下游」。
|
|
97
97
|
要扛住「预料之外」的情况,用 `recover`。
|
|
@@ -5,6 +5,6 @@ description: 列出当前 cwd 与插件包内可用的 YAML 工作流
|
|
|
5
5
|
# /workflows
|
|
6
6
|
|
|
7
7
|
由 workflow-runner 插件接管(plugin.ts.runCommand),扫描 cwd/workflows/ 与
|
|
8
|
-
|
|
8
|
+
packageRoot/workflows/(getResourceSearchPaths 双源,cwd 优先)下的 *.yaml,把名称 + 一行描述列出来。
|
|
9
9
|
|
|
10
10
|
提示:用 `agent:` 节点可把开放式的一步交给有界 TAOR 子 agent 随机应变完成;用 `onError: recover` 可让失败节点交给恢复 agent 自适应救回(而非整条崩停)。二者共用同一套「自我验证 / 不伪造」纪律——详见 `/workflow` 命令说明。
|
|
@@ -21,12 +21,13 @@ const api = {
|
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
if (commandName === 'workflow') {
|
|
24
|
+
const cwd = getWorkingDir();
|
|
24
25
|
yield* runWorkflowFromCommand(args, {
|
|
25
26
|
provider: ctx.provider,
|
|
26
27
|
history: ctx.history,
|
|
27
28
|
signal: ctx.signal,
|
|
28
29
|
sessionState: ctx.sessionState,
|
|
29
|
-
cwd
|
|
30
|
+
cwd,
|
|
30
31
|
tools: ALL_TOOLS,
|
|
31
32
|
});
|
|
32
33
|
return;
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
* ③ 检测逻辑增加内容长度启发式(reason > 80 字符视为误报)
|
|
20
20
|
* ============================================================
|
|
21
21
|
*/
|
|
22
|
+
import { runQuery, stripThinkBlocks, } from '../../../src/plugin-sdk.js';
|
|
23
|
+
import { normalizeCapture, } from './types.js';
|
|
22
24
|
/**
|
|
23
25
|
* agent 显式放弃的唯一标记;recover 与 agent 节点共用。
|
|
24
26
|
*
|
|
@@ -28,13 +30,11 @@
|
|
|
28
30
|
* - 使用 [bracket] 格式而非 ⟨angle⟩(避免 Unicode 字符在 Bun indexOf 中行为不一致)
|
|
29
31
|
*/
|
|
30
32
|
export const GIVEUP_MARKER = '[wf-internal-abort-do-not-generate]';
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
/** 把 step.capture 翻成「下游会把你的结果存成哪些变量」,让 agent 产出对得上形状。
|
|
34
|
+
* 经 normalizeCapture:裸字符串 capture(capture: design_doc)不再被拆成单字符
|
|
35
|
+
* 【d、e、s…】,而是正确显示为【design_doc】。 */
|
|
34
36
|
export function describeCaptureContract(step) {
|
|
35
|
-
|
|
36
|
-
return '';
|
|
37
|
-
const names = Object.values(step.capture);
|
|
37
|
+
const names = Object.values(normalizeCapture(step.capture));
|
|
38
38
|
if (names.length === 0)
|
|
39
39
|
return '';
|
|
40
40
|
return `\n\n下游契约:工作流会把你的结果保存为变量【${names.join('、')}】供后续步骤引用,请确保你的产出能填好这些变量。`;
|
|
@@ -42,6 +42,168 @@ export function describeCaptureContract(step) {
|
|
|
42
42
|
export function truncate(s, n) {
|
|
43
43
|
return s.length > n ? `${s.slice(0, n)}…` : s;
|
|
44
44
|
}
|
|
45
|
+
// stripThinkBlocks 已上移内核 src/utils/stripThink.ts(Agent 子任务工具同样需要,
|
|
46
|
+
// 内核不能 import 插件)——顶部 import 供本模块使用,此处 re-export 保持插件内
|
|
47
|
+
// 既有 import 路径不变。
|
|
48
|
+
export { stripThinkBlocks };
|
|
49
|
+
/**
|
|
50
|
+
* 组合「原始目标锚 + 累积的用户补充要求」为本步实际注入的锚定文本。
|
|
51
|
+
* agent / llm / skill / recovery 四个执行器统一经此取锚——补充要求
|
|
52
|
+
* (pause 审批反馈 / goal_supplement 步产出 / 仲裁延续的新指令)与原始目标
|
|
53
|
+
* 同等贯穿每一步,不再只活在被修订的文件或某个变量里。
|
|
54
|
+
* 返回空串 = 无锚(执行器跳过注入,行为同旧 ctx.goalAnchor 为空)。
|
|
55
|
+
*/
|
|
56
|
+
export function effectiveGoalAnchor(ctx) {
|
|
57
|
+
const base = ctx.goalAnchor ?? '';
|
|
58
|
+
const supps = (ctx.goalSupplements ?? []).filter((s) => s.trim());
|
|
59
|
+
if (supps.length === 0)
|
|
60
|
+
return base;
|
|
61
|
+
const lines = supps.map((s) => `> 📌 用户补充要求:${s}`).join('\n');
|
|
62
|
+
return base ? `${base}\n${lines}` : `${lines}\n> ⚠️ 以上补充要求与原始目标同等约束所有操作。`;
|
|
63
|
+
}
|
|
64
|
+
/** 把 llm_error 细节拼进可重试失败的抛错文案(无细节时退化为原样文案)。 */
|
|
65
|
+
export function describeLlmFailure(stepId, detail) {
|
|
66
|
+
const base = `step ${stepId}: LLM 调用失败且无产出(触发重试)`;
|
|
67
|
+
return detail ? `${base}—— ${truncate(detail, 300)}` : base;
|
|
68
|
+
}
|
|
69
|
+
function cloneMessage(msg) {
|
|
70
|
+
if (msg.role === 'user' && Array.isArray(msg.content)) {
|
|
71
|
+
return { ...msg, content: msg.content.map((part) => ({ ...part })) };
|
|
72
|
+
}
|
|
73
|
+
return { ...msg };
|
|
74
|
+
}
|
|
75
|
+
function createStepHistory(step, ctx) {
|
|
76
|
+
if (step.history_mode !== 'isolated')
|
|
77
|
+
return ctx.history;
|
|
78
|
+
return ctx.history.filter((msg) => msg.role === 'system').map(cloneMessage);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* agent / llm / skill 三个执行器共享的 runQuery 消费层。
|
|
82
|
+
*
|
|
83
|
+
* 为什么不能各自 `yield*` 直透(曾经的三份拷贝、agent.ts 漏同步酿成误报):
|
|
84
|
+
* runQuery 遇 LLM 超时/网络错是 yield error 后 return(不 throw),直透会让
|
|
85
|
+
* 执行器拿到空 history → 静默返回空文本 → runner 的 in-run retry 不触发
|
|
86
|
+
* (只对抛异常的 step 重试)。这里统一显式消费、侦测终结错误,把
|
|
87
|
+
* 「拿产出 + 记旗标」收敛成一份;**空产出 + sawLlmError 时抛不抛错的语义
|
|
88
|
+
* 差异保留在各执行器**(agent 还要过验证闸门,llm/skill 不过)。
|
|
89
|
+
*
|
|
90
|
+
* 事件透传逐字节等价于重构前:
|
|
91
|
+
* - error / interrupted 照常冒泡(红字照常显示,retry 交给 runner)
|
|
92
|
+
* - 'compact_failed' 非致命,不计为失败
|
|
93
|
+
* - suppressTurnDone(仅 skill 传 true):turn_done 是 runQuery 单次调用的
|
|
94
|
+
* 终结标记,不是 workflow 终结,外泄会让 gateway broker / -p json 误判
|
|
95
|
+
*/
|
|
96
|
+
export async function* runStepQuery(prompt, step, ctx, opts) {
|
|
97
|
+
const activeHistory = createStepHistory(step, ctx);
|
|
98
|
+
// 记录 runQuery 开始前的 history 长度,用于之后提取本步的 assistant 输出
|
|
99
|
+
const historyLenBefore = activeHistory.length;
|
|
100
|
+
let aborted = false;
|
|
101
|
+
let sawLlmError = false;
|
|
102
|
+
let sawMaxTurns = false;
|
|
103
|
+
let llmErrorDetail = '';
|
|
104
|
+
let sawToolCall = false;
|
|
105
|
+
let toolOkCount = 0;
|
|
106
|
+
let toolFailCount = 0;
|
|
107
|
+
const toolNames = [];
|
|
108
|
+
for await (const ev of runQuery(prompt, {
|
|
109
|
+
provider: ctx.provider,
|
|
110
|
+
history: activeHistory,
|
|
111
|
+
signal: ctx.signal,
|
|
112
|
+
maxTurns: opts.maxTurns,
|
|
113
|
+
allowedTools: step.allowed_tools,
|
|
114
|
+
chat: ctx.chat,
|
|
115
|
+
executeTool: ctx.executeTool,
|
|
116
|
+
sessionState: ctx.sessionState,
|
|
117
|
+
imageInputs: opts.imageInputs,
|
|
118
|
+
parseInlineImages: opts.parseInlineImages,
|
|
119
|
+
imageDetail: opts.imageDetail,
|
|
120
|
+
imageMaxLongSidePixel: opts.imageMaxLongSidePixel,
|
|
121
|
+
})) {
|
|
122
|
+
if (ev.type === 'error') {
|
|
123
|
+
if (ev.code === 'aborted') {
|
|
124
|
+
aborted = true;
|
|
125
|
+
}
|
|
126
|
+
else if (ev.code === 'llm_error') {
|
|
127
|
+
sawLlmError = true;
|
|
128
|
+
llmErrorDetail = ev.error; // 留住 provider 真实报错,供执行器抛错时附带
|
|
129
|
+
// 🚫 不原样把这条 raw error 事件漏给顶层消费者(2026-07-04 真机事故:-p 模式
|
|
130
|
+
// 收到任意 type:'error' 就 handleEvent→exitCode:1→process.exit(),把整个 -p 进程
|
|
131
|
+
// 杀死在这里——比 runner.ts 的 in-run retry(max_retries/onError:continue)先一步
|
|
132
|
+
// 判定「终结」,等于跳过了整套设计好的重试/降级机制。这条信号已被上面两行转成
|
|
133
|
+
// sawLlmError/llmErrorDetail,稍后由本函数调用方(agent.ts 等)转成规范的可重试
|
|
134
|
+
// Error 抛出,交给 runner.ts 的 catch 块按 max_retries/onError 决定真正要不要终结、
|
|
135
|
+
// 要终结时也是由 runner.ts 在恰当时机重新 yield 一条 warning/error,不需要这条 raw 事件。
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
else if (ev.code === 'max_turns') {
|
|
139
|
+
sawMaxTurns = true;
|
|
140
|
+
// 同上:max_turns 截断本是「可续跑」信号(isMaxTurnsCutoff),必须留给 runner.ts
|
|
141
|
+
// 的 in-run retry 先处理,不能原样漏给顶层当成终结。
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (ev.type === 'warning' &&
|
|
146
|
+
ev.message.includes('finish_reason=length')) {
|
|
147
|
+
sawMaxTurns = true;
|
|
148
|
+
}
|
|
149
|
+
else if (ev.type === 'tool_start') {
|
|
150
|
+
sawToolCall = true;
|
|
151
|
+
if (!toolNames.includes(ev.toolName))
|
|
152
|
+
toolNames.push(ev.toolName);
|
|
153
|
+
}
|
|
154
|
+
else if (ev.type === 'tool_end') {
|
|
155
|
+
sawToolCall = true;
|
|
156
|
+
if (!toolNames.includes(ev.toolName))
|
|
157
|
+
toolNames.push(ev.toolName);
|
|
158
|
+
if (ev.ok)
|
|
159
|
+
toolOkCount++;
|
|
160
|
+
else
|
|
161
|
+
toolFailCount++;
|
|
162
|
+
}
|
|
163
|
+
if (opts.suppressTurnDone && ev.type === 'turn_done')
|
|
164
|
+
continue;
|
|
165
|
+
yield ev;
|
|
166
|
+
}
|
|
167
|
+
// 从 history 提取本步产生的最后一条非空 assistant 消息。
|
|
168
|
+
// 经 stripThinkBlocks 净化:最后一条若是纯 <think> 块(模型收尾只剩思考),
|
|
169
|
+
// 继续向前回退到真正有内容的消息——capture/补充要求拿到的必须是交付文本。
|
|
170
|
+
let rawText = '';
|
|
171
|
+
for (let i = activeHistory.length - 1; i >= historyLenBefore; i--) {
|
|
172
|
+
const msg = activeHistory[i];
|
|
173
|
+
if (msg.role === 'assistant' && typeof msg.content === 'string') {
|
|
174
|
+
const cleaned = stripThinkBlocks(msg.content);
|
|
175
|
+
if (cleaned) {
|
|
176
|
+
rawText = cleaned;
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
rawText,
|
|
183
|
+
sawToolCall,
|
|
184
|
+
toolNames,
|
|
185
|
+
toolOkCount,
|
|
186
|
+
toolFailCount,
|
|
187
|
+
aborted,
|
|
188
|
+
sawLlmError,
|
|
189
|
+
sawMaxTurns,
|
|
190
|
+
llmErrorDetail,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/** maxTurns 截断失败文案的稳定标记(producer/detector 同源,防 runner 侧 delay 判定漂移)。 */
|
|
194
|
+
export const MAX_TURNS_CUTOFF_MARKER = '达到最大轮数';
|
|
195
|
+
/** maxTurns 截断的可重试失败文案(重试 = 在共享 history 上续作,再给一份轮数预算)。 */
|
|
196
|
+
export function describeMaxTurnsCutoff(stepId, maxTurns) {
|
|
197
|
+
return `step ${stepId}: ${MAX_TURNS_CUTOFF_MARKER} ${maxTurns} 被截断(可续跑)`;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* 该错误是否是 maxTurns 截断(续作语义)。runner 的 in-run retry 用它区分延时:
|
|
201
|
+
* maxTurns 截断默认立即续作,不套用普通 retry_delay_ms;长文档/PPT 类工作流
|
|
202
|
+
* 可显式配置 max_turns_retry_delay_ms 给截断续作增加等待窗口。
|
|
203
|
+
*/
|
|
204
|
+
export function isMaxTurnsCutoff(errMsg) {
|
|
205
|
+
return errMsg.includes(MAX_TURNS_CUTOFF_MARKER) && errMsg.includes('被截断');
|
|
206
|
+
}
|
|
45
207
|
/**
|
|
46
208
|
* 解析非 schema 模式下 agent 最终文本里的放弃标记。
|
|
47
209
|
* - 命中 GIVEUP_MARKER → 返回原因字符串(可能为空串)
|
|
@@ -117,10 +279,11 @@ export function interpretMiniReActResult(result, hasSchema) {
|
|
|
117
279
|
// v0.9.3: 误报过滤 —— 如果 "放弃原因" 太长或太结构化,
|
|
118
280
|
// 说明 LLM 是在正常输出中碰巧触发了标记,不应判为放弃
|
|
119
281
|
if (isLikelyFalsePositive(giveup)) {
|
|
120
|
-
//
|
|
282
|
+
// 降级为成功交付:去掉误触发的标记部分(replaceAll:标记可能被 LLM
|
|
283
|
+
// 误触发多次,replace 只删首个会让残留标记流进 capture 污染下游)
|
|
121
284
|
const cleanText = trimmed
|
|
122
|
-
.
|
|
123
|
-
.
|
|
285
|
+
.replaceAll(GIVEUP_MARKER, '')
|
|
286
|
+
.replaceAll(LEGACY_GIVEUP_MARKER, '')
|
|
124
287
|
.trim();
|
|
125
288
|
const raw = {
|
|
126
289
|
text: cleanText,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ACTION_KINDS, CONTROL_FLOW_TYPES, ON_ERROR_VALUES, VALID_STEP_TYPES } from './loader.js';
|
|
2
|
+
const llmAgentOnly = ['llm', 'agent'];
|
|
3
|
+
const llmAgentSkillOnly = ['llm', 'agent', 'skill'];
|
|
4
|
+
export const WORKFLOW_DSL_MANIFEST = {
|
|
5
|
+
version: '1.0.0',
|
|
6
|
+
actionKinds: [...ACTION_KINDS],
|
|
7
|
+
controlFlowTypes: [...CONTROL_FLOW_TYPES],
|
|
8
|
+
validStepTypes: [...VALID_STEP_TYPES],
|
|
9
|
+
onErrorValues: [...ON_ERROR_VALUES],
|
|
10
|
+
exclusiveActionFields: [...ACTION_KINDS, 'type'],
|
|
11
|
+
stepKinds: [
|
|
12
|
+
{ kind: 'tool', group: 'action', label: 'Tool', description: 'Call one deterministic tool.', primaryFields: ['tool', 'args'] },
|
|
13
|
+
{ kind: 'llm', group: 'action', label: 'LLM', description: 'Single LLM step.', primaryFields: ['llm', 'output_schema', 'context_files', 'allowed_tools'] },
|
|
14
|
+
{ kind: 'skill', group: 'action', label: 'Skill', description: 'Run one SKILL.md workflow agent.', primaryFields: ['skill', 'input', 'maxTurns'] },
|
|
15
|
+
{ kind: 'agent', group: 'action', label: 'Agent', description: 'Run an inline bounded TAOR agent.', primaryFields: ['agent', 'maxTurns', 'done_when', 'output_schema', 'context_files', 'allowed_tools'] },
|
|
16
|
+
{ kind: 'assert', group: 'quality', label: 'Assert', description: 'Halt when a condition is false.', primaryFields: ['condition', 'onFail'] },
|
|
17
|
+
{ kind: 'verify', group: 'quality', label: 'Verify', description: 'Run deterministic checks before continuing.', primaryFields: ['checks', 'onFail'] },
|
|
18
|
+
{ kind: 'set', group: 'control', label: 'Set', description: 'Set workflow variables deterministically.', primaryFields: ['set'] },
|
|
19
|
+
{ kind: 'branch', group: 'control', label: 'Branch', description: 'Route into then/else child steps.', primaryFields: ['condition'], childCollections: ['then', 'else'] },
|
|
20
|
+
{ kind: 'loop', group: 'control', label: 'Loop', description: 'For-each or bounded while loop.', primaryFields: ['over', 'as', 'max_iterations', 'fresh_context'], childCollections: ['do'] },
|
|
21
|
+
{ kind: 'break', group: 'control', label: 'Break', description: 'Exit the nearest (or target) loop.', primaryFields: ['when', 'target'] },
|
|
22
|
+
{ kind: 'continue', group: 'control', label: 'Continue', description: 'Skip to the next iteration of the nearest (or target) loop.', primaryFields: ['when', 'target'] },
|
|
23
|
+
{ kind: 'echo', group: 'control', label: 'Echo', description: 'Deterministically print an interpolated message (no LLM).', primaryFields: ['message'] },
|
|
24
|
+
{ kind: 'pause', group: 'control', label: 'Pause', description: 'Human approval gate.', primaryFields: ['prompt', 'free_text'] },
|
|
25
|
+
],
|
|
26
|
+
commonStepFields: [
|
|
27
|
+
{ name: 'id', type: 'string', ui: 'text', required: true, label: 'id' },
|
|
28
|
+
{ name: 'title', type: 'string', ui: 'text', label: 'title', description: 'Human-readable progress label (supports ${} interpolation); when set, the status line shows it instead of block-relative step numbers.' },
|
|
29
|
+
{ name: 'when', type: 'string', ui: 'text', label: 'when', description: 'Optional execution condition.' },
|
|
30
|
+
{ name: 'onError', type: 'enum', ui: 'select', enum: [...ON_ERROR_VALUES], label: 'onError' },
|
|
31
|
+
{ name: 'recover_hint', type: 'string', ui: 'text', label: 'recover_hint', description: 'Hint for onError=recover.' },
|
|
32
|
+
],
|
|
33
|
+
stepFields: [
|
|
34
|
+
{ name: 'tool', type: 'string', ui: 'text', appliesTo: ['tool'] },
|
|
35
|
+
{ name: 'args', type: 'object', ui: 'json', appliesTo: ['tool'] },
|
|
36
|
+
{ name: 'llm', type: 'string', ui: 'textarea', appliesTo: ['llm'] },
|
|
37
|
+
{ name: 'skill', type: 'string', ui: 'text', appliesTo: ['skill'] },
|
|
38
|
+
{ name: 'agent', type: 'string', ui: 'textarea', appliesTo: ['agent'] },
|
|
39
|
+
{ name: 'input', type: 'string', ui: 'textarea', appliesTo: ['skill'] },
|
|
40
|
+
{ name: 'capture', type: 'object', ui: 'json' },
|
|
41
|
+
{ name: 'maxTurns', type: 'number', ui: 'number', appliesTo: ['llm', 'skill', 'agent'] },
|
|
42
|
+
{ name: 'max_retries', type: 'number', ui: 'number' },
|
|
43
|
+
{ name: 'artifacts', type: 'string[]', ui: 'string[]' },
|
|
44
|
+
{ name: 'condition', type: 'string', ui: 'text', appliesTo: ['assert', 'branch'] },
|
|
45
|
+
{ name: 'onFail', type: 'string', ui: 'textarea', appliesTo: ['assert', 'verify'] },
|
|
46
|
+
{ name: 'set', type: 'object', ui: 'json', required: true, appliesTo: ['set'] },
|
|
47
|
+
{ name: 'checks', type: 'string[]', ui: 'string[]', required: true, appliesTo: ['verify'] },
|
|
48
|
+
{ name: 'over', type: 'string', ui: 'text', appliesTo: ['loop'] },
|
|
49
|
+
{ name: 'as', type: 'string', ui: 'text', appliesTo: ['loop'] },
|
|
50
|
+
{ name: 'max_iterations', type: 'number', ui: 'number', appliesTo: ['loop'] },
|
|
51
|
+
{ name: 'fresh_context', type: 'boolean', ui: 'boolean', appliesTo: ['loop'] },
|
|
52
|
+
{ name: 'prompt', type: 'string', ui: 'textarea', appliesTo: ['pause'] },
|
|
53
|
+
{ name: 'free_text', type: 'enum', ui: 'select', enum: ['halt', 'approve'], appliesTo: ['pause'] },
|
|
54
|
+
{ name: 'target', type: 'string', ui: 'text', appliesTo: ['break', 'continue'], description: 'Target loop id (label semantics; default = nearest loop).' },
|
|
55
|
+
{ name: 'message', type: 'string', ui: 'textarea', required: true, appliesTo: ['echo'] },
|
|
56
|
+
{ name: 'goal_supplement', type: 'boolean', ui: 'boolean', appliesTo: ['tool', 'skill', 'agent', 'llm', 'pause'], description: 'Append this step output to the goal anchor as a user supplement.' },
|
|
57
|
+
{ name: 'done_when', type: 'string', ui: 'text', appliesTo: ['agent'], description: 'Deterministic completion condition (whitelist expression, e.g. fileExists(...)); engine nudges the agent to keep working until it holds.' },
|
|
58
|
+
{ name: 'output_schema', type: 'object', ui: 'json', appliesTo: llmAgentOnly },
|
|
59
|
+
{ name: 'context_files', type: 'object[]', ui: 'object[]', appliesTo: llmAgentOnly },
|
|
60
|
+
{ name: 'allowed_tools', type: 'string[]', ui: 'string[]', appliesTo: llmAgentOnly },
|
|
61
|
+
{ name: 'history_mode', type: 'enum', ui: 'select', enum: ['shared', 'isolated'], appliesTo: llmAgentSkillOnly, description: 'Use shared workflow history or run this llm/agent/skill step in an isolated history (system prompt + current step only).' },
|
|
62
|
+
// 多模态(视觉):仅 llm/agent 生效。images 喂图给模型识图/打分(如 illustrate 配图工作流)。
|
|
63
|
+
{ name: 'images', type: 'array', ui: 'json', appliesTo: llmAgentOnly, description: 'Multimodal image inputs (paths/URLs, supports ${} interpolation). Array of strings or { source, detail, max_long_side_pixel }.' },
|
|
64
|
+
{ name: 'image_detail', type: 'enum', ui: 'select', enum: ['low', 'high', 'auto'], appliesTo: llmAgentOnly, description: 'Default vision detail for this step (per-image override allowed inside images[]).' },
|
|
65
|
+
{ name: 'image_max_long_side_pixel', type: 'number', ui: 'number', appliesTo: llmAgentOnly, description: 'Default max long-side pixels for downscaling images before sending.' },
|
|
66
|
+
{ name: 'parse_inline_images', type: 'boolean', ui: 'boolean', appliesTo: llmAgentOnly, description: 'Parse @./img.png or image URLs found in the prompt text.' },
|
|
67
|
+
],
|
|
68
|
+
workflowFields: [
|
|
69
|
+
{ name: 'artifacts', type: 'string[]', ui: 'string[]', label: 'workflow artifacts' },
|
|
70
|
+
{ name: 'self_heal', type: 'object', ui: 'json', label: 'self_heal' },
|
|
71
|
+
],
|
|
72
|
+
};
|