minimal-agent 0.12.0 → 0.14.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 (472) hide show
  1. package/README.md +6 -5
  2. package/package.json +62 -5
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +204 -185
  16. package/plugins/workflow-runner/src/index.ts +249 -224
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +404 -467
  28. package/plugins/workflow-runner/src/runner.ts +491 -535
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +172 -152
  54. package/plugins/workflow-runner/src/taskIdentity.ts +233 -200
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -105
  58. package/plugins/workflow-runner/src/types.ts +155 -520
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +542 -469
  68. package/plugins/workflow-runner/src/workflowState.ts +639 -589
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/skill-creator/scripts/run_eval.py +3 -2
  92. package/skills/ui-design/SKILL.md +5 -2
  93. package/skills/ui-design/references/layout-composition.md +1 -1
  94. package/skills/workflow-creator/SKILL.md +344 -0
  95. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  96. package/skills/workflow-creator/references/api.md +216 -0
  97. package/skills/workflow-creator/references/migration.md +103 -0
  98. package/skills/workflow-creator/references/patterns.md +779 -0
  99. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  100. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  101. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  102. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  103. package/src/advisor/advisorCoordinator.js +503 -0
  104. package/src/advisor/advisorCoordinator.ts +657 -0
  105. package/src/cli/configMenu.tsx +0 -1
  106. package/src/cli/print.js +44 -6
  107. package/src/cli/print.ts +73 -4
  108. package/src/cli/streamJson.js +5 -6
  109. package/src/cli/streamJson.ts +8 -4
  110. package/src/cli/wizards/advisorWizard.js +4 -2
  111. package/src/cli/wizards/advisorWizard.tsx +8 -2
  112. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  113. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  114. package/src/collaboration/taskFlow.js +115 -0
  115. package/src/collaboration/taskFlow.ts +169 -0
  116. package/src/config/configDefaults.js +41 -1
  117. package/src/config/configDefaults.ts +43 -1
  118. package/src/config/configDiagnostics.ts +2 -2
  119. package/src/config/configFile.js +40 -9
  120. package/src/config/configFile.ts +60 -11
  121. package/src/config/configService.js +443 -74
  122. package/src/config/configService.ts +723 -142
  123. package/src/config/numericLimits.js +22 -0
  124. package/src/config/numericLimits.ts +24 -0
  125. package/src/config.js +1 -0
  126. package/src/config.ts +3 -2
  127. package/src/context/budgetPlan.js +1 -1
  128. package/src/context/budgetPlan.ts +1 -1
  129. package/src/context/compact.js +7 -2
  130. package/src/context/compact.ts +9 -2
  131. package/src/context/microCompactLite.js +212 -13
  132. package/src/context/microCompactLite.ts +261 -12
  133. package/src/context/sessionRegistry.js +8 -1
  134. package/src/context/sessionRegistry.ts +18 -5
  135. package/src/context/toolResultArchive.js +72 -0
  136. package/src/context/toolResultArchive.ts +95 -0
  137. package/src/goal/errors.js +8 -0
  138. package/src/goal/errors.ts +18 -0
  139. package/src/goal/goalRuntime.js +344 -0
  140. package/src/goal/goalRuntime.ts +466 -0
  141. package/src/goal/goalStore.js +200 -0
  142. package/src/goal/goalStore.ts +219 -0
  143. package/src/goal/index.js +4 -0
  144. package/src/goal/index.ts +4 -0
  145. package/src/goal/statusMapping.js +71 -0
  146. package/src/goal/statusMapping.ts +95 -0
  147. package/src/goal/types.js +7 -0
  148. package/src/goal/types.ts +179 -0
  149. package/src/goal/workflowController.js +306 -0
  150. package/src/goal/workflowController.ts +360 -0
  151. package/src/harness/evidenceLedger.js +2 -0
  152. package/src/harness/evidenceLedger.ts +1 -0
  153. package/src/harness/stallGuard.js +9 -3
  154. package/src/harness/stallGuard.ts +7 -3
  155. package/src/images/imageResolver.js +161 -0
  156. package/src/images/imageResolver.ts +189 -0
  157. package/src/infra/verification.js +56 -20
  158. package/src/infra/verification.ts +87 -20
  159. package/src/llm/client.js +79 -21
  160. package/src/llm/client.ts +182 -35
  161. package/src/llm/gatewayClient.js +201 -0
  162. package/src/llm/gatewayClient.ts +299 -0
  163. package/src/llm/messageProvenance.js +46 -0
  164. package/src/llm/messageProvenance.ts +58 -0
  165. package/src/llm/modelProvider.js +1 -0
  166. package/src/llm/modelProvider.ts +22 -0
  167. package/src/llm/providers/anthropicFormat.js +108 -1
  168. package/src/llm/providers/anthropicFormat.ts +115 -4
  169. package/src/llm/providers/openaiFormat.js +9 -0
  170. package/src/llm/providers/openaiFormat.ts +12 -3
  171. package/src/loop.js +319 -54
  172. package/src/loop.ts +373 -57
  173. package/src/main.js +4 -1
  174. package/src/main.tsx +4 -1
  175. package/src/managedExecution/index.js +2 -0
  176. package/src/managedExecution/index.ts +2 -0
  177. package/src/managedExecution/registry.js +15 -0
  178. package/src/managedExecution/registry.ts +20 -0
  179. package/src/managedExecution/types.js +1 -0
  180. package/src/managedExecution/types.ts +86 -0
  181. package/src/modelRef.js +9 -0
  182. package/src/modelRef.ts +31 -0
  183. package/src/multimodal.js +14 -28
  184. package/src/multimodal.ts +17 -33
  185. package/src/net/lanDiscovery.js +65 -0
  186. package/src/net/lanDiscovery.ts +82 -0
  187. package/src/plugin-sdk.js +28 -3
  188. package/src/plugin-sdk.ts +39 -6
  189. package/src/plugins/pluginApi.ts +16 -1
  190. package/src/plugins/pluginLoader.js +4 -0
  191. package/src/plugins/pluginLoader.ts +6 -0
  192. package/src/plugins/pluginRunner.js +152 -9
  193. package/src/plugins/pluginRunner.ts +186 -8
  194. package/src/plugins/slashFallback.js +113 -0
  195. package/src/plugins/slashFallback.ts +137 -0
  196. package/src/prompts/policyRegistry.js +15 -8
  197. package/src/prompts/policyRegistry.ts +18 -8
  198. package/src/prompts/promptAssembly.js +103 -12
  199. package/src/prompts/promptAssembly.ts +114 -12
  200. package/src/prompts/skillList.js +21 -3
  201. package/src/prompts/skillList.ts +27 -2
  202. package/src/prompts/stableSystemPrompt.js +18 -0
  203. package/src/prompts/stableSystemPrompt.ts +33 -0
  204. package/src/runtime/agentRuntimeContext.js +8 -2
  205. package/src/runtime/agentRuntimeContext.ts +17 -4
  206. package/src/session/runAgentTurn.js +78 -12
  207. package/src/session/runAgentTurn.ts +105 -23
  208. package/src/session/runTurn.js +10 -9
  209. package/src/session/runTurn.ts +17 -8
  210. package/src/session/sessionState.ts +2 -0
  211. package/src/team/auth.js +186 -0
  212. package/src/team/auth.ts +298 -0
  213. package/src/team/cli.js +105 -0
  214. package/src/team/cli.ts +122 -0
  215. package/src/team/onlineToolContract.js +64 -0
  216. package/src/team/onlineToolContract.ts +109 -0
  217. package/src/team/toolPolicy.js +36 -0
  218. package/src/team/toolPolicy.ts +75 -0
  219. package/src/tools/advisor/advisor.js +148 -37
  220. package/src/tools/advisor/advisor.ts +161 -38
  221. package/src/tools/advisor/advisorDecision.js +71 -0
  222. package/src/tools/advisor/advisorDecision.ts +85 -0
  223. package/src/tools/agent/agent.js +18 -5
  224. package/src/tools/agent/agent.ts +21 -7
  225. package/src/tools/agent/agentControl.js +246 -0
  226. package/src/tools/agent/agentControl.ts +284 -0
  227. package/src/tools/agent/agentTaskService.js +40 -1
  228. package/src/tools/agent/agentTaskService.ts +44 -1
  229. package/src/tools/agent/agentTypes.js +14 -2
  230. package/src/tools/agent/agentTypes.ts +15 -2
  231. package/src/tools/applypatch/applyPatch.js +362 -0
  232. package/src/tools/applypatch/applyPatch.ts +428 -0
  233. package/src/tools/bash/bash.js +70 -18
  234. package/src/tools/bash/bash.ts +75 -20
  235. package/src/tools/capabilities.js +10 -5
  236. package/src/tools/capabilities.ts +10 -5
  237. package/src/tools/computeruse/computerIntent.js +32 -0
  238. package/src/tools/computeruse/computerIntent.ts +46 -0
  239. package/src/tools/computeruse/telemetryLog.js +12 -0
  240. package/src/tools/computeruse/telemetryLog.ts +16 -0
  241. package/src/tools/computeruse/vision/telemetry.js +1 -0
  242. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  243. package/src/tools/effectiveToolSet.js +4 -0
  244. package/src/tools/effectiveToolSet.ts +4 -0
  245. package/src/tools/index.js +21 -2
  246. package/src/tools/index.ts +33 -2
  247. package/src/tools/powershell/powershell.js +18 -1
  248. package/src/tools/powershell/powershell.ts +18 -2
  249. package/src/tools/presentresult/presentresult.js +6 -15
  250. package/src/tools/presentresult/presentresult.ts +6 -15
  251. package/src/tools/read/read.js +69 -11
  252. package/src/tools/read/read.ts +70 -11
  253. package/src/tools/shared/fileUtils.js +1 -2
  254. package/src/tools/shared/fileUtils.ts +1 -2
  255. package/src/tools/shared/permanentDeleteGuard.js +34 -3
  256. package/src/tools/shared/permanentDeleteGuard.ts +43 -6
  257. package/src/tools/shared/toolOutputStore.js +23 -1
  258. package/src/tools/shared/toolOutputStore.ts +22 -1
  259. package/src/tools/skill/skill.js +9 -3
  260. package/src/tools/skill/skill.ts +8 -4
  261. package/src/tools/toolPromptGuides.js +117 -0
  262. package/src/tools/toolPromptGuides.ts +137 -0
  263. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  264. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  265. package/src/tools/webbrowser/browser.js +27 -11
  266. package/src/tools/webbrowser/browser.ts +68 -24
  267. package/src/tools/webbrowser/browserAutomation.js +329 -0
  268. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  269. package/src/tools/webbrowser/browserAxState.js +97 -0
  270. package/src/tools/webbrowser/browserAxState.ts +142 -0
  271. package/src/tools/webbrowser/browserBatch.js +1578 -0
  272. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  273. package/src/tools/webbrowser/browserCdp.js +208 -0
  274. package/src/tools/webbrowser/browserCdp.ts +255 -0
  275. package/src/tools/webbrowser/browserConditions.js +24 -0
  276. package/src/tools/webbrowser/browserConditions.ts +45 -0
  277. package/src/tools/webbrowser/browserContent.js +281 -0
  278. package/src/tools/webbrowser/browserContent.ts +438 -0
  279. package/src/tools/webbrowser/browserControl.js +131 -30
  280. package/src/tools/webbrowser/browserControl.ts +210 -50
  281. package/src/tools/webbrowser/browserDaemon.js +22 -14
  282. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  283. package/src/tools/webbrowser/browserFrames.js +47 -0
  284. package/src/tools/webbrowser/browserFrames.ts +54 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  286. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  287. package/src/tools/webbrowser/browserLocator.js +140 -0
  288. package/src/tools/webbrowser/browserLocator.ts +194 -0
  289. package/src/tools/webbrowser/browserOutcome.js +10 -17
  290. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  291. package/src/tools/webbrowser/browserRecovery.js +58 -0
  292. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  293. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  294. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  295. package/src/tools/webbrowser/browserService.js +28 -2
  296. package/src/tools/webbrowser/browserService.ts +49 -9
  297. package/src/tools/webbrowser/browserStream.js +132 -33
  298. package/src/tools/webbrowser/browserStream.ts +224 -50
  299. package/src/tools/webbrowser/browserTabs.js +48 -15
  300. package/src/tools/webbrowser/browserTabs.ts +178 -96
  301. package/src/tools/webbrowser/webbrowser.js +683 -144
  302. package/src/tools/webbrowser/webbrowser.ts +979 -236
  303. package/src/tools/webfetch/preapproved.js +0 -2
  304. package/src/tools/webfetch/preapproved.ts +0 -2
  305. package/src/tools/websearch/websearch.js +129 -8
  306. package/src/tools/websearch/websearch.ts +138 -6
  307. package/src/types.ts +450 -42
  308. package/src/ui/App.js +377 -58
  309. package/src/ui/App.tsx +576 -111
  310. package/src/ui/LiveArea.js +14 -8
  311. package/src/ui/LiveArea.tsx +14 -10
  312. package/src/ui/MessageList.js +63 -20
  313. package/src/ui/MessageList.tsx +101 -16
  314. package/src/ui/ModelPicker.js +7 -4
  315. package/src/ui/ModelPicker.tsx +55 -8
  316. package/src/ui/hooks/useChat.js +152 -163
  317. package/src/ui/hooks/useChat.ts +396 -334
  318. package/src/ui/loginCommand.js +56 -0
  319. package/src/ui/loginCommand.ts +63 -0
  320. package/src/ui/toolProgress.js +41 -0
  321. package/src/ui/toolProgress.ts +44 -0
  322. package/src/web/browserBridge.js +20 -2
  323. package/src/web/browserBridge.ts +20 -2
  324. package/src/web/protocol.ts +1897 -194
  325. package/workflows/adaptive-research/workflow.mjs +86 -0
  326. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  327. package/workflows/e2e-llm/workflow.mjs +52 -0
  328. package/workflows/e2e-smoke/workflow.mjs +59 -0
  329. package/workflows/e2e-vision-schema/README.md +48 -0
  330. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  331. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  332. package/workflows/file-census/README.md +14 -0
  333. package/workflows/file-census/scripts/.gitkeep +2 -0
  334. package/workflows/file-census/workflow.mjs +110 -0
  335. package/workflows/goal/README.md +166 -0
  336. package/workflows/goal/prompts/audit.md +57 -0
  337. package/workflows/goal/prompts/contract.md +56 -0
  338. package/workflows/goal/prompts/iterate.md +37 -0
  339. package/workflows/goal/workflow.mjs +501 -0
  340. package/workflows/illustrate/README.md +90 -0
  341. package/workflows/illustrate/assets/engines.json +20 -0
  342. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  343. package/workflows/illustrate/assets/extract-bing.js +33 -0
  344. package/workflows/illustrate/assets/extract-google.js +31 -0
  345. package/workflows/illustrate/workflow.mjs +301 -0
  346. package/workflows/plan/workflow.mjs +389 -0
  347. package/workflows/question-crops/README.md +35 -0
  348. package/workflows/question-crops/prompts/inventory.md +23 -0
  349. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  350. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  351. package/workflows/question-crops/workflow.mjs +172 -0
  352. package/workflows/ralph-loop/workflow.mjs +162 -0
  353. package/workflows/research/DESIGN.md +449 -0
  354. package/workflows/research/README.md +74 -0
  355. package/workflows/research/prompts/s0-goal.md +43 -0
  356. package/workflows/research/prompts/s1-early-exit.md +22 -0
  357. package/workflows/research/prompts/s1-map.md +58 -0
  358. package/workflows/research/prompts/s2-options.md +53 -0
  359. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  360. package/workflows/research/prompts/s4-verify.md +74 -0
  361. package/workflows/research/prompts/s5-synthesis.md +81 -0
  362. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  363. package/workflows/research/prompts/s6-package.md +32 -0
  364. package/workflows/research/scripts/build-report.mjs +98 -0
  365. package/workflows/research/workflow.mjs +288 -0
  366. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  367. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  368. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  369. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  370. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  371. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  372. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  373. package/workflows/wrong-question-docx/README.md +55 -0
  374. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  375. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  376. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  377. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  378. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  379. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  380. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  381. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  382. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  383. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  384. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  385. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  386. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  387. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  388. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  389. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  390. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  391. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  392. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  393. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  394. package/plugins/workflow-runner/src/expressions.js +0 -618
  395. package/plugins/workflow-runner/src/expressions.ts +0 -622
  396. package/plugins/workflow-runner/src/loader.js +0 -573
  397. package/plugins/workflow-runner/src/loader.ts +0 -721
  398. package/plugins/workflow-runner/src/multimodal.js +0 -38
  399. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  400. package/plugins/workflow-runner/src/recovery.js +0 -119
  401. package/plugins/workflow-runner/src/recovery.ts +0 -149
  402. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  403. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  404. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -41
  405. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -50
  406. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  407. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  408. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  409. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  410. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  411. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  412. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  413. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  414. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -208
  415. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -256
  416. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -58
  417. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -68
  418. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  419. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  420. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  421. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  422. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  423. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  424. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -147
  425. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  426. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  427. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -226
  428. package/plugins/workflow-runner/test/expressions.test.ts +0 -397
  429. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  430. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  431. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  432. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  433. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  434. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  435. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  436. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  437. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  438. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  439. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -87
  440. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  441. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  442. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -220
  443. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -379
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -150
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -338
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -270
  451. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  452. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  453. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  454. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  455. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  456. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  457. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  458. package/src/advisorState.js +0 -22
  459. package/src/cli/configWizard.js +0 -293
  460. package/src/tools/toolProgressBridge.js +0 -48
  461. package/workflows/adaptive-research.yaml +0 -50
  462. package/workflows/book-review-short.yaml +0 -125
  463. package/workflows/e2e-write-greet.yaml +0 -31
  464. package/workflows/illustrate.yaml +0 -227
  465. package/workflows/plan.yaml +0 -470
  466. package/workflows/ppt.yaml +0 -1670
  467. package/workflows/ralph-loop.yaml +0 -199
  468. package/workflows/schema.json +0 -176
  469. package/workflows/webppt.yaml +0 -496
  470. package/workflows/wechat-reading-shots.yaml +0 -315
  471. package/workflows/word.yaml +0 -720
  472. package/workflows/youtube-shorts.yaml +0 -202
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * skills/workflow-creator/scripts/list-resources.mjs
4
+ * —— 现场列出「这台机器上现在有什么可用」
5
+ *
6
+ * 用法:
7
+ * node skills/workflow-creator/scripts/list-resources.mjs 全部
8
+ * node skills/workflow-creator/scripts/list-resources.mjs --tools 只列工具
9
+ * node skills/workflow-creator/scripts/list-resources.mjs --skills 只列 skills
10
+ * node skills/workflow-creator/scripts/list-resources.mjs --json 机器可读
11
+ *
12
+ * ⚠️ **为什么要有这个脚本,而不是在 SKILL.md 里写一张表**
13
+ *
14
+ * 写死的清单必然过时。工具会增删(现在 40+ 个)、skills 是运行时扫目录的
15
+ * (现在近 30 个,用户还能在自己项目里放)、插件也可能装卸。SKILL.md 里那张
16
+ * 手抄表一旦落后,agent 照着它写就会:
17
+ * · 用不上已经存在的能力 → **重复造轮子**(自己写 PPT 生成逻辑而不是用 pptx skill)
18
+ * · 写出不存在的工具名 → 被 `allowedTools` 静默过滤,agent 少了能力还不报错
19
+ *
20
+ * 所以:**清单靠现场查,判断靠 SKILL.md**。这个脚本负责前者。
21
+ *
22
+ * 纯 JS、零依赖、只读 —— 和 scriptGuard.mjs 一样要能被 `node` 直接 spawn。
23
+ */
24
+
25
+ import { spawnSync } from 'node:child_process';
26
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
27
+ import { dirname, join } from 'node:path';
28
+ import { fileURLToPath } from 'node:url';
29
+
30
+ const HERE = dirname(fileURLToPath(import.meta.url));
31
+ const ROOT = join(HERE, '..', '..', '..');
32
+
33
+ const argv = process.argv.slice(2);
34
+ const wantJson = argv.includes('--json');
35
+ const only = argv.find((a) => ['--tools', '--skills', '--plugins'].includes(a));
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // 工具:**直接问内核要 ALL_TOOLS 的真实 name 字段**
39
+ //
40
+ // ⚠️ 不要从变量名推断。第一版就是那么干的(`lspTool` → `Lsp`、
41
+ // `webFetchTool` → `Webfetch`、`genImageTool` → `GenImage`),全都是**错的**
42
+ // 真名分别是 `LSP` / `WebFetch` / `GenerateImage`。
43
+ // 一个「防止写错工具名」的脚本自己给出错的名字,比没有这个脚本更糟 ——
44
+ // 作者会照着它写,然后被 allowedTools 静默过滤掉。
45
+ //
46
+ // 所以走 bun 拿真值。本项目本来就是 bun 跑的(package.json 的 scripts 全是),
47
+ // 拿不到时**明说降级**,绝不假装准确。
48
+ // ---------------------------------------------------------------------------
49
+ function listTools() {
50
+ // ⚠️ probe 里**一个空格、一个 `>` 都不能有**:Windows 上要靠 shell 才找得到 bun,
51
+ // 而 shell 会按空格拆参数、把 `>` 当重定向 —— 两者都会让命令当场被截断。
52
+ // 所以用 `JSON.stringify(值, 属性白名单)` 这个冷门重载拿字段,
53
+ // 而不是 `.map(t => t.name)`(既有箭头又有空格)。
54
+ const probe =
55
+ "import{ALL_TOOLS}from'./src/tools/index.ts';" +
56
+ "console.log(JSON.stringify(ALL_TOOLS,['name']))";
57
+ const r = spawnSync('bun', ['-e', probe], {
58
+ cwd: ROOT,
59
+ encoding: 'utf8',
60
+ shell: process.platform === 'win32',
61
+ });
62
+ if (r.status === 0 && r.stdout) {
63
+ const line = r.stdout.trim().split('\n').pop();
64
+ try {
65
+ const arr = JSON.parse(line);
66
+ const names = arr.map((o) => o?.name).filter((n) => typeof n === 'string');
67
+ if (names.length > 0) return { names, exact: true };
68
+ } catch {
69
+ /* 落到下面的降级 */
70
+ }
71
+ }
72
+ return { names: [], exact: false, why: (r.stderr || '').trim().slice(0, 200) };
73
+ }
74
+
75
+ /** 工具太多,按用途归组 —— agent 要的是「做这件事用哪个」,不是字母序清单。 */
76
+ const TOOL_GROUPS = [
77
+ ['读写文件', ['Read', 'Write', 'Edit', 'MultiEdit', 'NotebookEdit', 'Trash']],
78
+ ['查找', ['Glob', 'Grep', 'LSP']],
79
+ ['执行命令', ['Bash', 'PowerShell', 'TerminalCapture']],
80
+ ['联网', ['WebSearch', 'WebFetch', 'WebBrowser', 'Download']],
81
+ ['生成媒体', ['GenerateImage', 'GenerateSpeech', 'Snip']],
82
+ ['桌面操控', ['ComputerUse']],
83
+ ['问人 / 交付', ['AskUserQuestion', 'PresentResult']],
84
+ ['子任务 / 技能', ['Agent', 'Skill', 'Advisor']],
85
+ ['长期记忆', ['RecallMemory', 'RememberMemory', 'SearchConversations']],
86
+ ['worktree', ['EnterWorktree', 'ExitWorktree']],
87
+ ];
88
+
89
+ // ---------------------------------------------------------------------------
90
+ // skills:扫 skills/*/SKILL.md 的 frontmatter
91
+ // ---------------------------------------------------------------------------
92
+ function listSkills() {
93
+ const dir = join(ROOT, 'skills');
94
+ const out = [];
95
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
96
+ if (!e.isDirectory()) continue;
97
+ const f = join(dir, e.name, 'SKILL.md');
98
+ if (!existsSync(f)) continue;
99
+ const head = readFileSync(f, 'utf8').slice(0, 1200);
100
+ const desc = head.match(/^description:\s*([\s\S]*?)(?=\n[a-z_-]+:|\n---)/m);
101
+ out.push({
102
+ name: e.name,
103
+ description: (desc?.[1] ?? '').replace(/\s+/g, ' ').trim().slice(0, 100),
104
+ });
105
+ }
106
+ return out.sort((a, b) => a.name.localeCompare(b.name));
107
+ }
108
+
109
+ // ---------------------------------------------------------------------------
110
+ // 插件:带 plugin.json 的目录 + 它们暴露的东西
111
+ // ---------------------------------------------------------------------------
112
+ function listPlugins() {
113
+ const dir = join(ROOT, 'plugins');
114
+ const out = [];
115
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
116
+ if (!e.isDirectory()) continue;
117
+ const manifest = join(dir, e.name, '.claude-plugin', 'plugin.json');
118
+ if (!existsSync(manifest)) continue;
119
+ let meta = {};
120
+ try {
121
+ meta = JSON.parse(readFileSync(manifest, 'utf8'));
122
+ } catch {
123
+ /* 坏 manifest 不阻断 */
124
+ }
125
+ const cmdDir = join(dir, e.name, 'commands');
126
+ const commands = existsSync(cmdDir)
127
+ ? readdirSync(cmdDir)
128
+ .filter((f) => f.endsWith('.md'))
129
+ .map((f) => `/${f.replace(/\.md$/, '')}`)
130
+ : [];
131
+ out.push({
132
+ name: meta.name ?? e.name,
133
+ description: String(meta.description ?? '').slice(0, 120),
134
+ commands,
135
+ });
136
+ }
137
+ return out;
138
+ }
139
+
140
+ // ---------------------------------------------------------------------------
141
+ // 输出
142
+ // ---------------------------------------------------------------------------
143
+ const toolInfo = listTools();
144
+ const tools = toolInfo.names;
145
+ const skills = listSkills();
146
+ const plugins = listPlugins();
147
+
148
+ if (wantJson) {
149
+ console.log(
150
+ JSON.stringify(
151
+ { tools, toolsExact: toolInfo.exact, skills, plugins },
152
+ null,
153
+ 2,
154
+ ),
155
+ );
156
+ process.exit(0);
157
+ }
158
+
159
+ const show = (k) => !only || only === `--${k}`;
160
+
161
+ if (show('tools')) {
162
+ if (!toolInfo.exact) {
163
+ // 宁可不报,也不给一份可能是错的工具名清单 —— 作者会照着它写,
164
+ // 然后被 allowedTools 静默过滤掉,比没有清单更糟。
165
+ console.log('\n⚠️ 拿不到工具清单 —— 需要 bun 可用(本项目本来就用 bun 跑)。');
166
+ if (toolInfo.why) console.log(` ${toolInfo.why}`);
167
+ console.log(' 工具名请直接看 src/tools/index.ts::ALL_TOOLS。\n');
168
+ } else {
169
+ console.log(
170
+ `\n═══ 工具(${tools.length} 个)—— 用于 tool() / allowedTools ═══\n`,
171
+ );
172
+ const seen = new Set();
173
+ for (const [group, names] of TOOL_GROUPS) {
174
+ const have = names.filter((n) => tools.includes(n));
175
+ if (have.length === 0) continue;
176
+ for (const n of have) seen.add(n);
177
+ console.log(` ${group.padEnd(14)} ${have.join(' ')}`);
178
+ }
179
+ const rest = tools.filter((t) => !seen.has(t));
180
+ if (rest.length > 0) console.log(` ${'其它'.padEnd(14)} ${rest.join(' ')}`);
181
+ console.log(
182
+ '\n ⚠️ allowedTools 里写错的名字会被**静默过滤**(引擎会发 warning,但别依赖它)。',
183
+ );
184
+ }
185
+ }
186
+
187
+ if (show('skills')) {
188
+ console.log(`\n═══ Skills(${skills.length} 个)—— 用 skill(名字, 任务描述) 调 ═══\n`);
189
+ for (const s of skills) {
190
+ console.log(` ${s.name.padEnd(22)} ${s.description}`);
191
+ }
192
+ console.log(
193
+ '\n 提示:现有 Skill 的能力、输入与产出契约匹配当前阶段时优先复用;不匹配时不要为迁就 Skill 扭曲流程。',
194
+ );
195
+ }
196
+
197
+ if (show('plugins')) {
198
+ console.log(`\n═══ 插件(${plugins.length} 个)═══\n`);
199
+ for (const p of plugins) {
200
+ console.log(` ${p.name.padEnd(24)} ${p.commands.join(' ') || '(无命令)'}`);
201
+ if (p.description) console.log(` ${' '.repeat(24)} ${p.description}`);
202
+ }
203
+ }
204
+
205
+ console.log('');
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 生成最小动态工作流目录。默认只创建真正必需的 workflow.mjs 和 README.md;
4
+ * scripts/prompts/assets 只有显式请求才创建,避免空目录和失效模板。
5
+ */
6
+
7
+ import { existsSync } from 'node:fs';
8
+ import { mkdir, writeFile } from 'node:fs/promises';
9
+ import { dirname, isAbsolute, join, resolve } from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+
12
+ const HERE = dirname(fileURLToPath(import.meta.url));
13
+
14
+ function findRepoRoot() {
15
+ const marker = join('plugins', 'workflow-runner', 'src', 'scriptGuard.mjs');
16
+ for (const start of [HERE, process.cwd()]) {
17
+ let dir = resolve(start);
18
+ for (let i = 0; i < 8; i++) {
19
+ if (existsSync(join(dir, marker))) return dir;
20
+ const up = dirname(dir);
21
+ if (up === dir) break;
22
+ dir = up;
23
+ }
24
+ }
25
+ return null;
26
+ }
27
+
28
+ function optionValue(prefix) {
29
+ const inline = process.argv.find((arg) => arg.startsWith(`${prefix}=`));
30
+ if (inline) return inline.slice(prefix.length + 1);
31
+ const index = process.argv.indexOf(prefix);
32
+ return index >= 0 ? process.argv[index + 1] : undefined;
33
+ }
34
+
35
+ const name = process.argv[2];
36
+ if (!name || name.startsWith('-')) {
37
+ console.error(
38
+ '用法:scaffold.mjs <名字> [--with=scripts,prompts,assets] [--workflows-root=<目录>]',
39
+ );
40
+ process.exit(1);
41
+ }
42
+ if (!/^[A-Za-z0-9._-]+$/.test(name)) {
43
+ console.error(`名字只能含字母数字 . _ -,收到「${name}」。`);
44
+ process.exit(1);
45
+ }
46
+
47
+ const root = findRepoRoot();
48
+ if (!root) {
49
+ console.error('找不到 minimal-agent 仓库根,请在仓库内运行。');
50
+ process.exit(1);
51
+ }
52
+
53
+ const requested = new Set(
54
+ String(optionValue('--with') ?? '')
55
+ .split(',')
56
+ .map((item) => item.trim())
57
+ .filter(Boolean),
58
+ );
59
+ const allowed = new Set(['scripts', 'prompts', 'assets']);
60
+ const unknown = [...requested].filter((item) => !allowed.has(item));
61
+ if (unknown.length) {
62
+ console.error(
63
+ `--with 不支持:${unknown.join(', ')};可选 scripts,prompts,assets`,
64
+ );
65
+ process.exit(1);
66
+ }
67
+
68
+ const configuredRoot = optionValue('--workflows-root');
69
+ const workflowsRoot = configuredRoot
70
+ ? isAbsolute(configuredRoot)
71
+ ? configuredRoot
72
+ : resolve(configuredRoot)
73
+ : join(root, 'workflows');
74
+ const dir = join(workflowsRoot, name);
75
+ if (existsSync(dir)) {
76
+ console.error(`${dir} 已存在,不覆盖。`);
77
+ process.exit(1);
78
+ }
79
+
80
+ await mkdir(dir, { recursive: true });
81
+ for (const subdir of requested)
82
+ await mkdir(join(dir, subdir), { recursive: true });
83
+
84
+ const workflow = `export const meta = {
85
+ apiVersion: 2,
86
+ description: 'TODO:一句话说明这个工作流交付什么成果',
87
+ inputs: [{ name: 'request', required: true, greedy: true }],
88
+ artifacts: [],
89
+ }
90
+
91
+ export default async function run(wf) {
92
+ // 先定义阶段契约:输入、输出、执行方式、成功证据、失败与恢复语义。
93
+ // 纯计算直接 import;确定性副作用用 wf.fs/wf.exec/wf.tools;开放判断用 wf.model。
94
+ const result = await wf.model.generate(
95
+ \`根据以下请求给出结果:\\n\\n\${wf.input.values.request}\`,
96
+ { label: '生成结果' },
97
+ )
98
+
99
+ wf.output.message(result)
100
+ return { result }
101
+ }
102
+ `;
103
+
104
+ await writeFile(join(dir, 'workflow.mjs'), workflow, 'utf8');
105
+ await writeFile(
106
+ join(dir, 'README.md'),
107
+ `# ${name}
108
+
109
+ ## 意图与边界
110
+ TODO:解决什么问题;什么情况不应使用这个工作流。
111
+
112
+ ## 阶段契约
113
+ TODO:逐阶段写明输入、输出、执行方式、成功证据、失败与恢复语义。
114
+
115
+ ## 输入与产物
116
+ TODO:输入含义、产物路径与格式、最终验收方式。
117
+
118
+ ## 前置条件与已知限制
119
+ TODO:仅记录真实存在的依赖和限制。
120
+ `,
121
+ 'utf8',
122
+ );
123
+
124
+ if (requested.has('scripts')) {
125
+ await writeFile(
126
+ join(dir, 'scripts', 'README.md'),
127
+ `确定性辅助脚本放在这里并使用 .mjs。工作流中通过:
128
+
129
+ await wf.exec.file('./scripts/<脚本>.mjs', ['子命令', '参数'])
130
+
131
+ 调用独立进程;纯计算辅助模块应直接 import。提示词用 wf.runtime.workflowDir 定位,
132
+ 不要假设当前 cwd 是工作流目录。
133
+ `,
134
+ 'utf8',
135
+ );
136
+ }
137
+
138
+ console.log(`✅ 已生成 ${dir}`);
139
+ console.log(
140
+ ` 可选目录:${requested.size ? [...requested].join(', ') : '无(按需再加)'}`,
141
+ );
142
+ console.log('');
143
+ console.log('下一步:');
144
+ console.log(` 1. 填写 ${join(dir, 'README.md')} 的阶段契约`);
145
+ console.log(` 2. 编辑 ${join(dir, 'workflow.mjs')}`);
146
+ console.log(
147
+ ` 3. node skills/workflow-creator/scripts/validate.mjs ${join(dir, 'workflow.mjs')}`,
148
+ );
@@ -0,0 +1,275 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * skills/workflow-creator/scripts/validate.mjs —— 工作流脚本校验
4
+ *
5
+ * 用法:
6
+ * node skills/workflow-creator/scripts/validate.mjs workflows/<名字>/workflow.mjs
7
+ * node skills/workflow-creator/scripts/validate.mjs --all # 校验全部工作流
8
+ * node skills/workflow-creator/scripts/validate.mjs --api-doc # 只跑 api.md 对账
9
+ *
10
+ * 四层检查:
11
+ * ① 引擎那份 scriptGuard.mjs(禁用构造 / meta 形状)—— **不另写一份**,
12
+ * 否则作者期与运行期的判据会分家,那正是这个文件要防的事。
13
+ * ② 脊梁规则:声明了产物、也用了 agent(),却全脚本没有一次 exists()/verify()
14
+ * → 这条工作流没有任何核实,agent 一旦 announce-not-do 就静默烂尾。
15
+ * ③ api.md 与 WorkflowContext 能力注册表对账 —— 手抄的参考会漂移,而漂移的参考比
16
+ * 没有参考更糟(它会教错)。
17
+ * ④ 配套目录检查:源码中可静态确定的 scripts/prompts/assets 引用必须存在。
18
+ *
19
+ * 退出码:0 全通过(可能有 warning);1 有 error。
20
+ */
21
+
22
+ import { readFile, readdir } from 'node:fs/promises';
23
+ import { existsSync } from 'node:fs';
24
+ import { basename, dirname, join, normalize, resolve, sep } from 'node:path';
25
+ import { fileURLToPath, pathToFileURL } from 'node:url';
26
+
27
+ const HERE = dirname(fileURLToPath(import.meta.url));
28
+
29
+ /** 从若干起点逐级向上找 minimal-agent 仓库根(认 plugins/workflow-runner/src 为标志)。 */
30
+ function findRepoRoot() {
31
+ const marker = join('plugins', 'workflow-runner', 'src', 'scriptGuard.mjs');
32
+ for (const start of [HERE, process.cwd()]) {
33
+ let dir = resolve(start);
34
+ for (let i = 0; i < 8; i++) {
35
+ if (existsSync(join(dir, marker))) return dir;
36
+ const up = dirname(dir);
37
+ if (up === dir) break;
38
+ dir = up;
39
+ }
40
+ }
41
+ return null;
42
+ }
43
+
44
+ const ROOT = findRepoRoot();
45
+ if (!ROOT) {
46
+ console.error(
47
+ '找不到 minimal-agent 仓库根(需要 plugins/workflow-runner/src/scriptGuard.mjs)。\n' +
48
+ '请在 minimal-agent 仓库内运行本脚本 —— 它刻意复用引擎那份守卫,不自己再写一份。',
49
+ );
50
+ process.exit(1);
51
+ }
52
+
53
+ const ENGINE = join(ROOT, 'plugins', 'workflow-runner', 'src');
54
+ const { validateScript, blankLiteralsAndComments } = await import(
55
+ pathToFileURL(join(ENGINE, 'scriptGuard.mjs')).href
56
+ );
57
+ const CONTEXT_CAPABILITIES = JSON.parse(
58
+ await readFile(join(ENGINE, 'workflowContextCapabilities.json'), 'utf8'),
59
+ );
60
+ const CONTEXT_NAMES = Object.entries(CONTEXT_CAPABILITIES).flatMap(([group, names]) =>
61
+ names.map((name) => `wf.${group}.${name}`),
62
+ );
63
+
64
+ /** 统计某个调用在**抹除字符串与注释后**的源码里出现几次(避免 prompt 文本误命中)。 */
65
+ function countCalls(blanked, name) {
66
+ const re = new RegExp(`${name.replace(/\\./g, '\\\\.')}\\s*\\(`, 'g');
67
+ return (blanked.match(re) ?? []).length;
68
+ }
69
+
70
+ /**
71
+ * 脊梁规则检查。
72
+ *
73
+ * 判据刻意保守(宁可漏报不要误报):只有当「用了 agent() **且** 声明了产物
74
+ * **且** 全脚本一次 exists()/verify() 都没有」时才报。这三条同时成立时,
75
+ * 这条工作流对 announce-not-do 是完全没有防护的。
76
+ */
77
+ function checkSpine(source, meta) {
78
+ const blanked = blankLiteralsAndComments(source);
79
+ const agents = countCalls(blanked, 'wf.model.agent');
80
+ if (agents === 0) return null;
81
+
82
+ const declaresArtifacts =
83
+ (Array.isArray(meta?.artifacts) && meta.artifacts.length > 0) ||
84
+ countCalls(blanked, 'wf.output.artifact') > 0;
85
+ if (!declaresArtifacts) return null;
86
+
87
+ // 脊梁规则的本质是「**不盲信 agent 的自述**」,核实形态不止一种:
88
+ // ① 核实文件 exists() / verify()
89
+ // ② 核实协议令牌 openState.match(/OPEN=([a-z]+)/) 之后判定
90
+ // ③ 核实结构化产出 parseJson(text) 之后判字段
91
+ //
92
+ // ⚠️ 早先只认 ①,于是 wechat-reading-shots 被误报 —— 它的 agent 调用一个文件都
93
+ // 不产出(产物是 ComputerUse observe 直接返回的截图),核实的是 `OPEN=ok` /
94
+ // `PAGE=N M` 这类协议令牌,守卫其实很严。**误报比漏报更伤**:作者一旦习惯
95
+ // 「这个警告可以忽略」,真正该看的那次也会被划过去。
96
+ const checks =
97
+ countCalls(blanked, 'wf.fs.exists') +
98
+ countCalls(blanked, 'wf.check.verify') +
99
+ (blanked.match(/\.match\s*\(/g)?.length ?? 0);
100
+ if (checks > 0) return null;
101
+
102
+ return (
103
+ `脚本有 ${agents} 处 agent() 调用并声明了产物,却没有任何核实。\n` +
104
+ ' agent 一旦「宣告要做却没动手」(announce-not-do),这条工作流会静默交付一个不存在的产物。\n' +
105
+ ' 核实方式任选其一:exists()/verify() 查文件、.match() 取协议令牌、parseJson() 解析结构化产出。\n' +
106
+ ' 参见 references/patterns.md 的脊梁规则。'
107
+ );
108
+ }
109
+
110
+ /** api.md 的能力表里列了哪些完整路径。 */
111
+ async function namesInApiDoc() {
112
+ const doc = await readFile(join(HERE, '..', 'references', 'api.md'), 'utf8');
113
+ const table = doc.slice(doc.indexOf('## 能力表'), doc.indexOf('## 选项'));
114
+ const names = new Set();
115
+ for (const m of table.matchAll(/^\|\s*`([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+)`\s*\|/gm)) {
116
+ names.add(m[1]);
117
+ }
118
+ return names;
119
+ }
120
+
121
+ async function checkApiDoc() {
122
+ const documented = await namesInApiDoc();
123
+ const declared = new Set(CONTEXT_NAMES);
124
+ const missing = [...declared].filter((n) => !documented.has(n));
125
+ const extra = [...documented].filter((n) => !declared.has(n));
126
+ const problems = [];
127
+ if (missing.length) {
128
+ problems.push(
129
+ `api.md 的能力表漏了:${missing.join(', ')}(引擎注入了但参考里没写,作者不会知道它存在)`,
130
+ );
131
+ }
132
+ if (extra.length) {
133
+ problems.push(
134
+ `api.md 的能力表多了:${extra.join(', ')}(参考里写了但引擎没注入,作者照着写会踩空)`,
135
+ );
136
+ }
137
+ return problems;
138
+ }
139
+
140
+ /**
141
+ * 真实加载 ESM 模块。默认 run 不执行,因此不会启动业务;相对 import 与运行时包
142
+ * 也会按生产规则解析,避免作者期校验与运行期分家。
143
+ */
144
+ async function checkSyntax(file) {
145
+ try {
146
+ const mod = await import(`${pathToFileURL(file).href}?validate=${encodeURIComponent(String(process.pid))}`);
147
+ if (typeof mod.default !== 'function') return '缺少 default run(wf) 导出';
148
+ return null;
149
+ } catch (e) {
150
+ return `语法错误:${e instanceof Error ? e.message : String(e)}`;
151
+ }
152
+ }
153
+
154
+ /**
155
+ * 检查工作流源码中能静态确定的配套文件引用。动态文件名无法假装验证,但其
156
+ * scripts/prompts/assets 根目录仍必须存在。路径只允许落在当前工作流目录或仓库
157
+ * workflows 下,避免校验器替脚本接受越界引用。
158
+ */
159
+ function checkCompanionReferences(source, file) {
160
+ const problems = [];
161
+ const workflowDir = dirname(resolve(file));
162
+ const workflowName = basename(workflowDir);
163
+ const workflowsRoot = dirname(workflowDir);
164
+ const checked = new Set();
165
+
166
+ const checkPath = (candidate, label) => {
167
+ const absolute = normalize(resolve(candidate));
168
+ const allowed =
169
+ absolute === workflowDir ||
170
+ absolute.startsWith(`${workflowDir}${sep}`) ||
171
+ absolute.startsWith(`${workflowsRoot}${sep}`);
172
+ if (!allowed) {
173
+ problems.push(`${label} 越出 workflows 目录:${absolute}`);
174
+ return;
175
+ }
176
+ if (checked.has(absolute)) return;
177
+ checked.add(absolute);
178
+ if (!existsSync(absolute)) problems.push(`${label} 不存在:${absolute}`);
179
+ };
180
+
181
+ // 完整静态文件引用:workflows/foo/scripts/a.mjs 或 scripts/a.mjs。
182
+ const exact =
183
+ /(?:^|[\s'"`(,=])(?:workflows\/([A-Za-z0-9._-]+)\/)?(scripts|prompts|assets)\/([A-Za-z0-9._/-]+\.[A-Za-z0-9._-]+)/gm;
184
+ for (const match of source.matchAll(exact)) {
185
+ const [, owner, kind, tail] = match;
186
+ const base = owner ? join(workflowsRoot, owner) : workflowDir;
187
+ checkPath(join(base, kind, tail), `配套文件引用 ${match[0]}`);
188
+ }
189
+
190
+ // 动态尾部至少检查根目录,例如 const PROMPTS='workflows/x/prompts'。
191
+ const roots =
192
+ /(?:^|[\s'"`(,=])(?:workflows\/([A-Za-z0-9._-]+)\/)?(scripts|prompts|assets)(?=[/'"`])/gm;
193
+ for (const match of source.matchAll(roots)) {
194
+ const [, owner, kind] = match;
195
+ // 普通英文叙述偶尔会出现裸单词;只检查当前工作流或显式 workflows 前缀。
196
+ if (!owner && !source.includes(`${kind}/`)) continue;
197
+ const base = owner ? join(workflowsRoot, owner) : workflowDir;
198
+ checkPath(join(base, kind), `配套目录引用 ${owner ? `workflows/${owner}/` : ''}${kind}`);
199
+ }
200
+
201
+ // 显式写错工作流名通常是复制后忘改,比“文件不存在”更容易定位。
202
+ for (const match of source.matchAll(/workflows\/([A-Za-z0-9._-]+)\/(scripts|prompts|assets)/g)) {
203
+ if (match[1] !== workflowName && !existsSync(join(workflowsRoot, match[1]))) {
204
+ problems.push(`引用了未知工作流目录 workflows/${match[1]}/(当前是 ${workflowName})`);
205
+ }
206
+ }
207
+ return [...new Set(problems)];
208
+ }
209
+
210
+ async function validateOne(file) {
211
+ const source = await readFile(file, 'utf8');
212
+ const verdict = validateScript(source, { filename: file });
213
+ const errors = [...verdict.errors];
214
+ const warnings = [];
215
+
216
+ if (verdict.ok) {
217
+ const syntax = await checkSyntax(file);
218
+ if (syntax) errors.push(syntax);
219
+ const spine = checkSpine(source, verdict.meta);
220
+ if (spine) warnings.push(spine);
221
+ errors.push(...checkCompanionReferences(source, file));
222
+ }
223
+ return { file, errors, warnings };
224
+ }
225
+
226
+ async function listWorkflowScripts() {
227
+ const dir = join(ROOT, 'workflows');
228
+ const out = [];
229
+ for (const e of await readdir(dir, { withFileTypes: true })) {
230
+ if (!e.isDirectory()) continue;
231
+ const p = join(dir, e.name, 'workflow.mjs');
232
+ if (existsSync(p)) out.push(p);
233
+ }
234
+ return out;
235
+ }
236
+
237
+ // ---- 主流程 ----
238
+ const argv = process.argv.slice(2);
239
+ let failed = false;
240
+
241
+ const apiProblems = await checkApiDoc();
242
+ if (apiProblems.length) {
243
+ failed = true;
244
+ console.error('❌ api.md 与 WorkflowContext 能力注册表不同步:');
245
+ for (const p of apiProblems) console.error(` · ${p}`);
246
+ } else if (argv.includes('--api-doc')) {
247
+ console.log('✅ api.md 与 WorkflowContext 能力注册表一致');
248
+ }
249
+ if (argv.includes('--api-doc')) process.exit(failed ? 1 : 0);
250
+
251
+ const targets = argv.includes('--all')
252
+ ? await listWorkflowScripts()
253
+ : argv.filter((a) => !a.startsWith('--'));
254
+
255
+ if (targets.length === 0) {
256
+ console.error('用法:validate.mjs <workflow.mjs> | --all | --api-doc');
257
+ process.exit(1);
258
+ }
259
+
260
+ for (const t of targets) {
261
+ const r = await validateOne(t);
262
+ const rel = r.file.replace(`${ROOT}\\`, '').replace(`${ROOT}/`, '');
263
+ if (r.errors.length) {
264
+ failed = true;
265
+ console.error(`❌ ${rel}`);
266
+ for (const e of r.errors) console.error(` · ${e}`);
267
+ } else if (r.warnings.length) {
268
+ console.warn(`⚠️ ${rel}`);
269
+ for (const w of r.warnings) console.warn(` · ${w}`);
270
+ } else {
271
+ console.log(`✅ ${rel}`);
272
+ }
273
+ }
274
+
275
+ process.exit(failed ? 1 : 0);