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.
Files changed (484) hide show
  1. package/README.md +14 -12
  2. package/package.json +34 -1
  3. package/plugins/cron-runner/.claude-plugin/plugin.json +5 -0
  4. package/plugins/cron-runner/commands/cron.md +26 -0
  5. package/plugins/cron-runner/commands/crons.md +7 -0
  6. package/plugins/cron-runner/plugin.js +34 -0
  7. package/plugins/cron-runner/src/commands.js +348 -0
  8. package/plugins/cron-runner/src/cronTime.js +148 -0
  9. package/plugins/cron-runner/src/lock.js +68 -0
  10. package/plugins/cron-runner/src/runs.js +89 -0
  11. package/plugins/cron-runner/src/scheduleEngine.js +72 -0
  12. package/plugins/cron-runner/src/scheduler.js +355 -0
  13. package/plugins/cron-runner/src/schema.js +140 -0
  14. package/plugins/cron-runner/src/service.js +167 -0
  15. package/plugins/cron-runner/src/store.js +298 -0
  16. package/plugins/cron-runner/src/types.js +1 -0
  17. package/plugins/workflow-runner/commands/workflow.md +4 -4
  18. package/plugins/workflow-runner/commands/workflows.md +1 -1
  19. package/plugins/workflow-runner/plugin.js +3 -1
  20. package/plugins/workflow-runner/src/agentCommon.js +249 -51
  21. package/plugins/workflow-runner/src/dslManifest.js +72 -0
  22. package/plugins/workflow-runner/src/expressions.js +198 -15
  23. package/plugins/workflow-runner/src/index.js +40 -8
  24. package/plugins/workflow-runner/src/jsonPayload.js +1 -1
  25. package/plugins/workflow-runner/src/loader.js +286 -72
  26. package/plugins/workflow-runner/src/multimodal.js +37 -0
  27. package/plugins/workflow-runner/src/recovery.js +49 -39
  28. package/plugins/workflow-runner/src/runner.js +802 -287
  29. package/plugins/workflow-runner/src/stepExecutors/agent.js +157 -39
  30. package/plugins/workflow-runner/src/stepExecutors/assert.js +16 -3
  31. package/plugins/workflow-runner/src/stepExecutors/llm.js +60 -111
  32. package/plugins/workflow-runner/src/stepExecutors/skill.js +47 -47
  33. package/plugins/workflow-runner/src/stepExecutors/tool.js +76 -10
  34. package/plugins/workflow-runner/src/stepExecutors/verify.js +27 -10
  35. package/plugins/workflow-runner/src/taskIdentity.js +296 -0
  36. package/plugins/workflow-runner/src/types.js +19 -9
  37. package/plugins/workflow-runner/src/workflowState.js +516 -33
  38. package/skills/adversarial-review/SKILL.md +0 -1
  39. package/skills/ai-image/SKILL.md +89 -0
  40. package/skills/ai-image/scripts/generate.mjs +497 -0
  41. package/skills/ai-image/scripts/generate_from_plan.mjs +469 -0
  42. package/skills/ai-image/scripts/generate_from_plan_test.mjs +223 -0
  43. package/skills/ai-image/scripts/generate_test.mjs +74 -0
  44. package/skills/browser-automation/SKILL.md +47 -0
  45. package/skills/docx/SKILL.md +25 -3
  46. package/skills/docx/scripts/office/helpers/__pycache__/__init__.cpython-314.pyc +0 -0
  47. package/skills/docx/scripts/office/helpers/__pycache__/merge_runs.cpython-314.pyc +0 -0
  48. package/skills/docx/scripts/office/helpers/__pycache__/simplify_redlines.cpython-314.pyc +0 -0
  49. package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-314.pyc +0 -0
  50. package/skills/docx/scripts/office/validators/__pycache__/base.cpython-314.pyc +0 -0
  51. package/skills/docx/scripts/office/validators/__pycache__/docx.cpython-314.pyc +0 -0
  52. package/skills/docx/scripts/office/validators/__pycache__/pptx.cpython-314.pyc +0 -0
  53. package/skills/docx/scripts/office/validators/__pycache__/redlining.cpython-314.pyc +0 -0
  54. package/skills/docx/scripts/opc_check.py +253 -0
  55. package/skills/image-gen-openrouter/SKILL.md +10 -2
  56. package/skills/image-stats/SKILL.md +65 -0
  57. package/skills/image-stats/scripts/__pycache__/image_stats.cpython-314.pyc +0 -0
  58. package/skills/image-stats/scripts/__pycache__/image_stats_test.cpython-314.pyc +0 -0
  59. package/skills/image-stats/scripts/image_stats.py +368 -0
  60. package/skills/image-stats/scripts/image_stats_test.py +181 -0
  61. package/skills/pptx/SKILL.md +123 -95
  62. package/skills/pptx/design.md +82 -0
  63. package/skills/pptx/examples/README.md +29 -0
  64. package/skills/pptx/examples/hybrid_example.mjs +107 -0
  65. package/skills/pptx/examples/hybrid_example.pptx +0 -0
  66. package/skills/pptx/pptxgenjs.md +41 -0
  67. package/skills/pptx/scripts/deck_helpers.mjs +224 -0
  68. package/skills/pptx/scripts/layout_lint.py +293 -0
  69. package/skills/pptx/scripts/layout_lint_test.py +160 -0
  70. package/skills/pptx/scripts/opc_check.py +339 -0
  71. package/skills/pptx/scripts/svg_fallback.mjs +145 -0
  72. package/skills/pptx/svg.md +67 -0
  73. package/skills/tts-zh/SKILL.md +19 -2
  74. package/skills/ui-design/SKILL.md +158 -0
  75. package/skills/ui-design/claude_design.md +309 -0
  76. package/skills/ui-design/evals/evals.json +254 -0
  77. package/skills/ui-design/references/aesthetic-direction.md +83 -0
  78. package/skills/ui-design/references/claude-design-protocol.md +36 -0
  79. package/skills/ui-design/references/design-context.md +53 -0
  80. package/skills/ui-design/references/design-execution-playbook.md +82 -0
  81. package/skills/ui-design/references/export-pptx.md +124 -0
  82. package/skills/ui-design/references/layout-composition.md +654 -0
  83. package/skills/ui-design/references/preview-feedback.md +37 -0
  84. package/skills/ui-design/references/source-image-layout.md +189 -0
  85. package/skills/ui-design/references/starter-components.md +78 -0
  86. package/skills/ui-design/references/vi-aegis-vector.md +144 -0
  87. package/skills/ui-design/references/vi-amber-prism.md +133 -0
  88. package/skills/ui-design/references/vi-aqua-glass.md +200 -0
  89. package/skills/ui-design/references/vi-comfort-vision.md +147 -0
  90. package/skills/ui-design/references/vi-ember-prism.md +140 -0
  91. package/skills/ui-design/references/vi-nebula-console.md +151 -0
  92. package/skills/ui-design/references/vi-obsidian-optics.md +139 -0
  93. package/skills/ui-design/references/vi-obsidian-xui.md +143 -0
  94. package/skills/ui-design/references/vi-precision-horizon-dark.md +117 -0
  95. package/skills/ui-design/references/vi-precision-horizon.md +215 -0
  96. package/skills/ui-design/references/vi-solar-relay.md +130 -0
  97. package/skills/ui-design/references/vi-template-workflow.md +48 -0
  98. package/skills/ui-design/references/vi-verdant-grid.md +141 -0
  99. package/skills/ui-design/references/vi-violet-meridian.md +172 -0
  100. package/skills/ui-design/scripts/__pycache__/assemble_material.cpython-314.pyc +0 -0
  101. package/skills/ui-design/scripts/__pycache__/assemble_material_test.cpython-314.pyc +0 -0
  102. package/skills/ui-design/scripts/__pycache__/chart_sanity_check.cpython-314.pyc +0 -0
  103. package/skills/ui-design/scripts/__pycache__/check_language_policy.cpython-314.pyc +0 -0
  104. package/skills/ui-design/scripts/__pycache__/check_ui_artifact.cpython-314.pyc +0 -0
  105. package/skills/ui-design/scripts/__pycache__/check_ui_artifact_pptx_test.cpython-314.pyc +0 -0
  106. package/skills/ui-design/scripts/__pycache__/deck_pages_check.cpython-314.pyc +0 -0
  107. package/skills/ui-design/scripts/__pycache__/deck_pages_check_test.cpython-314.pyc +0 -0
  108. package/skills/ui-design/scripts/__pycache__/deck_visual_style_check.cpython-314.pyc +0 -0
  109. package/skills/ui-design/scripts/__pycache__/deck_visual_style_check_test.cpython-314.pyc +0 -0
  110. package/skills/ui-design/scripts/__pycache__/design_budget_check.cpython-314.pyc +0 -0
  111. package/skills/ui-design/scripts/__pycache__/design_budget_check_test.cpython-314.pyc +0 -0
  112. package/skills/ui-design/scripts/__pycache__/design_repair_hints.cpython-314.pyc +0 -0
  113. package/skills/ui-design/scripts/__pycache__/design_repair_hints_test.cpython-314.pyc +0 -0
  114. package/skills/ui-design/scripts/__pycache__/design_style_check.cpython-314.pyc +0 -0
  115. package/skills/ui-design/scripts/__pycache__/design_style_check_test.cpython-314.pyc +0 -0
  116. package/skills/ui-design/scripts/__pycache__/draft_coverage_check.cpython-314.pyc +0 -0
  117. package/skills/ui-design/scripts/__pycache__/extract_source_assets.cpython-314.pyc +0 -0
  118. package/skills/ui-design/scripts/__pycache__/extract_source_assets_test.cpython-314.pyc +0 -0
  119. package/skills/ui-design/scripts/__pycache__/generated_image_review_collect.cpython-314.pyc +0 -0
  120. package/skills/ui-design/scripts/__pycache__/generated_image_review_collect_test.cpython-314.pyc +0 -0
  121. package/skills/ui-design/scripts/__pycache__/image_plan_lint.cpython-314.pyc +0 -0
  122. package/skills/ui-design/scripts/__pycache__/image_plan_lint_test.cpython-314.pyc +0 -0
  123. package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite.cpython-314.pyc +0 -0
  124. package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite_test.cpython-314.pyc +0 -0
  125. package/skills/ui-design/scripts/__pycache__/layout_balance.cpython-314.pyc +0 -0
  126. package/skills/ui-design/scripts/__pycache__/layout_balance_test.cpython-314.pyc +0 -0
  127. package/skills/ui-design/scripts/__pycache__/normalize_design_json.cpython-314.pyc +0 -0
  128. package/skills/ui-design/scripts/__pycache__/normalize_design_json_test.cpython-314.pyc +0 -0
  129. package/skills/ui-design/scripts/__pycache__/plan_source_layout.cpython-314.pyc +0 -0
  130. package/skills/ui-design/scripts/__pycache__/plan_source_layout_test.cpython-314.pyc +0 -0
  131. package/skills/ui-design/scripts/__pycache__/resolve_source_hint.cpython-314.pyc +0 -0
  132. package/skills/ui-design/scripts/__pycache__/resolve_source_hint_test.cpython-314.pyc +0 -0
  133. package/skills/ui-design/scripts/__pycache__/resolve_source_input.cpython-314.pyc +0 -0
  134. package/skills/ui-design/scripts/__pycache__/resolve_source_input_test.cpython-314.pyc +0 -0
  135. package/skills/ui-design/scripts/__pycache__/scaffold_ui_artifact.cpython-314.pyc +0 -0
  136. package/skills/ui-design/scripts/__pycache__/source_usage_check.cpython-314.pyc +0 -0
  137. package/skills/ui-design/scripts/__pycache__/source_usage_check_test.cpython-314.pyc +0 -0
  138. package/skills/ui-design/scripts/__pycache__/text_readability_pixel.cpython-314.pyc +0 -0
  139. package/skills/ui-design/scripts/__pycache__/visual_quality_gate.cpython-314.pyc +0 -0
  140. package/skills/ui-design/scripts/__pycache__/visual_quality_gate_test.cpython-314.pyc +0 -0
  141. package/skills/ui-design/scripts/assemble_material.py +217 -0
  142. package/skills/ui-design/scripts/assemble_material_test.py +149 -0
  143. package/skills/ui-design/scripts/browser_check_ui_artifact.mjs +221 -0
  144. package/skills/ui-design/scripts/chart_sanity_check.py +261 -0
  145. package/skills/ui-design/scripts/chart_sanity_check_test.py +165 -0
  146. package/skills/ui-design/scripts/check_language_policy.py +351 -0
  147. package/skills/ui-design/scripts/check_ui_artifact.py +435 -0
  148. package/skills/ui-design/scripts/check_ui_artifact_pptx_test.py +251 -0
  149. package/skills/ui-design/scripts/deck_pages_check.py +158 -0
  150. package/skills/ui-design/scripts/deck_pages_check_test.py +134 -0
  151. package/skills/ui-design/scripts/deck_visual_style_check.py +767 -0
  152. package/skills/ui-design/scripts/deck_visual_style_check_test.py +713 -0
  153. package/skills/ui-design/scripts/design_budget_check.py +271 -0
  154. package/skills/ui-design/scripts/design_budget_check_test.py +183 -0
  155. package/skills/ui-design/scripts/design_repair_hints.py +162 -0
  156. package/skills/ui-design/scripts/design_repair_hints_test.py +54 -0
  157. package/skills/ui-design/scripts/design_style_check.py +397 -0
  158. package/skills/ui-design/scripts/design_style_check_test.py +233 -0
  159. package/skills/ui-design/scripts/draft_coverage_check.py +184 -0
  160. package/skills/ui-design/scripts/draft_coverage_check_test.py +131 -0
  161. package/skills/ui-design/scripts/export_pptx_from_html.mjs +2367 -0
  162. package/skills/ui-design/scripts/extract_source_assets.py +607 -0
  163. package/skills/ui-design/scripts/extract_source_assets_test.py +256 -0
  164. package/skills/ui-design/scripts/generated_image_review_collect.py +206 -0
  165. package/skills/ui-design/scripts/generated_image_review_collect_test.py +91 -0
  166. package/skills/ui-design/scripts/image_plan_lint.py +571 -0
  167. package/skills/ui-design/scripts/image_plan_lint_test.py +515 -0
  168. package/skills/ui-design/scripts/image_prompt_rewrite.py +713 -0
  169. package/skills/ui-design/scripts/image_prompt_rewrite_test.py +966 -0
  170. package/skills/ui-design/scripts/layout_balance.py +881 -0
  171. package/skills/ui-design/scripts/layout_balance_test.py +927 -0
  172. package/skills/ui-design/scripts/normalize_design_json.py +272 -0
  173. package/skills/ui-design/scripts/normalize_design_json_test.py +119 -0
  174. package/skills/ui-design/scripts/plan_source_layout.py +1450 -0
  175. package/skills/ui-design/scripts/plan_source_layout_test.py +1136 -0
  176. package/skills/ui-design/scripts/resolve_source_input.py +270 -0
  177. package/skills/ui-design/scripts/resolve_source_input_test.py +98 -0
  178. package/skills/ui-design/scripts/scaffold_ui_artifact.py +377 -0
  179. package/skills/ui-design/scripts/source_usage_check.py +581 -0
  180. package/skills/ui-design/scripts/source_usage_check_test.py +427 -0
  181. package/skills/ui-design/scripts/text_readability_pixel.py +340 -0
  182. package/skills/ui-design/scripts/text_readability_pixel_test.py +219 -0
  183. package/skills/ui-design/scripts/visual_quality_gate.py +301 -0
  184. package/skills/ui-design/scripts/visual_quality_gate_test.py +233 -0
  185. package/skills/ui-design/tests/e2e/prompts/deck.md +19 -0
  186. package/skills/ui-design/tests/e2e/prompts/webpage.md +17 -0
  187. package/skills/ui-design/tests/e2e/render_check.mjs +101 -0
  188. package/skills/ui-design/tests/e2e/rubric.json +54 -0
  189. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/browser-check.json +49 -0
  190. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/language-check.txt +12 -0
  191. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/static-check.txt +15 -0
  192. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/outputs/index.html +837 -0
  193. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/prompt.md +12 -0
  194. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/review.md +21 -0
  195. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/screenshots/desktop.png +0 -0
  196. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/screenshots/mobile.png +0 -0
  197. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/outputs/homepage.html +373 -0
  198. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/outputs/platform.html +378 -0
  199. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/prompt.md +13 -0
  200. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/review.md +26 -0
  201. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/browser-check.json +49 -0
  202. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/desktop.png +0 -0
  203. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/mobile.png +0 -0
  204. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/browser-check.json +49 -0
  205. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/desktop.png +0 -0
  206. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/mobile.png +0 -0
  207. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/checks/static-check.txt +2 -0
  208. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/outputs/index.html +656 -0
  209. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/prompt.md +12 -0
  210. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/render_check.mjs +67 -0
  211. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/checks/static-check.txt +2 -0
  212. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/outputs/index.html +587 -0
  213. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/prompt.md +12 -0
  214. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/review.md +36 -0
  215. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/browser-check.json +49 -0
  216. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/language-check.txt +8 -0
  217. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/static-check.txt +16 -0
  218. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/outputs/index.html +739 -0
  219. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/prompt.md +11 -0
  220. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/review.md +22 -0
  221. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/screenshots/desktop.png +0 -0
  222. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/screenshots/mobile.png +0 -0
  223. package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/checks/browser-check.json +52 -0
  224. package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/outputs/index.html +641 -0
  225. package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/screenshots/desktop.png +0 -0
  226. package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/screenshots/mobile.png +0 -0
  227. package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/outputs/index.html +467 -0
  228. package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/browser-check.json +49 -0
  229. package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/desktop.png +0 -0
  230. package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/mobile.png +0 -0
  231. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/outputs/homepage.html +373 -0
  232. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/outputs/platform.html +378 -0
  233. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/prompt.md +13 -0
  234. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/review.md +26 -0
  235. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/browser-check.json +49 -0
  236. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/desktop.png +0 -0
  237. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/mobile.png +0 -0
  238. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/browser-check.json +49 -0
  239. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/desktop.png +0 -0
  240. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/mobile.png +0 -0
  241. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/browser-check.json +49 -0
  242. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/language-check.txt +4 -0
  243. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/static-check.txt +2 -0
  244. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/execution_notes.md +10 -0
  245. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/outputs/index.html +587 -0
  246. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/prompt.md +14 -0
  247. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/review.md +13 -0
  248. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/screenshots/desktop.png +0 -0
  249. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/screenshots/mobile.png +0 -0
  250. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/checks/browser-check.json +24 -0
  251. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/checks/static-check.txt +2 -0
  252. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/execution_notes.md +21 -0
  253. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/outputs/deck.html +451 -0
  254. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/screenshots/slide-01.png +0 -0
  255. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/screenshots/slide-02.png +0 -0
  256. package/skills/ui-design/tests/e2e/runs/iteration-1/review.md +79 -0
  257. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/checks/browser-check.json +26 -0
  258. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/checks/static-check.txt +2 -0
  259. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/execution_notes.md +20 -0
  260. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/outputs/index.html +534 -0
  261. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/screenshots/desktop.png +0 -0
  262. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/screenshots/mobile.png +0 -0
  263. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/browser-check.json +64 -0
  264. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/language-check.txt +7 -0
  265. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/quick-validate.txt +1 -0
  266. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/static-console.txt +2 -0
  267. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/static-homepage.txt +2 -0
  268. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/outputs/console.html +600 -0
  269. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/outputs/homepage.html +556 -0
  270. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/prompt.md +29 -0
  271. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/review.md +57 -0
  272. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/console-desktop.png +0 -0
  273. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/console-mobile.png +0 -0
  274. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/homepage-desktop.png +0 -0
  275. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/homepage-mobile.png +0 -0
  276. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/browser-check.json +33 -0
  277. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/language-check.txt +6 -0
  278. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/quick-validate.txt +1 -0
  279. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/static-check.txt +2 -0
  280. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/outputs/index.html +682 -0
  281. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/prompt.md +13 -0
  282. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/review.md +59 -0
  283. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/screenshots/desktop.png +0 -0
  284. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/screenshots/mobile.png +0 -0
  285. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/outputs/page-01.html +466 -0
  286. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/outputs/page-02.html +433 -0
  287. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/prompt.md +13 -0
  288. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/browser-check.json +49 -0
  289. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/desktop.png +0 -0
  290. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/mobile.png +0 -0
  291. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/browser-check.json +49 -0
  292. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/desktop.png +0 -0
  293. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/mobile.png +0 -0
  294. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/browser-check.json +49 -0
  295. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/language-check.txt +3 -0
  296. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/static-check.txt +2 -0
  297. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/execution_notes.md +24 -0
  298. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/outputs/index.html +723 -0
  299. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/prompt.md +15 -0
  300. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/review.md +26 -0
  301. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/screenshots/desktop.png +0 -0
  302. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/screenshots/mobile.png +0 -0
  303. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/browser-dark.json +49 -0
  304. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/browser-light.json +49 -0
  305. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/language-check.txt +11 -0
  306. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/static-dark.txt +2 -0
  307. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/static-light.txt +3 -0
  308. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/execution_notes.md +23 -0
  309. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/outputs/dark.html +392 -0
  310. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/outputs/light.html +476 -0
  311. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/prompt.md +23 -0
  312. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/review.md +41 -0
  313. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/dark/desktop.png +0 -0
  314. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/dark/mobile.png +0 -0
  315. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/light/desktop.png +0 -0
  316. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/light/mobile.png +0 -0
  317. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/browser-check.json +54 -0
  318. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/language-check.txt +5 -0
  319. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/quick-validate.txt +1 -0
  320. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/static-check.txt +2 -0
  321. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/outputs/index.html +765 -0
  322. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/prompt.md +15 -0
  323. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/review.md +59 -0
  324. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/screenshots/desktop.png +0 -0
  325. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/screenshots/mobile.png +0 -0
  326. package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/outputs/index.html +508 -0
  327. package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/browser-check.json +49 -0
  328. package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/desktop.png +0 -0
  329. package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/mobile.png +0 -0
  330. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/browser-check.json +54 -0
  331. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/language-check.txt +6 -0
  332. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/quick-validate.txt +1 -0
  333. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/static-check.txt +2 -0
  334. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/outputs/index.html +788 -0
  335. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/prompt.md +14 -0
  336. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/review.md +60 -0
  337. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/screenshots/desktop.png +0 -0
  338. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/screenshots/mobile.png +0 -0
  339. package/skills/video-compose/SKILL.md +8 -1
  340. package/skills/web-crawler/SKILL.md +70 -0
  341. package/skills/web-crawler/scripts/crawl.mjs +538 -0
  342. package/skills/web-crawler/scripts/crawl.test.mjs +204 -0
  343. package/skills/xlsx/SKILL.md +12 -0
  344. package/skills/xlsx/scripts/opc_check.py +253 -0
  345. package/src/advisorState.js +22 -0
  346. package/src/askBridge.js +97 -3
  347. package/src/bootstrap/workingDir.js +12 -1
  348. package/src/cli/args.js +17 -1
  349. package/src/cli/configMenu.js +236 -0
  350. package/src/cli/configWizard.js +7 -5
  351. package/src/cli/print.js +37 -4
  352. package/src/cli/streamJson.js +77 -24
  353. package/src/cli/wizards/advisorWizard.js +147 -0
  354. package/src/cli/wizards/fieldForm.js +149 -0
  355. package/src/cli/wizards/imageWizard.js +60 -0
  356. package/src/cli/wizards/openRouterWizard.js +23 -0
  357. package/src/cli/wizards/providerPresets.js +95 -0
  358. package/src/cli/wizards/providerWizard.js +219 -0
  359. package/src/cli/wizards/searchWizard.js +23 -0
  360. package/src/cli/wizards/ttsWizard.js +34 -0
  361. package/src/config/configFile.js +441 -83
  362. package/src/config/configService.js +446 -0
  363. package/src/config.js +24 -64
  364. package/src/context/agentHome.js +9 -0
  365. package/src/context/archive.js +7 -2
  366. package/src/context/compact.js +8 -5
  367. package/src/context/contextLock.js +81 -0
  368. package/src/context/persistContext.js +30 -11
  369. package/src/context/reactiveCompact.js +4 -2
  370. package/src/context/recentDirs.js +21 -61
  371. package/src/context/sessionPath.js +97 -23
  372. package/src/context/sessionRegistry.js +303 -24
  373. package/src/context/tokenCounter.js +18 -0
  374. package/src/context/workspaceIndex.js +731 -0
  375. package/src/infra/verification.js +28 -15
  376. package/src/llm/client.js +394 -159
  377. package/src/llm/providers/anthropicFormat.js +241 -0
  378. package/src/llm/providers/openaiFormat.js +190 -0
  379. package/src/loop.js +219 -32
  380. package/src/main.js +61 -11
  381. package/src/messageQueue.js +97 -0
  382. package/src/multimodal.js +203 -0
  383. package/src/plugin-sdk.js +15 -0
  384. package/src/plugins/commandRouter.js +3 -0
  385. package/src/plugins/hookEngine.js +5 -1
  386. package/src/plugins/pluginLifecycle.js +28 -0
  387. package/src/plugins/pluginLoader.js +2 -1
  388. package/src/plugins/pluginRunner.js +49 -21
  389. package/src/plugins/transcript.js +4 -3
  390. package/src/prompts/pluginList.js +5 -5
  391. package/src/prompts/projectInstructions.js +3 -3
  392. package/src/prompts/promptAssembly.js +133 -144
  393. package/src/prompts/skillList.js +12 -22
  394. package/src/prompts/system.js +0 -1
  395. package/src/session/runAgentTurn.js +70 -0
  396. package/src/session/runTurn.js +41 -6
  397. package/src/toolGate.js +17 -0
  398. package/src/tools/advisor/advisor.js +379 -0
  399. package/src/tools/agent/agent.js +555 -0
  400. package/src/tools/agent/agentTypes.js +59 -0
  401. package/src/tools/agent/coordinator.js +93 -0
  402. package/src/tools/agent/worktree.js +270 -0
  403. package/src/tools/ask/ask.js +7 -2
  404. package/src/tools/bash/bash.js +112 -18
  405. package/src/tools/download/download.js +144 -0
  406. package/src/tools/edit/edit.js +1 -0
  407. package/src/tools/edit/multi-edit.js +1 -0
  408. package/src/tools/genimage/genimage.js +242 -0
  409. package/src/tools/genspeech/genspeech.js +67 -0
  410. package/src/tools/glob/glob.js +1 -0
  411. package/src/tools/grep/grep.js +3 -0
  412. package/src/tools/grep/rgPath.js +2 -0
  413. package/src/tools/index.js +25 -2
  414. package/src/tools/read/read.js +1 -0
  415. package/src/tools/shared/killTree.js +52 -0
  416. package/src/tools/toolProgressBridge.js +48 -0
  417. package/src/tools/webbrowser/agentBrowserPath.js +258 -0
  418. package/src/tools/webbrowser/browser.js +59 -42
  419. package/src/tools/webbrowser/browserControl.js +118 -0
  420. package/src/tools/webbrowser/browserDaemon.js +97 -0
  421. package/src/tools/webbrowser/browserService.js +27 -0
  422. package/src/tools/webbrowser/browserStream.js +119 -0
  423. package/src/tools/webbrowser/webbrowser.js +699 -130
  424. package/src/tools/webfetch/webfetch.js +1 -0
  425. package/src/tools/websearch/websearch.js +134 -51
  426. package/src/tools/write/write.js +1 -0
  427. package/src/ui/App.js +249 -22
  428. package/src/ui/AskQuestion.js +29 -10
  429. package/src/ui/InputBox.js +104 -12
  430. package/src/ui/LiveArea.js +112 -19
  431. package/src/ui/MessageList.js +100 -14
  432. package/src/ui/ModelPicker.js +56 -0
  433. package/src/ui/QueuedMessagesBanner.js +14 -0
  434. package/src/ui/Root.js +18 -10
  435. package/src/ui/SessionPicker.js +102 -0
  436. package/src/ui/StatusLine.js +13 -4
  437. package/src/ui/WorkspacePicker.js +55 -0
  438. package/src/ui/figures.js +44 -0
  439. package/src/ui/hooks/askSlot.js +82 -0
  440. package/src/ui/hooks/useChat.js +358 -64
  441. package/src/ui/hooks/usePasteHandler.js +11 -1
  442. package/src/ui/hooks/useTextBuffer.js +1 -3
  443. package/src/ui/liveViewport.js +5 -1
  444. package/src/ui/markdown.js +206 -0
  445. package/src/ui/textBuffer.js +0 -7
  446. package/src/ui/theme.js +32 -0
  447. package/src/utils/debugLog.js +0 -4
  448. package/src/utils/resourcePaths.js +2 -2
  449. package/src/utils/stripThink.js +50 -0
  450. package/src/web/browserBridge.js +447 -0
  451. package/src/web/protocol.js +19 -0
  452. package/workflows/adaptive-research.yaml +13 -5
  453. package/workflows/book-review-short.yaml +36 -10
  454. package/workflows/e2e-write-greet.yaml +6 -2
  455. package/workflows/illustrate.yaml +227 -0
  456. package/workflows/plan.yaml +460 -179
  457. package/workflows/ppt.yaml +1659 -0
  458. package/workflows/ralph-loop.yaml +199 -0
  459. package/workflows/schema.json +81 -23
  460. package/workflows/webppt.yaml +496 -0
  461. package/workflows/word.yaml +710 -0
  462. package/workflows/youtube-shorts.yaml +46 -15
  463. package/MINIMAL-TRACE.md +0 -77
  464. package/plugins/HOW-TO-WRITE-A-PLUGIN.md +0 -186
  465. package/plugins/ralph-wiggum/.claude-plugin/plugin.json +0 -9
  466. package/plugins/ralph-wiggum/README.md +0 -197
  467. package/plugins/ralph-wiggum/commands/cancel-ralph.md +0 -18
  468. package/plugins/ralph-wiggum/commands/help.md +0 -137
  469. package/plugins/ralph-wiggum/commands/ralph-loop.md +0 -85
  470. package/plugins/ralph-wiggum/hooks/hooks.json +0 -15
  471. package/plugins/ralph-wiggum/hooks/stop-hook.sh +0 -191
  472. package/plugins/ralph-wiggum/plugin.js +0 -280
  473. package/plugins/ralph-wiggum/src/goalState.js +0 -258
  474. package/plugins/ralph-wiggum/src/sentinels.js +0 -76
  475. package/plugins/ralph-wiggum/src/stopHookRunner.js +0 -104
  476. package/plugins/ralph-wiggum/src/verificationGate.js +0 -202
  477. package/plugins/workflow-runner/src/miniReAct.js +0 -223
  478. package/plugins/workflow-runner/src/voteHelpers.js +0 -110
  479. package/skills/config/SKILL.md +0 -123
  480. package/skills/frontend-design/LICENSE.txt +0 -177
  481. package/skills/frontend-design/SKILL.md +0 -42
  482. package/src/ui/ProgressPanel.js +0 -54
  483. package/src/ui/StreamingBlock.js +0 -11
  484. 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
- * 执行 workflow 中 type: agent 的步骤:启动一个 miniReAct 子循环,
6
- * 用工具随机应变地完成开放性任务。
5
+ * v0.9 重构:不再使用独立 miniReAct 子循环,而是委托主 TAOR 引擎
6
+ * (runQuery / src/loop.ts)执行。这样做的好处:
7
7
  *
8
- * 与 llm 步骤的区别:
9
- * - agent 有工具白名单(allowed_tools 过滤),可以 Read/Write/Grep/...
10
- * - agent 跑多轮 miniReAct(maxTurns 上限),llm 只跑单轮 chat
11
- * - agent 的产出经过验证闸门(interpretMiniReActResult),llm 直接透传
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 { interpolate } from '../expressions.js';
15
- import { runMiniReAct } from '../miniReAct.js';
16
- import { AGENT_OPENING, buildWorkflowAgentSystem, describeCaptureContract, interpretMiniReActResult, } from '../agentCommon.js';
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
- * 关键变化(Phase 2 重构):
21
- * buildWorkflowAgentSystem 现在是 async(因为需要扫描 skill/plugin 目录),
22
- * agent 步骤的 system prompt 现在包含完整的:
23
- * - 工具列表 + 使用规范
24
- * - Skill 列表(含触发词)
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
- // 工具白名单:allowed_tools 声明时按白名单过滤;未声明时默认全量(不限制)
30
- const allTools = ctx.tools ?? [];
31
- const tools = step.allowed_tools
32
- ? allTools.filter((t) => step.allowed_tools.includes(t.name))
33
- : allTools;
34
- // ✅ Phase 2: 异步构建完整 system prompt(含 skill/plugin 列表)
35
- const systemContent = await buildWorkflowAgentSystem(ctx.cwd, // 新增:传入 cwd 用于 skill/plugin 扫描
36
- AGENT_OPENING, tools);
37
- const userMsg = interpolate(step.agent ?? '', vars) +
38
- describeCaptureContract(step) +
39
- (step.input ? `\n\n上下文变量:${interpolate(step.input, vars)}` : '');
40
- const messages = [
41
- { role: 'system', content: systemContent },
42
- { role: 'user', content: userMsg },
43
- ];
44
- const result = yield* runMiniReAct({
45
- messages,
46
- tools,
47
- maxTurns: step.maxTurns ?? 12,
48
- provider: ctx.provider,
49
- signal: ctx.signal,
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 outcome = interpretMiniReActResult(result, !!step.output_schema);
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/workflows/stepExecutors/assert.ts —— assert step 执行
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 step 执行
3
+ * plugins/workflow-runner/src/stepExecutors/llm.ts —— llm 步骤执行器
4
4
  * ------------------------------------------------------------
5
- * 单轮 LLM 生成。关键设计:
6
- * - tools: [] —— 不开任何工具(工具调用应该写成 tool: step)
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
- * Phase 2 重构:
13
- * - system prompt 现在追加 CapabilityHint(skill + plugin 轻量列表)
14
- * - 即使 tools=[] 的 llm 步骤也知道有哪些 skill/plugin 可用,
15
- * 可以在输出文本中引用或建议用户后续使用(如 draft_plan 提到"建议用 /pptx 执行")
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 }` 绑生成文本(无 output_schema 时)
19
- * - `{ result: var_name }` 同义
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 { ALL_TOOLS, chat, } from '../../../../src/plugin-sdk.js';
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 { runMiniReAct } from '../miniReAct.js';
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
- const prompt = interpolate(step.llm, vars);
53
- // ===== ADR-05 阶段 4: context_files → miniReAct 子循环 =====
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
- const augmented = `${prompt}\n\n**以下文件可用,请用 Read 工具按需读取**:\n${fileList}`;
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
- // ===== END NEW =====
77
- const useSchema = step.output_schema !== undefined;
78
- // schema 模式:把 schema 直接写进 system prompt。这样无论 provider 是否支持
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
- // ✅ Phase 2: 追加 CapabilityHint —— 让 llm 步骤知道有哪些 skill/plugin 可用
85
- // 即使 tools=[] 不能执行工具,模型也能在输出中引用或建议用户后续使用
86
- const capabilityHint = await assembleCapabilityHint(ctx.cwd);
87
- const baseSystem = (useSchema ? LLM_STEP_SYSTEM_SCHEMA : LLM_STEP_SYSTEM_PLAIN) + schemaHint;
88
- const messages = [
89
- {
90
- role: 'system',
91
- content: baseSystem + capabilityHint,
92
- },
93
- { role: 'user', content: prompt },
94
- ];
95
- const responseFormat = useSchema
96
- ? {
97
- type: 'json_schema',
98
- json_schema: {
99
- name: `${step.id}_output`,
100
- schema: step.output_schema,
101
- strict: true,
102
- },
103
- }
104
- : undefined;
105
- let text = '';
106
- for await (const ev of chat({
107
- provider: ctx.provider,
108
- messages,
109
- tools: [],
110
- responseFormat,
111
- signal: ctx.signal,
112
- })) {
113
- if (ev.type === 'text_delta') {
114
- text += ev.delta;
115
- // 非 schema 模式:把答案流式 yield 给 UI(答案是主角,消除"无声")。
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
- const trimmed = text.trim();
125
- if (useSchema) {
126
- // strict structured output:解析 JSON 后整个对象作为 raw。
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 step 执行
3
+ * plugins/workflow-runner/src/stepExecutors/skill.ts —— skill 步骤执行器
7
4
  * ------------------------------------------------------------
8
- * 把一个具名 skill(skills/<name>/SKILL.md)当作"迷你 ReAct 子循环"
9
- * 跑一次:复用 src/loop.ts::runQuery,让模型在子 history 内 T-A-O-R。
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
- * 支持按目录名 or 按 frontmatter::name 匹配
14
- * - 剥掉 frontmatter,body 作 system 指令;step.input 插值后作为 user
15
- * - 子 history 与外层 ctx.history 隔离,避免污染主对话
16
- * - 流式转发:runQuery yield 的事件直接 yield 出去(让 UI 看到子循环进度)
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, runQuery, } from '../../../../src/plugin-sdk.js';
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
- // 该子目录无 SKILL.md,跳过
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
- : `请按 SKILL "${skillName}" 的指示完成任务。`;
80
- const subHistory = [
81
- {
82
- role: 'system',
83
- content: `下面是要遵循的 SKILL 指示(来源:${skillFile}):\n\n${body}`,
84
- },
85
- ];
86
- let text = '';
87
- for await (const ev of runQuery(userInput, {
88
- provider: ctx.provider,
89
- history: subHistory,
90
- signal: ctx.signal,
91
- maxTurns: step.maxTurns,
92
- })) {
93
- if (ev.type === 'text')
94
- text += ev.delta;
95
- if (ev.type === 'interrupted')
96
- throw new Error('用户中断');
97
- if (ev.type === 'error')
98
- throw new Error(ev.error);
99
- // 子 skill 内部那次 runQuery 的 turn_done 是它自己的终结标记,不是整个 workflow 的终结。
100
- // 不外泄——否则把 turn_done 当终结的消费者(-p --output-format json / gateway broker)
101
- // 会在 workflow 中途(如 critic 步之后、verify 步之前)误判结束、漏掉后续步骤。
102
- // workflow 的对外收口由 index.ts::runWorkflowFromCommand 末尾统一补发。
103
- if (ev.type === 'turn_done')
104
- continue;
105
- yield ev;
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,