minimal-agent 0.13.0 → 0.15.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 (474) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  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 +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  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 +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  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 +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  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 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  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 +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  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/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +536 -0
  103. package/src/advisor/advisorCoordinator.ts +693 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/quickModelSetup.js +12 -1
  108. package/src/cli/quickModelSetup.tsx +15 -3
  109. package/src/cli/streamJson.js +5 -6
  110. package/src/cli/streamJson.ts +8 -4
  111. package/src/cli/wizards/advisorWizard.js +4 -2
  112. package/src/cli/wizards/advisorWizard.tsx +8 -2
  113. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  114. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  115. package/src/cli/wizards/providerPresets.js +18 -8
  116. package/src/cli/wizards/providerPresets.ts +18 -8
  117. package/src/collaboration/taskFlow.js +115 -0
  118. package/src/collaboration/taskFlow.ts +169 -0
  119. package/src/config/configDefaults.js +41 -1
  120. package/src/config/configDefaults.ts +43 -1
  121. package/src/config/configDiagnostics.ts +2 -2
  122. package/src/config/configFile.js +40 -9
  123. package/src/config/configFile.ts +60 -11
  124. package/src/config/configService.js +419 -74
  125. package/src/config/configService.ts +703 -145
  126. package/src/config/numericLimits.js +22 -0
  127. package/src/config/numericLimits.ts +24 -0
  128. package/src/config.js +1 -0
  129. package/src/config.ts +3 -2
  130. package/src/context/budgetPlan.js +1 -1
  131. package/src/context/budgetPlan.ts +1 -1
  132. package/src/context/compact.js +7 -2
  133. package/src/context/compact.ts +9 -2
  134. package/src/context/microCompactLite.js +212 -13
  135. package/src/context/microCompactLite.ts +261 -12
  136. package/src/context/sessionRegistry.js +8 -1
  137. package/src/context/sessionRegistry.ts +18 -5
  138. package/src/context/toolResultArchive.js +72 -0
  139. package/src/context/toolResultArchive.ts +95 -0
  140. package/src/goal/errors.js +8 -0
  141. package/src/goal/errors.ts +18 -0
  142. package/src/goal/goalRuntime.js +344 -0
  143. package/src/goal/goalRuntime.ts +466 -0
  144. package/src/goal/goalStore.js +200 -0
  145. package/src/goal/goalStore.ts +219 -0
  146. package/src/goal/index.js +4 -0
  147. package/src/goal/index.ts +4 -0
  148. package/src/goal/statusMapping.js +71 -0
  149. package/src/goal/statusMapping.ts +95 -0
  150. package/src/goal/types.js +7 -0
  151. package/src/goal/types.ts +179 -0
  152. package/src/goal/workflowController.js +306 -0
  153. package/src/goal/workflowController.ts +360 -0
  154. package/src/harness/evidenceLedger.js +2 -0
  155. package/src/harness/evidenceLedger.ts +1 -0
  156. package/src/harness/stallGuard.js +9 -3
  157. package/src/harness/stallGuard.ts +7 -3
  158. package/src/images/imageResolver.js +161 -0
  159. package/src/images/imageResolver.ts +189 -0
  160. package/src/infra/verification.js +34 -5
  161. package/src/infra/verification.ts +39 -4
  162. package/src/llm/client.js +79 -21
  163. package/src/llm/client.ts +182 -35
  164. package/src/llm/gatewayClient.js +201 -0
  165. package/src/llm/gatewayClient.ts +299 -0
  166. package/src/llm/messageProvenance.js +46 -0
  167. package/src/llm/messageProvenance.ts +58 -0
  168. package/src/llm/modelProvider.js +1 -0
  169. package/src/llm/modelProvider.ts +22 -0
  170. package/src/llm/providers/anthropicFormat.js +108 -1
  171. package/src/llm/providers/anthropicFormat.ts +115 -4
  172. package/src/llm/providers/openaiFormat.js +9 -0
  173. package/src/llm/providers/openaiFormat.ts +12 -3
  174. package/src/loop.js +328 -55
  175. package/src/loop.ts +382 -58
  176. package/src/main.js +4 -1
  177. package/src/main.tsx +4 -1
  178. package/src/managedExecution/index.js +2 -0
  179. package/src/managedExecution/index.ts +2 -0
  180. package/src/managedExecution/registry.js +15 -0
  181. package/src/managedExecution/registry.ts +20 -0
  182. package/src/managedExecution/types.js +1 -0
  183. package/src/managedExecution/types.ts +86 -0
  184. package/src/modelRef.js +9 -0
  185. package/src/modelRef.ts +31 -0
  186. package/src/multimodal.js +14 -28
  187. package/src/multimodal.ts +17 -33
  188. package/src/net/lanDiscovery.js +65 -0
  189. package/src/net/lanDiscovery.ts +82 -0
  190. package/src/plugin-sdk.js +28 -3
  191. package/src/plugin-sdk.ts +39 -6
  192. package/src/plugins/pluginApi.ts +16 -1
  193. package/src/plugins/pluginLoader.js +4 -0
  194. package/src/plugins/pluginLoader.ts +6 -0
  195. package/src/plugins/pluginRunner.js +139 -7
  196. package/src/plugins/pluginRunner.ts +173 -9
  197. package/src/plugins/slashFallback.js +113 -0
  198. package/src/plugins/slashFallback.ts +137 -0
  199. package/src/prompts/policyRegistry.js +12 -32
  200. package/src/prompts/policyRegistry.ts +15 -32
  201. package/src/prompts/promptAssembly.js +103 -12
  202. package/src/prompts/promptAssembly.ts +114 -12
  203. package/src/prompts/skillList.js +21 -3
  204. package/src/prompts/skillList.ts +27 -2
  205. package/src/prompts/stableSystemPrompt.js +18 -0
  206. package/src/prompts/stableSystemPrompt.ts +33 -0
  207. package/src/runtime/agentRuntimeContext.js +8 -2
  208. package/src/runtime/agentRuntimeContext.ts +17 -4
  209. package/src/session/runAgentTurn.js +78 -12
  210. package/src/session/runAgentTurn.ts +105 -23
  211. package/src/session/runTurn.js +10 -9
  212. package/src/session/runTurn.ts +17 -8
  213. package/src/session/sessionState.ts +2 -0
  214. package/src/team/auth.js +186 -0
  215. package/src/team/auth.ts +298 -0
  216. package/src/team/cli.js +105 -0
  217. package/src/team/cli.ts +122 -0
  218. package/src/team/onlineToolContract.js +64 -0
  219. package/src/team/onlineToolContract.ts +109 -0
  220. package/src/team/toolPolicy.js +36 -0
  221. package/src/team/toolPolicy.ts +75 -0
  222. package/src/tools/advisor/advisor.js +115 -50
  223. package/src/tools/advisor/advisor.ts +124 -51
  224. package/src/tools/advisor/advisorDecision.js +71 -0
  225. package/src/tools/advisor/advisorDecision.ts +85 -0
  226. package/src/tools/agent/agent.js +18 -5
  227. package/src/tools/agent/agent.ts +21 -7
  228. package/src/tools/agent/agentControl.js +246 -0
  229. package/src/tools/agent/agentControl.ts +284 -0
  230. package/src/tools/agent/agentTaskService.js +40 -1
  231. package/src/tools/agent/agentTaskService.ts +44 -1
  232. package/src/tools/agent/agentTypes.js +14 -2
  233. package/src/tools/agent/agentTypes.ts +15 -2
  234. package/src/tools/applypatch/applyPatch.js +362 -0
  235. package/src/tools/applypatch/applyPatch.ts +428 -0
  236. package/src/tools/bash/bash.js +22 -15
  237. package/src/tools/bash/bash.ts +23 -17
  238. package/src/tools/capabilities.js +10 -5
  239. package/src/tools/capabilities.ts +10 -5
  240. package/src/tools/computeruse/computerIntent.js +32 -0
  241. package/src/tools/computeruse/computerIntent.ts +46 -0
  242. package/src/tools/computeruse/telemetryLog.js +12 -0
  243. package/src/tools/computeruse/telemetryLog.ts +16 -0
  244. package/src/tools/computeruse/vision/telemetry.js +1 -0
  245. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  246. package/src/tools/effectiveToolSet.js +4 -0
  247. package/src/tools/effectiveToolSet.ts +4 -0
  248. package/src/tools/index.js +21 -2
  249. package/src/tools/index.ts +33 -2
  250. package/src/tools/presentresult/presentresult.js +6 -15
  251. package/src/tools/presentresult/presentresult.ts +6 -15
  252. package/src/tools/read/read.js +62 -9
  253. package/src/tools/read/read.ts +63 -9
  254. package/src/tools/shared/fileUtils.js +1 -2
  255. package/src/tools/shared/fileUtils.ts +1 -2
  256. package/src/tools/shared/toolOutputStore.js +23 -1
  257. package/src/tools/shared/toolOutputStore.ts +22 -1
  258. package/src/tools/skill/skill.js +9 -3
  259. package/src/tools/skill/skill.ts +8 -4
  260. package/src/tools/toolPromptGuides.js +125 -0
  261. package/src/tools/toolPromptGuides.ts +146 -0
  262. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  263. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  264. package/src/tools/webbrowser/browser.js +27 -11
  265. package/src/tools/webbrowser/browser.ts +68 -24
  266. package/src/tools/webbrowser/browserAutomation.js +329 -0
  267. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  268. package/src/tools/webbrowser/browserAxState.js +97 -0
  269. package/src/tools/webbrowser/browserAxState.ts +142 -0
  270. package/src/tools/webbrowser/browserBatch.js +1578 -0
  271. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  272. package/src/tools/webbrowser/browserCdp.js +208 -0
  273. package/src/tools/webbrowser/browserCdp.ts +255 -0
  274. package/src/tools/webbrowser/browserConditions.js +24 -0
  275. package/src/tools/webbrowser/browserConditions.ts +45 -0
  276. package/src/tools/webbrowser/browserContent.js +281 -0
  277. package/src/tools/webbrowser/browserContent.ts +438 -0
  278. package/src/tools/webbrowser/browserControl.js +131 -34
  279. package/src/tools/webbrowser/browserControl.ts +210 -56
  280. package/src/tools/webbrowser/browserDaemon.js +22 -14
  281. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  282. package/src/tools/webbrowser/browserFrames.js +47 -0
  283. package/src/tools/webbrowser/browserFrames.ts +54 -0
  284. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  286. package/src/tools/webbrowser/browserLocator.js +140 -0
  287. package/src/tools/webbrowser/browserLocator.ts +194 -0
  288. package/src/tools/webbrowser/browserOutcome.js +10 -17
  289. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  290. package/src/tools/webbrowser/browserRecovery.js +58 -0
  291. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  292. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  293. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  294. package/src/tools/webbrowser/browserService.js +28 -2
  295. package/src/tools/webbrowser/browserService.ts +49 -9
  296. package/src/tools/webbrowser/browserStream.js +132 -33
  297. package/src/tools/webbrowser/browserStream.ts +224 -50
  298. package/src/tools/webbrowser/browserTabs.js +48 -15
  299. package/src/tools/webbrowser/browserTabs.ts +178 -96
  300. package/src/tools/webbrowser/webbrowser.js +679 -144
  301. package/src/tools/webbrowser/webbrowser.ts +975 -236
  302. package/src/tools/webfetch/preapproved.js +0 -2
  303. package/src/tools/webfetch/preapproved.ts +0 -2
  304. package/src/tools/websearch/websearch.js +129 -8
  305. package/src/tools/websearch/websearch.ts +138 -6
  306. package/src/types.ts +459 -40
  307. package/src/ui/App.js +377 -58
  308. package/src/ui/App.tsx +576 -111
  309. package/src/ui/LiveArea.js +14 -8
  310. package/src/ui/LiveArea.tsx +14 -10
  311. package/src/ui/MessageList.js +63 -20
  312. package/src/ui/MessageList.tsx +101 -16
  313. package/src/ui/ModelPicker.js +7 -4
  314. package/src/ui/ModelPicker.tsx +55 -8
  315. package/src/ui/hooks/useChat.js +152 -163
  316. package/src/ui/hooks/useChat.ts +396 -334
  317. package/src/ui/loginCommand.js +56 -0
  318. package/src/ui/loginCommand.ts +63 -0
  319. package/src/ui/toolProgress.js +41 -0
  320. package/src/ui/toolProgress.ts +44 -0
  321. package/src/web/browserBridge.js +20 -2
  322. package/src/web/browserBridge.ts +20 -2
  323. package/src/web/protocol.ts +1897 -194
  324. package/workflows/adaptive-research/workflow.mjs +86 -0
  325. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  326. package/workflows/e2e-llm/workflow.mjs +52 -0
  327. package/workflows/e2e-smoke/workflow.mjs +59 -0
  328. package/workflows/e2e-vision-schema/README.md +48 -0
  329. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  330. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  331. package/workflows/file-census/README.md +14 -0
  332. package/workflows/file-census/scripts/.gitkeep +2 -0
  333. package/workflows/file-census/workflow.mjs +110 -0
  334. package/workflows/goal/README.md +166 -0
  335. package/workflows/goal/prompts/audit.md +57 -0
  336. package/workflows/goal/prompts/contract.md +56 -0
  337. package/workflows/goal/prompts/iterate.md +37 -0
  338. package/workflows/goal/workflow.mjs +501 -0
  339. package/workflows/illustrate/README.md +90 -0
  340. package/workflows/illustrate/assets/engines.json +20 -0
  341. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  342. package/workflows/illustrate/assets/extract-bing.js +33 -0
  343. package/workflows/illustrate/assets/extract-google.js +31 -0
  344. package/workflows/illustrate/workflow.mjs +301 -0
  345. package/workflows/plan/workflow.mjs +389 -0
  346. package/workflows/question-crops/README.md +35 -0
  347. package/workflows/question-crops/prompts/inventory.md +23 -0
  348. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  349. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  350. package/workflows/question-crops/workflow.mjs +172 -0
  351. package/workflows/ralph-loop/workflow.mjs +162 -0
  352. package/workflows/research/README.md +74 -0
  353. package/workflows/research/prompts/s0-goal.md +43 -0
  354. package/workflows/research/prompts/s1-early-exit.md +22 -0
  355. package/workflows/research/prompts/s1-map.md +58 -0
  356. package/workflows/research/prompts/s2-options.md +53 -0
  357. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  358. package/workflows/research/prompts/s4-verify.md +74 -0
  359. package/workflows/research/prompts/s5-synthesis.md +81 -0
  360. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  361. package/workflows/research/prompts/s6-package.md +32 -0
  362. package/workflows/research/scripts/build-report.mjs +98 -0
  363. package/workflows/research/workflow.mjs +288 -0
  364. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  365. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  366. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  367. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  368. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  369. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  370. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  371. package/workflows/wrong-question-docx/README.md +55 -0
  372. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  373. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  374. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  375. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  376. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  377. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  378. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  379. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  380. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  381. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  382. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  383. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  384. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  385. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  386. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  387. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  388. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  389. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  390. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  391. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  392. package/plugins/workflow-runner/src/expressions.js +0 -639
  393. package/plugins/workflow-runner/src/expressions.ts +0 -640
  394. package/plugins/workflow-runner/src/loader.js +0 -573
  395. package/plugins/workflow-runner/src/loader.ts +0 -721
  396. package/plugins/workflow-runner/src/multimodal.js +0 -38
  397. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  398. package/plugins/workflow-runner/src/recovery.js +0 -126
  399. package/plugins/workflow-runner/src/recovery.ts +0 -156
  400. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  401. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  402. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  403. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  404. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  405. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  406. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  407. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  408. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  409. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  410. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  411. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  412. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  413. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  414. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  415. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  416. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  417. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  418. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  419. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  420. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  421. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  422. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  423. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  424. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  425. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  426. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  427. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  428. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  429. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  430. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  431. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  432. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  433. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  434. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  435. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  436. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  437. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  438. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  439. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  440. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  441. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  442. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  443. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  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 -201
  468. package/workflows/research.yaml +0 -873
  469. package/workflows/schema.json +0 -176
  470. package/workflows/webppt.yaml +0 -496
  471. package/workflows/wechat-reading-shots.yaml +0 -315
  472. package/workflows/word.yaml +0 -720
  473. package/workflows/youtube-shorts.yaml +0 -202
  474. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -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
+ }