remoteclaw 0.2.0 → 0.2.1

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 (181) hide show
  1. package/dist/{accounts-Qulj3jS8.js → accounts-B0V43QEN.js} +1 -1
  2. package/dist/{accounts-PoAEsvXo.js → accounts-DObM4hAF.js} +2 -2
  3. package/dist/{accounts-C_7Xc5wa.js → accounts-DZ4c6f7x.js} +1 -1
  4. package/dist/{active-listener-nMUQ-dVt.js → active-listener-DVLYzYd3.js} +1 -1
  5. package/dist/{agent-O04J-JEw.js → agent-B2leLOo0.js} +377 -355
  6. package/dist/{agent-scope-wbu0VZoq.js → agent-scope-CYJrXxD6.js} +1 -1
  7. package/dist/{agents-BbQIzW1N.js → agents-Eg0_nSnn.js} +1 -1
  8. package/dist/{banner-DONy2WbW.js → banner-B52X-rEb.js} +1 -1
  9. package/dist/{bindings-0dx8vqz9.js → bindings-AUVd82yI.js} +2 -2
  10. package/dist/boot/handler.js +46 -46
  11. package/dist/build-info.json +3 -3
  12. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  13. package/dist/{channel-activity-D47P56pj.js → channel-activity-Bydtz0cv.js} +2 -2
  14. package/dist/{channel-options-DWOSBsjN.js → channel-options-CD6ZBbON.js} +1 -1
  15. package/dist/{channel-options-JoYluwGr.js → channel-options-h1pCAx0w.js} +1 -1
  16. package/dist/{channel-web-YLHk99fU.js → channel-web-DbNWyl5A.js} +2 -2
  17. package/dist/{channel-web-Cvf5FKyf.js → channel-web-FA7MGFJO.js} +2 -2
  18. package/dist/{channels-cli-Be0_n1L2.js → channels-cli-BIArqz2T.js} +9 -9
  19. package/dist/{channels-cli-BoDA0aQ1.js → channels-cli-BZ5sRWaP.js} +9 -9
  20. package/dist/{chunk-C5Oai9vm.js → chunk-0ZB8yVlw.js} +1 -1
  21. package/dist/{cli-BEOzFl_6.js → cli-C8XFOFxS.js} +5 -5
  22. package/dist/{cli-D1ORFJ6n.js → cli-ifZiERUK.js} +5 -5
  23. package/dist/command-logger/handler.js +1 -1
  24. package/dist/{command-registry-D6LIEhaY.js → command-registry-kxjFHjjE.js} +9 -9
  25. package/dist/{commands-registry-CB3qR3Ui.js → commands-registry-BQrQnwzJ.js} +3 -3
  26. package/dist/{completion-cli-ohSjYC4v.js → completion-cli-eH6YXa0H.js} +1 -1
  27. package/dist/{completion-cli-D93-g9B7.js → completion-cli-wYa36YaL.js} +2 -2
  28. package/dist/{config-Ca5Dfk8O.js → config-BIrnJuXL.js} +8 -8
  29. package/dist/{config-cli-CJ1S3_VC.js → config-cli-BfJacpda.js} +1 -1
  30. package/dist/{config-cli-uJUr7Pe-.js → config-cli-CkJFUL61.js} +1 -1
  31. package/dist/{configure-CXjIsq-V.js → configure-C9cTz03s.js} +2 -2
  32. package/dist/{configure-BAlORoYU.js → configure-Dh-yP8hn.js} +2 -2
  33. package/dist/{deliver-BGpFaGMz.js → deliver-B5eZoNwr.js} +2 -2
  34. package/dist/{deliver-D3lJfcWr.js → deliver-Cu2kD7-u.js} +2 -2
  35. package/dist/{deliver-BTjGqSGN.js → deliver-z04wZfnQ.js} +8 -8
  36. package/dist/{dock-C0qWBS5h.js → dock-BQ3iSblF.js} +5 -5
  37. package/dist/{doctor-completion-CKGabXFn.js → doctor-completion-Cz3-0qwJ.js} +1 -1
  38. package/dist/{doctor-completion-Bo9yo8-v.js → doctor-completion-D6DqtWrm.js} +1 -1
  39. package/dist/entry.js +1 -1
  40. package/dist/{env-Bs-DOhs6.js → env-D3fELH5B.js} +1 -1
  41. package/dist/{errors-bgTXk4n7.js → errors-Bg7BK273.js} +1 -1
  42. package/dist/extensionAPI.js +23 -1
  43. package/dist/{fetch-C-q-x9xS.js → fetch--eFpeNac.js} +3 -3
  44. package/dist/{fetch-B_D1a6ac.js → fetch-C3R1kkzO.js} +1 -1
  45. package/dist/{gateway-cli-DC1V6Fdf.js → gateway-cli-DuMZZmMm.js} +23 -14
  46. package/dist/{gateway-cli-CUPV9YIf.js → gateway-cli-ZPbldBb7.js} +23 -14
  47. package/dist/{health-D5YyZkng.js → health-6NZ23ZCc.js} +5 -5
  48. package/dist/{health-uTVcqwOx.js → health-D6T18gwU.js} +5 -5
  49. package/dist/{heartbeat-visibility-Z_3IqRgn.js → heartbeat-visibility-CXLlnSbK.js} +1 -1
  50. package/dist/{heartbeat-visibility-GeWWsF3e.js → heartbeat-visibility-CksK28e2.js} +1 -1
  51. package/dist/{hook-runner-global-D8bMcDPD.js → hook-runner-global-DPdZsDAH.js} +1 -1
  52. package/dist/{hooks-cli-DToXVDBQ.js → hooks-cli-CQAdRG0h.js} +6 -6
  53. package/dist/{hooks-cli-CpWC6lUu.js → hooks-cli-c8IB_ozo.js} +6 -6
  54. package/dist/{image-ops-CAVojpnw.js → image-ops-CD4YRYFY.js} +2 -2
  55. package/dist/index.js +10 -10
  56. package/dist/{ir-CDjoXuIW.js → ir-BK7K3Bbu.js} +6 -6
  57. package/dist/{logger-Bp0X6yHd.js → logger-BKFID___.js} +1 -1
  58. package/dist/{login-DWKSrC5K.js → login-BYHOjw55.js} +6 -6
  59. package/dist/{login-qr-C7zaGKxz.js → login-qr-ZRBRz2BA.js} +8 -8
  60. package/dist/{markdown-tables-Bm7xJUcn.js → markdown-tables-CfM1ner1.js} +1 -1
  61. package/dist/{message-action-names-y0-o46BN.js → message-action-names-AEii-fdA.js} +5 -5
  62. package/dist/{message-action-names-PbKqmcBa.js → message-action-names-CPJVqkJL.js} +5 -5
  63. package/dist/{message-channel-BuWy8hEk.js → message-channel-tSSi5C96.js} +1 -1
  64. package/dist/{npm-resolution-BLL-hroo.js → npm-resolution-C6jVPSqS.js} +1 -1
  65. package/dist/{npm-resolution-o9lE9iRL.js → npm-resolution-CdEbWlwy.js} +1 -1
  66. package/dist/{onboard-BohVFYna.js → onboard-CVpITzvB.js} +2 -2
  67. package/dist/{onboard-channels-DMgpmtQu.js → onboard-channels-D664lpQl.js} +1 -1
  68. package/dist/{onboard-channels-DzuidyBQ.js → onboard-channels-DReWe-Pi.js} +1 -1
  69. package/dist/{onboard-BKfLjwEp.js → onboard-zh78fAIB.js} +2 -2
  70. package/dist/{onboarding-sWcrQljf.js → onboarding-BnS6FhcE.js} +3 -3
  71. package/dist/{onboarding-BLgEs3xo.js → onboarding-CCahs79c.js} +3 -3
  72. package/dist/{onboarding.finalize-D5VLM268.js → onboarding.finalize-CmYoFs6n.js} +9 -9
  73. package/dist/{onboarding.finalize-CLmpb0fB.js → onboarding.finalize-uTFFUZ8O.js} +10 -10
  74. package/dist/{onboarding.gateway-config-DsTEqzPz.js → onboarding.gateway-config-DQX6SBU8.js} +1 -1
  75. package/dist/{onboarding.gateway-config-D-ZMefuj.js → onboarding.gateway-config-DYjDeKEw.js} +1 -1
  76. package/dist/{outbound-CCvRhb_6.js → outbound-BCY7cG5r.js} +6 -6
  77. package/dist/{outbound-attachment-BXwueqll.js → outbound-attachment-6NNNORlp.js} +3 -3
  78. package/dist/{plugin-registry-C-OlCiRd.js → plugin-registry-BC1RH6cl.js} +1 -1
  79. package/dist/{plugin-registry-LBCvRwK8.js → plugin-registry-TC2kC2iG.js} +1 -1
  80. package/dist/plugin-sdk/agents/session-run-registry.d.ts +36 -0
  81. package/dist/plugin-sdk/{channel-web-CM3jOFIe.js → channel-web-DSYJDq30.js} +4 -4
  82. package/dist/plugin-sdk/{deliver-DOBaX9a2.js → deliver-BzPIWEw5.js} +1 -1
  83. package/dist/plugin-sdk/index.js +5 -5
  84. package/dist/plugin-sdk/{reply-sVftK2Ge.js → reply-Dzts0EiK.js} +22 -8
  85. package/dist/plugin-sdk/{reply-payloads-DybMtW8a.js → reply-payloads-DwsjAWzB.js} +7 -1
  86. package/dist/plugin-sdk/{subagent-registry-BfxxwQv4.js → subagent-registry-DrBYYinw.js} +221 -5
  87. package/dist/plugin-sdk/web-afnwTWMq.js +7 -0
  88. package/dist/{plugins-cli-DCkrm_Bp.js → plugins-cli-CModgvwT.js} +6 -6
  89. package/dist/{plugins-cli-ChGSPhWr.js → plugins-cli-CpdkQdKD.js} +6 -6
  90. package/dist/{plugins-ODda1fNU.js → plugins-sjrWIkqk.js} +4 -4
  91. package/dist/{preflight-B9B3VBaW.js → preflight-a80t-iPi.js} +63 -63
  92. package/dist/{program-DYx2DvMr.js → program-BlZGbNe5.js} +11 -11
  93. package/dist/{program-context-B_oA8k9e.js → program-context-BVx30291.js} +16 -16
  94. package/dist/{prompt-select-styled-tATNv5wG.js → prompt-select-styled-Bqov4T-S.js} +4 -4
  95. package/dist/{prompt-select-styled-CHuBVQoF.js → prompt-select-styled-CtPeDmXo.js} +4 -4
  96. package/dist/{provider-dispatcher-CaVZ8Nhx.js → provider-dispatcher-BD5K64cR.js} +44 -22
  97. package/dist/{redact-DUvSdQvv.js → redact-D2_cayCv.js} +1 -1
  98. package/dist/{register.agent-mJGdqH4r.js → register.agent-B89Ymzwt.js} +8 -8
  99. package/dist/{register.agent-CAkJcVgr.js → register.agent-CuhMDT3t.js} +7 -7
  100. package/dist/{register.configure-BhkIDDW5.js → register.configure-C8WcdyT6.js} +9 -9
  101. package/dist/{register.configure-DvwKyrwL.js → register.configure-b8Ic06Uw.js} +9 -9
  102. package/dist/{register.maintenance-CKwKHDhS.js → register.maintenance-BlMuoELU.js} +11 -11
  103. package/dist/{register.maintenance-vpQOTI6u.js → register.maintenance-D5RP4wO6.js} +10 -10
  104. package/dist/{register.message-h_ydGqf0.js → register.message-CSeNrxdd.js} +7 -7
  105. package/dist/{register.message-NSrj_UY0.js → register.message-D7jdDTte.js} +7 -7
  106. package/dist/{register.onboard-C08IBU41.js → register.onboard-CRiXHw0n.js} +3 -3
  107. package/dist/{register.onboard-CcOONokP.js → register.onboard-Dj8wICC1.js} +3 -3
  108. package/dist/{register.setup-BHbQcv1_.js → register.setup-8gos4jqr.js} +3 -3
  109. package/dist/{register.setup-JYGpPbA2.js → register.setup-C_-8vfKv.js} +3 -3
  110. package/dist/{register.status-health-sessions-CAVFepVm.js → register.status-health-sessions-CrCsnTEq.js} +9 -9
  111. package/dist/{register.status-health-sessions-CV4R4Fe2.js → register.status-health-sessions-Df9SxgpH.js} +8 -8
  112. package/dist/{register.subclis-pRE159Cu.js → register.subclis-CxT7d8Bs.js} +8 -8
  113. package/dist/{replies-Cu8SG6CK.js → replies-Dsu1hdd7.js} +3 -3
  114. package/dist/{reply-DqJBHDn_.js → reply-Ccq9RRYF.js} +44 -22
  115. package/dist/{reply-payloads-DbQW7c5s.js → reply-payloads-DwEnDy7C.js} +4 -4
  116. package/dist/{reply-payloads-C4mbcSP-.js → reply-payloads-KYLwM629.js} +1 -1
  117. package/dist/{reply-prefix-DwJ8gxoz.js → reply-prefix-DtQ_7Eac.js} +1 -1
  118. package/dist/{resolve-route-BBztqaX0.js → resolve-route-DFUMTbRD.js} +4 -4
  119. package/dist/{response-prefix-template-BgDMziqu.js → response-prefix-template-DDQsoC2g.js} +1 -1
  120. package/dist/{run-main-D4CHxIUS.js → run-main-3RfLQTiu.js} +17 -17
  121. package/dist/{send-D3Uuw_MA.js → send-4gX7wep2.js} +8 -8
  122. package/dist/{send-CeBdN3Dp.js → send-CgAV9I1-.js} +15 -15
  123. package/dist/{send-DgVCmydL.js → send-CkPRLaz-.js} +8 -8
  124. package/dist/{send-C2J41ICD.js → send-DBeVQI-J.js} +7 -7
  125. package/dist/{send-Cibl-r-E.js → send-fdOUhBcN.js} +10 -10
  126. package/dist/{server-node-events-B60wtfXc.js → server-node-events-CRRE92S3.js} +6 -6
  127. package/dist/{server-node-events-DdwEsXLN.js → server-node-events-wpvPI-kw.js} +6 -6
  128. package/dist/{session-Bj8e8O8R.js → session-IUmTrU6A.js} +4 -4
  129. package/dist/{session-utils-CpgeP4rB.js → session-utils-ChEnoQCt.js} +1 -1
  130. package/dist/{session-utils-BUNcG-B2.js → session-utils-Dq5uiNDE.js} +1 -1
  131. package/dist/{sessions-3ACDrmHu.js → sessions-C6O5qrbx.js} +7 -1
  132. package/dist/{sessions-BePPqEtN.js → sessions-D5CiijxL.js} +12 -6
  133. package/dist/{sessions-n_z2PE4-.js → sessions-DPke45uf.js} +2 -2
  134. package/dist/{shell-env-DPAvieDD.js → shell-env-CKQ7fvtT.js} +1 -1
  135. package/dist/{status-BLKhFWFc.js → status-BeGUnsBd.js} +4 -4
  136. package/dist/{status-Ccfq5H-G.js → status-uyg2yOTM.js} +4 -4
  137. package/dist/{store-BS8fRU9w.js → store-BfW5-y9S.js} +7 -1
  138. package/dist/{subagent-registry-DIReZNw1.js → subagent-registry-BTv48FFX.js} +239 -6
  139. package/dist/{subagent-registry-DvnyYXMs.js → subagent-registry-D2yHvOBr.js} +238 -22
  140. package/dist/{subagent-registry-DMTgcI99.js → subagent-registry-DljM1oxO.js} +239 -6
  141. package/dist/{subsystem-DLQY6iY4.js → subsystem-9R2eOxp2.js} +2 -2
  142. package/dist/{tables-Bk8AXTIS.js → tables-CDsRjvfB.js} +2 -2
  143. package/dist/{tokens-CgIfCmK3.js → tokens-CFajuiSx.js} +1 -1
  144. package/dist/{tool-images-BMnWMHwL.js → tool-images-Cmsx31Bo.js} +1 -1
  145. package/dist/{update-cli-DCK9HF3t.js → update-cli-ChJoLU8L.js} +11 -11
  146. package/dist/{update-cli-1qesJ1_a.js → update-cli-DaW75dJC.js} +10 -10
  147. package/dist/{web-DG3SWzn_.js → web-BS0azDPB.js} +6 -6
  148. package/dist/{web-CCw02lmy.js → web-C_Alo-mS.js} +6 -6
  149. package/dist/{web-CKces-ap.js → web-DHXIgMOC.js} +50 -50
  150. package/dist/{whatsapp-actions-BzyFEHw4.js → whatsapp-actions-sR-u0T6U.js} +21 -21
  151. package/extensions/bluebubbles/package.json +1 -1
  152. package/extensions/diagnostics-otel/package.json +1 -1
  153. package/extensions/discord/package.json +1 -1
  154. package/extensions/feishu/package.json +1 -1
  155. package/extensions/googlechat/package.json +1 -1
  156. package/extensions/imessage/package.json +1 -1
  157. package/extensions/irc/package.json +1 -1
  158. package/extensions/line/package.json +1 -1
  159. package/extensions/matrix/package.json +1 -1
  160. package/extensions/mattermost/package.json +1 -1
  161. package/extensions/msteams/package.json +1 -1
  162. package/extensions/nextcloud-talk/package.json +1 -1
  163. package/extensions/nostr/package.json +1 -1
  164. package/extensions/signal/package.json +1 -1
  165. package/extensions/slack/package.json +1 -1
  166. package/extensions/synology-chat/package.json +1 -1
  167. package/extensions/telegram/package.json +1 -1
  168. package/extensions/tlon/package.json +1 -1
  169. package/extensions/twitch/package.json +1 -1
  170. package/extensions/voice-call/package.json +1 -1
  171. package/extensions/whatsapp/package.json +1 -1
  172. package/extensions/zalo/package.json +1 -1
  173. package/extensions/zalouser/package.json +1 -1
  174. package/package.json +1 -1
  175. package/dist/plugin-sdk/web-C24fSRzu.js +0 -7
  176. /package/dist/{fetch-timeout-DTIN7CGM.js → fetch-timeout-jOIu9Xud.js} +0 -0
  177. /package/dist/{file-lock-BftAtpBn.js → file-lock-CEhZlbAi.js} +0 -0
  178. /package/dist/{ip-B27WD9wk.js → ip-N_XHHVsM.js} +0 -0
  179. /package/dist/{json-file-CRyYLqpu.js → json-file-DYQIVLc1.js} +0 -0
  180. /package/dist/{render-DSLzcBxk.js → render-TpKSK5RV.js} +0 -0
  181. /package/dist/{target-errors-owiG6LWY.js → target-errors-D7fLx8zG.js} +0 -0
@@ -1,27 +1,27 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
2
- import { M as resolveUserPath, P as shortenHomeInString, S as CONFIG_DIR, T as escapeRegExp, at as resolveGatewayPort, r as defaultRuntime, rt as resolveConfigPath, st as resolveStateDir, t as createSubsystemLogger, w as ensureDir$1 } from "./subsystem-DLQY6iY4.js";
2
+ import { M as resolveUserPath, P as shortenHomeInString, S as CONFIG_DIR, T as escapeRegExp, at as resolveGatewayPort, r as defaultRuntime, rt as resolveConfigPath, st as resolveStateDir, t as createSubsystemLogger, w as ensureDir$1 } from "./subsystem-9R2eOxp2.js";
3
3
  import { _ as parseAgentSessionKey, c as resolveAgentIdFromSessionKey, f as normalizeAccountId, g as getSubagentDepth, s as normalizeMainKey } from "./session-key-X7pmdLBX.js";
4
- import { d as resolveSessionAgentId, u as resolveDefaultAgentId } from "./agent-scope-wbu0VZoq.js";
5
- import { i as isSilentReplyText, n as SILENT_REPLY_TOKEN, t as HEARTBEAT_TOKEN } from "./tokens-CgIfCmK3.js";
6
- import { r as normalizeChannelId, t as getChannelPlugin } from "./plugins-ODda1fNU.js";
7
- import { K as DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH, t as loadConfig, y as parseDurationMs } from "./config-Ca5Dfk8O.js";
8
- import { c as GATEWAY_CLIENT_IDS, i as isInternalMessageChannel, l as GATEWAY_CLIENT_MODES, n as isDeliverableMessageChannel, o as normalizeMessageChannel, t as INTERNAL_MESSAGE_CHANNEL, u as GATEWAY_CLIENT_NAMES } from "./message-channel-BuWy8hEk.js";
9
- import { F as resolveStorePath, R as resolveMainSessionKey, S as INPUT_PROVENANCE_KIND_VALUES, h as normalizeDeliveryContext, m as mergeDeliveryContext, p as deliveryContextFromSession, s as loadSessionStore } from "./sessions-BePPqEtN.js";
10
- import { n as logError, t as logDebug } from "./logger-Bp0X6yHd.js";
11
- import { h as getGlobalHookRunner, m as sanitizeUserFacingText, s as shouldSuppressReasoningPayload } from "./reply-payloads-DbQW7c5s.js";
12
- import { s as isLoopbackIpAddress } from "./ip-B27WD9wk.js";
13
- import { a as resolveEffectiveMessagesConfig, n as resolveResponsePrefixTemplate } from "./response-prefix-template-BgDMziqu.js";
14
- import { n as saveJsonFile, t as loadJsonFile } from "./json-file-CRyYLqpu.js";
4
+ import { d as resolveSessionAgentId, u as resolveDefaultAgentId } from "./agent-scope-CYJrXxD6.js";
5
+ import { i as isSilentReplyText, n as SILENT_REPLY_TOKEN, t as HEARTBEAT_TOKEN } from "./tokens-CFajuiSx.js";
6
+ import { r as normalizeChannelId, t as getChannelPlugin } from "./plugins-sjrWIkqk.js";
7
+ import { K as DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH, t as loadConfig, y as parseDurationMs } from "./config-BIrnJuXL.js";
8
+ import { c as GATEWAY_CLIENT_IDS, i as isInternalMessageChannel, l as GATEWAY_CLIENT_MODES, n as isDeliverableMessageChannel, o as normalizeMessageChannel, t as INTERNAL_MESSAGE_CHANNEL, u as GATEWAY_CLIENT_NAMES } from "./message-channel-tSSi5C96.js";
9
+ import { C as INPUT_PROVENANCE_KIND_VALUES, I as resolveStorePath, g as normalizeDeliveryContext, h as mergeDeliveryContext, m as deliveryContextKey, p as deliveryContextFromSession, s as loadSessionStore, z as resolveMainSessionKey } from "./sessions-D5CiijxL.js";
10
+ import { n as saveJsonFile, t as loadJsonFile } from "./json-file-DYQIVLc1.js";
11
+ import { n as logError, t as logDebug } from "./logger-BKFID___.js";
12
+ import { h as getGlobalHookRunner, m as sanitizeUserFacingText, s as shouldSuppressReasoningPayload } from "./reply-payloads-DwEnDy7C.js";
13
+ import { s as isLoopbackIpAddress } from "./ip-N_XHHVsM.js";
14
+ import { a as resolveEffectiveMessagesConfig, n as resolveResponsePrefixTemplate } from "./response-prefix-template-DDQsoC2g.js";
15
15
  import path from "node:path";
16
16
  import fs from "node:fs";
17
17
  import os from "node:os";
18
- import JSON5 from "json5";
18
+ import json5 from "json5";
19
19
  import { promisify } from "node:util";
20
20
  import fs$1 from "node:fs/promises";
21
21
  import crypto, { X509Certificate, randomUUID } from "node:crypto";
22
22
  import { execFile } from "node:child_process";
23
23
  import AjvPkg from "ajv";
24
- import { WebSocket } from "ws";
24
+ import { WebSocket as WebSocket$1 } from "ws";
25
25
  import { Buffer as Buffer$1 } from "node:buffer";
26
26
  import { Type } from "@sinclair/typebox";
27
27
 
@@ -153,6 +153,41 @@ function onAgentEvent(listener) {
153
153
  return () => listeners.delete(listener);
154
154
  }
155
155
 
156
+ //#endregion
157
+ //#region src/agents/session-run-registry.ts
158
+ const ACTIVE_SESSION_RUNS = /* @__PURE__ */ new Map();
159
+ /** Check whether a session currently has an active CLI agent turn. */
160
+ function isSessionRunActive(sessionKey) {
161
+ return ACTIVE_SESSION_RUNS.has(sessionKey);
162
+ }
163
+ /** Register an active session run. */
164
+ function registerSessionRun(sessionKey, handle) {
165
+ ACTIVE_SESSION_RUNS.set(sessionKey, handle);
166
+ }
167
+ /** Unregister a session run (on turn completion or crash). */
168
+ function unregisterSessionRun(sessionKey) {
169
+ ACTIVE_SESSION_RUNS.delete(sessionKey);
170
+ }
171
+ /**
172
+ * Kill an active session run by aborting its controller or sending SIGTERM to its PID.
173
+ * Returns `true` if a kill signal was dispatched.
174
+ */
175
+ function killSessionRun(sessionKey) {
176
+ const handle = ACTIVE_SESSION_RUNS.get(sessionKey);
177
+ if (!handle) return false;
178
+ if (handle.abortController && !handle.abortController.signal.aborted) {
179
+ handle.abortController.abort();
180
+ return true;
181
+ }
182
+ if (typeof handle.pid === "number") try {
183
+ process.kill(handle.pid, "SIGTERM");
184
+ return true;
185
+ } catch {
186
+ return false;
187
+ }
188
+ return false;
189
+ }
190
+
156
191
  //#endregion
157
192
  //#region src/process/lanes.ts
158
193
  let CommandLane = /* @__PURE__ */ function(CommandLane) {
@@ -1860,7 +1895,7 @@ var GatewayClient = class {
1860
1895
  if (fingerprint !== expected) return /* @__PURE__ */ new Error("gateway tls fingerprint mismatch");
1861
1896
  });
1862
1897
  }
1863
- this.ws = new WebSocket(url, wsOptions);
1898
+ this.ws = new WebSocket$1(url, wsOptions);
1864
1899
  this.ws.on("open", () => {
1865
1900
  if (url.startsWith("wss://") && this.opts.tlsFingerprint) {
1866
1901
  const tlsError = this.validateTlsFingerprint();
@@ -2056,7 +2091,7 @@ var GatewayClient = class {
2056
2091
  const connectChallengeTimeoutMs = typeof rawConnectDelayMs === "number" && Number.isFinite(rawConnectDelayMs) ? Math.max(250, Math.min(1e4, rawConnectDelayMs)) : 2e3;
2057
2092
  if (this.connectTimer) clearTimeout(this.connectTimer);
2058
2093
  this.connectTimer = setTimeout(() => {
2059
- if (this.connectSent || this.ws?.readyState !== WebSocket.OPEN) return;
2094
+ if (this.connectSent || this.ws?.readyState !== WebSocket$1.OPEN) return;
2060
2095
  this.opts.onConnectError?.(/* @__PURE__ */ new Error("gateway connect challenge timeout"));
2061
2096
  this.ws?.close(1008, "connect challenge timeout");
2062
2097
  }, connectChallengeTimeoutMs);
@@ -2098,7 +2133,7 @@ var GatewayClient = class {
2098
2133
  return null;
2099
2134
  }
2100
2135
  async request(method, params, opts) {
2101
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error("gateway not connected");
2136
+ if (!this.ws || this.ws.readyState !== WebSocket$1.OPEN) throw new Error("gateway not connected");
2102
2137
  const id = randomUUID();
2103
2138
  const frame = {
2104
2139
  type: "req",
@@ -2629,6 +2664,134 @@ function hasCrossChannelItems(items, resolveKey) {
2629
2664
  return keys.size > 1;
2630
2665
  }
2631
2666
 
2667
+ //#endregion
2668
+ //#region src/agents/subagent-announce-queue.ts
2669
+ const ANNOUNCE_QUEUES = /* @__PURE__ */ new Map();
2670
+ function getAnnounceQueue(key, settings, send) {
2671
+ const existing = ANNOUNCE_QUEUES.get(key);
2672
+ if (existing) {
2673
+ applyQueueRuntimeSettings({
2674
+ target: existing,
2675
+ settings
2676
+ });
2677
+ existing.send = send;
2678
+ return existing;
2679
+ }
2680
+ const created = {
2681
+ items: [],
2682
+ draining: false,
2683
+ lastEnqueuedAt: 0,
2684
+ mode: settings.mode,
2685
+ debounceMs: typeof settings.debounceMs === "number" ? Math.max(0, settings.debounceMs) : 1e3,
2686
+ cap: typeof settings.cap === "number" && settings.cap > 0 ? Math.floor(settings.cap) : 20,
2687
+ dropPolicy: settings.dropPolicy ?? "summarize",
2688
+ droppedCount: 0,
2689
+ summaryLines: [],
2690
+ send,
2691
+ consecutiveFailures: 0
2692
+ };
2693
+ applyQueueRuntimeSettings({
2694
+ target: created,
2695
+ settings
2696
+ });
2697
+ ANNOUNCE_QUEUES.set(key, created);
2698
+ return created;
2699
+ }
2700
+ function hasAnnounceCrossChannelItems(items) {
2701
+ return hasCrossChannelItems(items, (item) => {
2702
+ if (!item.origin) return {};
2703
+ if (!item.originKey) return { cross: true };
2704
+ return { key: item.originKey };
2705
+ });
2706
+ }
2707
+ function scheduleAnnounceDrain(key) {
2708
+ const queue = beginQueueDrain(ANNOUNCE_QUEUES, key);
2709
+ if (!queue) return;
2710
+ (async () => {
2711
+ try {
2712
+ const collectState = { forceIndividualCollect: false };
2713
+ for (;;) {
2714
+ if (queue.items.length === 0 && queue.droppedCount === 0) break;
2715
+ await waitForQueueDebounce(queue);
2716
+ if (queue.mode === "collect") {
2717
+ const collectDrainResult = await drainCollectQueueStep({
2718
+ collectState,
2719
+ isCrossChannel: hasAnnounceCrossChannelItems(queue.items),
2720
+ items: queue.items,
2721
+ run: async (item) => await queue.send(item)
2722
+ });
2723
+ if (collectDrainResult === "empty") break;
2724
+ if (collectDrainResult === "drained") continue;
2725
+ const items = queue.items.slice();
2726
+ const summary = previewQueueSummaryPrompt({
2727
+ state: queue,
2728
+ noun: "announce"
2729
+ });
2730
+ const prompt = buildCollectPrompt({
2731
+ title: "[Queued announce messages while agent was busy]",
2732
+ items,
2733
+ summary,
2734
+ renderItem: (item, idx) => `---\nQueued #${idx + 1}\n${item.prompt}`.trim()
2735
+ });
2736
+ const last = items.at(-1);
2737
+ if (!last) break;
2738
+ await queue.send({
2739
+ ...last,
2740
+ prompt
2741
+ });
2742
+ queue.items.splice(0, items.length);
2743
+ if (summary) clearQueueSummaryState(queue);
2744
+ continue;
2745
+ }
2746
+ const summaryPrompt = previewQueueSummaryPrompt({
2747
+ state: queue,
2748
+ noun: "announce"
2749
+ });
2750
+ if (summaryPrompt) {
2751
+ if (!await drainNextQueueItem(queue.items, async (item) => await queue.send({
2752
+ ...item,
2753
+ prompt: summaryPrompt
2754
+ }))) break;
2755
+ clearQueueSummaryState(queue);
2756
+ continue;
2757
+ }
2758
+ if (!await drainNextQueueItem(queue.items, async (item) => await queue.send(item))) break;
2759
+ }
2760
+ queue.consecutiveFailures = 0;
2761
+ } catch (err) {
2762
+ queue.consecutiveFailures++;
2763
+ const errorBackoffMs = Math.min(1e3 * Math.pow(2, queue.consecutiveFailures), 6e4);
2764
+ const retryDelayMs = Math.max(errorBackoffMs, queue.debounceMs);
2765
+ queue.lastEnqueuedAt = Date.now() + retryDelayMs - queue.debounceMs;
2766
+ defaultRuntime.error?.(`announce queue drain failed for ${key} (attempt ${queue.consecutiveFailures}, retry in ${Math.round(retryDelayMs / 1e3)}s): ${String(err)}`);
2767
+ } finally {
2768
+ queue.draining = false;
2769
+ if (queue.items.length === 0 && queue.droppedCount === 0) ANNOUNCE_QUEUES.delete(key);
2770
+ else scheduleAnnounceDrain(key);
2771
+ }
2772
+ })();
2773
+ }
2774
+ function enqueueAnnounce(params) {
2775
+ const queue = getAnnounceQueue(params.key, params.settings, params.send);
2776
+ queue.lastEnqueuedAt = Math.max(queue.lastEnqueuedAt, Date.now());
2777
+ if (!applyQueueDropPolicy({
2778
+ queue,
2779
+ summarize: (item) => item.summaryLine?.trim() || item.prompt.trim()
2780
+ })) {
2781
+ if (queue.dropPolicy === "new") scheduleAnnounceDrain(params.key);
2782
+ return false;
2783
+ }
2784
+ const origin = normalizeDeliveryContext(params.item.origin);
2785
+ const originKey = deliveryContextKey(origin);
2786
+ queue.items.push({
2787
+ ...params.item,
2788
+ origin,
2789
+ originKey
2790
+ });
2791
+ scheduleAnnounceDrain(params.key);
2792
+ return true;
2793
+ }
2794
+
2632
2795
  //#endregion
2633
2796
  //#region src/auto-reply/reply/directive-parsing.ts
2634
2797
  function skipDirectiveArgPrefix(raw) {
@@ -4393,7 +4556,7 @@ async function routeReply(params) {
4393
4556
  const resolvedReplyToId = replyToId ?? (channelId === "slack" && threadId != null && threadId !== "" ? String(threadId) : void 0);
4394
4557
  const resolvedThreadId = channelId === "slack" ? null : threadId ?? null;
4395
4558
  try {
4396
- const { deliverOutboundPayloads } = await import("./deliver-BTjGqSGN.js").then((n) => n.n);
4559
+ const { deliverOutboundPayloads } = await import("./deliver-z04wZfnQ.js").then((n) => n.n);
4397
4560
  const outboundSession = buildOutboundSessionContext({
4398
4561
  cfg,
4399
4562
  agentId: resolvedAgentId,
@@ -4855,6 +5018,11 @@ function buildAnnounceIdFromChildRun(params) {
4855
5018
  function buildAnnounceIdempotencyKey(announceId) {
4856
5019
  return `announce:${announceId}`;
4857
5020
  }
5021
+ function resolveQueueAnnounceId(params) {
5022
+ const announceId = params.announceId?.trim();
5023
+ if (announceId) return announceId;
5024
+ return `legacy:${params.sessionKey}:${params.enqueuedAt}`;
5025
+ }
4858
5026
 
4859
5027
  //#endregion
4860
5028
  //#region src/agents/subagent-depth.ts
@@ -4874,7 +5042,7 @@ function normalizeSessionKey(value) {
4874
5042
  function readSessionStore(storePath) {
4875
5043
  try {
4876
5044
  const raw = fs.readFileSync(storePath, "utf-8");
4877
- const parsed = JSON5.parse(raw);
5045
+ const parsed = json5.parse(raw);
4878
5046
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
4879
5047
  } catch {}
4880
5048
  return {};
@@ -6159,6 +6327,31 @@ async function resolveSubagentCompletionOrigin(params) {
6159
6327
  };
6160
6328
  }
6161
6329
  }
6330
+ async function sendAnnounce(item) {
6331
+ const announceTimeoutMs = resolveSubagentAnnounceTimeoutMs(loadConfig());
6332
+ const requesterIsSubagent = getSubagentDepthFromSessionStore(item.sessionKey) >= 1;
6333
+ const origin = item.origin;
6334
+ const threadId = origin?.threadId != null && origin.threadId !== "" ? String(origin.threadId) : void 0;
6335
+ const idempotencyKey = buildAnnounceIdempotencyKey(resolveQueueAnnounceId({
6336
+ announceId: item.announceId,
6337
+ sessionKey: item.sessionKey,
6338
+ enqueuedAt: item.enqueuedAt
6339
+ }));
6340
+ await callGateway({
6341
+ method: "agent",
6342
+ params: {
6343
+ sessionKey: item.sessionKey,
6344
+ message: item.prompt,
6345
+ channel: requesterIsSubagent ? void 0 : origin?.channel,
6346
+ accountId: requesterIsSubagent ? void 0 : origin?.accountId,
6347
+ to: requesterIsSubagent ? void 0 : origin?.to,
6348
+ threadId: requesterIsSubagent ? void 0 : threadId,
6349
+ deliver: !requesterIsSubagent,
6350
+ idempotencyKey
6351
+ },
6352
+ timeoutMs: announceTimeoutMs
6353
+ });
6354
+ }
6162
6355
  function resolveRequesterStoreKey(cfg, requesterSessionKey) {
6163
6356
  const raw = (requesterSessionKey ?? "").trim();
6164
6357
  if (!raw) return raw;
@@ -6178,17 +6371,40 @@ function loadRequesterSessionEntry(requesterSessionKey) {
6178
6371
  canonicalKey
6179
6372
  };
6180
6373
  }
6374
+ function buildAnnounceQueueKey(sessionKey, origin) {
6375
+ const accountId = normalizeAccountId(origin?.accountId);
6376
+ if (!accountId) return sessionKey;
6377
+ return `${sessionKey}:acct:${accountId}`;
6378
+ }
6181
6379
  async function maybeQueueSubagentAnnounce(params) {
6182
6380
  if (params.signal?.aborted) return "none";
6183
6381
  const { cfg, entry } = loadRequesterSessionEntry(params.requesterSessionKey);
6184
- resolveRequesterStoreKey(cfg, params.requesterSessionKey);
6382
+ const canonicalKey = resolveRequesterStoreKey(cfg, params.requesterSessionKey);
6185
6383
  if (!entry?.sessionId) return "none";
6186
6384
  const queueSettings = resolveQueueSettings({
6187
6385
  cfg,
6188
6386
  channel: entry?.channel ?? entry?.lastChannel,
6189
6387
  sessionEntry: entry
6190
6388
  });
6191
- queueSettings.mode === "followup" || queueSettings.mode === "collect" || queueSettings.mode === "steer-backlog" || queueSettings.mode;
6389
+ const isActive = isSessionRunActive(canonicalKey);
6390
+ const shouldFollowup = queueSettings.mode === "followup" || queueSettings.mode === "collect" || queueSettings.mode === "steer-backlog" || queueSettings.mode === "interrupt";
6391
+ if (isActive && (shouldFollowup || queueSettings.mode === "steer")) {
6392
+ const origin = resolveAnnounceOrigin(entry, params.requesterOrigin);
6393
+ enqueueAnnounce({
6394
+ key: buildAnnounceQueueKey(canonicalKey, origin),
6395
+ item: {
6396
+ announceId: params.announceId,
6397
+ prompt: params.triggerMessage,
6398
+ summaryLine: params.summaryLine,
6399
+ enqueuedAt: Date.now(),
6400
+ sessionKey: canonicalKey,
6401
+ origin
6402
+ },
6403
+ settings: queueSettings,
6404
+ send: sendAnnounce
6405
+ });
6406
+ return "queued";
6407
+ }
6192
6408
  return "none";
6193
6409
  }
6194
6410
  function queueOutcomeToDeliveryResult(outcome) {
@@ -7540,4 +7756,4 @@ function countActiveDescendantRuns(rootSessionKey) {
7540
7756
  }
7541
7757
 
7542
7758
  //#endregion
7543
- export { createReceiptCard as A, logWebhookReceived as B, resolveQueueSettings as C, isRoutableChannel as D, scheduleFollowupDrain as E, logMessageProcessed as F, extractQueueDirective as G, stopDiagnosticHeartbeat as H, logMessageQueued as I, AGENT_LANE_SUBAGENT as J, callGateway as K, logSessionStateChange as L, clearSessionQueues as M, clearCommandLane as N, routeReply as O, getQueueSize as P, resolveGatewayCredentialsFromConfig as Q, logWebhookError as R, unregisterSessionBindingAdapter as S, getFollowupQueueDepth as T, emitDiagnosticEvent as U, startDiagnosticHeartbeat as V, isDiagnosticsEnabled as W, emitAgentEvent as X, clearAgentRunContext as Y, registerAgentRunContext as Z, resolveMainSessionAlias as _, markSubagentRunTerminated as a, getSessionBindingService as b, subagent_registry_exports as c, extractAssistantText as d, sanitizeTextContent as f, resolveInternalSessionKey as g, resolveDisplaySessionKey as h, markSubagentRunForSteerRestart as i, buildOutboundSessionContext as j, normalizeReplyPayload as k, resolveAgentTimeoutMs as l, stripReasoningTagsFromText as m, countActiveRunsForSession as n, registerSubagentRun as o, stripToolMessages as p, AGENT_LANE_NESTED as q, listSubagentRunsForRequester as r, replaceSubagentRunAfterSteer as s, clearSubagentRunSteerRestart as t, buildSubagentSystemPrompt as u, getSubagentDepthFromSessionStore as v, enqueueFollowupRun as w, registerSessionBindingAdapter as x, extractTextFromChatContent as y, logWebhookProcessed as z };
7759
+ export { clearAgentRunContext as $, createReceiptCard as A, logWebhookReceived as B, resolveQueueSettings as C, isRoutableChannel as D, scheduleFollowupDrain as E, logMessageProcessed as F, extractQueueDirective as G, stopDiagnosticHeartbeat as H, logMessageQueued as I, AGENT_LANE_SUBAGENT as J, callGateway as K, logSessionStateChange as L, clearSessionQueues as M, clearCommandLane as N, routeReply as O, getQueueSize as P, unregisterSessionRun as Q, logWebhookError as R, unregisterSessionBindingAdapter as S, getFollowupQueueDepth as T, emitDiagnosticEvent as U, startDiagnosticHeartbeat as V, isDiagnosticsEnabled as W, killSessionRun as X, isSessionRunActive as Y, registerSessionRun as Z, resolveMainSessionAlias as _, markSubagentRunTerminated as a, getSessionBindingService as b, subagent_registry_exports as c, extractAssistantText as d, emitAgentEvent as et, sanitizeTextContent as f, resolveInternalSessionKey as g, resolveDisplaySessionKey as h, markSubagentRunForSteerRestart as i, buildOutboundSessionContext as j, normalizeReplyPayload as k, resolveAgentTimeoutMs as l, stripReasoningTagsFromText as m, countActiveRunsForSession as n, resolveGatewayCredentialsFromConfig as nt, registerSubagentRun as o, stripToolMessages as p, AGENT_LANE_NESTED as q, listSubagentRunsForRequester as r, replaceSubagentRunAfterSteer as s, clearSubagentRunSteerRestart as t, registerAgentRunContext as tt, buildSubagentSystemPrompt as u, getSubagentDepthFromSessionStore as v, enqueueFollowupRun as w, registerSessionBindingAdapter as x, extractTextFromChatContent as y, logWebhookProcessed as z };
@@ -10,9 +10,9 @@ import { et as DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH, i as loadConfig } from "./confi
10
10
  import { g as parseDurationMs } from "./zod-schema-C2MssSI0.js";
11
11
  import { r as normalizeChannelId$1, t as getChannelPlugin } from "./plugins-BzN42FWt.js";
12
12
  import { i as isSilentReplyText, n as SILENT_REPLY_TOKEN, t as HEARTBEAT_TOKEN } from "./tokens-DJrhANSO.js";
13
- import { p as getGlobalHookRunner, s as shouldSuppressReasoningPayload } from "./reply-payloads-C4mbcSP-.js";
13
+ import { p as getGlobalHookRunner, s as shouldSuppressReasoningPayload } from "./reply-payloads-KYLwM629.js";
14
14
  import { m as resolveStorePath } from "./chat-envelope-DPKIEKwe.js";
15
- import { X as resolveMainSessionKey, d as deliveryContextFromSession, f as mergeDeliveryContext, n as loadSessionStore, p as normalizeDeliveryContext } from "./store-BS8fRU9w.js";
15
+ import { Z as resolveMainSessionKey, d as deliveryContextFromSession, f as deliveryContextKey, m as normalizeDeliveryContext, n as loadSessionStore, p as mergeDeliveryContext } from "./store-BfW5-y9S.js";
16
16
  import { n as saveJsonFile, t as loadJsonFile } from "./json-file-BTOmHNpk.js";
17
17
  import { n as callGateway } from "./call-CzzsQW8Z.js";
18
18
  import { a as resolveEffectiveMessagesConfig, n as resolveResponsePrefixTemplate } from "./response-prefix-template-QvNeSzmd.js";
@@ -985,6 +985,134 @@ function hasCrossChannelItems(items, resolveKey) {
985
985
  return keys.size > 1;
986
986
  }
987
987
 
988
+ //#endregion
989
+ //#region src/agents/subagent-announce-queue.ts
990
+ const ANNOUNCE_QUEUES = /* @__PURE__ */ new Map();
991
+ function getAnnounceQueue(key, settings, send) {
992
+ const existing = ANNOUNCE_QUEUES.get(key);
993
+ if (existing) {
994
+ applyQueueRuntimeSettings({
995
+ target: existing,
996
+ settings
997
+ });
998
+ existing.send = send;
999
+ return existing;
1000
+ }
1001
+ const created = {
1002
+ items: [],
1003
+ draining: false,
1004
+ lastEnqueuedAt: 0,
1005
+ mode: settings.mode,
1006
+ debounceMs: typeof settings.debounceMs === "number" ? Math.max(0, settings.debounceMs) : 1e3,
1007
+ cap: typeof settings.cap === "number" && settings.cap > 0 ? Math.floor(settings.cap) : 20,
1008
+ dropPolicy: settings.dropPolicy ?? "summarize",
1009
+ droppedCount: 0,
1010
+ summaryLines: [],
1011
+ send,
1012
+ consecutiveFailures: 0
1013
+ };
1014
+ applyQueueRuntimeSettings({
1015
+ target: created,
1016
+ settings
1017
+ });
1018
+ ANNOUNCE_QUEUES.set(key, created);
1019
+ return created;
1020
+ }
1021
+ function hasAnnounceCrossChannelItems(items) {
1022
+ return hasCrossChannelItems(items, (item) => {
1023
+ if (!item.origin) return {};
1024
+ if (!item.originKey) return { cross: true };
1025
+ return { key: item.originKey };
1026
+ });
1027
+ }
1028
+ function scheduleAnnounceDrain(key) {
1029
+ const queue = beginQueueDrain(ANNOUNCE_QUEUES, key);
1030
+ if (!queue) return;
1031
+ (async () => {
1032
+ try {
1033
+ const collectState = { forceIndividualCollect: false };
1034
+ for (;;) {
1035
+ if (queue.items.length === 0 && queue.droppedCount === 0) break;
1036
+ await waitForQueueDebounce(queue);
1037
+ if (queue.mode === "collect") {
1038
+ const collectDrainResult = await drainCollectQueueStep({
1039
+ collectState,
1040
+ isCrossChannel: hasAnnounceCrossChannelItems(queue.items),
1041
+ items: queue.items,
1042
+ run: async (item) => await queue.send(item)
1043
+ });
1044
+ if (collectDrainResult === "empty") break;
1045
+ if (collectDrainResult === "drained") continue;
1046
+ const items = queue.items.slice();
1047
+ const summary = previewQueueSummaryPrompt({
1048
+ state: queue,
1049
+ noun: "announce"
1050
+ });
1051
+ const prompt = buildCollectPrompt({
1052
+ title: "[Queued announce messages while agent was busy]",
1053
+ items,
1054
+ summary,
1055
+ renderItem: (item, idx) => `---\nQueued #${idx + 1}\n${item.prompt}`.trim()
1056
+ });
1057
+ const last = items.at(-1);
1058
+ if (!last) break;
1059
+ await queue.send({
1060
+ ...last,
1061
+ prompt
1062
+ });
1063
+ queue.items.splice(0, items.length);
1064
+ if (summary) clearQueueSummaryState(queue);
1065
+ continue;
1066
+ }
1067
+ const summaryPrompt = previewQueueSummaryPrompt({
1068
+ state: queue,
1069
+ noun: "announce"
1070
+ });
1071
+ if (summaryPrompt) {
1072
+ if (!await drainNextQueueItem(queue.items, async (item) => await queue.send({
1073
+ ...item,
1074
+ prompt: summaryPrompt
1075
+ }))) break;
1076
+ clearQueueSummaryState(queue);
1077
+ continue;
1078
+ }
1079
+ if (!await drainNextQueueItem(queue.items, async (item) => await queue.send(item))) break;
1080
+ }
1081
+ queue.consecutiveFailures = 0;
1082
+ } catch (err) {
1083
+ queue.consecutiveFailures++;
1084
+ const errorBackoffMs = Math.min(1e3 * Math.pow(2, queue.consecutiveFailures), 6e4);
1085
+ const retryDelayMs = Math.max(errorBackoffMs, queue.debounceMs);
1086
+ queue.lastEnqueuedAt = Date.now() + retryDelayMs - queue.debounceMs;
1087
+ defaultRuntime.error?.(`announce queue drain failed for ${key} (attempt ${queue.consecutiveFailures}, retry in ${Math.round(retryDelayMs / 1e3)}s): ${String(err)}`);
1088
+ } finally {
1089
+ queue.draining = false;
1090
+ if (queue.items.length === 0 && queue.droppedCount === 0) ANNOUNCE_QUEUES.delete(key);
1091
+ else scheduleAnnounceDrain(key);
1092
+ }
1093
+ })();
1094
+ }
1095
+ function enqueueAnnounce(params) {
1096
+ const queue = getAnnounceQueue(params.key, params.settings, params.send);
1097
+ queue.lastEnqueuedAt = Math.max(queue.lastEnqueuedAt, Date.now());
1098
+ if (!applyQueueDropPolicy({
1099
+ queue,
1100
+ summarize: (item) => item.summaryLine?.trim() || item.prompt.trim()
1101
+ })) {
1102
+ if (queue.dropPolicy === "new") scheduleAnnounceDrain(params.key);
1103
+ return false;
1104
+ }
1105
+ const origin = normalizeDeliveryContext(params.item.origin);
1106
+ const originKey = deliveryContextKey(origin);
1107
+ queue.items.push({
1108
+ ...params.item,
1109
+ origin,
1110
+ originKey
1111
+ });
1112
+ scheduleAnnounceDrain(params.key);
1113
+ return true;
1114
+ }
1115
+
988
1116
  //#endregion
989
1117
  //#region src/auto-reply/reply/directive-parsing.ts
990
1118
  function skipDirectiveArgPrefix(raw) {
@@ -2191,7 +2319,7 @@ async function routeReply(params) {
2191
2319
  const resolvedReplyToId = replyToId ?? (channelId === "slack" && threadId != null && threadId !== "" ? String(threadId) : void 0);
2192
2320
  const resolvedThreadId = channelId === "slack" ? null : threadId ?? null;
2193
2321
  try {
2194
- const { deliverOutboundPayloads } = await import("./deliver-D3lJfcWr.js").then((n) => n.n);
2322
+ const { deliverOutboundPayloads } = await import("./deliver-Cu2kD7-u.js").then((n) => n.n);
2195
2323
  const outboundSession = buildOutboundSessionContext({
2196
2324
  cfg,
2197
2325
  agentId: resolvedAgentId,
@@ -2653,6 +2781,63 @@ function buildAnnounceIdFromChildRun(params) {
2653
2781
  function buildAnnounceIdempotencyKey(announceId) {
2654
2782
  return `announce:${announceId}`;
2655
2783
  }
2784
+ function resolveQueueAnnounceId(params) {
2785
+ const announceId = params.announceId?.trim();
2786
+ if (announceId) return announceId;
2787
+ return `legacy:${params.sessionKey}:${params.enqueuedAt}`;
2788
+ }
2789
+
2790
+ //#endregion
2791
+ //#region src/agents/session-run-registry.ts
2792
+ const ACTIVE_SESSION_RUNS = /* @__PURE__ */ new Map();
2793
+ /** Check whether a session currently has an active CLI agent turn. */
2794
+ function isSessionRunActive(sessionKey) {
2795
+ return ACTIVE_SESSION_RUNS.has(sessionKey);
2796
+ }
2797
+ /** Return the number of currently active session runs. */
2798
+ function getActiveSessionRunCount() {
2799
+ return ACTIVE_SESSION_RUNS.size;
2800
+ }
2801
+ /** Register an active session run. */
2802
+ function registerSessionRun(sessionKey, handle) {
2803
+ ACTIVE_SESSION_RUNS.set(sessionKey, handle);
2804
+ }
2805
+ /** Unregister a session run (on turn completion or crash). */
2806
+ function unregisterSessionRun(sessionKey) {
2807
+ ACTIVE_SESSION_RUNS.delete(sessionKey);
2808
+ }
2809
+ /**
2810
+ * Kill an active session run by aborting its controller or sending SIGTERM to its PID.
2811
+ * Returns `true` if a kill signal was dispatched.
2812
+ */
2813
+ function killSessionRun(sessionKey) {
2814
+ const handle = ACTIVE_SESSION_RUNS.get(sessionKey);
2815
+ if (!handle) return false;
2816
+ if (handle.abortController && !handle.abortController.signal.aborted) {
2817
+ handle.abortController.abort();
2818
+ return true;
2819
+ }
2820
+ if (typeof handle.pid === "number") try {
2821
+ process.kill(handle.pid, "SIGTERM");
2822
+ return true;
2823
+ } catch {
2824
+ return false;
2825
+ }
2826
+ return false;
2827
+ }
2828
+ /**
2829
+ * Wait (poll) for a session run to end.
2830
+ * Resolves `true` if the run ended, `false` on timeout.
2831
+ */
2832
+ async function waitForSessionRunEnd(sessionKey, timeoutMs) {
2833
+ if (!ACTIVE_SESSION_RUNS.has(sessionKey)) return true;
2834
+ const deadline = Date.now() + timeoutMs;
2835
+ while (ACTIVE_SESSION_RUNS.has(sessionKey)) {
2836
+ if (Date.now() >= deadline) return false;
2837
+ await new Promise((resolve) => setTimeout(resolve, 50));
2838
+ }
2839
+ return true;
2840
+ }
2656
2841
 
2657
2842
  //#endregion
2658
2843
  //#region src/agents/subagent-depth.ts
@@ -3769,6 +3954,31 @@ async function resolveSubagentCompletionOrigin(params) {
3769
3954
  };
3770
3955
  }
3771
3956
  }
3957
+ async function sendAnnounce(item) {
3958
+ const announceTimeoutMs = resolveSubagentAnnounceTimeoutMs(loadConfig());
3959
+ const requesterIsSubagent = getSubagentDepthFromSessionStore(item.sessionKey) >= 1;
3960
+ const origin = item.origin;
3961
+ const threadId = origin?.threadId != null && origin.threadId !== "" ? String(origin.threadId) : void 0;
3962
+ const idempotencyKey = buildAnnounceIdempotencyKey(resolveQueueAnnounceId({
3963
+ announceId: item.announceId,
3964
+ sessionKey: item.sessionKey,
3965
+ enqueuedAt: item.enqueuedAt
3966
+ }));
3967
+ await callGateway({
3968
+ method: "agent",
3969
+ params: {
3970
+ sessionKey: item.sessionKey,
3971
+ message: item.prompt,
3972
+ channel: requesterIsSubagent ? void 0 : origin?.channel,
3973
+ accountId: requesterIsSubagent ? void 0 : origin?.accountId,
3974
+ to: requesterIsSubagent ? void 0 : origin?.to,
3975
+ threadId: requesterIsSubagent ? void 0 : threadId,
3976
+ deliver: !requesterIsSubagent,
3977
+ idempotencyKey
3978
+ },
3979
+ timeoutMs: announceTimeoutMs
3980
+ });
3981
+ }
3772
3982
  function resolveRequesterStoreKey(cfg, requesterSessionKey) {
3773
3983
  const raw = (requesterSessionKey ?? "").trim();
3774
3984
  if (!raw) return raw;
@@ -3788,17 +3998,40 @@ function loadRequesterSessionEntry(requesterSessionKey) {
3788
3998
  canonicalKey
3789
3999
  };
3790
4000
  }
4001
+ function buildAnnounceQueueKey(sessionKey, origin) {
4002
+ const accountId = normalizeAccountId(origin?.accountId);
4003
+ if (!accountId) return sessionKey;
4004
+ return `${sessionKey}:acct:${accountId}`;
4005
+ }
3791
4006
  async function maybeQueueSubagentAnnounce(params) {
3792
4007
  if (params.signal?.aborted) return "none";
3793
4008
  const { cfg, entry } = loadRequesterSessionEntry(params.requesterSessionKey);
3794
- resolveRequesterStoreKey(cfg, params.requesterSessionKey);
4009
+ const canonicalKey = resolveRequesterStoreKey(cfg, params.requesterSessionKey);
3795
4010
  if (!entry?.sessionId) return "none";
3796
4011
  const queueSettings = resolveQueueSettings({
3797
4012
  cfg,
3798
4013
  channel: entry?.channel ?? entry?.lastChannel,
3799
4014
  sessionEntry: entry
3800
4015
  });
3801
- queueSettings.mode === "followup" || queueSettings.mode === "collect" || queueSettings.mode === "steer-backlog" || queueSettings.mode;
4016
+ const isActive = isSessionRunActive(canonicalKey);
4017
+ const shouldFollowup = queueSettings.mode === "followup" || queueSettings.mode === "collect" || queueSettings.mode === "steer-backlog" || queueSettings.mode === "interrupt";
4018
+ if (isActive && (shouldFollowup || queueSettings.mode === "steer")) {
4019
+ const origin = resolveAnnounceOrigin(entry, params.requesterOrigin);
4020
+ enqueueAnnounce({
4021
+ key: buildAnnounceQueueKey(canonicalKey, origin),
4022
+ item: {
4023
+ announceId: params.announceId,
4024
+ prompt: params.triggerMessage,
4025
+ summaryLine: params.summaryLine,
4026
+ enqueuedAt: Date.now(),
4027
+ sessionKey: canonicalKey,
4028
+ origin
4029
+ },
4030
+ settings: queueSettings,
4031
+ send: sendAnnounce
4032
+ });
4033
+ return "queued";
4034
+ }
3802
4035
  return "none";
3803
4036
  }
3804
4037
  function queueOutcomeToDeliveryResult(outcome) {
@@ -5195,4 +5428,4 @@ function initSubagentRegistry() {
5195
5428
  }
5196
5429
 
5197
5430
  //#endregion
5198
- export { DEFAULT_HEARTBEAT_EVERY as $, createSessionVisibilityGuard as A, AGENT_LANE_SUBAGENT as B, classifySessionKind as C, clearAgentRunContext as Ct, stripToolMessages as D, registerAgentRunContext as Dt, sanitizeTextContent as E, onAgentEvent as Et, resolveInternalSessionKey as F, unregisterSessionBindingAdapter as G, extractTextFromChatContent as H, resolveMainSessionAlias as I, getFollowupQueueDepth as J, resolveQueueSettings as K, resolveSessionReference as L, resolveSandboxedSessionToolContext as M, isResolvedSessionVisibleToRequester as N, stripReasoningTagsFromText as O, createReceiptCard as Ot, resolveDisplaySessionKey as P, normalizeReplyPayload as Q, shouldResolveSessionIdInput as R, runAgentStep as S, extractQueueDirective as St, extractAssistantText as T, getAgentRunContext as Tt, getSessionBindingService as U, getSubagentDepthFromSessionStore as V, registerSessionBindingAdapter as W, isRoutableChannel as X, scheduleFollowupDrain as Y, routeReply as Z, isAnnounceSkip as _, logWebhookReceived as _t, listDescendantRunsForRequester as a, getQueueSize as at, resolvePingPongTurns as b, emitDiagnosticEvent as bt, markSubagentRunTerminated as c, resetAllLanes as ct, subagent_registry_exports as d, CommandLane as dt, resolveHeartbeatPrompt as et, buildSubagentSystemPrompt as f, logMessageProcessed as ft, buildAgentToAgentReplyContext as g, logWebhookProcessed as gt, buildAgentToAgentMessageContext as h, logWebhookError as ht, initSubagentRegistry as i, getActiveTaskCount as it, resolveEffectiveSessionToolsVisibility as j, createAgentToAgentPolicy as k, resolveAgentTimeoutMs as kt, registerSubagentRun as l, setCommandLaneConcurrency as lt, buildAgentToAgentAnnounceContext as m, logSessionStateChange as mt, countActiveDescendantRuns as n, clearSessionQueues as nt, listSubagentRunsForRequester as o, getTotalQueueSize as ot, runSubagentAnnounceFlow as p, logMessageQueued as pt, enqueueFollowupRun as q, countActiveRunsForSession as r, clearCommandLane as rt, markSubagentRunForSteerRestart as s, markGatewayDraining as st, clearSubagentRunSteerRestart as t, buildOutboundSessionContext as tt, replaceSubagentRunAfterSteer as u, waitForActiveTasks as ut, isReplySkip as v, startDiagnosticHeartbeat as vt, deriveChannel as w, emitAgentEvent as wt, readLatestAssistantReply as x, isDiagnosticsEnabled as xt, resolveAnnounceTargetFromKey as y, stopDiagnosticHeartbeat as yt, AGENT_LANE_NESTED as z };
5431
+ export { enqueueFollowupRun as $, createSessionVisibilityGuard as A, emitAgentEvent as At, AGENT_LANE_SUBAGENT as B, classifySessionKind as C, logWebhookReceived as Ct, stripToolMessages as D, isDiagnosticsEnabled as Dt, sanitizeTextContent as E, emitDiagnosticEvent as Et, resolveInternalSessionKey as F, resolveAgentTimeoutMs as Ft, registerSessionRun as G, getActiveSessionRunCount as H, resolveMainSessionAlias as I, extractTextFromChatContent as J, unregisterSessionRun as K, resolveSessionReference as L, resolveSandboxedSessionToolContext as M, onAgentEvent as Mt, isResolvedSessionVisibleToRequester as N, registerAgentRunContext as Nt, stripReasoningTagsFromText as O, extractQueueDirective as Ot, resolveDisplaySessionKey as P, createReceiptCard as Pt, resolveQueueSettings as Q, shouldResolveSessionIdInput as R, runAgentStep as S, logWebhookProcessed as St, extractAssistantText as T, stopDiagnosticHeartbeat as Tt, isSessionRunActive as U, getSubagentDepthFromSessionStore as V, killSessionRun as W, registerSessionBindingAdapter as X, getSessionBindingService as Y, unregisterSessionBindingAdapter as Z, isAnnounceSkip as _, CommandLane as _t, listDescendantRunsForRequester as a, DEFAULT_HEARTBEAT_EVERY as at, resolvePingPongTurns as b, logSessionStateChange as bt, markSubagentRunTerminated as c, clearSessionQueues as ct, subagent_registry_exports as d, getQueueSize as dt, getFollowupQueueDepth as et, buildSubagentSystemPrompt as f, getTotalQueueSize as ft, buildAgentToAgentReplyContext as g, waitForActiveTasks as gt, buildAgentToAgentMessageContext as h, setCommandLaneConcurrency as ht, initSubagentRegistry as i, normalizeReplyPayload as it, resolveEffectiveSessionToolsVisibility as j, getAgentRunContext as jt, createAgentToAgentPolicy as k, clearAgentRunContext as kt, registerSubagentRun as l, clearCommandLane as lt, buildAgentToAgentAnnounceContext as m, resetAllLanes as mt, countActiveDescendantRuns as n, isRoutableChannel as nt, listSubagentRunsForRequester as o, resolveHeartbeatPrompt as ot, runSubagentAnnounceFlow as p, markGatewayDraining as pt, waitForSessionRunEnd as q, countActiveRunsForSession as r, routeReply as rt, markSubagentRunForSteerRestart as s, buildOutboundSessionContext as st, clearSubagentRunSteerRestart as t, scheduleFollowupDrain as tt, replaceSubagentRunAfterSteer as u, getActiveTaskCount as ut, isReplySkip as v, logMessageProcessed as vt, deriveChannel as w, startDiagnosticHeartbeat as wt, readLatestAssistantReply as x, logWebhookError as xt, resolveAnnounceTargetFromKey as y, logMessageQueued as yt, AGENT_LANE_NESTED as z };