@songsid/agend 2.1.2-beta.5 → 2.1.2-beta.50

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 (178) hide show
  1. package/dist/access-path.js +15 -6
  2. package/dist/access-path.js.map +1 -1
  3. package/dist/agent-cli-instructions.md +1 -0
  4. package/dist/agent-cli.js +14 -0
  5. package/dist/agent-cli.js.map +1 -1
  6. package/dist/agent-endpoint.d.ts +2 -0
  7. package/dist/agent-endpoint.js +25 -1
  8. package/dist/agent-endpoint.js.map +1 -1
  9. package/dist/backend/antigravity.d.ts +20 -0
  10. package/dist/backend/antigravity.js +51 -4
  11. package/dist/backend/antigravity.js.map +1 -1
  12. package/dist/backend/claude-code.d.ts +59 -0
  13. package/dist/backend/claude-code.js +67 -1
  14. package/dist/backend/claude-code.js.map +1 -1
  15. package/dist/backend/codex.d.ts +26 -0
  16. package/dist/backend/codex.js +100 -0
  17. package/dist/backend/codex.js.map +1 -1
  18. package/dist/backend/grok.d.ts +25 -0
  19. package/dist/backend/grok.js +51 -0
  20. package/dist/backend/grok.js.map +1 -1
  21. package/dist/backend/kiro.d.ts +23 -0
  22. package/dist/backend/kiro.js +120 -2
  23. package/dist/backend/kiro.js.map +1 -1
  24. package/dist/backend/types.d.ts +58 -0
  25. package/dist/backend/types.js +13 -1
  26. package/dist/backend/types.js.map +1 -1
  27. package/dist/channel/adapters/discord.d.ts +15 -0
  28. package/dist/channel/adapters/discord.js +120 -8
  29. package/dist/channel/adapters/discord.js.map +1 -1
  30. package/dist/channel/adapters/telegram.d.ts +21 -0
  31. package/dist/channel/adapters/telegram.js +86 -0
  32. package/dist/channel/adapters/telegram.js.map +1 -1
  33. package/dist/channel/ipc-bridge.d.ts +9 -1
  34. package/dist/channel/ipc-bridge.js +12 -3
  35. package/dist/channel/ipc-bridge.js.map +1 -1
  36. package/dist/channel/ipc-timeouts.d.ts +46 -0
  37. package/dist/channel/ipc-timeouts.js +65 -0
  38. package/dist/channel/ipc-timeouts.js.map +1 -0
  39. package/dist/channel/mcp-server.js +30 -14
  40. package/dist/channel/mcp-server.js.map +1 -1
  41. package/dist/channel/mcp-tools.js +30 -1
  42. package/dist/channel/mcp-tools.js.map +1 -1
  43. package/dist/channel/reconnect-backoff.d.ts +17 -0
  44. package/dist/channel/reconnect-backoff.js +21 -0
  45. package/dist/channel/reconnect-backoff.js.map +1 -0
  46. package/dist/channel/types.d.ts +29 -0
  47. package/dist/classic-channel-manager.js +1 -5
  48. package/dist/classic-channel-manager.js.map +1 -1
  49. package/dist/cli.js +242 -91
  50. package/dist/cli.js.map +1 -1
  51. package/dist/completion.d.ts +27 -0
  52. package/dist/completion.js +121 -0
  53. package/dist/completion.js.map +1 -0
  54. package/dist/config-validator.js +21 -0
  55. package/dist/config-validator.js.map +1 -1
  56. package/dist/config.js +2 -0
  57. package/dist/config.js.map +1 -1
  58. package/dist/cost-guard.d.ts +3 -1
  59. package/dist/cost-guard.js +3 -1
  60. package/dist/cost-guard.js.map +1 -1
  61. package/dist/daemon.d.ts +302 -8
  62. package/dist/daemon.js +1165 -312
  63. package/dist/daemon.js.map +1 -1
  64. package/dist/event-log.d.ts +31 -0
  65. package/dist/event-log.js +96 -0
  66. package/dist/event-log.js.map +1 -1
  67. package/dist/fleet-context.d.ts +14 -0
  68. package/dist/fleet-lock.d.ts +28 -0
  69. package/dist/fleet-lock.js +130 -0
  70. package/dist/fleet-lock.js.map +1 -0
  71. package/dist/fleet-manager.d.ts +347 -6
  72. package/dist/fleet-manager.js +1794 -215
  73. package/dist/fleet-manager.js.map +1 -1
  74. package/dist/general-instance.d.ts +9 -0
  75. package/dist/general-instance.js +11 -0
  76. package/dist/general-instance.js.map +1 -0
  77. package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +22 -0
  78. package/dist/general-knowledge/skills/model-discovery/SKILL.md +14 -23
  79. package/dist/general-knowledge/skills/session-management/SKILL.md +15 -34
  80. package/dist/hang-detector.d.ts +19 -13
  81. package/dist/hang-detector.js +19 -49
  82. package/dist/hang-detector.js.map +1 -1
  83. package/dist/instance-lifecycle.d.ts +60 -3
  84. package/dist/instance-lifecycle.js +237 -48
  85. package/dist/instance-lifecycle.js.map +1 -1
  86. package/dist/instructions.d.ts +5 -0
  87. package/dist/instructions.js +9 -11
  88. package/dist/instructions.js.map +1 -1
  89. package/dist/locale.js +7 -1
  90. package/dist/locale.js.map +1 -1
  91. package/dist/logger.js +14 -0
  92. package/dist/logger.js.map +1 -1
  93. package/dist/mcp-liveness.d.ts +21 -0
  94. package/dist/mcp-liveness.js +27 -0
  95. package/dist/mcp-liveness.js.map +1 -0
  96. package/dist/outbound-handlers.d.ts +18 -0
  97. package/dist/outbound-handlers.js +215 -35
  98. package/dist/outbound-handlers.js.map +1 -1
  99. package/dist/outbound-schemas.d.ts +11 -3
  100. package/dist/outbound-schemas.js +16 -2
  101. package/dist/outbound-schemas.js.map +1 -1
  102. package/dist/pane-write-lock.d.ts +48 -0
  103. package/dist/pane-write-lock.js +73 -0
  104. package/dist/pane-write-lock.js.map +1 -0
  105. package/dist/process-memory.d.ts +31 -0
  106. package/dist/process-memory.js +79 -0
  107. package/dist/process-memory.js.map +1 -0
  108. package/dist/quickstart.js +17 -16
  109. package/dist/quickstart.js.map +1 -1
  110. package/dist/reply-dedup.d.ts +41 -0
  111. package/dist/reply-dedup.js +0 -0
  112. package/dist/reply-dedup.js.map +1 -0
  113. package/dist/restart-progress.d.ts +34 -0
  114. package/dist/restart-progress.js +87 -0
  115. package/dist/restart-progress.js.map +1 -0
  116. package/dist/scheduler/db.js +3 -0
  117. package/dist/scheduler/db.js.map +1 -1
  118. package/dist/sd-notify.d.ts +27 -0
  119. package/dist/sd-notify.js +33 -1
  120. package/dist/sd-notify.js.map +1 -1
  121. package/dist/secret-file.d.ts +33 -0
  122. package/dist/secret-file.js +36 -0
  123. package/dist/secret-file.js.map +1 -0
  124. package/dist/service-installer.d.ts +28 -0
  125. package/dist/service-installer.js +72 -1
  126. package/dist/service-installer.js.map +1 -1
  127. package/dist/settings-api.js +5 -3
  128. package/dist/settings-api.js.map +1 -1
  129. package/dist/setup-wizard.js +9 -7
  130. package/dist/setup-wizard.js.map +1 -1
  131. package/dist/tmux-control.d.ts +58 -5
  132. package/dist/tmux-control.js +102 -14
  133. package/dist/tmux-control.js.map +1 -1
  134. package/dist/tmux-manager.d.ts +31 -1
  135. package/dist/tmux-manager.js +40 -11
  136. package/dist/tmux-manager.js.map +1 -1
  137. package/dist/topic-commands.d.ts +49 -9
  138. package/dist/topic-commands.js +279 -110
  139. package/dist/topic-commands.js.map +1 -1
  140. package/dist/tui-glyphs.d.ts +5 -1
  141. package/dist/tui-glyphs.js +6 -2
  142. package/dist/tui-glyphs.js.map +1 -1
  143. package/dist/types.d.ts +19 -2
  144. package/dist/ui/settings.html +1 -1
  145. package/dist/ui/view.html +123 -2
  146. package/dist/update-marker.d.ts +15 -0
  147. package/dist/update-marker.js +69 -0
  148. package/dist/update-marker.js.map +1 -0
  149. package/dist/usage/format-rich.d.ts +11 -0
  150. package/dist/usage/format-rich.js +121 -0
  151. package/dist/usage/format-rich.js.map +1 -0
  152. package/dist/usage/provider-alerts.d.ts +33 -0
  153. package/dist/usage/provider-alerts.js +57 -0
  154. package/dist/usage/provider-alerts.js.map +1 -0
  155. package/dist/usage/providers.d.ts +130 -0
  156. package/dist/usage/providers.js +1063 -0
  157. package/dist/usage/providers.js.map +1 -0
  158. package/dist/usage/statusline-usage.d.ts +20 -0
  159. package/dist/usage/statusline-usage.js +120 -0
  160. package/dist/usage/statusline-usage.js.map +1 -0
  161. package/dist/usage/usage-api.d.ts +50 -0
  162. package/dist/usage/usage-api.js +197 -0
  163. package/dist/usage/usage-api.js.map +1 -0
  164. package/dist/view-api.d.ts +3 -0
  165. package/dist/view-api.js +11 -2
  166. package/dist/view-api.js.map +1 -1
  167. package/dist/web-api.js +7 -3
  168. package/dist/web-api.js.map +1 -1
  169. package/dist/web-auth.d.ts +6 -0
  170. package/dist/web-auth.js +54 -0
  171. package/dist/web-auth.js.map +1 -0
  172. package/package.json +4 -1
  173. package/dist/channel/tool-tracker.d.ts +0 -13
  174. package/dist/channel/tool-tracker.js +0 -58
  175. package/dist/channel/tool-tracker.js.map +0 -1
  176. package/dist/daemon-entry.d.ts +0 -1
  177. package/dist/daemon-entry.js +0 -30
  178. package/dist/daemon-entry.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"locale.js","sourceRoot":"","sources":["../src/locale.ts"],"names":[],"mappings":"AAQA,IAAI,OAAO,GAAW,IAAI,CAAC;AAC3B,MAAM,UAAU,SAAS,CAAC,CAAS,IAAU,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;AAC3D,MAAM,UAAU,SAAS,KAAa,OAAO,OAAO,CAAC,CAAC,CAAC;AAEvD,qDAAqD;AACrD,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,YAAY,CAAC,WAAgD;IAC3E,MAAM,GAAG,GAAG,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC;IAC1C,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC;IAChD,OAAO,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,MAAM,QAAQ,GAA2C;IACvD,EAAE,EAAE;QACF,eAAe,EAAE,WAAW;QAC5B,aAAa,EAAE,wBAAwB;QACvC,oBAAoB,EAAE,oBAAoB;QAC1C,UAAU,EAAE,uBAAuB;QACnC,aAAa,EAAE,cAAc;QAC7B,WAAW,EAAE,YAAY;QACzB,cAAc,EAAE,eAAe;QAC/B,iBAAiB,EAAE,iCAAiC;QACpD,wBAAwB,EAAE,8DAA8D;QACxF,qBAAqB,EAAE,yDAAyD;QAChF,8BAA8B,EAAE,kDAAkD;QAClF,kBAAkB,EAAE,kCAAkC;QACtD,wBAAwB,EAAE,oDAAoD;QAC9E,iBAAiB,EAAE,6EAA6E;QAChG,wBAAwB,EAAE,kCAAkC;QAC5D,0BAA0B,EAAE,+HAA+H;QAC3J,2BAA2B,EAAE,0DAA0D;QACvF,+BAA+B,EAAE,6EAA6E;QAC9G,iBAAiB,EAAE,mCAAmC;QACtD,uBAAuB,EAAE,kCAAkC;QAC3D,YAAY,EAAE,4BAA4B;QAC1C,gBAAgB,EAAE,uCAAuC;QACzD,mBAAmB,EAAE,sBAAsB;QAC3C,aAAa,EAAE,iCAAiC;QAChD,YAAY,EAAE,gCAAgC;QAC9C,eAAe,EAAE,eAAe;QAChC,cAAc,EAAE,eAAe;QAC/B,gBAAgB,EAAE,2DAA2D;QAC7E,cAAc,EAAE,4BAA4B;QAC5C,aAAa,EAAE,2BAA2B;QAC1C,oBAAoB,EAAE,2BAA2B;QACjD,gBAAgB,EAAE,kBAAkB;QACpC,YAAY,EAAE,0BAA0B;QACxC,iBAAiB,EAAE,oBAAoB;QACvC,kBAAkB,EAAE,2CAA2C;QAC/D,mBAAmB,EAAE,iBAAiB;QACtC,aAAa,EAAE,8CAA8C;QAC7D,yBAAyB,EAAE,4DAA4D;QACvF,kBAAkB,EAAE,+BAA+B;QACnD,oBAAoB,EAAE,oDAAoD;QAC1E,sBAAsB,EAAE,mDAAmD;QAC3E,2BAA2B,EAAE,uJAAuJ;QACpL,uBAAuB,EAAE,4JAA4J;QACrL,sBAAsB,EAAE,2JAA2J;QACnL,oBAAoB,EAAE,mJAAmJ;QACzK,iBAAiB,EAAE,iIAAiI;QACpJ,iBAAiB,EAAE,+IAA+I;QAClK,mBAAmB,EAAE,kDAAkD;QACvE,wBAAwB,EAAE,0FAA0F;QACpH,4BAA4B,EAAE,sEAAsE;QACpG,wBAAwB,EAAE,+BAA+B;QACzD,4BAA4B,EAAE,sEAAsE;QACpG,2BAA2B,EAAE,+DAA+D;QAC5F,qBAAqB,EAAE,2GAA2G;QAClI,gBAAgB,EAAE,4BAA4B;QAC9C,sBAAsB,EAAE,iHAAiH;QACzI,mBAAmB,EAAE,4BAA4B;QACjD,kBAAkB,EAAE,wDAAwD;QAC5E,gBAAgB,EAAE,wDAAwD;QAC1E,aAAa,EAAE,gCAAgC;QAC/C,YAAY,EAAE,gCAAgC;QAC9C,YAAY,EAAE,6BAA6B;QAC3C,WAAW,EAAE,oBAAoB;QACjC,cAAc,EAAE,wDAAwD;QACxE,iBAAiB,EAAE,iCAAiC;QACpD,eAAe,EAAE,8BAA8B;QAC/C,YAAY,EAAE,+BAA+B;QAC7C,YAAY,EAAE,2BAA2B;QACzC,cAAc,EAAE,uCAAuC;QACvD,cAAc,EAAE,6BAA6B;QAC7C,eAAe,EAAE,oBAAoB;QACrC,eAAe,EAAE,gCAAgC;QACjD,cAAc,EAAE,gCAAgC;QAChD,cAAc,EAAE,wBAAwB;QACxC,YAAY,EAAE,0BAA0B;QACxC,kBAAkB,EAAE,iFAAiF;QACrG,oBAAoB,EAAE,qDAAqD;QAC3E,iBAAiB,EAAE,kDAAkD;QACrE,gBAAgB,EAAE,2BAA2B;QAC7C,YAAY,EAAE,yBAAyB;QACvC,WAAW,EAAE,qBAAqB;QAClC,0BAA0B,EAAE,0CAA0C;QACtE,0BAA0B,EAAE,iDAAiD;QAC7E,0BAA0B,EAAE,yDAAyD;QACrF,yBAAyB,EAAE,gCAAgC;QAC3D,oBAAoB,EAAE,8BAA8B;QACpD,WAAW,EAAE,kEAAkE;QAC/E,YAAY,EAAE,2BAA2B;QACzC,mBAAmB,EAAE,oGAAoG;QACzH,oBAAoB,EAAE,6DAA6D;KACpF;IACD,OAAO,EAAE;QACP,eAAe,EAAE,OAAO;QACxB,aAAa,EAAE,gBAAgB;QAC/B,oBAAoB,EAAE,aAAa;QACnC,UAAU,EAAE,oBAAoB;QAChC,aAAa,EAAE,QAAQ;QACvB,WAAW,EAAE,WAAW;QACxB,cAAc,EAAE,WAAW;QAC3B,iBAAiB,EAAE,iBAAiB;QACpC,wBAAwB,EAAE,8BAA8B;QACxD,qBAAqB,EAAE,6BAA6B;QACpD,8BAA8B,EAAE,gBAAgB;QAChD,kBAAkB,EAAE,kBAAkB;QACtC,wBAAwB,EAAE,6BAA6B;QACvD,iBAAiB,EAAE,+CAA+C;QAClE,wBAAwB,EAAE,iBAAiB;QAC3C,0BAA0B,EAAE,qEAAqE;QACjG,2BAA2B,EAAE,sBAAsB;QACnD,+BAA+B,EAAE,iDAAiD;QAClF,iBAAiB,EAAE,mBAAmB;QACtC,uBAAuB,EAAE,kBAAkB;QAC3C,YAAY,EAAE,gBAAgB;QAC9B,gBAAgB,EAAE,eAAe;QACjC,mBAAmB,EAAE,SAAS;QAC9B,aAAa,EAAE,6BAA6B;QAC5C,YAAY,EAAE,4BAA4B;QAC1C,eAAe,EAAE,YAAY;QAC7B,cAAc,EAAE,aAAa;QAC7B,gBAAgB,EAAE,0BAA0B;QAC5C,cAAc,EAAE,iBAAiB;QACjC,aAAa,EAAE,iBAAiB;QAChC,oBAAoB,EAAE,oBAAoB;QAC1C,gBAAgB,EAAE,OAAO;QACzB,YAAY,EAAE,iBAAiB;QAC/B,iBAAiB,EAAE,cAAc;QACjC,kBAAkB,EAAE,6BAA6B;QACjD,mBAAmB,EAAE,UAAU;QAC/B,aAAa,EAAE,mCAAmC;QAClD,yBAAyB,EAAE,4CAA4C;QACvE,kBAAkB,EAAE,2BAA2B;QAC/C,oBAAoB,EAAE,+BAA+B;QACrD,sBAAsB,EAAE,iCAAiC;QACzD,2BAA2B,EAAE,yGAAyG;QACtI,uBAAuB,EAAE,gHAAgH;QACzI,sBAAsB,EAAE,+GAA+G;QACvI,oBAAoB,EAAE,kHAAkH;QACxI,iBAAiB,EAAE,mGAAmG;QACtH,iBAAiB,EAAE,8GAA8G;QACjI,mBAAmB,EAAE,iCAAiC;QACtD,wBAAwB,EAAE,mCAAmC;QAC7D,4BAA4B,EAAE,8BAA8B;QAC5D,wBAAwB,EAAE,gBAAgB;QAC1C,4BAA4B,EAAE,uCAAuC;QACrE,2BAA2B,EAAE,qCAAqC;QAClE,qBAAqB,EAAE,qDAAqD;QAC5E,gBAAgB,EAAE,eAAe;QACjC,sBAAsB,EAAE,2FAA2F;QACnH,mBAAmB,EAAE,qBAAqB;QAC1C,kBAAkB,EAAE,+BAA+B;QACnD,gBAAgB,EAAE,+BAA+B;QACjD,aAAa,EAAE,cAAc;QAC7B,YAAY,EAAE,cAAc;QAC5B,YAAY,EAAE,aAAa;QAC3B,WAAW,EAAE,UAAU;QACvB,cAAc,EAAE,2BAA2B;QAC3C,iBAAiB,EAAE,cAAc;QACjC,eAAe,EAAE,cAAc;QAC/B,YAAY,EAAE,aAAa;QAC3B,YAAY,EAAE,UAAU;QACxB,cAAc,EAAE,qBAAqB;QACrC,cAAc,EAAE,gBAAgB;QAChC,eAAe,EAAE,MAAM;QACvB,eAAe,EAAE,kBAAkB;QACnC,cAAc,EAAE,eAAe;QAC/B,cAAc,EAAE,QAAQ;QACxB,YAAY,EAAE,iBAAiB;QAC/B,kBAAkB,EAAE,6BAA6B;QACjD,oBAAoB,EAAE,sCAAsC;QAC5D,iBAAiB,EAAE,mCAAmC;QACtD,gBAAgB,EAAE,aAAa;QAC/B,YAAY,EAAE,eAAe;QAC7B,WAAW,EAAE,mBAAmB;QAChC,0BAA0B,EAAE,gBAAgB;QAC5C,0BAA0B,EAAE,oBAAoB;QAChD,0BAA0B,EAAE,gCAAgC;QAC5D,yBAAyB,EAAE,mBAAmB;QAC9C,oBAAoB,EAAE,gBAAgB;QACtC,WAAW,EAAE,sCAAsC;QACnD,YAAY,EAAE,WAAW;QACzB,mBAAmB,EAAE,kDAAkD;QACvE,oBAAoB,EAAE,yBAAyB;KAChD;CACF,CAAC;AAEF,+EAA+E;AAC/E,MAAM,UAAU,CAAC,CAAC,GAAW,EAAE,GAAG,IAAyB;IACzD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,EAAE,CAAC;IAC/C,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;IAClD,OAAO,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC5E,CAAC"}
1
+ {"version":3,"file":"locale.js","sourceRoot":"","sources":["../src/locale.ts"],"names":[],"mappings":"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"}
package/dist/logger.js CHANGED
@@ -43,6 +43,20 @@ export function rotateLogIfNeeded(logPath, maxSize = MAX_LOG_SIZE, maxFiles = RO
43
43
  const stat = statSync(logPath);
44
44
  if (stat.size < maxSize)
45
45
  return;
46
+ // Ballooned far past the limit (e.g. never-rotated TUI animation flood at
47
+ // hundreds of MB): drop content in place. Copying a 700MB+ file to .1 is
48
+ // slow and wasteful; the open writer (pipe-pane `cat >>`, pino) keeps the
49
+ // same inode so truncate is enough.
50
+ if (stat.size > maxSize * 10) {
51
+ for (let i = 1; i <= maxFiles; i++) {
52
+ try {
53
+ unlinkSync(`${logPath}.${i}`);
54
+ }
55
+ catch { /* no rotated file */ }
56
+ }
57
+ truncateSync(logPath, 0);
58
+ return;
59
+ }
46
60
  // Shift existing rotated files: .2 → .3 (oldest deleted), .1 → .2, …
47
61
  for (let i = maxFiles; i >= 2; i--) {
48
62
  const src = `${logPath}.${i - 1}`;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Liveness of an instance's MCP server, derived from `channel.mcp.pid`.
3
+ *
4
+ * The MCP server writes that file at startup and unlinks it on a clean exit, so:
5
+ * - **dead** → file present but the pid is gone: it died without cleaning up
6
+ * (crash / OOM / SIGKILL). This is the incident worth reporting.
7
+ * - **unknown** → no file, or an unusable value: not started yet, or exited
8
+ * cleanly. Never alarm on this, or every startup would alert.
9
+ * - **alive** → the pid responds to signal 0 (EPERM counts as alive: the
10
+ * process exists but is owned by another user).
11
+ */
12
+ export type McpServerState = {
13
+ state: "alive";
14
+ pid: number;
15
+ } | {
16
+ state: "dead";
17
+ pid: number;
18
+ } | {
19
+ state: "unknown";
20
+ };
21
+ export declare function mcpServerState(instanceDir: string): McpServerState;
@@ -0,0 +1,27 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ export function mcpServerState(instanceDir) {
4
+ let raw;
5
+ try {
6
+ raw = readFileSync(join(instanceDir, "channel.mcp.pid"), "utf-8").trim();
7
+ }
8
+ catch {
9
+ return { state: "unknown" };
10
+ }
11
+ const pid = Number.parseInt(raw, 10);
12
+ // Reject non-numeric, init, and anything unsafe — a bad pid must never be
13
+ // reported as "dead" (that would be a false alarm) nor signalled.
14
+ if (!Number.isSafeInteger(pid) || pid <= 1 || String(pid) !== raw.replace(/^\+/, "")) {
15
+ return { state: "unknown" };
16
+ }
17
+ try {
18
+ process.kill(pid, 0);
19
+ return { state: "alive", pid };
20
+ }
21
+ catch (err) {
22
+ if (err.code === "EPERM")
23
+ return { state: "alive", pid };
24
+ return { state: "dead", pid };
25
+ }
26
+ }
27
+ //# sourceMappingURL=mcp-liveness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-liveness.js","sourceRoot":"","sources":["../src/mcp-liveness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAkBjC,MAAM,UAAU,cAAc,CAAC,WAAmB;IAChD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACrC,0EAA0E;IAC1E,kEAAkE;IAClE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;QACrF,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;IACD,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QACpF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IAChC,CAAC;AACH,CAAC"}
@@ -21,10 +21,13 @@ export interface OutboundContext {
21
21
  instanceName: string;
22
22
  name: string;
23
23
  backend?: string;
24
+ model?: string;
24
25
  channelId: string;
26
+ adapterId?: string;
25
27
  }[];
26
28
  getChannelIdByInstance?(name: string): string | undefined;
27
29
  getBackendByInstance?(name: string, fleetDefault?: string): string;
30
+ getModel?(channelId: string, adapterId?: string, fleetDefault?: string): string | undefined;
28
31
  } | null;
29
32
  lastActivityMs(name: string): number;
30
33
  startInstance(name: string, config: InstanceConfig, topicMode: boolean): Promise<void>;
@@ -41,10 +44,20 @@ export interface OutboundContext {
41
44
  id: string;
42
45
  adapter: ChannelAdapter;
43
46
  } | undefined;
47
+ /** Post a notice into an instance's own topic (used to report failed deliveries). */
48
+ notifyInstanceTopic?(instanceName: string, text: string): void;
44
49
  sendCancelButton?(instanceName: string, correlationId?: string): Promise<void>;
45
50
  clearCancelButton?(instanceName: string): void;
46
51
  clearCancelButtonByCorrelation?(correlationId: string): void;
47
52
  getInstanceExecutionState?(name: string): "idle" | "working" | "stuck" | "paused" | null;
53
+ /** Effective process state used to annotate cross-instance delivery results. */
54
+ getInstanceStatus?(name: string): "running" | "paused" | "stopped" | "crashed";
55
+ resolveInstanceModel?(name: string): {
56
+ model: string;
57
+ source: "instance" | "fleet-default" | "classic" | "cli-default" | "unresolved";
58
+ display: string;
59
+ reason?: string;
60
+ };
48
61
  }
49
62
  /** Metadata extracted from the raw outbound message. */
50
63
  export interface OutboundMeta {
@@ -55,5 +68,10 @@ export interface OutboundMeta {
55
68
  }
56
69
  type Respond = (result: unknown, error?: string) => void;
57
70
  type Handler = (ctx: OutboundContext, args: Record<string, unknown>, respond: Respond, meta: OutboundMeta) => Promise<void> | void;
71
+ /** Test seam: real retry intervals are 30s, far beyond a test's patience. */
72
+ export declare function setCrossInstanceRetryForTests(cfg: {
73
+ retries: number;
74
+ intervalMs: number;
75
+ } | null): void;
58
76
  export declare const outboundHandlers: Map<string, Handler>;
59
77
  export {};
@@ -1,6 +1,7 @@
1
1
  import { resolve as pathResolve, isAbsolute } from "node:path";
2
2
  import { homedir } from "node:os";
3
- import { BroadcastArgs, CreateInstanceArgs, CreateTeamArgs, DelegateTaskArgs, DeleteInstanceArgs, DeleteTeamArgs, DeployTemplateArgs, DescribeInstanceArgs, ListDeploymentsArgs, ListInstancesArgs, ListTeamsArgs, ReplaceInstanceArgs, ReportResultArgs, RequestInformationArgs, RestartInstanceArgs, SendToInstanceArgs, PauseInstanceArgs, WakeInstanceArgs, StopInstanceArgs, GetInstanceLogsArgs, GetFleetConfigArgs, UpdateInstanceConfigArgs, UpdateFleetDefaultsArgs, StartInstanceArgs, TeardownDeploymentArgs, UpdateTeamArgs, validateArgs, } from "./outbound-schemas.js";
3
+ import { GENERAL_PAUSE_ERROR, isGeneralInstance } from "./general-instance.js";
4
+ import { BroadcastArgs, CreateInstanceArgs, CreateTeamArgs, DelegateTaskArgs, DeleteInstanceArgs, DeleteTeamArgs, DeployTemplateArgs, DescribeInstanceArgs, ListDeploymentsArgs, ListInstancesArgs, ListTeamsArgs, ReplaceInstanceArgs, ReportResultArgs, RequestInformationArgs, RestartInstanceArgs, SendToInstanceArgs, PauseInstanceArgs, WakeInstanceArgs, StopInstanceArgs, GetInstanceLogsArgs, GetEffortArgs, GetUsageArgs, GetFleetConfigArgs, UpdateInstanceConfigArgs, UpdateFleetDefaultsArgs, StartInstanceArgs, TeardownDeploymentArgs, UpdateTeamArgs, validateArgs, } from "./outbound-schemas.js";
4
5
  const HOME_DIR = homedir();
5
6
  /**
6
7
  * Sanitize an error for inclusion in outbound responses sent to agents.
@@ -33,6 +34,78 @@ async function deliverToInstance(ctx, instanceName, payload) {
33
34
  throw new Error(`Instance '${instanceName}' is not connected`);
34
35
  ipc.send(payload);
35
36
  }
37
+ /** Resolve state before delivery so a paused wake is visible to the sender. */
38
+ function targetState(ctx, name) {
39
+ const daemon = ctx.lifecycle.daemons.get(name);
40
+ // A daemon can still have a live pid while its crash-loop guard has disabled
41
+ // respawn. Surface that as crashed instead of promising a delivery that the
42
+ // pane can never process.
43
+ if (daemon?.isCrashLoop)
44
+ return "crashed";
45
+ if (ctx.getInstanceStatus)
46
+ return ctx.getInstanceStatus(name);
47
+ if (ctx.lifecycle.isPaused?.(name))
48
+ return "paused";
49
+ if (daemon || ctx.instanceIpcClients.has(name))
50
+ return "running";
51
+ return "stopped";
52
+ }
53
+ /** Cross-instance delivery retries: same shape the scheduler already uses. */
54
+ const CROSS_INSTANCE_RETRY_DEFAULTS = { retries: 3, intervalMs: 30_000 };
55
+ let crossInstanceRetry = { ...CROSS_INSTANCE_RETRY_DEFAULTS };
56
+ /** Test seam: real retry intervals are 30s, far beyond a test's patience. */
57
+ export function setCrossInstanceRetryForTests(cfg) {
58
+ crossInstanceRetry = cfg ?? { ...CROSS_INSTANCE_RETRY_DEFAULTS };
59
+ }
60
+ /**
61
+ * Deliver a cross-instance message with retries, and make a final failure VISIBLE.
62
+ *
63
+ * This path used to be pure fire-and-forget: the handler answered
64
+ * `{sent: true, queued: true}` and a later rejection went to `logger.warn` and
65
+ * nowhere else. The sending agent believed it had delivered, the recipient never
66
+ * got it, and no human was told — the last large hole under "instance messages
67
+ * must not get lost". The failure window is real: `deliverWithIdleGate` throws
68
+ * whenever the target's IPC has gone, which is exactly what happens while a target
69
+ * is restarting or crash-looping.
70
+ *
71
+ * Retries reuse the scheduler's proven numbers (3 attempts, 30s apart). On final
72
+ * failure we log at error, record it in the event log, and post to BOTH the
73
+ * sender's and the target's topic so the agent that sent it and any watching human
74
+ * both find out.
75
+ */
76
+ async function deliverCrossInstanceWithRetry(ctx, targetInstanceName, targetLabel, senderLabel, correlationId, payload) {
77
+ const attempt = async () => {
78
+ try {
79
+ await deliverToInstance(ctx, targetInstanceName, payload);
80
+ return null;
81
+ }
82
+ catch (err) {
83
+ return err instanceof Error ? err : new Error(String(err));
84
+ }
85
+ };
86
+ let lastError = await attempt();
87
+ for (let i = 0; lastError && i < crossInstanceRetry.retries; i++) {
88
+ ctx.logger.warn({ err: lastError.message, target: targetLabel, correlation_id: correlationId, attempt: i + 1 }, "Cross-instance delivery failed — retrying");
89
+ await new Promise(r => setTimeout(r, crossInstanceRetry.intervalMs));
90
+ lastError = await attempt();
91
+ }
92
+ if (!lastError)
93
+ return;
94
+ ctx.logger.error({ err: lastError.message, target: targetLabel, correlation_id: correlationId, attempts: crossInstanceRetry.retries + 1 }, "Cross-instance delivery failed after retries — message lost");
95
+ ctx.eventLog?.insert(targetInstanceName, "cross_instance_delivery_failed", {
96
+ from: senderLabel,
97
+ correlation_id: correlationId,
98
+ error: lastError.message,
99
+ });
100
+ const notice = `❌ Message from ${senderLabel} to ${targetLabel} could not be delivered after `
101
+ + `${crossInstanceRetry.retries + 1} attempts (${lastError.message}). `
102
+ + `correlation_id: ${correlationId}`;
103
+ // Both topics: the sender's agent needs to know its send did not land, and a human
104
+ // watching the target needs to know something was addressed to it and never arrived.
105
+ ctx.notifyInstanceTopic?.(senderLabel, notice);
106
+ if (targetInstanceName !== senderLabel)
107
+ ctx.notifyInstanceTopic?.(targetInstanceName, notice);
108
+ }
36
109
  // ── Handler implementations ─────────────────────────────────────────────
37
110
  const sendToInstance = async (ctx, rawArgs, respond, meta) => {
38
111
  const v = validateArgs(SendToInstanceArgs, rawArgs, "send_to_instance");
@@ -54,14 +127,22 @@ const sendToInstance = async (ctx, rawArgs, respond, meta) => {
54
127
  targetInstanceName = hostInstance;
55
128
  }
56
129
  }
57
- if (!targetIpc) {
58
- const existsInConfig = targetName in (ctx.fleetConfig?.instances ?? {});
59
- if (existsInConfig) {
60
- respond(null, `Instance '${targetName}' is stopped. Use start_instance('${targetName}') to start it first.`);
61
- }
62
- else {
63
- respond(null, `Instance or session not found: ${targetName}`);
64
- }
130
+ const existsInConfig = targetName in (ctx.fleetConfig?.instances ?? {})
131
+ || targetInstanceName in (ctx.fleetConfig?.instances ?? {});
132
+ if (!existsInConfig && !targetIpc) {
133
+ respond(null, `Instance or session not found: ${targetName}`);
134
+ return;
135
+ }
136
+ const state = targetState(ctx, targetInstanceName);
137
+ // Paused instances may have no live IPC while their persisted window is being
138
+ // woken. The FleetManager facade can still start them, so let that path run.
139
+ const canWakePersisted = state === "paused" && !!ctx.deliverToInstance;
140
+ if (state === "crashed") {
141
+ respond(null, `Instance '${targetName}' is crashed (target_state=crashed). Restart it before sending.`);
142
+ return;
143
+ }
144
+ if (state === "stopped" || (!targetIpc && !canWakePersisted)) {
145
+ respond(null, `Instance '${targetName}' is stopped (target_state=stopped). Use start_instance('${targetName}') to start it first.`);
65
146
  return;
66
147
  }
67
148
  const correlationId = parsedCorrelationId || `cid-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
@@ -90,13 +171,16 @@ const sendToInstance = async (ctx, rawArgs, respond, meta) => {
90
171
  const senderDisplay = ctx.fleetConfig?.instances[senderLabel]?.display_name;
91
172
  if (senderDisplay && senderDisplay !== senderLabel)
92
173
  ipcMeta.from_display = senderDisplay;
93
- try {
94
- await deliverToInstance(ctx, targetInstanceName, { type: "fleet_inbound", targetSession, content: message, meta: ipcMeta });
95
- }
96
- catch (err) {
97
- respond(null, sanitizeError(err, ctx, `wake/deliver to ${targetName}`));
98
- return;
99
- }
174
+ // Fire-and-queue: hand the message to the fleet and respond immediately.
175
+ // deliverToInstance owns waking a paused target, the idle gate and retries;
176
+ // awaiting it here blocked this call for as long as the target stayed busy
177
+ // (up to the idle-gate timeout), which serialized ALL cross-instance traffic
178
+ // and surfaced as "IPC request timed out after 30000ms" on the caller.
179
+ // Unknown/stopped targets already errored synchronously above, so anything
180
+ // failing past this point is a delivery problem to log, not a caller error.
181
+ // Retries and, on final failure, tells both agents' topics — see
182
+ // deliverCrossInstanceWithRetry. It never rejects, so nothing escapes here.
183
+ void deliverCrossInstanceWithRetry(ctx, targetInstanceName, targetName, senderLabel, correlationId, { type: "fleet_inbound", targetSession, content: message, meta: ipcMeta });
100
184
  // Show a cancel button on the target's topic so a watching user can interrupt
101
185
  // work started by another instance — but only for messages that actually put
102
186
  // the recipient to work (task/query). Informational report/update messages
@@ -155,7 +239,8 @@ const sendToInstance = async (ctx, rawArgs, respond, meta) => {
155
239
  const taskSummary = ipcMeta.task_summary || (message ?? "").slice(0, 200);
156
240
  ctx.eventLog?.logActivity("message", senderLabel, taskSummary, targetName, ipcMeta.request_kind);
157
241
  ctx.queueMirrorMessage?.(`${senderLabel} → ${targetName}: ${(message ?? "").slice(0, 500)}${(message ?? "").length > 500 ? " […]" : ""}`);
158
- respond({ sent: true, target: targetName, correlation_id: correlationId,
242
+ respond({ sent: true, queued: true, target: targetName, target_state: state,
243
+ ...(state === "paused" ? { waking: true } : {}), correlation_id: correlationId,
159
244
  ...(ctx.lifecycle.daemons.get(targetInstanceName)?.isErrorState && {
160
245
  warning: (() => {
161
246
  const daemon = ctx.lifecycle.daemons.get(targetInstanceName);
@@ -191,6 +276,8 @@ const listInstances = (ctx, rawArgs, respond, meta) => {
191
276
  display_name: config.display_name ?? null,
192
277
  description: config.description ?? null,
193
278
  backend: config.backend ?? "claude-code",
279
+ model: ctx.resolveInstanceModel?.(name).model ?? config.model ?? "default",
280
+ kind: "fleet-topic",
194
281
  tags: config.tags ?? [],
195
282
  last_activity: ctx.lastActivityMs(name) ? new Date(ctx.lastActivityMs(name)).toISOString() : null,
196
283
  }));
@@ -212,7 +299,11 @@ const listInstances = (ctx, rawArgs, respond, meta) => {
212
299
  topic_id: ch.channelId,
213
300
  display_name: `classic: ${ch.name}`,
214
301
  description: `ClassicBot channel (${ch.name})`,
215
- backend: ch.backend ?? "claude-code",
302
+ backend: ctx.classicChannels.getBackendByInstance?.(ch.instanceName, ctx.fleetConfig?.defaults?.backend) ?? ch.backend ?? ctx.fleetConfig?.defaults?.backend ?? "claude-code",
303
+ model: ctx.resolveInstanceModel?.(ch.instanceName).model
304
+ ?? ctx.classicChannels.getModel?.(ch.channelId, ch.adapterId, ctx.fleetConfig?.defaults?.model)
305
+ ?? "default",
306
+ kind: "classic",
216
307
  tags: ["classic"],
217
308
  last_activity: ctx.lastActivityMs(ch.instanceName) ? new Date(ctx.lastActivityMs(ch.instanceName)).toISOString() : null,
218
309
  });
@@ -232,9 +323,11 @@ const describeInstance = (ctx, rawArgs, respond) => {
232
323
  const targetName = v.data.name;
233
324
  const config = ctx.fleetConfig?.instances[targetName];
234
325
  if (config) {
326
+ const model = ctx.resolveInstanceModel?.(targetName);
235
327
  respond({
236
328
  name: targetName,
237
329
  type: "instance",
330
+ kind: "fleet-topic",
238
331
  description: config.description ?? null,
239
332
  tags: config.tags ?? [],
240
333
  working_directory: config.working_directory,
@@ -245,7 +338,8 @@ const describeInstance = (ctx, rawArgs, respond) => {
245
338
  : null,
246
339
  topic_id: config.topic_id ?? null,
247
340
  backend: config.backend ?? "claude-code",
248
- model: config.model ?? null,
341
+ model: model?.model ?? config.model ?? "default",
342
+ model_source: model?.source ?? (config.model ? "instance" : "unresolved"),
249
343
  last_activity: ctx.lastActivityMs(targetName) ? new Date(ctx.lastActivityMs(targetName)).toISOString() : null,
250
344
  worktree_source: config.worktree_source ?? null,
251
345
  });
@@ -255,9 +349,12 @@ const describeInstance = (ctx, rawArgs, respond) => {
255
349
  if (ctx.classicChannels) {
256
350
  const channelId = ctx.classicChannels.getChannelIdByInstance?.(targetName);
257
351
  if (channelId) {
352
+ const channel = ctx.classicChannels.getAll().find(ch => ch.instanceName === targetName);
353
+ const model = ctx.resolveInstanceModel?.(targetName);
258
354
  respond({
259
355
  name: targetName,
260
356
  type: "instance",
357
+ kind: "classic",
261
358
  description: `ClassicBot channel`,
262
359
  tags: ["classic"],
263
360
  working_directory: "",
@@ -265,8 +362,13 @@ const describeInstance = (ctx, rawArgs, respond) => {
265
362
  instance_state: ctx.getInstanceExecutionState?.(targetName) ?? null,
266
363
  last_paused_at: null,
267
364
  topic_id: channelId,
268
- backend: ctx.classicChannels.getBackendByInstance?.(targetName) ?? "claude-code",
269
- model: null,
365
+ backend: ctx.classicChannels.getBackendByInstance?.(targetName, ctx.fleetConfig?.defaults?.backend) ?? ctx.fleetConfig?.defaults?.backend ?? "claude-code",
366
+ model: model?.model
367
+ ?? ctx.classicChannels.getModel?.(channelId, channel?.adapterId, ctx.fleetConfig?.defaults?.model)
368
+ ?? "default",
369
+ model_source: model?.source ?? (ctx.classicChannels.getModel?.(channelId, channel?.adapterId, ctx.fleetConfig?.defaults?.model)
370
+ ? "classic"
371
+ : "unresolved"),
270
372
  last_activity: ctx.lastActivityMs(targetName) ? new Date(ctx.lastActivityMs(targetName)).toISOString() : null,
271
373
  worktree_source: null,
272
374
  });
@@ -287,7 +389,33 @@ const startInstance = async (ctx, rawArgs, respond) => {
287
389
  return;
288
390
  }
289
391
  const targetName = v.data.name;
392
+ // `start_instance` is an explicit operator request, not the fleet startup
393
+ // reconciliation path. Treat a persisted/daemon pause as wake so the
394
+ // marker is cleared and the next state snapshot is visible to `agend ls`.
395
+ if (ctx.lifecycle.isPaused?.(targetName)) {
396
+ try {
397
+ await ctx.lifecycle.wake(targetName, 30_000);
398
+ respond({ success: true, status: "started" });
399
+ }
400
+ catch (err) {
401
+ respond(null, `Failed to wake instance '${targetName}': ${sanitizeError(err, ctx, `start_instance(${targetName})`)}`);
402
+ }
403
+ return;
404
+ }
290
405
  if (ctx.lifecycle.daemons.has(targetName)) {
406
+ // A crash-loop daemon stays in the map while its pane is dead. Do not
407
+ // report it as already running; restart it so its crash marker is consumed.
408
+ const status = ctx.getInstanceStatus?.(targetName);
409
+ if (status === "crashed" || status === "stopped") {
410
+ try {
411
+ await ctx.restartSingleInstance(targetName);
412
+ respond({ success: true, status: "started" });
413
+ }
414
+ catch (err) {
415
+ respond(null, `Failed to restart instance '${targetName}': ${sanitizeError(err, ctx, `start_instance(${targetName})`)}`);
416
+ }
417
+ return;
418
+ }
291
419
  respond({ success: true, status: "already_running" });
292
420
  return;
293
421
  }
@@ -338,6 +466,10 @@ const pauseInstance = async (ctx, rawArgs, respond) => {
338
466
  respond(null, v.error);
339
467
  return;
340
468
  }
469
+ if (isGeneralInstance(ctx.fleetConfig, v.data.name)) {
470
+ respond(null, GENERAL_PAUSE_ERROR);
471
+ return;
472
+ }
341
473
  try {
342
474
  await ctx.lifecycle.pause(v.data.name);
343
475
  respond({ success: true, status: "paused" });
@@ -388,6 +520,50 @@ const getFleetStatus = (ctx, rawArgs, respond) => {
388
520
  const stopped = names.length - running - paused;
389
521
  respond({ total: names.length, running, paused, stopped });
390
522
  };
523
+ const getEffort = (ctx, rawArgs, respond, meta) => {
524
+ const v = validateArgs(GetEffortArgs, rawArgs, "get_effort");
525
+ if (!v.ok) {
526
+ respond(null, v.error);
527
+ return;
528
+ }
529
+ const name = v.data.name ?? meta?.instanceName;
530
+ if (!name) {
531
+ respond(null, "No instance name available");
532
+ return;
533
+ }
534
+ const fm = ctx;
535
+ const strategy = fm.effortStrategyFor?.(name) ?? "unsupported";
536
+ const supported = strategy !== "unsupported";
537
+ const levels = supported ? fm.effortLevelsFor?.(name) ?? [] : [];
538
+ const resolved = fm.resolveInstanceEffort?.(name) ?? { effort: null, source: "unset" };
539
+ respond({
540
+ instance: name,
541
+ backend: fm.backendNameForInstance?.(name) ?? null,
542
+ // null (not "") when the CLI has none, so a caller can branch on it rather
543
+ // than parse a sentinel string.
544
+ effort: supported ? resolved.effort : null,
545
+ source: supported ? resolved.source : "unsupported",
546
+ available_levels: levels,
547
+ // "restart" warns the agent that changing this costs a respawn — worth
548
+ // knowing before it changes its own effort mid-task.
549
+ change_strategy: strategy,
550
+ });
551
+ };
552
+ const getUsage = async (ctx, rawArgs, respond) => {
553
+ const v = validateArgs(GetUsageArgs, rawArgs, "get_usage");
554
+ if (!v.ok) {
555
+ respond(null, v.error);
556
+ return;
557
+ }
558
+ try {
559
+ // Same structure as GET /api/ai-usage, same 5-minute cache behind it.
560
+ const { getUsageSnapshot } = await import("./usage/usage-api.js");
561
+ respond(await getUsageSnapshot(v.data.force === true));
562
+ }
563
+ catch (err) {
564
+ respond(null, `Usage fetch failed: ${err.message}`);
565
+ }
566
+ };
391
567
  const getInstanceLogs = async (ctx, rawArgs, respond) => {
392
568
  const v = validateArgs(GetInstanceLogsArgs, rawArgs, "get_instance_logs");
393
569
  if (!v.ok) {
@@ -615,10 +791,17 @@ const broadcast = async (ctx, rawArgs, respond, meta) => {
615
791
  else {
616
792
  targetNames = [...ctx.instanceIpcClients.keys()].filter(n => n !== meta.instanceName && n !== senderLabel);
617
793
  }
618
- const deliveryResults = await Promise.all(targetNames.map(async (targetName) => {
794
+ // Fire-and-queue, same rationale as send_to_instance: a broadcast awaiting every
795
+ // target's idle gate blocked for as long as the BUSIEST recipient. Connectivity
796
+ // is decided synchronously (that's the real failure), delivery runs in background.
797
+ const sentTo = [];
798
+ const failed = [];
799
+ for (const targetName of targetNames) {
619
800
  const hostInstance = ctx.instanceIpcClients.has(targetName) ? targetName : ctx.sessionRegistry.get(targetName);
620
- if (!hostInstance || !ctx.instanceIpcClients.has(hostInstance))
621
- return { targetName, sent: false };
801
+ if (!hostInstance || !ctx.instanceIpcClients.has(hostInstance)) {
802
+ failed.push(targetName);
803
+ continue;
804
+ }
622
805
  const correlationId = `bcast-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
623
806
  const ipcMeta = {
624
807
  chat_id: "", message_id: `bcast-${Date.now()}`, user: `instance:${senderLabel}`,
@@ -633,23 +816,18 @@ const broadcast = async (ctx, rawArgs, respond, meta) => {
633
816
  ipcMeta.task_summary = task_summary;
634
817
  if (senderDisplay && senderDisplay !== senderLabel)
635
818
  ipcMeta.from_display = senderDisplay;
636
- try {
637
- await deliverToInstance(ctx, hostInstance, { type: "fleet_inbound", targetSession: targetName, content: message, meta: ipcMeta });
638
- return { targetName, sent: true };
639
- }
640
- catch {
641
- return { targetName, sent: false };
642
- }
643
- }));
644
- const sentTo = deliveryResults.filter(result => result.sent).map(result => result.targetName);
645
- const failed = deliveryResults.filter(result => !result.sent).map(result => result.targetName);
819
+ // Same at-least-once treatment as send_to_instance: retry, then surface a
820
+ // final failure on both topics instead of dying in a warn-level log line.
821
+ void deliverCrossInstanceWithRetry(ctx, hostInstance, targetName, senderLabel, correlationId, { type: "fleet_inbound", targetSession: targetName, content: message, meta: ipcMeta });
822
+ sentTo.push(targetName);
823
+ }
646
824
  ctx.logger.info(`📢 ${senderLabel} broadcast to ${sentTo.length} instances: ${(message).slice(0, 80)}`);
647
825
  const summary = task_summary || message.slice(0, 200);
648
826
  for (const target of sentTo) {
649
827
  ctx.eventLog?.logActivity("message", senderLabel, summary, target);
650
828
  }
651
829
  ctx.queueMirrorMessage?.(`📢 ${senderLabel} → [${sentTo.join(", ")}]: ${message.slice(0, 500)}${message.length > 500 ? " […]" : ""}`);
652
- respond({ sent_to: sentTo, failed, count: sentTo.length });
830
+ respond({ sent_to: sentTo, failed, count: sentTo.length, queued: true });
653
831
  };
654
832
  // ── Teams ────────────────────────────────────────────────────────────────
655
833
  const createTeam = (ctx, rawArgs, respond) => {
@@ -993,6 +1171,8 @@ export const outboundHandlers = new Map([
993
1171
  ["wake_instance", wakeInstance],
994
1172
  ["stop_instance", stopInstance],
995
1173
  ["get_fleet_status", getFleetStatus],
1174
+ ["get_effort", getEffort],
1175
+ ["get_usage", getUsage],
996
1176
  ["get_instance_logs", getInstanceLogs],
997
1177
  ["get_fleet_config", getFleetConfig],
998
1178
  ["update_instance_config", updateInstanceConfig],