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,246 @@
1
+ import { z } from 'zod';
2
+ import { toToolParameters } from '../../utils/zodToJson.js';
3
+ import { runManagedAgentTask } from './agent.js';
4
+ import { appendAgentEvent, enqueueAgentMessage, getLiveAgentTask, listAgentRecords, loadAgentRecord, saveAgentRecord, } from './agentTaskService.js';
5
+ const agentId = z.string().regex(/^agent_[0-9a-f-]{36}$/i);
6
+ function needsContext(context) {
7
+ if (!context.sessionState)
8
+ return { ok: false, error: 'Agent 控制工具需要当前 Session 运行状态。' };
9
+ return undefined;
10
+ }
11
+ function snapshot(record) {
12
+ return {
13
+ agent_id: record.id,
14
+ status: record.status,
15
+ description: record.description,
16
+ progress: record.progress,
17
+ created_at: record.createdAt,
18
+ updated_at: record.updatedAt,
19
+ result: record.result
20
+ ? record.result.ok
21
+ ? record.result.content.slice(0, 4_000)
22
+ : `Error: ${record.result.error.slice(0, 4_000)}`
23
+ : undefined,
24
+ };
25
+ }
26
+ const messageSchema = z.object({
27
+ agent_id: agentId,
28
+ message: z.string().min(1).max(100_000),
29
+ });
30
+ export const agentMessageTool = {
31
+ name: 'AgentMessage',
32
+ description: 'Sends additional context or a correction to one running sub-agent by stable agent_id. ' +
33
+ 'The message is inserted at the next model boundary without cancelling its current tool call. ' +
34
+ 'Use AgentFollowup instead when the agent is already idle or completed.',
35
+ inputSchema: messageSchema,
36
+ parameters: toToolParameters(messageSchema),
37
+ isReadOnly: false,
38
+ isConcurrencySafe: true,
39
+ call: async () => ({
40
+ ok: false,
41
+ error: 'AgentMessage requires session context',
42
+ }),
43
+ callWithContext: async (input, _signal, context) => {
44
+ const missing = needsContext(context);
45
+ if (missing)
46
+ return missing;
47
+ const task = getLiveAgentTask(context.sessionState.agentTasks, input.agent_id);
48
+ if (!task || task.status !== 'running') {
49
+ const saved = await loadAgentRecord(context, input.agent_id);
50
+ return saved
51
+ ? {
52
+ ok: false,
53
+ error: `Agent ${input.agent_id} 当前为 ${saved.status};请使用 AgentFollowup 启动后续回合。`,
54
+ }
55
+ : { ok: false, error: `当前 Session 中不存在 Agent ${input.agent_id}` };
56
+ }
57
+ enqueueAgentMessage(task, input.message);
58
+ await saveAgentRecord(context, task);
59
+ await appendAgentEvent(context, task.id, {
60
+ phase: 'message',
61
+ message: input.message,
62
+ });
63
+ return {
64
+ ok: true,
65
+ content: `消息已发送给 ${task.id},将在下一个模型边界生效。`,
66
+ };
67
+ },
68
+ };
69
+ const listSchema = z.object({
70
+ include_completed: z.boolean().optional(),
71
+ });
72
+ export const agentListTool = {
73
+ name: 'AgentList',
74
+ description: 'Lists sub-agents owned by the current Session, including stable IDs, status and latest progress.',
75
+ inputSchema: listSchema,
76
+ parameters: toToolParameters(listSchema),
77
+ isReadOnly: true,
78
+ isConcurrencySafe: true,
79
+ call: async () => ({
80
+ ok: false,
81
+ error: 'AgentList requires session context',
82
+ }),
83
+ callWithContext: async (input, _signal, context) => {
84
+ const missing = needsContext(context);
85
+ if (missing)
86
+ return missing;
87
+ const records = (await listAgentRecords(context)).filter((record) => input.include_completed !== false || record.status === 'running');
88
+ return {
89
+ ok: true,
90
+ content: records.length
91
+ ? JSON.stringify(records.map(snapshot), null, 2)
92
+ : '当前 Session 没有符合条件的子 Agent。',
93
+ };
94
+ },
95
+ };
96
+ const waitSchema = z.object({
97
+ agent_ids: z.array(agentId).min(1).max(8),
98
+ timeout_ms: z.number().int().min(0).max(120_000).optional(),
99
+ });
100
+ export const agentWaitTool = {
101
+ name: 'AgentWait',
102
+ description: 'Waits efficiently until any selected running sub-agent finishes or the timeout expires, then returns fresh snapshots for all selected IDs. Do not poll repeatedly.',
103
+ inputSchema: waitSchema,
104
+ parameters: toToolParameters(waitSchema),
105
+ isReadOnly: true,
106
+ isConcurrencySafe: true,
107
+ interruptBehavior: () => 'cancel',
108
+ call: async () => ({
109
+ ok: false,
110
+ error: 'AgentWait requires session context',
111
+ }),
112
+ callWithContext: async (input, signal, context) => {
113
+ const missing = needsContext(context);
114
+ if (missing)
115
+ return missing;
116
+ const live = input.agent_ids
117
+ .map((id) => getLiveAgentTask(context.sessionState.agentTasks, id))
118
+ .filter((task) => Boolean(task?.status === 'running'));
119
+ const timeoutMs = input.timeout_ms ?? 30_000;
120
+ if (live.length && timeoutMs > 0) {
121
+ let timer;
122
+ let onAbort;
123
+ const timeout = new Promise((resolve) => {
124
+ timer = setTimeout(resolve, timeoutMs);
125
+ timer.unref?.();
126
+ });
127
+ const aborted = new Promise((resolve) => {
128
+ if (!signal)
129
+ return;
130
+ onAbort = () => resolve();
131
+ if (signal.aborted)
132
+ resolve();
133
+ else
134
+ signal.addEventListener('abort', onAbort, { once: true });
135
+ });
136
+ await Promise.race([
137
+ ...live.map((task) => task.completion),
138
+ timeout,
139
+ aborted,
140
+ ]);
141
+ if (timer)
142
+ clearTimeout(timer);
143
+ if (signal && onAbort)
144
+ signal.removeEventListener('abort', onAbort);
145
+ if (signal?.aborted)
146
+ return { ok: false, error: 'aborted' };
147
+ }
148
+ const records = [];
149
+ const missingIds = [];
150
+ for (const id of input.agent_ids) {
151
+ const record = getLiveAgentTask(context.sessionState.agentTasks, id) ??
152
+ (await loadAgentRecord(context, id));
153
+ if (record)
154
+ records.push(record);
155
+ else
156
+ missingIds.push(id);
157
+ }
158
+ return {
159
+ ok: true,
160
+ content: JSON.stringify({ agents: records.map(snapshot), missing: missingIds }, null, 2),
161
+ };
162
+ },
163
+ };
164
+ const interruptSchema = z.object({ agent_id: agentId });
165
+ export const agentInterruptTool = {
166
+ name: 'AgentInterrupt',
167
+ description: 'Interrupts one running sub-agent owned by the current Session. Its private history, progress and worktree are preserved for a later AgentFollowup.',
168
+ inputSchema: interruptSchema,
169
+ parameters: toToolParameters(interruptSchema),
170
+ isReadOnly: false,
171
+ isConcurrencySafe: true,
172
+ call: async () => ({
173
+ ok: false,
174
+ error: 'AgentInterrupt requires session context',
175
+ }),
176
+ callWithContext: async (input, _signal, context) => {
177
+ const missing = needsContext(context);
178
+ if (missing)
179
+ return missing;
180
+ const live = getLiveAgentTask(context.sessionState.agentTasks, input.agent_id);
181
+ if (!live || live.status !== 'running') {
182
+ const saved = await loadAgentRecord(context, input.agent_id);
183
+ return saved
184
+ ? {
185
+ ok: true,
186
+ content: `Agent ${input.agent_id} 已经是 ${saved.status},未执行中断。`,
187
+ }
188
+ : { ok: false, error: `当前 Session 中不存在 Agent ${input.agent_id}` };
189
+ }
190
+ const previous = live.status;
191
+ live.abort.abort(new Error('interrupted-by-parent-agent'));
192
+ await Promise.race([
193
+ live.completion,
194
+ new Promise((resolve) => setTimeout(resolve, 5_000)),
195
+ ]);
196
+ return {
197
+ ok: true,
198
+ content: `已中断 ${live.id}(先前状态:${previous};当前状态:${live.status})。`,
199
+ };
200
+ },
201
+ };
202
+ const followupSchema = z.object({
203
+ agent_id: agentId,
204
+ message: z.string().min(1).max(100_000),
205
+ run_in_background: z.boolean().optional(),
206
+ });
207
+ export const agentFollowupTool = {
208
+ name: 'AgentFollowup',
209
+ description: 'Adds a follow-up task to a stable sub-agent. If it is running, delivers the message at the next model boundary; if idle, resumes its persisted private history and starts a new turn.',
210
+ inputSchema: followupSchema,
211
+ parameters: toToolParameters(followupSchema),
212
+ isReadOnly: false,
213
+ isConcurrencySafe: true,
214
+ interruptBehavior: () => 'block',
215
+ call: async () => ({
216
+ ok: false,
217
+ error: 'AgentFollowup requires session context',
218
+ }),
219
+ callWithContext: async (input, signal, context) => {
220
+ const missing = needsContext(context);
221
+ if (missing)
222
+ return missing;
223
+ const live = getLiveAgentTask(context.sessionState.agentTasks, input.agent_id);
224
+ if (live?.status === 'running') {
225
+ enqueueAgentMessage(live, input.message);
226
+ await saveAgentRecord(context, live);
227
+ await appendAgentEvent(context, live.id, {
228
+ phase: 'followup',
229
+ message: input.message,
230
+ });
231
+ return { ok: true, content: `后续任务已发送给运行中的 ${live.id}。` };
232
+ }
233
+ const saved = await loadAgentRecord(context, input.agent_id);
234
+ if (!saved)
235
+ return {
236
+ ok: false,
237
+ error: `当前 Session 中不存在 Agent ${input.agent_id}`,
238
+ };
239
+ return runManagedAgentTask({
240
+ description: saved.description,
241
+ prompt: input.message,
242
+ resume_agent_id: input.agent_id,
243
+ run_in_background: input.run_in_background ?? true,
244
+ }, signal, context);
245
+ },
246
+ };
@@ -0,0 +1,284 @@
1
+ import { z } from 'zod';
2
+
3
+ import type { Tool, ToolCallContext, ToolResult } from '../../types.js';
4
+ import { toToolParameters } from '../../utils/zodToJson.js';
5
+ import { runManagedAgentTask } from './agent.js';
6
+ import {
7
+ type AgentTaskRecord,
8
+ appendAgentEvent,
9
+ enqueueAgentMessage,
10
+ getLiveAgentTask,
11
+ listAgentRecords,
12
+ loadAgentRecord,
13
+ saveAgentRecord,
14
+ } from './agentTaskService.js';
15
+
16
+ const agentId = z.string().regex(/^agent_[0-9a-f-]{36}$/i);
17
+
18
+ function needsContext(context: ToolCallContext): ToolResult | undefined {
19
+ if (!context.sessionState)
20
+ return { ok: false, error: 'Agent 控制工具需要当前 Session 运行状态。' };
21
+ return undefined;
22
+ }
23
+
24
+ function snapshot(record: AgentTaskRecord) {
25
+ return {
26
+ agent_id: record.id,
27
+ status: record.status,
28
+ description: record.description,
29
+ progress: record.progress,
30
+ created_at: record.createdAt,
31
+ updated_at: record.updatedAt,
32
+ result: record.result
33
+ ? record.result.ok
34
+ ? record.result.content.slice(0, 4_000)
35
+ : `Error: ${record.result.error.slice(0, 4_000)}`
36
+ : undefined,
37
+ };
38
+ }
39
+
40
+ const messageSchema = z.object({
41
+ agent_id: agentId,
42
+ message: z.string().min(1).max(100_000),
43
+ });
44
+
45
+ export const agentMessageTool: Tool<z.infer<typeof messageSchema>> = {
46
+ name: 'AgentMessage',
47
+ description:
48
+ 'Sends additional context or a correction to one running sub-agent by stable agent_id. ' +
49
+ 'The message is inserted at the next model boundary without cancelling its current tool call. ' +
50
+ 'Use AgentFollowup instead when the agent is already idle or completed.',
51
+ inputSchema: messageSchema,
52
+ parameters: toToolParameters(messageSchema),
53
+ isReadOnly: false,
54
+ isConcurrencySafe: true,
55
+ call: async () => ({
56
+ ok: false,
57
+ error: 'AgentMessage requires session context',
58
+ }),
59
+ callWithContext: async (input, _signal, context) => {
60
+ const missing = needsContext(context);
61
+ if (missing) return missing;
62
+ const task = getLiveAgentTask(
63
+ context.sessionState!.agentTasks,
64
+ input.agent_id,
65
+ );
66
+ if (!task || task.status !== 'running') {
67
+ const saved = await loadAgentRecord(context, input.agent_id);
68
+ return saved
69
+ ? {
70
+ ok: false,
71
+ error: `Agent ${input.agent_id} 当前为 ${saved.status};请使用 AgentFollowup 启动后续回合。`,
72
+ }
73
+ : { ok: false, error: `当前 Session 中不存在 Agent ${input.agent_id}` };
74
+ }
75
+ enqueueAgentMessage(task, input.message);
76
+ await saveAgentRecord(context, task);
77
+ await appendAgentEvent(context, task.id, {
78
+ phase: 'message',
79
+ message: input.message,
80
+ });
81
+ return {
82
+ ok: true,
83
+ content: `消息已发送给 ${task.id},将在下一个模型边界生效。`,
84
+ };
85
+ },
86
+ };
87
+
88
+ const listSchema = z.object({
89
+ include_completed: z.boolean().optional(),
90
+ });
91
+
92
+ export const agentListTool: Tool<z.infer<typeof listSchema>> = {
93
+ name: 'AgentList',
94
+ description:
95
+ 'Lists sub-agents owned by the current Session, including stable IDs, status and latest progress.',
96
+ inputSchema: listSchema,
97
+ parameters: toToolParameters(listSchema),
98
+ isReadOnly: true,
99
+ isConcurrencySafe: true,
100
+ call: async () => ({
101
+ ok: false,
102
+ error: 'AgentList requires session context',
103
+ }),
104
+ callWithContext: async (input, _signal, context) => {
105
+ const missing = needsContext(context);
106
+ if (missing) return missing;
107
+ const records = (await listAgentRecords(context)).filter(
108
+ (record) =>
109
+ input.include_completed !== false || record.status === 'running',
110
+ );
111
+ return {
112
+ ok: true,
113
+ content: records.length
114
+ ? JSON.stringify(records.map(snapshot), null, 2)
115
+ : '当前 Session 没有符合条件的子 Agent。',
116
+ };
117
+ },
118
+ };
119
+
120
+ const waitSchema = z.object({
121
+ agent_ids: z.array(agentId).min(1).max(8),
122
+ timeout_ms: z.number().int().min(0).max(120_000).optional(),
123
+ });
124
+
125
+ export const agentWaitTool: Tool<z.infer<typeof waitSchema>> = {
126
+ name: 'AgentWait',
127
+ description:
128
+ 'Waits efficiently until any selected running sub-agent finishes or the timeout expires, then returns fresh snapshots for all selected IDs. Do not poll repeatedly.',
129
+ inputSchema: waitSchema,
130
+ parameters: toToolParameters(waitSchema),
131
+ isReadOnly: true,
132
+ isConcurrencySafe: true,
133
+ interruptBehavior: () => 'cancel',
134
+ call: async () => ({
135
+ ok: false,
136
+ error: 'AgentWait requires session context',
137
+ }),
138
+ callWithContext: async (input, signal, context) => {
139
+ const missing = needsContext(context);
140
+ if (missing) return missing;
141
+ const live = input.agent_ids
142
+ .map((id) => getLiveAgentTask(context.sessionState!.agentTasks, id))
143
+ .filter((task): task is NonNullable<typeof task> =>
144
+ Boolean(task?.status === 'running'),
145
+ );
146
+ const timeoutMs = input.timeout_ms ?? 30_000;
147
+ if (live.length && timeoutMs > 0) {
148
+ let timer: ReturnType<typeof setTimeout> | undefined;
149
+ let onAbort: (() => void) | undefined;
150
+ const timeout = new Promise<void>((resolve) => {
151
+ timer = setTimeout(resolve, timeoutMs);
152
+ timer.unref?.();
153
+ });
154
+ const aborted = new Promise<void>((resolve) => {
155
+ if (!signal) return;
156
+ onAbort = () => resolve();
157
+ if (signal.aborted) resolve();
158
+ else signal.addEventListener('abort', onAbort, { once: true });
159
+ });
160
+ await Promise.race([
161
+ ...live.map((task) => task.completion),
162
+ timeout,
163
+ aborted,
164
+ ]);
165
+ if (timer) clearTimeout(timer);
166
+ if (signal && onAbort) signal.removeEventListener('abort', onAbort);
167
+ if (signal?.aborted) return { ok: false, error: 'aborted' };
168
+ }
169
+ const records: AgentTaskRecord[] = [];
170
+ const missingIds: string[] = [];
171
+ for (const id of input.agent_ids) {
172
+ const record =
173
+ getLiveAgentTask(context.sessionState!.agentTasks, id) ??
174
+ (await loadAgentRecord(context, id));
175
+ if (record) records.push(record);
176
+ else missingIds.push(id);
177
+ }
178
+ return {
179
+ ok: true,
180
+ content: JSON.stringify(
181
+ { agents: records.map(snapshot), missing: missingIds },
182
+ null,
183
+ 2,
184
+ ),
185
+ };
186
+ },
187
+ };
188
+
189
+ const interruptSchema = z.object({ agent_id: agentId });
190
+
191
+ export const agentInterruptTool: Tool<z.infer<typeof interruptSchema>> = {
192
+ name: 'AgentInterrupt',
193
+ description:
194
+ 'Interrupts one running sub-agent owned by the current Session. Its private history, progress and worktree are preserved for a later AgentFollowup.',
195
+ inputSchema: interruptSchema,
196
+ parameters: toToolParameters(interruptSchema),
197
+ isReadOnly: false,
198
+ isConcurrencySafe: true,
199
+ call: async () => ({
200
+ ok: false,
201
+ error: 'AgentInterrupt requires session context',
202
+ }),
203
+ callWithContext: async (input, _signal, context) => {
204
+ const missing = needsContext(context);
205
+ if (missing) return missing;
206
+ const live = getLiveAgentTask(
207
+ context.sessionState!.agentTasks,
208
+ input.agent_id,
209
+ );
210
+ if (!live || live.status !== 'running') {
211
+ const saved = await loadAgentRecord(context, input.agent_id);
212
+ return saved
213
+ ? {
214
+ ok: true,
215
+ content: `Agent ${input.agent_id} 已经是 ${saved.status},未执行中断。`,
216
+ }
217
+ : { ok: false, error: `当前 Session 中不存在 Agent ${input.agent_id}` };
218
+ }
219
+ const previous = live.status;
220
+ live.abort.abort(new Error('interrupted-by-parent-agent'));
221
+ await Promise.race([
222
+ live.completion,
223
+ new Promise<void>((resolve) => setTimeout(resolve, 5_000)),
224
+ ]);
225
+ return {
226
+ ok: true,
227
+ content: `已中断 ${live.id}(先前状态:${previous};当前状态:${live.status})。`,
228
+ };
229
+ },
230
+ };
231
+
232
+ const followupSchema = z.object({
233
+ agent_id: agentId,
234
+ message: z.string().min(1).max(100_000),
235
+ run_in_background: z.boolean().optional(),
236
+ });
237
+
238
+ export const agentFollowupTool: Tool<z.infer<typeof followupSchema>> = {
239
+ name: 'AgentFollowup',
240
+ description:
241
+ 'Adds a follow-up task to a stable sub-agent. If it is running, delivers the message at the next model boundary; if idle, resumes its persisted private history and starts a new turn.',
242
+ inputSchema: followupSchema,
243
+ parameters: toToolParameters(followupSchema),
244
+ isReadOnly: false,
245
+ isConcurrencySafe: true,
246
+ interruptBehavior: () => 'block',
247
+ call: async () => ({
248
+ ok: false,
249
+ error: 'AgentFollowup requires session context',
250
+ }),
251
+ callWithContext: async (input, signal, context) => {
252
+ const missing = needsContext(context);
253
+ if (missing) return missing;
254
+ const live = getLiveAgentTask(
255
+ context.sessionState!.agentTasks,
256
+ input.agent_id,
257
+ );
258
+ if (live?.status === 'running') {
259
+ enqueueAgentMessage(live, input.message);
260
+ await saveAgentRecord(context, live);
261
+ await appendAgentEvent(context, live.id, {
262
+ phase: 'followup',
263
+ message: input.message,
264
+ });
265
+ return { ok: true, content: `后续任务已发送给运行中的 ${live.id}。` };
266
+ }
267
+ const saved = await loadAgentRecord(context, input.agent_id);
268
+ if (!saved)
269
+ return {
270
+ ok: false,
271
+ error: `当前 Session 中不存在 Agent ${input.agent_id}`,
272
+ };
273
+ return runManagedAgentTask(
274
+ {
275
+ description: saved.description,
276
+ prompt: input.message,
277
+ resume_agent_id: input.agent_id,
278
+ run_in_background: input.run_in_background ?? true,
279
+ },
280
+ signal,
281
+ context,
282
+ );
283
+ },
284
+ };
@@ -1,4 +1,4 @@
1
- import { appendFile, mkdir } from 'node:fs/promises';
1
+ import { appendFile, mkdir, readdir } from 'node:fs/promises';
2
2
  import { join } from 'node:path';
3
3
  import { readRuntimeJson, sessionRuntimeDir, withRuntimeFileLock, writeRuntimeJson, } from '../../session/runtimeStore.js';
4
4
  export function createAgentTaskState() {
@@ -49,6 +49,45 @@ export async function loadAgentRecord(ctx, id) {
49
49
  export function getLiveAgentTask(state, id) {
50
50
  return state?.tasks.get(id);
51
51
  }
52
+ /** List the durable tasks owned by this Session, with process-local state winning. */
53
+ export async function listAgentRecords(ctx) {
54
+ const root = join(sessionRuntimeDir(ctx), 'agents');
55
+ const entries = await readdir(root, { withFileTypes: true }).catch(() => []);
56
+ const records = new Map();
57
+ for (const entry of entries) {
58
+ if (!entry.isDirectory() || !/^agent_[0-9a-f-]{36}$/i.test(entry.name))
59
+ continue;
60
+ const record = await loadAgentRecord(ctx, entry.name);
61
+ if (record)
62
+ records.set(record.id, record);
63
+ }
64
+ for (const live of ctx.sessionState?.agentTasks.tasks.values() ?? [])
65
+ records.set(live.id, live);
66
+ return [...records.values()].sort((a, b) => b.updatedAt - a.updatedAt);
67
+ }
68
+ export function agentMessage(message) {
69
+ return {
70
+ role: 'user',
71
+ content: `[主 Agent 后续消息]\n${message}`,
72
+ timestamp: Date.now(),
73
+ };
74
+ }
75
+ /** Deliver at the next model-message boundary without aborting the active turn. */
76
+ export function enqueueAgentMessage(task, message) {
77
+ if (task.history)
78
+ task.history.push(agentMessage(message));
79
+ else
80
+ task.inbox.push(message);
81
+ task.updatedAt = Date.now();
82
+ task.events.emit('change');
83
+ }
84
+ /** Attach the live private history and flush messages accepted during startup. */
85
+ export function attachAgentHistory(task, history) {
86
+ task.history = history;
87
+ for (const message of task.inbox.splice(0))
88
+ history.push(agentMessage(message));
89
+ task.events.emit('change');
90
+ }
52
91
  export async function stopAllAgentTasks(state) {
53
92
  const running = [...state.tasks.values()].filter((t) => t.status === 'running');
54
93
  running.forEach((t) => t.abort.abort());
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from 'node:events';
2
- import { appendFile, mkdir } from 'node:fs/promises';
2
+ import { appendFile, mkdir, readdir } from 'node:fs/promises';
3
3
  import { join } from 'node:path';
4
4
  import type { Message, ToolCallContext, ToolResult } from '../../types.js';
5
5
  import type { AgentWorktree } from './worktree.js';
@@ -28,6 +28,8 @@ export interface LiveAgentTask extends AgentTaskRecord {
28
28
  abort: AbortController;
29
29
  completion: Promise<void>;
30
30
  events: EventEmitter;
31
+ /** Messages accepted before the private history is ready are flushed in order. */
32
+ inbox: string[];
31
33
  }
32
34
  export interface AgentTaskState {
33
35
  tasks: Map<string, LiveAgentTask>;
@@ -100,6 +102,47 @@ export function getLiveAgentTask(
100
102
  ): LiveAgentTask | undefined {
101
103
  return state?.tasks.get(id);
102
104
  }
105
+
106
+ /** List the durable tasks owned by this Session, with process-local state winning. */
107
+ export async function listAgentRecords(
108
+ ctx: ToolCallContext,
109
+ ): Promise<AgentTaskRecord[]> {
110
+ const root = join(sessionRuntimeDir(ctx), 'agents');
111
+ const entries = await readdir(root, { withFileTypes: true }).catch(() => []);
112
+ const records = new Map<string, AgentTaskRecord>();
113
+ for (const entry of entries) {
114
+ if (!entry.isDirectory() || !/^agent_[0-9a-f-]{36}$/i.test(entry.name))
115
+ continue;
116
+ const record = await loadAgentRecord(ctx, entry.name);
117
+ if (record) records.set(record.id, record);
118
+ }
119
+ for (const live of ctx.sessionState?.agentTasks.tasks.values() ?? [])
120
+ records.set(live.id, live);
121
+ return [...records.values()].sort((a, b) => b.updatedAt - a.updatedAt);
122
+ }
123
+
124
+ export function agentMessage(message: string): Message {
125
+ return {
126
+ role: 'user',
127
+ content: `[主 Agent 后续消息]\n${message}`,
128
+ timestamp: Date.now(),
129
+ };
130
+ }
131
+
132
+ /** Deliver at the next model-message boundary without aborting the active turn. */
133
+ export function enqueueAgentMessage(task: LiveAgentTask, message: string): void {
134
+ if (task.history) task.history.push(agentMessage(message));
135
+ else task.inbox.push(message);
136
+ task.updatedAt = Date.now();
137
+ task.events.emit('change');
138
+ }
139
+
140
+ /** Attach the live private history and flush messages accepted during startup. */
141
+ export function attachAgentHistory(task: LiveAgentTask, history: Message[]): void {
142
+ task.history = history;
143
+ for (const message of task.inbox.splice(0)) history.push(agentMessage(message));
144
+ task.events.emit('change');
145
+ }
103
146
  export async function stopAllAgentTasks(state: AgentTaskState): Promise<void> {
104
147
  const running = [...state.tasks.values()].filter(
105
148
  (t) => t.status === 'running',
@@ -13,6 +13,7 @@
13
13
  * (两次规则:真实需要出现两次再议)。
14
14
  * ============================================================
15
15
  */
16
+ import { DEFAULT_SUBAGENTS_CONFIG } from '../../config/configDefaults.js';
16
17
  /**
17
18
  * 任何 agent_type 都排除的工具:
18
19
  * - Agent:防递归 fork(子 agent 再 fork 子 agent,深度失控)。
@@ -20,7 +21,13 @@
20
21
  */
21
22
  export const SUBAGENT_EXCLUDED_TOOLS = [
22
23
  'Agent',
24
+ 'AgentMessage',
25
+ 'AgentList',
26
+ 'AgentWait',
27
+ 'AgentInterrupt',
28
+ 'AgentFollowup',
23
29
  'Advisor',
30
+ 'AdvisorDecision',
24
31
  // 子任务只向主 Agent 汇报;正式用户交付由主 Agent 统一收口,避免重复结果卡。
25
32
  'PresentResult',
26
33
  'RememberMemory',
@@ -41,6 +48,8 @@ export const EXPLORE_ALLOWED_TOOLS = [
41
48
  'WebSearch',
42
49
  'WebFetch',
43
50
  'WebBrowser',
51
+ 'BrowserBatch',
52
+ 'BrowserCDP',
44
53
  'RecallMemory',
45
54
  'ListMemories',
46
55
  'ReviewMemories',
@@ -53,16 +62,19 @@ const EXPLORE_APPENDIX = `# 本次子任务类型:只读调研(explore)
53
62
  严格使用已提供的只读工具。报告给出结论、关键证据和没查到的缺口。`;
54
63
  const GENERAL_APPENDIX = `# 本次子任务类型:读写执行(general)
55
64
  只做任务书范围内的修改;报告列出改动文件和验证结果。`;
65
+ // 轮数上限的**唯一真值**在 configDefaults.ts。这里只是「没有 subagentConfig 时」的
66
+ // 兜底取值,必须与那份一致 —— 曾经两边各写一份字面量(都是 200/100),
67
+ // 改一处漏一处就会出现「有配置时 200、没配置时 50」这种只在缺省路径显形的分裂。
56
68
  const EXPLORE_DEF = {
57
69
  type: 'explore',
58
70
  resolveAllowedTools: (all) => all.filter((n) => EXPLORE_ALLOWED_TOOLS.includes(n)),
59
- maxTurns: 50,
71
+ maxTurns: DEFAULT_SUBAGENTS_CONFIG.exploreMaxTurns,
60
72
  promptAppendix: EXPLORE_APPENDIX,
61
73
  };
62
74
  const GENERAL_DEF = {
63
75
  type: 'general',
64
76
  resolveAllowedTools: (all) => all.filter((n) => !SUBAGENT_EXCLUDED_TOOLS.includes(n)),
65
- maxTurns: 100,
77
+ maxTurns: DEFAULT_SUBAGENTS_CONFIG.generalMaxTurns,
66
78
  promptAppendix: GENERAL_APPENDIX,
67
79
  };
68
80
  /** 未知/缺省一律回落 explore(最安全的默认:只读)。 */