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
@@ -0,0 +1,379 @@
1
+ /**
2
+ * ============================================================
3
+ * src/tools/advisor/advisor.ts —— Advisor 工具(顾问模型第二意见)
4
+ * ------------------------------------------------------------
5
+ * 独立配置的第二个 LLM,供主循环的模型在关键判断点
6
+ * (方案/诊断成型前、卡住时、收尾汇报前——具体见 CORE_IDENTITY 的"顾问咨询
7
+ * 原则")主动调用,拿到一个不同模型的第二意见。
8
+ *
9
+ * 设计要点(吸收自 Claude Code 官方 /advisor 的架构,但按 minimal-agent
10
+ * 的实际约束做了取舍——不照搬服务端单请求内编排/模型分级/加密返回等
11
+ * 与我们架构无关的部分,见设计计划):
12
+ * - 输入 schema 几乎为空(只有可选的 note):模型调用前自己写的方案/
13
+ * 诊断文字,早就随 assistant 消息 push 进了 history,顾问能从
14
+ * ctx.history 里直接看到,不需要模型重复手填一段结构化 question。
15
+ * - 顾问自己独立的 persona system prompt,与主 provider 的五层提示词
16
+ * 完全无关。
17
+ * - 顾问不给工具权限,只做单轮只读推理(tools: [])——避免变成一个
18
+ * 带自己循环的子 agent,那是远比"第二意见"更大的功能。
19
+ * - 未配置 / 被 /advisor off 关闭 / 调用报错,全部走 ToolResult 的
20
+ * ok:false 路径——这条路径本来就有成熟的"错误喂回 LLM 自行判断"
21
+ * 机制,loop.ts 不需要为此新增任何代码。
22
+ * ============================================================
23
+ */
24
+ import { z } from 'zod';
25
+ import { configService } from '../../config/configService.js';
26
+ import { countMessagesTokens } from '../../context/tokenCounter.js';
27
+ import { chat } from '../../llm/client.js';
28
+ import { toToolParameters } from '../../utils/zodToJson.js';
29
+ import { DEFAULT_MAX_RESULT_SIZE_CHARS } from '../types.js';
30
+ // ---------------- 1. Zod 输入 schema ----------------
31
+ const inputSchema = z.object({
32
+ note: z
33
+ .string()
34
+ .max(2000, 'note 太长(>2000 字)')
35
+ .optional()
36
+ .describe('可选。大多数情况下不需要填——你此前说过的方案/诊断已经在会话历史里,顾问会自动看到。' +
37
+ '只有需要额外强调、历史里没体现的点时才填一句话。'),
38
+ });
39
+ const parameters = toToolParameters(inputSchema);
40
+ // ---------------- 2. Description(给 LLM 看的工具说明) ----------------
41
+ const description = `- Consults an independent, separately-configured second LLM ("顾问模型" / advisor) for a second opinion on your current plan, diagnosis, or progress.
42
+ - Call with no arguments in most cases — the advisor receives a bounded, relevant view of the current session (the original request, recent discussion, current plan/diagnosis, and key tool results). Only pass \`note\` if something important is not otherwise clear.
43
+ - Exception: if your current plan/diagnosis relies on things you saw in images (screenshots, photos, diagrams), summarize the key visual facts in \`note\` in 1-2 sentences (what each image shows and what you concluded from it) — the advisor may not be able to see the images themselves, and any visual judgment you never wrote down as text does not exist for it.
44
+ - Call this: (1) after a plan/diagnosis has taken shape but before you commit to it (write code, declare a conclusion); (2) when you're stuck — the same error keeps recurring, your fixes aren't converging, or the user has pushed back and you're reconsidering direction; (3) before declaring a multi-step task complete and reporting back to the user.
45
+ - The advisor has no tool access and does a single read-only pass over the transcript — it cannot verify anything itself, only reason about what it's shown.
46
+ - If this tool errors (advisor not configured in shared settings, disabled, manual-only, or a call failure), that's not a signal to stop — treat it as "no second opinion available this time" and continue with your own judgment. Do not block or retry in a loop.`;
47
+ // ---------------- 3. 顾问 persona system prompt ----------------
48
+ const ADVISOR_SYSTEM_PROMPT = `你是一位经验丰富的全栈开发专家技术顾问,为正在独立执行任务的另一个 AI 助手提供第二意见评审。
49
+ 你的职责:技术方案评估、代码评审、疑难问题的根因定位与解决方向判断。
50
+
51
+ 你会看到该助手当前会话的完整历史——包括用户最初的需求、双方历次交流、以及它已经做过的工具调用
52
+ 与执行结果,以及它现在想让你重点关注的内容(如果有)。
53
+
54
+ 审视时请做到:
55
+ - 像资深工程师做方案评审/代码评审一样直接、具体——发现问题就明说,不要无条件附和或说套话。
56
+ - 优先检查:方案是否遗漏了风险或边界情况、诊断是否真的找到了根因还是只是让症状消失、
57
+ 是否存在更简单或更稳妥的替代方向。
58
+ - 结论必须基于你在历史记录里看到的实际证据,不要脱离上下文给泛泛的通用建议。
59
+ - 篇幅精炼:只讲最关键的 1-3 点,不要复述历史、不要客套开场白。`;
60
+ // ---------------- 4. 消息构造(纯函数,单独导出可测) ----------------
61
+ /**
62
+ * 把主循环的 history 转成喂给顾问模型的 messages。
63
+ *
64
+ * 过滤掉所有 role==='system' 的消息——同时去掉了 minimal-agent 自己的系统提示词
65
+ * 和 TUI 的 ephemeral 提示消息(两者都是 role:'system'),换成顾问自己的 persona。
66
+ */
67
+ const MAX_TOOL_RESULT_CHARS = 12_000;
68
+ function truncateMiddle(value, limit = MAX_TOOL_RESULT_CHARS) {
69
+ if (value.length <= limit)
70
+ return value;
71
+ const half = Math.floor((limit - 100) / 2);
72
+ return `${value.slice(0, half)}\n\n[... 顾问上下文已省略 ${value.length - half * 2} 个字符 ...]\n\n${value.slice(-half)}`;
73
+ }
74
+ function redactSensitiveText(value, secrets) {
75
+ let output = value;
76
+ for (const secret of secrets) {
77
+ if (secret.length >= 6)
78
+ output = output.split(secret).join('[REDACTED]');
79
+ }
80
+ return output
81
+ .replace(/\b(sk-[A-Za-z0-9._-]{12,}|tvly-[A-Za-z0-9._-]{12,})\b/g, '[REDACTED]')
82
+ .replace(/((?:api[_-]?key|token|secret|password)\s*[:=]\s*)[^\s,;]+/gi, '$1[REDACTED]');
83
+ }
84
+ function redactAdvisorHistory(history, secrets) {
85
+ return history.map((message) => {
86
+ if (message.role === 'user') {
87
+ const content = typeof message.content === 'string'
88
+ ? redactSensitiveText(message.content, secrets)
89
+ : message.content.map((part) => part.type === 'text'
90
+ ? { ...part, text: redactSensitiveText(part.text, secrets) }
91
+ : part);
92
+ return { ...message, content };
93
+ }
94
+ if (message.role === 'assistant')
95
+ return {
96
+ ...message,
97
+ content: message.content ? redactSensitiveText(message.content, secrets) : message.content,
98
+ tool_calls: message.tool_calls?.map((call) => ({
99
+ ...call,
100
+ function: { ...call.function, arguments: redactSensitiveText(call.function.arguments, secrets) },
101
+ })),
102
+ };
103
+ return { ...message, content: redactSensitiveText(message.content, secrets) };
104
+ });
105
+ }
106
+ const MAX_ADVISOR_IMAGES = 4;
107
+ const MAX_ADVISOR_IMAGE_BYTES = 8 * 1024 * 1024;
108
+ function contentForAdvisor(message, supportsVision, allowImages, imageBudget) {
109
+ if (!Array.isArray(message.content))
110
+ return truncateMiddle(message.content ?? '');
111
+ const parts = message.content.map((part) => {
112
+ if (part.type === 'text')
113
+ return { ...part, text: truncateMiddle(part.text) };
114
+ if (part.type === 'image_url' && supportsVision && allowImages) {
115
+ const encodedBytes = part.image_url.url.startsWith('data:')
116
+ ? new TextEncoder().encode(part.image_url.url).byteLength
117
+ : 0;
118
+ if (imageBudget.count >= MAX_ADVISOR_IMAGES ||
119
+ imageBudget.encodedBytes + encodedBytes > MAX_ADVISOR_IMAGE_BYTES) {
120
+ return { type: 'text', text: '[图片未发送:超过顾问视觉输入的数量或体积限制。]' };
121
+ }
122
+ imageBudget.count++;
123
+ imageBudget.encodedBytes += encodedBytes;
124
+ return part;
125
+ }
126
+ if (part.type === 'image_url' && supportsVision && !allowImages) {
127
+ return { type: 'text', text: '[图片未发送:未允许向顾问模型共享敏感原文或图像。]' };
128
+ }
129
+ if (part.type === 'image_url') {
130
+ return { type: 'text', text: '[图片未发送:顾问模型未启用视觉能力;请结合会话中已有的图片描述评审。]' };
131
+ }
132
+ return { type: 'text', text: '[视频内容未发送给顾问模型。]' };
133
+ });
134
+ return parts;
135
+ }
136
+ function normalizeAdvisorMessage(message, supportsVision, allowImages, imageBudget) {
137
+ if (message.role === 'system')
138
+ return null;
139
+ if (message.role === 'tool') {
140
+ return { role: 'user', content: `[工具结果 ${message.tool_call_id}]\n${truncateMiddle(message.content)}` };
141
+ }
142
+ if (message.role === 'assistant') {
143
+ const calls = message.tool_calls?.map((call) => `[调用工具 ${call.function.name}] ${truncateMiddle(call.function.arguments, 2000)}`).join('\n');
144
+ return {
145
+ role: 'assistant',
146
+ content: [message.content ?? '', calls ?? ''].filter(Boolean).join('\n'),
147
+ };
148
+ }
149
+ const attachmentSummary = message.attachments?.length
150
+ ? `\n[附件] ${message.attachments.map((item) => `${item.name} (${item.mime}, ${item.size} bytes)`).join('、')}`
151
+ : '';
152
+ const content = contentForAdvisor(message, supportsVision, allowImages, imageBudget);
153
+ if (typeof content === 'string')
154
+ return { role: 'user', content: `${content}${attachmentSummary}` };
155
+ return attachmentSummary
156
+ ? { role: 'user', content: [...content, { type: 'text', text: attachmentSummary }] }
157
+ : { role: 'user', content };
158
+ }
159
+ function fitAdvisorBudget(messages, inputBudget) {
160
+ if (countMessagesTokens(messages) <= inputBudget)
161
+ return messages;
162
+ const system = messages[0];
163
+ const closing = messages[messages.length - 1];
164
+ const body = messages.slice(1, -1);
165
+ const firstUserIndex = body.findIndex((message) => message.role === 'user');
166
+ const selected = [];
167
+ let used = countMessagesTokens([system, closing]);
168
+ if (firstUserIndex >= 0) {
169
+ const first = body[firstUserIndex];
170
+ selected.push(first);
171
+ used += countMessagesTokens([first]);
172
+ }
173
+ const recent = [];
174
+ for (let index = body.length - 1; index >= 0; index--) {
175
+ if (index === firstUserIndex)
176
+ continue;
177
+ const message = body[index];
178
+ const cost = countMessagesTokens([message]);
179
+ if (used + cost > inputBudget)
180
+ continue;
181
+ recent.unshift(message);
182
+ used += cost;
183
+ }
184
+ if (selected.length + recent.length < body.length) {
185
+ selected.push({ role: 'user', content: `[较早历史因顾问上下文预算省略 ${body.length - selected.length - recent.length} 条;已保留最初需求和最近相关记录。]` });
186
+ }
187
+ return [system, ...selected, ...recent, closing];
188
+ }
189
+ export function buildAdvisorMessages(history, note, options = {}) {
190
+ const imageBudget = { count: 0, encodedBytes: 0 };
191
+ const nonSystem = history
192
+ .map((message) => normalizeAdvisorMessage(message, options.supportsVision === true, options.allowImages ?? (options.supportsVision === true), imageBudget))
193
+ .filter((message) => message !== null);
194
+ const closing = [
195
+ '以上是执行助手当前会话的受预算约束相关记录(保留最初需求、近期交流、当前方案与关键工具结果)。',
196
+ note ? `\n执行助手额外补充:\n${note}` : '',
197
+ '\n请审视以上内容——它当前的方案/诊断/进展是否存在问题、遗漏的风险,或有没有更好的方向?给出你的意见。',
198
+ ]
199
+ .filter(Boolean)
200
+ .join('\n');
201
+ const messages = [
202
+ { role: 'system', content: ADVISOR_SYSTEM_PROMPT },
203
+ ...nonSystem,
204
+ { role: 'user', content: closing },
205
+ ];
206
+ const contextWindow = options.contextWindow ?? 128_000;
207
+ const maxTokens = options.maxTokens ?? 4096;
208
+ const configuredBudget = Math.min(128_000, Math.max(8_000, options.inputTokenBudget ?? 128_000));
209
+ const providerBudget = Math.max(8_000, contextWindow - maxTokens - 4096);
210
+ const inputBudget = Math.min(configuredBudget, providerBudget);
211
+ return fitAdvisorBudget(messages, inputBudget);
212
+ }
213
+ /** 轻量错误分类:把第三方 HTTP/网络报错文本归到几类可操作的提示上。 */
214
+ function classifyAdvisorError(e) {
215
+ const msg = e.message ?? String(e);
216
+ const lower = msg.toLowerCase();
217
+ if (lower.includes('context') ||
218
+ lower.includes('too long') ||
219
+ lower.includes('maximum context') ||
220
+ lower.includes('token limit')) {
221
+ return `顾问模型上下文超限(当前会话历史过长,超出顾问的上下文窗口):${msg}`;
222
+ }
223
+ if (lower.includes('429') || lower.includes('rate limit') || lower.includes('too many requests')) {
224
+ return `顾问模型被限流:${msg}`;
225
+ }
226
+ if (lower.includes('timeout') || lower.includes('timed out') || lower.includes('network') || lower.includes('econnreset')) {
227
+ return `顾问模型响应超时或网络错误:${msg}`;
228
+ }
229
+ return `顾问模型调用失败:${msg}`;
230
+ }
231
+ // ---------------- 5. 执行逻辑(导出供测试 DI) ----------------
232
+ /**
233
+ * 真正的执行逻辑,chatFn 可注入 stub(测试用,镜像 compact.ts::runCompaction 的
234
+ * `chatFn: typeof chat = chat` 模式),不需要 mock.module。
235
+ */
236
+ export async function runAdvisor(input, signal, ctx, chatFn = chat, runtime = {}) {
237
+ const advisor = await configService.advisor();
238
+ if (!advisor) {
239
+ return {
240
+ ok: false,
241
+ error: '顾问模型未配置。请在设置 → 模型中完成专家顾问配置。' +
242
+ '可继续凭自己判断推进,不必等待顾问。',
243
+ };
244
+ }
245
+ if (!advisor.enabled) {
246
+ return {
247
+ ok: false,
248
+ error: '顾问模型当前已关闭(/advisor on 开启)。可继续凭自己判断推进,不必等待顾问。',
249
+ };
250
+ }
251
+ if (advisor.mode === 'manual' && ctx?.advisorInvocation !== 'manual') {
252
+ return { ok: false, error: '顾问模型当前为“仅手动”模式;请使用 /advisor ask 发起咨询。' };
253
+ }
254
+ if (ctx?.advisorCalls && ctx.advisorCalls.used >= ctx.advisorCalls.max) {
255
+ return { ok: false, error: `本回合已达到顾问咨询上限(${ctx.advisorCalls.max} 次),请继续按已有意见推进。` };
256
+ }
257
+ if (ctx?.advisorCalls)
258
+ ctx.advisorCalls.used++;
259
+ const provider = advisor.provider;
260
+ const snapshot = await configService.getSnapshot();
261
+ const secrets = [
262
+ ...(snapshot.config?.models.map((entry) => entry.apiKey) ?? []),
263
+ snapshot.config?.tools.webSearch?.apiKey,
264
+ snapshot.config?.tools.imageGeneration?.apiKey,
265
+ snapshot.config?.tools.openRouter?.apiKey,
266
+ snapshot.config?.tools.textToSpeech?.apiKey,
267
+ ].filter((value) => !!value);
268
+ const history = advisor.shareSensitive
269
+ ? [...(ctx?.history ?? [])]
270
+ : redactAdvisorHistory(ctx?.history ?? [], secrets);
271
+ const messages = buildAdvisorMessages(history, input.note, {
272
+ supportsVision: advisor.supportsVision,
273
+ allowImages: advisor.supportsVision && advisor.shareSensitive,
274
+ contextWindow: provider.contextWindow,
275
+ maxTokens: provider.maxTokens,
276
+ inputTokenBudget: advisor.inputTokenBudget,
277
+ });
278
+ // Advisor 是可降级的第二意见:使用独立、可配置的总时限,不影响主模型的流式时限。
279
+ // 默认 180 秒,直接使用所选模型的上下文窗口配置。
280
+ const timeoutMs = runtime.timeoutMs ?? advisor.timeoutMs;
281
+ const timeoutController = new AbortController();
282
+ const timer = setTimeout(() => timeoutController.abort(new Error('advisor-timeout')), timeoutMs);
283
+ const combinedSignal = signal ? AbortSignal.any([signal, timeoutController.signal]) : timeoutController.signal;
284
+ let content = '';
285
+ let reasoningChars = 0;
286
+ // 发布端节流:LoopEvent 消费端直接更新对应 toolCallId,这里控制事件频率,
287
+ // 而流式 delta 每秒可达几十上百条——阶段切换(思考中→整理意见)立即发保证切换及时可见,
288
+ // 同阶段后续 delta 以 ≥200ms 门控,与主循环流式 setState 的 100ms 节流纪律同量级。
289
+ let lastPhase = null;
290
+ let lastPublishAt = 0;
291
+ const publishProgress = (phase, buildLine) => {
292
+ const now = Date.now();
293
+ if (phase === lastPhase && now - lastPublishAt < 200)
294
+ return;
295
+ lastPhase = phase;
296
+ lastPublishAt = now;
297
+ ctx?.reportProgress?.(buildLine());
298
+ };
299
+ // 步内实时进度:治"顾问模型思考阶段 reasoning_delta 被静默丢弃、TUI 看起来像卡住"
300
+ // (2026-07 真实反馈:2m05s 无任何变化,用户误判死机)。无 UI 宿主时 no-op,零副作用。
301
+ const streamOnce = async (advisorMessages) => {
302
+ let output = '';
303
+ for await (const ev of chatFn({ provider, messages: advisorMessages, tools: [], signal: combinedSignal })) {
304
+ if (ev.type === 'reasoning_delta' && ev.delta) {
305
+ reasoningChars += ev.delta.length;
306
+ publishProgress('reasoning', () => `顾问模型思考中…(已生成 ${reasoningChars} 字思考)`);
307
+ }
308
+ else if (ev.type === 'text_delta') {
309
+ output += ev.delta;
310
+ publishProgress('text', () => `顾问模型正在整理意见…(已输出 ${output.length} 字)`);
311
+ }
312
+ }
313
+ return output;
314
+ };
315
+ const sentImageParts = messages.some((message) => Array.isArray(message.content) && message.content.some((part) => part.type === 'image_url'));
316
+ let degradedWithoutImages = false;
317
+ try {
318
+ try {
319
+ content = await streamOnce(messages);
320
+ }
321
+ catch (e) {
322
+ // 剥图重试保底:配置声称 supportsVision 但 provider 实际拒收图片(能力不符/图片
323
+ // 格式不合口味)时,把图片降级成占位文本重试一次,别白丢一次咨询。只在真的发过
324
+ // 图、且失败不是超时/用户中断时触发;共用同一个超时预算(timer 不重置,不叠加等待)。
325
+ if (!sentImageParts || timeoutController.signal.aborted || signal?.aborted)
326
+ throw e;
327
+ content = await streamOnce(buildAdvisorMessages(history, input.note, {
328
+ supportsVision: false,
329
+ contextWindow: provider.contextWindow,
330
+ maxTokens: provider.maxTokens,
331
+ inputTokenBudget: advisor.inputTokenBudget,
332
+ }));
333
+ degradedWithoutImages = true;
334
+ }
335
+ }
336
+ catch (e) {
337
+ if (timeoutController.signal.aborted && !signal?.aborted) {
338
+ return {
339
+ ok: false,
340
+ error: `顾问模型响应超过 ${Math.round(timeoutMs / 1000)}s 未完成,已跳过。` +
341
+ '可继续凭自己判断推进,不必等待顾问。',
342
+ };
343
+ }
344
+ return {
345
+ ok: false,
346
+ error: `${classifyAdvisorError(e)} 可继续凭自己判断推进,不必等待顾问。`,
347
+ };
348
+ }
349
+ finally {
350
+ clearTimeout(timer);
351
+ }
352
+ if (degradedWithoutImages) {
353
+ // 让主模型如实理解这份意见的局限:顾问没看到图,评的是纯文本上下文。
354
+ content = `(顾问未能接收图片,本意见基于纯文本上下文。)\n${content}`;
355
+ }
356
+ if (content.length > DEFAULT_MAX_RESULT_SIZE_CHARS) {
357
+ content =
358
+ content.slice(0, DEFAULT_MAX_RESULT_SIZE_CHARS) +
359
+ `\n\n... (输出超过 ${DEFAULT_MAX_RESULT_SIZE_CHARS} 字符,已截断)`;
360
+ }
361
+ return { ok: true, content };
362
+ }
363
+ // 无宿主上下文的调用视为用户手动咨询;生产主循环使用 callWithContext。
364
+ async function call(input, signal) {
365
+ return runAdvisor(input, signal, { advisorInvocation: 'manual' });
366
+ }
367
+ // ---------------- 6. 导出 ----------------
368
+ export const advisorTool = {
369
+ name: 'Advisor',
370
+ description,
371
+ inputSchema,
372
+ parameters,
373
+ isReadOnly: true,
374
+ isConcurrencySafe: false,
375
+ maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
376
+ interruptBehavior: () => 'cancel',
377
+ call,
378
+ callWithContext: runAdvisor,
379
+ };