crewly 1.20.106 → 1.20.107

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 (548) hide show
  1. package/README.md +22 -12
  2. package/config/constants.ts +43 -0
  3. package/config/index.ts +2 -0
  4. package/config/skills/_common/lib.sh +55 -2
  5. package/config/skills/_common/lib.test.sh +58 -1
  6. package/config/skills/_common/task-pool-body-shape.test.sh +60 -0
  7. package/config/skills/agent/core/cancel-followup/execute.sh +18 -3
  8. package/config/skills/agent/core/cancel-followup/execute.test.sh +73 -0
  9. package/config/skills/agent/core/complete-task/execute.sh +1 -1
  10. package/config/skills/agent/core/create-intent-tasks/execute.sh +1 -1
  11. package/config/skills/agent/core/create-task/SKILL.md +1 -0
  12. package/config/skills/agent/core/create-task/execute.sh +10 -0
  13. package/config/skills/agent/core/decompose-intent/execute.sh +1 -1
  14. package/config/skills/agent/core/handoff-task/execute.sh +1 -1
  15. package/config/skills/agent/core/list-my-followups/SKILL.md +1 -1
  16. package/config/skills/agent/core/list-my-followups/execute.sh +25 -3
  17. package/config/skills/agent/core/list-my-followups/execute.test.sh +72 -0
  18. package/config/skills/agent/core/poll-tasks/execute.sh +3 -3
  19. package/config/skills/agent/core/reply-channel/SKILL.md +1 -1
  20. package/config/skills/agent/core/report-progress/execute.sh +1 -1
  21. package/config/skills/agent/core/report-status/execute.sh +1 -1
  22. package/config/skills/agent/core/slack-post/SKILL.md +1 -1
  23. package/config/skills/agent/core/update-intent-task/execute.sh +1 -1
  24. package/config/skills/agent/marketing/brand-onboarding/execute.sh +1 -1
  25. package/config/skills/agent/marketing/submit-for-approval/execute.sh +1 -1
  26. package/config/skills/agent/remote-browser/SOP-google-flow-video.md +1 -1
  27. package/config/skills/agent/remote-browser/execute.sh +33 -1
  28. package/config/skills/agent/remote-browser/execute.test.sh +62 -0
  29. package/config/skills/agent/screenshot-compare/execute.sh +1 -1
  30. package/config/skills/agent/transcribe-audio/SKILL.md +1 -1
  31. package/config/skills/agent/transcribe-audio/execute.sh +1 -1
  32. package/config/skills/agent/transcribe-audio/instructions.md +1 -1
  33. package/config/skills/orchestrator/delegate-task/SKILL.md +1 -1
  34. package/config/skills/orchestrator/get-tasks/SKILL.md +7 -1
  35. package/config/skills/orchestrator/get-tasks/execute.sh +51 -28
  36. package/config/skills/orchestrator/get-tasks/execute.test.sh +67 -0
  37. package/config/skills/orchestrator/heartbeat/execute.sh +2 -2
  38. package/config/skills/orchestrator/list-missions/execute.sh +1 -1
  39. package/config/skills/orchestrator/list-missions/execute.test.sh +38 -11
  40. package/config/skills/team-leader/decompose-goal/SKILL.md +1 -0
  41. package/config/skills/team-leader/decompose-goal/execute.sh +17 -2
  42. package/config/skills/team-leader/delegate-task/SKILL.md +1 -0
  43. package/config/skills/team-leader/delegate-task/execute.sh +6 -2
  44. package/dist/backend/backend/src/constants.d.ts +199 -2
  45. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  46. package/dist/backend/backend/src/constants.js +190 -3
  47. package/dist/backend/backend/src/constants.js.map +1 -1
  48. package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts +33 -0
  49. package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
  50. package/dist/backend/backend/src/controllers/browser/browser.controller.js +176 -9
  51. package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
  52. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
  53. package/dist/backend/backend/src/controllers/chat/chat.controller.js +38 -35
  54. package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
  55. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts +10 -45
  56. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts.map +1 -1
  57. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js +40 -89
  58. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js.map +1 -1
  59. package/dist/backend/backend/src/controllers/session/session.controller.d.ts +2 -1
  60. package/dist/backend/backend/src/controllers/session/session.controller.d.ts.map +1 -1
  61. package/dist/backend/backend/src/controllers/session/session.controller.js +21 -0
  62. package/dist/backend/backend/src/controllers/session/session.controller.js.map +1 -1
  63. package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
  64. package/dist/backend/backend/src/controllers/slack/slack.controller.js +51 -3
  65. package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
  66. package/dist/backend/backend/src/controllers/system/restart-readiness.controller.d.ts +23 -0
  67. package/dist/backend/backend/src/controllers/system/restart-readiness.controller.d.ts.map +1 -0
  68. package/dist/backend/backend/src/controllers/system/restart-readiness.controller.js +35 -0
  69. package/dist/backend/backend/src/controllers/system/restart-readiness.controller.js.map +1 -0
  70. package/dist/backend/backend/src/controllers/system/system.controller.d.ts +5 -3
  71. package/dist/backend/backend/src/controllers/system/system.controller.d.ts.map +1 -1
  72. package/dist/backend/backend/src/controllers/system/system.controller.js +27 -6
  73. package/dist/backend/backend/src/controllers/system/system.controller.js.map +1 -1
  74. package/dist/backend/backend/src/controllers/system/system.routes.d.ts.map +1 -1
  75. package/dist/backend/backend/src/controllers/system/system.routes.js +3 -0
  76. package/dist/backend/backend/src/controllers/system/system.routes.js.map +1 -1
  77. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
  78. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +29 -1
  79. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
  80. package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
  81. package/dist/backend/backend/src/controllers/team/team.controller.js +86 -6
  82. package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
  83. package/dist/backend/backend/src/controllers/tickets/tickets.controller.d.ts +41 -0
  84. package/dist/backend/backend/src/controllers/tickets/tickets.controller.d.ts.map +1 -0
  85. package/dist/backend/backend/src/controllers/tickets/tickets.controller.js +135 -0
  86. package/dist/backend/backend/src/controllers/tickets/tickets.controller.js.map +1 -0
  87. package/dist/backend/backend/src/controllers/tickets/tickets.routes.d.ts +18 -0
  88. package/dist/backend/backend/src/controllers/tickets/tickets.routes.d.ts.map +1 -0
  89. package/dist/backend/backend/src/controllers/tickets/tickets.routes.js +25 -0
  90. package/dist/backend/backend/src/controllers/tickets/tickets.routes.js.map +1 -0
  91. package/dist/backend/backend/src/index.d.ts +70 -1
  92. package/dist/backend/backend/src/index.d.ts.map +1 -1
  93. package/dist/backend/backend/src/index.js +352 -71
  94. package/dist/backend/backend/src/index.js.map +1 -1
  95. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  96. package/dist/backend/backend/src/routes/api.routes.js +3 -0
  97. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  98. package/dist/backend/backend/src/scripts/leaked-stub-teams.lib.d.ts +128 -0
  99. package/dist/backend/backend/src/scripts/leaked-stub-teams.lib.d.ts.map +1 -0
  100. package/dist/backend/backend/src/scripts/leaked-stub-teams.lib.js +200 -0
  101. package/dist/backend/backend/src/scripts/leaked-stub-teams.lib.js.map +1 -0
  102. package/dist/backend/backend/src/services/agent/active-work-briefing.service.d.ts +2 -2
  103. package/dist/backend/backend/src/services/agent/active-work-briefing.service.d.ts.map +1 -1
  104. package/dist/backend/backend/src/services/agent/active-work-briefing.service.js +3 -1
  105. package/dist/backend/backend/src/services/agent/active-work-briefing.service.js.map +1 -1
  106. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +4 -0
  107. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  108. package/dist/backend/backend/src/services/agent/agent-registration.service.js +61 -4
  109. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  110. package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts +30 -0
  111. package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -1
  112. package/dist/backend/backend/src/services/agent/claude-runtime.service.js +62 -1
  113. package/dist/backend/backend/src/services/agent/claude-runtime.service.js.map +1 -1
  114. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
  115. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +2 -1
  116. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
  117. package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts +0 -2
  118. package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts.map +1 -1
  119. package/dist/backend/backend/src/services/agent/crewly-agent/types.js +0 -2
  120. package/dist/backend/backend/src/services/agent/crewly-agent/types.js.map +1 -1
  121. package/dist/backend/backend/src/services/agent/gemini-runtime.service.d.ts +65 -1
  122. package/dist/backend/backend/src/services/agent/gemini-runtime.service.d.ts.map +1 -1
  123. package/dist/backend/backend/src/services/agent/gemini-runtime.service.js +113 -10
  124. package/dist/backend/backend/src/services/agent/gemini-runtime.service.js.map +1 -1
  125. package/dist/backend/backend/src/services/agent/restore-filter.d.ts +12 -0
  126. package/dist/backend/backend/src/services/agent/restore-filter.d.ts.map +1 -1
  127. package/dist/backend/backend/src/services/agent/restore-filter.js +19 -0
  128. package/dist/backend/backend/src/services/agent/restore-filter.js.map +1 -1
  129. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
  130. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js +3 -2
  131. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
  132. package/dist/backend/backend/src/services/agent/runtime-startup-blocked.error.d.ts +28 -0
  133. package/dist/backend/backend/src/services/agent/runtime-startup-blocked.error.d.ts.map +1 -0
  134. package/dist/backend/backend/src/services/agent/runtime-startup-blocked.error.js +34 -0
  135. package/dist/backend/backend/src/services/agent/runtime-startup-blocked.error.js.map +1 -0
  136. package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts +57 -5
  137. package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts.map +1 -1
  138. package/dist/backend/backend/src/services/browser/browser-bridge.service.js +98 -18
  139. package/dist/backend/backend/src/services/browser/browser-bridge.service.js.map +1 -1
  140. package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts +12 -1
  141. package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts.map +1 -1
  142. package/dist/backend/backend/src/services/browser/browser-proxy.service.js +25 -4
  143. package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
  144. package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.d.ts +2 -1
  145. package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.d.ts.map +1 -1
  146. package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.js +5 -1
  147. package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.js.map +1 -1
  148. package/dist/backend/backend/src/services/browser/browser-session.service.d.ts +38 -0
  149. package/dist/backend/backend/src/services/browser/browser-session.service.d.ts.map +1 -1
  150. package/dist/backend/backend/src/services/browser/browser-session.service.js +34 -0
  151. package/dist/backend/backend/src/services/browser/browser-session.service.js.map +1 -1
  152. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +6 -0
  153. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
  154. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +5 -0
  155. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  156. package/dist/backend/backend/src/services/chat-v2/chat-v2.relay-adapter.service.d.ts.map +1 -1
  157. package/dist/backend/backend/src/services/chat-v2/chat-v2.relay-adapter.service.js +7 -2
  158. package/dist/backend/backend/src/services/chat-v2/chat-v2.relay-adapter.service.js.map +1 -1
  159. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +23 -1
  160. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  161. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +58 -1
  162. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  163. package/dist/backend/backend/src/services/chat-v2/owner-inbound.utils.d.ts +63 -0
  164. package/dist/backend/backend/src/services/chat-v2/owner-inbound.utils.d.ts.map +1 -0
  165. package/dist/backend/backend/src/services/chat-v2/owner-inbound.utils.js +72 -0
  166. package/dist/backend/backend/src/services/chat-v2/owner-inbound.utils.js.map +1 -0
  167. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +10 -0
  168. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
  169. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +15 -0
  170. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
  171. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -1
  172. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +6 -1
  173. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
  174. package/dist/backend/backend/src/services/core/retry.util.d.ts +5 -0
  175. package/dist/backend/backend/src/services/core/retry.util.d.ts.map +1 -1
  176. package/dist/backend/backend/src/services/core/retry.util.js +2 -2
  177. package/dist/backend/backend/src/services/core/retry.util.js.map +1 -1
  178. package/dist/backend/backend/src/services/factory.service.js +3 -3
  179. package/dist/backend/backend/src/services/factory.service.js.map +1 -1
  180. package/dist/backend/backend/src/services/messaging/google-chat-initializer.d.ts.map +1 -1
  181. package/dist/backend/backend/src/services/messaging/google-chat-initializer.js +24 -1
  182. package/dist/backend/backend/src/services/messaging/google-chat-initializer.js.map +1 -1
  183. package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts +9 -0
  184. package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
  185. package/dist/backend/backend/src/services/messaging/queue-processor.service.js +55 -0
  186. package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -1
  187. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +7 -0
  188. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
  189. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js +12 -0
  190. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
  191. package/dist/backend/backend/src/services/messaging/thread-status-queue.service.d.ts +36 -1
  192. package/dist/backend/backend/src/services/messaging/thread-status-queue.service.d.ts.map +1 -1
  193. package/dist/backend/backend/src/services/messaging/thread-status-queue.service.js +90 -2
  194. package/dist/backend/backend/src/services/messaging/thread-status-queue.service.js.map +1 -1
  195. package/dist/backend/backend/src/services/orchestrator/commitment-approval-guard.d.ts.map +1 -1
  196. package/dist/backend/backend/src/services/orchestrator/commitment-approval-guard.js +22 -16
  197. package/dist/backend/backend/src/services/orchestrator/commitment-approval-guard.js.map +1 -1
  198. package/dist/backend/backend/src/services/orchestrator/onboarding/materialize-team.js +11 -1
  199. package/dist/backend/backend/src/services/orchestrator/onboarding/materialize-team.js.map +1 -1
  200. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts.map +1 -1
  201. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js +9 -9
  202. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js.map +1 -1
  203. package/dist/backend/backend/src/services/restart/in-flight-turn-tracker.service.d.ts +189 -0
  204. package/dist/backend/backend/src/services/restart/in-flight-turn-tracker.service.d.ts.map +1 -0
  205. package/dist/backend/backend/src/services/restart/in-flight-turn-tracker.service.js +246 -0
  206. package/dist/backend/backend/src/services/restart/in-flight-turn-tracker.service.js.map +1 -0
  207. package/dist/backend/backend/src/services/restart/interrupted-turns.d.ts +153 -0
  208. package/dist/backend/backend/src/services/restart/interrupted-turns.d.ts.map +1 -0
  209. package/dist/backend/backend/src/services/restart/interrupted-turns.js +279 -0
  210. package/dist/backend/backend/src/services/restart/interrupted-turns.js.map +1 -0
  211. package/dist/backend/backend/src/services/restart/restart-drain.service.d.ts +176 -0
  212. package/dist/backend/backend/src/services/restart/restart-drain.service.d.ts.map +1 -0
  213. package/dist/backend/backend/src/services/restart/restart-drain.service.js +298 -0
  214. package/dist/backend/backend/src/services/restart/restart-drain.service.js.map +1 -0
  215. package/dist/backend/backend/src/services/restart/turn-probe.d.ts +52 -0
  216. package/dist/backend/backend/src/services/restart/turn-probe.d.ts.map +1 -0
  217. package/dist/backend/backend/src/services/restart/turn-probe.js +61 -0
  218. package/dist/backend/backend/src/services/restart/turn-probe.js.map +1 -0
  219. package/dist/backend/backend/src/services/session/pty/node-pty-install.utils.d.ts +70 -0
  220. package/dist/backend/backend/src/services/session/pty/node-pty-install.utils.d.ts.map +1 -0
  221. package/dist/backend/backend/src/services/session/pty/node-pty-install.utils.js +105 -0
  222. package/dist/backend/backend/src/services/session/pty/node-pty-install.utils.js.map +1 -0
  223. package/dist/backend/backend/src/services/session/pty/pty-session.d.ts +2 -0
  224. package/dist/backend/backend/src/services/session/pty/pty-session.d.ts.map +1 -1
  225. package/dist/backend/backend/src/services/session/pty/pty-session.js +53 -1
  226. package/dist/backend/backend/src/services/session/pty/pty-session.js.map +1 -1
  227. package/dist/backend/backend/src/services/session/session-binding.d.ts +125 -0
  228. package/dist/backend/backend/src/services/session/session-binding.d.ts.map +1 -0
  229. package/dist/backend/backend/src/services/session/session-binding.js +183 -0
  230. package/dist/backend/backend/src/services/session/session-binding.js.map +1 -0
  231. package/dist/backend/backend/src/services/session/session-handoff.service.d.ts.map +1 -1
  232. package/dist/backend/backend/src/services/session/session-handoff.service.js +19 -0
  233. package/dist/backend/backend/src/services/session/session-handoff.service.js.map +1 -1
  234. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts +10 -0
  235. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
  236. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js +37 -1
  237. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  238. package/dist/backend/backend/src/services/slack/slack-cloud-config.service.d.ts +4 -3
  239. package/dist/backend/backend/src/services/slack/slack-cloud-config.service.d.ts.map +1 -1
  240. package/dist/backend/backend/src/services/slack/slack-cloud-config.service.js +4 -3
  241. package/dist/backend/backend/src/services/slack/slack-cloud-config.service.js.map +1 -1
  242. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts +72 -7
  243. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
  244. package/dist/backend/backend/src/services/slack/slack-initializer.js +185 -23
  245. package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
  246. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +4 -45
  247. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  248. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +57 -190
  249. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  250. package/dist/backend/backend/src/services/slack/slack-source-preference.service.d.ts +59 -0
  251. package/dist/backend/backend/src/services/slack/slack-source-preference.service.d.ts.map +1 -0
  252. package/dist/backend/backend/src/services/slack/slack-source-preference.service.js +69 -0
  253. package/dist/backend/backend/src/services/slack/slack-source-preference.service.js.map +1 -0
  254. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +18 -0
  255. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  256. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +64 -3
  257. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  258. package/dist/backend/backend/src/services/slack/slack.service.d.ts +33 -1
  259. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
  260. package/dist/backend/backend/src/services/slack/slack.service.js +129 -4
  261. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
  262. package/dist/backend/backend/src/services/task-pool/pool-archive-migration.d.ts +108 -0
  263. package/dist/backend/backend/src/services/task-pool/pool-archive-migration.d.ts.map +1 -0
  264. package/dist/backend/backend/src/services/task-pool/pool-archive-migration.js +193 -0
  265. package/dist/backend/backend/src/services/task-pool/pool-archive-migration.js.map +1 -0
  266. package/dist/backend/backend/src/services/task-pool/pool-storage.d.ts +15 -0
  267. package/dist/backend/backend/src/services/task-pool/pool-storage.d.ts.map +1 -1
  268. package/dist/backend/backend/src/services/task-pool/pool-storage.js +30 -0
  269. package/dist/backend/backend/src/services/task-pool/pool-storage.js.map +1 -1
  270. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +41 -1
  271. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  272. package/dist/backend/backend/src/services/task-pool/task-pool.service.js +55 -1
  273. package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  274. package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.d.ts +7 -0
  275. package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.d.ts.map +1 -1
  276. package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.js +32 -1
  277. package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.js.map +1 -1
  278. package/dist/backend/backend/src/services/v3/agent-auto-claim.service.d.ts.map +1 -1
  279. package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js +4 -3
  280. package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js.map +1 -1
  281. package/dist/backend/backend/src/services/v3/request-decompose.subscriber.d.ts.map +1 -1
  282. package/dist/backend/backend/src/services/v3/request-decompose.subscriber.js +12 -0
  283. package/dist/backend/backend/src/services/v3/request-decompose.subscriber.js.map +1 -1
  284. package/dist/backend/backend/src/services/v3/request.service.d.ts +7 -0
  285. package/dist/backend/backend/src/services/v3/request.service.d.ts.map +1 -1
  286. package/dist/backend/backend/src/services/v3/request.service.js +17 -0
  287. package/dist/backend/backend/src/services/v3/request.service.js.map +1 -1
  288. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.d.ts +279 -0
  289. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.d.ts.map +1 -0
  290. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.js +458 -0
  291. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.js.map +1 -0
  292. package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts +376 -0
  293. package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts.map +1 -0
  294. package/dist/backend/backend/src/services/v3/ticket-intake.service.js +566 -0
  295. package/dist/backend/backend/src/services/v3/ticket-intake.service.js.map +1 -0
  296. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.d.ts.map +1 -1
  297. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.js +3 -3
  298. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.js.map +1 -1
  299. package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts +28 -4
  300. package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts.map +1 -1
  301. package/dist/backend/backend/src/services/v3/trigger-engine.service.js +40 -10
  302. package/dist/backend/backend/src/services/v3/trigger-engine.service.js.map +1 -1
  303. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts +1 -0
  304. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts.map +1 -1
  305. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +3 -3
  306. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
  307. package/dist/backend/backend/src/types/slack.types.d.ts +29 -0
  308. package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
  309. package/dist/backend/backend/src/types/slack.types.js.map +1 -1
  310. package/dist/backend/backend/src/types/thread-status.types.d.ts +26 -0
  311. package/dist/backend/backend/src/types/thread-status.types.d.ts.map +1 -1
  312. package/dist/backend/backend/src/types/thread-status.types.js +17 -0
  313. package/dist/backend/backend/src/types/thread-status.types.js.map +1 -1
  314. package/dist/backend/backend/src/types/v2/index.d.ts +3 -2
  315. package/dist/backend/backend/src/types/v2/index.d.ts.map +1 -1
  316. package/dist/backend/backend/src/types/v2/index.js +1 -1
  317. package/dist/backend/backend/src/types/v2/index.js.map +1 -1
  318. package/dist/backend/backend/src/types/v2/request.types.d.ts +39 -3
  319. package/dist/backend/backend/src/types/v2/request.types.d.ts.map +1 -1
  320. package/dist/backend/backend/src/types/v2/request.types.js +11 -2
  321. package/dist/backend/backend/src/types/v2/request.types.js.map +1 -1
  322. package/dist/backend/backend/src/types/v2/ticket.types.d.ts +173 -0
  323. package/dist/backend/backend/src/types/v2/ticket.types.d.ts.map +1 -0
  324. package/dist/backend/backend/src/types/v2/ticket.types.js +203 -0
  325. package/dist/backend/backend/src/types/v2/ticket.types.js.map +1 -0
  326. package/dist/backend/backend/src/utils/agent-caller.utils.d.ts +26 -0
  327. package/dist/backend/backend/src/utils/agent-caller.utils.d.ts.map +1 -1
  328. package/dist/backend/backend/src/utils/agent-caller.utils.js +40 -3
  329. package/dist/backend/backend/src/utils/agent-caller.utils.js.map +1 -1
  330. package/dist/backend/backend/src/utils/gemini-auth-settings.d.ts +62 -0
  331. package/dist/backend/backend/src/utils/gemini-auth-settings.d.ts.map +1 -0
  332. package/dist/backend/backend/src/utils/gemini-auth-settings.js +104 -0
  333. package/dist/backend/backend/src/utils/gemini-auth-settings.js.map +1 -0
  334. package/dist/backend/backend/src/utils/local-api-url.utils.d.ts +56 -0
  335. package/dist/backend/backend/src/utils/local-api-url.utils.d.ts.map +1 -0
  336. package/dist/backend/backend/src/utils/local-api-url.utils.js +80 -0
  337. package/dist/backend/backend/src/utils/local-api-url.utils.js.map +1 -0
  338. package/dist/backend/build-info.json +2 -2
  339. package/dist/backend/config/constants.d.ts +40 -0
  340. package/dist/backend/config/constants.d.ts.map +1 -1
  341. package/dist/backend/config/constants.js +41 -0
  342. package/dist/backend/config/constants.js.map +1 -1
  343. package/dist/backend/config/index.d.ts +4 -2
  344. package/dist/backend/config/index.d.ts.map +1 -1
  345. package/dist/backend/config/index.js +2 -2
  346. package/dist/backend/config/index.js.map +1 -1
  347. package/dist/cli/backend/src/constants.d.ts +199 -2
  348. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  349. package/dist/cli/backend/src/constants.js +190 -3
  350. package/dist/cli/backend/src/constants.js.map +1 -1
  351. package/dist/cli/backend/src/services/agent/active-work-briefing.service.d.ts +2 -2
  352. package/dist/cli/backend/src/services/agent/active-work-briefing.service.d.ts.map +1 -1
  353. package/dist/cli/backend/src/services/agent/active-work-briefing.service.js +3 -1
  354. package/dist/cli/backend/src/services/agent/active-work-briefing.service.js.map +1 -1
  355. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +4 -0
  356. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  357. package/dist/cli/backend/src/services/agent/agent-registration.service.js +61 -4
  358. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
  359. package/dist/cli/backend/src/services/agent/claude-runtime.service.d.ts +30 -0
  360. package/dist/cli/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -1
  361. package/dist/cli/backend/src/services/agent/claude-runtime.service.js +62 -1
  362. package/dist/cli/backend/src/services/agent/claude-runtime.service.js.map +1 -1
  363. package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
  364. package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +2 -1
  365. package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
  366. package/dist/cli/backend/src/services/agent/crewly-agent/types.d.ts +0 -2
  367. package/dist/cli/backend/src/services/agent/crewly-agent/types.d.ts.map +1 -1
  368. package/dist/cli/backend/src/services/agent/crewly-agent/types.js +0 -2
  369. package/dist/cli/backend/src/services/agent/crewly-agent/types.js.map +1 -1
  370. package/dist/cli/backend/src/services/agent/gemini-runtime.service.d.ts +65 -1
  371. package/dist/cli/backend/src/services/agent/gemini-runtime.service.d.ts.map +1 -1
  372. package/dist/cli/backend/src/services/agent/gemini-runtime.service.js +113 -10
  373. package/dist/cli/backend/src/services/agent/gemini-runtime.service.js.map +1 -1
  374. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
  375. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js +3 -2
  376. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
  377. package/dist/cli/backend/src/services/agent/runtime-startup-blocked.error.d.ts +28 -0
  378. package/dist/cli/backend/src/services/agent/runtime-startup-blocked.error.d.ts.map +1 -0
  379. package/dist/cli/backend/src/services/agent/runtime-startup-blocked.error.js +34 -0
  380. package/dist/cli/backend/src/services/agent/runtime-startup-blocked.error.js.map +1 -0
  381. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +6 -0
  382. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
  383. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +5 -0
  384. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  385. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts +23 -1
  386. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  387. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js +58 -1
  388. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  389. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts +10 -0
  390. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
  391. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js +15 -0
  392. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
  393. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +7 -0
  394. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
  395. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js +12 -0
  396. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
  397. package/dist/cli/backend/src/services/messaging/thread-status-queue.service.d.ts +36 -1
  398. package/dist/cli/backend/src/services/messaging/thread-status-queue.service.d.ts.map +1 -1
  399. package/dist/cli/backend/src/services/messaging/thread-status-queue.service.js +90 -2
  400. package/dist/cli/backend/src/services/messaging/thread-status-queue.service.js.map +1 -1
  401. package/dist/cli/backend/src/services/restart/in-flight-turn-tracker.service.d.ts +189 -0
  402. package/dist/cli/backend/src/services/restart/in-flight-turn-tracker.service.d.ts.map +1 -0
  403. package/dist/cli/backend/src/services/restart/in-flight-turn-tracker.service.js +246 -0
  404. package/dist/cli/backend/src/services/restart/in-flight-turn-tracker.service.js.map +1 -0
  405. package/dist/cli/backend/src/services/restart/restart-drain.service.d.ts +176 -0
  406. package/dist/cli/backend/src/services/restart/restart-drain.service.d.ts.map +1 -0
  407. package/dist/cli/backend/src/services/restart/restart-drain.service.js +298 -0
  408. package/dist/cli/backend/src/services/restart/restart-drain.service.js.map +1 -0
  409. package/dist/cli/backend/src/services/session/pty/node-pty-install.utils.d.ts +70 -0
  410. package/dist/cli/backend/src/services/session/pty/node-pty-install.utils.d.ts.map +1 -0
  411. package/dist/cli/backend/src/services/session/pty/node-pty-install.utils.js +105 -0
  412. package/dist/cli/backend/src/services/session/pty/node-pty-install.utils.js.map +1 -0
  413. package/dist/cli/backend/src/services/session/pty/pty-session.d.ts +2 -0
  414. package/dist/cli/backend/src/services/session/pty/pty-session.d.ts.map +1 -1
  415. package/dist/cli/backend/src/services/session/pty/pty-session.js +53 -1
  416. package/dist/cli/backend/src/services/session/pty/pty-session.js.map +1 -1
  417. package/dist/cli/backend/src/services/session/session-handoff.service.d.ts.map +1 -1
  418. package/dist/cli/backend/src/services/session/session-handoff.service.js +19 -0
  419. package/dist/cli/backend/src/services/session/session-handoff.service.js.map +1 -1
  420. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts +10 -0
  421. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
  422. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +37 -1
  423. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  424. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts +4 -45
  425. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  426. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +57 -190
  427. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  428. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +18 -0
  429. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  430. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +64 -3
  431. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  432. package/dist/cli/backend/src/services/slack/slack.service.d.ts +33 -1
  433. package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
  434. package/dist/cli/backend/src/services/slack/slack.service.js +129 -4
  435. package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
  436. package/dist/cli/backend/src/services/task-pool/pool-storage.d.ts +15 -0
  437. package/dist/cli/backend/src/services/task-pool/pool-storage.d.ts.map +1 -1
  438. package/dist/cli/backend/src/services/task-pool/pool-storage.js +30 -0
  439. package/dist/cli/backend/src/services/task-pool/pool-storage.js.map +1 -1
  440. package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +41 -1
  441. package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  442. package/dist/cli/backend/src/services/task-pool/task-pool.service.js +55 -1
  443. package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  444. package/dist/cli/backend/src/services/v3/request.service.d.ts +7 -0
  445. package/dist/cli/backend/src/services/v3/request.service.d.ts.map +1 -1
  446. package/dist/cli/backend/src/services/v3/request.service.js +17 -0
  447. package/dist/cli/backend/src/services/v3/request.service.js.map +1 -1
  448. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.d.ts +279 -0
  449. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.d.ts.map +1 -0
  450. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.js +458 -0
  451. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.js.map +1 -0
  452. package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts +376 -0
  453. package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts.map +1 -0
  454. package/dist/cli/backend/src/services/v3/ticket-intake.service.js +566 -0
  455. package/dist/cli/backend/src/services/v3/ticket-intake.service.js.map +1 -0
  456. package/dist/cli/backend/src/types/slack.types.d.ts +29 -0
  457. package/dist/cli/backend/src/types/slack.types.d.ts.map +1 -1
  458. package/dist/cli/backend/src/types/slack.types.js.map +1 -1
  459. package/dist/cli/backend/src/types/thread-status.types.d.ts +26 -0
  460. package/dist/cli/backend/src/types/thread-status.types.d.ts.map +1 -1
  461. package/dist/cli/backend/src/types/thread-status.types.js +17 -0
  462. package/dist/cli/backend/src/types/thread-status.types.js.map +1 -1
  463. package/dist/cli/backend/src/types/v2/index.d.ts +3 -2
  464. package/dist/cli/backend/src/types/v2/index.d.ts.map +1 -1
  465. package/dist/cli/backend/src/types/v2/index.js +1 -1
  466. package/dist/cli/backend/src/types/v2/index.js.map +1 -1
  467. package/dist/cli/backend/src/types/v2/request.types.d.ts +39 -3
  468. package/dist/cli/backend/src/types/v2/request.types.d.ts.map +1 -1
  469. package/dist/cli/backend/src/types/v2/request.types.js +11 -2
  470. package/dist/cli/backend/src/types/v2/request.types.js.map +1 -1
  471. package/dist/cli/backend/src/types/v2/ticket.types.d.ts +173 -0
  472. package/dist/cli/backend/src/types/v2/ticket.types.d.ts.map +1 -0
  473. package/dist/cli/backend/src/types/v2/ticket.types.js +203 -0
  474. package/dist/cli/backend/src/types/v2/ticket.types.js.map +1 -0
  475. package/dist/cli/backend/src/utils/gemini-auth-settings.d.ts +62 -0
  476. package/dist/cli/backend/src/utils/gemini-auth-settings.d.ts.map +1 -0
  477. package/dist/cli/backend/src/utils/gemini-auth-settings.js +104 -0
  478. package/dist/cli/backend/src/utils/gemini-auth-settings.js.map +1 -0
  479. package/dist/cli/backend/src/utils/local-api-url.utils.d.ts +56 -0
  480. package/dist/cli/backend/src/utils/local-api-url.utils.d.ts.map +1 -0
  481. package/dist/cli/backend/src/utils/local-api-url.utils.js +80 -0
  482. package/dist/cli/backend/src/utils/local-api-url.utils.js.map +1 -0
  483. package/dist/cli/cli/src/commands/doctor.d.ts +73 -2
  484. package/dist/cli/cli/src/commands/doctor.d.ts.map +1 -1
  485. package/dist/cli/cli/src/commands/doctor.js +250 -8
  486. package/dist/cli/cli/src/commands/doctor.js.map +1 -1
  487. package/dist/cli/cli/src/commands/install.js +2 -0
  488. package/dist/cli/cli/src/commands/install.js.map +1 -1
  489. package/dist/cli/cli/src/commands/onboard.d.ts +68 -0
  490. package/dist/cli/cli/src/commands/onboard.d.ts.map +1 -1
  491. package/dist/cli/cli/src/commands/onboard.js +149 -18
  492. package/dist/cli/cli/src/commands/onboard.js.map +1 -1
  493. package/dist/cli/cli/src/commands/service.d.ts +6 -0
  494. package/dist/cli/cli/src/commands/service.d.ts.map +1 -1
  495. package/dist/cli/cli/src/commands/service.js +152 -50
  496. package/dist/cli/cli/src/commands/service.js.map +1 -1
  497. package/dist/cli/cli/src/commands/start.d.ts.map +1 -1
  498. package/dist/cli/cli/src/commands/start.js +25 -80
  499. package/dist/cli/cli/src/commands/start.js.map +1 -1
  500. package/dist/cli/cli/src/commands/status.d.ts +17 -1
  501. package/dist/cli/cli/src/commands/status.d.ts.map +1 -1
  502. package/dist/cli/cli/src/commands/status.js +133 -68
  503. package/dist/cli/cli/src/commands/status.js.map +1 -1
  504. package/dist/cli/cli/src/commands/stop.d.ts +28 -1
  505. package/dist/cli/cli/src/commands/stop.d.ts.map +1 -1
  506. package/dist/cli/cli/src/commands/stop.js +260 -100
  507. package/dist/cli/cli/src/commands/stop.js.map +1 -1
  508. package/dist/cli/cli/src/index.js +3 -2
  509. package/dist/cli/cli/src/index.js.map +1 -1
  510. package/dist/cli/cli/src/scripts/ensure-node-pty.d.ts +68 -0
  511. package/dist/cli/cli/src/scripts/ensure-node-pty.d.ts.map +1 -0
  512. package/dist/cli/cli/src/scripts/ensure-node-pty.js +167 -0
  513. package/dist/cli/cli/src/scripts/ensure-node-pty.js.map +1 -0
  514. package/dist/cli/cli/src/utils/backend-status.d.ts +175 -0
  515. package/dist/cli/cli/src/utils/backend-status.d.ts.map +1 -0
  516. package/dist/cli/cli/src/utils/backend-status.js +322 -0
  517. package/dist/cli/cli/src/utils/backend-status.js.map +1 -0
  518. package/dist/cli/cli/src/utils/marketplace.d.ts +31 -2
  519. package/dist/cli/cli/src/utils/marketplace.d.ts.map +1 -1
  520. package/dist/cli/cli/src/utils/marketplace.js +78 -20
  521. package/dist/cli/cli/src/utils/marketplace.js.map +1 -1
  522. package/dist/cli/cli/src/utils/native-toolchain.d.ts +53 -8
  523. package/dist/cli/cli/src/utils/native-toolchain.d.ts.map +1 -1
  524. package/dist/cli/cli/src/utils/native-toolchain.js +107 -15
  525. package/dist/cli/cli/src/utils/native-toolchain.js.map +1 -1
  526. package/dist/cli/cli/src/utils/process-cleanup.d.ts +38 -6
  527. package/dist/cli/cli/src/utils/process-cleanup.d.ts.map +1 -1
  528. package/dist/cli/cli/src/utils/process-cleanup.js +83 -53
  529. package/dist/cli/cli/src/utils/process-cleanup.js.map +1 -1
  530. package/dist/cli/cli/src/utils/runtime-auth.d.ts +130 -0
  531. package/dist/cli/cli/src/utils/runtime-auth.d.ts.map +1 -0
  532. package/dist/cli/cli/src/utils/runtime-auth.js +248 -0
  533. package/dist/cli/cli/src/utils/runtime-auth.js.map +1 -0
  534. package/dist/cli/cli/src/utils/safe-shutdown.d.ts +137 -0
  535. package/dist/cli/cli/src/utils/safe-shutdown.d.ts.map +1 -0
  536. package/dist/cli/cli/src/utils/safe-shutdown.js +236 -0
  537. package/dist/cli/cli/src/utils/safe-shutdown.js.map +1 -0
  538. package/dist/cli/config/constants.d.ts +40 -0
  539. package/dist/cli/config/constants.d.ts.map +1 -1
  540. package/dist/cli/config/constants.js +41 -0
  541. package/dist/cli/config/constants.js.map +1 -1
  542. package/dist/cli/config/index.d.ts +4 -2
  543. package/dist/cli/config/index.d.ts.map +1 -1
  544. package/dist/cli/config/index.js +2 -2
  545. package/dist/cli/config/index.js.map +1 -1
  546. package/frontend/dist/assets/{index-488339c1.js → index-f7b99e81.js} +222 -222
  547. package/frontend/dist/index.html +1 -1
  548. package/package.json +4 -4
@@ -16,6 +16,7 @@ import { fileURLToPath } from 'url';
16
16
  import { StorageService, TmuxService, SchedulerService, MessageSchedulerService, ActivityMonitorService, TeamActivityWebSocketService, TeamsJsonWatcherService, } from './services/index.js';
17
17
  import { getSessionBackend, getSessionBackendSync, getSessionStatePersistence, destroySessionBackend, PtySessionBackend, } from './services/session/index.js';
18
18
  import { RuntimePidRegistry } from './services/session/runtime-pid-registry.service.js';
19
+ import { removeCrewlyAgentFile, resolvePersistedSessions, selectAutoRestoreSessions } from './services/session/session-binding.js';
19
20
  import { ApiController } from './controllers/api.controller.js';
20
21
  import { createApiRoutes } from './routes/api.routes.js';
21
22
  import { TerminalGateway, setTerminalGateway } from './websocket/terminal.gateway.js';
@@ -57,7 +58,15 @@ import { setRequestServiceEventBus, RequestService } from './services/v3/request
57
58
  import { getSlackService } from './services/slack/slack.service.js';
58
59
  import { sendBootAnnouncement, isFirstBoot, markBooted } from './services/boot/boot-announce.service.js';
59
60
  import { SubAgentMessageQueue } from './services/messaging/sub-agent-message-queue.service.js';
60
- import { SUB_AGENT_QUEUE_CONSTANTS, CHAT_CONTEXT_CONSTANTS } from './constants.js';
61
+ import { SUB_AGENT_QUEUE_CONSTANTS, CHAT_CONTEXT_CONSTANTS, SAFE_RESTART, PROCESS_EXIT_CODES, CLAUDE_STARTUP_CONSTANTS, WEB_CONSTANTS } from './constants.js';
62
+ import { PtyActivityTrackerService } from './services/agent/pty-activity-tracker.service.js';
63
+ import { InFlightTurnTracker } from './services/restart/in-flight-turn-tracker.service.js';
64
+ import { TicketIntakeService, setTicketIntakeService, resolveTicketIdForSession, } from './services/v3/ticket-intake.service.js';
65
+ import { createChatV2ReceiptSink } from './services/v3/ticket-channel-hooks.js';
66
+ import { runPoolArchiveMigration } from './services/task-pool/pool-archive-migration.js';
67
+ import { createPtyTurnProbe } from './services/restart/turn-probe.js';
68
+ import { RestartDrainService, resolveRestartDrainMs } from './services/restart/restart-drain.service.js';
69
+ import { interruptedTurnsPath, loadInterruptedTurns, saveInterruptedTurns, writeInterruptedTurns, resumeInterruptedTurns, } from './services/restart/interrupted-turns.js';
61
70
  import { DeviceIdentityService } from './services/cloud/device-identity.service.js';
62
71
  import { SlackThreadStoreService, setSlackThreadStore, getSlackThreadStore } from './services/slack/slack-thread-store.service.js';
63
72
  import { GoogleChatThreadStoreService, setGchatThreadStore } from './services/messaging/gchat-thread-store.service.js';
@@ -86,6 +95,7 @@ import { ContextWindowMonitorService } from './services/agent/context-window-mon
86
95
  import { OAuthReloginMonitorService } from './services/agent/oauth-relogin-monitor.service.js';
87
96
  import { getChatV2Service } from './services/chat-v2/chat-v2.singleton.js';
88
97
  import { findPackageRoot } from './utils/package-root.js';
98
+ import { getLocalApiBaseUrl, setLocalApiPort } from './utils/local-api-url.utils.js';
89
99
  import { assertBuildProvenance } from './utils/build-provenance.js';
90
100
  import { isNativeBindingFatalError } from './utils/native-binding.utils.js';
91
101
  import { VersionCheckService } from './services/system/version-check.service.js';
@@ -101,7 +111,7 @@ import { FissionGuardService, createFailOpenBudgetChecker } from './services/fis
101
111
  import { BudgetService } from './services/autonomous/budget.service.js';
102
112
  import { setFissionGuardService } from './controllers/fission/fission.controller.js';
103
113
  import { TaskPoolService } from './services/task-pool/task-pool.service.js';
104
- import { sessionsWithWorkInHand } from './services/agent/restore-filter.js';
114
+ import { sessionsToRestore } from './services/agent/restore-filter.js';
105
115
  import { ProjectMemoryService } from './services/memory/project-memory.service.js';
106
116
  import { TaskHistorySubscriber } from './services/memory/task-history.subscriber.js';
107
117
  import { TeamHealthWatchdogService, LiveTeamHealthDataProvider, loadTeamHealthConfig, setTeamHealthWatchdogSingleton, getTeamHealthWatchdogSingleton, } from './services/team-health/index.js';
@@ -192,6 +202,10 @@ export class CrewlyServer {
192
202
  chatV2Dispatcher = null;
193
203
  // Shutdown state
194
204
  isShuttingDown = false;
205
+ /** Epoch ms of the last shutdown signal acted on (dedups process-group delivery) */
206
+ lastShutdownSignalAt = 0;
207
+ /** Interrupted turns loaded at boot, resumed once their agents are back */
208
+ interruptedTurnsAtBoot = [];
195
209
  healthMonitoringInterval = null;
196
210
  constructor(config) {
197
211
  // Resolve ~ to actual home directory
@@ -206,7 +220,7 @@ export class CrewlyServer {
206
220
  };
207
221
  const defaultAgentmuxHome = config?.crewlyHome || process.env.CREWLY_HOME || '~/.crewly';
208
222
  this.config = {
209
- webPort: config?.webPort || parseIntWithFallback(process.env.WEB_PORT, 8787, 'WEB_PORT'),
223
+ webPort: config?.webPort || parseIntWithFallback(process.env.WEB_PORT, WEB_CONSTANTS.PORTS.BACKEND, 'WEB_PORT'),
210
224
  crewlyHome: resolveHomePath(defaultAgentmuxHome),
211
225
  defaultCheckInterval: config?.defaultCheckInterval ||
212
226
  parseIntWithFallback(process.env.DEFAULT_CHECK_INTERVAL, 30, 'DEFAULT_CHECK_INTERVAL'),
@@ -216,6 +230,9 @@ export class CrewlyServer {
216
230
  process.env[API_SECURITY_CONSTANTS.ENV.BIND_HOST] ||
217
231
  API_SECURITY_CONSTANTS.DEFAULT_BIND_HOST,
218
232
  };
233
+ // Single source of truth for "where is this instance's API": agents get
234
+ // it as CREWLY_API_URL and internal self-calls use it (#777).
235
+ setLocalApiPort(this.config.webPort);
219
236
  this.app = express();
220
237
  this.httpServer = createServer(this.app);
221
238
  this.io = new SocketIOServer(this.httpServer, {
@@ -367,6 +384,53 @@ export class CrewlyServer {
367
384
  // that data. The setter is duck-typed on IWorkItemQueryable so
368
385
  // neither side needs a static import of the other.
369
386
  RequestService.getInstance().setTaskPoolService(TaskPoolService.getInstance());
387
+ // Ticket loop (specs/ticket-loop.md, Phase 1): the single intake for
388
+ // owner messages on every channel, the chat-v2 receipt poster (the
389
+ // Slack one is wired in slack-initializer once Slack is up), and the
390
+ // WorkItem → ticket link through the creating agent's in-flight turn.
391
+ // Failure-isolated: tickets are an addition — messages are delivered
392
+ // whether or not this is wired.
393
+ try {
394
+ const ticketIntake = new TicketIntakeService({
395
+ requests: RequestService.getInstance(),
396
+ findWorkItem: (id) => TaskPoolService.getInstance().findWorkItem(id),
397
+ });
398
+ ticketIntake.setReceiptSink('chat-v2', createChatV2ReceiptSink({
399
+ chat: {
400
+ recordTurn: (input) => getChatV2Service().recordTurn(input),
401
+ updateSystemMessage: (id, content, patch) => getChatV2Service().updateSystemMessage(id, content, patch),
402
+ },
403
+ // Lazy, like the rest of the chat-v2 realtime wiring (the gateway
404
+ // only exists once the HTTP server is up).
405
+ broadcast: (message) => {
406
+ void Promise.all([
407
+ import('./services/chat-v2/chat-v2.realtime-holder.js'),
408
+ import('./websocket/chat-v2.gateway.js'),
409
+ ])
410
+ .then(([{ getChatV2RealtimeDeps }, { buildMessageEvent }]) => {
411
+ getChatV2RealtimeDeps().gateway?.broadcast(message.channelId, buildMessageEvent(message.channelId, message));
412
+ })
413
+ .catch(() => undefined);
414
+ },
415
+ }));
416
+ setTicketIntakeService(ticketIntake);
417
+ TaskPoolService.getInstance().setTicketResolver((sessionName) => resolveTicketIdForSession(InFlightTurnTracker.getInstance(), sessionName));
418
+ }
419
+ catch (ticketBootErr) {
420
+ this.logger.error('Ticket intake boot failed — messages are still delivered, no tickets filed', {
421
+ error: ticketBootErr instanceof Error ? ticketBootErr.message : String(ticketBootErr),
422
+ });
423
+ }
424
+ // Ticket loop §4: one-time archive of old WorkItems (marker file makes
425
+ // it run once). Through the pool's own storage cache, so no later
426
+ // flush can write the archived items back. Never deletes.
427
+ void runPoolArchiveMigration(TaskPoolService.getInstance().getStorage(), {
428
+ logger: LoggerService.getInstance().createComponentLogger('PoolArchive'),
429
+ }).catch((archiveErr) => {
430
+ this.logger.warn('Task pool one-time archive failed (pool left as is; retried next boot)', {
431
+ error: archiveErr instanceof Error ? archiveErr.message : String(archiveErr),
432
+ });
433
+ });
370
434
  // Atlas 2026-05-23 fix: wire the agent-liveness gate so claimFromPool /
371
435
  // claimSpecificItem refuse to put a WI into `running` when the requesting
372
436
  // agent's session is dead. delegate-task's "self-heal fix #1" used to
@@ -856,6 +920,7 @@ export class CrewlyServer {
856
920
  }
857
921
  }
858
922
  });
923
+ this.wireSafeRestart();
859
924
  // Shared LiveReconcilerDataProvider instance used by both the
860
925
  // Reconciler service and the TeamHealthWatchdog data provider.
861
926
  // Sharing is required so the memory-pressure broadcast state
@@ -1058,7 +1123,7 @@ export class CrewlyServer {
1058
1123
  // CORS — allow Cloud Console frontend and localhost OSS instances
1059
1124
  const CORS_ALLOWED_ORIGINS = process.env['CORS_ALLOWED_ORIGINS']
1060
1125
  ? process.env['CORS_ALLOWED_ORIGINS'].split(',')
1061
- : ['https://crewlyai.com', 'https://www.crewlyai.com', 'http://localhost:8787', 'http://localhost:3000'];
1126
+ : ['https://crewlyai.com', 'https://www.crewlyai.com', getLocalApiBaseUrl(), 'http://localhost:3000'];
1062
1127
  this.app.use(cors({
1063
1128
  origin: process.env.NODE_ENV === 'production'
1064
1129
  ? CORS_ALLOWED_ORIGINS
@@ -1330,7 +1395,7 @@ export class CrewlyServer {
1330
1395
  command: sessionInfo.command,
1331
1396
  args: sessionInfo.args,
1332
1397
  env: sessionInfo.env,
1333
- }, sessionInfo.runtimeType, sessionInfo.role, sessionInfo.teamId);
1398
+ }, sessionInfo.runtimeType, sessionInfo.role, sessionInfo.teamId, sessionInfo.memberId);
1334
1399
  if (sessionInfo.claudeSessionId) {
1335
1400
  persistence.updateSessionId(sessionInfo.name, sessionInfo.claudeSessionId);
1336
1401
  }
@@ -1339,6 +1404,7 @@ export class CrewlyServer {
1339
1404
  count: savedState.sessions.length,
1340
1405
  sessionsWithResumeId: savedState.sessions.filter(s => s.claudeSessionId).length,
1341
1406
  });
1407
+ await this.pruneUnboundPersistedSessions(savedState.sessions);
1342
1408
  }
1343
1409
  }
1344
1410
  catch (loadError) {
@@ -1529,24 +1595,20 @@ export class CrewlyServer {
1529
1595
  // The capturer is injected rather than imported by the session
1530
1596
  // service so transport selection (direct WS vs relay) stays in
1531
1597
  // one place — here and in the browser controller.
1532
- const { getBrowserSessions } = await import('./services/browser/browser-session.service.js');
1598
+ const { getBrowserSessions, createBoundTabCapturer } = await import('./services/browser/browser-session.service.js');
1533
1599
  const browserSessions = getBrowserSessions();
1534
- browserSessions.setCapturer(async (agentSession, options) => {
1535
- const { BrowserProxyService } = await import('./services/browser/browser-proxy.service.js');
1536
- const proxy = BrowserProxyService.getInstance();
1537
- let response;
1538
- if (browserBridge.isConnected()) {
1539
- response = await browserBridge.sendCommandForAgent(agentSession, 'screenshot', options);
1540
- }
1541
- else if (proxy.isAvailable()) {
1542
- response = await proxy.sendCommand('screenshot', options, undefined, undefined, undefined, agentSession);
1543
- }
1544
- else {
1600
+ browserSessions.setCapturer(createBoundTabCapturer({
1601
+ getBoundTabId: (agentSession) => browserBridge.getBinding(agentSession)?.tabId,
1602
+ sendScreenshot: async (params) => {
1603
+ const { BrowserProxyService } = await import('./services/browser/browser-proxy.service.js');
1604
+ const proxy = BrowserProxyService.getInstance();
1605
+ if (browserBridge.isConnected())
1606
+ return browserBridge.sendCommand('screenshot', params);
1607
+ if (proxy.isAvailable())
1608
+ return proxy.sendCommand('screenshot', params);
1545
1609
  return null;
1546
- }
1547
- const result = response?.result;
1548
- return result ?? null;
1549
- });
1610
+ },
1611
+ }));
1550
1612
  browserSessions.start();
1551
1613
  // Let the browser controller reach agents, so taking the wheel
1552
1614
  // and answering a held action actually tell the agent what
@@ -2401,10 +2463,16 @@ export class CrewlyServer {
2401
2463
  error: err instanceof Error ? err.message : String(err),
2402
2464
  });
2403
2465
  }
2466
+ // Turns a previous shutdown cut off (see services/restart). Loaded
2467
+ // before restore so their agents count as having work in hand.
2468
+ this.loadInterruptedTurnsAtBoot();
2404
2469
  // Auto-start orchestrator if enabled in settings
2405
2470
  await this.autoStartOrchestratorIfEnabled();
2406
2471
  // Auto-restore agent sessions that were running before the last shutdown
2407
2472
  await this.autoRestoreAgentSessionsIfEnabled();
2473
+ // Re-deliver interrupted turns now that their agents are coming back.
2474
+ // Background: the orchestrator may take minutes to register.
2475
+ void this.resumeInterruptedTurnsAfterBoot();
2408
2476
  // #166: Auto-recover in-progress tasks after restart.
2409
2477
  // #196: Skip tasks older than 1 hour to avoid re-sending stale work.
2410
2478
  // V3-only as of spec 2026-05-06-task-management-v1-deprecation.md —
@@ -2713,6 +2781,9 @@ export class CrewlyServer {
2713
2781
  maxAttempts: MAX_AUTOSTART_ATTEMPTS,
2714
2782
  backoffMs: AUTOSTART_BACKOFF_MS,
2715
2783
  isSuccess: r => r.success,
2784
+ // A start-up blocked on the user (Claude Code as root, or never
2785
+ // set up) cannot succeed on retry: stop and report it once.
2786
+ shouldStop: r => r.errorCode === CLAUDE_STARTUP_CONSTANTS.BLOCKED_ERROR_CODE,
2716
2787
  onRetry: ({ attempt, maxAttempts, retryInMs, result: r }) => {
2717
2788
  this.logger.warn('Auto-start orchestrator failed to create session — retrying', {
2718
2789
  error: r.error,
@@ -2728,8 +2799,11 @@ export class CrewlyServer {
2728
2799
  // a benign skip. The orchestrator stays inactive; recovery now
2729
2800
  // falls to the reconciler's hybrid-wake on the next queued
2730
2801
  // inbound WorkItem (#679 routing fix).
2731
- this.logger.error('Auto-start orchestrator FAILED after all retries — orchestrator is INACTIVE', {
2802
+ this.logger.error(result.errorCode === CLAUDE_STARTUP_CONSTANTS.BLOCKED_ERROR_CODE
2803
+ ? 'Auto-start orchestrator BLOCKED — needs user action; orchestrator is INACTIVE'
2804
+ : 'Auto-start orchestrator FAILED after all retries — orchestrator is INACTIVE', {
2732
2805
  error: result.error,
2806
+ errorCode: result.errorCode,
2733
2807
  attempts: MAX_AUTOSTART_ATTEMPTS,
2734
2808
  });
2735
2809
  return;
@@ -2812,6 +2886,43 @@ export class CrewlyServer {
2812
2886
  // Don't fail startup if auto-start fails
2813
2887
  }
2814
2888
  }
2889
+ /**
2890
+ * Drop persisted team sessions whose name no team member is bound to.
2891
+ *
2892
+ * session-state.json caches what was running; the team config is the
2893
+ * source of truth for each member's session name. An entry left under a
2894
+ * member's old name (it was renamed) would otherwise stay in the Resume
2895
+ * dialog and could be relaunched, running the member twice. Each unbound
2896
+ * entry is unregistered (rewriting the state file without it) and its
2897
+ * generated Claude Code agent file is removed. Failure to read the teams,
2898
+ * or an empty team list, prunes nothing.
2899
+ *
2900
+ * @param sessions - Entries loaded from session-state.json.
2901
+ */
2902
+ async pruneUnboundPersistedSessions(sessions) {
2903
+ try {
2904
+ const teams = await this.storageService.getTeams();
2905
+ // No teams at all is indistinguishable from a failed read: prune
2906
+ // nothing rather than drop every member's resume entry.
2907
+ if (teams.length === 0)
2908
+ return;
2909
+ const { unbound, rebound } = resolvePersistedSessions(sessions, teams);
2910
+ if (unbound.length === 0)
2911
+ return;
2912
+ const persistence = getSessionStatePersistence();
2913
+ const byName = new Map(sessions.map((s) => [s.name, s]));
2914
+ for (const name of unbound) {
2915
+ persistence.unregisterSession(name);
2916
+ await removeCrewlyAgentFile(byName.get(name)?.cwd, name);
2917
+ }
2918
+ this.logger.warn('Pruned persisted sessions whose name no team member is bound to', { unbound, rebound });
2919
+ }
2920
+ catch (error) {
2921
+ this.logger.warn('Could not check persisted sessions against team bindings (nothing pruned)', {
2922
+ error: error instanceof Error ? error.message : String(error),
2923
+ });
2924
+ }
2925
+ }
2815
2926
  /**
2816
2927
  * Auto-restore agent sessions that were running before the last shutdown.
2817
2928
  * Loads persisted session state and calls createAgentSession() for each
@@ -2843,41 +2954,50 @@ export class CrewlyServer {
2843
2954
  return false;
2844
2955
  return true;
2845
2956
  });
2846
- // 2026-05-17 — gate by task-pool work. Pre-fix the boot path
2847
- // blindly resurrected every persisted session even when none had
2848
- // pending work, defeating the wake-gate philosophy (PR #574/#585)
2849
- // and bloating RAM until IdleDetection eventually drained them
2850
- // back. Now: only restore a session if the pool has at least one
2851
- // non-terminal WorkItem with `target === sessionName`. Idle
2852
- // agents stay dead until orc dispatches new work, at which point
2853
- // the dispatcher / wake path raises them on demand.
2957
+ // Relaunch team members only under the session name the team config
2958
+ // binds them to: a persisted entry under a stale name (the member was
2959
+ // renamed) is rebound through its memberId or dropped, never launched
2960
+ // under the stale name. Then gate by task-pool work.
2854
2961
  //
2855
- // Safety valve: if the pool lookup throws (e.g. SQLite not yet
2856
- // open during early boot), preserve the legacy behaviour rather
2857
- // than block all restores — better to over-restore than to
2858
- // silently strand work.
2859
- let agentSessions = baselineSessions;
2962
+ // Work gate: only restore a session with work in hand (see
2963
+ // restore-filter) or whose turn the last restart cut off. Idle agents
2964
+ // stay down until work or a message wakes them (PR #574/#585).
2965
+ // Safety valve: if the pool lookup throws (e.g. SQLite not yet open
2966
+ // during early boot), skip the gate rather than strand work.
2967
+ let teams = null;
2860
2968
  try {
2861
- const pool = TaskPoolService.getInstance();
2862
- const allItems = await pool.getAllItems();
2863
- // Work in hand only: active statuses, touched recently (see restore-filter).
2864
- const targetedSessions = sessionsWithWorkInHand(allItems);
2865
- const filtered = baselineSessions.filter((s) => targetedSessions.has(s.name));
2866
- const skipped = baselineSessions
2867
- .filter((s) => !targetedSessions.has(s.name))
2868
- .map((s) => s.name);
2869
- if (skipped.length > 0) {
2870
- this.logger.info('Skipping auto-restore for sessions with no work in hand (idle agents stay down until work or a message wakes them)', {
2871
- skippedCount: skipped.length,
2872
- skipped: skipped.slice(0, 20),
2873
- truncated: skipped.length > 20,
2874
- });
2875
- }
2876
- agentSessions = filtered;
2969
+ teams = await this.storageService.getTeams();
2970
+ }
2971
+ catch (bindErr) {
2972
+ this.logger.warn('Auto-restore could not read team bindings; restoring only non-team sessions', {
2973
+ error: bindErr instanceof Error ? bindErr.message : String(bindErr),
2974
+ });
2975
+ }
2976
+ let targets = null;
2977
+ try {
2978
+ const allItems = await TaskPoolService.getInstance().getAllItems();
2979
+ // Work in hand only: active statuses, touched recently (see restore-filter),
2980
+ // plus agents whose turn the last restart cut off.
2981
+ targets = sessionsToRestore(allItems, this.interruptedTurnsAtBoot.map((t) => t.sessionName));
2877
2982
  }
2878
2983
  catch (poolErr) {
2879
2984
  this.logger.warn('Auto-restore could not query task pool; falling back to restoring every persisted session', { error: poolErr instanceof Error ? poolErr.message : String(poolErr) });
2880
2985
  }
2986
+ const selection = selectAutoRestoreSessions({ sessions: baselineSessions, teams, targets });
2987
+ if (selection.unbound.length > 0) {
2988
+ this.logger.warn('Not auto-restoring sessions whose name no team member is bound to', {
2989
+ unbound: selection.unbound,
2990
+ rebound: selection.rebound,
2991
+ });
2992
+ }
2993
+ if (selection.skippedNoWork.length > 0) {
2994
+ this.logger.info('Skipping auto-restore for sessions with no work in hand (idle agents stay down until work or a message wakes them)', {
2995
+ skippedCount: selection.skippedNoWork.length,
2996
+ skipped: selection.skippedNoWork.slice(0, 20),
2997
+ truncated: selection.skippedNoWork.length > 20,
2998
+ });
2999
+ }
3000
+ const agentSessions = selection.sessions;
2881
3001
  if (agentSessions.length === 0) {
2882
3002
  this.logger.info('No persisted agent sessions to restore (all idle, no pending WorkItems)');
2883
3003
  return;
@@ -3132,25 +3252,14 @@ export class CrewlyServer {
3132
3252
  sigintCount = 0;
3133
3253
  registerSignalHandlers() {
3134
3254
  this.logger.info('Registering signal handlers...');
3135
- process.on('SIGTERM', () => {
3136
- this.logger.info('Received SIGTERM signal');
3137
- this.shutdown();
3138
- });
3139
- process.on('SIGINT', () => {
3140
- this.sigintCount++;
3141
- if (this.sigintCount === 1) {
3142
- this.logger.info('Received SIGINT signal (Ctrl+C) - shutting down gracefully. Press Ctrl+C again to force exit.');
3143
- this.shutdown();
3144
- }
3145
- else {
3146
- this.logger.info('Received second SIGINT - forcing immediate exit');
3147
- process.exit(1);
3148
- }
3149
- });
3255
+ process.on('SIGTERM', () => this.handleShutdownSignal('SIGTERM'));
3256
+ process.on('SIGINT', () => this.handleShutdownSignal('SIGINT'));
3150
3257
  process.on('uncaughtException', (error) => {
3151
3258
  this.logger.error('Uncaught exception', { error: error.message, stack: error.stack });
3152
3259
  this.logMemoryUsage();
3153
- this.shutdown();
3260
+ // A crashing process should not linger for the drain; its in-flight
3261
+ // turns are still persisted and resumed after the restart.
3262
+ this.shutdown({ reason: 'uncaughtException', drain: false });
3154
3263
  });
3155
3264
  process.on('unhandledRejection', (reason, promise) => {
3156
3265
  const message = unhandledRejectionMessage(reason);
@@ -3170,9 +3279,168 @@ export class CrewlyServer {
3170
3279
  stack: reason instanceof Error ? reason.stack : undefined
3171
3280
  });
3172
3281
  this.logMemoryUsage();
3173
- this.shutdown();
3282
+ this.shutdown({ reason: 'unhandledRejection', drain: false });
3174
3283
  });
3175
3284
  }
3285
+ /**
3286
+ * Handle SIGTERM / SIGINT with safe-restart semantics.
3287
+ *
3288
+ * - First signal: graceful shutdown, which first drains in-flight agent turns.
3289
+ * - A repeat within SIGNAL_DEDUP_WINDOW_MS is the same request arriving twice
3290
+ * (Ctrl+C reaches the whole process group, and the CLI parent forwards it
3291
+ * too) and is ignored.
3292
+ * - A later repeat during the drain skips the wait; interrupted turns are
3293
+ * persisted and resumed after the restart.
3294
+ * - A later SIGINT after the drain forces an immediate exit, as before.
3295
+ *
3296
+ * @param signal - The signal received
3297
+ */
3298
+ handleShutdownSignal(signal) {
3299
+ const now = Date.now();
3300
+ if (!this.isShuttingDown) {
3301
+ this.lastShutdownSignalAt = now;
3302
+ this.logger.info(`Received ${signal} — shutting down; in-flight agent turns are drained first. Send ${signal} again to stop waiting.`);
3303
+ void this.shutdown({ reason: signal });
3304
+ return;
3305
+ }
3306
+ if (now - this.lastShutdownSignalAt < SAFE_RESTART.SIGNAL_DEDUP_WINDOW_MS) {
3307
+ this.logger.debug(`Duplicate ${signal} ignored (same shutdown request)`);
3308
+ return;
3309
+ }
3310
+ this.lastShutdownSignalAt = now;
3311
+ if (RestartDrainService.getInstance().requestSkip(`second ${signal}`)) {
3312
+ return;
3313
+ }
3314
+ if (signal === 'SIGINT') {
3315
+ this.sigintCount++;
3316
+ this.logger.info('Received another SIGINT after the drain - forcing immediate exit');
3317
+ process.exit(1);
3318
+ }
3319
+ this.logger.info(`Received ${signal} while shutdown is already past the drain; continuing`);
3320
+ }
3321
+ /**
3322
+ * Wire the safe-restart pieces: the turn probe, idle-event re-probing,
3323
+ * readiness queue counting, and the graceful-shutdown hook used by
3324
+ * POST /api/system/restart.
3325
+ */
3326
+ wireSafeRestart() {
3327
+ const tracker = InFlightTurnTracker.getInstance();
3328
+ const activity = PtyActivityTrackerService.getInstance();
3329
+ tracker.setProbe(createPtyTurnProbe({
3330
+ getBackend: () => getSessionBackendSync(),
3331
+ getIdleTimeMs: (sessionName) => (activity.hasActivity(sessionName) ? activity.getIdleTimeMs(sessionName) : null),
3332
+ }));
3333
+ tracker.attachEventSource(this.eventBusService);
3334
+ const drain = RestartDrainService.getInstance();
3335
+ drain.setQueueCounter(() => this.messageQueueService.pendingCount + SubAgentMessageQueue.getInstance().getTotalQueued());
3336
+ drain.setShutdownHandler((request) => this.shutdown({ reason: request.reason, exitCode: request.exitCode }));
3337
+ }
3338
+ /**
3339
+ * Load interrupted turns left by the previous shutdown (fresh ones only).
3340
+ */
3341
+ loadInterruptedTurnsAtBoot() {
3342
+ try {
3343
+ const file = interruptedTurnsPath(this.config.crewlyHome);
3344
+ const { fresh, dropped } = loadInterruptedTurns(file);
3345
+ this.interruptedTurnsAtBoot = fresh;
3346
+ if (dropped > 0) {
3347
+ this.logger.info('Dropped stale interrupted turns from the previous run', { dropped });
3348
+ }
3349
+ if (fresh.length > 0) {
3350
+ this.logger.info('Found turns interrupted by the last restart; their agents will be restored and resumed', {
3351
+ count: fresh.length,
3352
+ sessions: [...new Set(fresh.map((t) => t.sessionName))],
3353
+ });
3354
+ }
3355
+ else if (dropped > 0) {
3356
+ writeInterruptedTurns(file, []);
3357
+ }
3358
+ }
3359
+ catch (error) {
3360
+ this.logger.warn('Could not read interrupted turns (non-fatal)', {
3361
+ error: error instanceof Error ? error.message : String(error),
3362
+ });
3363
+ }
3364
+ }
3365
+ /**
3366
+ * Re-deliver the turns the previous shutdown cut off, then clear the file.
3367
+ * The file is rewritten after each entry so a restart during this pass
3368
+ * neither loses nor repeats work.
3369
+ */
3370
+ async resumeInterruptedTurnsAfterBoot() {
3371
+ const entries = this.interruptedTurnsAtBoot;
3372
+ if (entries.length === 0)
3373
+ return;
3374
+ this.interruptedTurnsAtBoot = [];
3375
+ const file = interruptedTurnsPath(this.config.crewlyHome);
3376
+ const registration = this.apiController.agentRegistrationService;
3377
+ try {
3378
+ const summary = await resumeInterruptedTurns(entries, {
3379
+ orchestratorSession: ORCHESTRATOR_SESSION_NAME,
3380
+ isSessionRunning: (name) => Boolean(getSessionBackendSync()?.sessionExists(name)) || Boolean(registration.getInProcessRuntime(name)),
3381
+ enqueue: (input) => {
3382
+ this.messageQueueService.enqueue(input);
3383
+ },
3384
+ sendMessageToAgent: (name, text) => registration.sendMessageToAgent(name, text),
3385
+ waitForOrchestratorActive: async () => {
3386
+ const deadline = Date.now() + SAFE_RESTART.RESUME_ORC_READY_TIMEOUT_MS;
3387
+ while (Date.now() < deadline) {
3388
+ if (this.isShuttingDown)
3389
+ return false;
3390
+ const status = await this.storageService.getOrchestratorStatus().catch(() => null);
3391
+ if (status?.agentStatus === CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE)
3392
+ return true;
3393
+ await new Promise((resolve) => setTimeout(resolve, SAFE_RESTART.RESUME_ORC_POLL_MS));
3394
+ }
3395
+ return false;
3396
+ },
3397
+ onEntryHandled: (_entry, remaining) => {
3398
+ try {
3399
+ writeInterruptedTurns(file, remaining);
3400
+ }
3401
+ catch {
3402
+ // Best-effort bookkeeping; the in-memory pass continues.
3403
+ }
3404
+ },
3405
+ logger: this.logger,
3406
+ });
3407
+ this.logger.info('Interrupted-turn resume complete', { ...summary });
3408
+ }
3409
+ catch (error) {
3410
+ this.logger.warn('Interrupted-turn resume failed (non-fatal)', {
3411
+ error: error instanceof Error ? error.message : String(error),
3412
+ });
3413
+ }
3414
+ }
3415
+ /**
3416
+ * Drain in-flight agent turns before the rest of shutdown, and persist
3417
+ * whatever is still mid-turn when the drain ends.
3418
+ *
3419
+ * @param reason - Why we are shutting down (signal or caller)
3420
+ * @param drainEnabled - False to skip the wait (crash paths)
3421
+ */
3422
+ async drainInFlightTurns(reason, drainEnabled) {
3423
+ try {
3424
+ const drain = RestartDrainService.getInstance();
3425
+ drain.pauseDelivery(reason);
3426
+ const timeoutMs = drainEnabled ? resolveRestartDrainMs(process.env) : 0;
3427
+ const result = await drain.drain({ timeoutMs });
3428
+ if (result.remaining.length > 0) {
3429
+ const saved = saveInterruptedTurns(interruptedTurnsPath(this.config.crewlyHome), result.remaining, `${reason}: ${result.outcome}`);
3430
+ this.logger.warn('Persisted interrupted agent turns for resume after restart', {
3431
+ outcome: result.outcome,
3432
+ sessions: result.remaining.map((t) => t.sessionName),
3433
+ entries: saved,
3434
+ });
3435
+ }
3436
+ }
3437
+ catch (error) {
3438
+ // Never let the drain block shutdown.
3439
+ this.logger.error('Restart drain failed; continuing shutdown', {
3440
+ error: error instanceof Error ? error.message : String(error),
3441
+ });
3442
+ }
3443
+ }
3176
3444
  startHealthMonitoring() {
3177
3445
  this.logger.info('Starting health monitoring...');
3178
3446
  // Monitor memory usage every 30 seconds
@@ -3418,14 +3686,27 @@ export class CrewlyServer {
3418
3686
  this.logger.warn('High memory usage detected', { heapUsedMB: heapUsed });
3419
3687
  }
3420
3688
  }
3421
- async shutdown() {
3689
+ /**
3690
+ * Gracefully shut the server down.
3691
+ *
3692
+ * Drains in-flight agent turns first (see services/restart), while the
3693
+ * HTTP API is still up so agents can finish and reply; everything after
3694
+ * that runs under the hard force-exit timer.
3695
+ *
3696
+ * @param options - reason (for logs), drain=false to skip the wait, exitCode for process.exit
3697
+ */
3698
+ async shutdown(options = {}) {
3422
3699
  // Prevent double shutdown
3423
3700
  if (this.isShuttingDown) {
3424
3701
  this.logger.info('Shutdown already in progress, skipping...');
3425
3702
  return;
3426
3703
  }
3427
3704
  this.isShuttingDown = true;
3428
- this.logger.info('Shutting down Crewly server...');
3705
+ const exitCode = options.exitCode ?? PROCESS_EXIT_CODES.SUCCESS;
3706
+ this.logger.info('Shutting down Crewly server...', { reason: options.reason ?? 'unspecified' });
3707
+ // Safe restart: stop delivering, wait for agents mid-turn, persist the rest.
3708
+ // Runs before the force-exit timer below, which only bounds the teardown.
3709
+ await this.drainInFlightTurns(options.reason ?? 'shutdown', options.drain !== false);
3429
3710
  // Set a hard timeout to force exit if graceful shutdown takes too long.
3430
3711
  // Use SIGKILL on self as the ultimate fallback — this is uncatchable and
3431
3712
  // guarantees death even if native node-pty handles keep the event loop alive.
@@ -3719,7 +4000,7 @@ export class CrewlyServer {
3719
4000
  setTimeout(resolve, 3000);
3720
4001
  });
3721
4002
  clearTimeout(forceExitTimeout);
3722
- process.exit(0);
4003
+ process.exit(exitCode);
3723
4004
  }
3724
4005
  catch (error) {
3725
4006
  this.logger.error('Error during shutdown', { error: error instanceof Error ? error.message : String(error) });