minimal-agent 0.13.0 → 0.14.0

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