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,162 @@
1
+ /**
2
+ * ============================================================
3
+ * plugins/workflow-runner/src/jsonSchema.ts —— JSON Schema 子集校验
4
+ * ------------------------------------------------------------
5
+ * 为什么手写而不是引 ajv:
6
+ * ① 工作流的结构化输出契约采用可序列化的 JSON Schema 子集,便于参与 journal
7
+ * 指纹并跨 provider 使用。
8
+ * ② 校验结果要**回喂给模型做修复**,所以错误消息比规范覆盖度重要得多 ——
9
+ * 「`branches[2].score` 应为 number,实际是 string」比一句
10
+ * `must be number` 有用,而通用库的默认文案偏向后者。
11
+ * ③ 项目一贯取向:能用基本类型说清就不引第三方(见 CLAUDE.md 设计原则)。
12
+ *
13
+ * 支持的关键字:type(含数组联合)/ properties / required / items /
14
+ * enum / additionalProperties:false / minItems / maxItems / minimum / maximum /
15
+ * nullable。**不支持**的关键字一律**忽略**(宽松),不报错 —— 校验器的职责是
16
+ * 挡住畸形输出,不是当规范警察;误伤一个合法产出的代价比放过一个边角约束大。
17
+ * ============================================================
18
+ */
19
+
20
+ export interface JsonSchema {
21
+ type?: string | string[];
22
+ properties?: Record<string, JsonSchema>;
23
+ required?: string[];
24
+ items?: JsonSchema;
25
+ enum?: unknown[];
26
+ additionalProperties?: boolean | JsonSchema;
27
+ minItems?: number;
28
+ maxItems?: number;
29
+ minimum?: number;
30
+ maximum?: number;
31
+ nullable?: boolean;
32
+ [k: string]: unknown;
33
+ }
34
+
35
+ /** 校验失败的具体位置与原因(要拿去喂模型,所以必须是人话 + 路径)。 */
36
+ export interface SchemaViolation {
37
+ path: string;
38
+ message: string;
39
+ }
40
+
41
+ function typeOf(v: unknown): string {
42
+ if (v === null) return 'null';
43
+ if (Array.isArray(v)) return 'array';
44
+ if (Number.isInteger(v)) return 'integer';
45
+ return typeof v;
46
+ }
47
+
48
+ /** `integer` 也满足 `number`;其余按 typeof 对齐。 */
49
+ function typeMatches(want: string, v: unknown): boolean {
50
+ const actual = typeOf(v);
51
+ if (want === actual) return true;
52
+ if (want === 'number') return actual === 'integer' || actual === 'number';
53
+ if (want === 'integer') return actual === 'integer';
54
+ return false;
55
+ }
56
+
57
+ function describe(v: unknown): string {
58
+ const t = typeOf(v);
59
+ if (t === 'string') return `string(${JSON.stringify(String(v)).slice(0, 40)})`;
60
+ if (t === 'array') return `array(长度 ${(v as unknown[]).length})`;
61
+ if (t === 'object') return `object(键 ${Object.keys(v as object).join('/')})`;
62
+ return `${t}(${String(v)})`;
63
+ }
64
+
65
+ function walk(
66
+ value: unknown,
67
+ schema: JsonSchema,
68
+ path: string,
69
+ out: SchemaViolation[],
70
+ ): void {
71
+ if (!schema || typeof schema !== 'object') return;
72
+
73
+ if (value === null && schema.nullable === true) return;
74
+
75
+ if (schema.enum && Array.isArray(schema.enum)) {
76
+ if (!schema.enum.some((e) => e === value)) {
77
+ out.push({
78
+ path,
79
+ message: `应为 [${schema.enum.map((e) => JSON.stringify(e)).join(', ')}] 之一,实际是 ${describe(value)}`,
80
+ });
81
+ return;
82
+ }
83
+ }
84
+
85
+ if (schema.type !== undefined) {
86
+ const wants = Array.isArray(schema.type) ? schema.type : [schema.type];
87
+ if (!wants.some((w) => typeMatches(w, value))) {
88
+ out.push({
89
+ path,
90
+ message: `应为 ${wants.join(' 或 ')},实际是 ${describe(value)}`,
91
+ });
92
+ return; // 类型都不对,再查下去只会刷屏
93
+ }
94
+ }
95
+
96
+ const t = typeOf(value);
97
+
98
+ if (t === 'object') {
99
+ const obj = value as Record<string, unknown>;
100
+ for (const key of schema.required ?? []) {
101
+ if (!(key in obj)) {
102
+ out.push({ path: path ? `${path}.${key}` : key, message: '缺少必填字段' });
103
+ }
104
+ }
105
+ if (schema.properties) {
106
+ for (const [key, sub] of Object.entries(schema.properties)) {
107
+ if (key in obj) walk(obj[key], sub, path ? `${path}.${key}` : key, out);
108
+ }
109
+ if (schema.additionalProperties === false) {
110
+ for (const key of Object.keys(obj)) {
111
+ if (!(key in schema.properties)) {
112
+ out.push({
113
+ path: path ? `${path}.${key}` : key,
114
+ message: '不允许的额外字段',
115
+ });
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+ if (t === 'array') {
123
+ const arr = value as unknown[];
124
+ if (typeof schema.minItems === 'number' && arr.length < schema.minItems) {
125
+ out.push({ path, message: `至少要 ${schema.minItems} 项,实际 ${arr.length} 项` });
126
+ }
127
+ if (typeof schema.maxItems === 'number' && arr.length > schema.maxItems) {
128
+ out.push({ path, message: `最多 ${schema.maxItems} 项,实际 ${arr.length} 项` });
129
+ }
130
+ if (schema.items) {
131
+ arr.forEach((el, i) => walk(el, schema.items!, `${path}[${i}]`, out));
132
+ }
133
+ }
134
+
135
+ if (t === 'number' || t === 'integer') {
136
+ const n = value as number;
137
+ if (typeof schema.minimum === 'number' && n < schema.minimum) {
138
+ out.push({ path, message: `不得小于 ${schema.minimum},实际 ${n}` });
139
+ }
140
+ if (typeof schema.maximum === 'number' && n > schema.maximum) {
141
+ out.push({ path, message: `不得大于 ${schema.maximum},实际 ${n}` });
142
+ }
143
+ }
144
+ }
145
+
146
+ /** 校验一个值。返回空数组 = 通过。 */
147
+ export function validateAgainstSchema(
148
+ value: unknown,
149
+ schema: JsonSchema,
150
+ ): SchemaViolation[] {
151
+ const out: SchemaViolation[] = [];
152
+ walk(value, schema, '', out);
153
+ return out;
154
+ }
155
+
156
+ /** 把违规列表渲染成给**模型**看的修复指令(不是给人看的报错)。 */
157
+ export function renderViolations(violations: SchemaViolation[]): string {
158
+ return violations
159
+ .slice(0, 20)
160
+ .map((v) => ` · ${v.path || '(根)'}:${v.message}`)
161
+ .join('\n');
162
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * ============================================================
3
+ * plugins/workflow-runner/src/moduleResolution.ts —— ESM 依赖图解析的唯一实现
4
+ * ------------------------------------------------------------
5
+ * `workflowFingerprint.ts`(指纹计算)与 `sandbox.ts`(实际执行)此前各自独立
6
+ * 实现了同一组"扫 import/解析相对模块/取裸包名"逻辑,且已经漂移出行为分歧
7
+ * (符号链接策略、`.json` 候选扩展名)。指纹计算总是先于执行
8
+ * (见 `workflowDependencies.ts::resolveWorkflowBundle`),所以漂移目前只表现
9
+ * 成"先炸在指纹这一步"而不是安全漏洞,但仍是两份本该一致的判断各自演化。
10
+ * 这里统一成一份,两处都改成从这里导入。
11
+ *
12
+ * `scriptGuard.mjs` 不从这里导入——它必须保持零依赖纯 `.mjs`(同时被 TS 侧
13
+ * `import` 和 `skills/workflow-creator/scripts/validate.mjs` 裸 `node` spawn),
14
+ * 多一个必须原样发布的 `.mjs` 文件会重演 CLAUDE.md 里
15
+ * "package.json::files 是逐后缀白名单"那类漏发布事故的风险面。它自己那份小小的
16
+ * `STATIC_IMPORT`/`packageName` 保留原样,人工与本文件保持同步。
17
+ * ============================================================
18
+ */
19
+ import { lstat } from 'node:fs/promises';
20
+ import { dirname, extname, join, resolve } from 'node:path';
21
+ /**
22
+ * 匹配静态 `import`/`export ... from '...'` 的说明符。三个捕获组
23
+ * (前缀/说明符/后缀)让 `sandbox.ts` 能就地 `.replace()` 改写裸包名为 file URL;
24
+ * `moduleImports()` 只取第二组即可。
25
+ */
26
+ export const STATIC_IMPORT = /((?:^|[;\n])\s*(?:import|export)\s+(?:[^'";]*?\s+from\s+)?['"])([^'"]+)(['"])/gm;
27
+ /** 从源码里抽出全部静态 import/export 说明符。 */
28
+ export function moduleImports(source) {
29
+ return [...source.matchAll(STATIC_IMPORT)].map((match) => match[2]);
30
+ }
31
+ /** 裸导入说明符 → 包名(`@scope/pkg/sub` → `@scope/pkg`,`pkg/sub` → `pkg`)。 */
32
+ export function packageName(specifier) {
33
+ return specifier.startsWith('@')
34
+ ? specifier.split('/').slice(0, 2).join('/')
35
+ : specifier.split('/')[0];
36
+ }
37
+ /**
38
+ * 把一个相对 import 说明符解析成真实文件路径。
39
+ *
40
+ * **拒绝符号链接**(用 `lstat` 而不是 `stat`)——采纳 `workflowFingerprint.ts`
41
+ * 对随包资源文件本来就有的安全立场;`sandbox.ts` 此前用 `stat`(跟随符号链接)
42
+ * 是漂移,不是有意选择,收紧它是严格向下兼容。
43
+ *
44
+ * **候选扩展名不含 `.json`**——不带扩展名的相对导入解析到 `.json` 在 Node 原生
45
+ * ESM 下本来就不合法(没有 import assertion 语法写不出这种导入),全部 15 个
46
+ * 真实工作流也确认没有依赖这个候选项,去掉是安全的。显式写 `./x.json` 走
47
+ * `sandbox.ts::copyModule` 里单独的 `extname === '.json'` 分支,与这里正交。
48
+ */
49
+ export async function resolveRelativeModule(from, specifier) {
50
+ const base = resolve(dirname(from), specifier);
51
+ const candidates = extname(base)
52
+ ? [base]
53
+ : [base, `${base}.mjs`, `${base}.js`, join(base, 'index.mjs'), join(base, 'index.js')];
54
+ for (const candidate of candidates) {
55
+ try {
56
+ if ((await lstat(candidate)).isFile())
57
+ return candidate;
58
+ }
59
+ catch {
60
+ // 试下一个候选
61
+ }
62
+ }
63
+ throw new Error(`无法解析工作流相对模块:${specifier}(来自 ${from})`);
64
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * ============================================================
3
+ * plugins/workflow-runner/src/moduleResolution.ts —— ESM 依赖图解析的唯一实现
4
+ * ------------------------------------------------------------
5
+ * `workflowFingerprint.ts`(指纹计算)与 `sandbox.ts`(实际执行)此前各自独立
6
+ * 实现了同一组"扫 import/解析相对模块/取裸包名"逻辑,且已经漂移出行为分歧
7
+ * (符号链接策略、`.json` 候选扩展名)。指纹计算总是先于执行
8
+ * (见 `workflowDependencies.ts::resolveWorkflowBundle`),所以漂移目前只表现
9
+ * 成"先炸在指纹这一步"而不是安全漏洞,但仍是两份本该一致的判断各自演化。
10
+ * 这里统一成一份,两处都改成从这里导入。
11
+ *
12
+ * `scriptGuard.mjs` 不从这里导入——它必须保持零依赖纯 `.mjs`(同时被 TS 侧
13
+ * `import` 和 `skills/workflow-creator/scripts/validate.mjs` 裸 `node` spawn),
14
+ * 多一个必须原样发布的 `.mjs` 文件会重演 CLAUDE.md 里
15
+ * "package.json::files 是逐后缀白名单"那类漏发布事故的风险面。它自己那份小小的
16
+ * `STATIC_IMPORT`/`packageName` 保留原样,人工与本文件保持同步。
17
+ * ============================================================
18
+ */
19
+
20
+ import { lstat } from 'node:fs/promises';
21
+ import { dirname, extname, join, resolve } from 'node:path';
22
+
23
+ /**
24
+ * 匹配静态 `import`/`export ... from '...'` 的说明符。三个捕获组
25
+ * (前缀/说明符/后缀)让 `sandbox.ts` 能就地 `.replace()` 改写裸包名为 file URL;
26
+ * `moduleImports()` 只取第二组即可。
27
+ */
28
+ export const STATIC_IMPORT =
29
+ /((?:^|[;\n])\s*(?:import|export)\s+(?:[^'";]*?\s+from\s+)?['"])([^'"]+)(['"])/gm;
30
+
31
+ /** 从源码里抽出全部静态 import/export 说明符。 */
32
+ export function moduleImports(source: string): string[] {
33
+ return [...source.matchAll(STATIC_IMPORT)].map((match) => match[2]!);
34
+ }
35
+
36
+ /** 裸导入说明符 → 包名(`@scope/pkg/sub` → `@scope/pkg`,`pkg/sub` → `pkg`)。 */
37
+ export function packageName(specifier: string): string {
38
+ return specifier.startsWith('@')
39
+ ? specifier.split('/').slice(0, 2).join('/')
40
+ : specifier.split('/')[0]!;
41
+ }
42
+
43
+ /**
44
+ * 把一个相对 import 说明符解析成真实文件路径。
45
+ *
46
+ * **拒绝符号链接**(用 `lstat` 而不是 `stat`)——采纳 `workflowFingerprint.ts`
47
+ * 对随包资源文件本来就有的安全立场;`sandbox.ts` 此前用 `stat`(跟随符号链接)
48
+ * 是漂移,不是有意选择,收紧它是严格向下兼容。
49
+ *
50
+ * **候选扩展名不含 `.json`**——不带扩展名的相对导入解析到 `.json` 在 Node 原生
51
+ * ESM 下本来就不合法(没有 import assertion 语法写不出这种导入),全部 15 个
52
+ * 真实工作流也确认没有依赖这个候选项,去掉是安全的。显式写 `./x.json` 走
53
+ * `sandbox.ts::copyModule` 里单独的 `extname === '.json'` 分支,与这里正交。
54
+ */
55
+ export async function resolveRelativeModule(
56
+ from: string,
57
+ specifier: string,
58
+ ): Promise<string> {
59
+ const base = resolve(dirname(from), specifier);
60
+ const candidates = extname(base)
61
+ ? [base]
62
+ : [base, `${base}.mjs`, `${base}.js`, join(base, 'index.mjs'), join(base, 'index.js')];
63
+ for (const candidate of candidates) {
64
+ try {
65
+ if ((await lstat(candidate)).isFile()) return candidate;
66
+ } catch {
67
+ // 试下一个候选
68
+ }
69
+ }
70
+ throw new Error(`无法解析工作流相对模块:${specifier}(来自 ${from})`);
71
+ }
@@ -0,0 +1,220 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { createReadStream } from 'node:fs';
3
+ import { chmod, copyFile, mkdir, readdir, readlink, stat, } from 'node:fs/promises';
4
+ import { homedir } from 'node:os';
5
+ import { basename, join, resolve } from 'node:path';
6
+ import { agentStateDir } from '../../../src/context/agentHome.js';
7
+ const MIME_BY_EXT = {
8
+ '.jpg': 'image/jpeg',
9
+ '.jpeg': 'image/jpeg',
10
+ '.png': 'image/png',
11
+ '.webp': 'image/webp',
12
+ '.heic': 'image/heic',
13
+ '.heif': 'image/heif',
14
+ '.gif': 'image/gif',
15
+ '.bmp': 'image/bmp',
16
+ '.svg': 'image/svg+xml',
17
+ '.pdf': 'application/pdf',
18
+ '.doc': 'application/msword',
19
+ '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
20
+ '.xls': 'application/vnd.ms-excel',
21
+ '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
22
+ '.ppt': 'application/vnd.ms-powerpoint',
23
+ '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
24
+ '.zip': 'application/zip',
25
+ '.txt': 'text/plain',
26
+ '.md': 'text/markdown',
27
+ '.csv': 'text/csv',
28
+ '.json': 'application/json',
29
+ '.mp3': 'audio/mpeg',
30
+ '.wav': 'audio/wav',
31
+ '.m4a': 'audio/mp4',
32
+ '.mp4': 'video/mp4',
33
+ '.mov': 'video/quicktime',
34
+ '.mkv': 'video/x-matroska',
35
+ };
36
+ function mimeForPath(path) {
37
+ const match = /\.[^.]+$/.exec(path.toLowerCase());
38
+ return (match && MIME_BY_EXT[match[0]]) || 'application/octet-stream';
39
+ }
40
+ function mimeMatches(mime, accepted) {
41
+ const a = accepted.toLowerCase();
42
+ return a.endsWith('/*')
43
+ ? mime.toLowerCase().startsWith(a.slice(0, -1))
44
+ : mime.toLowerCase() === a;
45
+ }
46
+ function compatible(resource, def) {
47
+ if (resource.kind === 'directory' && def.allowDirectory === false)
48
+ return false;
49
+ if (resource.kind === 'file' && def.allowFile === false)
50
+ return false;
51
+ if (def.accepts?.length &&
52
+ resource.kind === 'file' &&
53
+ !def.accepts.some((a) => {
54
+ const accepted = a.toLowerCase();
55
+ const ext = resource.name.toLowerCase().match(/\.[^.]+$/)?.[0];
56
+ return mimeMatches(resource.mime, accepted) || accepted === ext;
57
+ }))
58
+ return false;
59
+ return true;
60
+ }
61
+ function resourceId(path) {
62
+ return `path-${createHash('sha256').update(resolve(path)).digest('hex').slice(0, 24)}`;
63
+ }
64
+ async function contentHash(path) {
65
+ const hash = createHash('sha256');
66
+ for await (const chunk of createReadStream(path))
67
+ hash.update(chunk);
68
+ return hash.digest('hex');
69
+ }
70
+ async function directoryContentHash(root) {
71
+ const hash = createHash('sha256');
72
+ const visit = async (dir, prefix) => {
73
+ const entries = await readdir(dir, { withFileTypes: true });
74
+ entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
75
+ for (const entry of entries) {
76
+ const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
77
+ const fullPath = join(dir, entry.name);
78
+ if (entry.isDirectory()) {
79
+ hash.update(`d\0${relative}\0`);
80
+ await visit(fullPath, relative);
81
+ }
82
+ else if (entry.isFile()) {
83
+ hash.update(`f\0${relative}\0${await contentHash(fullPath)}\0`);
84
+ }
85
+ else if (entry.isSymbolicLink()) {
86
+ hash.update(`l\0${relative}\0${await readlink(fullPath)}\0`);
87
+ }
88
+ else {
89
+ // Keep uncommon filesystem entries deterministic without opening them.
90
+ const info = await stat(fullPath);
91
+ hash.update(`o\0${relative}\0${info.mode}\0${info.size}\0`);
92
+ }
93
+ }
94
+ };
95
+ await visit(root, '');
96
+ return hash.digest('hex');
97
+ }
98
+ function safeSegment(value) {
99
+ return value.replace(/[^a-zA-Z0-9._-]/g, '_').slice(0, 120) || 'default';
100
+ }
101
+ function safeFileName(value, fallback) {
102
+ return ([...basename(value)]
103
+ .map((ch) => ch.codePointAt(0) < 32 || '<>:"|?*/\\'.includes(ch) ? '_' : ch)
104
+ .join('')
105
+ .slice(0, 180) || fallback);
106
+ }
107
+ function stagedFilePath(dir, resource, index) {
108
+ const safe = safeFileName(resource.name, `input-${index + 1}`);
109
+ return join(dir, `${String(index + 1).padStart(3, '0')}-${safe}`);
110
+ }
111
+ function resolveInputPath(value, cwd) {
112
+ if (value === '~')
113
+ return homedir();
114
+ if (value.startsWith('~/') || value.startsWith('~\\')) {
115
+ return resolve(homedir(), value.slice(2));
116
+ }
117
+ return resolve(cwd, value);
118
+ }
119
+ async function resourceFromPath(value, cwd) {
120
+ const localPath = resolveInputPath(value, cwd);
121
+ const info = await stat(localPath);
122
+ const kind = info.isDirectory() ? 'directory' : 'file';
123
+ const sha256 = kind === 'file'
124
+ ? await contentHash(localPath)
125
+ : await directoryContentHash(localPath);
126
+ return {
127
+ id: resourceId(localPath),
128
+ origin: 'path',
129
+ name: basename(localPath),
130
+ mime: kind === 'directory' ? 'inode/directory' : mimeForPath(localPath),
131
+ size: kind === 'file' ? info.size : undefined,
132
+ sha256,
133
+ localPath,
134
+ kind,
135
+ };
136
+ }
137
+ /** Stage attachment files in a deterministic, private directory for legacy path APIs. */
138
+ export async function materializeResources(workflowName, sessionId, inputName, resources) {
139
+ const fingerprint = createHash('sha256')
140
+ .update(resources
141
+ .map((r) => `${r.sha256 ?? r.id}:${r.name}:${r.size ?? ''}`)
142
+ .join('|'))
143
+ .digest('hex')
144
+ .slice(0, 24);
145
+ const dir = join(agentStateDir(), 'workflow-inputs', safeSegment(workflowName), safeSegment(sessionId), safeSegment(inputName), fingerprint);
146
+ await mkdir(dir, { recursive: true, mode: 0o700 });
147
+ for (let i = 0; i < resources.length; i++) {
148
+ const source = resources[i];
149
+ if (source.kind !== 'file')
150
+ continue;
151
+ const target = stagedFilePath(dir, source, i);
152
+ try {
153
+ await stat(target);
154
+ continue;
155
+ }
156
+ catch {
157
+ // First materialization for this content fingerprint.
158
+ }
159
+ await copyFile(source.localPath, target);
160
+ await chmod(target, 0o400);
161
+ }
162
+ return dir;
163
+ }
164
+ /** Bind explicit paths first, then compatible current-turn attachments. */
165
+ export async function bindResourceInputs(opts) {
166
+ const inputs = { ...opts.rawInputs };
167
+ const resourceMap = {};
168
+ const resourceIdentity = [];
169
+ const warnings = [];
170
+ for (const def of opts.defs ?? []) {
171
+ if (def.type !== 'resource')
172
+ continue;
173
+ const explicit = opts.rawInputs[def.name];
174
+ if (explicit?.trim()) {
175
+ const resource = await resourceFromPath(explicit, opts.cwd ?? process.cwd());
176
+ const stageAsDirectory = def.materialize === 'directory' && resource.kind === 'file';
177
+ const accepted = stageAsDirectory
178
+ ? compatible(resource, { ...def, allowFile: true })
179
+ : compatible(resource, def);
180
+ if (!accepted)
181
+ throw new Error(`input ${def.name} 的路径类型不受支持:${explicit}`);
182
+ resourceMap[def.name] = [resource];
183
+ inputs[def.name] = stageAsDirectory
184
+ ? await materializeResources(opts.workflowName, opts.sessionId, def.name, [resource])
185
+ : resource.localPath;
186
+ resourceIdentity.push(def.identity === 'reference'
187
+ ? `${def.name}:${resource.id}`
188
+ : `${def.name}:${resource.sha256 ?? resource.id}`);
189
+ continue;
190
+ }
191
+ if (!def.attachmentFallback)
192
+ continue;
193
+ const matches = (opts.attachments ?? []).filter((resource) => def.materialize === 'directory' && resource.kind === 'file'
194
+ ? compatible(resource, { ...def, allowFile: true })
195
+ : compatible(resource, def));
196
+ if (!matches.length)
197
+ continue;
198
+ if (def.maxItems !== undefined && matches.length > def.maxItems) {
199
+ throw new Error(`input ${def.name} 最多允许 ${def.maxItems} 个附件,但本轮有 ${matches.length} 个兼容附件;请减少附件或调整 maxItems`);
200
+ }
201
+ if (def.multiple !== true && matches.length > 1) {
202
+ throw new Error(`input ${def.name} 只允许一个附件,但本轮有 ${matches.length} 个兼容附件;请使用 --input ${def.name}=路径 或声明 multiple: true`);
203
+ }
204
+ resourceMap[def.name] = matches;
205
+ for (const resource of matches) {
206
+ resourceIdentity.push(def.identity === 'reference'
207
+ ? `${def.name}:${resource.id}`
208
+ : `${def.name}:${resource.sha256 ?? resource.id}`);
209
+ }
210
+ const staged = await materializeResources(opts.workflowName, opts.sessionId, def.name, matches);
211
+ // Host attachment paths can be temporary (notably team deliveries), so
212
+ // even a single file must use the stable Runner copy for journal resume.
213
+ inputs[def.name] =
214
+ matches.length === 1 && def.materialize !== 'directory'
215
+ ? stagedFilePath(staged, matches[0], 0)
216
+ : staged;
217
+ warnings.push(`已将本轮 ${matches.length} 个附件绑定到 input ${def.name}`);
218
+ }
219
+ return { inputs, resourceMap, resourceIdentity, warnings };
220
+ }