@bastani/atomic 0.9.19-alpha.1 → 0.9.19-alpha.3

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 (720) hide show
  1. package/CHANGELOG.md +108 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +23 -0
  3. package/dist/builtin/intercom/README.md +21 -11
  4. package/dist/builtin/intercom/broker/broker.ts +81 -9
  5. package/dist/builtin/intercom/broker/client.ts +22 -0
  6. package/dist/builtin/intercom/broker/framing.ts +5 -2
  7. package/dist/builtin/intercom/broker/group-membership.ts +4 -2
  8. package/dist/builtin/intercom/broker/presence-handler.ts +14 -0
  9. package/dist/builtin/intercom/broker/send-handler.ts +43 -5
  10. package/dist/builtin/intercom/broker/terminal-questions.ts +29 -0
  11. package/dist/builtin/intercom/index.bundle.mjs +978 -742
  12. package/dist/builtin/intercom/package.json +2 -2
  13. package/dist/builtin/intercom/recipient-purpose.ts +9 -0
  14. package/dist/builtin/intercom/recoverable-disconnect.ts +2 -3
  15. package/dist/builtin/intercom/retry-policy.ts +4 -2
  16. package/dist/builtin/intercom/skills/intercom/SKILL.md +5 -4
  17. package/dist/builtin/intercom/types.ts +18 -3
  18. package/dist/builtin/mcp/CHANGELOG.md +6 -0
  19. package/dist/builtin/mcp/README.md +2 -0
  20. package/dist/builtin/mcp/index.bundle.mjs +2201 -12000
  21. package/dist/builtin/mcp/package.json +2 -2
  22. package/dist/builtin/subagents/CHANGELOG.md +33 -0
  23. package/dist/builtin/subagents/README.md +35 -14
  24. package/dist/builtin/subagents/agents/code-simplifier.md +1 -1
  25. package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
  26. package/dist/builtin/subagents/agents/codebase-locator.md +2 -2
  27. package/dist/builtin/subagents/agents/codebase-online-researcher.md +1 -1
  28. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +2 -2
  29. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
  30. package/dist/builtin/subagents/agents/codebase-research-locator.md +2 -2
  31. package/dist/builtin/subagents/agents/debugger.md +1 -1
  32. package/dist/builtin/subagents/agents/worker.md +1 -1
  33. package/dist/builtin/subagents/package.json +2 -2
  34. package/dist/builtin/subagents/skills/herdr/LICENSE +201 -0
  35. package/dist/builtin/subagents/skills/herdr/SKILL.md +202 -0
  36. package/dist/builtin/subagents/skills/subagent/SKILL.md +14 -10
  37. package/dist/builtin/subagents/skills/tmux/SKILL.md +1 -1
  38. package/dist/builtin/subagents/src/extension/index.bundle.mjs +1286 -611
  39. package/dist/builtin/web-access/index.bundle.mjs +26280 -26274
  40. package/dist/builtin/web-access/package.json +2 -2
  41. package/dist/builtin/workflows/CHANGELOG.md +51 -0
  42. package/dist/builtin/workflows/README.md +1 -1
  43. package/dist/builtin/workflows/builtin/adversarial-verification.js +5 -7
  44. package/dist/builtin/workflows/builtin/{chunk-reqr3sr3.js → chunk-1kx4aggw.js} +22 -22
  45. package/dist/builtin/workflows/builtin/{chunk-42s7sw0b.js → chunk-62v3gg9f.js} +9 -9
  46. package/dist/builtin/workflows/builtin/{chunk-wgccch41.js → chunk-6w6cvk6b.js} +16 -16
  47. package/dist/builtin/workflows/builtin/{chunk-zbekjqew.js → chunk-a2kdsqn8.js} +4 -4
  48. package/dist/builtin/workflows/builtin/{chunk-ze5x3d1r.js → chunk-fg9esgkj.js} +7 -7
  49. package/dist/builtin/workflows/builtin/{chunk-n8h4yyew.js → chunk-g0csgs7w.js} +11 -11
  50. package/dist/builtin/workflows/builtin/{chunk-79fjkcvh.js → chunk-hbnwv56f.js} +17 -17
  51. package/dist/builtin/workflows/builtin/{chunk-ed4jfn5t.js → chunk-mygmtz6e.js} +43 -43
  52. package/dist/builtin/workflows/builtin/{chunk-7430zyas.js → chunk-p8jjwfg6.js} +1 -1
  53. package/dist/builtin/workflows/builtin/{chunk-hqpe2cyx.js → chunk-r9qq7xfj.js} +49 -49
  54. package/dist/builtin/workflows/builtin/{chunk-k3w87x8y.js → chunk-t6x2d78s.js} +10 -10
  55. package/dist/builtin/workflows/builtin/{chunk-6fqs7c01.js → chunk-z0d03ktm.js} +1 -1
  56. package/dist/builtin/workflows/builtin/{chunk-b0v2xab1.js → chunk-zggjyg5z.js} +221 -23
  57. package/dist/builtin/workflows/builtin/classify-and-act.js +5 -6
  58. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +3 -4
  59. package/dist/builtin/workflows/builtin/generate-and-filter.js +5 -6
  60. package/dist/builtin/workflows/builtin/goal.js +7 -8
  61. package/dist/builtin/workflows/builtin/index.js +20 -22
  62. package/dist/builtin/workflows/builtin/loop-until-done.js +5 -6
  63. package/dist/builtin/workflows/builtin/open-claude-design.js +3 -3
  64. package/dist/builtin/workflows/builtin/ralph.js +7 -8
  65. package/dist/builtin/workflows/builtin/steering-context.js +3 -3
  66. package/dist/builtin/workflows/builtin/tournament.js +5 -7
  67. package/dist/builtin/workflows/package.json +2 -2
  68. package/dist/builtin/workflows/src/extension/index.bundle.mjs +26708 -25862
  69. package/dist/builtin/workflows/src/index.js +921 -477
  70. package/dist/cli/config-selector.js.map +1 -1
  71. package/dist/cli/startup-ui.d.ts +1 -1
  72. package/dist/cli/startup-ui.js.map +1 -1
  73. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  74. package/dist/core/agent-session-auto-compaction.js +5 -4
  75. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  76. package/dist/core/agent-session-bash.d.ts +1 -1
  77. package/dist/core/agent-session-bash.d.ts.map +1 -1
  78. package/dist/core/agent-session-bash.js +5 -1
  79. package/dist/core/agent-session-bash.js.map +1 -1
  80. package/dist/core/agent-session-compaction.d.ts +1 -1
  81. package/dist/core/agent-session-compaction.js.map +1 -1
  82. package/dist/core/agent-session-custom-message-commit.d.ts +1 -1
  83. package/dist/core/agent-session-custom-message-commit.js.map +1 -1
  84. package/dist/core/agent-session-delivery-forwarding.d.ts +1 -1
  85. package/dist/core/agent-session-delivery-forwarding.js.map +1 -1
  86. package/dist/core/agent-session-events.d.ts.map +1 -1
  87. package/dist/core/agent-session-events.js +5 -0
  88. package/dist/core/agent-session-events.js.map +1 -1
  89. package/dist/core/agent-session-export.d.ts +1 -1
  90. package/dist/core/agent-session-export.js.map +1 -1
  91. package/dist/core/agent-session-extension-bindings.d.ts +8 -1
  92. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  93. package/dist/core/agent-session-extension-bindings.js +45 -3
  94. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  95. package/dist/core/agent-session-message-queue.d.ts +1 -1
  96. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  97. package/dist/core/agent-session-message-queue.js +2 -2
  98. package/dist/core/agent-session-message-queue.js.map +1 -1
  99. package/dist/core/agent-session-methods.d.ts +17 -7
  100. package/dist/core/agent-session-methods.d.ts.map +1 -1
  101. package/dist/core/agent-session-methods.js.map +1 -1
  102. package/dist/core/agent-session-prompt.d.ts +2 -2
  103. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  104. package/dist/core/agent-session-prompt.js +22 -18
  105. package/dist/core/agent-session-prompt.js.map +1 -1
  106. package/dist/core/agent-session-runtime-auth.d.ts +1 -1
  107. package/dist/core/agent-session-runtime-auth.js.map +1 -1
  108. package/dist/core/agent-session-runtime.d.ts +13 -4
  109. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  110. package/dist/core/agent-session-runtime.js +27 -4
  111. package/dist/core/agent-session-runtime.js.map +1 -1
  112. package/dist/core/agent-session-services.d.ts +5 -1
  113. package/dist/core/agent-session-services.d.ts.map +1 -1
  114. package/dist/core/agent-session-services.js +44 -34
  115. package/dist/core/agent-session-services.js.map +1 -1
  116. package/dist/core/agent-session-state.d.ts +1 -1
  117. package/dist/core/agent-session-state.js.map +1 -1
  118. package/dist/core/agent-session-tasks.d.ts +14 -0
  119. package/dist/core/agent-session-tasks.d.ts.map +1 -0
  120. package/dist/core/agent-session-tasks.js +120 -0
  121. package/dist/core/agent-session-tasks.js.map +1 -0
  122. package/dist/core/agent-session-tool-registry.d.ts +1 -0
  123. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  124. package/dist/core/agent-session-tool-registry.js +30 -5
  125. package/dist/core/agent-session-tool-registry.js.map +1 -1
  126. package/dist/core/agent-session-tree.d.ts.map +1 -1
  127. package/dist/core/agent-session-tree.js +3 -0
  128. package/dist/core/agent-session-tree.js.map +1 -1
  129. package/dist/core/agent-session-types.d.ts +2 -2
  130. package/dist/core/agent-session-types.js.map +1 -1
  131. package/dist/core/agent-session.d.ts +4 -1
  132. package/dist/core/agent-session.d.ts.map +1 -1
  133. package/dist/core/agent-session.js +7 -1
  134. package/dist/core/agent-session.js.map +1 -1
  135. package/dist/core/bash-executor.d.ts +1 -1
  136. package/dist/core/bash-executor.js.map +1 -1
  137. package/dist/core/export-html/index.js.map +1 -1
  138. package/dist/core/export-html/tool-renderer.d.ts +1 -1
  139. package/dist/core/export-html/tool-renderer.js.map +1 -1
  140. package/dist/core/extension-session-state.js.map +1 -1
  141. package/dist/core/extensions/agent-events.d.ts +4 -4
  142. package/dist/core/extensions/agent-events.d.ts.map +1 -1
  143. package/dist/core/extensions/agent-events.js.map +1 -1
  144. package/dist/core/extensions/api-types.d.ts +8 -2
  145. package/dist/core/extensions/api-types.d.ts.map +1 -1
  146. package/dist/core/extensions/api-types.js.map +1 -1
  147. package/dist/core/extensions/context-types.d.ts +9 -0
  148. package/dist/core/extensions/context-types.d.ts.map +1 -1
  149. package/dist/core/extensions/context-types.js.map +1 -1
  150. package/dist/core/extensions/event-results.d.ts +1 -1
  151. package/dist/core/extensions/event-results.js.map +1 -1
  152. package/dist/core/extensions/event-types.d.ts +2 -1
  153. package/dist/core/extensions/event-types.d.ts.map +1 -1
  154. package/dist/core/extensions/event-types.js.map +1 -1
  155. package/dist/core/extensions/index.d.ts +2 -1
  156. package/dist/core/extensions/index.d.ts.map +1 -1
  157. package/dist/core/extensions/index.js.map +1 -1
  158. package/dist/core/extensions/loader-api.d.ts +1 -1
  159. package/dist/core/extensions/loader-api.d.ts.map +1 -1
  160. package/dist/core/extensions/loader-api.js +10 -0
  161. package/dist/core/extensions/loader-api.js.map +1 -1
  162. package/dist/core/extensions/loader-core.d.ts +1 -1
  163. package/dist/core/extensions/loader-core.js.map +1 -1
  164. package/dist/core/extensions/loader-discovery.d.ts +1 -1
  165. package/dist/core/extensions/loader-discovery.js.map +1 -1
  166. package/dist/core/extensions/loader-host-modules.d.ts +1 -1
  167. package/dist/core/extensions/loader-host-modules.d.ts.map +1 -1
  168. package/dist/core/extensions/loader-host-modules.js +2 -1
  169. package/dist/core/extensions/loader-host-modules.js.map +1 -1
  170. package/dist/core/extensions/loader-runtime.d.ts.map +1 -1
  171. package/dist/core/extensions/loader-runtime.js +3 -0
  172. package/dist/core/extensions/loader-runtime.js.map +1 -1
  173. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  174. package/dist/core/extensions/loader-virtual-modules.js +4 -1
  175. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  176. package/dist/core/extensions/loader.d.ts +1 -1
  177. package/dist/core/extensions/loader.js.map +1 -1
  178. package/dist/core/extensions/message-types.d.ts +1 -1
  179. package/dist/core/extensions/message-types.js.map +1 -1
  180. package/dist/core/extensions/runner-context.d.ts +11 -1
  181. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  182. package/dist/core/extensions/runner-context.js +41 -2
  183. package/dist/core/extensions/runner-context.js.map +1 -1
  184. package/dist/core/extensions/runner-events.d.ts +1 -1
  185. package/dist/core/extensions/runner-events.d.ts.map +1 -1
  186. package/dist/core/extensions/runner-events.js +17 -2
  187. package/dist/core/extensions/runner-events.js.map +1 -1
  188. package/dist/core/extensions/runner-ui.js.map +1 -1
  189. package/dist/core/extensions/runner.d.ts +17 -2
  190. package/dist/core/extensions/runner.d.ts.map +1 -1
  191. package/dist/core/extensions/runner.js +68 -18
  192. package/dist/core/extensions/runner.js.map +1 -1
  193. package/dist/core/extensions/runtime-types.d.ts +4 -1
  194. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  195. package/dist/core/extensions/runtime-types.js.map +1 -1
  196. package/dist/core/extensions/tool-types.d.ts +1 -1
  197. package/dist/core/extensions/tool-types.js.map +1 -1
  198. package/dist/core/extensions/types.d.ts +1 -0
  199. package/dist/core/extensions/types.d.ts.map +1 -1
  200. package/dist/core/extensions/types.js.map +1 -1
  201. package/dist/core/extensions/ui-types.d.ts +5 -1
  202. package/dist/core/extensions/ui-types.d.ts.map +1 -1
  203. package/dist/core/extensions/ui-types.js.map +1 -1
  204. package/dist/core/extensions/workflow-activity-hub.d.ts +25 -0
  205. package/dist/core/extensions/workflow-activity-hub.d.ts.map +1 -0
  206. package/dist/core/extensions/workflow-activity-hub.js +183 -0
  207. package/dist/core/extensions/workflow-activity-hub.js.map +1 -0
  208. package/dist/core/extensions/workflow-events.d.ts +118 -0
  209. package/dist/core/extensions/workflow-events.d.ts.map +1 -0
  210. package/dist/core/extensions/workflow-events.js +2 -0
  211. package/dist/core/extensions/workflow-events.js.map +1 -0
  212. package/dist/core/footer-data-provider.d.ts +8 -4
  213. package/dist/core/footer-data-provider.d.ts.map +1 -1
  214. package/dist/core/footer-data-provider.js +97 -11
  215. package/dist/core/footer-data-provider.js.map +1 -1
  216. package/dist/core/index.d.ts +3 -3
  217. package/dist/core/index.js.map +1 -1
  218. package/dist/core/keybindings.d.ts +27 -2
  219. package/dist/core/keybindings.d.ts.map +1 -1
  220. package/dist/core/keybindings.js +7 -2
  221. package/dist/core/keybindings.js.map +1 -1
  222. package/dist/core/mandatory-runtime-tools.d.ts +1 -1
  223. package/dist/core/mandatory-runtime-tools.js.map +1 -1
  224. package/dist/core/model-fallback-failures.js +2 -2
  225. package/dist/core/model-fallback-failures.js.map +1 -1
  226. package/dist/core/model-registry.d.ts +5 -1
  227. package/dist/core/model-registry.d.ts.map +1 -1
  228. package/dist/core/model-registry.js +8 -0
  229. package/dist/core/model-registry.js.map +1 -1
  230. package/dist/core/model-resolver-defaults.js +1 -1
  231. package/dist/core/model-resolver-defaults.js.map +1 -1
  232. package/dist/core/resource-loader-assets.js.map +1 -1
  233. package/dist/core/resource-loader-core.d.ts +1 -1
  234. package/dist/core/resource-loader-core.js.map +1 -1
  235. package/dist/core/resource-loader-internals.d.ts +2 -2
  236. package/dist/core/resource-loader-internals.js.map +1 -1
  237. package/dist/core/resource-loader-reload.d.ts +2 -0
  238. package/dist/core/resource-loader-reload.d.ts.map +1 -1
  239. package/dist/core/resource-loader-reload.js +231 -191
  240. package/dist/core/resource-loader-reload.js.map +1 -1
  241. package/dist/core/resource-loader-types.d.ts +4 -2
  242. package/dist/core/resource-loader-types.d.ts.map +1 -1
  243. package/dist/core/resource-loader-types.js.map +1 -1
  244. package/dist/core/retry-policy.d.ts +1 -0
  245. package/dist/core/retry-policy.d.ts.map +1 -1
  246. package/dist/core/retry-policy.js +2 -1
  247. package/dist/core/retry-policy.js.map +1 -1
  248. package/dist/core/sdk-exports.d.ts +2 -2
  249. package/dist/core/sdk-exports.js.map +1 -1
  250. package/dist/core/sdk-types.d.ts +2 -2
  251. package/dist/core/sdk-types.js.map +1 -1
  252. package/dist/core/sdk.js.map +1 -1
  253. package/dist/core/settings-manager-basic-accessors.d.ts +1 -0
  254. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  255. package/dist/core/settings-manager-basic-accessors.js +2 -0
  256. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  257. package/dist/core/settings-manager-core.d.ts.map +1 -1
  258. package/dist/core/settings-manager-core.js +10 -4
  259. package/dist/core/settings-manager-core.js.map +1 -1
  260. package/dist/core/settings-storage.d.ts +1 -0
  261. package/dist/core/settings-storage.d.ts.map +1 -1
  262. package/dist/core/settings-storage.js +18 -0
  263. package/dist/core/settings-storage.js.map +1 -1
  264. package/dist/core/settings-types.d.ts +12 -0
  265. package/dist/core/settings-types.d.ts.map +1 -1
  266. package/dist/core/settings-types.js.map +1 -1
  267. package/dist/core/slash-commands.d.ts.map +1 -1
  268. package/dist/core/slash-commands.js +2 -0
  269. package/dist/core/slash-commands.js.map +1 -1
  270. package/dist/core/system-prompt.d.ts.map +1 -1
  271. package/dist/core/system-prompt.js +5 -6
  272. package/dist/core/system-prompt.js.map +1 -1
  273. package/dist/core/tasks/agent-adapter.d.ts +41 -0
  274. package/dist/core/tasks/agent-adapter.d.ts.map +1 -0
  275. package/dist/core/tasks/agent-adapter.js +105 -0
  276. package/dist/core/tasks/agent-adapter.js.map +1 -0
  277. package/dist/core/tasks/command-output.d.ts +15 -0
  278. package/dist/core/tasks/command-output.d.ts.map +1 -0
  279. package/dist/core/tasks/command-output.js +29 -0
  280. package/dist/core/tasks/command-output.js.map +1 -0
  281. package/dist/core/tasks/completion-ordering.d.ts +11 -0
  282. package/dist/core/tasks/completion-ordering.d.ts.map +1 -0
  283. package/dist/core/tasks/completion-ordering.js +19 -0
  284. package/dist/core/tasks/completion-ordering.js.map +1 -0
  285. package/dist/core/tasks/completion.d.ts +36 -0
  286. package/dist/core/tasks/completion.d.ts.map +1 -0
  287. package/dist/core/tasks/completion.js +115 -0
  288. package/dist/core/tasks/completion.js.map +1 -0
  289. package/dist/core/tasks/contracts.d.ts +404 -0
  290. package/dist/core/tasks/contracts.d.ts.map +1 -0
  291. package/dist/core/tasks/contracts.js +2 -0
  292. package/dist/core/tasks/contracts.js.map +1 -0
  293. package/dist/core/tasks/execution-scope.d.ts +10 -0
  294. package/dist/core/tasks/execution-scope.d.ts.map +1 -0
  295. package/dist/core/tasks/execution-scope.js +27 -0
  296. package/dist/core/tasks/execution-scope.js.map +1 -0
  297. package/dist/core/tasks/owner-store.d.ts +53 -0
  298. package/dist/core/tasks/owner-store.d.ts.map +1 -0
  299. package/dist/core/tasks/owner-store.js +155 -0
  300. package/dist/core/tasks/owner-store.js.map +1 -0
  301. package/dist/core/tasks/pause.d.ts +4 -0
  302. package/dist/core/tasks/pause.d.ts.map +1 -0
  303. package/dist/core/tasks/pause.js +49 -0
  304. package/dist/core/tasks/pause.js.map +1 -0
  305. package/dist/core/tasks/supervisor.d.ts +123 -0
  306. package/dist/core/tasks/supervisor.d.ts.map +1 -0
  307. package/dist/core/tasks/supervisor.js +942 -0
  308. package/dist/core/tasks/supervisor.js.map +1 -0
  309. package/dist/core/tasks/transcript.d.ts +23 -0
  310. package/dist/core/tasks/transcript.d.ts.map +1 -0
  311. package/dist/core/tasks/transcript.js +74 -0
  312. package/dist/core/tasks/transcript.js.map +1 -0
  313. package/dist/core/tools/ask-user-question/ask-user-question.d.ts +2 -2
  314. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
  315. package/dist/core/tools/ask-user-question/ask-user-question.js +8 -4
  316. package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
  317. package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts +1 -1
  318. package/dist/core/tools/ask-user-question/state/build-questionnaire.js.map +1 -1
  319. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts +1 -1
  320. package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -1
  321. package/dist/core/tools/ask-user-question/view/components/multi-select-view.d.ts +1 -1
  322. package/dist/core/tools/ask-user-question/view/components/multi-select-view.js.map +1 -1
  323. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.d.ts +1 -1
  324. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.js.map +1 -1
  325. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts +1 -1
  326. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js.map +1 -1
  327. package/dist/core/tools/ask-user-question/view/components/submit-picker.d.ts +1 -1
  328. package/dist/core/tools/ask-user-question/view/components/submit-picker.js.map +1 -1
  329. package/dist/core/tools/ask-user-question/view/components/tab-bar.d.ts +1 -1
  330. package/dist/core/tools/ask-user-question/view/components/tab-bar.js.map +1 -1
  331. package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts +1 -1
  332. package/dist/core/tools/ask-user-question/view/dialog-builder.js.map +1 -1
  333. package/dist/core/tools/ask-user-question/view/tab-content-strategy.d.ts +1 -1
  334. package/dist/core/tools/ask-user-question/view/tab-content-strategy.js.map +1 -1
  335. package/dist/core/tools/bash-pty-native.d.ts +18 -3
  336. package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
  337. package/dist/core/tools/bash-pty-native.js +116 -1
  338. package/dist/core/tools/bash-pty-native.js.map +1 -1
  339. package/dist/core/tools/bash.d.ts +13 -4
  340. package/dist/core/tools/bash.d.ts.map +1 -1
  341. package/dist/core/tools/bash.js +53 -9
  342. package/dist/core/tools/bash.js.map +1 -1
  343. package/dist/core/tools/edit.d.ts.map +1 -1
  344. package/dist/core/tools/edit.js +1 -2
  345. package/dist/core/tools/edit.js.map +1 -1
  346. package/dist/core/tools/find.js.map +1 -1
  347. package/dist/core/tools/grep.js.map +1 -1
  348. package/dist/core/tools/index.d.ts +2 -2
  349. package/dist/core/tools/index.js.map +1 -1
  350. package/dist/core/tools/ls.js.map +1 -1
  351. package/dist/core/tools/powershell.d.ts +20 -10
  352. package/dist/core/tools/powershell.d.ts.map +1 -1
  353. package/dist/core/tools/powershell.js +33 -7
  354. package/dist/core/tools/powershell.js.map +1 -1
  355. package/dist/core/tools/read.d.ts.map +1 -1
  356. package/dist/core/tools/read.js +1 -2
  357. package/dist/core/tools/read.js.map +1 -1
  358. package/dist/core/tools/render-utils.d.ts +1 -1
  359. package/dist/core/tools/render-utils.js.map +1 -1
  360. package/dist/core/tools/resource-selectors.d.ts +1 -1
  361. package/dist/core/tools/resource-selectors.d.ts.map +1 -1
  362. package/dist/core/tools/resource-selectors.js +21 -10
  363. package/dist/core/tools/resource-selectors.js.map +1 -1
  364. package/dist/core/tools/search.js.map +1 -1
  365. package/dist/core/tools/todos-render.d.ts +1 -1
  366. package/dist/core/tools/todos-render.js.map +1 -1
  367. package/dist/core/tools/write.d.ts.map +1 -1
  368. package/dist/core/tools/write.js +1 -2
  369. package/dist/core/tools/write.js.map +1 -1
  370. package/dist/core/workflow-stage-admission.d.ts +10 -0
  371. package/dist/core/workflow-stage-admission.d.ts.map +1 -1
  372. package/dist/core/workflow-stage-admission.js +24 -0
  373. package/dist/core/workflow-stage-admission.js.map +1 -1
  374. package/dist/extensions/herdr/activity.d.ts +15 -0
  375. package/dist/extensions/herdr/activity.d.ts.map +1 -0
  376. package/dist/extensions/herdr/activity.js +24 -0
  377. package/dist/extensions/herdr/activity.js.map +1 -0
  378. package/dist/extensions/herdr/environment.d.ts +7 -0
  379. package/dist/extensions/herdr/environment.d.ts.map +1 -0
  380. package/dist/extensions/herdr/environment.js +6 -0
  381. package/dist/extensions/herdr/environment.js.map +1 -0
  382. package/dist/extensions/herdr/index.d.ts +9 -0
  383. package/dist/extensions/herdr/index.d.ts.map +1 -0
  384. package/dist/extensions/herdr/index.js +225 -0
  385. package/dist/extensions/herdr/index.js.map +1 -0
  386. package/dist/extensions/herdr/pane-owner.d.ts +30 -0
  387. package/dist/extensions/herdr/pane-owner.d.ts.map +1 -0
  388. package/dist/extensions/herdr/pane-owner.js +111 -0
  389. package/dist/extensions/herdr/pane-owner.js.map +1 -0
  390. package/dist/extensions/herdr/transport.d.ts +8 -0
  391. package/dist/extensions/herdr/transport.d.ts.map +1 -0
  392. package/dist/extensions/herdr/transport.js +28 -0
  393. package/dist/extensions/herdr/transport.js.map +1 -0
  394. package/dist/extensions/index.d.ts.map +1 -1
  395. package/dist/extensions/index.js +2 -0
  396. package/dist/extensions/index.js.map +1 -1
  397. package/dist/extensions/llama/huggingface-ui.d.ts +1 -1
  398. package/dist/extensions/llama/huggingface-ui.js.map +1 -1
  399. package/dist/extensions/llama/ui.js.map +1 -1
  400. package/dist/index-extensions.d.ts +3 -2
  401. package/dist/index-extensions.d.ts.map +1 -1
  402. package/dist/index-extensions.js.map +1 -1
  403. package/dist/index.d.ts +11 -3
  404. package/dist/index.d.ts.map +1 -1
  405. package/dist/index.js +8 -0
  406. package/dist/index.js.map +1 -1
  407. package/dist/main-session.js.map +1 -1
  408. package/dist/main.d.ts.map +1 -1
  409. package/dist/main.js +149 -69
  410. package/dist/main.js.map +1 -1
  411. package/dist/modes/interactive/components/armin.js.map +1 -1
  412. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  413. package/dist/modes/interactive/components/atomic-banner.d.ts +1 -1
  414. package/dist/modes/interactive/components/atomic-banner.js.map +1 -1
  415. package/dist/modes/interactive/components/atomic-working-status.js.map +1 -1
  416. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  417. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
  418. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  419. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  420. package/dist/modes/interactive/components/chat-message-renderer.d.ts +12 -0
  421. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  422. package/dist/modes/interactive/components/chat-message-renderer.js +44 -0
  423. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  424. package/dist/modes/interactive/components/chat-session-host-actions.d.ts +1 -1
  425. package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
  426. package/dist/modes/interactive/components/chat-session-host-actions.js +43 -8
  427. package/dist/modes/interactive/components/chat-session-host-actions.js.map +1 -1
  428. package/dist/modes/interactive/components/chat-session-host-editor.d.ts +1 -1
  429. package/dist/modes/interactive/components/chat-session-host-editor.js.map +1 -1
  430. package/dist/modes/interactive/components/chat-session-host-events.d.ts +2 -2
  431. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  432. package/dist/modes/interactive/components/chat-session-host-rendering.d.ts +2 -2
  433. package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
  434. package/dist/modes/interactive/components/chat-session-host-rendering.js +12 -3
  435. package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
  436. package/dist/modes/interactive/components/chat-session-host-runtime.d.ts +4 -5
  437. package/dist/modes/interactive/components/chat-session-host-runtime.d.ts.map +1 -1
  438. package/dist/modes/interactive/components/chat-session-host-runtime.js +8 -6
  439. package/dist/modes/interactive/components/chat-session-host-runtime.js.map +1 -1
  440. package/dist/modes/interactive/components/chat-session-host-state.d.ts +7 -2
  441. package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
  442. package/dist/modes/interactive/components/chat-session-host-state.js +1 -0
  443. package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
  444. package/dist/modes/interactive/components/chat-session-host-terminal-cleanup.d.ts +1 -1
  445. package/dist/modes/interactive/components/chat-session-host-terminal-cleanup.js.map +1 -1
  446. package/dist/modes/interactive/components/chat-session-host-types.d.ts +8 -3
  447. package/dist/modes/interactive/components/chat-session-host-types.d.ts.map +1 -1
  448. package/dist/modes/interactive/components/chat-session-host-types.js.map +1 -1
  449. package/dist/modes/interactive/components/chat-session-host-utils.d.ts +1 -1
  450. package/dist/modes/interactive/components/chat-session-host-utils.d.ts.map +1 -1
  451. package/dist/modes/interactive/components/chat-session-host-utils.js +2 -0
  452. package/dist/modes/interactive/components/chat-session-host-utils.js.map +1 -1
  453. package/dist/modes/interactive/components/chat-session-host.d.ts +17 -2
  454. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  455. package/dist/modes/interactive/components/chat-session-host.js +100 -3
  456. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  457. package/dist/modes/interactive/components/chat-transcript.d.ts +1 -0
  458. package/dist/modes/interactive/components/chat-transcript.d.ts.map +1 -1
  459. package/dist/modes/interactive/components/chat-transcript.js +1 -1
  460. package/dist/modes/interactive/components/chat-transcript.js.map +1 -1
  461. package/dist/modes/interactive/components/compaction-boundary-message.js.map +1 -1
  462. package/dist/modes/interactive/components/config-selector-list.js.map +1 -1
  463. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  464. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  465. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  466. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  467. package/dist/modes/interactive/components/custom-message.js +12 -0
  468. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  469. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  470. package/dist/modes/interactive/components/diff.js.map +1 -1
  471. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  472. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  473. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  474. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  475. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  476. package/dist/modes/interactive/components/first-time-setup.d.ts +1 -1
  477. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  478. package/dist/modes/interactive/components/footer.d.ts +7 -6
  479. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  480. package/dist/modes/interactive/components/footer.js +27 -9
  481. package/dist/modes/interactive/components/footer.js.map +1 -1
  482. package/dist/modes/interactive/components/host-input-form-mount.js.map +1 -1
  483. package/dist/modes/interactive/components/host-input-form.d.ts +1 -1
  484. package/dist/modes/interactive/components/host-input-form.js.map +1 -1
  485. package/dist/modes/interactive/components/index.d.ts +2 -2
  486. package/dist/modes/interactive/components/index.js.map +1 -1
  487. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  488. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  489. package/dist/modes/interactive/components/mermaid.d.ts +1 -1
  490. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  491. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  492. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  493. package/dist/modes/interactive/components/reserved-bottom-overlay.js.map +1 -1
  494. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  495. package/dist/modes/interactive/components/session-selector-header.js.map +1 -1
  496. package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
  497. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  498. package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
  499. package/dist/modes/interactive/components/settings-selector-submenus.d.ts +1 -1
  500. package/dist/modes/interactive/components/settings-selector-submenus.js.map +1 -1
  501. package/dist/modes/interactive/components/settings-selector-types.d.ts +1 -1
  502. package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
  503. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  504. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  505. package/dist/modes/interactive/components/skill-invocation-message.d.ts +1 -1
  506. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  507. package/dist/modes/interactive/components/task-completion-message.d.ts +13 -0
  508. package/dist/modes/interactive/components/task-completion-message.d.ts.map +1 -0
  509. package/dist/modes/interactive/components/task-completion-message.js +65 -0
  510. package/dist/modes/interactive/components/task-completion-message.js.map +1 -0
  511. package/dist/modes/interactive/components/task-detail.d.ts +27 -0
  512. package/dist/modes/interactive/components/task-detail.d.ts.map +1 -0
  513. package/dist/modes/interactive/components/task-detail.js +107 -0
  514. package/dist/modes/interactive/components/task-detail.js.map +1 -0
  515. package/dist/modes/interactive/components/task-inspector.d.ts +50 -0
  516. package/dist/modes/interactive/components/task-inspector.d.ts.map +1 -0
  517. package/dist/modes/interactive/components/task-inspector.js +599 -0
  518. package/dist/modes/interactive/components/task-inspector.js.map +1 -0
  519. package/dist/modes/interactive/components/task-list.d.ts +18 -0
  520. package/dist/modes/interactive/components/task-list.d.ts.map +1 -0
  521. package/dist/modes/interactive/components/task-list.js +59 -0
  522. package/dist/modes/interactive/components/task-list.js.map +1 -0
  523. package/dist/modes/interactive/components/task-live-transcript.d.ts +17 -0
  524. package/dist/modes/interactive/components/task-live-transcript.d.ts.map +1 -0
  525. package/dist/modes/interactive/components/task-live-transcript.js +33 -0
  526. package/dist/modes/interactive/components/task-live-transcript.js.map +1 -0
  527. package/dist/modes/interactive/components/task-navigation.d.ts +38 -0
  528. package/dist/modes/interactive/components/task-navigation.d.ts.map +1 -0
  529. package/dist/modes/interactive/components/task-navigation.js +93 -0
  530. package/dist/modes/interactive/components/task-navigation.js.map +1 -0
  531. package/dist/modes/interactive/components/task-row.d.ts +34 -0
  532. package/dist/modes/interactive/components/task-row.d.ts.map +1 -0
  533. package/dist/modes/interactive/components/task-row.js +158 -0
  534. package/dist/modes/interactive/components/task-row.js.map +1 -0
  535. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  536. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  537. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  538. package/dist/modes/interactive/components/transcript-follow-indicator.js.map +1 -1
  539. package/dist/modes/interactive/components/tree-selector-component.js.map +1 -1
  540. package/dist/modes/interactive/components/tree-selector-content.js.map +1 -1
  541. package/dist/modes/interactive/components/tree-selector-help.js.map +1 -1
  542. package/dist/modes/interactive/components/tree-selector-label-input.js.map +1 -1
  543. package/dist/modes/interactive/components/tree-selector-list.js.map +1 -1
  544. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  545. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  546. package/dist/modes/interactive/components/user-message.js.map +1 -1
  547. package/dist/modes/interactive/components/working-status.js.map +1 -1
  548. package/dist/modes/interactive/interactive-agent-events.js +8 -2
  549. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  550. package/dist/modes/interactive/interactive-auth-login.js +3 -1
  551. package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
  552. package/dist/modes/interactive/interactive-autocomplete.js +9 -30
  553. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  554. package/dist/modes/interactive/interactive-deferred-startup.js +2 -1
  555. package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
  556. package/dist/modes/interactive/interactive-extension-context.js +14 -4
  557. package/dist/modes/interactive/interactive-extension-context.js.map +1 -1
  558. package/dist/modes/interactive/interactive-extension-custom-ui.js +52 -4
  559. package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
  560. package/dist/modes/interactive/interactive-extension-runtime.js +1 -0
  561. package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
  562. package/dist/modes/interactive/interactive-extension-widgets.js +9 -1
  563. package/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  564. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  565. package/dist/modes/interactive/interactive-input-handling.js +19 -0
  566. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  567. package/dist/modes/interactive/interactive-mode-base.d.ts +6 -1
  568. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  569. package/dist/modes/interactive/interactive-mode-base.js +4 -1
  570. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  571. package/dist/modes/interactive/interactive-mode-deps.d.ts +6 -6
  572. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  573. package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -1
  574. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  575. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  576. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  577. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  578. package/dist/modes/interactive/interactive-mode.js +3 -0
  579. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  580. package/dist/modes/interactive/interactive-process-lifecycle.js +4 -1
  581. package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
  582. package/dist/modes/interactive/interactive-render-chat.js +2 -0
  583. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  584. package/dist/modes/interactive/interactive-session-routing.js +33 -23
  585. package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
  586. package/dist/modes/interactive/interactive-session-runtime.js +1 -0
  587. package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
  588. package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
  589. package/dist/modes/interactive/interactive-summarization-retry-events.js +2 -2
  590. package/dist/modes/interactive/interactive-summarization-retry-events.js.map +1 -1
  591. package/dist/modes/interactive/interactive-task-projection.d.ts +13 -0
  592. package/dist/modes/interactive/interactive-task-projection.d.ts.map +1 -0
  593. package/dist/modes/interactive/interactive-task-projection.js +72 -0
  594. package/dist/modes/interactive/interactive-task-projection.js.map +1 -0
  595. package/dist/modes/interactive/interactive-tui.js.map +1 -1
  596. package/dist/modes/interactive/interactive-windows-subshell.d.ts +17 -0
  597. package/dist/modes/interactive/interactive-windows-subshell.d.ts.map +1 -0
  598. package/dist/modes/interactive/interactive-windows-subshell.js +92 -0
  599. package/dist/modes/interactive/interactive-windows-subshell.js.map +1 -0
  600. package/dist/modes/interactive/skill-command-autocomplete.d.ts +12 -0
  601. package/dist/modes/interactive/skill-command-autocomplete.d.ts.map +1 -0
  602. package/dist/modes/interactive/skill-command-autocomplete.js +69 -0
  603. package/dist/modes/interactive/skill-command-autocomplete.js.map +1 -0
  604. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  605. package/dist/modes/interactive/theme/theme-class.js +4 -1
  606. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  607. package/dist/modes/interactive/theme/theme-controller.d.ts +1 -1
  608. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  609. package/dist/modes/interactive-engine/create-isolated-runtime.d.ts +1 -1
  610. package/dist/modes/interactive-engine/create-isolated-runtime.js.map +1 -1
  611. package/dist/modes/interactive-engine/engine-custom-ui.d.ts +5 -9
  612. package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
  613. package/dist/modes/interactive-engine/engine-custom-ui.js +14 -5
  614. package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
  615. package/dist/modes/interactive-engine/engine-dialog-host.d.ts +2 -2
  616. package/dist/modes/interactive-engine/engine-dialog-host.js.map +1 -1
  617. package/dist/modes/interactive-engine/engine-project-trust.d.ts +10 -0
  618. package/dist/modes/interactive-engine/engine-project-trust.d.ts.map +1 -0
  619. package/dist/modes/interactive-engine/engine-project-trust.js +28 -0
  620. package/dist/modes/interactive-engine/engine-project-trust.js.map +1 -0
  621. package/dist/modes/interactive-engine/engine-render-service.d.ts +1 -1
  622. package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
  623. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts +3 -1
  624. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts.map +1 -1
  625. package/dist/modes/interactive-engine/extension-ui-bridge.js +6 -0
  626. package/dist/modes/interactive-engine/extension-ui-bridge.js.map +1 -1
  627. package/dist/modes/interactive-engine/input-form-host.d.ts +2 -2
  628. package/dist/modes/interactive-engine/input-form-host.js.map +1 -1
  629. package/dist/modes/interactive-engine/isolated-auth.d.ts +1 -1
  630. package/dist/modes/interactive-engine/isolated-auth.js.map +1 -1
  631. package/dist/modes/interactive-engine/isolated-runtime.d.ts +5 -2
  632. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  633. package/dist/modes/interactive-engine/isolated-runtime.js +40 -3
  634. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  635. package/dist/modes/interactive-engine/protocol.d.ts +9 -0
  636. package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
  637. package/dist/modes/interactive-engine/protocol.js +8 -0
  638. package/dist/modes/interactive-engine/protocol.js.map +1 -1
  639. package/dist/modes/interactive-engine/remote-component.d.ts +2 -2
  640. package/dist/modes/interactive-engine/remote-component.d.ts.map +1 -1
  641. package/dist/modes/interactive-engine/remote-component.js +3 -2
  642. package/dist/modes/interactive-engine/remote-component.js.map +1 -1
  643. package/dist/modes/interactive-engine/remote-model-catalog.d.ts +1 -1
  644. package/dist/modes/interactive-engine/remote-model-catalog.js.map +1 -1
  645. package/dist/modes/interactive-engine/remote-renderer.d.ts +1 -1
  646. package/dist/modes/interactive-engine/remote-renderer.js.map +1 -1
  647. package/dist/modes/interactive-engine/session-picker-host.d.ts +2 -2
  648. package/dist/modes/interactive-engine/session-picker-host.js.map +1 -1
  649. package/dist/modes/json-event.d.ts +1 -1
  650. package/dist/modes/json-event.js.map +1 -1
  651. package/dist/modes/print-mode.js.map +1 -1
  652. package/dist/modes/rpc/rpc-bash-request-owners.d.ts +2 -2
  653. package/dist/modes/rpc/rpc-bash-request-owners.js.map +1 -1
  654. package/dist/modes/rpc/rpc-client-api.d.ts +2 -2
  655. package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
  656. package/dist/modes/rpc/rpc-client-api.js +2 -2
  657. package/dist/modes/rpc/rpc-client-api.js.map +1 -1
  658. package/dist/modes/rpc/rpc-client-waits.d.ts +1 -1
  659. package/dist/modes/rpc/rpc-client-waits.js.map +1 -1
  660. package/dist/modes/rpc/rpc-client.d.ts +3 -1
  661. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  662. package/dist/modes/rpc/rpc-client.js +20 -0
  663. package/dist/modes/rpc/rpc-client.js.map +1 -1
  664. package/dist/modes/rpc/rpc-command-handler.d.ts +4 -2
  665. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  666. package/dist/modes/rpc/rpc-command-handler.js +12 -4
  667. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  668. package/dist/modes/rpc/rpc-extension-ui.d.ts +1 -1
  669. package/dist/modes/rpc/rpc-extension-ui.js.map +1 -1
  670. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  671. package/dist/modes/rpc/rpc-mode.js +11 -2
  672. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  673. package/dist/modes/rpc/rpc-provider-auth.d.ts +1 -1
  674. package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
  675. package/dist/modes/rpc/rpc-session-binding.d.ts +4 -1
  676. package/dist/modes/rpc/rpc-session-binding.d.ts.map +1 -1
  677. package/dist/modes/rpc/rpc-session-binding.js +35 -1
  678. package/dist/modes/rpc/rpc-session-binding.js.map +1 -1
  679. package/dist/modes/rpc/rpc-types.d.ts +13 -1
  680. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  681. package/dist/modes/rpc/rpc-types.js.map +1 -1
  682. package/dist/modes/rpc/task-ui-bridge.d.ts +9 -0
  683. package/dist/modes/rpc/task-ui-bridge.d.ts.map +1 -0
  684. package/dist/modes/rpc/task-ui-bridge.js +146 -0
  685. package/dist/modes/rpc/task-ui-bridge.js.map +1 -0
  686. package/dist/self-update-plan.js.map +1 -1
  687. package/docs/background-tasks.md +205 -0
  688. package/docs/compaction.md +2 -0
  689. package/docs/development.md +23 -72
  690. package/docs/docs.json +2 -0
  691. package/docs/environment-variables.md +1 -1
  692. package/docs/extensions.md +112 -6
  693. package/docs/herdr.md +53 -0
  694. package/docs/intercom.md +42 -35
  695. package/docs/keybindings.md +19 -2
  696. package/docs/models/evals.md +224 -147
  697. package/docs/models/model-selection.md +28 -19
  698. package/docs/models/pareto-efficiency.md +2 -2
  699. package/docs/providers.md +48 -46
  700. package/docs/quickstart.md +1 -1
  701. package/docs/sdk.md +244 -0
  702. package/docs/settings.md +19 -3
  703. package/docs/skills.md +23 -1
  704. package/docs/subagents.md +74 -10
  705. package/docs/themes.md +4 -0
  706. package/docs/tools.md +29 -0
  707. package/docs/tui.md +29 -2
  708. package/docs/usage.md +4 -0
  709. package/docs/windows.md +4 -4
  710. package/docs/workflows/api-reference.md +14 -5
  711. package/docs/workflows/operations.md +49 -3
  712. package/docs/workflows/reliable-design.md +35 -4
  713. package/docs/workflows/verification.md +21 -4
  714. package/docs/workflows.md +3 -1
  715. package/npm-shrinkwrap.json +797 -677
  716. package/package.json +10 -10
  717. /package/dist/builtin/workflows/builtin/{chunk-cg9tmks0.js → chunk-n1910xc4.js} +0 -0
  718. /package/dist/builtin/workflows/builtin/{chunk-wpckd35c.js → chunk-rc5ec5xx.js} +0 -0
  719. /package/dist/builtin/workflows/builtin/{chunk-7at6dnkr.js → chunk-tgt0s5e5.js} +0 -0
  720. /package/dist/builtin/workflows/builtin/{chunk-bfkmzv9h.js → chunk-xtxcq5tj.js} +0 -0
@@ -12,7 +12,17 @@ var __export = (target, all) => {
12
12
  set: __exportSetter.bind(all, name)
13
13
  });
14
14
  };
15
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
15
+ var __esm = (fn, res, err) => () => {
16
+ if (fn)
17
+ try {
18
+ res = fn(fn = 0);
19
+ } catch (e) {
20
+ err = [e];
21
+ }
22
+ if (err)
23
+ throw err[0];
24
+ return res;
25
+ };
16
26
 
17
27
  // dist/builtin/intercom/result-renderers.ts
18
28
  import { Text } from "@earendil-works/pi-tui";
@@ -80,7 +90,7 @@ function isRecoverableIntercomDisconnect(error) {
80
90
  }
81
91
  return false;
82
92
  }
83
- var RECOVERABLE_DISCONNECT_MESSAGE = "Client disconnected. Retry the same Intercom call up to three times to reconnect.", MAX_CAUSE_DEPTH = 8, IntercomClientDisconnectedError;
93
+ var RECOVERABLE_DISCONNECT_MESSAGE = "Client disconnected", MAX_CAUSE_DEPTH = 8, IntercomClientDisconnectedError;
84
94
  var init_recoverable_disconnect = __esm(() => {
85
95
  IntercomClientDisconnectedError = class IntercomClientDisconnectedError extends Error {
86
96
  intercomRecoverableDisconnect = true;
@@ -91,6 +101,16 @@ var init_recoverable_disconnect = __esm(() => {
91
101
  };
92
102
  });
93
103
 
104
+ // dist/builtin/intercom/retry-policy.ts
105
+ var ASK_REPLY_TIMEOUT_MS, RETRY_IDENTITY_RETRY_OPPORTUNITY_MS, RETRY_IDENTITY_TTL_MS, DELIVERED_MESSAGE_TTL_MS, RECONNECT_DELAYS_MS;
106
+ var init_retry_policy = __esm(() => {
107
+ ASK_REPLY_TIMEOUT_MS = 10 * 60 * 1000;
108
+ RETRY_IDENTITY_RETRY_OPPORTUNITY_MS = 60 * 1000;
109
+ RETRY_IDENTITY_TTL_MS = ASK_REPLY_TIMEOUT_MS + RETRY_IDENTITY_RETRY_OPPORTUNITY_MS;
110
+ DELIVERED_MESSAGE_TTL_MS = RETRY_IDENTITY_TTL_MS + RETRY_IDENTITY_RETRY_OPPORTUNITY_MS;
111
+ RECONNECT_DELAYS_MS = [1000, 2000, 5000];
112
+ });
113
+
94
114
  // dist/builtin/intercom/reconnect-backoff.ts
95
115
  function reconnectDelayMs(attempt) {
96
116
  return BACKOFF_MS[Math.min(attempt, BACKOFF_MS.length - 1)];
@@ -100,6 +120,37 @@ var init_reconnect_backoff = __esm(() => {
100
120
  BACKOFF_MS = [1000, 2000, 5000, 1e4, 30000];
101
121
  });
102
122
 
123
+ // dist/builtin/intercom/subagent-reply-capability.ts
124
+ function registerSubagentReplyCapability(pi, client) {
125
+ let signal;
126
+ let unbind;
127
+ const capability = () => {
128
+ if (!signal)
129
+ return;
130
+ return signal.aborted ? "terminal" : "live";
131
+ };
132
+ pi.on("session_start", (_event, ctx) => {
133
+ unbind?.();
134
+ signal = ctx.subagentPolicy?.executionEnded;
135
+ const current = signal;
136
+ const terminal = () => {
137
+ if (signal !== current)
138
+ return;
139
+ client()?.updatePresence({ replyCapability: "terminal" });
140
+ };
141
+ current?.addEventListener("abort", terminal, { once: true });
142
+ unbind = () => current?.removeEventListener("abort", terminal);
143
+ if (current?.aborted)
144
+ terminal();
145
+ });
146
+ pi.on("session_shutdown", () => {
147
+ unbind?.();
148
+ unbind = undefined;
149
+ signal = undefined;
150
+ });
151
+ return capability;
152
+ }
153
+
103
154
  // dist/builtin/intercom/broker/framing.ts
104
155
  function writeMessage(socket, msg, callback) {
105
156
  const json = JSON.stringify(msg);
@@ -472,6 +523,7 @@ var init_client = __esm(() => {
472
523
  _supervisorSessionId = null;
473
524
  _messageSource;
474
525
  pendingSends = new PendingSendRegistry;
526
+ pendingReplyTargets = new Map;
475
527
  pendingGroupLists = new Map;
476
528
  pendingLists = new Map;
477
529
  pendingPresence = new Map;
@@ -679,6 +731,16 @@ var init_client = __esm(() => {
679
731
  this.emit("_registration_failed", new Error(brokerMessage.reason));
680
732
  break;
681
733
  }
734
+ case "question_target": {
735
+ const { messageId, attemptId, sessionId } = brokerMessage;
736
+ if (typeof messageId !== "string" || typeof attemptId !== "string" || typeof sessionId !== "string") {
737
+ throw new Error("Invalid question_target message");
738
+ }
739
+ const pending = this.pendingReplyTargets.get(attemptId);
740
+ if (pending?.messageId === messageId)
741
+ pending.bind(sessionId);
742
+ break;
743
+ }
682
744
  case "sessions": {
683
745
  const { requestId, sessions, workflowStages, workflowFutureStages } = brokerMessage;
684
746
  if (typeof requestId !== "string" || !Array.isArray(sessions) || !sessions.every(isSessionInfo) || workflowStages !== undefined && !isWorkflowStageRosterEntries(workflowStages) || workflowFutureStages !== undefined && !isWorkflowFutureStageRosterEntries(workflowFutureStages)) {
@@ -1096,14 +1158,15 @@ var init_client = __esm(() => {
1096
1158
  }
1097
1159
  });
1098
1160
  }
1099
- registerPendingStageRoute(runId, group, capability, stages, possibleStages) {
1161
+ registerPendingStageRoute(runId, group, capability, stages, possibleStages, parent) {
1100
1162
  writeMessage(this.requireActiveSocket(), {
1101
1163
  type: "register_pending_stage_route",
1102
1164
  runId,
1103
1165
  group,
1104
1166
  capability,
1105
1167
  stages,
1106
- possibleStages
1168
+ possibleStages,
1169
+ ...parent === undefined ? {} : { parent }
1107
1170
  });
1108
1171
  }
1109
1172
  registerLiveWorkflowStageRoute(runId, stageKeys, capability) {
@@ -1194,12 +1257,16 @@ var init_client = __esm(() => {
1194
1257
  source: this._messageSource,
1195
1258
  content: { text: options.text, attachments: options.attachments }
1196
1259
  };
1260
+ if (options.onReplyTarget !== undefined) {
1261
+ this.pendingReplyTargets.set(acquired.attempt.attemptId, { messageId, bind: options.onReplyTarget });
1262
+ }
1197
1263
  try {
1198
1264
  writeMessage(socket, {
1199
1265
  type,
1200
1266
  to,
1201
1267
  ...options.logicalTarget === undefined ? {} : { logicalTarget: options.logicalTarget },
1202
1268
  ...options.requirePendingReply === undefined ? {} : { requirePendingReply: options.requirePendingReply },
1269
+ ...options.onReplyTarget === undefined ? {} : { resolveReplyTarget: true },
1203
1270
  message,
1204
1271
  attemptId: acquired.attempt.attemptId,
1205
1272
  ...extra
@@ -1207,6 +1274,10 @@ var init_client = __esm(() => {
1207
1274
  } catch (error) {
1208
1275
  this.pendingSends.reject(acquired.attempt, toError(error));
1209
1276
  }
1277
+ const clearReplyTarget = () => {
1278
+ this.pendingReplyTargets.delete(acquired.attempt.attemptId);
1279
+ };
1280
+ acquired.attempt.promise.then(clearReplyTarget, clearReplyTarget);
1210
1281
  return acquired.attempt.promise;
1211
1282
  }
1212
1283
  updatePresence(updates) {
@@ -1676,15 +1747,6 @@ class InlineMessageComponent {
1676
1747
  }
1677
1748
  var init_inline_message = () => {};
1678
1749
 
1679
- // dist/builtin/intercom/retry-policy.ts
1680
- var ASK_REPLY_TIMEOUT_MS, RETRY_IDENTITY_RETRY_OPPORTUNITY_MS, RETRY_IDENTITY_TTL_MS, DELIVERED_MESSAGE_TTL_MS;
1681
- var init_retry_policy = __esm(() => {
1682
- ASK_REPLY_TIMEOUT_MS = 10 * 60 * 1000;
1683
- RETRY_IDENTITY_RETRY_OPPORTUNITY_MS = 60 * 1000;
1684
- RETRY_IDENTITY_TTL_MS = ASK_REPLY_TIMEOUT_MS + RETRY_IDENTITY_RETRY_OPPORTUNITY_MS;
1685
- DELIVERED_MESSAGE_TTL_MS = RETRY_IDENTITY_TTL_MS + RETRY_IDENTITY_RETRY_OPPORTUNITY_MS;
1686
- });
1687
-
1688
1750
  // dist/builtin/intercom/reply-waiter.ts
1689
1751
  class ReplyWaiterRegistry {
1690
1752
  timeoutMs;
@@ -1756,6 +1818,10 @@ class ReplyWaiterRegistry {
1756
1818
  ok: true,
1757
1819
  wait: {
1758
1820
  promise,
1821
+ bindSender: (sender) => {
1822
+ if (this.waiters.get(replyTo) === record)
1823
+ record.from = sender;
1824
+ },
1759
1825
  cancel: (error) => record.reject(error)
1760
1826
  }
1761
1827
  };
@@ -2264,32 +2330,32 @@ function validateSupervisorInterviewReply(value, interview) {
2264
2330
  if (!Object.hasOwn(raw, "value")) {
2265
2331
  throw new Error(`responses[${index}].value is required`);
2266
2332
  }
2267
- const value2 = raw.value;
2333
+ const value = raw.value;
2268
2334
  if (question.type === "single") {
2269
- if (typeof value2 !== "string")
2335
+ if (typeof value !== "string")
2270
2336
  throw new Error(`responses[${index}].value must be a string for single questions`);
2271
2337
  const optionLabels = new Set(question.options?.map(interviewOptionLabel));
2272
- if (!optionLabels.has(value2.trim()))
2338
+ if (!optionLabels.has(value.trim()))
2273
2339
  throw new Error(`responses[${index}].value must match one of the question options`);
2274
- responses.push({ id, value: value2.trim() });
2340
+ responses.push({ id, value: value.trim() });
2275
2341
  continue;
2276
2342
  }
2277
2343
  if (question.type === "multi") {
2278
- if (!Array.isArray(value2) || value2.some((item) => typeof item !== "string")) {
2344
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
2279
2345
  throw new Error(`responses[${index}].value must be an array of strings for multi questions`);
2280
2346
  }
2281
2347
  const optionLabels = new Set(question.options?.map(interviewOptionLabel));
2282
- const selected = value2.map((item) => item.trim());
2348
+ const selected = value.map((item) => item.trim());
2283
2349
  const invalid = selected.find((item) => !optionLabels.has(item));
2284
2350
  if (invalid)
2285
2351
  throw new Error(`responses[${index}].value contains an option that is not in the question options: ${invalid}`);
2286
2352
  responses.push({ id, value: selected });
2287
2353
  continue;
2288
2354
  }
2289
- if (typeof value2 !== "string") {
2355
+ if (typeof value !== "string") {
2290
2356
  throw new Error(`responses[${index}].value must be a string for ${question.type} questions`);
2291
2357
  }
2292
- responses.push({ id, value: value2 });
2358
+ responses.push({ id, value });
2293
2359
  }
2294
2360
  return { responses };
2295
2361
  }
@@ -2371,7 +2437,8 @@ function formatSessionListRow(session, currentCwd, isSelf) {
2371
2437
  const name = session.name || "Unnamed session";
2372
2438
  const normalizedGroup = normalizeGroup(session.group);
2373
2439
  const groupTag = normalizedGroup !== DEFAULT_GROUP ? `group: ${normalizedGroup}` : undefined;
2374
- const tags = [isSelf ? "self" : session.cwd === currentCwd ? "same cwd" : undefined, session.status, groupTag].filter((tag) => Boolean(tag));
2440
+ const capabilityTag = session.replyCapability === undefined ? undefined : `replyCapability: ${session.replyCapability}`;
2441
+ const tags = [isSelf ? "self" : session.cwd === currentCwd ? "same cwd" : undefined, session.status, capabilityTag, groupTag].filter((tag) => Boolean(tag));
2375
2442
  const suffix = tags.length ? ` [${tags.join(", ")}]` : "";
2376
2443
  return `• ${name} (${session.id}) — ${session.cwd} (${session.model})${suffix}`;
2377
2444
  }
@@ -2395,7 +2462,7 @@ import { randomUUID as randomUUID3 } from "crypto";
2395
2462
  import { Type } from "typebox";
2396
2463
  import { Text as Text2 } from "@earendil-works/pi-tui";
2397
2464
  function registerContactSupervisorTool(pi, deps) {
2398
- const { childOrchestratorMetadata, ensureConnected, syncPresenceIdentity, resolveSessionTarget: resolveSessionTarget2, beginReplyWait } = deps;
2465
+ const { childOrchestratorMetadata, ensureConnected, syncPresenceIdentity, resolveSessionTarget, beginReplyWait } = deps;
2399
2466
  const getMetadata = typeof childOrchestratorMetadata === "function" ? childOrchestratorMetadata : () => childOrchestratorMetadata;
2400
2467
  let supervisorWaitActive = false;
2401
2468
  let supervisorHandoffClaimed = false;
@@ -2508,13 +2575,6 @@ function registerContactSupervisorTool(pi, deps) {
2508
2575
  details: { yielded: true }
2509
2576
  };
2510
2577
  }
2511
- if (reason === "need_decision" && typeof params.message !== "string") {
2512
- return {
2513
- content: [{ type: "text", text: `Missing 'message' parameter for reason '${reason}'.` }],
2514
- isError: true,
2515
- details: { error: true }
2516
- };
2517
- }
2518
2578
  let connectedClient;
2519
2579
  try {
2520
2580
  connectedClient = await ensureConnected("tool");
@@ -2538,7 +2598,7 @@ function registerContactSupervisorTool(pi, deps) {
2538
2598
  sendTo = connectedClient.supervisorSessionId ?? metadata.supervisor.supervisorSessionId;
2539
2599
  } else {
2540
2600
  try {
2541
- sendTo = await resolveSessionTarget2(connectedClient, metadata.orchestratorTarget) ?? metadata.orchestratorTarget;
2601
+ sendTo = await resolveSessionTarget(connectedClient, metadata.orchestratorTarget) ?? metadata.orchestratorTarget;
2542
2602
  } catch (error) {
2543
2603
  return {
2544
2604
  content: [{ type: "text", text: `Failed to resolve supervisor target: ${getErrorMessage(error)}` }],
@@ -2607,7 +2667,7 @@ function registerContactSupervisorTool(pi, deps) {
2607
2667
  };
2608
2668
  }
2609
2669
  wait = admission.wait;
2610
- const requestText = reason === "interview_request" ? formatChildOrchestratorMessage("interview", metadata, formatSupervisorInterviewRequest(supervisorInterview, typeof params.message === "string" ? params.message : undefined)) : formatChildOrchestratorMessage("ask", metadata, params.message);
2670
+ const requestText = reason === "interview_request" ? formatChildOrchestratorMessage("interview", metadata, formatSupervisorInterviewRequest(supervisorInterview, typeof params.message === "string" ? params.message : undefined)) : formatChildOrchestratorMessage("ask", metadata, typeof params.message === "string" ? params.message : "");
2611
2671
  const sendResult = await connectedClient.sendToSupervisor(sendTo, {
2612
2672
  messageId: questionId,
2613
2673
  text: requestText,
@@ -2808,6 +2868,11 @@ class RetryIdentityReservations {
2808
2868
  }
2809
2869
  this.finishRetained(reservation, "settled");
2810
2870
  }
2871
+ discard(retryToken) {
2872
+ const reservation = this.tokenReservations.get(retryToken);
2873
+ if (reservation !== undefined)
2874
+ this.expire(reservation);
2875
+ }
2811
2876
  remainingRetries(attempt) {
2812
2877
  const reservation = this.currentReservation(attempt);
2813
2878
  return reservation === undefined ? 0 : Math.max(0, this.maxReuses - reservation.reuseCount);
@@ -2961,14 +3026,73 @@ var init_retry_identity = __esm(() => {
2961
3026
  };
2962
3027
  });
2963
3028
 
3029
+ // dist/builtin/intercom/tool-retry.ts
3030
+ import { setTimeout as delay2 } from "node:timers/promises";
3031
+ async function runIntercomOperation(attempt, release, signal) {
3032
+ const deadline = new AbortController;
3033
+ const timer = setTimeout(() => deadline.abort(), RETRY_IDENTITY_TTL_MS);
3034
+ const operationSignal = signal === undefined ? deadline.signal : AbortSignal.any([signal, deadline.signal]);
3035
+ let token;
3036
+ let recovering = false;
3037
+ let retries = 0;
3038
+ let last = {
3039
+ content: [{ type: "text", text: "Cancelled" }],
3040
+ isError: true,
3041
+ details: { error: true }
3042
+ };
3043
+ try {
3044
+ for (;; ) {
3045
+ if (operationSignal.aborted)
3046
+ break;
3047
+ last = await attempt(token, operationSignal);
3048
+ const { retryToken, retryable, deliveryUncertain, ...details } = last.details;
3049
+ last = { ...last, details };
3050
+ if (!last.isError)
3051
+ return last;
3052
+ recovering ||= deliveryUncertain === true || retryable === true;
3053
+ const nextToken = typeof retryToken === "string" ? retryToken : undefined;
3054
+ const canRetry = nextToken !== undefined || token === undefined && retryable === true;
3055
+ token = nextToken ?? token;
3056
+ if (!canRetry) {
3057
+ if (!recovering && retryable !== true)
3058
+ return last;
3059
+ break;
3060
+ }
3061
+ recovering = true;
3062
+ if (retries >= RETRY_IDENTITY_MAX_REUSES || operationSignal.aborted)
3063
+ break;
3064
+ try {
3065
+ await delay2(RECONNECT_DELAYS_MS[retries], undefined, { signal: operationSignal });
3066
+ } catch {
3067
+ break;
3068
+ }
3069
+ retries += 1;
3070
+ }
3071
+ const reason = operationSignal.aborted ? "Cancelled" : last.content.map(({ text }) => text).join(`
3072
+ `);
3073
+ return {
3074
+ content: [{
3075
+ type: "text",
3076
+ text: recovering ? `${reason}
3077
+ Intercom recovery stopped after ${retries} automatic retries. Delivery may already have occurred. Do not repeat this operation automatically; check with the recipient before intentionally sending a new message.` : reason
3078
+ }],
3079
+ isError: true,
3080
+ details: { error: true, terminal: true, automaticRetries: retries, ...recovering ? { outcome: "unknown" } : {} }
3081
+ };
3082
+ } finally {
3083
+ clearTimeout(timer);
3084
+ if (token !== undefined)
3085
+ release(token);
3086
+ }
3087
+ }
3088
+ var init_tool_retry = __esm(() => {
3089
+ init_retry_identity();
3090
+ init_retry_policy();
3091
+ });
3092
+
2964
3093
  // dist/builtin/intercom/intercom-tool.ts
2965
3094
  import { Type as Type2 } from "typebox";
2966
3095
  import { Text as Text3 } from "@earendil-works/pi-tui";
2967
- function retryTokenGuidance(retryToken, remainingRetries) {
2968
- if (retryToken === undefined)
2969
- return "";
2970
- return ` Retry this exact operation with retryToken \`${retryToken}\` (${remainingRetries} claimed ${remainingRetries === 1 ? "attempt" : "attempts"} remain; the original deadline is unchanged).`;
2971
- }
2972
3096
  function retryErrorDetails(retryToken) {
2973
3097
  return retryToken === undefined ? { error: true } : { error: true, retryToken };
2974
3098
  }
@@ -3086,7 +3210,7 @@ A valid target outside the known set queues speculatively with a \`notInKnownSet
3086
3210
  undeliverable at terminal only if never delivered. Use \`ask\` only for a live, reply-capable target.
3087
3211
  Stage paths win over same-named owned subgroups for send/ask; \`list\` with \`group\` continues to
3088
3212
  select the group.
3089
- If a \`send\`, \`ask\`, or \`reply\` fails with \`Client disconnected\`, retry that exact operation with the returned \`retryToken\`, up to three claimed attempts; a call without the token is always a distinct operation.
3213
+ For send/ask/reply, Intercom retries recoverable disconnects internally up to three times with the same operation identity. Each new tool call is a new operation. If recovery ends with an unknown delivery outcome, do not repeat it automatically.
3090
3214
 
3091
3215
  Usage:
3092
3216
  intercom({ action: "list" }) → List sessions visible through your groups
@@ -3098,14 +3222,13 @@ Usage:
3098
3222
  intercom({ action: "send", to: "session-name", message: "..." }) → Send message (shared group only)
3099
3223
  intercom({ action: "ask", to: "session-name", message: "..." }) → Ask and wait for reply
3100
3224
  intercom({ action: "reply", message: "..." }) → Reply to the active or exact pending ask
3101
- intercom({ action: "send", to: "session-name", message: "...", retryToken: "..." }) → Claim the exact retry returned by a retryable failure
3102
3225
  intercom({ action: "pending" }) → List unresolved inbound asks
3103
3226
  intercom({ action: "status" }) → Show connection status and all your groups
3104
3227
 
3105
3228
  The "join" action is additive. "default" is the shared default group; "true" and
3106
3229
  "auto" are reserved for subagent auto-groups. Ordinary delivery requires at least
3107
3230
  one shared membership; contact_supervisor remains the only cross-group path.`,
3108
- promptSnippet: "Use to coordinate with other local agent sessions that share an intercom group. For a retryable send/ask/reply failure, repeat the exact operation with its returned retryToken; omit retryToken for fresh operations.",
3231
+ promptSnippet: "Use to coordinate with other local agent sessions that share an intercom group. Send/ask/reply retry reconnects internally; do not automatically repeat an unknown delivery outcome.",
3109
3232
  parameters: Type2.Object({
3110
3233
  action: Type2.String({
3111
3234
  description: "Action: 'list', 'groups', 'join', 'leave', 'send', 'ask', 'reply', 'pending', or 'status'"
@@ -3125,78 +3248,25 @@ one shared membership; contact_supervisor remains the only cross-group path.`,
3125
3248
  replyTo: Type2.Optional(Type2.String({
3126
3249
  description: "Exact pending-ask message ID; disambiguates concurrent asks, including asks from one sender"
3127
3250
  })),
3128
- retryToken: Type2.Optional(Type2.String({
3129
- minLength: 1,
3130
- maxLength: 128,
3131
- description: "Opaque token returned after a retryable send/ask/reply failure. Repeat the exact same action and arguments with this token; omit it for every fresh operation."
3132
- })),
3133
3251
  group: Type2.Optional(Type2.String({
3134
3252
  description: "Group name for 'join' or optional targeted 'leave'; read-only group filter for 'list'/'status'. 'send'/'ask' use shared memberships."
3135
3253
  }))
3136
3254
  }),
3137
- async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
3138
- const toolSessionId = ctx.sessionManager.getSessionId();
3139
- const { action, to, message, attachments, replyTo, retryToken, group } = params;
3140
- let retryPreflightRemaining;
3141
- if (retryToken !== undefined) {
3142
- if (action !== "send" && action !== "ask" && action !== "reply") {
3143
- const error = new RetryTokenError("mismatch");
3144
- return {
3145
- content: [{ type: "text", text: getErrorMessage(error) }],
3146
- isError: true,
3147
- details: { error: true }
3148
- };
3149
- }
3150
- try {
3151
- retryPreflightRemaining = retryIdentities.validateRetryToken(retryToken, toolSessionId, action);
3152
- } catch (error) {
3153
- return {
3154
- content: [{ type: "text", text: getErrorMessage(error) }],
3155
- isError: true,
3156
- details: { error: true }
3157
- };
3158
- }
3159
- }
3160
- let connectedClient;
3161
- try {
3162
- connectedClient = await ensureConnected("tool");
3163
- } catch (error) {
3164
- const retainedToken = retryToken !== undefined && isRecoverableIntercomDisconnect(error) ? retryToken : undefined;
3255
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
3256
+ if ("retryToken" in params) {
3165
3257
  return {
3166
- content: [{
3167
- type: "text",
3168
- text: `Intercom not connected: ${getErrorMessage(error)}${retryTokenGuidance(retainedToken, retryPreflightRemaining ?? 0)}`
3169
- }],
3258
+ content: [{ type: "text", text: "Intercom manages retries internally. Caller-supplied retry tokens are not supported; this call was not sent." }],
3170
3259
  isError: true,
3171
- details: retryErrorDetails(retainedToken)
3260
+ details: { error: true }
3172
3261
  };
3173
3262
  }
3174
- syncPresenceIdentity(toolSessionId);
3175
- const resolveOwnGroups = (sessions) => {
3176
- if (Array.isArray(connectedClient.groups)) {
3177
- return connectedClient.groups.map((membership) => normalizeGroup(membership));
3178
- }
3179
- const self = sessions?.find((session) => session.id === connectedClient.sessionId);
3180
- return [...normalizeGroups(self?.groups, self?.group)];
3181
- };
3182
- const isOnlyOwnGroup = (candidate, ownGroups) => candidate !== undefined && ownGroups.length === 1 && ownGroups[0] === candidate;
3183
- const requestedGroup = typeof group === "string" && group.trim() ? normalizeGroup(group) : undefined;
3184
- if ((action === "send" || action === "ask") && requestedGroup) {
3185
- const ownGroups = resolveOwnGroups();
3186
- if (!ownGroups.includes(requestedGroup)) {
3187
- return {
3188
- content: [{ type: "text", text: `The 'group' parameter is read-only for 'list'/'status'. '${action}' is always locked to your groups (${ownGroups.join(", ")}); it cannot target group "${requestedGroup}".` }],
3189
- isError: true,
3190
- details: { error: true }
3191
- };
3192
- }
3193
- }
3194
- switch (action) {
3195
- case "join": {
3196
- let targetGroup;
3197
- try {
3198
- targetGroup = validateRuntimeGroup(group);
3199
- } catch (error) {
3263
+ const toolSessionId = ctx.sessionManager.getSessionId();
3264
+ const { action, to, message, replyTo, group } = params;
3265
+ const attachments = params.attachments?.map((attachment) => ({ ...attachment }));
3266
+ const executeAttempt = async (retryToken, _signal) => {
3267
+ if (retryToken !== undefined) {
3268
+ if (action !== "send" && action !== "ask" && action !== "reply") {
3269
+ const error = new RetryTokenError("mismatch");
3200
3270
  return {
3201
3271
  content: [{ type: "text", text: getErrorMessage(error) }],
3202
3272
  isError: true,
@@ -3204,174 +3274,256 @@ one shared membership; contact_supervisor remains the only cross-group path.`,
3204
3274
  };
3205
3275
  }
3206
3276
  try {
3207
- const groups = await connectedClient.joinGroup(targetGroup);
3208
- deps.setJoinedGroups(groups);
3209
- return {
3210
- content: [{ type: "text", text: `Joined intercom group "${targetGroup}". Memberships: ${groups.join(", ")}.` }],
3211
- isError: false,
3212
- details: { group: targetGroup, groups }
3213
- };
3277
+ retryIdentities.validateRetryToken(retryToken, toolSessionId, action);
3214
3278
  } catch (error) {
3215
3279
  return {
3216
- content: [{ type: "text", text: `Failed to join group: ${getErrorMessage(error)}` }],
3280
+ content: [{ type: "text", text: getErrorMessage(error) }],
3217
3281
  isError: true,
3218
3282
  details: { error: true }
3219
3283
  };
3220
3284
  }
3221
3285
  }
3222
- case "leave": {
3223
- let targetGroup;
3224
- let homeGroup;
3225
- try {
3226
- targetGroup = typeof group === "string" && group.trim().length > 0 ? validateRuntimeGroup(group) : undefined;
3227
- if (targetGroup === undefined)
3228
- homeGroup = validateRuntimeGroup(deps.homeGroup());
3229
- } catch (error) {
3286
+ let connectedClient;
3287
+ try {
3288
+ connectedClient = await ensureConnected("tool");
3289
+ } catch (error) {
3290
+ const retainedToken = retryToken !== undefined && isRecoverableIntercomDisconnect(error) ? retryToken : undefined;
3291
+ return {
3292
+ content: [{
3293
+ type: "text",
3294
+ text: `Intercom not connected: ${getErrorMessage(error)}`
3295
+ }],
3296
+ isError: true,
3297
+ details: { ...retryErrorDetails(retainedToken), retryable: isRecoverableIntercomDisconnect(error) }
3298
+ };
3299
+ }
3300
+ syncPresenceIdentity(toolSessionId);
3301
+ const resolveOwnGroups = (sessions) => {
3302
+ if (Array.isArray(connectedClient.groups)) {
3303
+ return connectedClient.groups.map((membership) => normalizeGroup(membership));
3304
+ }
3305
+ const self = sessions?.find((session) => session.id === connectedClient.sessionId);
3306
+ return [...normalizeGroups(self?.groups, self?.group)];
3307
+ };
3308
+ const isOnlyOwnGroup = (candidate, ownGroups) => candidate !== undefined && ownGroups.length === 1 && ownGroups[0] === candidate;
3309
+ const requestedGroup = typeof group === "string" && group.trim() ? normalizeGroup(group) : undefined;
3310
+ if ((action === "send" || action === "ask") && requestedGroup) {
3311
+ const ownGroups = resolveOwnGroups();
3312
+ if (!ownGroups.includes(requestedGroup)) {
3230
3313
  return {
3231
- content: [{ type: "text", text: `Cannot leave intercom group: ${getErrorMessage(error)}` }],
3314
+ content: [{ type: "text", text: `The 'group' parameter is read-only for 'list'/'status'. '${action}' is always locked to your groups (${ownGroups.join(", ")}); it cannot target group "${requestedGroup}".` }],
3232
3315
  isError: true,
3233
3316
  details: { error: true }
3234
3317
  };
3235
3318
  }
3236
- try {
3237
- let groups;
3238
- if (targetGroup === undefined) {
3239
- if (homeGroup === undefined)
3240
- throw new Error("Intercom home group is unavailable");
3241
- await connectedClient.updatePresenceAcked({ groups: [homeGroup] });
3242
- groups = connectedClient.groups;
3243
- deps.clearJoinedGroups();
3244
- } else {
3245
- groups = await connectedClient.leaveGroup(targetGroup);
3319
+ }
3320
+ switch (action) {
3321
+ case "join": {
3322
+ let targetGroup;
3323
+ try {
3324
+ targetGroup = validateRuntimeGroup(group);
3325
+ } catch (error) {
3326
+ return {
3327
+ content: [{ type: "text", text: getErrorMessage(error) }],
3328
+ isError: true,
3329
+ details: { error: true }
3330
+ };
3331
+ }
3332
+ try {
3333
+ const groups = await connectedClient.joinGroup(targetGroup);
3246
3334
  deps.setJoinedGroups(groups);
3335
+ return {
3336
+ content: [{ type: "text", text: `Joined intercom group "${targetGroup}". Memberships: ${groups.join(", ")}.` }],
3337
+ isError: false,
3338
+ details: { group: targetGroup, groups }
3339
+ };
3340
+ } catch (error) {
3341
+ return {
3342
+ content: [{ type: "text", text: `Failed to join group: ${getErrorMessage(error)}` }],
3343
+ isError: true,
3344
+ details: { error: true }
3345
+ };
3247
3346
  }
3248
- const text = targetGroup === undefined ? `Returned to home intercom membership. Memberships: ${groups.join(", ")}.` : `Left intercom group "${targetGroup}". Memberships: ${groups.join(", ")}.`;
3249
- return {
3250
- content: [{ type: "text", text }],
3251
- isError: false,
3252
- details: targetGroup === undefined ? { group: homeGroup, groups } : { groups }
3253
- };
3254
- } catch (error) {
3255
- return {
3256
- content: [{ type: "text", text: `Failed to leave group: ${getErrorMessage(error)}` }],
3257
- isError: true,
3258
- details: { error: true }
3259
- };
3260
3347
  }
3261
- }
3262
- case "groups": {
3263
- try {
3264
- const groups = await connectedClient.listGroups();
3265
- const lines = groups.map(({ group: groupName, sessionCount, member }) => `- ${groupName} — ${sessionCount} session${sessionCount === 1 ? "" : "s"}${member ? " [member]" : ""}`);
3266
- return {
3267
- content: [{ type: "text", text: `**Intercom groups:**
3348
+ case "leave": {
3349
+ let targetGroup;
3350
+ let homeGroup;
3351
+ try {
3352
+ targetGroup = typeof group === "string" && group.trim().length > 0 ? validateRuntimeGroup(group) : undefined;
3353
+ if (targetGroup === undefined)
3354
+ homeGroup = validateRuntimeGroup(deps.homeGroup());
3355
+ } catch (error) {
3356
+ return {
3357
+ content: [{ type: "text", text: `Cannot leave intercom group: ${getErrorMessage(error)}` }],
3358
+ isError: true,
3359
+ details: { error: true }
3360
+ };
3361
+ }
3362
+ try {
3363
+ let groups;
3364
+ if (targetGroup === undefined) {
3365
+ if (homeGroup === undefined)
3366
+ throw new Error("Intercom home group is unavailable");
3367
+ await connectedClient.updatePresenceAcked({ groups: [homeGroup] });
3368
+ groups = connectedClient.groups;
3369
+ deps.clearJoinedGroups();
3370
+ } else {
3371
+ groups = await connectedClient.leaveGroup(targetGroup);
3372
+ deps.setJoinedGroups(groups);
3373
+ }
3374
+ const text = targetGroup === undefined ? `Returned to home intercom membership. Memberships: ${groups.join(", ")}.` : `Left intercom group "${targetGroup}". Memberships: ${groups.join(", ")}.`;
3375
+ return {
3376
+ content: [{ type: "text", text }],
3377
+ isError: false,
3378
+ details: targetGroup === undefined ? { group: homeGroup, groups } : { groups }
3379
+ };
3380
+ } catch (error) {
3381
+ return {
3382
+ content: [{ type: "text", text: `Failed to leave group: ${getErrorMessage(error)}` }],
3383
+ isError: true,
3384
+ details: { error: true }
3385
+ };
3386
+ }
3387
+ }
3388
+ case "groups": {
3389
+ try {
3390
+ const groups = await connectedClient.listGroups();
3391
+ const lines = groups.map(({ group: groupName, sessionCount, member }) => `- ${groupName} — ${sessionCount} session${sessionCount === 1 ? "" : "s"}${member ? " [member]" : ""}`);
3392
+ return {
3393
+ content: [{ type: "text", text: `**Intercom groups:**
3268
3394
  ${lines.join(`
3269
3395
  `)}` }],
3270
- isError: false,
3271
- details: { groups }
3272
- };
3273
- } catch (error) {
3274
- return {
3275
- content: [{ type: "text", text: `Failed to list groups: ${getErrorMessage(error)}` }],
3276
- isError: true,
3277
- details: { error: true }
3278
- };
3279
- }
3280
- }
3281
- case "list": {
3282
- try {
3283
- const mySessionId = connectedClient.sessionId;
3284
- const ownDirectory = await listDirectory(connectedClient);
3285
- const ownSessions = ownDirectory.sessions;
3286
- const currentSession = ownSessions.find((session) => session.id === mySessionId);
3287
- if (!currentSession) {
3396
+ isError: false,
3397
+ details: { groups }
3398
+ };
3399
+ } catch (error) {
3288
3400
  return {
3289
- content: [{ type: "text", text: "Current session is missing from intercom session list." }],
3401
+ content: [{ type: "text", text: `Failed to list groups: ${getErrorMessage(error)}` }],
3290
3402
  isError: true,
3291
3403
  details: { error: true }
3292
3404
  };
3293
3405
  }
3294
- const ownGroups = resolveOwnGroups(ownSessions);
3295
- if (requestedGroup && !isOnlyOwnGroup(requestedGroup, ownGroups)) {
3296
- const peeked = await listDirectory(connectedClient, requestedGroup);
3297
- const rows = [
3298
- ...peeked.sessions.map((session) => formatSessionListRow(session, currentSession.cwd, session.id === mySessionId)),
3299
- ...peeked.workflowStages.map(formatWorkflowStageRow),
3300
- ...(peeked.workflowFutureStages ?? []).map(formatWorkflowFutureStageRow)
3301
- ];
3302
- const section = rows.length === 0 ? `**Group [${requestedGroup}] (read-only peek):**
3406
+ }
3407
+ case "list": {
3408
+ try {
3409
+ const mySessionId = connectedClient.sessionId;
3410
+ const ownDirectory = await listDirectory(connectedClient);
3411
+ const ownSessions = ownDirectory.sessions;
3412
+ const currentSession = ownSessions.find((session) => session.id === mySessionId);
3413
+ if (!currentSession) {
3414
+ return {
3415
+ content: [{ type: "text", text: "Current session is missing from intercom session list." }],
3416
+ isError: true,
3417
+ details: { error: true }
3418
+ };
3419
+ }
3420
+ const ownGroups = resolveOwnGroups(ownSessions);
3421
+ if (requestedGroup && !isOnlyOwnGroup(requestedGroup, ownGroups)) {
3422
+ const peeked = await listDirectory(connectedClient, requestedGroup);
3423
+ const rows = [
3424
+ ...peeked.sessions.map((session) => formatSessionListRow(session, currentSession.cwd, session.id === mySessionId)),
3425
+ ...peeked.workflowStages.map(formatWorkflowStageRow),
3426
+ ...(peeked.workflowFutureStages ?? []).map(formatWorkflowFutureStageRow)
3427
+ ];
3428
+ const section = rows.length === 0 ? `**Group [${requestedGroup}] (read-only peek):**
3303
3429
  No sessions or workflow stages in this group.` : `**Group [${requestedGroup}] (read-only peek):**
3304
3430
  ${rows.join(`
3305
3431
  `)}`;
3306
- return {
3307
- content: [{ type: "text", text: `Your groups: ${ownGroups.join(", ")}
3432
+ return {
3433
+ content: [{ type: "text", text: `Your groups: ${ownGroups.join(", ")}
3308
3434
 
3309
3435
  ${section}` }],
3436
+ isError: false,
3437
+ details: {
3438
+ group: ownGroups.at(-1),
3439
+ groups: ownGroups,
3440
+ peekGroup: requestedGroup,
3441
+ workflowStages: peeked.workflowStages,
3442
+ ...(peeked.workflowFutureStages?.length ?? 0) === 0 ? {} : { workflowFutureStages: peeked.workflowFutureStages }
3443
+ }
3444
+ };
3445
+ }
3446
+ const otherSessions = ownSessions.filter((session) => session.id !== mySessionId);
3447
+ const currentSection = `**Current session** (groups: ${ownGroups.join(", ")}):
3448
+ ${formatSessionListRow(currentSession, currentSession.cwd, true)}`;
3449
+ const visibleRows = [
3450
+ ...otherSessions.map((session) => formatSessionListRow(session, currentSession.cwd, false)),
3451
+ ...ownDirectory.workflowStages.map(formatWorkflowStageRow),
3452
+ ...(ownDirectory.workflowFutureStages ?? []).map(formatWorkflowFutureStageRow)
3453
+ ];
3454
+ const otherSection = visibleRows.length === 0 ? `**Other sessions and workflow stages:**
3455
+ No other sessions or workflow stages share any of your groups.` : `**Other visible sessions and workflow stages:**
3456
+ ${visibleRows.join(`
3457
+ `)}`;
3458
+ return {
3459
+ content: [{ type: "text", text: `${currentSection}
3460
+
3461
+ ${otherSection}` }],
3310
3462
  isError: false,
3311
3463
  details: {
3312
3464
  group: ownGroups.at(-1),
3313
3465
  groups: ownGroups,
3314
- peekGroup: requestedGroup,
3315
- workflowStages: peeked.workflowStages,
3316
- ...(peeked.workflowFutureStages?.length ?? 0) === 0 ? {} : { workflowFutureStages: peeked.workflowFutureStages }
3466
+ ...ownDirectory.workflowStages.length === 0 ? {} : { workflowStages: ownDirectory.workflowStages },
3467
+ ...(ownDirectory.workflowFutureStages?.length ?? 0) === 0 ? {} : { workflowFutureStages: ownDirectory.workflowFutureStages }
3317
3468
  }
3318
3469
  };
3470
+ } catch (error) {
3471
+ return {
3472
+ content: [{ type: "text", text: `Failed to list sessions: ${getErrorMessage(error)}` }],
3473
+ isError: true,
3474
+ details: { error: true }
3475
+ };
3319
3476
  }
3320
- const otherSessions = ownSessions.filter((session) => session.id !== mySessionId);
3321
- const currentSection = `**Current session** (groups: ${ownGroups.join(", ")}):
3322
- ${formatSessionListRow(currentSession, currentSession.cwd, true)}`;
3323
- const visibleRows = [
3324
- ...otherSessions.map((session) => formatSessionListRow(session, currentSession.cwd, false)),
3325
- ...ownDirectory.workflowStages.map(formatWorkflowStageRow),
3326
- ...(ownDirectory.workflowFutureStages ?? []).map(formatWorkflowFutureStageRow)
3327
- ];
3328
- const otherSection = visibleRows.length === 0 ? `**Other sessions and workflow stages:**
3329
- No other sessions or workflow stages share any of your groups.` : `**Other visible sessions and workflow stages:**
3330
- ${visibleRows.join(`
3331
- `)}`;
3332
- return {
3333
- content: [{ type: "text", text: `${currentSection}
3477
+ }
3478
+ case "send": {
3479
+ if (!to || !message) {
3480
+ const errorText = retryToken === undefined ? "Missing 'to' or 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
3481
+ return {
3482
+ content: [{ type: "text", text: errorText }],
3483
+ isError: true,
3484
+ details: { error: true }
3485
+ };
3486
+ }
3487
+ if (_signal?.aborted) {
3488
+ return {
3489
+ content: [{
3490
+ type: "text",
3491
+ text: "Cancelled"
3492
+ }],
3493
+ isError: true,
3494
+ details: retryErrorDetails(retryToken)
3495
+ };
3496
+ }
3497
+ let retryIdentity;
3498
+ try {
3499
+ if (retryToken === undefined) {
3500
+ retryIdentity = retryIdentities.begin({
3501
+ sessionId: toolSessionId,
3502
+ action: "send",
3503
+ target: to,
3504
+ text: message,
3505
+ attachments,
3506
+ replyTo,
3507
+ expectsReply: false
3508
+ });
3509
+ }
3510
+ if (retryToken === undefined && !replyTo && deps.confirmSend && ctx.hasUI) {
3511
+ const attachmentText = attachments?.length ? formatAttachments(attachments) : "";
3512
+ const confirmed = await ctx.ui.confirm("Send Message", `Send to "${to}":
3334
3513
 
3335
- ${otherSection}` }],
3336
- isError: false,
3337
- details: {
3338
- group: ownGroups.at(-1),
3339
- groups: ownGroups,
3340
- ...ownDirectory.workflowStages.length === 0 ? {} : { workflowStages: ownDirectory.workflowStages },
3341
- ...(ownDirectory.workflowFutureStages?.length ?? 0) === 0 ? {} : { workflowFutureStages: ownDirectory.workflowFutureStages }
3514
+ ${message}${attachmentText}`);
3515
+ if (!confirmed) {
3516
+ if (retryIdentity !== undefined)
3517
+ retryIdentities.release(retryIdentity);
3518
+ retryIdentity = undefined;
3519
+ return {
3520
+ content: [{ type: "text", text: "Message cancelled by user" }],
3521
+ isError: false,
3522
+ details: {}
3523
+ };
3524
+ }
3342
3525
  }
3343
- };
3344
- } catch (error) {
3345
- return {
3346
- content: [{ type: "text", text: `Failed to list sessions: ${getErrorMessage(error)}` }],
3347
- isError: true,
3348
- details: { error: true }
3349
- };
3350
- }
3351
- }
3352
- case "send": {
3353
- if (!to || !message) {
3354
- const errorText = retryToken === undefined ? "Missing 'to' or 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
3355
- return {
3356
- content: [{ type: "text", text: errorText }],
3357
- isError: true,
3358
- details: { error: true }
3359
- };
3360
- }
3361
- if (_signal?.aborted) {
3362
- return {
3363
- content: [{
3364
- type: "text",
3365
- text: `Cancelled${retryTokenGuidance(retryToken, retryPreflightRemaining ?? 0)}`
3366
- }],
3367
- isError: true,
3368
- details: retryErrorDetails(retryToken)
3369
- };
3370
- }
3371
- let retryIdentity;
3372
- try {
3373
- if (retryToken === undefined) {
3374
- retryIdentity = retryIdentities.begin({
3526
+ retryIdentity ??= retryIdentities.begin({
3375
3527
  sessionId: toolSessionId,
3376
3528
  action: "send",
3377
3529
  target: to,
@@ -3379,63 +3531,79 @@ ${otherSection}` }],
3379
3531
  attachments,
3380
3532
  replyTo,
3381
3533
  expectsReply: false
3534
+ }, retryToken);
3535
+ const sendTo = await resolveTarget(connectedClient, to) ?? to;
3536
+ if (_signal?.aborted) {
3537
+ const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3538
+ retryIdentity = undefined;
3539
+ return {
3540
+ content: [{ type: "text", text: "Cancelled" }],
3541
+ isError: true,
3542
+ details: retryErrorDetails(retained.retryToken)
3543
+ };
3544
+ }
3545
+ if (sendTo === connectedClient.sessionId) {
3546
+ const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3547
+ retryIdentity = undefined;
3548
+ return {
3549
+ content: [{
3550
+ type: "text",
3551
+ text: "Cannot message the current session"
3552
+ }],
3553
+ isError: true,
3554
+ details: retryErrorDetails(retained.retryToken)
3555
+ };
3556
+ }
3557
+ const result = await connectedClient.send(sendTo, {
3558
+ messageId: retryIdentity.messageId,
3559
+ logicalTarget: to,
3560
+ text: message,
3561
+ attachments,
3562
+ replyTo
3382
3563
  });
3383
- }
3384
- if (!replyTo && deps.confirmSend && ctx.hasUI) {
3385
- const attachmentText = attachments?.length ? formatAttachments(attachments) : "";
3386
- const confirmed = await ctx.ui.confirm("Send Message", `Send to "${to}":
3387
-
3388
- ${message}${attachmentText}`);
3389
- if (!confirmed) {
3390
- if (retryIdentity !== undefined)
3391
- retryIdentities.release(retryIdentity);
3564
+ if (result.queued === true) {
3565
+ retryIdentities.release(retryIdentity);
3392
3566
  retryIdentity = undefined;
3567
+ pi.appendEntry("intercom_sent", {
3568
+ to,
3569
+ message: { text: message, attachments, replyTo },
3570
+ messageId: result.id,
3571
+ timestamp: Date.now()
3572
+ });
3573
+ const notInKnownSet = result.notInKnownSet === true;
3393
3574
  return {
3394
- content: [{ type: "text", text: "Message cancelled by user" }],
3575
+ content: [{
3576
+ type: "text",
3577
+ text: notInKnownSet ? `Message queued for ${to} (not in the workflow's known stage set; it will be delivered to every matching stage that starts before the run terminates)` : `Message queued for ${to}`
3578
+ }],
3395
3579
  isError: false,
3396
- details: {}
3580
+ details: {
3581
+ messageId: result.id,
3582
+ delivered: false,
3583
+ queued: true,
3584
+ target: result.target,
3585
+ position: result.position,
3586
+ ...notInKnownSet ? { notInKnownSet: true } : {}
3587
+ }
3588
+ };
3589
+ }
3590
+ if (!result.delivered) {
3591
+ const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3592
+ retryIdentity = undefined;
3593
+ const errorText = result.reason ?? "Session may not exist or has disconnected.";
3594
+ return {
3595
+ content: [{
3596
+ type: "text",
3597
+ text: `Message to "${to}" was not delivered: ${errorText}`
3598
+ }],
3599
+ isError: true,
3600
+ details: retryToken === undefined ? { messageId: result.id, delivered: false, reason: result.reason } : {
3601
+ delivered: false,
3602
+ reason: result.reason,
3603
+ ...retained.retryToken === undefined ? {} : { retryToken: retained.retryToken }
3604
+ }
3397
3605
  };
3398
3606
  }
3399
- }
3400
- retryIdentity ??= retryIdentities.begin({
3401
- sessionId: toolSessionId,
3402
- action: "send",
3403
- target: to,
3404
- text: message,
3405
- attachments,
3406
- replyTo,
3407
- expectsReply: false
3408
- }, retryToken);
3409
- const sendTo = await resolveTarget(connectedClient, to) ?? to;
3410
- if (_signal?.aborted) {
3411
- const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3412
- retryIdentity = undefined;
3413
- return {
3414
- content: [{ type: "text", text: `Cancelled${retryTokenGuidance(retained.retryToken, retained.remainingRetries)}` }],
3415
- isError: true,
3416
- details: retryErrorDetails(retained.retryToken)
3417
- };
3418
- }
3419
- if (sendTo === connectedClient.sessionId) {
3420
- const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3421
- retryIdentity = undefined;
3422
- return {
3423
- content: [{
3424
- type: "text",
3425
- text: `Cannot message the current session${retryTokenGuidance(retained.retryToken, retained.remainingRetries)}`
3426
- }],
3427
- isError: true,
3428
- details: retryErrorDetails(retained.retryToken)
3429
- };
3430
- }
3431
- const result = await connectedClient.send(sendTo, {
3432
- messageId: retryIdentity.messageId,
3433
- logicalTarget: to,
3434
- text: message,
3435
- attachments,
3436
- replyTo
3437
- });
3438
- if (result.queued === true) {
3439
3607
  retryIdentities.release(retryIdentity);
3440
3608
  retryIdentity = undefined;
3441
3609
  pi.appendEntry("intercom_sent", {
@@ -3444,376 +3612,379 @@ ${message}${attachmentText}`);
3444
3612
  messageId: result.id,
3445
3613
  timestamp: Date.now()
3446
3614
  });
3447
- const notInKnownSet = result.notInKnownSet === true;
3615
+ if (replyTo)
3616
+ activeReplyTracker().markReplied(replyTo);
3448
3617
  return {
3449
- content: [{
3450
- type: "text",
3451
- text: notInKnownSet ? `Message queued for ${to} (not in the workflow's known stage set; it will be delivered to every matching stage that starts before the run terminates)` : `Message queued for ${to}`
3452
- }],
3618
+ content: [{ type: "text", text: `Message sent to ${to}` }],
3453
3619
  isError: false,
3454
- details: {
3455
- messageId: result.id,
3456
- delivered: false,
3457
- queued: true,
3458
- target: result.target,
3459
- position: result.position,
3460
- ...notInKnownSet ? { notInKnownSet: true } : {}
3461
- }
3620
+ details: { messageId: result.id, delivered: true }
3462
3621
  };
3463
- }
3464
- if (!result.delivered) {
3465
- const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3466
- retryIdentity = undefined;
3467
- const errorText = result.reason ?? "Session may not exist or has disconnected.";
3622
+ } catch (error) {
3623
+ let failure = error;
3624
+ let retained;
3625
+ if (retryIdentity !== undefined) {
3626
+ if (isRecoverableIntercomDisconnect(error)) {
3627
+ try {
3628
+ retained = retainRecoverableRetry(retryIdentities, retryIdentity);
3629
+ } catch (retentionError) {
3630
+ failure = retentionError;
3631
+ }
3632
+ } else {
3633
+ retryIdentities.release(retryIdentity);
3634
+ }
3635
+ }
3468
3636
  return {
3469
3637
  content: [{
3470
3638
  type: "text",
3471
- text: `Message to "${to}" was not delivered: ${errorText}${retryTokenGuidance(retained.retryToken, retained.remainingRetries)}`
3639
+ text: `Failed to send: ${getErrorMessage(failure)}`
3472
3640
  }],
3473
3641
  isError: true,
3474
- details: retryToken === undefined ? { messageId: result.id, delivered: false, reason: result.reason } : {
3475
- delivered: false,
3476
- reason: result.reason,
3477
- ...retained.retryToken === undefined ? {} : { retryToken: retained.retryToken }
3478
- }
3642
+ details: { ...retryErrorDetails(retained?.retryToken), retryable: isRecoverableIntercomDisconnect(error) }
3479
3643
  };
3480
3644
  }
3481
- retryIdentities.release(retryIdentity);
3482
- retryIdentity = undefined;
3483
- pi.appendEntry("intercom_sent", {
3484
- to,
3485
- message: { text: message, attachments, replyTo },
3486
- messageId: result.id,
3487
- timestamp: Date.now()
3488
- });
3489
- if (replyTo)
3490
- activeReplyTracker().markReplied(replyTo);
3491
- return {
3492
- content: [{ type: "text", text: `Message sent to ${to}` }],
3493
- isError: false,
3494
- details: { messageId: result.id, delivered: true }
3495
- };
3496
- } catch (error) {
3497
- let failure = error;
3498
- let retained;
3499
- if (retryIdentity !== undefined) {
3500
- if (isRecoverableIntercomDisconnect(error)) {
3501
- try {
3502
- retained = retainRecoverableRetry(retryIdentities, retryIdentity);
3503
- } catch (retentionError) {
3504
- failure = retentionError;
3505
- }
3506
- } else {
3507
- retryIdentities.release(retryIdentity);
3508
- }
3509
- }
3510
- return {
3511
- content: [{
3512
- type: "text",
3513
- text: `Failed to send: ${getErrorMessage(failure)}${retryTokenGuidance(retained?.retryToken, retained?.remainingRetries ?? 0)}`
3514
- }],
3515
- isError: true,
3516
- details: retryErrorDetails(retained?.retryToken)
3517
- };
3518
- }
3519
- }
3520
- case "ask": {
3521
- if (!to) {
3522
- const errorText = retryToken === undefined ? "Missing 'to' or 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
3523
- return {
3524
- content: [{ type: "text", text: errorText }],
3525
- isError: true,
3526
- details: { error: true }
3527
- };
3528
3645
  }
3529
- if (_signal?.aborted) {
3530
- return {
3531
- content: [{
3532
- type: "text",
3533
- text: `Cancelled${retryTokenGuidance(retryToken, retryPreflightRemaining ?? 0)}`
3534
- }],
3535
- isError: true,
3536
- details: retryErrorDetails(retryToken)
3537
- };
3538
- }
3539
- let wait = null;
3540
- let retryIdentity;
3541
- try {
3542
- if (retryToken !== undefined && !message)
3543
- throw new RetryTokenError("mismatch");
3544
- retryIdentity = retryIdentities.begin({
3545
- sessionId: toolSessionId,
3546
- action: "ask",
3547
- target: to,
3548
- text: message ?? "",
3549
- attachments,
3550
- replyTo,
3551
- expectsReply: true
3552
- }, retryToken);
3553
- const metadata = getMetadata();
3554
- const currentSupervisorId = connectedClient.supervisorSessionId ?? undefined;
3555
- const metadataSupervisorId = metadata?.supervisor?.supervisorSessionId;
3556
- const directParentTarget = Boolean(metadata && (to === metadata.orchestratorTarget || to === currentSupervisorId || to === metadataSupervisorId));
3557
- const claimParentAsk = (resolvedTargetId) => Boolean(metadata && requestParentAskHandoff(pi.events, metadata, {
3558
- kind: "intercom",
3559
- question: typeof message === "string" ? message : "",
3560
- attachments,
3561
- resolvedTargetId
3562
- }));
3563
- if (retryToken === undefined && directParentTarget && claimParentAsk(currentSupervisorId ?? metadataSupervisorId ?? to)) {
3564
- retryIdentities.release(retryIdentity);
3565
- retryIdentity = undefined;
3566
- return {
3567
- content: [{ type: "text", text: "Parent ask claimed; this child is ending for a fresh subagent start." }],
3568
- isError: false,
3569
- details: { yielded: true }
3570
- };
3571
- }
3572
- const sendTo = await resolveTarget(connectedClient, to) ?? to;
3573
- if (_signal?.aborted) {
3574
- const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
3575
- retryIdentity = undefined;
3646
+ case "ask": {
3647
+ if (!to) {
3648
+ const errorText = retryToken === undefined ? "Missing 'to' or 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
3576
3649
  return {
3577
- content: [{
3578
- type: "text",
3579
- text: `Cancelled${retryTokenGuidance(retained?.retryToken, retained?.remainingRetries ?? 0)}`
3580
- }],
3650
+ content: [{ type: "text", text: errorText }],
3581
3651
  isError: true,
3582
- details: retryErrorDetails(retained?.retryToken)
3652
+ details: { error: true }
3583
3653
  };
3584
3654
  }
3585
- if (sendTo === connectedClient.sessionId) {
3586
- const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
3587
- retryIdentity = undefined;
3655
+ if (_signal?.aborted) {
3588
3656
  return {
3589
3657
  content: [{
3590
3658
  type: "text",
3591
- text: `Cannot message the current session${retryTokenGuidance(retained?.retryToken, retained?.remainingRetries ?? 0)}`
3659
+ text: "Cancelled"
3592
3660
  }],
3593
3661
  isError: true,
3594
- details: retryErrorDetails(retained?.retryToken)
3662
+ details: retryErrorDetails(retryToken)
3595
3663
  };
3596
3664
  }
3597
- if (retryToken === undefined && metadata && !directParentTarget) {
3598
- const authoritativeParent = [currentSupervisorId, metadataSupervisorId].find((candidate) => candidate === sendTo);
3599
- const resolvedParent = authoritativeParent ?? await resolveTarget(connectedClient, metadata.orchestratorTarget);
3600
- if (resolvedParent !== null && resolvedParent === sendTo && claimParentAsk(sendTo)) {
3665
+ let wait = null;
3666
+ let retryIdentity;
3667
+ let askDelivered = false;
3668
+ try {
3669
+ retryIdentity = retryIdentities.begin({
3670
+ sessionId: toolSessionId,
3671
+ action: "ask",
3672
+ target: to,
3673
+ text: message ?? "",
3674
+ attachments,
3675
+ replyTo,
3676
+ expectsReply: true
3677
+ }, retryToken);
3678
+ const metadata = getMetadata();
3679
+ const currentSupervisorId = connectedClient.supervisorSessionId ?? undefined;
3680
+ const metadataSupervisorId = metadata?.supervisor?.supervisorSessionId;
3681
+ const directParentTarget = Boolean(metadata && (to === metadata.orchestratorTarget || to === currentSupervisorId || to === metadataSupervisorId));
3682
+ let parentTarget = directParentTarget;
3683
+ const claimParentAsk = (resolvedTargetId) => Boolean(metadata && requestParentAskHandoff(pi.events, metadata, {
3684
+ kind: "intercom",
3685
+ question: typeof message === "string" ? message : "",
3686
+ attachments: params.attachments,
3687
+ resolvedTargetId
3688
+ }));
3689
+ if (retryToken === undefined && directParentTarget && claimParentAsk(currentSupervisorId ?? metadataSupervisorId ?? to)) {
3690
+ retryIdentities.release(retryIdentity);
3691
+ retryIdentity = undefined;
3692
+ return {
3693
+ content: [{ type: "text", text: "Parent ask claimed; this child is ending for a fresh subagent start." }],
3694
+ isError: false,
3695
+ details: { yielded: true }
3696
+ };
3697
+ }
3698
+ const sendTo = await resolveTarget(connectedClient, to) ?? to;
3699
+ if (_signal?.aborted) {
3700
+ const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
3701
+ retryIdentity = undefined;
3702
+ return {
3703
+ content: [{
3704
+ type: "text",
3705
+ text: "Cancelled"
3706
+ }],
3707
+ isError: true,
3708
+ details: retryErrorDetails(retained?.retryToken)
3709
+ };
3710
+ }
3711
+ if (sendTo === connectedClient.sessionId) {
3712
+ const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
3713
+ retryIdentity = undefined;
3714
+ return {
3715
+ content: [{
3716
+ type: "text",
3717
+ text: "Cannot message the current session"
3718
+ }],
3719
+ isError: true,
3720
+ details: retryErrorDetails(retained?.retryToken)
3721
+ };
3722
+ }
3723
+ if (metadata && !directParentTarget) {
3724
+ const authoritativeParent = [currentSupervisorId, metadataSupervisorId].find((candidate) => candidate === sendTo);
3725
+ const resolvedParent = authoritativeParent ?? await resolveTarget(connectedClient, metadata.orchestratorTarget);
3726
+ parentTarget = resolvedParent !== null && resolvedParent === sendTo;
3727
+ if (retryToken === undefined && parentTarget && claimParentAsk(sendTo)) {
3728
+ retryIdentities.release(retryIdentity);
3729
+ retryIdentity = undefined;
3730
+ return {
3731
+ content: [{ type: "text", text: "Parent ask claimed; this child is ending for a fresh subagent start." }],
3732
+ isError: false,
3733
+ details: { yielded: true }
3734
+ };
3735
+ }
3736
+ }
3737
+ if (!message && !parentTarget) {
3738
+ retryIdentities.release(retryIdentity);
3739
+ retryIdentity = undefined;
3740
+ return {
3741
+ content: [{ type: "text", text: "Missing 'to' or 'message' parameter" }],
3742
+ isError: true,
3743
+ details: { error: true }
3744
+ };
3745
+ }
3746
+ const replySender = await resolveReplySender(connectedClient, to, sendTo);
3747
+ if (replySender.kind === "ambiguous") {
3748
+ const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
3749
+ retryIdentity = undefined;
3750
+ return {
3751
+ content: [{
3752
+ type: "text",
3753
+ text: `Message to "${to}" is ambiguous: ${replySender.reason}. Use the exact target shown by intercom list.`
3754
+ }],
3755
+ isError: true,
3756
+ details: retryErrorDetails(retained?.retryToken)
3757
+ };
3758
+ }
3759
+ const questionId = retryIdentity.messageId;
3760
+ const replyFrom = replySender.kind === "resolved" ? replySender.sessionId : sendTo;
3761
+ const admission = beginReplyWait(replyFrom, questionId, _signal);
3762
+ if (!admission.ok) {
3763
+ const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3764
+ retryIdentity = undefined;
3765
+ const text = admission.reason === "busy" ? `Too many pending asks (${admission.limit}); reply-wait slots are full` : "Cancelled";
3766
+ return {
3767
+ content: [{
3768
+ type: "text",
3769
+ text
3770
+ }],
3771
+ isError: true,
3772
+ details: retryErrorDetails(retained.retryToken)
3773
+ };
3774
+ }
3775
+ wait = admission.wait;
3776
+ const sendResult = await connectedClient.send(sendTo, {
3777
+ messageId: questionId,
3778
+ logicalTarget: to,
3779
+ text: message ?? "",
3780
+ attachments,
3781
+ replyTo,
3782
+ expectsReply: true,
3783
+ ...parseWorkflowStageTarget(to)?.kind === "path" ? { onReplyTarget: wait.bindSender } : {}
3784
+ });
3785
+ if (sendResult.queued === true) {
3601
3786
  retryIdentities.release(retryIdentity);
3602
3787
  retryIdentity = undefined;
3788
+ wait.cancel(new Error(`Message queued for ${to}`));
3789
+ pi.appendEntry("intercom_sent", {
3790
+ to,
3791
+ message: { text: message, attachments, replyTo },
3792
+ messageId: sendResult.id,
3793
+ timestamp: Date.now()
3794
+ });
3603
3795
  return {
3604
- content: [{ type: "text", text: "Parent ask claimed; this child is ending for a fresh subagent start." }],
3796
+ content: [{ type: "text", text: `Message queued for ${to}` }],
3605
3797
  isError: false,
3606
- details: { yielded: true }
3798
+ details: {
3799
+ messageId: sendResult.id,
3800
+ delivered: false,
3801
+ queued: true,
3802
+ target: sendResult.target,
3803
+ position: sendResult.position
3804
+ }
3607
3805
  };
3608
3806
  }
3609
- }
3610
- if (!message) {
3611
- retryIdentities.release(retryIdentity);
3612
- retryIdentity = undefined;
3613
- return {
3614
- content: [{ type: "text", text: "Missing 'to' or 'message' parameter" }],
3615
- isError: true,
3616
- details: { error: true }
3617
- };
3618
- }
3619
- const replySender = await resolveReplySender(connectedClient, to, sendTo);
3620
- if (replySender.kind === "ambiguous") {
3621
- const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
3622
- retryIdentity = undefined;
3623
- return {
3624
- content: [{
3625
- type: "text",
3626
- text: `Message to "${to}" is ambiguous: ${replySender.reason}. Use the exact target shown by intercom list.${retryTokenGuidance(retained?.retryToken, retained?.remainingRetries ?? 0)}`
3627
- }],
3628
- isError: true,
3629
- details: retryErrorDetails(retained?.retryToken)
3630
- };
3631
- }
3632
- const questionId = retryIdentity.messageId;
3633
- const replyFrom = replySender.kind === "resolved" ? replySender.sessionId : sendTo;
3634
- const admission = beginReplyWait(replyFrom, questionId, _signal);
3635
- if (!admission.ok) {
3636
- const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3637
- retryIdentity = undefined;
3638
- const text = admission.reason === "busy" ? `Too many pending asks (${admission.limit}); reply-wait slots are full` : "Cancelled";
3639
- return {
3640
- content: [{
3641
- type: "text",
3642
- text: `${text}${retryTokenGuidance(retained.retryToken, retained.remainingRetries)}`
3643
- }],
3644
- isError: true,
3645
- details: retryErrorDetails(retained.retryToken)
3646
- };
3647
- }
3648
- wait = admission.wait;
3649
- const sendResult = await connectedClient.send(sendTo, {
3650
- messageId: questionId,
3651
- logicalTarget: to,
3652
- text: message,
3653
- attachments,
3654
- replyTo,
3655
- expectsReply: true
3656
- });
3657
- if (sendResult.queued === true) {
3658
- retryIdentities.release(retryIdentity);
3659
- retryIdentity = undefined;
3660
- wait.cancel(new Error(`Message queued for ${to}`));
3807
+ if (!sendResult.delivered) {
3808
+ const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3809
+ retryIdentity = undefined;
3810
+ const errorText = sendResult.reason ?? "Session may not exist or has disconnected.";
3811
+ wait.cancel(new Error(`Message to "${to}" was not delivered: ${errorText}`));
3812
+ const pendingStageAskRefusal = errorText.startsWith("Cannot ask a workflow stage whose session has not initialized.");
3813
+ return {
3814
+ content: [{
3815
+ type: "text",
3816
+ text: `Message to "${to}" was not delivered: ${errorText}`
3817
+ }],
3818
+ isError: true,
3819
+ details: {
3820
+ ...pendingStageAskRefusal ? {
3821
+ refusal: "pending_stage_ask_unsupported",
3822
+ recommendedAction: "send",
3823
+ reason: errorText
3824
+ } : {},
3825
+ ...retryErrorDetails(retained.retryToken)
3826
+ }
3827
+ };
3828
+ }
3829
+ askDelivered = true;
3661
3830
  pi.appendEntry("intercom_sent", {
3662
3831
  to,
3663
3832
  message: { text: message, attachments, replyTo },
3664
3833
  messageId: sendResult.id,
3665
3834
  timestamp: Date.now()
3666
3835
  });
3836
+ const replyMessage = await wait.promise;
3837
+ retryIdentities.release(retryIdentity);
3838
+ retryIdentity = undefined;
3839
+ const replyText = replyMessage.content.text;
3840
+ const replyAttachments = replyMessage.content.attachments?.length ? formatAttachments(replyMessage.content.attachments) : "";
3841
+ pi.appendEntry("intercom_received", {
3842
+ from: to,
3843
+ message: { text: replyText, attachments: replyMessage.content.attachments },
3844
+ messageId: replyMessage.id,
3845
+ timestamp: replyMessage.timestamp
3846
+ });
3847
+ if (replyMessage.replyError !== undefined) {
3848
+ return {
3849
+ content: [{ type: "text", text: `Failed: ${replyMessage.replyError}` }],
3850
+ isError: true,
3851
+ details: { error: true, replyTo: replyMessage.replyTo }
3852
+ };
3853
+ }
3667
3854
  return {
3668
- content: [{ type: "text", text: `Message queued for ${to}` }],
3855
+ content: [{ type: "text", text: `**Reply from ${to}:**
3856
+ ${replyText}${replyAttachments}` }],
3669
3857
  isError: false,
3670
- details: {
3671
- messageId: sendResult.id,
3672
- delivered: false,
3673
- queued: true,
3674
- target: sendResult.target,
3675
- position: sendResult.position
3676
- }
3858
+ details: {}
3677
3859
  };
3678
- }
3679
- if (!sendResult.delivered) {
3680
- const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3681
- retryIdentity = undefined;
3682
- const errorText = sendResult.reason ?? "Session may not exist or has disconnected.";
3683
- wait.cancel(new Error(`Message to "${to}" was not delivered: ${errorText}`));
3684
- const pendingStageAskRefusal = errorText.startsWith("Cannot ask a workflow stage whose session has not initialized.");
3860
+ } catch (error) {
3861
+ wait?.cancel(toError3(error));
3862
+ let failure = error;
3863
+ let retained;
3864
+ if (retryIdentity !== undefined) {
3865
+ if (isRecoverableIntercomDisconnect(error)) {
3866
+ try {
3867
+ retained = retainRecoverableRetry(retryIdentities, retryIdentity);
3868
+ } catch (retentionError) {
3869
+ failure = retentionError;
3870
+ }
3871
+ } else {
3872
+ retryIdentities.release(retryIdentity);
3873
+ }
3874
+ }
3685
3875
  return {
3686
3876
  content: [{
3687
3877
  type: "text",
3688
- text: `Message to "${to}" was not delivered: ${errorText}${retryTokenGuidance(retained.retryToken, retained.remainingRetries)}`
3878
+ text: `Failed: ${getErrorMessage(failure)}`
3689
3879
  }],
3690
3880
  isError: true,
3691
- details: {
3692
- ...pendingStageAskRefusal ? {
3693
- refusal: "pending_stage_ask_unsupported",
3694
- recommendedAction: "send",
3695
- reason: errorText
3696
- } : {},
3697
- ...retryErrorDetails(retained.retryToken)
3698
- }
3699
- };
3700
- }
3701
- pi.appendEntry("intercom_sent", {
3702
- to,
3703
- message: { text: message, attachments, replyTo },
3704
- messageId: sendResult.id,
3705
- timestamp: Date.now()
3706
- });
3707
- const replyMessage = await wait.promise;
3708
- retryIdentities.release(retryIdentity);
3709
- retryIdentity = undefined;
3710
- const replyText = replyMessage.content.text;
3711
- const replyAttachments = replyMessage.content.attachments?.length ? formatAttachments(replyMessage.content.attachments) : "";
3712
- pi.appendEntry("intercom_received", {
3713
- from: to,
3714
- message: { text: replyText, attachments: replyMessage.content.attachments },
3715
- messageId: replyMessage.id,
3716
- timestamp: replyMessage.timestamp
3717
- });
3718
- if (replyMessage.replyError !== undefined) {
3719
- return {
3720
- content: [{ type: "text", text: `Failed: ${replyMessage.replyError}` }],
3721
- isError: true,
3722
- details: { error: true, replyTo: replyMessage.replyTo }
3881
+ details: { ...retryErrorDetails(retained?.retryToken), retryable: isRecoverableIntercomDisconnect(error), deliveryUncertain: askDelivered }
3723
3882
  };
3724
3883
  }
3725
- return {
3726
- content: [{ type: "text", text: `**Reply from ${to}:**
3727
- ${replyText}${replyAttachments}` }],
3728
- isError: false,
3729
- details: {}
3730
- };
3731
- } catch (error) {
3732
- wait?.cancel(toError3(error));
3733
- let failure = error;
3734
- let retained;
3735
- if (retryIdentity !== undefined) {
3736
- if (isRecoverableIntercomDisconnect(error)) {
3737
- try {
3738
- retained = retainRecoverableRetry(retryIdentities, retryIdentity);
3739
- } catch (retentionError) {
3740
- failure = retentionError;
3741
- }
3742
- } else {
3743
- retryIdentities.release(retryIdentity);
3744
- }
3745
- }
3746
- return {
3747
- content: [{
3748
- type: "text",
3749
- text: `Failed: ${getErrorMessage(failure)}${retryTokenGuidance(retained?.retryToken, retained?.remainingRetries ?? 0)}`
3750
- }],
3751
- isError: true,
3752
- details: retryErrorDetails(retained?.retryToken)
3753
- };
3754
- }
3755
- }
3756
- case "reply": {
3757
- if (!message) {
3758
- const errorText = retryToken === undefined ? "Missing 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
3759
- return {
3760
- content: [{ type: "text", text: errorText }],
3761
- isError: true,
3762
- details: { error: true }
3763
- };
3764
3884
  }
3765
- let retryIdentity;
3766
- try {
3767
- retryIdentity = retryIdentities.begin({
3768
- sessionId: toolSessionId,
3769
- action: "reply",
3770
- target: to,
3771
- text: message,
3772
- attachments,
3773
- replyTo,
3774
- expectsReply: false
3775
- }, retryToken);
3776
- if (retryToken === undefined) {
3777
- const target = activeReplyTracker().resolveReplyTarget({ to, replyTo });
3778
- retryIdentities.bindReplyRoute(retryIdentity, {
3779
- senderId: target.from.id,
3780
- ...target.from.name === undefined ? {} : { senderName: target.from.name },
3781
- messageId: target.message.id,
3782
- expectsReply: target.message.expectsReply === true
3783
- });
3784
- }
3785
- const route = retryIdentities.replyRoute(retryIdentity);
3786
- if (route === undefined)
3787
- throw new RetryTokenError("invalid");
3788
- const replySendTo = to ?? route.senderId;
3789
- const replyLogicalTarget = to ?? route.senderId;
3790
- const displayTarget = route.senderName || route.senderId;
3791
- if (route.senderId === connectedClient.sessionId) {
3792
- const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3793
- retryIdentity = undefined;
3885
+ case "reply": {
3886
+ if (!message) {
3887
+ const errorText = retryToken === undefined ? "Missing 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
3794
3888
  return {
3795
- content: [{
3796
- type: "text",
3797
- text: `Cannot message the current session${retryTokenGuidance(retained.retryToken, retained.remainingRetries)}`
3798
- }],
3889
+ content: [{ type: "text", text: errorText }],
3799
3890
  isError: true,
3800
- details: retryErrorDetails(retained.retryToken)
3891
+ details: { error: true }
3801
3892
  };
3802
3893
  }
3803
- const replyMessageId = retryIdentity.messageId;
3804
- const sendReply = (targetId) => connectedClient.send(targetId, {
3805
- messageId: replyMessageId,
3806
- logicalTarget: replyLogicalTarget,
3807
- ...route.expectsReply ? { requirePendingReply: true } : {},
3808
- text: message,
3809
- attachments,
3810
- replyTo: route.messageId
3811
- });
3812
- let result = await sendReply(replySendTo);
3813
- if (to === undefined && result.delivered === false && result.reasonCode === "session_not_found" && route.senderName !== undefined) {
3814
- result = await sendReply(route.senderName);
3894
+ if (_signal?.aborted) {
3895
+ return { content: [{ type: "text", text: "Cancelled" }], isError: true, details: retryErrorDetails(retryToken) };
3815
3896
  }
3816
- if (result.queued === true) {
3897
+ let retryIdentity;
3898
+ try {
3899
+ retryIdentity = retryIdentities.begin({
3900
+ sessionId: toolSessionId,
3901
+ action: "reply",
3902
+ target: to,
3903
+ text: message,
3904
+ attachments,
3905
+ replyTo,
3906
+ expectsReply: false
3907
+ }, retryToken);
3908
+ if (retryToken === undefined) {
3909
+ const target = activeReplyTracker().resolveReplyTarget({ to, replyTo });
3910
+ retryIdentities.bindReplyRoute(retryIdentity, {
3911
+ senderId: target.from.id,
3912
+ ...target.from.name === undefined ? {} : { senderName: target.from.name },
3913
+ messageId: target.message.id,
3914
+ expectsReply: target.message.expectsReply === true
3915
+ });
3916
+ }
3917
+ const route = retryIdentities.replyRoute(retryIdentity);
3918
+ if (route === undefined)
3919
+ throw new RetryTokenError("invalid");
3920
+ const replySendTo = to ?? route.senderId;
3921
+ const replyLogicalTarget = to ?? route.senderId;
3922
+ const displayTarget = route.senderName || route.senderId;
3923
+ if (route.senderId === connectedClient.sessionId) {
3924
+ const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3925
+ retryIdentity = undefined;
3926
+ return {
3927
+ content: [{
3928
+ type: "text",
3929
+ text: "Cannot message the current session"
3930
+ }],
3931
+ isError: true,
3932
+ details: retryErrorDetails(retained.retryToken)
3933
+ };
3934
+ }
3935
+ const replyMessageId = retryIdentity.messageId;
3936
+ const sendReply = (targetId) => connectedClient.send(targetId, {
3937
+ messageId: replyMessageId,
3938
+ logicalTarget: replyLogicalTarget,
3939
+ ...route.expectsReply ? { requirePendingReply: true } : {},
3940
+ text: message,
3941
+ attachments,
3942
+ replyTo: route.messageId
3943
+ });
3944
+ let result = await sendReply(replySendTo);
3945
+ if (to === undefined && result.delivered === false && result.reasonCode === "session_not_found" && route.senderName !== undefined) {
3946
+ result = await sendReply(route.senderName);
3947
+ }
3948
+ if (result.queued === true) {
3949
+ retryIdentities.release(retryIdentity);
3950
+ retryIdentity = undefined;
3951
+ activeReplyTracker().markReplied(route.messageId);
3952
+ pi.appendEntry("intercom_sent", {
3953
+ to: displayTarget,
3954
+ message: { text: message, attachments, replyTo: route.messageId },
3955
+ messageId: result.id,
3956
+ timestamp: Date.now()
3957
+ });
3958
+ return {
3959
+ content: [{ type: "text", text: `Reply queued for ${displayTarget}` }],
3960
+ isError: false,
3961
+ details: {
3962
+ messageId: result.id,
3963
+ delivered: false,
3964
+ queued: true,
3965
+ replyTo: route.messageId,
3966
+ target: result.target,
3967
+ position: result.position
3968
+ }
3969
+ };
3970
+ }
3971
+ if (!result.delivered) {
3972
+ const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3973
+ retryIdentity = undefined;
3974
+ const errorText = result.reason ?? "Session may not exist or has disconnected.";
3975
+ return {
3976
+ content: [{
3977
+ type: "text",
3978
+ text: `Reply to "${displayTarget}" was not delivered: ${errorText}`
3979
+ }],
3980
+ isError: true,
3981
+ details: retryToken === undefined ? { messageId: result.id, delivered: false, reason: result.reason } : {
3982
+ delivered: false,
3983
+ reason: result.reason,
3984
+ ...retained.retryToken === undefined ? {} : { retryToken: retained.retryToken }
3985
+ }
3986
+ };
3987
+ }
3817
3988
  retryIdentities.release(retryIdentity);
3818
3989
  retryIdentity = undefined;
3819
3990
  activeReplyTracker().markReplied(route.messageId);
@@ -3824,136 +3995,101 @@ ${replyText}${replyAttachments}` }],
3824
3995
  timestamp: Date.now()
3825
3996
  });
3826
3997
  return {
3827
- content: [{ type: "text", text: `Reply queued for ${displayTarget}` }],
3998
+ content: [{ type: "text", text: `Reply sent to ${displayTarget}` }],
3828
3999
  isError: false,
3829
- details: {
3830
- messageId: result.id,
3831
- delivered: false,
3832
- queued: true,
3833
- replyTo: route.messageId,
3834
- target: result.target,
3835
- position: result.position
3836
- }
4000
+ details: { messageId: result.id, delivered: true, replyTo: route.messageId }
3837
4001
  };
3838
- }
3839
- if (!result.delivered) {
3840
- const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
3841
- retryIdentity = undefined;
3842
- const errorText = result.reason ?? "Session may not exist or has disconnected.";
4002
+ } catch (error) {
4003
+ let failure = error;
4004
+ let retained;
4005
+ if (retryIdentity !== undefined) {
4006
+ if (isRecoverableIntercomDisconnect(error)) {
4007
+ try {
4008
+ retained = retainRecoverableRetry(retryIdentities, retryIdentity);
4009
+ } catch (retentionError) {
4010
+ failure = retentionError;
4011
+ }
4012
+ } else {
4013
+ retryIdentities.release(retryIdentity);
4014
+ }
4015
+ }
3843
4016
  return {
3844
4017
  content: [{
3845
4018
  type: "text",
3846
- text: `Reply to "${displayTarget}" was not delivered: ${errorText}${retryTokenGuidance(retained.retryToken, retained.remainingRetries)}`
4019
+ text: `Failed to reply: ${getErrorMessage(failure)}`
3847
4020
  }],
3848
4021
  isError: true,
3849
- details: retryToken === undefined ? { messageId: result.id, delivered: false, reason: result.reason } : {
3850
- delivered: false,
3851
- reason: result.reason,
3852
- ...retained.retryToken === undefined ? {} : { retryToken: retained.retryToken }
3853
- }
4022
+ details: { ...retryErrorDetails(retained?.retryToken), retryable: isRecoverableIntercomDisconnect(error) }
3854
4023
  };
3855
4024
  }
3856
- retryIdentities.release(retryIdentity);
3857
- retryIdentity = undefined;
3858
- activeReplyTracker().markReplied(route.messageId);
3859
- pi.appendEntry("intercom_sent", {
3860
- to: displayTarget,
3861
- message: { text: message, attachments, replyTo: route.messageId },
3862
- messageId: result.id,
3863
- timestamp: Date.now()
3864
- });
3865
- return {
3866
- content: [{ type: "text", text: `Reply sent to ${displayTarget}` }],
3867
- isError: false,
3868
- details: { messageId: result.id, delivered: true, replyTo: route.messageId }
3869
- };
3870
- } catch (error) {
3871
- let failure = error;
3872
- let retained;
3873
- if (retryIdentity !== undefined) {
3874
- if (isRecoverableIntercomDisconnect(error)) {
3875
- try {
3876
- retained = retainRecoverableRetry(retryIdentities, retryIdentity);
3877
- } catch (retentionError) {
3878
- failure = retentionError;
3879
- }
3880
- } else {
3881
- retryIdentities.release(retryIdentity);
3882
- }
3883
- }
3884
- return {
3885
- content: [{
3886
- type: "text",
3887
- text: `Failed to reply: ${getErrorMessage(failure)}${retryTokenGuidance(retained?.retryToken, retained?.remainingRetries ?? 0)}`
3888
- }],
3889
- isError: true,
3890
- details: retryErrorDetails(retained?.retryToken)
3891
- };
3892
4025
  }
3893
- }
3894
- case "pending": {
3895
- const pendingAsks = activeReplyTracker().listPending();
3896
- if (pendingAsks.length === 0) {
4026
+ case "pending": {
4027
+ const pendingAsks = activeReplyTracker().listPending();
4028
+ if (pendingAsks.length === 0) {
4029
+ return {
4030
+ content: [{ type: "text", text: "No unresolved inbound asks." }],
4031
+ isError: false,
4032
+ details: {}
4033
+ };
4034
+ }
4035
+ const now = Date.now();
4036
+ const lines = pendingAsks.map(({ from, message, receivedAt }) => {
4037
+ const preview = message.content.text.replace(/\s+/g, " ").slice(0, 80);
4038
+ const elapsedSeconds = Math.max(0, Math.floor((now - receivedAt) / 1000));
4039
+ return `- ${from.name || from.id} · ${message.id} · ${elapsedSeconds}s ago · ${preview}`;
4040
+ });
3897
4041
  return {
3898
- content: [{ type: "text", text: "No unresolved inbound asks." }],
4042
+ content: [{ type: "text", text: `**Pending asks:**
4043
+ ${lines.join(`
4044
+ `)}` }],
3899
4045
  isError: false,
3900
4046
  details: {}
3901
4047
  };
3902
4048
  }
3903
- const now = Date.now();
3904
- const lines = pendingAsks.map(({ from, message: message2, receivedAt }) => {
3905
- const preview = message2.content.text.replace(/\s+/g, " ").slice(0, 80);
3906
- const elapsedSeconds = Math.max(0, Math.floor((now - receivedAt) / 1000));
3907
- return `- ${from.name || from.id} · ${message2.id} · ${elapsedSeconds}s ago · ${preview}`;
3908
- });
3909
- return {
3910
- content: [{ type: "text", text: `**Pending asks:**
3911
- ${lines.join(`
3912
- `)}` }],
3913
- isError: false,
3914
- details: {}
3915
- };
3916
- }
3917
- case "status": {
3918
- try {
3919
- const mySessionId = connectedClient.sessionId;
3920
- const sessions = await connectedClient.listSessions();
3921
- const ownGroups = resolveOwnGroups(sessions);
3922
- const selectedGroup = isOnlyOwnGroup(requestedGroup, ownGroups) ? undefined : requestedGroup;
3923
- const selectedGroupSessions = selectedGroup === undefined ? undefined : await connectedClient.listSessions(selectedGroup);
3924
- const selectedSection = selectedGroupSessions === undefined ? "" : `
4049
+ case "status": {
4050
+ try {
4051
+ const mySessionId = connectedClient.sessionId;
4052
+ const sessions = await connectedClient.listSessions();
4053
+ const ownGroups = resolveOwnGroups(sessions);
4054
+ const selectedGroup = isOnlyOwnGroup(requestedGroup, ownGroups) ? undefined : requestedGroup;
4055
+ const selectedGroupSessions = selectedGroup === undefined ? undefined : await connectedClient.listSessions(selectedGroup);
4056
+ const selectedSection = selectedGroupSessions === undefined ? "" : `
3925
4057
  Selected group [${selectedGroup}]: ${selectedGroupSessions.length} session(s)`;
3926
- return {
3927
- content: [{
3928
- type: "text",
3929
- text: `**Intercom Status:**
4058
+ return {
4059
+ content: [{
4060
+ type: "text",
4061
+ text: `**Intercom Status:**
3930
4062
  Connected: Yes
3931
4063
  Session ID: ${mySessionId}
3932
4064
  Groups: ${ownGroups.join(", ")}
3933
4065
  Active visible sessions: ${sessions.length}${selectedSection}`
3934
- }],
3935
- isError: false,
3936
- details: {
3937
- group: ownGroups.at(-1),
3938
- groups: ownGroups,
3939
- ...selectedGroup === undefined ? {} : { selectedGroup, selectedGroupSessionCount: selectedGroupSessions?.length ?? 0 }
3940
- }
3941
- };
3942
- } catch (error) {
4066
+ }],
4067
+ isError: false,
4068
+ details: {
4069
+ group: ownGroups.at(-1),
4070
+ groups: ownGroups,
4071
+ ...selectedGroup === undefined ? {} : { selectedGroup, selectedGroupSessionCount: selectedGroupSessions?.length ?? 0 }
4072
+ }
4073
+ };
4074
+ } catch (error) {
4075
+ return {
4076
+ content: [{ type: "text", text: `Failed to get status: ${getErrorMessage(error)}` }],
4077
+ isError: true,
4078
+ details: { error: true }
4079
+ };
4080
+ }
4081
+ }
4082
+ default:
3943
4083
  return {
3944
- content: [{ type: "text", text: `Failed to get status: ${getErrorMessage(error)}` }],
4084
+ content: [{ type: "text", text: `Unknown action: ${action}` }],
3945
4085
  isError: true,
3946
4086
  details: { error: true }
3947
4087
  };
3948
- }
3949
4088
  }
3950
- default:
3951
- return {
3952
- content: [{ type: "text", text: `Unknown action: ${action}` }],
3953
- isError: true,
3954
- details: { error: true }
3955
- };
3956
- }
4089
+ };
4090
+ if (action !== "send" && action !== "ask" && action !== "reply")
4091
+ return executeAttempt(undefined, signal);
4092
+ return runIntercomOperation(executeAttempt, (token) => retryIdentities.discard(token), signal);
3957
4093
  },
3958
4094
  renderCall(args, theme) {
3959
4095
  const action = typeof args.action === "string" ? args.action : "intercom";
@@ -3985,6 +4121,7 @@ var init_intercom_tool = __esm(() => {
3985
4121
  init_workflow_stage_target();
3986
4122
  init_recoverable_disconnect();
3987
4123
  init_retry_identity();
4124
+ init_tool_retry();
3988
4125
  });
3989
4126
 
3990
4127
  // dist/builtin/intercom/ui/compose.ts
@@ -4375,7 +4512,10 @@ var init_overlay = __esm(() => {
4375
4512
  function registerIntercomLifecycle(pi, deps) {
4376
4513
  const activeReplyTracker = () => typeof deps.replyTracker === "function" ? deps.replyTracker() : deps.replyTracker;
4377
4514
  let hasActiveSession = false;
4515
+ let unbindStageClose;
4378
4516
  async function cleanupRuntime(reason) {
4517
+ unbindStageClose?.();
4518
+ unbindStageClose = undefined;
4379
4519
  deps.setRuntimeStarted(false);
4380
4520
  deps.setShuttingDown(true);
4381
4521
  deps.setDisposed(true);
@@ -4426,6 +4566,12 @@ function registerIntercomLifecycle(pi, deps) {
4426
4566
  deps.setSessionStartedAt(Date.now());
4427
4567
  deps.setAgentRunning(false);
4428
4568
  deps.activeTools.clear();
4569
+ const stage = ctx.orchestrationContext;
4570
+ const closeSignal = stage?.kind === "workflow-stage" ? stage.messageAdmission?.boundary?.closeSignal : undefined;
4571
+ closeSignal?.addEventListener("abort", deps.syncPresenceStatus, { once: true });
4572
+ unbindStageClose = () => closeSignal?.removeEventListener("abort", deps.syncPresenceStatus);
4573
+ if (closeSignal?.aborted)
4574
+ deps.syncPresenceStatus();
4429
4575
  });
4430
4576
  pi.on("session_shutdown", async () => {
4431
4577
  if (!hasActiveSession)
@@ -4564,12 +4710,12 @@ function prepareDurableAuthority(storagePath) {
4564
4710
  if (databaseExists !== keyExists)
4565
4711
  return;
4566
4712
  if (!databaseExists) {
4567
- const key2 = randomBytes(AUTHORITY_KEY_BYTES);
4568
- writeFileSync2(keyPath, key2, { flag: "wx", mode: 384 });
4713
+ const key = randomBytes(AUTHORITY_KEY_BYTES);
4714
+ writeFileSync2(keyPath, key, { flag: "wx", mode: 384 });
4569
4715
  const databaseDescriptor = openSync2(storagePath, "wx", 384);
4570
4716
  closeSync2(databaseDescriptor);
4571
4717
  restrictExistingAuthorityArtifacts(storagePath, keyPath);
4572
- return key2;
4718
+ return key;
4573
4719
  }
4574
4720
  const key = readFileSync3(keyPath);
4575
4721
  if (key.length !== AUTHORITY_KEY_BYTES)
@@ -4878,7 +5024,7 @@ function parseBarrier(value) {
4878
5024
  return null;
4879
5025
  if (typeof record.terminalAt !== "number" || !Number.isFinite(record.terminalAt))
4880
5026
  return null;
4881
- if (record.source !== "detached-notify" && record.source !== "result-relay")
5027
+ if (record.source !== "detached-notify" && record.source !== "result-relay" && record.source !== "owner-task")
4882
5028
  return null;
4883
5029
  if (!Array.isArray(record.sourceSessionTargets))
4884
5030
  return null;
@@ -4954,11 +5100,17 @@ function registerTerminalOrderingBarrier(pi, options) {
4954
5100
  envelope.completion = currentOwner;
4955
5101
  return;
4956
5102
  }
4957
- const drainedTargets = drainedTargetsByTerminal.get(terminalKey) ?? new Set;
5103
+ const drainedTargets = barrier.source === "owner-task" ? new Set : drainedTargetsByTerminal.get(terminalKey) ?? new Set;
4958
5104
  const pendingTargets = barrier.sourceSessionTargets.filter((target) => !drainedTargets.has(target));
4959
5105
  if (pendingTargets.length === 0)
4960
5106
  return;
4961
5107
  const claim = options.queue.claimOrdinarySourceTargets(barrier.runId, pendingTargets, barrier.terminalAt);
5108
+ const deliverPrelude = (entry) => {
5109
+ if (!claim.isCurrent() || options.isCurrent?.() === false) {
5110
+ throw new Error("Intercom terminal delivery owner retired");
5111
+ }
5112
+ return options.deliver(entry, "prelude");
5113
+ };
4962
5114
  const ownership = Promise.withResolvers();
4963
5115
  ownership.promise.catch(() => {});
4964
5116
  inFlightByTerminal.set(terminalKey, ownership.promise);
@@ -4968,7 +5120,7 @@ function registerTerminalOrderingBarrier(pi, options) {
4968
5120
  ownership.reject(error);
4969
5121
  };
4970
5122
  const finish = () => {
4971
- if (barrier.dispatch && options.toMessage || claim.entries.length > 0) {
5123
+ if (barrier.source !== "owner-task" && (barrier.dispatch && options.toMessage || claim.entries.length > 0)) {
4972
5124
  for (const target of pendingTargets)
4973
5125
  drainedTargets.add(target);
4974
5126
  drainedTargetsByTerminal.set(terminalKey, drainedTargets);
@@ -5019,7 +5171,7 @@ function registerTerminalOrderingBarrier(pi, options) {
5019
5171
  let delivered;
5020
5172
  let deliveredAsync;
5021
5173
  try {
5022
- delivered = options.deliver(claim.entries[index], "prelude");
5174
+ delivered = deliverPrelude(claim.entries[index]);
5023
5175
  deliveredAsync = isPromiseLike(delivered);
5024
5176
  } catch (error) {
5025
5177
  if (barrier.owner)
@@ -5035,7 +5187,7 @@ function registerTerminalOrderingBarrier(pi, options) {
5035
5187
  try {
5036
5188
  await delivered;
5037
5189
  for (current = index + 1;current < claim.entries.length; current++) {
5038
- await options.deliver(claim.entries[current], "prelude");
5190
+ await deliverPrelude(claim.entries[current]);
5039
5191
  }
5040
5192
  finish();
5041
5193
  } catch (error) {
@@ -5111,7 +5263,7 @@ async function dispatchRelayFallback(pi, prefix, terminalMessage, stageAdmission
5111
5263
  }
5112
5264
  }
5113
5265
  function registerSubagentRelay(pi, deps) {
5114
- const { getLiveContext, currentSessionTargetMatches, sendIncomingMessage, ensureConnected, resolveSessionTarget: resolveSessionTarget2 } = deps;
5266
+ const { getLiveContext, currentSessionTargetMatches, sendIncomingMessage, ensureConnected, resolveSessionTarget } = deps;
5115
5267
  const localDeliveries = deps.localDeliveryAuthority ?? new DeliveredMessageCache;
5116
5268
  function deliverLocalSubagentRelayMessage(sender, status, messageText, terminalBarrier, requestId) {
5117
5269
  const now = Date.now();
@@ -5268,7 +5420,7 @@ ${messageText}`,
5268
5420
  let target;
5269
5421
  try {
5270
5422
  activeClient = await ensureConnected("background");
5271
- target = await resolveSessionTarget2(activeClient, parsed.to) ?? parsed.to;
5423
+ target = await resolveSessionTarget(activeClient, parsed.to) ?? parsed.to;
5272
5424
  } catch (error) {
5273
5425
  if (!relayStillLive()) {
5274
5426
  acknowledgeResult(options, parsed.requestId, false, error);
@@ -5545,6 +5697,20 @@ function framePreStartPendingStageMessage(entry) {
5545
5697
 
5546
5698
  Sent: ${framePendingStageTimestamp(entry.message.timestamp)}
5547
5699
 
5700
+ ${entry.bodyText}`
5701
+ };
5702
+ }
5703
+ function isDeliveryFeedback(message) {
5704
+ return Boolean(message.replyTo) && message.replyError !== undefined;
5705
+ }
5706
+ function frameDeliveryFeedback(entry) {
5707
+ return {
5708
+ ...entry,
5709
+ replyCommand: undefined,
5710
+ bodyText: `**Intercom delivery failed**
5711
+
5712
+ Sent: ${framePendingStageTimestamp(entry.message.timestamp)}
5713
+
5548
5714
  ${entry.bodyText}`
5549
5715
  };
5550
5716
  }
@@ -5566,6 +5732,7 @@ ${entry.bodyText}`,
5566
5732
  // dist/builtin/intercom/inbound-idle-queue.ts
5567
5733
  class InboundIdleQueue {
5568
5734
  entries = [];
5735
+ generation = 0;
5569
5736
  get size() {
5570
5737
  return this.entries.length;
5571
5738
  }
@@ -5589,6 +5756,7 @@ class InboundIdleQueue {
5589
5756
  }
5590
5757
  claimOrdinarySourceTargets(runId, sourceSessionTargets, terminalAt = Number.POSITIVE_INFINITY) {
5591
5758
  const targets = new Set(sourceSessionTargets);
5759
+ const generation = this.generation;
5592
5760
  const original = this.entries;
5593
5761
  const legacyIdsByName = new Map;
5594
5762
  for (const entry of original) {
@@ -5618,8 +5786,9 @@ class InboundIdleQueue {
5618
5786
  let settled = false;
5619
5787
  return {
5620
5788
  entries: selected,
5789
+ isCurrent: () => generation === this.generation,
5621
5790
  rollbackFrom: (index) => {
5622
- if (settled)
5791
+ if (settled || generation !== this.generation)
5623
5792
  return;
5624
5793
  settled = true;
5625
5794
  const undelivered = new Set(selected.slice(index));
@@ -5629,6 +5798,7 @@ class InboundIdleQueue {
5629
5798
  };
5630
5799
  }
5631
5800
  clear() {
5801
+ this.generation++;
5632
5802
  this.entries = [];
5633
5803
  }
5634
5804
  }
@@ -5954,7 +6124,7 @@ function routeClosedWorkflowStageMessage(entry, admission, tracker, waiter, deli
5954
6124
  const sourceRunId = entry.message.source?.subagentRunId;
5955
6125
  if (sourceRunId !== undefined && ownsSubagentRun(sourceRunId))
5956
6126
  return;
5957
- if (entry.message.expectsReply !== true) {
6127
+ if (entry.message.expectsReply !== true && !isDeliveryFeedback(entry.message)) {
5958
6128
  retryStableDelivery({ deliver, isCurrent }).catch(() => {});
5959
6129
  return;
5960
6130
  }
@@ -5965,6 +6135,14 @@ function routeClosedWorkflowStageMessage(entry, admission, tracker, waiter, deli
5965
6135
  admission.commit(admitted.reservation);
5966
6136
  return;
5967
6137
  }
6138
+ if (isDeliveryFeedback(entry.message)) {
6139
+ retryStableDelivery({ deliver, isCurrent }).then(() => {
6140
+ admission.commit(admitted.reservation);
6141
+ }, (error) => {
6142
+ admission.release(admitted.reservation, error instanceof Error ? error : new Error(String(error)));
6143
+ });
6144
+ return;
6145
+ }
5968
6146
  const replyContext = tracker.recordIncomingMessage(entry.from, entry.message);
5969
6147
  tracker.queueTurnContext(replyContext);
5970
6148
  const delivery = invoke(deliver);
@@ -6050,6 +6228,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
6050
6228
  };
6051
6229
  let client = null;
6052
6230
  let clientRegistrationGroup = null;
6231
+ const replyCapability = registerSubagentReplyCapability(pi, () => client);
6053
6232
  const config = loadConfig();
6054
6233
  const legacyChildOrchestratorMetadata = readChildOrchestratorMetadata();
6055
6234
  let runtimeContext = null;
@@ -6118,7 +6297,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
6118
6297
  }
6119
6298
  function currentStatus() {
6120
6299
  const activeToolName = activeTools.values().next().value;
6121
- const lifecycleStatus = activeToolName ? `tool:${activeToolName}` : agentRunning ? "thinking" : "idle";
6300
+ const stage = getLiveContext()?.orchestrationContext;
6301
+ const lifecycleStatus = stage?.kind === "workflow-stage" && stage.messageAdmission?.isOpen() === false ? `closed · reply: ${stage.lateMessageRouter === undefined ? "unavailable" : "post-mortem only"}` : activeToolName ? `tool:${activeToolName}` : agentRunning ? "thinking" : "idle";
6122
6302
  return config.status ? `${lifecycleStatus} · ${config.status}` : lifecycleStatus;
6123
6303
  }
6124
6304
  function resolveSessionHomeGroup() {
@@ -6156,6 +6336,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
6156
6336
  startedAt: sessionStartedAt,
6157
6337
  lastActivity: Date.now(),
6158
6338
  status: currentStatus(),
6339
+ replyCapability: replyCapability(),
6159
6340
  groups: [...currentIntercomGroups()],
6160
6341
  group: currentIntercomGroup()
6161
6342
  };
@@ -6257,14 +6438,20 @@ function piIntercomExtension(pi, testOverrides = {}) {
6257
6438
  const bodyText = `${message.content.text}${attachmentText}`;
6258
6439
  const replyCommand = config.replyHint && message.expectsReply ? `intercom({ action: "reply", message: "..." })` : undefined;
6259
6440
  const rawEntry = { from, message, replyCommand, bodyText, ...channel ? { channel } : {} };
6260
- const entry = receivedBeforeStageStart ? framePreStartPendingStageMessage(rawEntry) : rawEntry;
6441
+ const framedEntry = isDeliveryFeedback(message) ? frameDeliveryFeedback(rawEntry) : rawEntry;
6442
+ const entry = receivedBeforeStageStart ? framePreStartPendingStageMessage(framedEntry) : framedEntry;
6261
6443
  if (receivedBeforeStageStart) {
6262
6444
  return sendIncomingMessage(entry, "prelude", messageGeneration, false);
6263
6445
  }
6264
6446
  const stageAdmission = liveContext.orchestrationContext?.kind === "workflow-stage" ? liveContext.orchestrationContext.messageAdmission : undefined;
6265
6447
  const stageClosed = stageAdmission?.isOpen() === false;
6266
6448
  if (stageClosed) {
6267
- routeClosedWorkflowStageMessage(entry, inboundDeliveries, replyTracker, replyWaiters.pending(), () => sendIncomingMessage(entry, "trigger", messageGeneration, false), () => client, () => Boolean(getLiveContext(liveContext, messageGeneration)), (runId) => stageAdmission.boundary.ownsSubagentRun(runId));
6449
+ routeClosedWorkflowStageMessage(entry, inboundDeliveries, replyTracker, replyWaiters.pending(), () => {
6450
+ if (message.expectsReply === true && liveContext.orchestrationContext?.lateMessageRouter === undefined) {
6451
+ throw new Error("Workflow stage is closed and cannot reply because post-mortem routing is unavailable. Contact a live stage or start new work with explicit context.");
6452
+ }
6453
+ return sendIncomingMessage(entry, isDeliveryFeedback(message) ? "prelude" : "trigger", messageGeneration, false);
6454
+ }, () => client, () => Boolean(getLiveContext(liveContext, messageGeneration)), (runId) => stageAdmission.boundary.ownsSubagentRun(runId));
6268
6455
  return;
6269
6456
  }
6270
6457
  const admission = inboundDeliveries.admit(from, message);
@@ -6275,6 +6462,12 @@ function piIntercomExtension(pi, testOverrides = {}) {
6275
6462
  inboundDeliveries.commit(reservation);
6276
6463
  return;
6277
6464
  }
6465
+ if (isDeliveryFeedback(message)) {
6466
+ return retryStableDelivery({
6467
+ deliver: () => sendIncomingMessage(entry, "prelude", messageGeneration, false),
6468
+ isCurrent: () => Boolean(getLiveContext(liveContext, messageGeneration))
6469
+ }).then(() => inboundDeliveries.commit(reservation), (error) => inboundDeliveries.release(reservation, toError3(error)));
6470
+ }
6278
6471
  const replyContext = replyTracker.recordIncomingMessage(from, message);
6279
6472
  const commit = () => {
6280
6473
  inboundDeliveries.commit(reservation);
@@ -6311,9 +6504,11 @@ function piIntercomExtension(pi, testOverrides = {}) {
6311
6504
  const activeClient = client;
6312
6505
  if (!message.replyTo && activeClient?.isConnected()) {
6313
6506
  try {
6507
+ const refusal = "Message not accepted: recipient was busy in non-interactive mode. Its task was not interrupted.";
6314
6508
  const result = await activeClient.send(from.id, {
6315
- text: "This agent is running in non-interactive mode and cannot respond to intercom messages while it is working. It will continue its current task and exit when done.",
6316
- replyTo: message.id
6509
+ text: refusal,
6510
+ replyTo: message.id,
6511
+ replyError: refusal
6317
6512
  });
6318
6513
  if (result.delivered && getLiveContext(liveContext, messageGeneration)) {
6319
6514
  replyTracker.markReplied(message.id);
@@ -6581,7 +6776,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
6581
6776
  pendingStageRouteClients.set(runId, state);
6582
6777
  if (state.client?.isConnected()) {
6583
6778
  state.route = route;
6584
- state.client.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages);
6779
+ state.client.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent);
6780
+ await state.client.listSessions();
6585
6781
  return;
6586
6782
  }
6587
6783
  if (state.promise) {
@@ -6593,12 +6789,12 @@ function piIntercomExtension(pi, testOverrides = {}) {
6593
6789
  const nextClient = new IntercomClient(`${currentSessionId}:pending-stage-route:${runId}`);
6594
6790
  state.client = nextClient;
6595
6791
  attachPendingStageRouteClientHandlers(runId, state, nextClient);
6596
- await nextClient.connect({ ...buildRegistration(), name: undefined, groups: [normalizeGroup(route.group)], group: normalizeGroup(route.group) }, undefined, undefined, readSubagentMessageSource(runtimeContext?.subagentPolicy));
6792
+ await nextClient.connect({ ...buildRegistration(), recipientPurpose: "control", name: undefined, groups: [normalizeGroup(route.group)], group: normalizeGroup(route.group) }, undefined, undefined, readSubagentMessageSource(runtimeContext?.subagentPolicy));
6597
6793
  if (!pendingStageRouteClientIsCurrent(runId, state, contextAtStart, generationAtStart)) {
6598
6794
  await nextClient.disconnect();
6599
6795
  throw new Error("Intercom runtime no longer active");
6600
6796
  }
6601
- nextClient.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages);
6797
+ nextClient.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent);
6602
6798
  await nextClient.listSessions();
6603
6799
  if (!pendingStageRouteClientIsCurrent(runId, state, contextAtStart, generationAtStart)) {
6604
6800
  await nextClient.disconnect();
@@ -6646,7 +6842,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
6646
6842
  async function registerPendingStageRoute(activeClient, runId, route) {
6647
6843
  const routeGroup = normalizeGroup(route.group);
6648
6844
  if (clientRegistrationGroup === routeGroup) {
6649
- activeClient.registerPendingStageRoute(runId, routeGroup, route.capability, route.stages, route.possibleStages);
6845
+ activeClient.registerPendingStageRoute(runId, routeGroup, route.capability, route.stages, route.possibleStages, route.parent);
6846
+ await activeClient.listSessions();
6650
6847
  return;
6651
6848
  }
6652
6849
  await ensurePendingStageRouteClient(runId, { ...route, group: routeGroup });
@@ -6672,15 +6869,16 @@ function piIntercomExtension(pi, testOverrides = {}) {
6672
6869
  let connectFailed = false;
6673
6870
  await ownershipRecorded.promise;
6674
6871
  const nextClient = new IntercomClient(currentSessionId);
6675
- const registration = buildRegistration();
6676
6872
  client = nextClient;
6677
6873
  attachClientHandlers(nextClient);
6678
6874
  try {
6679
6875
  await testOverrides.beforeConnectAttempt?.(reason);
6680
6876
  await spawnBrokerIfNeeded(config.brokerCommand, config.brokerArgs);
6681
6877
  const childMetadata = currentChildOrchestratorMetadata();
6682
- await nextClient.connect(registration, childMetadata?.supervisor, supervisorAuthorizations.ownerToken, readSubagentMessageSource(runtimeContext?.subagentPolicy), resolveSessionHomeGroup());
6878
+ await nextClient.connect(buildRegistration(), childMetadata?.supervisor, supervisorAuthorizations.ownerToken, readSubagentMessageSource(runtimeContext?.subagentPolicy), resolveSessionHomeGroup());
6683
6879
  clientRegistrationGroup = resolveSessionHomeGroup();
6880
+ if (replyCapability() === "terminal")
6881
+ nextClient.updatePresence({ replyCapability: "terminal" });
6684
6882
  await supervisorAuthorizations.restore(nextClient);
6685
6883
  for (const [runId, route] of pendingStageRoutes) {
6686
6884
  await registerPendingStageRoute(nextClient, runId, route);
@@ -6734,7 +6932,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
6734
6932
  group: payload.group,
6735
6933
  capability: payload.capability,
6736
6934
  ...payload.stages === undefined ? {} : { stages: payload.stages },
6737
- ...payload.possibleStages === undefined ? {} : { possibleStages: payload.possibleStages }
6935
+ ...payload.possibleStages === undefined ? {} : { possibleStages: payload.possibleStages },
6936
+ ...payload.parent === undefined ? {} : { parent: payload.parent }
6738
6937
  });
6739
6938
  const completion = ensureConnected("background").then((activeClient) => registerPendingStageRoute(activeClient, payload.runId, payload));
6740
6939
  payload.completion = completion;
@@ -6942,8 +7141,34 @@ import { Text as Text4 } from "@earendil-works/pi-tui";
6942
7141
  import { Type as Type3 } from "typebox";
6943
7142
 
6944
7143
  // dist/builtin/intercom/lazy-tool-execution.ts
7144
+ init_recoverable_disconnect();
7145
+ init_retry_policy();
7146
+ import { setTimeout as delay } from "node:timers/promises";
6945
7147
  async function executeHeavyTool(loadHeavy, name, args) {
6946
- const handle = await loadHeavy(args[4]);
7148
+ const params = args[1];
7149
+ const recoverInitialization = name === "intercom" && ["send", "ask", "reply"].includes(params.action ?? "");
7150
+ let handle;
7151
+ let retries = 0;
7152
+ for (;; ) {
7153
+ if (recoverInitialization && args[2]?.aborted)
7154
+ return initializationFailure("Cancelled", retries);
7155
+ try {
7156
+ handle = await loadHeavy(args[4]);
7157
+ break;
7158
+ } catch (error) {
7159
+ if (!recoverInitialization || !isRecoverableIntercomDisconnect(error))
7160
+ throw error;
7161
+ const delayMs = RECONNECT_DELAYS_MS[retries];
7162
+ if (delayMs === undefined)
7163
+ return initializationFailure("Client disconnected", retries);
7164
+ try {
7165
+ await delay(delayMs, undefined, { signal: args[2] });
7166
+ } catch {
7167
+ return initializationFailure("Cancelled", retries);
7168
+ }
7169
+ retries += 1;
7170
+ }
7171
+ }
6947
7172
  handle.assertCurrent();
6948
7173
  const tool = handle.heavy.tools.get(name);
6949
7174
  if (!tool?.execute)
@@ -6952,6 +7177,13 @@ async function executeHeavyTool(loadHeavy, name, args) {
6952
7177
  handle.assertCurrent();
6953
7178
  return result;
6954
7179
  }
7180
+ function initializationFailure(reason, retries) {
7181
+ return {
7182
+ content: [{ type: "text", text: `${reason}. Intercom initialization stopped after ${retries} automatic retries. This operation was not sent.` }],
7183
+ isError: true,
7184
+ details: { error: true, terminal: true, automaticRetries: retries, outcome: "not_sent" }
7185
+ };
7186
+ }
6955
7187
  async function runHeavyCommand(loadHeavy, args, ctx) {
6956
7188
  const handle = await loadHeavy(ctx);
6957
7189
  handle.assertCurrent();
@@ -7634,7 +7866,7 @@ function intercom(pi, options = {}) {
7634
7866
  Use this to communicate findings, request help, or coordinate work with other sessions.
7635
7867
  Sessions belong to an intercom group and can ONLY message sessions in the same group; cross-group sends are rejected by the broker. Ungrouped sessions share the "default" group.
7636
7868
  For send, live session names and exact full session IDs remain supported. Workflow-stage targets use \`workflow:<rootRunId>/<segment>[/<segment>...]\`; \`*\` matches one segment and \`**\` any depth. Use \`intercom list\` inside the invocation group to see live, pending, and possible future targets with queued counts. \`workflow:<rootRunId>/**\` reaches live stages now and remains sticky for every future stage until root termination; valid targets outside the known set queue with a \`notInKnownSet\` warning and settle undeliverable at terminal only if never delivered. Use \`ask\` only on live targets.
7637
- If a \`send\`, \`ask\`, or \`reply\` fails with \`Client disconnected\`, retry that exact operation with the returned \`retryToken\`, up to three claimed attempts; omit the token for every fresh operation.
7869
+ For send/ask/reply, Intercom retries recoverable disconnects internally up to three times with the same operation identity. Each new tool call is a new operation. If recovery ends with an unknown delivery outcome, do not repeat it automatically.
7638
7870
  Usage:
7639
7871
  intercom({ action: "list" }) → List sessions in your group
7640
7872
  intercom({ action: "list", group: "name" }) → Read-only peek at another group's sessions
@@ -7643,12 +7875,11 @@ Usage:
7643
7875
  intercom({ action: "send", to: "session-name", message: "..." }) → Send message (own group only)
7644
7876
  intercom({ action: "ask", to: "session-name", message: "..." }) → Ask and wait for reply
7645
7877
  intercom({ action: "reply", message: "..." }) → Reply to the active or exact pending ask
7646
- intercom({ action: "send", to: "session-name", message: "...", retryToken: "..." }) → Claim the exact retry returned by a retryable failure
7647
7878
  intercom({ action: "pending" }) → List unresolved inbound asks
7648
7879
  intercom({ action: "status" }) → Show connection status and your group
7649
7880
 
7650
7881
  "default" is the shared group; "true" and "auto" are reserved for subagent auto-groups. Joining does not grant cross-group access; contact_supervisor remains the only cross-group path.`,
7651
- promptSnippet: "Use to coordinate with other local agent sessions in your intercom group. For a retryable send/ask/reply failure, repeat the exact operation with its returned retryToken; omit retryToken for fresh operations.",
7882
+ promptSnippet: "Use to coordinate with other local agent sessions in your intercom group. Send/ask/reply retry reconnects internally; do not automatically repeat an unknown delivery outcome.",
7652
7883
  parameters: Type3.Object({
7653
7884
  action: Type3.String({ description: "Action: 'list', 'join', 'leave', 'send', 'ask', 'reply', 'pending', or 'status'" }),
7654
7885
  to: Type3.Optional(Type3.String({ description: "Live session name, exact full session ID, or `workflow:<rootRunId>/<segment>[/<segment>...]` path; `*` matches one segment and `**` any depth. Send queues sticky pending/future delivery and `workflow:<rootRunId>/**` broadcasts to live and future stages; use `ask` only on live targets (for 'send', 'ask', or targeted 'reply')" })),
@@ -7660,10 +7891,15 @@ Usage:
7660
7891
  language: Type3.Optional(Type3.String())
7661
7892
  }))),
7662
7893
  replyTo: Type3.Optional(Type3.String({ description: "Exact pending-ask message ID; disambiguates concurrent asks, including asks from one sender" })),
7663
- retryToken: Type3.Optional(Type3.String({ minLength: 1, maxLength: 128, description: "Opaque token returned after a retryable send/ask/reply failure. Repeat the exact same action and arguments with it; omit it for fresh operations." })),
7664
7894
  group: Type3.Optional(Type3.String({ description: "Group name for 'join'; read-only group filter for 'list'/'status'. 'send'/'ask' are locked to your own group." }))
7665
7895
  }),
7666
- execute: (...args) => executeHeavyTool(loadHeavy, "intercom", args),
7896
+ execute: (...args) => {
7897
+ const invocationLease = activeLease;
7898
+ return executeHeavyTool((ctx) => {
7899
+ assertLease(invocationLease);
7900
+ return loadHeavy(ctx);
7901
+ }, "intercom", args);
7902
+ },
7667
7903
  renderResult: (...args) => renderHeavyToolResult(loadedHeavy?.heavy ?? null, "intercom", args),
7668
7904
  renderCall(args, theme) {
7669
7905
  const input = args;