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,47 @@
1
+ /**
2
+ * ============================================================
3
+ * plugins/workflow-runner/src/util.ts —— 引擎内共用小件
4
+ * ------------------------------------------------------------
5
+ * 只放「多处要用、又不值得单开文件」的纯函数。有任何状态或 IO 的都不该进这里。
6
+ * ============================================================
7
+ */
8
+ import { resolve, sep } from 'node:path';
9
+ /** 截断到 n 个字符,超出补省略号。 */
10
+ export function truncate(s, n) {
11
+ return s.length > n ? `${s.slice(0, n)}…` : s;
12
+ }
13
+ /**
14
+ * 把一个声明产物路径收敛成「相对 workingDir 的安全相对路径」;越界返回 null。
15
+ *
16
+ * 自 legacy `types.ts` 原样移植,两处判据都是踩出来的,改之前先读:
17
+ *
18
+ * ① **前缀匹配必须带路径分隔符边界**。裸 `startsWith(base)` 会让 `/repo` 匹配上
19
+ * `/repo-hack/evil` —— 一个只差几个字符的兄弟目录就能骗过越界检查。
20
+ *
21
+ * ② **Windows 上比较前要统一大小写**。NTFS 不区分大小写,`D:\Code` 与 `D:\code`
22
+ * 是同一个目录,逐字节比较会把合法路径判成越界。(相关教训见记忆
23
+ * `project_windows_path_separator_gotcha`:同一类判据写死 `/` 分隔符时,
24
+ * Windows 上条件恒为 false,缓存清理曾因此静默失效。)
25
+ */
26
+ export function safeArtifactPath(workingDir, rawPath) {
27
+ if (!rawPath || typeof rawPath !== 'string')
28
+ return null;
29
+ const base = resolve(workingDir);
30
+ const baseWithSep = base.endsWith(sep) ? base : base + sep;
31
+ let abs;
32
+ try {
33
+ abs = resolve(workingDir, rawPath);
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ const sameCase = (p) => process.platform === 'win32' ? p.toLowerCase() : p;
39
+ const nAbs = sameCase(abs);
40
+ const nBase = sameCase(base);
41
+ const nBaseSep = sameCase(baseWithSep);
42
+ // 恰好等于 base 本身(rawPath='.' 这种极端情形)也算合法。
43
+ if (nAbs !== nBase && !nAbs.startsWith(nBaseSep))
44
+ return null;
45
+ const rel = abs.slice(base.length).replace(/^[/\\]/, '');
46
+ return rel.length === 0 ? '.' : rel;
47
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * ============================================================
3
+ * plugins/workflow-runner/src/util.ts —— 引擎内共用小件
4
+ * ------------------------------------------------------------
5
+ * 只放「多处要用、又不值得单开文件」的纯函数。有任何状态或 IO 的都不该进这里。
6
+ * ============================================================
7
+ */
8
+
9
+ import { resolve, sep } from 'node:path';
10
+
11
+ /** 截断到 n 个字符,超出补省略号。 */
12
+ export function truncate(s: string, n: number): string {
13
+ return s.length > n ? `${s.slice(0, n)}…` : s;
14
+ }
15
+
16
+ /**
17
+ * 把一个声明产物路径收敛成「相对 workingDir 的安全相对路径」;越界返回 null。
18
+ *
19
+ * 自 legacy `types.ts` 原样移植,两处判据都是踩出来的,改之前先读:
20
+ *
21
+ * ① **前缀匹配必须带路径分隔符边界**。裸 `startsWith(base)` 会让 `/repo` 匹配上
22
+ * `/repo-hack/evil` —— 一个只差几个字符的兄弟目录就能骗过越界检查。
23
+ *
24
+ * ② **Windows 上比较前要统一大小写**。NTFS 不区分大小写,`D:\Code` 与 `D:\code`
25
+ * 是同一个目录,逐字节比较会把合法路径判成越界。(相关教训见记忆
26
+ * `project_windows_path_separator_gotcha`:同一类判据写死 `/` 分隔符时,
27
+ * Windows 上条件恒为 false,缓存清理曾因此静默失效。)
28
+ */
29
+ export function safeArtifactPath(
30
+ workingDir: string,
31
+ rawPath: string,
32
+ ): string | null {
33
+ if (!rawPath || typeof rawPath !== 'string') return null;
34
+ const base = resolve(workingDir);
35
+ const baseWithSep = base.endsWith(sep) ? base : base + sep;
36
+ let abs: string;
37
+ try {
38
+ abs = resolve(workingDir, rawPath);
39
+ } catch {
40
+ return null;
41
+ }
42
+ const sameCase = (p: string): string =>
43
+ process.platform === 'win32' ? p.toLowerCase() : p;
44
+ const nAbs = sameCase(abs);
45
+ const nBase = sameCase(base);
46
+ const nBaseSep = sameCase(baseWithSep);
47
+ // 恰好等于 base 本身(rawPath='.' 这种极端情形)也算合法。
48
+ if (nAbs !== nBase && !nAbs.startsWith(nBaseSep)) return null;
49
+ const rel = abs.slice(base.length).replace(/^[/\\]/, '');
50
+ return rel.length === 0 ? '.' : rel;
51
+ }
@@ -0,0 +1,20 @@
1
+ import capabilities from './workflowContextCapabilities.json' with { type: 'json' };
2
+ export const WORKFLOW_CONTEXT_CAPABILITIES = capabilities;
3
+ export function assertWorkflowContextShape(value) {
4
+ const context = value;
5
+ for (const [group, names] of Object.entries(WORKFLOW_CONTEXT_CAPABILITIES)) {
6
+ const actual = context[group];
7
+ if (!actual || typeof actual !== 'object') {
8
+ throw new Error(`WorkflowContext 缺少能力组 wf.${group}`);
9
+ }
10
+ const keys = Object.keys(actual).sort();
11
+ const expected = [...names].sort();
12
+ const missing = expected.filter((name) => !keys.includes(name));
13
+ const extra = keys.filter((name) => !expected.includes(name));
14
+ if (missing.length || extra.length) {
15
+ throw new Error(`WorkflowContext wf.${group} 与能力注册表不同步` +
16
+ `${missing.length ? `;缺少 ${missing.join(', ')}` : ''}` +
17
+ `${extra.length ? `;多出 ${extra.join(', ')}` : ''}`);
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,58 @@
1
+ import capabilities from './workflowContextCapabilities.json' with { type: 'json' };
2
+
3
+ export const WORKFLOW_CONTEXT_CAPABILITIES = capabilities as Readonly<
4
+ Record<string, readonly string[]>
5
+ >;
6
+
7
+ export interface WorkflowPipelineSuccess<T = unknown> {
8
+ ok: true;
9
+ index: number;
10
+ value: T;
11
+ }
12
+
13
+ export interface WorkflowPipelineFailure {
14
+ ok: false;
15
+ index: number;
16
+ error: { name: string; message: string; code?: string };
17
+ }
18
+
19
+ export interface WorkflowPipelineResult<T = unknown> {
20
+ results: (WorkflowPipelineSuccess<T> | WorkflowPipelineFailure)[];
21
+ succeeded: number;
22
+ failed: number;
23
+ }
24
+
25
+ /** Public V2 contract. Function signatures remain structural so the registry is the key truth. */
26
+ export interface WorkflowContext {
27
+ input: { values: Record<string, unknown>; resources: Record<string, unknown> };
28
+ runtime: Record<string, unknown>;
29
+ model: Record<string, (...args: any[]) => any>;
30
+ tools: Record<string, (...args: any[]) => any>;
31
+ exec: Record<string, (...args: any[]) => any>;
32
+ fs: Record<string, (...args: any[]) => any>;
33
+ flow: Record<string, (...args: any[]) => any>;
34
+ check: Record<string, (...args: any[]) => any>;
35
+ state: Record<string, (...args: any[]) => any>;
36
+ output: Record<string, (...args: any[]) => any>;
37
+ }
38
+
39
+ export function assertWorkflowContextShape(value: object): void {
40
+ const context = value as Record<string, unknown>;
41
+ for (const [group, names] of Object.entries(WORKFLOW_CONTEXT_CAPABILITIES)) {
42
+ const actual = context[group];
43
+ if (!actual || typeof actual !== 'object') {
44
+ throw new Error(`WorkflowContext 缺少能力组 wf.${group}`);
45
+ }
46
+ const keys = Object.keys(actual).sort();
47
+ const expected = [...names].sort();
48
+ const missing = expected.filter((name) => !keys.includes(name));
49
+ const extra = keys.filter((name) => !expected.includes(name));
50
+ if (missing.length || extra.length) {
51
+ throw new Error(
52
+ `WorkflowContext wf.${group} 与能力注册表不同步` +
53
+ `${missing.length ? `;缺少 ${missing.join(', ')}` : ''}` +
54
+ `${extra.length ? `;多出 ${extra.join(', ')}` : ''}`,
55
+ );
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,36 @@
1
+ import { discoverWorkflows } from './discovery.js';
2
+ import { fingerprint } from './journal.js';
3
+ import { workflowFingerprint } from './workflowFingerprint.js';
4
+ /** Resolve once per root execution using the same override precedence as /workflow. */
5
+ export async function resolveWorkflowBundle(root, cwd) {
6
+ const discovered = root.meta.dependencies?.length
7
+ ? await discoverWorkflows(cwd)
8
+ : { workflows: [], failures: [] };
9
+ const scripts = new Map(discovered.workflows.map((s) => [s.name, s]));
10
+ scripts.set(root.name, root);
11
+ async function visit(script, ancestors) {
12
+ if (ancestors.includes(script.name))
13
+ throw new Error(`工作流依赖环:${[...ancestors, script.name].join(' → ')}`);
14
+ if (ancestors.length >= 8)
15
+ throw new Error('子工作流嵌套超过8层');
16
+ if (ancestors.length && script.meta.managedRuntime)
17
+ throw new Error(`不能把 managedRuntime 工作流 ${script.name} 作为子流程调用`);
18
+ const children = new Map();
19
+ for (const name of script.meta.dependencies ?? []) {
20
+ const child = scripts.get(name);
21
+ if (!child)
22
+ throw new Error(`依赖工作流 ${name} 不可用:${discovered.failures.find((f) => f.name === name)?.errors.join('; ') ?? '未找到'}`);
23
+ children.set(name, await visit(child, [...ancestors, script.name]));
24
+ }
25
+ const own = await workflowFingerprint(script.source, script.dir, script.meta.packages ?? []);
26
+ // Keep legacy leaf fingerprints, avoiding unrelated invalidations.
27
+ const hash = children.size
28
+ ? fingerprint('workflow-tree-v1', {
29
+ own,
30
+ children: [...children].map(([name, b]) => [name, b.hash]),
31
+ })
32
+ : own;
33
+ return { script, hash, children };
34
+ }
35
+ return visit(root, []);
36
+ }
@@ -0,0 +1,59 @@
1
+ import { discoverWorkflows } from './discovery.js';
2
+ import { fingerprint } from './journal.js';
3
+ import type { WorkflowScript } from './types.js';
4
+ import { workflowFingerprint } from './workflowFingerprint.js';
5
+
6
+ export interface WorkflowBundle {
7
+ script: WorkflowScript;
8
+ hash: string;
9
+ children: Map<string, WorkflowBundle>;
10
+ }
11
+
12
+ /** Resolve once per root execution using the same override precedence as /workflow. */
13
+ export async function resolveWorkflowBundle(
14
+ root: WorkflowScript,
15
+ cwd: string,
16
+ ): Promise<WorkflowBundle> {
17
+ const discovered = root.meta.dependencies?.length
18
+ ? await discoverWorkflows(cwd)
19
+ : { workflows: [], failures: [] };
20
+ const scripts = new Map(discovered.workflows.map((s) => [s.name, s]));
21
+ scripts.set(root.name, root);
22
+ async function visit(
23
+ script: WorkflowScript,
24
+ ancestors: string[],
25
+ ): Promise<WorkflowBundle> {
26
+ if (ancestors.includes(script.name))
27
+ throw new Error(
28
+ `工作流依赖环:${[...ancestors, script.name].join(' → ')}`,
29
+ );
30
+ if (ancestors.length >= 8) throw new Error('子工作流嵌套超过8层');
31
+ if (ancestors.length && script.meta.managedRuntime)
32
+ throw new Error(
33
+ `不能把 managedRuntime 工作流 ${script.name} 作为子流程调用`,
34
+ );
35
+ const children = new Map<string, WorkflowBundle>();
36
+ for (const name of script.meta.dependencies ?? []) {
37
+ const child = scripts.get(name);
38
+ if (!child)
39
+ throw new Error(
40
+ `依赖工作流 ${name} 不可用:${discovered.failures.find((f) => f.name === name)?.errors.join('; ') ?? '未找到'}`,
41
+ );
42
+ children.set(name, await visit(child, [...ancestors, script.name]));
43
+ }
44
+ const own = await workflowFingerprint(
45
+ script.source,
46
+ script.dir,
47
+ script.meta.packages ?? [],
48
+ );
49
+ // Keep legacy leaf fingerprints, avoiding unrelated invalidations.
50
+ const hash = children.size
51
+ ? fingerprint('workflow-tree-v1', {
52
+ own,
53
+ children: [...children].map(([name, b]) => [name, b.hash]),
54
+ })
55
+ : own;
56
+ return { script, hash, children };
57
+ }
58
+ return visit(root, []);
59
+ }
@@ -0,0 +1,118 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { createRequire } from 'node:module';
3
+ import { readFile, readdir, lstat } from 'node:fs/promises';
4
+ import { dirname, join, relative, resolve, sep } from 'node:path';
5
+ import { pathContains } from '../../../src/plugin-sdk.js';
6
+ import { moduleImports, packageName, resolveRelativeModule } from './moduleResolution.js';
7
+ /**
8
+ * 宿主引擎自身的 npm 包名(`package.json::name`)。硬编码、人工同步,**不**在
9
+ * 这里动态读 `package.json`:这个文件会被绿色版 `bun --compile` 编译进单文件
10
+ * exe,届时 `import.meta.url` 变成虚拟路径——用相对路径去定位磁盘上的
11
+ * `package.json` 会复现 CLAUDE.md 反复警告过的那类绿色版地雷。改包名时要与
12
+ * `scriptGuard.mjs::HOST_PACKAGE_NAME` 一起改。
13
+ */
14
+ const HOST_PACKAGE_NAME = 'minimal-agent';
15
+ async function packageVersion(entry, name) {
16
+ let cursor = dirname(entry);
17
+ for (;;) {
18
+ const manifest = join(cursor, 'package.json');
19
+ try {
20
+ const value = JSON.parse(await readFile(manifest, 'utf8'));
21
+ if (value.name === name && value.version)
22
+ return value.version;
23
+ }
24
+ catch {
25
+ // continue upwards
26
+ }
27
+ const parent = dirname(cursor);
28
+ if (parent === cursor)
29
+ break;
30
+ cursor = parent;
31
+ }
32
+ return 'unknown';
33
+ }
34
+ /** Fingerprint executable ESM graph, prompts/assets, and declared package versions. */
35
+ export async function workflowFingerprint(source, dir, packages = []) {
36
+ const hash = createHash('sha256').update('workflow-bundle-v2\0');
37
+ const entry = join(dir, 'workflow.mjs');
38
+ const seen = new Set();
39
+ const importedPackages = new Set();
40
+ async function addModule(path, knownSource) {
41
+ const absolute = resolve(path);
42
+ if (!pathContains(dir, absolute)) {
43
+ throw new Error(`工作流相对模块越出工作流目录:${absolute}`);
44
+ }
45
+ if (seen.has(absolute))
46
+ return;
47
+ seen.add(absolute);
48
+ const text = knownSource ?? (await readFile(absolute, 'utf8'));
49
+ const name = relative(dir, absolute).split(sep).join('/');
50
+ hash.update(JSON.stringify(['module', name, Buffer.byteLength(text)])).update(text);
51
+ for (const specifier of moduleImports(text)) {
52
+ if (specifier.startsWith('.')) {
53
+ await addModule(await resolveRelativeModule(absolute, specifier));
54
+ }
55
+ else if (specifier.startsWith('node:')) {
56
+ continue;
57
+ }
58
+ else if (specifier.startsWith('/') || specifier.startsWith('file:')) {
59
+ throw new Error(`工作流 ESM import 不得使用绝对路径:${specifier}`);
60
+ }
61
+ else if (packageName(specifier) === HOST_PACKAGE_NAME) {
62
+ // 第二道闸,对齐 scriptGuard.mjs 的同名检查:包自引用 +
63
+ // package.json::exports 的 "./src/*"/"./plugins/*" 通配符会让
64
+ // `minimal-agent/src/xxx` 解析到真实内核文件,完全绕开 wf 分组能力
65
+ // 对象。声明进 meta.packages 也无法绕过这条——即使调用顺序以后变了、
66
+ // discovery.ts 没能先跑 scriptGuard 校验,这里仍然拦得住。
67
+ throw new Error(`工作流禁止 import 宿主引擎自身(${specifier}):一切对内核的访问必须经 wf 分组能力对象。`);
68
+ }
69
+ else {
70
+ importedPackages.add(packageName(specifier));
71
+ }
72
+ }
73
+ }
74
+ await addModule(entry, source);
75
+ async function visit(relativeDir) {
76
+ let entries;
77
+ try {
78
+ if ((await lstat(join(dir, relativeDir))).isSymbolicLink())
79
+ throw new Error(`工作流随包资源不能是符号链接:${relativeDir}`);
80
+ entries = await readdir(join(dir, relativeDir), { withFileTypes: true });
81
+ }
82
+ catch (error) {
83
+ if (error.code === 'ENOENT')
84
+ return;
85
+ throw error;
86
+ }
87
+ for (const item of entries.sort((a, b) => a.name.localeCompare(b.name))) {
88
+ const name = `${relativeDir}/${item.name}`;
89
+ if (item.isSymbolicLink())
90
+ throw new Error(`工作流随包资源不能是符号链接:${name}`);
91
+ if (item.isDirectory())
92
+ await visit(name);
93
+ else if (item.isFile() && !seen.has(resolve(dir, name))) {
94
+ const bytes = await readFile(join(dir, name));
95
+ hash.update(JSON.stringify(['resource', name, bytes.length])).update(bytes);
96
+ }
97
+ }
98
+ }
99
+ for (const folder of ['prompts', 'scripts', 'assets'])
100
+ await visit(folder);
101
+ const require = createRequire(entry);
102
+ for (const name of importedPackages) {
103
+ if (!packages.includes(name)) {
104
+ throw new Error(`运行时包 ${name} 必须声明在 meta.packages 中。`);
105
+ }
106
+ }
107
+ for (const name of [...packages].sort()) {
108
+ let resolved;
109
+ try {
110
+ resolved = require.resolve(name);
111
+ }
112
+ catch (error) {
113
+ throw new Error(`无法解析 meta.packages 中的 ${name}:${error instanceof Error ? error.message : String(error)}`);
114
+ }
115
+ hash.update(JSON.stringify(['package', name, await packageVersion(resolved, name)]));
116
+ }
117
+ return hash.digest('hex').slice(0, 16);
118
+ }
@@ -0,0 +1,122 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { createRequire } from 'node:module';
3
+ import { readFile, readdir, lstat } from 'node:fs/promises';
4
+ import type { Dirent } from 'node:fs';
5
+ import { dirname, join, relative, resolve, sep } from 'node:path';
6
+
7
+ import { pathContains } from '../../../src/plugin-sdk.js';
8
+ import { moduleImports, packageName, resolveRelativeModule } from './moduleResolution.js';
9
+
10
+ /**
11
+ * 宿主引擎自身的 npm 包名(`package.json::name`)。硬编码、人工同步,**不**在
12
+ * 这里动态读 `package.json`:这个文件会被绿色版 `bun --compile` 编译进单文件
13
+ * exe,届时 `import.meta.url` 变成虚拟路径——用相对路径去定位磁盘上的
14
+ * `package.json` 会复现 CLAUDE.md 反复警告过的那类绿色版地雷。改包名时要与
15
+ * `scriptGuard.mjs::HOST_PACKAGE_NAME` 一起改。
16
+ */
17
+ const HOST_PACKAGE_NAME = 'minimal-agent';
18
+
19
+ async function packageVersion(entry: string, name: string): Promise<string> {
20
+ let cursor = dirname(entry);
21
+ for (;;) {
22
+ const manifest = join(cursor, 'package.json');
23
+ try {
24
+ const value = JSON.parse(await readFile(manifest, 'utf8')) as {
25
+ name?: string;
26
+ version?: string;
27
+ };
28
+ if (value.name === name && value.version) return value.version;
29
+ } catch {
30
+ // continue upwards
31
+ }
32
+ const parent = dirname(cursor);
33
+ if (parent === cursor) break;
34
+ cursor = parent;
35
+ }
36
+ return 'unknown';
37
+ }
38
+
39
+ /** Fingerprint executable ESM graph, prompts/assets, and declared package versions. */
40
+ export async function workflowFingerprint(
41
+ source: string,
42
+ dir: string,
43
+ packages: string[] = [],
44
+ ): Promise<string> {
45
+ const hash = createHash('sha256').update('workflow-bundle-v2\0');
46
+ const entry = join(dir, 'workflow.mjs');
47
+ const seen = new Set<string>();
48
+ const importedPackages = new Set<string>();
49
+
50
+ async function addModule(path: string, knownSource?: string): Promise<void> {
51
+ const absolute = resolve(path);
52
+ if (!pathContains(dir, absolute)) {
53
+ throw new Error(`工作流相对模块越出工作流目录:${absolute}`);
54
+ }
55
+ if (seen.has(absolute)) return;
56
+ seen.add(absolute);
57
+ const text = knownSource ?? (await readFile(absolute, 'utf8'));
58
+ const name = relative(dir, absolute).split(sep).join('/');
59
+ hash.update(JSON.stringify(['module', name, Buffer.byteLength(text)])).update(text);
60
+ for (const specifier of moduleImports(text)) {
61
+ if (specifier.startsWith('.')) {
62
+ await addModule(await resolveRelativeModule(absolute, specifier));
63
+ } else if (specifier.startsWith('node:')) {
64
+ continue;
65
+ } else if (specifier.startsWith('/') || specifier.startsWith('file:')) {
66
+ throw new Error(`工作流 ESM import 不得使用绝对路径:${specifier}`);
67
+ } else if (packageName(specifier) === HOST_PACKAGE_NAME) {
68
+ // 第二道闸,对齐 scriptGuard.mjs 的同名检查:包自引用 +
69
+ // package.json::exports 的 "./src/*"/"./plugins/*" 通配符会让
70
+ // `minimal-agent/src/xxx` 解析到真实内核文件,完全绕开 wf 分组能力
71
+ // 对象。声明进 meta.packages 也无法绕过这条——即使调用顺序以后变了、
72
+ // discovery.ts 没能先跑 scriptGuard 校验,这里仍然拦得住。
73
+ throw new Error(
74
+ `工作流禁止 import 宿主引擎自身(${specifier}):一切对内核的访问必须经 wf 分组能力对象。`,
75
+ );
76
+ } else {
77
+ importedPackages.add(packageName(specifier));
78
+ }
79
+ }
80
+ }
81
+
82
+ await addModule(entry, source);
83
+
84
+ async function visit(relativeDir: string): Promise<void> {
85
+ let entries: Dirent[];
86
+ try {
87
+ if ((await lstat(join(dir, relativeDir))).isSymbolicLink())
88
+ throw new Error(`工作流随包资源不能是符号链接:${relativeDir}`);
89
+ entries = await readdir(join(dir, relativeDir), { withFileTypes: true });
90
+ } catch (error) {
91
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;
92
+ throw error;
93
+ }
94
+ for (const item of entries.sort((a, b) => a.name.localeCompare(b.name))) {
95
+ const name = `${relativeDir}/${item.name}`;
96
+ if (item.isSymbolicLink()) throw new Error(`工作流随包资源不能是符号链接:${name}`);
97
+ if (item.isDirectory()) await visit(name);
98
+ else if (item.isFile() && !seen.has(resolve(dir, name))) {
99
+ const bytes = await readFile(join(dir, name));
100
+ hash.update(JSON.stringify(['resource', name, bytes.length])).update(bytes);
101
+ }
102
+ }
103
+ }
104
+ for (const folder of ['prompts', 'scripts', 'assets']) await visit(folder);
105
+
106
+ const require = createRequire(entry);
107
+ for (const name of importedPackages) {
108
+ if (!packages.includes(name)) {
109
+ throw new Error(`运行时包 ${name} 必须声明在 meta.packages 中。`);
110
+ }
111
+ }
112
+ for (const name of [...packages].sort()) {
113
+ let resolved: string;
114
+ try {
115
+ resolved = require.resolve(name);
116
+ } catch (error) {
117
+ throw new Error(`无法解析 meta.packages 中的 ${name}:${error instanceof Error ? error.message : String(error)}`);
118
+ }
119
+ hash.update(JSON.stringify(['package', name, await packageVersion(resolved, name)]));
120
+ }
121
+ return hash.digest('hex').slice(0, 16);
122
+ }