crewly 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1208) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/config/auto-assign/default-config.yaml +74 -0
  4. package/config/constants.d.ts.map +1 -0
  5. package/config/constants.test.ts +469 -0
  6. package/config/constants.ts +827 -0
  7. package/config/continuation/prompts/continue-work.md +60 -0
  8. package/config/continuation/prompts/max-iterations.md +41 -0
  9. package/config/continuation/prompts/quality-gates-failed.md +37 -0
  10. package/config/continuation/prompts/retry-error.md +59 -0
  11. package/config/continuation/prompts/task-assignment.md +60 -0
  12. package/config/index.d.ts.map +1 -0
  13. package/config/index.ts +87 -0
  14. package/config/orchestrator_tasks/prompts/assign-task-orchestrator-prompt-template.md +70 -0
  15. package/config/orchestrator_tasks/prompts/checkin-orchestrator-prompt-template.md +138 -0
  16. package/config/orchestrator_tasks/prompts/orchestrator-prompt.md +68 -0
  17. package/config/orchestrator_tasks/prompts/project-start-orchestrator-prompt-template.md +104 -0
  18. package/config/quality-gates/default-gates.test.ts +246 -0
  19. package/config/quality-gates/default-gates.ts +191 -0
  20. package/config/quality-gates/index.ts +21 -0
  21. package/config/roles/_common/memory-instructions.md +56 -0
  22. package/config/roles/architect/prompt.md +87 -0
  23. package/config/roles/architect/role.json +13 -0
  24. package/config/roles/backend-developer/prompt.md +86 -0
  25. package/config/roles/backend-developer/role.json +13 -0
  26. package/config/roles/designer/prompt.md +86 -0
  27. package/config/roles/designer/role.json +13 -0
  28. package/config/roles/developer/prompt.md +94 -0
  29. package/config/roles/developer/role.json +13 -0
  30. package/config/roles/frontend-developer/prompt.md +86 -0
  31. package/config/roles/frontend-developer/role.json +13 -0
  32. package/config/roles/fullstack-dev/prompt.md +86 -0
  33. package/config/roles/fullstack-dev/role.json +13 -0
  34. package/config/roles/generalist/prompt.md +87 -0
  35. package/config/roles/generalist/role.json +13 -0
  36. package/config/roles/orchestrator/prompt.md +865 -0
  37. package/config/roles/orchestrator/role.json +13 -0
  38. package/config/roles/product-manager/prompt.md +86 -0
  39. package/config/roles/product-manager/role.json +13 -0
  40. package/config/roles/qa/prompt.md +86 -0
  41. package/config/roles/qa/role.json +13 -0
  42. package/config/roles/qa-engineer/prompt.md +86 -0
  43. package/config/roles/qa-engineer/role.json +13 -0
  44. package/config/roles/sales/prompt.md +86 -0
  45. package/config/roles/sales/role.json +13 -0
  46. package/config/roles/support/prompt.md +86 -0
  47. package/config/roles/support/role.json +13 -0
  48. package/config/roles/tpm/prompt.md +87 -0
  49. package/config/roles/tpm/role.json +13 -0
  50. package/config/runtime_scripts/initialize_claude.sh +14 -0
  51. package/config/runtime_scripts/initialize_codex.sh +14 -0
  52. package/config/runtime_scripts/runtime-config.json +26 -0
  53. package/config/skills/_common/lib.sh +64 -0
  54. package/config/skills/agent/_common/lib.sh +4 -0
  55. package/config/skills/agent/accept-task/execute.sh +21 -0
  56. package/config/skills/agent/accept-task/instructions.md +20 -0
  57. package/config/skills/agent/accept-task/skill.json +20 -0
  58. package/config/skills/agent/block-task/execute.sh +26 -0
  59. package/config/skills/agent/block-task/instructions.md +22 -0
  60. package/config/skills/agent/block-task/skill.json +20 -0
  61. package/config/skills/agent/check-quality-gates/execute.sh +20 -0
  62. package/config/skills/agent/check-quality-gates/instructions.md +23 -0
  63. package/config/skills/agent/check-quality-gates/skill.json +20 -0
  64. package/config/skills/agent/complete-task/execute.sh +26 -0
  65. package/config/skills/agent/complete-task/instructions.md +22 -0
  66. package/config/skills/agent/complete-task/skill.json +20 -0
  67. package/config/skills/agent/get-my-context/execute.sh +23 -0
  68. package/config/skills/agent/get-my-context/instructions.md +21 -0
  69. package/config/skills/agent/get-my-context/skill.json +20 -0
  70. package/config/skills/agent/get-sops/execute.sh +24 -0
  71. package/config/skills/agent/get-sops/instructions.md +21 -0
  72. package/config/skills/agent/get-sops/skill.json +20 -0
  73. package/config/skills/agent/get-team-status/execute.sh +8 -0
  74. package/config/skills/agent/get-team-status/instructions.md +17 -0
  75. package/config/skills/agent/get-team-status/skill.json +20 -0
  76. package/config/skills/agent/manage-knowledge/execute.sh +60 -0
  77. package/config/skills/agent/manage-knowledge/instructions.md +46 -0
  78. package/config/skills/agent/nano-banana-image/.env +2 -0
  79. package/config/skills/agent/nano-banana-image/.env.example +6 -0
  80. package/config/skills/agent/nano-banana-image/generate.sh +73 -0
  81. package/config/skills/agent/nano-banana-image/instructions.md +50 -0
  82. package/config/skills/agent/nano-banana-image/skill.json +39 -0
  83. package/config/skills/agent/query-knowledge/execute.sh +30 -0
  84. package/config/skills/agent/query-knowledge/instructions.md +47 -0
  85. package/config/skills/agent/query-knowledge/skill.json +20 -0
  86. package/config/skills/agent/read-task/execute.sh +15 -0
  87. package/config/skills/agent/read-task/instructions.md +19 -0
  88. package/config/skills/agent/read-task/skill.json +20 -0
  89. package/config/skills/agent/recall/execute.sh +24 -0
  90. package/config/skills/agent/recall/instructions.md +23 -0
  91. package/config/skills/agent/recall/skill.json +20 -0
  92. package/config/skills/agent/record-learning/execute.sh +29 -0
  93. package/config/skills/agent/record-learning/instructions.md +24 -0
  94. package/config/skills/agent/record-learning/skill.json +20 -0
  95. package/config/skills/agent/register-self/execute.sh +28 -0
  96. package/config/skills/agent/register-self/instructions.md +18 -0
  97. package/config/skills/agent/register-self/skill.json +20 -0
  98. package/config/skills/agent/remember/execute.sh +29 -0
  99. package/config/skills/agent/remember/instructions.md +24 -0
  100. package/config/skills/agent/remember/skill.json +20 -0
  101. package/config/skills/agent/report-progress/execute.sh +28 -0
  102. package/config/skills/agent/report-progress/instructions.md +25 -0
  103. package/config/skills/agent/report-progress/skill.json +20 -0
  104. package/config/skills/agent/report-status/execute.sh +35 -0
  105. package/config/skills/agent/report-status/instructions.md +36 -0
  106. package/config/skills/agent/report-status/skill.json +20 -0
  107. package/config/skills/agent/send-chat-response/execute.sh +26 -0
  108. package/config/skills/agent/send-chat-response/instructions.md +22 -0
  109. package/config/skills/agent/send-chat-response/skill.json +20 -0
  110. package/config/skills/agent/send-message/execute.sh +17 -0
  111. package/config/skills/agent/send-message/instructions.md +20 -0
  112. package/config/skills/agent/send-message/skill.json +20 -0
  113. package/config/skills/agent/send-pdf-to-slack/execute.sh +182 -0
  114. package/config/skills/agent/send-pdf-to-slack/instructions.md +49 -0
  115. package/config/skills/agent/send-pdf-to-slack/skill.json +20 -0
  116. package/config/skills/chrome-browser/instructions.md +42 -0
  117. package/config/skills/chrome-browser/skill.json +39 -0
  118. package/config/skills/nano-banana-image/.env +2 -0
  119. package/config/skills/nano-banana-image/.env.example +6 -0
  120. package/config/skills/nano-banana-image/generate.sh +73 -0
  121. package/config/skills/nano-banana-image/instructions.md +50 -0
  122. package/config/skills/nano-banana-image/skill.json +39 -0
  123. package/config/skills/orchestrator/_common/lib.sh +4 -0
  124. package/config/skills/orchestrator/assign-task/execute.sh +11 -0
  125. package/config/skills/orchestrator/assign-task/instructions.md +17 -0
  126. package/config/skills/orchestrator/assign-task/skill.json +20 -0
  127. package/config/skills/orchestrator/assign-team-to-project/execute.sh +14 -0
  128. package/config/skills/orchestrator/assign-team-to-project/instructions.md +20 -0
  129. package/config/skills/orchestrator/assign-team-to-project/skill.json +20 -0
  130. package/config/skills/orchestrator/broadcast/execute.sh +35 -0
  131. package/config/skills/orchestrator/broadcast/instructions.md +19 -0
  132. package/config/skills/orchestrator/broadcast/skill.json +20 -0
  133. package/config/skills/orchestrator/cancel-schedule/execute.sh +13 -0
  134. package/config/skills/orchestrator/cancel-schedule/instructions.md +19 -0
  135. package/config/skills/orchestrator/cancel-schedule/skill.json +20 -0
  136. package/config/skills/orchestrator/complete-task/execute.sh +10 -0
  137. package/config/skills/orchestrator/complete-task/instructions.md +17 -0
  138. package/config/skills/orchestrator/complete-task/skill.json +20 -0
  139. package/config/skills/orchestrator/create-project/execute.sh +14 -0
  140. package/config/skills/orchestrator/create-project/instructions.md +21 -0
  141. package/config/skills/orchestrator/create-project/skill.json +20 -0
  142. package/config/skills/orchestrator/create-team/execute.sh +14 -0
  143. package/config/skills/orchestrator/create-team/instructions.md +21 -0
  144. package/config/skills/orchestrator/create-team/skill.json +20 -0
  145. package/config/skills/orchestrator/delegate-task/execute.sh +37 -0
  146. package/config/skills/orchestrator/delegate-task/instructions.md +23 -0
  147. package/config/skills/orchestrator/delegate-task/skill.json +20 -0
  148. package/config/skills/orchestrator/get-agent-logs/execute.sh +14 -0
  149. package/config/skills/orchestrator/get-agent-logs/instructions.md +20 -0
  150. package/config/skills/orchestrator/get-agent-logs/skill.json +20 -0
  151. package/config/skills/orchestrator/get-agent-status/execute.sh +22 -0
  152. package/config/skills/orchestrator/get-agent-status/instructions.md +19 -0
  153. package/config/skills/orchestrator/get-agent-status/skill.json +20 -0
  154. package/config/skills/orchestrator/get-project-overview/execute.sh +7 -0
  155. package/config/skills/orchestrator/get-project-overview/instructions.md +17 -0
  156. package/config/skills/orchestrator/get-project-overview/skill.json +20 -0
  157. package/config/skills/orchestrator/get-tasks/execute.sh +27 -0
  158. package/config/skills/orchestrator/get-tasks/instructions.md +17 -0
  159. package/config/skills/orchestrator/get-tasks/skill.json +20 -0
  160. package/config/skills/orchestrator/get-team-status/execute.sh +7 -0
  161. package/config/skills/orchestrator/get-team-status/instructions.md +17 -0
  162. package/config/skills/orchestrator/get-team-status/skill.json +20 -0
  163. package/config/skills/orchestrator/heartbeat/execute.sh +37 -0
  164. package/config/skills/orchestrator/heartbeat/instructions.md +24 -0
  165. package/config/skills/orchestrator/heartbeat/skill.json +20 -0
  166. package/config/skills/orchestrator/list-subscriptions/execute.sh +7 -0
  167. package/config/skills/orchestrator/list-subscriptions/instructions.md +17 -0
  168. package/config/skills/orchestrator/list-subscriptions/skill.json +20 -0
  169. package/config/skills/orchestrator/query-knowledge/execute.sh +30 -0
  170. package/config/skills/orchestrator/query-knowledge/instructions.md +47 -0
  171. package/config/skills/orchestrator/query-knowledge/skill.json +20 -0
  172. package/config/skills/orchestrator/recall/execute.sh +13 -0
  173. package/config/skills/orchestrator/recall/instructions.md +23 -0
  174. package/config/skills/orchestrator/recall/skill.json +20 -0
  175. package/config/skills/orchestrator/record-failure/execute.sh +13 -0
  176. package/config/skills/orchestrator/record-failure/instructions.md +22 -0
  177. package/config/skills/orchestrator/record-failure/skill.json +20 -0
  178. package/config/skills/orchestrator/record-learning/execute.sh +13 -0
  179. package/config/skills/orchestrator/record-learning/instructions.md +23 -0
  180. package/config/skills/orchestrator/record-learning/skill.json +20 -0
  181. package/config/skills/orchestrator/record-success/execute.sh +13 -0
  182. package/config/skills/orchestrator/record-success/instructions.md +22 -0
  183. package/config/skills/orchestrator/record-success/skill.json +20 -0
  184. package/config/skills/orchestrator/register-self/execute.sh +24 -0
  185. package/config/skills/orchestrator/register-self/instructions.md +21 -0
  186. package/config/skills/orchestrator/register-self/skill.json +20 -0
  187. package/config/skills/orchestrator/remember/execute.sh +15 -0
  188. package/config/skills/orchestrator/remember/instructions.md +24 -0
  189. package/config/skills/orchestrator/remember/skill.json +20 -0
  190. package/config/skills/orchestrator/reply-slack/execute.sh +174 -0
  191. package/config/skills/orchestrator/reply-slack/instructions.md +52 -0
  192. package/config/skills/orchestrator/reply-slack/skill.json +20 -0
  193. package/config/skills/orchestrator/restart-crewly/execute.sh +7 -0
  194. package/config/skills/orchestrator/restart-crewly/instructions.md +23 -0
  195. package/config/skills/orchestrator/restart-crewly/skill.json +20 -0
  196. package/config/skills/orchestrator/resume-session/execute.sh +22 -0
  197. package/config/skills/orchestrator/resume-session/instructions.md +31 -0
  198. package/config/skills/orchestrator/resume-session/skill.json +20 -0
  199. package/config/skills/orchestrator/schedule-check/execute.sh +35 -0
  200. package/config/skills/orchestrator/schedule-check/instructions.md +35 -0
  201. package/config/skills/orchestrator/schedule-check/skill.json +20 -0
  202. package/config/skills/orchestrator/send-key/execute.sh +17 -0
  203. package/config/skills/orchestrator/send-message/execute.sh +17 -0
  204. package/config/skills/orchestrator/send-message/instructions.md +20 -0
  205. package/config/skills/orchestrator/send-message/skill.json +20 -0
  206. package/config/skills/orchestrator/send-pdf-to-slack/execute.sh +182 -0
  207. package/config/skills/orchestrator/send-pdf-to-slack/instructions.md +49 -0
  208. package/config/skills/orchestrator/send-pdf-to-slack/skill.json +20 -0
  209. package/config/skills/orchestrator/set-goal/execute.sh +13 -0
  210. package/config/skills/orchestrator/set-goal/instructions.md +21 -0
  211. package/config/skills/orchestrator/set-goal/skill.json +20 -0
  212. package/config/skills/orchestrator/start-agent/execute.sh +15 -0
  213. package/config/skills/orchestrator/start-agent/instructions.md +20 -0
  214. package/config/skills/orchestrator/start-agent/skill.json +20 -0
  215. package/config/skills/orchestrator/start-team/execute.sh +14 -0
  216. package/config/skills/orchestrator/start-team/instructions.md +20 -0
  217. package/config/skills/orchestrator/start-team/skill.json +20 -0
  218. package/config/skills/orchestrator/stop-agent/execute.sh +15 -0
  219. package/config/skills/orchestrator/stop-agent/instructions.md +20 -0
  220. package/config/skills/orchestrator/stop-agent/skill.json +20 -0
  221. package/config/skills/orchestrator/stop-team/execute.sh +13 -0
  222. package/config/skills/orchestrator/stop-team/instructions.md +19 -0
  223. package/config/skills/orchestrator/stop-team/skill.json +20 -0
  224. package/config/skills/orchestrator/subscribe-event/execute.sh +19 -0
  225. package/config/skills/orchestrator/subscribe-event/instructions.md +21 -0
  226. package/config/skills/orchestrator/subscribe-event/skill.json +20 -0
  227. package/config/skills/orchestrator/terminate-agent/execute.sh +13 -0
  228. package/config/skills/orchestrator/terminate-agent/instructions.md +19 -0
  229. package/config/skills/orchestrator/terminate-agent/skill.json +20 -0
  230. package/config/skills/orchestrator/unsubscribe-event/execute.sh +13 -0
  231. package/config/skills/orchestrator/unsubscribe-event/instructions.md +19 -0
  232. package/config/skills/orchestrator/unsubscribe-event/skill.json +20 -0
  233. package/config/skills/orchestrator/update-focus/execute.sh +13 -0
  234. package/config/skills/orchestrator/update-focus/instructions.md +21 -0
  235. package/config/skills/orchestrator/update-focus/skill.json +20 -0
  236. package/config/skills/playwright-chrome-browser/instructions.md +95 -0
  237. package/config/skills/playwright-chrome-browser/skill.json +44 -0
  238. package/config/sops/common/blocker-handling.md +55 -0
  239. package/config/sops/common/communication-protocol.md +52 -0
  240. package/config/sops/developer/coding-standards.md +54 -0
  241. package/config/sops/developer/git-workflow.md +58 -0
  242. package/config/sops/developer/testing-requirements.md +62 -0
  243. package/config/sops/pm/progress-tracking.md +57 -0
  244. package/config/sops/pm/task-decomposition.md +59 -0
  245. package/config/sops/qa/testing-procedures.md +60 -0
  246. package/config/task_assignment/prompts/target-agent-assignment-prompt.md +119 -0
  247. package/config/task_starters/build_e2e_test_plan_prompt.json +51 -0
  248. package/config/task_starters/build_spec_prompt.json +79 -0
  249. package/config/task_starters/build_tasks_prompt.json +55 -0
  250. package/config/task_starters/prompts/build_spec_step1_project_requirements.md +120 -0
  251. package/config/task_starters/prompts/build_spec_step2_technical_design.md +147 -0
  252. package/config/task_starters/prompts/build_spec_step3_integration_testing.md +196 -0
  253. package/config/task_starters/prompts/build_tasks_step1_milestone_structure.md +274 -0
  254. package/config/task_starters/prompts/e2e_test_plan_step1_build_tests.md +391 -0
  255. package/config/task_starters/prompts/e2e_test_plan_step2_run_tests.md +240 -0
  256. package/dist/backend/backend/src/constants.d.ts +669 -0
  257. package/dist/backend/backend/src/constants.d.ts.map +1 -0
  258. package/dist/backend/backend/src/constants.js +482 -0
  259. package/dist/backend/backend/src/constants.js.map +1 -0
  260. package/dist/backend/backend/src/controllers/api.controller.d.ts +115 -0
  261. package/dist/backend/backend/src/controllers/api.controller.d.ts.map +1 -0
  262. package/dist/backend/backend/src/controllers/api.controller.js +427 -0
  263. package/dist/backend/backend/src/controllers/api.controller.js.map +1 -0
  264. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts +160 -0
  265. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -0
  266. package/dist/backend/backend/src/controllers/chat/chat.controller.js +555 -0
  267. package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -0
  268. package/dist/backend/backend/src/controllers/chat/chat.routes.d.ts +18 -0
  269. package/dist/backend/backend/src/controllers/chat/chat.routes.d.ts.map +1 -0
  270. package/dist/backend/backend/src/controllers/chat/chat.routes.js +39 -0
  271. package/dist/backend/backend/src/controllers/chat/chat.routes.js.map +1 -0
  272. package/dist/backend/backend/src/controllers/chat/index.d.ts +10 -0
  273. package/dist/backend/backend/src/controllers/chat/index.d.ts.map +1 -0
  274. package/dist/backend/backend/src/controllers/chat/index.js +10 -0
  275. package/dist/backend/backend/src/controllers/chat/index.js.map +1 -0
  276. package/dist/backend/backend/src/controllers/event-bus/event-bus.controller.d.ts +54 -0
  277. package/dist/backend/backend/src/controllers/event-bus/event-bus.controller.d.ts.map +1 -0
  278. package/dist/backend/backend/src/controllers/event-bus/event-bus.controller.js +123 -0
  279. package/dist/backend/backend/src/controllers/event-bus/event-bus.controller.js.map +1 -0
  280. package/dist/backend/backend/src/controllers/event-bus/event-bus.routes.d.ts +15 -0
  281. package/dist/backend/backend/src/controllers/event-bus/event-bus.routes.d.ts.map +1 -0
  282. package/dist/backend/backend/src/controllers/event-bus/event-bus.routes.js +27 -0
  283. package/dist/backend/backend/src/controllers/event-bus/event-bus.routes.js.map +1 -0
  284. package/dist/backend/backend/src/controllers/index.d.ts +10 -0
  285. package/dist/backend/backend/src/controllers/index.d.ts.map +1 -0
  286. package/dist/backend/backend/src/controllers/index.js +37 -0
  287. package/dist/backend/backend/src/controllers/index.js.map +1 -0
  288. package/dist/backend/backend/src/controllers/knowledge/index.d.ts +7 -0
  289. package/dist/backend/backend/src/controllers/knowledge/index.d.ts.map +1 -0
  290. package/dist/backend/backend/src/controllers/knowledge/index.js +7 -0
  291. package/dist/backend/backend/src/controllers/knowledge/index.js.map +1 -0
  292. package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.d.ts +71 -0
  293. package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.d.ts.map +1 -0
  294. package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.js +237 -0
  295. package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.js.map +1 -0
  296. package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.d.ts +24 -0
  297. package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.d.ts.map +1 -0
  298. package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.js +34 -0
  299. package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.js.map +1 -0
  300. package/dist/backend/backend/src/controllers/marketplace/index.d.ts +11 -0
  301. package/dist/backend/backend/src/controllers/marketplace/index.d.ts.map +1 -0
  302. package/dist/backend/backend/src/controllers/marketplace/index.js +11 -0
  303. package/dist/backend/backend/src/controllers/marketplace/index.js.map +1 -0
  304. package/dist/backend/backend/src/controllers/marketplace/marketplace.controller.d.ts +135 -0
  305. package/dist/backend/backend/src/controllers/marketplace/marketplace.controller.d.ts.map +1 -0
  306. package/dist/backend/backend/src/controllers/marketplace/marketplace.controller.js +228 -0
  307. package/dist/backend/backend/src/controllers/marketplace/marketplace.controller.js.map +1 -0
  308. package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.d.ts +30 -0
  309. package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.d.ts.map +1 -0
  310. package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.js +44 -0
  311. package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.js.map +1 -0
  312. package/dist/backend/backend/src/controllers/memory/index.d.ts +11 -0
  313. package/dist/backend/backend/src/controllers/memory/index.d.ts.map +1 -0
  314. package/dist/backend/backend/src/controllers/memory/index.js +11 -0
  315. package/dist/backend/backend/src/controllers/memory/index.js.map +1 -0
  316. package/dist/backend/backend/src/controllers/memory/memory.controller.d.ts +183 -0
  317. package/dist/backend/backend/src/controllers/memory/memory.controller.d.ts.map +1 -0
  318. package/dist/backend/backend/src/controllers/memory/memory.controller.js +505 -0
  319. package/dist/backend/backend/src/controllers/memory/memory.controller.js.map +1 -0
  320. package/dist/backend/backend/src/controllers/memory/memory.routes.d.ts +30 -0
  321. package/dist/backend/backend/src/controllers/memory/memory.routes.d.ts.map +1 -0
  322. package/dist/backend/backend/src/controllers/memory/memory.routes.js +46 -0
  323. package/dist/backend/backend/src/controllers/memory/memory.routes.js.map +1 -0
  324. package/dist/backend/backend/src/controllers/messaging/delivery-logs.controller.d.ts +5 -0
  325. package/dist/backend/backend/src/controllers/messaging/delivery-logs.controller.d.ts.map +1 -0
  326. package/dist/backend/backend/src/controllers/messaging/delivery-logs.controller.js +21 -0
  327. package/dist/backend/backend/src/controllers/messaging/delivery-logs.controller.js.map +1 -0
  328. package/dist/backend/backend/src/controllers/messaging/messaging.controller.d.ts +72 -0
  329. package/dist/backend/backend/src/controllers/messaging/messaging.controller.d.ts.map +1 -0
  330. package/dist/backend/backend/src/controllers/messaging/messaging.controller.js +164 -0
  331. package/dist/backend/backend/src/controllers/messaging/messaging.controller.js.map +1 -0
  332. package/dist/backend/backend/src/controllers/messaging/messaging.routes.d.ts +15 -0
  333. package/dist/backend/backend/src/controllers/messaging/messaging.routes.d.ts.map +1 -0
  334. package/dist/backend/backend/src/controllers/messaging/messaging.routes.js +31 -0
  335. package/dist/backend/backend/src/controllers/messaging/messaging.routes.js.map +1 -0
  336. package/dist/backend/backend/src/controllers/messaging/scheduled-messages.controller.d.ts +10 -0
  337. package/dist/backend/backend/src/controllers/messaging/scheduled-messages.controller.d.ts.map +1 -0
  338. package/dist/backend/backend/src/controllers/messaging/scheduled-messages.controller.js +223 -0
  339. package/dist/backend/backend/src/controllers/messaging/scheduled-messages.controller.js.map +1 -0
  340. package/dist/backend/backend/src/controllers/monitoring/file-watcher.controller.d.ts +121 -0
  341. package/dist/backend/backend/src/controllers/monitoring/file-watcher.controller.d.ts.map +1 -0
  342. package/dist/backend/backend/src/controllers/monitoring/file-watcher.controller.js +392 -0
  343. package/dist/backend/backend/src/controllers/monitoring/file-watcher.controller.js.map +1 -0
  344. package/dist/backend/backend/src/controllers/monitoring/monitoring.routes.d.ts +9 -0
  345. package/dist/backend/backend/src/controllers/monitoring/monitoring.routes.d.ts.map +1 -0
  346. package/dist/backend/backend/src/controllers/monitoring/monitoring.routes.js +15 -0
  347. package/dist/backend/backend/src/controllers/monitoring/monitoring.routes.js.map +1 -0
  348. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts +117 -0
  349. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -0
  350. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +705 -0
  351. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -0
  352. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.d.ts +22 -0
  353. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.d.ts.map +1 -0
  354. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.js +465 -0
  355. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.js.map +1 -0
  356. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.routes.d.ts +9 -0
  357. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.routes.d.ts.map +1 -0
  358. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.routes.js +26 -0
  359. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.routes.js.map +1 -0
  360. package/dist/backend/backend/src/controllers/project/git.controller.d.ts +10 -0
  361. package/dist/backend/backend/src/controllers/project/git.controller.d.ts.map +1 -0
  362. package/dist/backend/backend/src/controllers/project/git.controller.js +160 -0
  363. package/dist/backend/backend/src/controllers/project/git.controller.js.map +1 -0
  364. package/dist/backend/backend/src/controllers/project/project.controller.d.ts +41 -0
  365. package/dist/backend/backend/src/controllers/project/project.controller.d.ts.map +1 -0
  366. package/dist/backend/backend/src/controllers/project/project.controller.js +1126 -0
  367. package/dist/backend/backend/src/controllers/project/project.controller.js.map +1 -0
  368. package/dist/backend/backend/src/controllers/project/project.routes.d.ts +19 -0
  369. package/dist/backend/backend/src/controllers/project/project.routes.d.ts.map +1 -0
  370. package/dist/backend/backend/src/controllers/project/project.routes.js +141 -0
  371. package/dist/backend/backend/src/controllers/project/project.routes.js.map +1 -0
  372. package/dist/backend/backend/src/controllers/quality-gate/quality-gate.controller.d.ts +32 -0
  373. package/dist/backend/backend/src/controllers/quality-gate/quality-gate.controller.d.ts.map +1 -0
  374. package/dist/backend/backend/src/controllers/quality-gate/quality-gate.controller.js +57 -0
  375. package/dist/backend/backend/src/controllers/quality-gate/quality-gate.controller.js.map +1 -0
  376. package/dist/backend/backend/src/controllers/request-types.d.ts +225 -0
  377. package/dist/backend/backend/src/controllers/request-types.d.ts.map +1 -0
  378. package/dist/backend/backend/src/controllers/request-types.js +8 -0
  379. package/dist/backend/backend/src/controllers/request-types.js.map +1 -0
  380. package/dist/backend/backend/src/controllers/self-improvement/index.d.ts +9 -0
  381. package/dist/backend/backend/src/controllers/self-improvement/index.d.ts.map +1 -0
  382. package/dist/backend/backend/src/controllers/self-improvement/index.js +9 -0
  383. package/dist/backend/backend/src/controllers/self-improvement/index.js.map +1 -0
  384. package/dist/backend/backend/src/controllers/self-improvement/self-improvement.controller.d.ts +11 -0
  385. package/dist/backend/backend/src/controllers/self-improvement/self-improvement.controller.d.ts.map +1 -0
  386. package/dist/backend/backend/src/controllers/self-improvement/self-improvement.controller.js +166 -0
  387. package/dist/backend/backend/src/controllers/self-improvement/self-improvement.controller.js.map +1 -0
  388. package/dist/backend/backend/src/controllers/session/session.controller.d.ts +80 -0
  389. package/dist/backend/backend/src/controllers/session/session.controller.d.ts.map +1 -0
  390. package/dist/backend/backend/src/controllers/session/session.controller.js +275 -0
  391. package/dist/backend/backend/src/controllers/session/session.controller.js.map +1 -0
  392. package/dist/backend/backend/src/controllers/session/session.routes.d.ts +19 -0
  393. package/dist/backend/backend/src/controllers/session/session.routes.d.ts.map +1 -0
  394. package/dist/backend/backend/src/controllers/session/session.routes.js +33 -0
  395. package/dist/backend/backend/src/controllers/session/session.routes.js.map +1 -0
  396. package/dist/backend/backend/src/controllers/settings/index.d.ts +18 -0
  397. package/dist/backend/backend/src/controllers/settings/index.d.ts.map +1 -0
  398. package/dist/backend/backend/src/controllers/settings/index.js +27 -0
  399. package/dist/backend/backend/src/controllers/settings/index.js.map +1 -0
  400. package/dist/backend/backend/src/controllers/settings/role.controller.d.ts +10 -0
  401. package/dist/backend/backend/src/controllers/settings/role.controller.d.ts.map +1 -0
  402. package/dist/backend/backend/src/controllers/settings/role.controller.js +365 -0
  403. package/dist/backend/backend/src/controllers/settings/role.controller.js.map +1 -0
  404. package/dist/backend/backend/src/controllers/settings/settings.controller.d.ts +10 -0
  405. package/dist/backend/backend/src/controllers/settings/settings.controller.d.ts.map +1 -0
  406. package/dist/backend/backend/src/controllers/settings/settings.controller.js +176 -0
  407. package/dist/backend/backend/src/controllers/settings/settings.controller.js.map +1 -0
  408. package/dist/backend/backend/src/controllers/skill/index.d.ts +17 -0
  409. package/dist/backend/backend/src/controllers/skill/index.d.ts.map +1 -0
  410. package/dist/backend/backend/src/controllers/skill/index.js +18 -0
  411. package/dist/backend/backend/src/controllers/skill/index.js.map +1 -0
  412. package/dist/backend/backend/src/controllers/skill/skill.controller.d.ts +10 -0
  413. package/dist/backend/backend/src/controllers/skill/skill.controller.d.ts.map +1 -0
  414. package/dist/backend/backend/src/controllers/skill/skill.controller.js +423 -0
  415. package/dist/backend/backend/src/controllers/skill/skill.controller.js.map +1 -0
  416. package/dist/backend/backend/src/controllers/slack/index.d.ts +17 -0
  417. package/dist/backend/backend/src/controllers/slack/index.d.ts.map +1 -0
  418. package/dist/backend/backend/src/controllers/slack/index.js +18 -0
  419. package/dist/backend/backend/src/controllers/slack/index.js.map +1 -0
  420. package/dist/backend/backend/src/controllers/slack/slack-thread.controller.d.ts +22 -0
  421. package/dist/backend/backend/src/controllers/slack/slack-thread.controller.d.ts.map +1 -0
  422. package/dist/backend/backend/src/controllers/slack/slack-thread.controller.js +59 -0
  423. package/dist/backend/backend/src/controllers/slack/slack-thread.controller.js.map +1 -0
  424. package/dist/backend/backend/src/controllers/slack/slack-thread.routes.d.ts +15 -0
  425. package/dist/backend/backend/src/controllers/slack/slack-thread.routes.d.ts.map +1 -0
  426. package/dist/backend/backend/src/controllers/slack/slack-thread.routes.js +21 -0
  427. package/dist/backend/backend/src/controllers/slack/slack-thread.routes.js.map +1 -0
  428. package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts +11 -0
  429. package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -0
  430. package/dist/backend/backend/src/controllers/slack/slack.controller.js +416 -0
  431. package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -0
  432. package/dist/backend/backend/src/controllers/system/config.controller.d.ts +4 -0
  433. package/dist/backend/backend/src/controllers/system/config.controller.d.ts.map +1 -0
  434. package/dist/backend/backend/src/controllers/system/config.controller.js +48 -0
  435. package/dist/backend/backend/src/controllers/system/config.controller.js.map +1 -0
  436. package/dist/backend/backend/src/controllers/system/errors.controller.d.ts +8 -0
  437. package/dist/backend/backend/src/controllers/system/errors.controller.d.ts.map +1 -0
  438. package/dist/backend/backend/src/controllers/system/errors.controller.js +99 -0
  439. package/dist/backend/backend/src/controllers/system/errors.controller.js.map +1 -0
  440. package/dist/backend/backend/src/controllers/system/scheduler.controller.d.ts +13 -0
  441. package/dist/backend/backend/src/controllers/system/scheduler.controller.d.ts.map +1 -0
  442. package/dist/backend/backend/src/controllers/system/scheduler.controller.js +63 -0
  443. package/dist/backend/backend/src/controllers/system/scheduler.controller.js.map +1 -0
  444. package/dist/backend/backend/src/controllers/system/system.controller.d.ts +67 -0
  445. package/dist/backend/backend/src/controllers/system/system.controller.d.ts.map +1 -0
  446. package/dist/backend/backend/src/controllers/system/system.controller.js +390 -0
  447. package/dist/backend/backend/src/controllers/system/system.controller.js.map +1 -0
  448. package/dist/backend/backend/src/controllers/system/system.routes.d.ts +9 -0
  449. package/dist/backend/backend/src/controllers/system/system.routes.d.ts.map +1 -0
  450. package/dist/backend/backend/src/controllers/system/system.routes.js +16 -0
  451. package/dist/backend/backend/src/controllers/system/system.routes.js.map +1 -0
  452. package/dist/backend/backend/src/controllers/task-management/assignments.controller.d.ts +5 -0
  453. package/dist/backend/backend/src/controllers/task-management/assignments.controller.d.ts.map +1 -0
  454. package/dist/backend/backend/src/controllers/task-management/assignments.controller.js +56 -0
  455. package/dist/backend/backend/src/controllers/task-management/assignments.controller.js.map +1 -0
  456. package/dist/backend/backend/src/controllers/task-management/in-progress-tasks.controller.d.ts +10 -0
  457. package/dist/backend/backend/src/controllers/task-management/in-progress-tasks.controller.d.ts.map +1 -0
  458. package/dist/backend/backend/src/controllers/task-management/in-progress-tasks.controller.js +43 -0
  459. package/dist/backend/backend/src/controllers/task-management/in-progress-tasks.controller.js.map +1 -0
  460. package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +95 -0
  461. package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +1 -0
  462. package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +1034 -0
  463. package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +1 -0
  464. package/dist/backend/backend/src/controllers/task-management/tasks.controller.d.ts +8 -0
  465. package/dist/backend/backend/src/controllers/task-management/tasks.controller.d.ts.map +1 -0
  466. package/dist/backend/backend/src/controllers/task-management/tasks.controller.js +117 -0
  467. package/dist/backend/backend/src/controllers/task-management/tasks.controller.js.map +1 -0
  468. package/dist/backend/backend/src/controllers/task-management/tickets.controller.d.ts +13 -0
  469. package/dist/backend/backend/src/controllers/task-management/tickets.controller.d.ts.map +1 -0
  470. package/dist/backend/backend/src/controllers/task-management/tickets.controller.js +212 -0
  471. package/dist/backend/backend/src/controllers/task-management/tickets.controller.js.map +1 -0
  472. package/dist/backend/backend/src/controllers/team/team.controller.d.ts +35 -0
  473. package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -0
  474. package/dist/backend/backend/src/controllers/team/team.controller.js +1629 -0
  475. package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -0
  476. package/dist/backend/backend/src/controllers/team/team.routes.d.ts +9 -0
  477. package/dist/backend/backend/src/controllers/team/team.routes.d.ts.map +1 -0
  478. package/dist/backend/backend/src/controllers/team/team.routes.js +41 -0
  479. package/dist/backend/backend/src/controllers/team/team.routes.js.map +1 -0
  480. package/dist/backend/backend/src/controllers/teams-backup/teams-backup.controller.d.ts +32 -0
  481. package/dist/backend/backend/src/controllers/teams-backup/teams-backup.controller.d.ts.map +1 -0
  482. package/dist/backend/backend/src/controllers/teams-backup/teams-backup.controller.js +99 -0
  483. package/dist/backend/backend/src/controllers/teams-backup/teams-backup.controller.js.map +1 -0
  484. package/dist/backend/backend/src/controllers/teams-backup/teams-backup.routes.d.ts +15 -0
  485. package/dist/backend/backend/src/controllers/teams-backup/teams-backup.routes.d.ts.map +1 -0
  486. package/dist/backend/backend/src/controllers/teams-backup/teams-backup.routes.js +23 -0
  487. package/dist/backend/backend/src/controllers/teams-backup/teams-backup.routes.js.map +1 -0
  488. package/dist/backend/backend/src/controllers/types.d.ts +18 -0
  489. package/dist/backend/backend/src/controllers/types.d.ts.map +1 -0
  490. package/dist/backend/backend/src/controllers/types.js +2 -0
  491. package/dist/backend/backend/src/controllers/types.js.map +1 -0
  492. package/dist/backend/backend/src/controllers/utils/file-utils.d.ts +3 -0
  493. package/dist/backend/backend/src/controllers/utils/file-utils.d.ts.map +1 -0
  494. package/dist/backend/backend/src/controllers/utils/file-utils.js +98 -0
  495. package/dist/backend/backend/src/controllers/utils/file-utils.js.map +1 -0
  496. package/dist/backend/backend/src/index.d.ts +60 -0
  497. package/dist/backend/backend/src/index.d.ts.map +1 -0
  498. package/dist/backend/backend/src/index.js +872 -0
  499. package/dist/backend/backend/src/index.js.map +1 -0
  500. package/dist/backend/backend/src/middleware/agent-heartbeat.middleware.d.ts +22 -0
  501. package/dist/backend/backend/src/middleware/agent-heartbeat.middleware.d.ts.map +1 -0
  502. package/dist/backend/backend/src/middleware/agent-heartbeat.middleware.js +36 -0
  503. package/dist/backend/backend/src/middleware/agent-heartbeat.middleware.js.map +1 -0
  504. package/dist/backend/backend/src/models/Project.d.ts +18 -0
  505. package/dist/backend/backend/src/models/Project.d.ts.map +1 -0
  506. package/dist/backend/backend/src/models/Project.js +70 -0
  507. package/dist/backend/backend/src/models/Project.js.map +1 -0
  508. package/dist/backend/backend/src/models/ScheduledMessage.d.ts +27 -0
  509. package/dist/backend/backend/src/models/ScheduledMessage.d.ts.map +1 -0
  510. package/dist/backend/backend/src/models/ScheduledMessage.js +50 -0
  511. package/dist/backend/backend/src/models/ScheduledMessage.js.map +1 -0
  512. package/dist/backend/backend/src/models/Team.d.ts +20 -0
  513. package/dist/backend/backend/src/models/Team.d.ts.map +1 -0
  514. package/dist/backend/backend/src/models/Team.js +120 -0
  515. package/dist/backend/backend/src/models/Team.js.map +1 -0
  516. package/dist/backend/backend/src/models/Ticket.d.ts +24 -0
  517. package/dist/backend/backend/src/models/Ticket.d.ts.map +1 -0
  518. package/dist/backend/backend/src/models/Ticket.js +102 -0
  519. package/dist/backend/backend/src/models/Ticket.js.map +1 -0
  520. package/dist/backend/backend/src/models/index.d.ts +5 -0
  521. package/dist/backend/backend/src/models/index.d.ts.map +1 -0
  522. package/dist/backend/backend/src/models/index.js +5 -0
  523. package/dist/backend/backend/src/models/index.js.map +1 -0
  524. package/dist/backend/backend/src/routes/api.routes.d.ts +9 -0
  525. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -0
  526. package/dist/backend/backend/src/routes/api.routes.js +81 -0
  527. package/dist/backend/backend/src/routes/api.routes.js.map +1 -0
  528. package/dist/backend/backend/src/routes/factory.routes.d.ts +19 -0
  529. package/dist/backend/backend/src/routes/factory.routes.d.ts.map +1 -0
  530. package/dist/backend/backend/src/routes/factory.routes.js +103 -0
  531. package/dist/backend/backend/src/routes/factory.routes.js.map +1 -0
  532. package/dist/backend/backend/src/routes/modules/assignments.routes.d.ts +4 -0
  533. package/dist/backend/backend/src/routes/modules/assignments.routes.d.ts.map +1 -0
  534. package/dist/backend/backend/src/routes/modules/assignments.routes.js +7 -0
  535. package/dist/backend/backend/src/routes/modules/assignments.routes.js.map +1 -0
  536. package/dist/backend/backend/src/routes/modules/config.routes.d.ts +4 -0
  537. package/dist/backend/backend/src/routes/modules/config.routes.d.ts.map +1 -0
  538. package/dist/backend/backend/src/routes/modules/config.routes.js +6 -0
  539. package/dist/backend/backend/src/routes/modules/config.routes.js.map +1 -0
  540. package/dist/backend/backend/src/routes/modules/delivery-logs.routes.d.ts +4 -0
  541. package/dist/backend/backend/src/routes/modules/delivery-logs.routes.d.ts.map +1 -0
  542. package/dist/backend/backend/src/routes/modules/delivery-logs.routes.js +7 -0
  543. package/dist/backend/backend/src/routes/modules/delivery-logs.routes.js.map +1 -0
  544. package/dist/backend/backend/src/routes/modules/errors.routes.d.ts +4 -0
  545. package/dist/backend/backend/src/routes/modules/errors.routes.d.ts.map +1 -0
  546. package/dist/backend/backend/src/routes/modules/errors.routes.js +10 -0
  547. package/dist/backend/backend/src/routes/modules/errors.routes.js.map +1 -0
  548. package/dist/backend/backend/src/routes/modules/quality-gate.routes.d.ts +20 -0
  549. package/dist/backend/backend/src/routes/modules/quality-gate.routes.d.ts.map +1 -0
  550. package/dist/backend/backend/src/routes/modules/quality-gate.routes.js +25 -0
  551. package/dist/backend/backend/src/routes/modules/quality-gate.routes.js.map +1 -0
  552. package/dist/backend/backend/src/routes/modules/scheduled-messages.routes.d.ts +4 -0
  553. package/dist/backend/backend/src/routes/modules/scheduled-messages.routes.d.ts.map +1 -0
  554. package/dist/backend/backend/src/routes/modules/scheduled-messages.routes.js +12 -0
  555. package/dist/backend/backend/src/routes/modules/scheduled-messages.routes.js.map +1 -0
  556. package/dist/backend/backend/src/routes/modules/scheduler.routes.d.ts +4 -0
  557. package/dist/backend/backend/src/routes/modules/scheduler.routes.d.ts.map +1 -0
  558. package/dist/backend/backend/src/routes/modules/scheduler.routes.js +9 -0
  559. package/dist/backend/backend/src/routes/modules/scheduler.routes.js.map +1 -0
  560. package/dist/backend/backend/src/routes/modules/system.routes.d.ts +4 -0
  561. package/dist/backend/backend/src/routes/modules/system.routes.d.ts.map +1 -0
  562. package/dist/backend/backend/src/routes/modules/system.routes.js +24 -0
  563. package/dist/backend/backend/src/routes/modules/system.routes.js.map +1 -0
  564. package/dist/backend/backend/src/routes/modules/task-management.routes.d.ts +4 -0
  565. package/dist/backend/backend/src/routes/modules/task-management.routes.d.ts.map +1 -0
  566. package/dist/backend/backend/src/routes/modules/task-management.routes.js +25 -0
  567. package/dist/backend/backend/src/routes/modules/task-management.routes.js.map +1 -0
  568. package/dist/backend/backend/src/routes/modules/terminal.routes.d.ts +29 -0
  569. package/dist/backend/backend/src/routes/modules/terminal.routes.d.ts.map +1 -0
  570. package/dist/backend/backend/src/routes/modules/terminal.routes.js +49 -0
  571. package/dist/backend/backend/src/routes/modules/terminal.routes.js.map +1 -0
  572. package/dist/backend/backend/src/services/agent/agent-heartbeat.service.d.ts +240 -0
  573. package/dist/backend/backend/src/services/agent/agent-heartbeat.service.d.ts.map +1 -0
  574. package/dist/backend/backend/src/services/agent/agent-heartbeat.service.js +524 -0
  575. package/dist/backend/backend/src/services/agent/agent-heartbeat.service.js.map +1 -0
  576. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +398 -0
  577. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -0
  578. package/dist/backend/backend/src/services/agent/agent-registration.service.js +2863 -0
  579. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -0
  580. package/dist/backend/backend/src/services/agent/agent-suspend.service.d.ts +118 -0
  581. package/dist/backend/backend/src/services/agent/agent-suspend.service.d.ts.map +1 -0
  582. package/dist/backend/backend/src/services/agent/agent-suspend.service.js +304 -0
  583. package/dist/backend/backend/src/services/agent/agent-suspend.service.js.map +1 -0
  584. package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts +71 -0
  585. package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -0
  586. package/dist/backend/backend/src/services/agent/claude-runtime.service.js +220 -0
  587. package/dist/backend/backend/src/services/agent/claude-runtime.service.js.map +1 -0
  588. package/dist/backend/backend/src/services/agent/codex-runtime.service.d.ts +43 -0
  589. package/dist/backend/backend/src/services/agent/codex-runtime.service.d.ts.map +1 -0
  590. package/dist/backend/backend/src/services/agent/codex-runtime.service.js +118 -0
  591. package/dist/backend/backend/src/services/agent/codex-runtime.service.js.map +1 -0
  592. package/dist/backend/backend/src/services/agent/disk-cleanup.service.d.ts +79 -0
  593. package/dist/backend/backend/src/services/agent/disk-cleanup.service.d.ts.map +1 -0
  594. package/dist/backend/backend/src/services/agent/disk-cleanup.service.js +137 -0
  595. package/dist/backend/backend/src/services/agent/disk-cleanup.service.js.map +1 -0
  596. package/dist/backend/backend/src/services/agent/file-watcher.service.d.ts +87 -0
  597. package/dist/backend/backend/src/services/agent/file-watcher.service.d.ts.map +1 -0
  598. package/dist/backend/backend/src/services/agent/file-watcher.service.js +312 -0
  599. package/dist/backend/backend/src/services/agent/file-watcher.service.js.map +1 -0
  600. package/dist/backend/backend/src/services/agent/gemini-runtime.service.d.ts +83 -0
  601. package/dist/backend/backend/src/services/agent/gemini-runtime.service.d.ts.map +1 -0
  602. package/dist/backend/backend/src/services/agent/gemini-runtime.service.js +300 -0
  603. package/dist/backend/backend/src/services/agent/gemini-runtime.service.js.map +1 -0
  604. package/dist/backend/backend/src/services/agent/git-integration.service.d.ts +131 -0
  605. package/dist/backend/backend/src/services/agent/git-integration.service.d.ts.map +1 -0
  606. package/dist/backend/backend/src/services/agent/git-integration.service.js +368 -0
  607. package/dist/backend/backend/src/services/agent/git-integration.service.js.map +1 -0
  608. package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts +54 -0
  609. package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts.map +1 -0
  610. package/dist/backend/backend/src/services/agent/idle-detection.service.js +156 -0
  611. package/dist/backend/backend/src/services/agent/idle-detection.service.js.map +1 -0
  612. package/dist/backend/backend/src/services/agent/pty-activity-tracker.service.d.ts +77 -0
  613. package/dist/backend/backend/src/services/agent/pty-activity-tracker.service.d.ts.map +1 -0
  614. package/dist/backend/backend/src/services/agent/pty-activity-tracker.service.js +104 -0
  615. package/dist/backend/backend/src/services/agent/pty-activity-tracker.service.js.map +1 -0
  616. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts +114 -0
  617. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -0
  618. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +437 -0
  619. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -0
  620. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts +81 -0
  621. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -0
  622. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js +284 -0
  623. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -0
  624. package/dist/backend/backend/src/services/agent/runtime-service.factory.d.ts +71 -0
  625. package/dist/backend/backend/src/services/agent/runtime-service.factory.d.ts.map +1 -0
  626. package/dist/backend/backend/src/services/agent/runtime-service.factory.js +165 -0
  627. package/dist/backend/backend/src/services/agent/runtime-service.factory.js.map +1 -0
  628. package/dist/backend/backend/src/services/agent/tmux-command.service.d.ts +163 -0
  629. package/dist/backend/backend/src/services/agent/tmux-command.service.d.ts.map +1 -0
  630. package/dist/backend/backend/src/services/agent/tmux-command.service.js +962 -0
  631. package/dist/backend/backend/src/services/agent/tmux-command.service.js.map +1 -0
  632. package/dist/backend/backend/src/services/agent/tmux.service.d.ts +189 -0
  633. package/dist/backend/backend/src/services/agent/tmux.service.d.ts.map +1 -0
  634. package/dist/backend/backend/src/services/agent/tmux.service.js +673 -0
  635. package/dist/backend/backend/src/services/agent/tmux.service.js.map +1 -0
  636. package/dist/backend/backend/src/services/ai/context-loader.service.d.ts +40 -0
  637. package/dist/backend/backend/src/services/ai/context-loader.service.d.ts.map +1 -0
  638. package/dist/backend/backend/src/services/ai/context-loader.service.js +311 -0
  639. package/dist/backend/backend/src/services/ai/context-loader.service.js.map +1 -0
  640. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts +183 -0
  641. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -0
  642. package/dist/backend/backend/src/services/ai/prompt-builder.service.js +591 -0
  643. package/dist/backend/backend/src/services/ai/prompt-builder.service.js.map +1 -0
  644. package/dist/backend/backend/src/services/ai/prompt-template.service.d.ts +51 -0
  645. package/dist/backend/backend/src/services/ai/prompt-template.service.d.ts.map +1 -0
  646. package/dist/backend/backend/src/services/ai/prompt-template.service.js +99 -0
  647. package/dist/backend/backend/src/services/ai/prompt-template.service.js.map +1 -0
  648. package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts +429 -0
  649. package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts.map +1 -0
  650. package/dist/backend/backend/src/services/autonomous/auto-assign.service.js +852 -0
  651. package/dist/backend/backend/src/services/autonomous/auto-assign.service.js.map +1 -0
  652. package/dist/backend/backend/src/services/autonomous/budget.service.d.ts +319 -0
  653. package/dist/backend/backend/src/services/autonomous/budget.service.d.ts.map +1 -0
  654. package/dist/backend/backend/src/services/autonomous/budget.service.js +594 -0
  655. package/dist/backend/backend/src/services/autonomous/budget.service.js.map +1 -0
  656. package/dist/backend/backend/src/services/autonomous/index.d.ts +11 -0
  657. package/dist/backend/backend/src/services/autonomous/index.d.ts.map +1 -0
  658. package/dist/backend/backend/src/services/autonomous/index.js +11 -0
  659. package/dist/backend/backend/src/services/autonomous/index.js.map +1 -0
  660. package/dist/backend/backend/src/services/chat/chat.service.d.ts +358 -0
  661. package/dist/backend/backend/src/services/chat/chat.service.d.ts.map +1 -0
  662. package/dist/backend/backend/src/services/chat/chat.service.js +727 -0
  663. package/dist/backend/backend/src/services/chat/chat.service.js.map +1 -0
  664. package/dist/backend/backend/src/services/chat/index.d.ts +10 -0
  665. package/dist/backend/backend/src/services/chat/index.d.ts.map +1 -0
  666. package/dist/backend/backend/src/services/chat/index.js +10 -0
  667. package/dist/backend/backend/src/services/chat/index.js.map +1 -0
  668. package/dist/backend/backend/src/services/continuation/continuation-events.service.d.ts +152 -0
  669. package/dist/backend/backend/src/services/continuation/continuation-events.service.d.ts.map +1 -0
  670. package/dist/backend/backend/src/services/continuation/continuation-events.service.js +293 -0
  671. package/dist/backend/backend/src/services/continuation/continuation-events.service.js.map +1 -0
  672. package/dist/backend/backend/src/services/continuation/continuation.service.d.ts +278 -0
  673. package/dist/backend/backend/src/services/continuation/continuation.service.d.ts.map +1 -0
  674. package/dist/backend/backend/src/services/continuation/continuation.service.js +616 -0
  675. package/dist/backend/backend/src/services/continuation/continuation.service.js.map +1 -0
  676. package/dist/backend/backend/src/services/continuation/index.d.ts +14 -0
  677. package/dist/backend/backend/src/services/continuation/index.d.ts.map +1 -0
  678. package/dist/backend/backend/src/services/continuation/index.js +15 -0
  679. package/dist/backend/backend/src/services/continuation/index.js.map +1 -0
  680. package/dist/backend/backend/src/services/continuation/output-analyzer.service.d.ts +199 -0
  681. package/dist/backend/backend/src/services/continuation/output-analyzer.service.d.ts.map +1 -0
  682. package/dist/backend/backend/src/services/continuation/output-analyzer.service.js +390 -0
  683. package/dist/backend/backend/src/services/continuation/output-analyzer.service.js.map +1 -0
  684. package/dist/backend/backend/src/services/continuation/patterns/completion-patterns.d.ts +44 -0
  685. package/dist/backend/backend/src/services/continuation/patterns/completion-patterns.d.ts.map +1 -0
  686. package/dist/backend/backend/src/services/continuation/patterns/completion-patterns.js +82 -0
  687. package/dist/backend/backend/src/services/continuation/patterns/completion-patterns.js.map +1 -0
  688. package/dist/backend/backend/src/services/continuation/patterns/error-patterns.d.ts +37 -0
  689. package/dist/backend/backend/src/services/continuation/patterns/error-patterns.d.ts.map +1 -0
  690. package/dist/backend/backend/src/services/continuation/patterns/error-patterns.js +105 -0
  691. package/dist/backend/backend/src/services/continuation/patterns/error-patterns.js.map +1 -0
  692. package/dist/backend/backend/src/services/continuation/patterns/idle-patterns.d.ts +29 -0
  693. package/dist/backend/backend/src/services/continuation/patterns/idle-patterns.d.ts.map +1 -0
  694. package/dist/backend/backend/src/services/continuation/patterns/idle-patterns.js +49 -0
  695. package/dist/backend/backend/src/services/continuation/patterns/idle-patterns.js.map +1 -0
  696. package/dist/backend/backend/src/services/continuation/patterns/index.d.ts +12 -0
  697. package/dist/backend/backend/src/services/continuation/patterns/index.d.ts.map +1 -0
  698. package/dist/backend/backend/src/services/continuation/patterns/index.js +12 -0
  699. package/dist/backend/backend/src/services/continuation/patterns/index.js.map +1 -0
  700. package/dist/backend/backend/src/services/continuation/patterns/waiting-patterns.d.ts +34 -0
  701. package/dist/backend/backend/src/services/continuation/patterns/waiting-patterns.d.ts.map +1 -0
  702. package/dist/backend/backend/src/services/continuation/patterns/waiting-patterns.js +64 -0
  703. package/dist/backend/backend/src/services/continuation/patterns/waiting-patterns.js.map +1 -0
  704. package/dist/backend/backend/src/services/continuation/template-loader.service.d.ts +196 -0
  705. package/dist/backend/backend/src/services/continuation/template-loader.service.d.ts.map +1 -0
  706. package/dist/backend/backend/src/services/continuation/template-loader.service.js +323 -0
  707. package/dist/backend/backend/src/services/continuation/template-loader.service.js.map +1 -0
  708. package/dist/backend/backend/src/services/core/config.service.d.ts +85 -0
  709. package/dist/backend/backend/src/services/core/config.service.d.ts.map +1 -0
  710. package/dist/backend/backend/src/services/core/config.service.js +226 -0
  711. package/dist/backend/backend/src/services/core/config.service.js.map +1 -0
  712. package/dist/backend/backend/src/services/core/error-tracking.service.d.ts +98 -0
  713. package/dist/backend/backend/src/services/core/error-tracking.service.d.ts.map +1 -0
  714. package/dist/backend/backend/src/services/core/error-tracking.service.js +291 -0
  715. package/dist/backend/backend/src/services/core/error-tracking.service.js.map +1 -0
  716. package/dist/backend/backend/src/services/core/logger.service.d.ts +70 -0
  717. package/dist/backend/backend/src/services/core/logger.service.d.ts.map +1 -0
  718. package/dist/backend/backend/src/services/core/logger.service.js +350 -0
  719. package/dist/backend/backend/src/services/core/logger.service.js.map +1 -0
  720. package/dist/backend/backend/src/services/core/storage.service.d.ts +261 -0
  721. package/dist/backend/backend/src/services/core/storage.service.d.ts.map +1 -0
  722. package/dist/backend/backend/src/services/core/storage.service.js +1390 -0
  723. package/dist/backend/backend/src/services/core/storage.service.js.map +1 -0
  724. package/dist/backend/backend/src/services/core/teams-backup.service.d.ts +92 -0
  725. package/dist/backend/backend/src/services/core/teams-backup.service.d.ts.map +1 -0
  726. package/dist/backend/backend/src/services/core/teams-backup.service.js +120 -0
  727. package/dist/backend/backend/src/services/core/teams-backup.service.js.map +1 -0
  728. package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts +144 -0
  729. package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts.map +1 -0
  730. package/dist/backend/backend/src/services/event-bus/event-bus.service.js +337 -0
  731. package/dist/backend/backend/src/services/event-bus/event-bus.service.js.map +1 -0
  732. package/dist/backend/backend/src/services/event-bus/index.d.ts +7 -0
  733. package/dist/backend/backend/src/services/event-bus/index.d.ts.map +1 -0
  734. package/dist/backend/backend/src/services/event-bus/index.js +7 -0
  735. package/dist/backend/backend/src/services/event-bus/index.js.map +1 -0
  736. package/dist/backend/backend/src/services/factory/factory-sse.service.d.ts +163 -0
  737. package/dist/backend/backend/src/services/factory/factory-sse.service.d.ts.map +1 -0
  738. package/dist/backend/backend/src/services/factory/factory-sse.service.js +274 -0
  739. package/dist/backend/backend/src/services/factory/factory-sse.service.js.map +1 -0
  740. package/dist/backend/backend/src/services/factory.service.d.ts +157 -0
  741. package/dist/backend/backend/src/services/factory.service.d.ts.map +1 -0
  742. package/dist/backend/backend/src/services/factory.service.js +545 -0
  743. package/dist/backend/backend/src/services/factory.service.js.map +1 -0
  744. package/dist/backend/backend/src/services/index.d.ts +37 -0
  745. package/dist/backend/backend/src/services/index.d.ts.map +1 -0
  746. package/dist/backend/backend/src/services/index.js +50 -0
  747. package/dist/backend/backend/src/services/index.js.map +1 -0
  748. package/dist/backend/backend/src/services/knowledge/index.d.ts +7 -0
  749. package/dist/backend/backend/src/services/knowledge/index.d.ts.map +1 -0
  750. package/dist/backend/backend/src/services/knowledge/index.js +7 -0
  751. package/dist/backend/backend/src/services/knowledge/index.js.map +1 -0
  752. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts +125 -0
  753. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -0
  754. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js +247 -0
  755. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +1 -0
  756. package/dist/backend/backend/src/services/knowledge/knowledge.service.d.ts +153 -0
  757. package/dist/backend/backend/src/services/knowledge/knowledge.service.d.ts.map +1 -0
  758. package/dist/backend/backend/src/services/knowledge/knowledge.service.js +409 -0
  759. package/dist/backend/backend/src/services/knowledge/knowledge.service.js.map +1 -0
  760. package/dist/backend/backend/src/services/marketplace/index.d.ts +11 -0
  761. package/dist/backend/backend/src/services/marketplace/index.d.ts.map +1 -0
  762. package/dist/backend/backend/src/services/marketplace/index.js +13 -0
  763. package/dist/backend/backend/src/services/marketplace/index.js.map +1 -0
  764. package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.d.ts +47 -0
  765. package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.d.ts.map +1 -0
  766. package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js +127 -0
  767. package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -0
  768. package/dist/backend/backend/src/services/marketplace/marketplace.service.d.ts +101 -0
  769. package/dist/backend/backend/src/services/marketplace/marketplace.service.d.ts.map +1 -0
  770. package/dist/backend/backend/src/services/marketplace/marketplace.service.js +207 -0
  771. package/dist/backend/backend/src/services/marketplace/marketplace.service.js.map +1 -0
  772. package/dist/backend/backend/src/services/memory/agent-memory.service.d.ts +259 -0
  773. package/dist/backend/backend/src/services/memory/agent-memory.service.d.ts.map +1 -0
  774. package/dist/backend/backend/src/services/memory/agent-memory.service.js +539 -0
  775. package/dist/backend/backend/src/services/memory/agent-memory.service.js.map +1 -0
  776. package/dist/backend/backend/src/services/memory/daily-log.service.d.ts +159 -0
  777. package/dist/backend/backend/src/services/memory/daily-log.service.d.ts.map +1 -0
  778. package/dist/backend/backend/src/services/memory/daily-log.service.js +272 -0
  779. package/dist/backend/backend/src/services/memory/daily-log.service.js.map +1 -0
  780. package/dist/backend/backend/src/services/memory/goal-tracking.service.d.ts +239 -0
  781. package/dist/backend/backend/src/services/memory/goal-tracking.service.d.ts.map +1 -0
  782. package/dist/backend/backend/src/services/memory/goal-tracking.service.js +353 -0
  783. package/dist/backend/backend/src/services/memory/goal-tracking.service.js.map +1 -0
  784. package/dist/backend/backend/src/services/memory/index.d.ts +16 -0
  785. package/dist/backend/backend/src/services/memory/index.d.ts.map +1 -0
  786. package/dist/backend/backend/src/services/memory/index.js +15 -0
  787. package/dist/backend/backend/src/services/memory/index.js.map +1 -0
  788. package/dist/backend/backend/src/services/memory/learning-accumulation.service.d.ts +228 -0
  789. package/dist/backend/backend/src/services/memory/learning-accumulation.service.d.ts.map +1 -0
  790. package/dist/backend/backend/src/services/memory/learning-accumulation.service.js +336 -0
  791. package/dist/backend/backend/src/services/memory/learning-accumulation.service.js.map +1 -0
  792. package/dist/backend/backend/src/services/memory/memory.service.d.ts +306 -0
  793. package/dist/backend/backend/src/services/memory/memory.service.d.ts.map +1 -0
  794. package/dist/backend/backend/src/services/memory/memory.service.js +517 -0
  795. package/dist/backend/backend/src/services/memory/memory.service.js.map +1 -0
  796. package/dist/backend/backend/src/services/memory/project-memory.service.d.ts +252 -0
  797. package/dist/backend/backend/src/services/memory/project-memory.service.d.ts.map +1 -0
  798. package/dist/backend/backend/src/services/memory/project-memory.service.js +600 -0
  799. package/dist/backend/backend/src/services/memory/project-memory.service.js.map +1 -0
  800. package/dist/backend/backend/src/services/memory/session-memory.service.d.ts +197 -0
  801. package/dist/backend/backend/src/services/memory/session-memory.service.d.ts.map +1 -0
  802. package/dist/backend/backend/src/services/memory/session-memory.service.js +369 -0
  803. package/dist/backend/backend/src/services/memory/session-memory.service.js.map +1 -0
  804. package/dist/backend/backend/src/services/messaging/index.d.ts +9 -0
  805. package/dist/backend/backend/src/services/messaging/index.d.ts.map +1 -0
  806. package/dist/backend/backend/src/services/messaging/index.js +9 -0
  807. package/dist/backend/backend/src/services/messaging/index.js.map +1 -0
  808. package/dist/backend/backend/src/services/messaging/message-queue.service.d.ts +198 -0
  809. package/dist/backend/backend/src/services/messaging/message-queue.service.d.ts.map +1 -0
  810. package/dist/backend/backend/src/services/messaging/message-queue.service.js +445 -0
  811. package/dist/backend/backend/src/services/messaging/message-queue.service.js.map +1 -0
  812. package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts +90 -0
  813. package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -0
  814. package/dist/backend/backend/src/services/messaging/queue-processor.service.js +324 -0
  815. package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -0
  816. package/dist/backend/backend/src/services/messaging/response-router.service.d.ts +56 -0
  817. package/dist/backend/backend/src/services/messaging/response-router.service.d.ts.map +1 -0
  818. package/dist/backend/backend/src/services/messaging/response-router.service.js +134 -0
  819. package/dist/backend/backend/src/services/messaging/response-router.service.js.map +1 -0
  820. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +84 -0
  821. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -0
  822. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js +136 -0
  823. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -0
  824. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts +113 -0
  825. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -0
  826. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js +473 -0
  827. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js.map +1 -0
  828. package/dist/backend/backend/src/services/monitoring/monitoring.service.d.ts +129 -0
  829. package/dist/backend/backend/src/services/monitoring/monitoring.service.d.ts.map +1 -0
  830. package/dist/backend/backend/src/services/monitoring/monitoring.service.js +469 -0
  831. package/dist/backend/backend/src/services/monitoring/monitoring.service.js.map +1 -0
  832. package/dist/backend/backend/src/services/monitoring/system-resource-alert.service.d.ts +48 -0
  833. package/dist/backend/backend/src/services/monitoring/system-resource-alert.service.d.ts.map +1 -0
  834. package/dist/backend/backend/src/services/monitoring/system-resource-alert.service.js +151 -0
  835. package/dist/backend/backend/src/services/monitoring/system-resource-alert.service.js.map +1 -0
  836. package/dist/backend/backend/src/services/monitoring/task-assignment-monitor.service.d.ts +71 -0
  837. package/dist/backend/backend/src/services/monitoring/task-assignment-monitor.service.d.ts.map +1 -0
  838. package/dist/backend/backend/src/services/monitoring/task-assignment-monitor.service.js +304 -0
  839. package/dist/backend/backend/src/services/monitoring/task-assignment-monitor.service.js.map +1 -0
  840. package/dist/backend/backend/src/services/monitoring/team-activity-websocket.service.d.ts +100 -0
  841. package/dist/backend/backend/src/services/monitoring/team-activity-websocket.service.d.ts.map +1 -0
  842. package/dist/backend/backend/src/services/monitoring/team-activity-websocket.service.js +285 -0
  843. package/dist/backend/backend/src/services/monitoring/team-activity-websocket.service.js.map +1 -0
  844. package/dist/backend/backend/src/services/monitoring/teams-json-watcher.service.d.ts +107 -0
  845. package/dist/backend/backend/src/services/monitoring/teams-json-watcher.service.d.ts.map +1 -0
  846. package/dist/backend/backend/src/services/monitoring/teams-json-watcher.service.js +568 -0
  847. package/dist/backend/backend/src/services/monitoring/teams-json-watcher.service.js.map +1 -0
  848. package/dist/backend/backend/src/services/orchestrator/improvement-marker.service.d.ts +231 -0
  849. package/dist/backend/backend/src/services/orchestrator/improvement-marker.service.d.ts.map +1 -0
  850. package/dist/backend/backend/src/services/orchestrator/improvement-marker.service.js +344 -0
  851. package/dist/backend/backend/src/services/orchestrator/improvement-marker.service.js.map +1 -0
  852. package/dist/backend/backend/src/services/orchestrator/improvement-startup.service.d.ts +156 -0
  853. package/dist/backend/backend/src/services/orchestrator/improvement-startup.service.d.ts.map +1 -0
  854. package/dist/backend/backend/src/services/orchestrator/improvement-startup.service.js +481 -0
  855. package/dist/backend/backend/src/services/orchestrator/improvement-startup.service.js.map +1 -0
  856. package/dist/backend/backend/src/services/orchestrator/index.d.ts +15 -0
  857. package/dist/backend/backend/src/services/orchestrator/index.d.ts.map +1 -0
  858. package/dist/backend/backend/src/services/orchestrator/index.js +15 -0
  859. package/dist/backend/backend/src/services/orchestrator/index.js.map +1 -0
  860. package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.d.ts +112 -0
  861. package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.d.ts.map +1 -0
  862. package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js +244 -0
  863. package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js.map +1 -0
  864. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.d.ts +61 -0
  865. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.d.ts.map +1 -0
  866. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js +156 -0
  867. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js.map +1 -0
  868. package/dist/backend/backend/src/services/orchestrator/safe-restart.service.d.ts +191 -0
  869. package/dist/backend/backend/src/services/orchestrator/safe-restart.service.d.ts.map +1 -0
  870. package/dist/backend/backend/src/services/orchestrator/safe-restart.service.js +393 -0
  871. package/dist/backend/backend/src/services/orchestrator/safe-restart.service.js.map +1 -0
  872. package/dist/backend/backend/src/services/orchestrator/self-improvement.service.d.ts +200 -0
  873. package/dist/backend/backend/src/services/orchestrator/self-improvement.service.d.ts.map +1 -0
  874. package/dist/backend/backend/src/services/orchestrator/self-improvement.service.js +394 -0
  875. package/dist/backend/backend/src/services/orchestrator/self-improvement.service.js.map +1 -0
  876. package/dist/backend/backend/src/services/orchestrator/state-persistence.service.d.ts +226 -0
  877. package/dist/backend/backend/src/services/orchestrator/state-persistence.service.d.ts.map +1 -0
  878. package/dist/backend/backend/src/services/orchestrator/state-persistence.service.js +504 -0
  879. package/dist/backend/backend/src/services/orchestrator/state-persistence.service.js.map +1 -0
  880. package/dist/backend/backend/src/services/project/active-projects.service.d.ts +39 -0
  881. package/dist/backend/backend/src/services/project/active-projects.service.d.ts.map +1 -0
  882. package/dist/backend/backend/src/services/project/active-projects.service.js +295 -0
  883. package/dist/backend/backend/src/services/project/active-projects.service.js.map +1 -0
  884. package/dist/backend/backend/src/services/project/task-folder.service.d.ts +48 -0
  885. package/dist/backend/backend/src/services/project/task-folder.service.d.ts.map +1 -0
  886. package/dist/backend/backend/src/services/project/task-folder.service.js +193 -0
  887. package/dist/backend/backend/src/services/project/task-folder.service.js.map +1 -0
  888. package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +47 -0
  889. package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +1 -0
  890. package/dist/backend/backend/src/services/project/task-tracking.service.js +330 -0
  891. package/dist/backend/backend/src/services/project/task-tracking.service.js.map +1 -0
  892. package/dist/backend/backend/src/services/project/task.service.d.ts +31 -0
  893. package/dist/backend/backend/src/services/project/task.service.d.ts.map +1 -0
  894. package/dist/backend/backend/src/services/project/task.service.js +193 -0
  895. package/dist/backend/backend/src/services/project/task.service.js.map +1 -0
  896. package/dist/backend/backend/src/services/project/ticket-editor.service.d.ts +129 -0
  897. package/dist/backend/backend/src/services/project/ticket-editor.service.d.ts.map +1 -0
  898. package/dist/backend/backend/src/services/project/ticket-editor.service.js +405 -0
  899. package/dist/backend/backend/src/services/project/ticket-editor.service.js.map +1 -0
  900. package/dist/backend/backend/src/services/prompt/index.d.ts +7 -0
  901. package/dist/backend/backend/src/services/prompt/index.d.ts.map +1 -0
  902. package/dist/backend/backend/src/services/prompt/index.js +7 -0
  903. package/dist/backend/backend/src/services/prompt/index.js.map +1 -0
  904. package/dist/backend/backend/src/services/prompt/prompt-generator.service.d.ts +106 -0
  905. package/dist/backend/backend/src/services/prompt/prompt-generator.service.d.ts.map +1 -0
  906. package/dist/backend/backend/src/services/prompt/prompt-generator.service.js +287 -0
  907. package/dist/backend/backend/src/services/prompt/prompt-generator.service.js.map +1 -0
  908. package/dist/backend/backend/src/services/quality/index.d.ts +10 -0
  909. package/dist/backend/backend/src/services/quality/index.d.ts.map +1 -0
  910. package/dist/backend/backend/src/services/quality/index.js +10 -0
  911. package/dist/backend/backend/src/services/quality/index.js.map +1 -0
  912. package/dist/backend/backend/src/services/quality/quality-gate.service.d.ts +223 -0
  913. package/dist/backend/backend/src/services/quality/quality-gate.service.d.ts.map +1 -0
  914. package/dist/backend/backend/src/services/quality/quality-gate.service.js +388 -0
  915. package/dist/backend/backend/src/services/quality/quality-gate.service.js.map +1 -0
  916. package/dist/backend/backend/src/services/session/index.d.ts +43 -0
  917. package/dist/backend/backend/src/services/session/index.d.ts.map +1 -0
  918. package/dist/backend/backend/src/services/session/index.js +46 -0
  919. package/dist/backend/backend/src/services/session/index.js.map +1 -0
  920. package/dist/backend/backend/src/services/session/pty/index.d.ts +11 -0
  921. package/dist/backend/backend/src/services/session/pty/index.d.ts.map +1 -0
  922. package/dist/backend/backend/src/services/session/pty/index.js +11 -0
  923. package/dist/backend/backend/src/services/session/pty/index.js.map +1 -0
  924. package/dist/backend/backend/src/services/session/pty/pty-session-backend.d.ts +258 -0
  925. package/dist/backend/backend/src/services/session/pty/pty-session-backend.d.ts.map +1 -0
  926. package/dist/backend/backend/src/services/session/pty/pty-session-backend.js +435 -0
  927. package/dist/backend/backend/src/services/session/pty/pty-session-backend.js.map +1 -0
  928. package/dist/backend/backend/src/services/session/pty/pty-session.d.ts +196 -0
  929. package/dist/backend/backend/src/services/session/pty/pty-session.d.ts.map +1 -0
  930. package/dist/backend/backend/src/services/session/pty/pty-session.js +393 -0
  931. package/dist/backend/backend/src/services/session/pty/pty-session.js.map +1 -0
  932. package/dist/backend/backend/src/services/session/pty/pty-terminal-buffer.d.ts +241 -0
  933. package/dist/backend/backend/src/services/session/pty/pty-terminal-buffer.d.ts.map +1 -0
  934. package/dist/backend/backend/src/services/session/pty/pty-terminal-buffer.js +351 -0
  935. package/dist/backend/backend/src/services/session/pty/pty-terminal-buffer.js.map +1 -0
  936. package/dist/backend/backend/src/services/session/session-backend.factory.d.ts +127 -0
  937. package/dist/backend/backend/src/services/session/session-backend.factory.d.ts.map +1 -0
  938. package/dist/backend/backend/src/services/session/session-backend.factory.js +226 -0
  939. package/dist/backend/backend/src/services/session/session-backend.factory.js.map +1 -0
  940. package/dist/backend/backend/src/services/session/session-backend.interface.d.ts +358 -0
  941. package/dist/backend/backend/src/services/session/session-backend.interface.d.ts.map +1 -0
  942. package/dist/backend/backend/src/services/session/session-backend.interface.js +19 -0
  943. package/dist/backend/backend/src/services/session/session-backend.interface.js.map +1 -0
  944. package/dist/backend/backend/src/services/session/session-command-helper.d.ts +327 -0
  945. package/dist/backend/backend/src/services/session/session-command-helper.d.ts.map +1 -0
  946. package/dist/backend/backend/src/services/session/session-command-helper.js +687 -0
  947. package/dist/backend/backend/src/services/session/session-command-helper.js.map +1 -0
  948. package/dist/backend/backend/src/services/session/session-state-persistence.d.ts +228 -0
  949. package/dist/backend/backend/src/services/session/session-state-persistence.d.ts.map +1 -0
  950. package/dist/backend/backend/src/services/session/session-state-persistence.js +394 -0
  951. package/dist/backend/backend/src/services/session/session-state-persistence.js.map +1 -0
  952. package/dist/backend/backend/src/services/settings/index.d.ts +10 -0
  953. package/dist/backend/backend/src/services/settings/index.d.ts.map +1 -0
  954. package/dist/backend/backend/src/services/settings/index.js +12 -0
  955. package/dist/backend/backend/src/services/settings/index.js.map +1 -0
  956. package/dist/backend/backend/src/services/settings/role.service.d.ts +276 -0
  957. package/dist/backend/backend/src/services/settings/role.service.d.ts.map +1 -0
  958. package/dist/backend/backend/src/services/settings/role.service.js +726 -0
  959. package/dist/backend/backend/src/services/settings/role.service.js.map +1 -0
  960. package/dist/backend/backend/src/services/settings/settings.service.d.ts +160 -0
  961. package/dist/backend/backend/src/services/settings/settings.service.d.ts.map +1 -0
  962. package/dist/backend/backend/src/services/settings/settings.service.js +294 -0
  963. package/dist/backend/backend/src/services/settings/settings.service.js.map +1 -0
  964. package/dist/backend/backend/src/services/skill/index.d.ts +10 -0
  965. package/dist/backend/backend/src/services/skill/index.d.ts.map +1 -0
  966. package/dist/backend/backend/src/services/skill/index.js +10 -0
  967. package/dist/backend/backend/src/services/skill/index.js.map +1 -0
  968. package/dist/backend/backend/src/services/skill/skill-catalog.service.d.ts +236 -0
  969. package/dist/backend/backend/src/services/skill/skill-catalog.service.d.ts.map +1 -0
  970. package/dist/backend/backend/src/services/skill/skill-catalog.service.js +550 -0
  971. package/dist/backend/backend/src/services/skill/skill-catalog.service.js.map +1 -0
  972. package/dist/backend/backend/src/services/skill/skill-executor.service.d.ts +135 -0
  973. package/dist/backend/backend/src/services/skill/skill-executor.service.d.ts.map +1 -0
  974. package/dist/backend/backend/src/services/skill/skill-executor.service.js +493 -0
  975. package/dist/backend/backend/src/services/skill/skill-executor.service.js.map +1 -0
  976. package/dist/backend/backend/src/services/skill/skill.service.d.ts +241 -0
  977. package/dist/backend/backend/src/services/skill/skill.service.d.ts.map +1 -0
  978. package/dist/backend/backend/src/services/skill/skill.service.js +542 -0
  979. package/dist/backend/backend/src/services/skill/skill.service.js.map +1 -0
  980. package/dist/backend/backend/src/services/slack/index.d.ts +13 -0
  981. package/dist/backend/backend/src/services/slack/index.d.ts.map +1 -0
  982. package/dist/backend/backend/src/services/slack/index.js +13 -0
  983. package/dist/backend/backend/src/services/slack/index.js.map +1 -0
  984. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.d.ts +63 -0
  985. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.d.ts.map +1 -0
  986. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.js +182 -0
  987. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.js.map +1 -0
  988. package/dist/backend/backend/src/services/slack/slack-image.service.d.ts +113 -0
  989. package/dist/backend/backend/src/services/slack/slack-image.service.d.ts.map +1 -0
  990. package/dist/backend/backend/src/services/slack/slack-image.service.js +329 -0
  991. package/dist/backend/backend/src/services/slack/slack-image.service.js.map +1 -0
  992. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts +71 -0
  993. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -0
  994. package/dist/backend/backend/src/services/slack/slack-initializer.js +106 -0
  995. package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -0
  996. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +302 -0
  997. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -0
  998. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +806 -0
  999. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -0
  1000. package/dist/backend/backend/src/services/slack/slack-thread-store.service.d.ts +147 -0
  1001. package/dist/backend/backend/src/services/slack/slack-thread-store.service.d.ts.map +1 -0
  1002. package/dist/backend/backend/src/services/slack/slack-thread-store.service.js +258 -0
  1003. package/dist/backend/backend/src/services/slack/slack-thread-store.service.js.map +1 -0
  1004. package/dist/backend/backend/src/services/slack/slack.service.d.ts +219 -0
  1005. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -0
  1006. package/dist/backend/backend/src/services/slack/slack.service.js +551 -0
  1007. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -0
  1008. package/dist/backend/backend/src/services/sop/index.d.ts +9 -0
  1009. package/dist/backend/backend/src/services/sop/index.d.ts.map +1 -0
  1010. package/dist/backend/backend/src/services/sop/index.js +9 -0
  1011. package/dist/backend/backend/src/services/sop/index.js.map +1 -0
  1012. package/dist/backend/backend/src/services/sop/sop.service.d.ts +286 -0
  1013. package/dist/backend/backend/src/services/sop/sop.service.d.ts.map +1 -0
  1014. package/dist/backend/backend/src/services/sop/sop.service.js +583 -0
  1015. package/dist/backend/backend/src/services/sop/sop.service.js.map +1 -0
  1016. package/dist/backend/backend/src/services/system/version-check.service.d.ts +112 -0
  1017. package/dist/backend/backend/src/services/system/version-check.service.d.ts.map +1 -0
  1018. package/dist/backend/backend/src/services/system/version-check.service.js +195 -0
  1019. package/dist/backend/backend/src/services/system/version-check.service.js.map +1 -0
  1020. package/dist/backend/backend/src/services/workflow/message-scheduler.service.d.ts +99 -0
  1021. package/dist/backend/backend/src/services/workflow/message-scheduler.service.d.ts.map +1 -0
  1022. package/dist/backend/backend/src/services/workflow/message-scheduler.service.js +408 -0
  1023. package/dist/backend/backend/src/services/workflow/message-scheduler.service.js.map +1 -0
  1024. package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts +300 -0
  1025. package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -0
  1026. package/dist/backend/backend/src/services/workflow/scheduler.service.js +924 -0
  1027. package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -0
  1028. package/dist/backend/backend/src/types/auto-assign.types.d.ts +271 -0
  1029. package/dist/backend/backend/src/types/auto-assign.types.d.ts.map +1 -0
  1030. package/dist/backend/backend/src/types/auto-assign.types.js +136 -0
  1031. package/dist/backend/backend/src/types/auto-assign.types.js.map +1 -0
  1032. package/dist/backend/backend/src/types/budget.types.d.ts +217 -0
  1033. package/dist/backend/backend/src/types/budget.types.d.ts.map +1 -0
  1034. package/dist/backend/backend/src/types/budget.types.js +82 -0
  1035. package/dist/backend/backend/src/types/budget.types.js.map +1 -0
  1036. package/dist/backend/backend/src/types/chat.types.d.ts +550 -0
  1037. package/dist/backend/backend/src/types/chat.types.d.ts.map +1 -0
  1038. package/dist/backend/backend/src/types/chat.types.js +743 -0
  1039. package/dist/backend/backend/src/types/chat.types.js.map +1 -0
  1040. package/dist/backend/backend/src/types/continuation.types.d.ts +237 -0
  1041. package/dist/backend/backend/src/types/continuation.types.d.ts.map +1 -0
  1042. package/dist/backend/backend/src/types/continuation.types.js +10 -0
  1043. package/dist/backend/backend/src/types/continuation.types.js.map +1 -0
  1044. package/dist/backend/backend/src/types/event-bus.types.d.ts +112 -0
  1045. package/dist/backend/backend/src/types/event-bus.types.d.ts.map +1 -0
  1046. package/dist/backend/backend/src/types/event-bus.types.js +82 -0
  1047. package/dist/backend/backend/src/types/event-bus.types.js.map +1 -0
  1048. package/dist/backend/backend/src/types/index.d.ts +161 -0
  1049. package/dist/backend/backend/src/types/index.d.ts.map +1 -0
  1050. package/dist/backend/backend/src/types/index.js +23 -0
  1051. package/dist/backend/backend/src/types/index.js.map +1 -0
  1052. package/dist/backend/backend/src/types/knowledge.types.d.ts +195 -0
  1053. package/dist/backend/backend/src/types/knowledge.types.d.ts.map +1 -0
  1054. package/dist/backend/backend/src/types/knowledge.types.js +38 -0
  1055. package/dist/backend/backend/src/types/knowledge.types.js.map +1 -0
  1056. package/dist/backend/backend/src/types/marketplace.types.d.ts +68 -0
  1057. package/dist/backend/backend/src/types/marketplace.types.d.ts.map +1 -0
  1058. package/dist/backend/backend/src/types/marketplace.types.js +6 -0
  1059. package/dist/backend/backend/src/types/marketplace.types.js.map +1 -0
  1060. package/dist/backend/backend/src/types/memory.types.d.ts +587 -0
  1061. package/dist/backend/backend/src/types/memory.types.d.ts.map +1 -0
  1062. package/dist/backend/backend/src/types/memory.types.js +47 -0
  1063. package/dist/backend/backend/src/types/memory.types.js.map +1 -0
  1064. package/dist/backend/backend/src/types/messaging.types.d.ts +216 -0
  1065. package/dist/backend/backend/src/types/messaging.types.d.ts.map +1 -0
  1066. package/dist/backend/backend/src/types/messaging.types.js +224 -0
  1067. package/dist/backend/backend/src/types/messaging.types.js.map +1 -0
  1068. package/dist/backend/backend/src/types/orchestrator-state.types.d.ts +482 -0
  1069. package/dist/backend/backend/src/types/orchestrator-state.types.d.ts.map +1 -0
  1070. package/dist/backend/backend/src/types/orchestrator-state.types.js +83 -0
  1071. package/dist/backend/backend/src/types/orchestrator-state.types.js.map +1 -0
  1072. package/dist/backend/backend/src/types/quality-gate.types.d.ts +171 -0
  1073. package/dist/backend/backend/src/types/quality-gate.types.d.ts.map +1 -0
  1074. package/dist/backend/backend/src/types/quality-gate.types.js +42 -0
  1075. package/dist/backend/backend/src/types/quality-gate.types.js.map +1 -0
  1076. package/dist/backend/backend/src/types/role.types.d.ts +260 -0
  1077. package/dist/backend/backend/src/types/role.types.d.ts.map +1 -0
  1078. package/dist/backend/backend/src/types/role.types.js +238 -0
  1079. package/dist/backend/backend/src/types/role.types.js.map +1 -0
  1080. package/dist/backend/backend/src/types/scheduler.types.d.ts +237 -0
  1081. package/dist/backend/backend/src/types/scheduler.types.d.ts.map +1 -0
  1082. package/dist/backend/backend/src/types/scheduler.types.js +32 -0
  1083. package/dist/backend/backend/src/types/scheduler.types.js.map +1 -0
  1084. package/dist/backend/backend/src/types/settings.types.d.ts +178 -0
  1085. package/dist/backend/backend/src/types/settings.types.d.ts.map +1 -0
  1086. package/dist/backend/backend/src/types/settings.types.js +206 -0
  1087. package/dist/backend/backend/src/types/settings.types.js.map +1 -0
  1088. package/dist/backend/backend/src/types/skill.types.d.ts +515 -0
  1089. package/dist/backend/backend/src/types/skill.types.d.ts.map +1 -0
  1090. package/dist/backend/backend/src/types/skill.types.js +481 -0
  1091. package/dist/backend/backend/src/types/skill.types.js.map +1 -0
  1092. package/dist/backend/backend/src/types/slack.types.d.ts +329 -0
  1093. package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -0
  1094. package/dist/backend/backend/src/types/slack.types.js +66 -0
  1095. package/dist/backend/backend/src/types/slack.types.js.map +1 -0
  1096. package/dist/backend/backend/src/types/sop.types.d.ts +224 -0
  1097. package/dist/backend/backend/src/types/sop.types.d.ts.map +1 -0
  1098. package/dist/backend/backend/src/types/sop.types.js +85 -0
  1099. package/dist/backend/backend/src/types/sop.types.js.map +1 -0
  1100. package/dist/backend/backend/src/types/task-tracking.types.d.ts +91 -0
  1101. package/dist/backend/backend/src/types/task-tracking.types.d.ts.map +1 -0
  1102. package/dist/backend/backend/src/types/task-tracking.types.js +5 -0
  1103. package/dist/backend/backend/src/types/task-tracking.types.js.map +1 -0
  1104. package/dist/backend/backend/src/utils/async.utils.d.ts +68 -0
  1105. package/dist/backend/backend/src/utils/async.utils.d.ts.map +1 -0
  1106. package/dist/backend/backend/src/utils/async.utils.js +80 -0
  1107. package/dist/backend/backend/src/utils/async.utils.js.map +1 -0
  1108. package/dist/backend/backend/src/utils/defaultPrompts.d.ts +5 -0
  1109. package/dist/backend/backend/src/utils/defaultPrompts.d.ts.map +1 -0
  1110. package/dist/backend/backend/src/utils/defaultPrompts.js +285 -0
  1111. package/dist/backend/backend/src/utils/defaultPrompts.js.map +1 -0
  1112. package/dist/backend/backend/src/utils/file-io.utils.d.ts +102 -0
  1113. package/dist/backend/backend/src/utils/file-io.utils.d.ts.map +1 -0
  1114. package/dist/backend/backend/src/utils/file-io.utils.js +214 -0
  1115. package/dist/backend/backend/src/utils/file-io.utils.js.map +1 -0
  1116. package/dist/backend/backend/src/utils/package-root.d.ts +15 -0
  1117. package/dist/backend/backend/src/utils/package-root.d.ts.map +1 -0
  1118. package/dist/backend/backend/src/utils/package-root.js +38 -0
  1119. package/dist/backend/backend/src/utils/package-root.js.map +1 -0
  1120. package/dist/backend/backend/src/utils/process-recovery.d.ts +81 -0
  1121. package/dist/backend/backend/src/utils/process-recovery.d.ts.map +1 -0
  1122. package/dist/backend/backend/src/utils/process-recovery.js +283 -0
  1123. package/dist/backend/backend/src/utils/process-recovery.js.map +1 -0
  1124. package/dist/backend/backend/src/utils/prompt-resolver.d.ts +79 -0
  1125. package/dist/backend/backend/src/utils/prompt-resolver.d.ts.map +1 -0
  1126. package/dist/backend/backend/src/utils/prompt-resolver.js +132 -0
  1127. package/dist/backend/backend/src/utils/prompt-resolver.js.map +1 -0
  1128. package/dist/backend/backend/src/utils/resource-monitor.d.ts +177 -0
  1129. package/dist/backend/backend/src/utils/resource-monitor.d.ts.map +1 -0
  1130. package/dist/backend/backend/src/utils/resource-monitor.js +404 -0
  1131. package/dist/backend/backend/src/utils/resource-monitor.js.map +1 -0
  1132. package/dist/backend/backend/src/utils/security.d.ts +194 -0
  1133. package/dist/backend/backend/src/utils/security.d.ts.map +1 -0
  1134. package/dist/backend/backend/src/utils/security.js +533 -0
  1135. package/dist/backend/backend/src/utils/security.js.map +1 -0
  1136. package/dist/backend/backend/src/utils/terminal-output.utils.d.ts +54 -0
  1137. package/dist/backend/backend/src/utils/terminal-output.utils.d.ts.map +1 -0
  1138. package/dist/backend/backend/src/utils/terminal-output.utils.js +97 -0
  1139. package/dist/backend/backend/src/utils/terminal-output.utils.js.map +1 -0
  1140. package/dist/backend/backend/src/websocket/chat.gateway.d.ts +127 -0
  1141. package/dist/backend/backend/src/websocket/chat.gateway.d.ts.map +1 -0
  1142. package/dist/backend/backend/src/websocket/chat.gateway.js +306 -0
  1143. package/dist/backend/backend/src/websocket/chat.gateway.js.map +1 -0
  1144. package/dist/backend/backend/src/websocket/file-watcher.gateway.d.ts +54 -0
  1145. package/dist/backend/backend/src/websocket/file-watcher.gateway.d.ts.map +1 -0
  1146. package/dist/backend/backend/src/websocket/file-watcher.gateway.js +202 -0
  1147. package/dist/backend/backend/src/websocket/file-watcher.gateway.js.map +1 -0
  1148. package/dist/backend/backend/src/websocket/terminal.gateway.d.ts +310 -0
  1149. package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -0
  1150. package/dist/backend/backend/src/websocket/terminal.gateway.js +980 -0
  1151. package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -0
  1152. package/dist/backend/config/constants.d.ts +722 -0
  1153. package/dist/backend/config/constants.d.ts.map +1 -0
  1154. package/dist/backend/config/constants.js +752 -0
  1155. package/dist/backend/config/constants.js.map +1 -0
  1156. package/dist/backend/config/index.d.ts +344 -0
  1157. package/dist/backend/config/index.d.ts.map +1 -0
  1158. package/dist/backend/config/index.js +42 -0
  1159. package/dist/backend/config/index.js.map +1 -0
  1160. package/dist/backend/config/quality-gates/default-gates.d.ts +71 -0
  1161. package/dist/backend/config/quality-gates/default-gates.d.ts.map +1 -0
  1162. package/dist/backend/config/quality-gates/default-gates.js +168 -0
  1163. package/dist/backend/config/quality-gates/default-gates.js.map +1 -0
  1164. package/dist/cli/cli/src/commands/logs.d.ts +7 -0
  1165. package/dist/cli/cli/src/commands/logs.d.ts.map +1 -0
  1166. package/dist/cli/cli/src/commands/logs.js +198 -0
  1167. package/dist/cli/cli/src/commands/logs.js.map +1 -0
  1168. package/dist/cli/cli/src/commands/start.d.ts +8 -0
  1169. package/dist/cli/cli/src/commands/start.d.ts.map +1 -0
  1170. package/dist/cli/cli/src/commands/start.js +254 -0
  1171. package/dist/cli/cli/src/commands/start.js.map +1 -0
  1172. package/dist/cli/cli/src/commands/status.d.ts +6 -0
  1173. package/dist/cli/cli/src/commands/status.d.ts.map +1 -0
  1174. package/dist/cli/cli/src/commands/status.js +130 -0
  1175. package/dist/cli/cli/src/commands/status.js.map +1 -0
  1176. package/dist/cli/cli/src/commands/stop.d.ts +6 -0
  1177. package/dist/cli/cli/src/commands/stop.d.ts.map +1 -0
  1178. package/dist/cli/cli/src/commands/stop.js +140 -0
  1179. package/dist/cli/cli/src/commands/stop.js.map +1 -0
  1180. package/dist/cli/cli/src/commands/upgrade.d.ts +26 -0
  1181. package/dist/cli/cli/src/commands/upgrade.d.ts.map +1 -0
  1182. package/dist/cli/cli/src/commands/upgrade.js +54 -0
  1183. package/dist/cli/cli/src/commands/upgrade.js.map +1 -0
  1184. package/dist/cli/cli/src/constants.d.ts +106 -0
  1185. package/dist/cli/cli/src/constants.d.ts.map +1 -0
  1186. package/dist/cli/cli/src/constants.js +88 -0
  1187. package/dist/cli/cli/src/constants.js.map +1 -0
  1188. package/dist/cli/cli/src/index.d.ts +3 -0
  1189. package/dist/cli/cli/src/index.d.ts.map +1 -0
  1190. package/dist/cli/cli/src/index.js +60 -0
  1191. package/dist/cli/cli/src/index.js.map +1 -0
  1192. package/dist/cli/cli/src/utils/version-check.d.ts +66 -0
  1193. package/dist/cli/cli/src/utils/version-check.d.ts.map +1 -0
  1194. package/dist/cli/cli/src/utils/version-check.js +192 -0
  1195. package/dist/cli/cli/src/utils/version-check.js.map +1 -0
  1196. package/dist/cli/config/constants.d.ts +722 -0
  1197. package/dist/cli/config/constants.d.ts.map +1 -0
  1198. package/dist/cli/config/constants.js +752 -0
  1199. package/dist/cli/config/constants.js.map +1 -0
  1200. package/dist/cli/config/index.d.ts +344 -0
  1201. package/dist/cli/config/index.d.ts.map +1 -0
  1202. package/dist/cli/config/index.js +42 -0
  1203. package/dist/cli/config/index.js.map +1 -0
  1204. package/frontend/dist/assets/index-5ddf71c8.css +33 -0
  1205. package/frontend/dist/assets/index-77b6a2a0.js +4919 -0
  1206. package/frontend/dist/index.html +19 -0
  1207. package/frontend/dist/logo/crewly-icon.svg +118 -0
  1208. package/package.json +121 -0
@@ -0,0 +1,2863 @@
1
+ import * as path from 'path';
2
+ import * as os from 'os';
3
+ import { readFile, readdir, stat, mkdir, writeFile } from 'fs/promises';
4
+ import { LoggerService } from '../core/logger.service.js';
5
+ import { createSessionCommandHelper, getSessionBackendSync, createSessionBackend, getSessionStatePersistence, } from '../session/index.js';
6
+ import { RuntimeServiceFactory } from './runtime-service.factory.js';
7
+ import { CREWLY_CONSTANTS, ENV_CONSTANTS, AGENT_TIMEOUTS, ORCHESTRATOR_ROLE, RUNTIME_TYPES, SESSION_COMMAND_DELAYS, EVENT_DELIVERY_CONSTANTS, TERMINAL_PATTERNS, GEMINI_SHELL_MODE_CONSTANTS, } from '../../constants.js';
8
+ import { WEB_CONSTANTS } from '../../../../config/constants.js';
9
+ import { delay } from '../../utils/async.utils.js';
10
+ import { getSettingsService } from '../settings/settings.service.js';
11
+ import { SessionMemoryService } from '../memory/session-memory.service.js';
12
+ import { RuntimeExitMonitorService } from './runtime-exit-monitor.service.js';
13
+ import { SubAgentMessageQueue } from '../messaging/sub-agent-message-queue.service.js';
14
+ import { AgentSuspendService } from './agent-suspend.service.js';
15
+ /**
16
+ * Service responsible for the complex, multi-step process of agent initialization and registration.
17
+ * Isolates the complex state management of agent startup with progressive escalation.
18
+ *
19
+ * Key capabilities:
20
+ * - Agent session creation and management
21
+ * - Runtime initialization and registration
22
+ * - Reliable message delivery to Claude Code with retry logic
23
+ * - Health checking and status management
24
+ */
25
+ export class AgentRegistrationService {
26
+ logger;
27
+ _sessionHelper = null;
28
+ storageService;
29
+ projectRoot;
30
+ // Prompt file caching to eliminate file I/O contention during concurrent session creation
31
+ promptCache = new Map();
32
+ // AbortControllers for pending registration prompts (keyed by session name)
33
+ registrationAbortControllers = new Map();
34
+ // Background stuck-message detector timer
35
+ stuckMessageDetectorTimer = null;
36
+ // Track TUI sessions for the stuck-message detector (sessionName → runtimeType)
37
+ tuiSessionRegistry = new Map();
38
+ // Track recently-sent messages for background stuck-detection (all runtimes).
39
+ // Key: sessionName, Value: array of tracked message entries
40
+ sentMessageTracker = new Map();
41
+ // Terminal patterns are now centralized in TERMINAL_PATTERNS constant
42
+ // Keeping these as static getters for backwards compatibility within the class
43
+ static get CLAUDE_PROMPT_INDICATORS() {
44
+ return TERMINAL_PATTERNS.PROMPT_CHARS;
45
+ }
46
+ static get CLAUDE_PROMPT_STREAM_PATTERN() {
47
+ return TERMINAL_PATTERNS.PROMPT_STREAM;
48
+ }
49
+ static get CLAUDE_PROCESSING_INDICATORS() {
50
+ return TERMINAL_PATTERNS.PROCESSING_INDICATORS;
51
+ }
52
+ constructor(_legacyTmuxService, // Legacy parameter for backwards compatibility
53
+ projectRoot, storageService) {
54
+ this.logger = LoggerService.getInstance().createComponentLogger('AgentRegistrationService');
55
+ this.storageService = storageService;
56
+ this.projectRoot = projectRoot || this.findProjectRoot();
57
+ // Wire up the exit monitor to cancel pending registrations on runtime exit
58
+ RuntimeExitMonitorService.getInstance().setOnExitDetectedCallback((sessionName) => {
59
+ this.cancelPendingRegistration(sessionName);
60
+ this.unregisterTuiSession(sessionName);
61
+ // Preserve queued messages for suspended agents (they'll be delivered on rehydrate)
62
+ if (!AgentSuspendService.getInstance().isSuspended(sessionName)) {
63
+ SubAgentMessageQueue.getInstance().clear(sessionName);
64
+ }
65
+ });
66
+ }
67
+ /**
68
+ * Cancel a pending registration prompt for a session.
69
+ * Called by RuntimeExitMonitorService when a runtime exit is detected.
70
+ *
71
+ * @param sessionName - The session whose registration to cancel
72
+ */
73
+ cancelPendingRegistration(sessionName) {
74
+ const controller = this.registrationAbortControllers.get(sessionName);
75
+ if (controller) {
76
+ controller.abort();
77
+ this.registrationAbortControllers.delete(sessionName);
78
+ this.logger.info('Cancelled pending registration', { sessionName });
79
+ }
80
+ }
81
+ /**
82
+ * Get or create the session helper with lazy initialization
83
+ */
84
+ async getSessionHelper() {
85
+ this.logger.debug('Getting session helper', {
86
+ hasExistingHelper: !!this._sessionHelper,
87
+ });
88
+ if (this._sessionHelper) {
89
+ return this._sessionHelper;
90
+ }
91
+ let backend = getSessionBackendSync();
92
+ this.logger.debug('Backend sync check', {
93
+ hasBackend: !!backend,
94
+ });
95
+ if (!backend) {
96
+ this.logger.info('Creating new PTY session backend');
97
+ backend = await createSessionBackend('pty');
98
+ this.logger.info('PTY session backend created', {
99
+ hasBackend: !!backend,
100
+ });
101
+ }
102
+ this._sessionHelper = createSessionCommandHelper(backend);
103
+ this.logger.debug('Session helper created');
104
+ return this._sessionHelper;
105
+ }
106
+ /**
107
+ * Get session helper synchronously (may throw if not initialized)
108
+ */
109
+ getSessionHelperSync() {
110
+ if (!this._sessionHelper) {
111
+ const backend = getSessionBackendSync();
112
+ if (!backend) {
113
+ throw new Error('Session backend not initialized');
114
+ }
115
+ this._sessionHelper = createSessionCommandHelper(backend);
116
+ }
117
+ return this._sessionHelper;
118
+ }
119
+ /**
120
+ * Find the project root by looking for package.json
121
+ */
122
+ findProjectRoot() {
123
+ // Simple fallback - could be improved to walk up directories
124
+ return process.cwd();
125
+ }
126
+ /**
127
+ * Resolve runtime flags from the agent's effective skills.
128
+ * Reads role config and skill configs to collect flags compatible with the runtime.
129
+ *
130
+ * @param role - The agent's role name
131
+ * @param runtimeType - The agent's runtime type (e.g. 'claude-code')
132
+ * @param skillOverrides - Additional skills assigned to the member
133
+ * @param excludedRoleSkills - Skills excluded from the role's default set
134
+ * @returns Array of CLI flags to inject (e.g. ['--chrome'])
135
+ */
136
+ async resolveRuntimeFlags(role, runtimeType, skillOverrides, excludedRoleSkills) {
137
+ const flags = new Set();
138
+ try {
139
+ // 1. Get role's assigned skills from config/roles/{role}/role.json
140
+ const roleName = role.toLowerCase().replace(/\s+/g, '-');
141
+ const rolePath = path.join(this.projectRoot, 'config', 'roles', roleName, 'role.json');
142
+ const roleContent = await readFile(rolePath, 'utf8');
143
+ const roleConfig = JSON.parse(roleContent);
144
+ const roleSkills = roleConfig.assignedSkills || [];
145
+ // 2. Apply skill overrides and exclusions
146
+ const effectiveSkills = new Set([...roleSkills, ...(skillOverrides || [])]);
147
+ for (const excluded of (excludedRoleSkills || [])) {
148
+ effectiveSkills.delete(excluded);
149
+ }
150
+ // 3. For each skill, read skill.json and collect flags matching runtime
151
+ for (const skillId of effectiveSkills) {
152
+ try {
153
+ const skillPath = path.join(this.projectRoot, 'config', 'skills', skillId, 'skill.json');
154
+ const skillContent = await readFile(skillPath, 'utf8');
155
+ const skillConfig = JSON.parse(skillContent);
156
+ if (skillConfig.runtime?.runtime === runtimeType && Array.isArray(skillConfig.runtime?.flags)) {
157
+ for (const flag of skillConfig.runtime.flags) {
158
+ flags.add(flag);
159
+ }
160
+ }
161
+ }
162
+ catch {
163
+ // Skill config not found — skip silently
164
+ }
165
+ }
166
+ if (flags.size > 0) {
167
+ this.logger.info('Resolved runtime flags from skills', {
168
+ role, runtimeType, flags: Array.from(flags),
169
+ });
170
+ }
171
+ }
172
+ catch (error) {
173
+ this.logger.debug('Could not resolve runtime flags (no role config or read error)', {
174
+ role, runtimeType, error: error instanceof Error ? error.message : String(error),
175
+ });
176
+ }
177
+ return Array.from(flags);
178
+ }
179
+ /**
180
+ * Create a runtime service instance for the given runtime type.
181
+ * Centralizes RuntimeServiceFactory creation to reduce code duplication.
182
+ */
183
+ createRuntimeService(runtimeType) {
184
+ return RuntimeServiceFactory.create(runtimeType, null, this.projectRoot);
185
+ }
186
+ /**
187
+ * Get the check interval based on environment.
188
+ * Uses shorter intervals in test environment for faster tests.
189
+ */
190
+ getCheckInterval() {
191
+ return process.env.NODE_ENV === 'test' ? 1000 : 2000;
192
+ }
193
+ /**
194
+ * Update agent status with safe error handling (non-blocking).
195
+ * Returns true if successful, false if failed.
196
+ */
197
+ async updateAgentStatusSafe(sessionName, status, context) {
198
+ try {
199
+ await this.storageService.updateAgentStatus(sessionName, status);
200
+ this.logger.info(`Agent status updated to ${status}`, { sessionName, ...context });
201
+ return true;
202
+ }
203
+ catch (error) {
204
+ this.logger.warn('Failed to update agent status (non-critical)', {
205
+ sessionName,
206
+ error: error instanceof Error ? error.message : String(error),
207
+ });
208
+ return false;
209
+ }
210
+ }
211
+ /**
212
+ * Get prompt file path for a specific role
213
+ * Uses the unified config/roles/{role}/prompt.md structure
214
+ */
215
+ async getPromptFileForRole(role) {
216
+ // Normalize role name to directory name format
217
+ const roleName = role.toLowerCase().replace(/\s+/g, '-');
218
+ return path.join(process.cwd(), 'config', 'roles', roleName, 'prompt.md');
219
+ }
220
+ /**
221
+ * Initialize agent with optimized 2-step escalation process
222
+ * Reduced from 4-step to 2-step with shorter timeouts for better concurrency
223
+ */
224
+ async initializeAgentWithRegistration(sessionName, role, projectPath, timeout = AGENT_TIMEOUTS.REGULAR_AGENT_INITIALIZATION, memberId, runtimeType = RUNTIME_TYPES.CLAUDE_CODE, runtimeFlags) {
225
+ const startTime = Date.now();
226
+ this.logger.info('Starting optimized agent initialization with registration', {
227
+ sessionName,
228
+ role,
229
+ timeout,
230
+ runtimeType,
231
+ });
232
+ // PHASE 4: agentStatus is now set immediately in API endpoints (startTeam/startTeamMember)
233
+ // No longer need to set it here - focus only on session creation
234
+ this.logger.info('Starting agent session initialization', { sessionName, role });
235
+ // Clear detection cache to ensure fresh runtime detection
236
+ const runtimeService = this.createRuntimeService(runtimeType);
237
+ runtimeService.clearDetectionCache(sessionName);
238
+ // Skip Step 1 (direct registration) as it often fails in concurrent scenarios
239
+ // Go directly to Step 2: Cleanup + reinit (more reliable)
240
+ try {
241
+ this.logger.info('Step 1: Attempting cleanup and reinitialization', {
242
+ sessionName,
243
+ });
244
+ const step1Success = await this.tryCleanupAndReinit(sessionName, role, 40000, // 40 seconds for cleanup and reinit
245
+ projectPath, memberId, runtimeType, runtimeFlags);
246
+ if (step1Success) {
247
+ return {
248
+ success: true,
249
+ message: 'Agent registered successfully after cleanup and reinit',
250
+ };
251
+ }
252
+ }
253
+ catch (error) {
254
+ this.logger.warn('Step 1 (cleanup + reinit) failed', {
255
+ sessionName,
256
+ error: error instanceof Error ? error.message : String(error),
257
+ });
258
+ }
259
+ // Step 2: Full session recreation (30 seconds) - only if time remaining
260
+ if (Date.now() - startTime < timeout - 35000) {
261
+ try {
262
+ this.logger.info('Step 2: Attempting full session recreation', { sessionName });
263
+ const step2Success = await this.tryFullRecreation(sessionName, role, 30000, // Reduced from 45000 to 30000
264
+ projectPath, memberId, runtimeType, runtimeFlags);
265
+ if (step2Success) {
266
+ return {
267
+ success: true,
268
+ message: 'Agent registered successfully after full recreation',
269
+ };
270
+ }
271
+ }
272
+ catch (error) {
273
+ this.logger.warn('Step 2 (full recreation) failed', {
274
+ sessionName,
275
+ error: error instanceof Error ? error.message : String(error),
276
+ });
277
+ }
278
+ }
279
+ // Give up after 2 steps
280
+ const errorMsg = `Failed to initialize agent after optimized escalation attempts (${Math.round((Date.now() - startTime) / 1000)}s)`;
281
+ this.logger.error(errorMsg, { sessionName, role });
282
+ return { success: false, error: errorMsg };
283
+ }
284
+ /**
285
+ * Step 1: Try direct registration prompt
286
+ * Assumes Claude is already running and just needs a registration prompt
287
+ */
288
+ async tryDirectRegistration(sessionName, role, timeout, memberId, runtimeType = RUNTIME_TYPES.CLAUDE_CODE) {
289
+ // Clear any existing input. Claude already performs Ctrl+C cleanup during
290
+ // runtime detection, so avoid sending additional Ctrl+C sequences.
291
+ // Gemini CLI: Skip cleanup — Ctrl+C at an empty prompt triggers /quit.
292
+ // Escape defocuses the TUI. Ctrl+U is ignored by the TUI.
293
+ const helper = await this.getSessionHelper();
294
+ // First check if runtime is running before sending the prompt
295
+ // runtimeService2: Separate instance for pre-registration runtime detection
296
+ // This instance is isolated from main runtimeService to avoid cache interference
297
+ const runtimeService2 = this.createRuntimeService(runtimeType);
298
+ const runtimeRunning = await runtimeService2.detectRuntimeWithCommand(sessionName);
299
+ if (!runtimeRunning) {
300
+ this.logger.debug('Runtime not detected in Step 1, skipping direct registration', {
301
+ sessionName,
302
+ runtimeType,
303
+ });
304
+ return false;
305
+ }
306
+ this.logger.debug('Runtime detected, sending registration prompt', {
307
+ sessionName,
308
+ runtimeType,
309
+ });
310
+ // Clear any pending slash command from detection. Claude detection already
311
+ // exits slash mode. Gemini CLI: skip — Ctrl+C at empty prompt exits CLI,
312
+ // Escape defocuses TUI, Ctrl+U is ignored. The prompt should be clean.
313
+ const prompt = await this.loadRegistrationPrompt(role, sessionName, memberId);
314
+ const promptDelivered = await this.sendPromptRobustly(sessionName, prompt, runtimeType);
315
+ if (!promptDelivered) {
316
+ this.logger.warn('Failed to deliver registration prompt', { sessionName, role });
317
+ return false;
318
+ }
319
+ return await this.waitForRegistration(sessionName, role, timeout);
320
+ }
321
+ /**
322
+ * Step 2: Cleanup with Ctrl+C and reinitialize
323
+ * Tries to reset the runtime session and start fresh
324
+ */
325
+ async tryCleanupAndReinit(sessionName, role, timeout, projectPath, memberId, runtimeType = RUNTIME_TYPES.CLAUDE_CODE, runtimeFlags) {
326
+ // Clear Commandline
327
+ await (await this.getSessionHelper()).clearCurrentCommandLine(sessionName);
328
+ // Inject --resume flag if this was a previously running Claude Code session
329
+ const effectiveFlags = runtimeFlags ? [...runtimeFlags] : [];
330
+ if (runtimeType === RUNTIME_TYPES.CLAUDE_CODE) {
331
+ try {
332
+ const settings = await getSettingsService().getSettings();
333
+ if (settings.general.autoResumeOnRestart) {
334
+ const persistence = getSessionStatePersistence();
335
+ if (persistence.isRestoredSession(sessionName)) {
336
+ const storedSessionId = persistence.getSessionId(sessionName);
337
+ if (storedSessionId) {
338
+ effectiveFlags.push('--resume', storedSessionId);
339
+ this.logger.info('Injecting --resume flag for session restore', {
340
+ sessionName, sessionId: storedSessionId,
341
+ });
342
+ }
343
+ }
344
+ }
345
+ else {
346
+ this.logger.info('Auto-resume disabled by settings, skipping session resume', { sessionName });
347
+ }
348
+ }
349
+ catch (resumeError) {
350
+ this.logger.debug('Could not resolve resume flag (non-fatal)', {
351
+ sessionName, error: resumeError instanceof Error ? resumeError.message : String(resumeError),
352
+ });
353
+ }
354
+ }
355
+ // Reinitialize runtime using the appropriate initialization script (always fresh start)
356
+ // runtimeService2: Fresh instance for runtime reinitialization after cleanup
357
+ // New instance ensures clean state without cached detection results
358
+ const runtimeService2 = this.createRuntimeService(runtimeType);
359
+ await runtimeService2.executeRuntimeInitScript(sessionName, projectPath, effectiveFlags);
360
+ // Wait for runtime to be ready (simplified detection)
361
+ // Use shorter check interval in test environment, and reasonable interval in production
362
+ const checkInterval = process.env.NODE_ENV === 'test' ? 1000 : 2000; // Check every 1-2 seconds
363
+ const isReady = await runtimeService2.waitForRuntimeReady(sessionName, 30000, checkInterval); // 30s timeout
364
+ if (!isReady) {
365
+ throw new Error(`Failed to reinitialize ${runtimeType} within timeout`);
366
+ }
367
+ // Start runtime exit monitoring IMMEDIATELY after runtime is ready.
368
+ // Must be before postInitialize and sendRegistrationPromptAsync so exits
369
+ // during those phases are detected and the abort signal fires in time.
370
+ RuntimeExitMonitorService.getInstance().startMonitoring(sessionName, runtimeType, role);
371
+ // Run post-initialization hook (e.g., Gemini CLI directory allowlist)
372
+ try {
373
+ await runtimeService2.postInitialize(sessionName, projectPath);
374
+ // Drain stale terminal escape sequences (e.g. DA1 [?1;2c) that may have
375
+ // arrived during postInitialize commands, so they don't leak into the prompt input
376
+ await delay(500);
377
+ // Clear any pending input after post-initialization.
378
+ // Claude Code: Ctrl+C + Ctrl+U (clearCurrentCommandLine) — standard cleanup.
379
+ // Gemini CLI: Skip cleanup entirely — the TUI just started with a clean
380
+ // prompt. Ctrl+C at an empty Gemini CLI prompt triggers /quit and exits
381
+ // the CLI. Escape defocuses the TUI. Ctrl+U is ignored. The delay(500)
382
+ // above is sufficient to drain stale escape sequences.
383
+ if (runtimeType === RUNTIME_TYPES.CLAUDE_CODE) {
384
+ await (await this.getSessionHelper()).clearCurrentCommandLine(sessionName);
385
+ }
386
+ }
387
+ catch (postInitError) {
388
+ this.logger.warn('Post-initialization hook failed (non-fatal)', {
389
+ sessionName,
390
+ runtimeType,
391
+ error: postInitError instanceof Error ? postInitError.message : String(postInitError),
392
+ });
393
+ }
394
+ // For PTY sessions, once runtime is detected as ready, consider initialization successful
395
+ // MCP registration will happen async when the agent processes its first prompt
396
+ this.logger.info('Runtime detected as ready, session initialization successful', {
397
+ sessionName,
398
+ role,
399
+ runtimeType,
400
+ });
401
+ // Background: detect and store session ID for resume-on-restart
402
+ if (runtimeType === RUNTIME_TYPES.CLAUDE_CODE) {
403
+ const detectPath = projectPath || process.cwd();
404
+ setTimeout(() => {
405
+ this.detectAndStoreSessionId(sessionName, detectPath).catch(() => { });
406
+ }, 10000);
407
+ }
408
+ // Send the registration prompt in background (don't block on it)
409
+ this.sendRegistrationPromptAsync(sessionName, role, memberId, runtimeType).catch((err) => {
410
+ this.logger.warn('Background registration prompt failed (non-blocking)', {
411
+ sessionName,
412
+ error: err instanceof Error ? err.message : String(err),
413
+ });
414
+ });
415
+ // Update agent status to 'started' since the runtime is running
416
+ // The agent will become 'active' only after it registers via the API endpoint
417
+ try {
418
+ await this.storageService.updateAgentStatus(sessionName, CREWLY_CONSTANTS.AGENT_STATUSES.STARTED);
419
+ this.logger.info('Agent status updated to started (runtime running, awaiting registration)', { sessionName, role });
420
+ }
421
+ catch (statusError) {
422
+ this.logger.warn('Failed to update agent status (non-critical)', {
423
+ sessionName,
424
+ error: statusError instanceof Error ? statusError.message : String(statusError),
425
+ });
426
+ }
427
+ return true;
428
+ }
429
+ /**
430
+ * Detect and store the Claude Code session ID by scanning the filesystem.
431
+ * Claude Code stores conversations as <UUID>.jsonl files in
432
+ * ~/.claude/projects/<path-slug>/ where path-slug is the absolute
433
+ * project path with / replaced by -.
434
+ *
435
+ * Runs in background after agent init to capture the session ID
436
+ * for resume-on-restart support.
437
+ *
438
+ * @param sessionName - PTY session name
439
+ * @param projectPath - Absolute path to the agent's project directory
440
+ */
441
+ async detectAndStoreSessionId(sessionName, projectPath) {
442
+ try {
443
+ const slug = projectPath.replace(/\//g, '-');
444
+ const claudeProjectDir = path.join(os.homedir(), '.claude', 'projects', slug);
445
+ const files = await readdir(claudeProjectDir);
446
+ const jsonlFiles = files.filter(f => f.endsWith('.jsonl'));
447
+ if (jsonlFiles.length === 0)
448
+ return;
449
+ // Find most recent .jsonl by mtime
450
+ let latestFile = '';
451
+ let latestMtime = 0;
452
+ for (const file of jsonlFiles) {
453
+ const fileStat = await stat(path.join(claudeProjectDir, file));
454
+ if (fileStat.mtimeMs > latestMtime) {
455
+ latestMtime = fileStat.mtimeMs;
456
+ latestFile = file;
457
+ }
458
+ }
459
+ if (!latestFile)
460
+ return;
461
+ // Extract UUID from filename (remove .jsonl extension)
462
+ const sessionId = latestFile.replace('.jsonl', '');
463
+ const persistence = getSessionStatePersistence();
464
+ persistence.updateSessionId(sessionName, sessionId);
465
+ this.logger.info('Detected and stored Claude session ID from filesystem', {
466
+ sessionName,
467
+ sessionId,
468
+ claudeProjectDir,
469
+ });
470
+ }
471
+ catch (error) {
472
+ this.logger.debug('Could not detect Claude session ID from filesystem (non-fatal)', {
473
+ sessionName,
474
+ error: error instanceof Error ? error.message : String(error),
475
+ });
476
+ }
477
+ }
478
+ /**
479
+ * Send registration prompt asynchronously (non-blocking).
480
+ * Uses an AbortController so the operation can be cancelled if the
481
+ * runtime exits before registration completes.
482
+ */
483
+ async sendRegistrationPromptAsync(sessionName, role, memberId, runtimeType = RUNTIME_TYPES.CLAUDE_CODE) {
484
+ // Create AbortController for this registration
485
+ const controller = new AbortController();
486
+ this.registrationAbortControllers.set(sessionName, controller);
487
+ try {
488
+ if (controller.signal.aborted)
489
+ return;
490
+ const prompt = await this.loadRegistrationPrompt(role, sessionName, memberId);
491
+ if (controller.signal.aborted)
492
+ return;
493
+ await this.sendPromptRobustly(sessionName, prompt, runtimeType, controller.signal);
494
+ this.logger.debug('Registration prompt sent asynchronously', { sessionName, role });
495
+ }
496
+ catch (error) {
497
+ if (controller.signal.aborted) {
498
+ this.logger.info('Registration prompt cancelled (runtime exited)', { sessionName });
499
+ return;
500
+ }
501
+ this.logger.warn('Failed to send registration prompt asynchronously', {
502
+ sessionName,
503
+ error: error instanceof Error ? error.message : String(error),
504
+ });
505
+ }
506
+ finally {
507
+ this.registrationAbortControllers.delete(sessionName);
508
+ }
509
+ }
510
+ /**
511
+ * Step 3: Kill session and recreate completely
512
+ * Most aggressive approach - completely recreates the session from scratch
513
+ */
514
+ async tryFullRecreation(sessionName, role, timeout, projectPath, memberId, runtimeType = RUNTIME_TYPES.CLAUDE_CODE, runtimeFlags) {
515
+ // Kill existing session
516
+ await (await this.getSessionHelper()).killSession(sessionName);
517
+ // Wait for cleanup
518
+ await delay(1000);
519
+ // Inject --resume flag if this was a previously running Claude Code session
520
+ const effectiveFlags = runtimeFlags ? [...runtimeFlags] : [];
521
+ if (runtimeType === RUNTIME_TYPES.CLAUDE_CODE) {
522
+ try {
523
+ const settings = await getSettingsService().getSettings();
524
+ if (settings.general.autoResumeOnRestart) {
525
+ const persistence = getSessionStatePersistence();
526
+ if (persistence.isRestoredSession(sessionName)) {
527
+ const storedSessionId = persistence.getSessionId(sessionName);
528
+ if (storedSessionId) {
529
+ effectiveFlags.push('--resume', storedSessionId);
530
+ this.logger.info('Injecting --resume flag for session restore (full recreation)', {
531
+ sessionName, sessionId: storedSessionId,
532
+ });
533
+ }
534
+ }
535
+ }
536
+ else {
537
+ this.logger.info('Auto-resume disabled by settings, skipping session resume after recreation', { sessionName });
538
+ }
539
+ }
540
+ catch (resumeError) {
541
+ this.logger.debug('Could not resolve resume flag (non-fatal)', {
542
+ sessionName, error: resumeError instanceof Error ? resumeError.message : String(resumeError),
543
+ });
544
+ }
545
+ }
546
+ // Recreate session based on role
547
+ if (role === ORCHESTRATOR_ROLE) {
548
+ await this.createOrchestratorSession({
549
+ sessionName,
550
+ projectPath: projectPath || process.cwd(),
551
+ });
552
+ // Initialize runtime for orchestrator using script (always fresh start)
553
+ const runtimeService = this.createRuntimeService(runtimeType);
554
+ await runtimeService.executeRuntimeInitScript(sessionName, process.cwd(), effectiveFlags);
555
+ // Wait for runtime to be ready
556
+ const checkInterval = this.getCheckInterval();
557
+ // runtimeService3: Separate instance for orchestrator ready-state detection
558
+ // Isolated from runtimeService to prevent interference between init and ready checks
559
+ const runtimeService3 = this.createRuntimeService(runtimeType);
560
+ const isReady = await runtimeService3.waitForRuntimeReady(sessionName, 45000, checkInterval);
561
+ if (!isReady) {
562
+ throw new Error(`Failed to initialize ${runtimeType} in recreated orchestrator session within timeout`);
563
+ }
564
+ // Start runtime exit monitoring immediately after runtime is ready
565
+ RuntimeExitMonitorService.getInstance().startMonitoring(sessionName, runtimeType, role);
566
+ // Additional verification: Use runtime detection to confirm runtime is responding
567
+ // Wait a bit longer for runtime to fully load after showing welcome message
568
+ this.logger.debug('Runtime ready detected for orchestrator, waiting for full startup before verification', { sessionName, runtimeType });
569
+ await delay(5000);
570
+ this.logger.debug('Verifying orchestrator runtime responsiveness', {
571
+ sessionName,
572
+ runtimeType,
573
+ });
574
+ // runtimeService4: Final verification instance for orchestrator responsiveness
575
+ // Clean instance for post-initialization responsiveness testing
576
+ const runtimeService4 = this.createRuntimeService(runtimeType);
577
+ const runtimeResponding = await runtimeService4.detectRuntimeWithCommand(sessionName);
578
+ if (!runtimeResponding) {
579
+ throw new Error(`${runtimeType} not responding to commands after orchestrator recreation`);
580
+ }
581
+ this.logger.debug('Runtime confirmed ready for orchestrator in Step 3', { sessionName, runtimeType });
582
+ }
583
+ else {
584
+ // For other roles, create basic session and initialize Claude (always fresh start)
585
+ await (await this.getSessionHelper()).createSession(sessionName, projectPath || process.cwd());
586
+ const runtimeService = this.createRuntimeService(runtimeType);
587
+ await runtimeService.executeRuntimeInitScript(sessionName, projectPath, effectiveFlags);
588
+ // Wait for runtime to be ready (simplified detection)
589
+ const checkInterval = this.getCheckInterval();
590
+ const isReady = await this.createRuntimeService(runtimeType)
591
+ .waitForRuntimeReady(sessionName, 25000, checkInterval); // 25s timeout
592
+ if (!isReady) {
593
+ throw new Error(`Failed to initialize ${runtimeType} in recreated session within timeout`);
594
+ }
595
+ // Start runtime exit monitoring immediately after runtime is ready
596
+ RuntimeExitMonitorService.getInstance().startMonitoring(sessionName, runtimeType, role);
597
+ }
598
+ // Run post-initialization hook (e.g., Gemini CLI directory allowlist)
599
+ try {
600
+ const postInitService = this.createRuntimeService(runtimeType);
601
+ await postInitService.postInitialize(sessionName, projectPath);
602
+ // Drain stale terminal escape sequences (e.g. DA1 [?1;2c) that may have
603
+ // arrived during postInitialize commands, so they don't leak into the prompt input
604
+ await delay(500);
605
+ // Claude Code: Ctrl+C + Ctrl+U to clear any stale input.
606
+ // Gemini CLI (Ink TUI): Do NOT send any cleanup keystrokes.
607
+ // Escape defocuses the Ink TUI input permanently. Ctrl+C at empty
608
+ // prompt triggers /quit. Ctrl+U is ignored. The delay above is
609
+ // sufficient to drain stale escape sequences.
610
+ if (runtimeType === RUNTIME_TYPES.CLAUDE_CODE) {
611
+ await (await this.getSessionHelper()).clearCurrentCommandLine(sessionName);
612
+ }
613
+ }
614
+ catch (postInitError) {
615
+ this.logger.warn('Post-initialization hook failed after recreation (non-fatal)', {
616
+ sessionName,
617
+ runtimeType,
618
+ error: postInitError instanceof Error ? postInitError.message : String(postInitError),
619
+ });
620
+ }
621
+ // For PTY sessions, once runtime is detected as ready, consider initialization successful
622
+ this.logger.info('Runtime detected as ready after full recreation, session initialization successful', {
623
+ sessionName,
624
+ role,
625
+ runtimeType,
626
+ });
627
+ // Background: detect and store session ID for resume-on-restart
628
+ if (runtimeType === RUNTIME_TYPES.CLAUDE_CODE) {
629
+ const detectPath = projectPath || process.cwd();
630
+ setTimeout(() => {
631
+ this.detectAndStoreSessionId(sessionName, detectPath).catch(() => { });
632
+ }, 10000);
633
+ }
634
+ // Send the registration prompt in background (don't block on it)
635
+ this.sendRegistrationPromptAsync(sessionName, role, memberId, runtimeType).catch((err) => {
636
+ this.logger.warn('Background registration prompt failed after recreation (non-blocking)', {
637
+ sessionName,
638
+ error: err instanceof Error ? err.message : String(err),
639
+ });
640
+ });
641
+ // Update agent status to 'started' since the runtime is running
642
+ // The agent will become 'active' only after it registers via the API endpoint
643
+ try {
644
+ await this.storageService.updateAgentStatus(sessionName, CREWLY_CONSTANTS.AGENT_STATUSES.STARTED);
645
+ this.logger.info('Agent status updated to started after recreation (awaiting registration)', { sessionName, role });
646
+ }
647
+ catch (statusError) {
648
+ this.logger.warn('Failed to update agent status after recreation (non-critical)', {
649
+ sessionName,
650
+ error: statusError instanceof Error ? statusError.message : String(statusError),
651
+ });
652
+ }
653
+ return true;
654
+ }
655
+ /**
656
+ * Load registration prompt from config files (with caching to prevent file I/O contention)
657
+ */
658
+ async loadRegistrationPrompt(role, sessionName, memberId) {
659
+ try {
660
+ // Cache key is role only - the template file is the same regardless of memberId
661
+ const cacheKey = role;
662
+ // Check cache first to avoid file I/O during concurrent operations
663
+ if (!this.promptCache.has(cacheKey)) {
664
+ this.logger.debug('Loading prompt template from file', { role, cacheKey });
665
+ // Get the prompt file path from team roles configuration
666
+ const promptPath = await this.getPromptFileForRole(role);
667
+ const promptTemplate = await readFile(promptPath, 'utf8');
668
+ this.promptCache.set(cacheKey, promptTemplate);
669
+ this.logger.debug('Prompt template cached', { role, cacheKey, promptPath });
670
+ }
671
+ else {
672
+ this.logger.debug('Using cached prompt template', { role, cacheKey });
673
+ }
674
+ // Get cached template and apply variable replacements
675
+ let prompt = this.promptCache.get(cacheKey);
676
+ // Replace all template placeholders
677
+ prompt = prompt.replace(/\{\{SESSION_ID\}\}/g, sessionName);
678
+ prompt = prompt.replace(/\{\{SESSION_NAME\}\}/g, sessionName);
679
+ prompt = prompt.replace(/\{\{ROLE\}\}/g, role);
680
+ if (memberId) {
681
+ prompt = prompt.replace(/\{\{MEMBER_ID\}\}/g, memberId);
682
+ }
683
+ else {
684
+ // For orchestrator or cases without member ID, remove the memberId parameter
685
+ prompt = prompt.replace(/,\s*"memberId":\s*"\{\{MEMBER_ID\}\}"/g, '');
686
+ }
687
+ // Look up project path for team members
688
+ let projectPath = process.cwd();
689
+ try {
690
+ const teams = await this.storageService.getTeams();
691
+ for (const team of teams) {
692
+ const member = team.members?.find((m) => m.sessionName === sessionName);
693
+ if (member && team.projectIds[0]) {
694
+ const projects = await this.storageService.getProjects();
695
+ const project = projects.find((p) => p.id === team.projectIds[0]);
696
+ if (project?.path) {
697
+ projectPath = project.path;
698
+ }
699
+ break;
700
+ }
701
+ }
702
+ }
703
+ catch {
704
+ // Non-critical - use default project path
705
+ }
706
+ // Replace project path placeholder (must happen after project path lookup above)
707
+ prompt = prompt.replace(/\{\{PROJECT_PATH\}\}/g, projectPath);
708
+ // Replace agent skills path placeholder
709
+ const agentSkillsPath = path.join(this.projectRoot, 'config', 'skills', 'agent');
710
+ prompt = prompt.replace(/\{\{AGENT_SKILLS_PATH\}\}/g, agentSkillsPath);
711
+ // Generate and inject startup briefing from session memory
712
+ try {
713
+ const sessionMemoryService = SessionMemoryService.getInstance();
714
+ await sessionMemoryService.onSessionStart(sessionName, role, projectPath);
715
+ const briefing = await sessionMemoryService.generateStartupBriefing(sessionName, role, projectPath);
716
+ const briefingMd = sessionMemoryService.formatBriefingAsMarkdown(briefing);
717
+ if (briefingMd && briefingMd.length > 30) {
718
+ prompt += `\n\n---\n\n${briefingMd}`;
719
+ this.logger.info('Startup briefing injected into prompt', { sessionName, role, briefingLength: briefingMd.length });
720
+ }
721
+ }
722
+ catch (briefingError) {
723
+ this.logger.warn('Failed to generate startup briefing (non-critical)', {
724
+ sessionName,
725
+ error: briefingError instanceof Error ? briefingError.message : String(briefingError),
726
+ });
727
+ }
728
+ // Append identity section so the agent knows its session name and project path
729
+ prompt += `\n\n---\n\n## Your Identity\n- **Session Name:** ${sessionName}\n- **Project Path:** ${projectPath}`;
730
+ if (memberId) {
731
+ prompt += `\n- **Member ID:** ${memberId}`;
732
+ }
733
+ return prompt;
734
+ }
735
+ catch (error) {
736
+ // Fallback to inline prompt if file doesn't exist
737
+ const attemptedPath = await this.getPromptFileForRole(role);
738
+ this.logger.error('Could not load prompt from config, using fallback', {
739
+ role,
740
+ promptPath: attemptedPath,
741
+ error: error instanceof Error ? error.message : String(error),
742
+ stack: error instanceof Error ? error.stack : undefined,
743
+ });
744
+ const memberIdJson = memberId ? `,"teamMemberId":"${memberId}"` : '';
745
+ const skillsPath = path.join(this.projectRoot, 'config', 'skills', 'agent');
746
+ return `Hey! I need your help with some tasks on this project.
747
+
748
+ ## Quick context about this setup
749
+
750
+ This project uses Crewly for team coordination. You have bash skills available at \`${skillsPath}/\` that communicate with the Crewly backend running locally. Read the skills catalog at \`~/.crewly/skills/AGENT_SKILLS_CATALOG.md\` for a full reference of available skills.
751
+
752
+ ## First thing - please check in
753
+
754
+ Please run the register-self skill to let the team dashboard know you're available:
755
+ \`\`\`bash
756
+ bash ${skillsPath}/register-self/execute.sh '{"role":"${role}","sessionName":"${sessionName}"${memberIdJson}}'
757
+ \`\`\`
758
+ All it does is update a local status flag so the web UI shows you as online - nothing more.
759
+
760
+ After checking in, just say "Ready for tasks" and wait for me to send you work.`;
761
+ }
762
+ }
763
+ /**
764
+ * Wait for agent registration to complete
765
+ */
766
+ async waitForRegistration(sessionName, role, timeout) {
767
+ const startTime = Date.now();
768
+ const checkInterval = 5000; // Check every 5 seconds to prevent overlapping with `/` detection
769
+ while (Date.now() - startTime < timeout) {
770
+ try {
771
+ if (await this.checkAgentRegistration(sessionName, role)) {
772
+ this.logger.info('Agent registration confirmed', { sessionName, role });
773
+ return true;
774
+ }
775
+ await delay(checkInterval);
776
+ }
777
+ catch (error) {
778
+ this.logger.warn('Error checking registration', {
779
+ sessionName,
780
+ role,
781
+ error: error instanceof Error ? error.message : String(error),
782
+ });
783
+ await delay(checkInterval);
784
+ }
785
+ }
786
+ this.logger.warn('Timeout waiting for agent registration', { sessionName, role, timeout });
787
+ return false;
788
+ }
789
+ /**
790
+ * Check if agent is properly registered
791
+ */
792
+ async checkAgentRegistration(sessionName, role) {
793
+ try {
794
+ if (role === ORCHESTRATOR_ROLE) {
795
+ // For orchestrator, check agentStatus is active
796
+ const orchestratorStatus = await this.storageService.getOrchestratorStatus();
797
+ return orchestratorStatus?.agentStatus === CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE;
798
+ }
799
+ // For team members, check teams data
800
+ const teams = await this.storageService.getTeams();
801
+ // Find team member with matching sessionName and check agentStatus
802
+ for (const team of teams) {
803
+ if (team.members) {
804
+ for (const member of team.members) {
805
+ if (member.sessionName === sessionName && member.role === role) {
806
+ return member.agentStatus === CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE;
807
+ }
808
+ }
809
+ }
810
+ }
811
+ return false;
812
+ }
813
+ catch (error) {
814
+ this.logger.debug('Error checking agent registration', {
815
+ sessionName,
816
+ role,
817
+ error: error instanceof Error ? error.message : String(error),
818
+ });
819
+ return false;
820
+ }
821
+ }
822
+ /**
823
+ * Fast registration with verification and retry mechanism
824
+ * Sends system prompt to runtime which triggers MCP registration via teams.json
825
+ * @param skipInitialCleanup If true, skips Ctrl+C on first attempt (when runtime was just initialized)
826
+ */
827
+ async attemptRegistrationWithVerification(sessionName, role, timeout, memberId, maxRetries = 3, skipInitialCleanup = false, runtimeType = RUNTIME_TYPES.CLAUDE_CODE) {
828
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
829
+ this.logger.info('Attempting system prompt registration with MCP flow', {
830
+ sessionName,
831
+ role,
832
+ runtimeType,
833
+ attempt,
834
+ maxRetries,
835
+ });
836
+ try {
837
+ // Step 1: Send Ctrl+C to clear any pending commands (skip on first attempt if Claude was just initialized)
838
+ if (!skipInitialCleanup || attempt > 1) {
839
+ await (await this.getSessionHelper()).clearCurrentCommandLine(sessionName);
840
+ await delay(500);
841
+ this.logger.debug('Sent Ctrl+C to clear terminal state', {
842
+ sessionName,
843
+ attempt,
844
+ });
845
+ }
846
+ else {
847
+ this.logger.debug('Skipping Ctrl+C on first attempt (Claude was just initialized)', { sessionName, attempt });
848
+ }
849
+ // Step 2: Verify runtime is running (skip detection if runtime was just initialized and verified)
850
+ let runtimeRunning = true; // Assume true if we skip detection
851
+ if (!skipInitialCleanup || attempt > 1) {
852
+ // Only do runtime detection on retries or when runtime wasn't just initialized
853
+ const forceRefresh = attempt > 1; // Force refresh on retry attempts
854
+ const runtimeService5 = this.createRuntimeService(runtimeType);
855
+ runtimeRunning = await runtimeService5.detectRuntimeWithCommand(sessionName, forceRefresh);
856
+ if (!runtimeRunning) {
857
+ this.logger.warn('Runtime not detected, cannot send system prompt', {
858
+ sessionName,
859
+ runtimeType,
860
+ attempt,
861
+ forceRefresh,
862
+ });
863
+ // Clear detection cache before continuing to retry
864
+ const runtimeService6 = this.createRuntimeService(runtimeType);
865
+ runtimeService6.clearDetectionCache(sessionName);
866
+ // Add longer delay between failed detection attempts
867
+ if (attempt < maxRetries) {
868
+ await delay(2000);
869
+ }
870
+ continue; // Try again
871
+ }
872
+ }
873
+ else {
874
+ this.logger.debug('Skipping runtime detection (runtime was just initialized and verified)', {
875
+ sessionName,
876
+ runtimeType,
877
+ attempt,
878
+ });
879
+ }
880
+ // Step 3: Send system prompt with robust delivery mechanism
881
+ const prompt = await this.loadRegistrationPrompt(role, sessionName, memberId);
882
+ const promptDelivered = await this.sendPromptRobustly(sessionName, prompt, runtimeType);
883
+ if (!promptDelivered) {
884
+ this.logger.warn('Failed to deliver system prompt reliably', {
885
+ sessionName,
886
+ attempt,
887
+ promptLength: prompt.length,
888
+ });
889
+ continue; // Try again
890
+ }
891
+ this.logger.debug('System prompt delivered successfully', {
892
+ sessionName,
893
+ promptLength: prompt.length,
894
+ });
895
+ this.logger.debug('Terminal activity detected, waiting for MCP registration', {
896
+ sessionName,
897
+ });
898
+ // Step 5: Wait for registration API call to update teams.json (agentStatus: activating -> active)
899
+ const registrationTimeout = Math.min(timeout, 25000); // Max 25s per attempt
900
+ const registered = await this.waitForRegistrationFast(sessionName, role, registrationTimeout);
901
+ if (registered) {
902
+ this.logger.info('MCP registration successful (teams.json updated)', {
903
+ sessionName,
904
+ role,
905
+ attempt,
906
+ });
907
+ return true;
908
+ }
909
+ this.logger.warn('MCP registration timeout, retrying', {
910
+ sessionName,
911
+ role,
912
+ attempt,
913
+ nextAttempt: attempt < maxRetries,
914
+ });
915
+ }
916
+ catch (error) {
917
+ this.logger.error('System prompt registration attempt failed', {
918
+ sessionName,
919
+ role,
920
+ attempt,
921
+ error: error instanceof Error ? error.message : String(error),
922
+ });
923
+ }
924
+ // Short delay before retry
925
+ if (attempt < maxRetries) {
926
+ await delay(1000);
927
+ }
928
+ }
929
+ this.logger.error('All runtime registration attempts failed', {
930
+ sessionName,
931
+ role,
932
+ runtimeType,
933
+ maxRetries,
934
+ });
935
+ return false;
936
+ }
937
+ /**
938
+ * Fast registration polling with shorter intervals
939
+ */
940
+ async waitForRegistrationFast(sessionName, role, timeout) {
941
+ const startTime = Date.now();
942
+ const fastCheckInterval = 2000; // Check every 2 seconds (faster than original 5s)
943
+ while (Date.now() - startTime < timeout) {
944
+ try {
945
+ if (await this.checkAgentRegistration(sessionName, role)) {
946
+ this.logger.info('Fast registration confirmation', { sessionName, role });
947
+ return true;
948
+ }
949
+ await delay(fastCheckInterval);
950
+ }
951
+ catch (error) {
952
+ this.logger.debug('Error in fast registration check', {
953
+ sessionName,
954
+ role,
955
+ error: error instanceof Error ? error.message : String(error),
956
+ });
957
+ await delay(1000); // Shorter error delay
958
+ }
959
+ }
960
+ this.logger.warn('Fast registration timeout', { sessionName, role, timeout });
961
+ return false;
962
+ }
963
+ /**
964
+ * Create orchestrator session - extracted from the original tmux service
965
+ */
966
+ async createOrchestratorSession(config) {
967
+ this.logger.info('Creating orchestrator session', {
968
+ sessionName: config.sessionName,
969
+ projectPath: config.projectPath,
970
+ });
971
+ // Check if session already exists
972
+ if (await (await this.getSessionHelper()).sessionExists(config.sessionName)) {
973
+ this.logger.info('Orchestrator session already exists', {
974
+ sessionName: config.sessionName,
975
+ });
976
+ return;
977
+ }
978
+ // Create new session for orchestrator
979
+ await (await this.getSessionHelper()).createSession(config.sessionName, config.projectPath
980
+ // windowName not used in PTY backend
981
+ );
982
+ this.logger.info('Orchestrator session created successfully', {
983
+ sessionName: config.sessionName,
984
+ });
985
+ }
986
+ /**
987
+ * Unified session creation that handles both orchestrator and team members
988
+ * @param config Session configuration
989
+ * @returns Promise with success/error information
990
+ */
991
+ async createAgentSession(config) {
992
+ const { sessionName, role, projectPath = process.cwd(), windowName, memberId } = config;
993
+ // Get runtime type from config or default to claude-code
994
+ let runtimeType = config.runtimeType || RUNTIME_TYPES.CLAUDE_CODE;
995
+ // Resolve runtime flags from the agent's effective skills
996
+ let runtimeFlags = [];
997
+ // For team members, try to get runtime type from storage and resolve skill flags
998
+ if (!config.runtimeType && role !== ORCHESTRATOR_ROLE) {
999
+ try {
1000
+ const teams = await this.storageService.getTeams();
1001
+ for (const team of teams) {
1002
+ const member = team.members?.find((m) => m.sessionName === sessionName);
1003
+ if (member) {
1004
+ if (member.runtimeType) {
1005
+ runtimeType = member.runtimeType;
1006
+ }
1007
+ // Resolve runtime flags from role skills + member overrides
1008
+ runtimeFlags = await this.resolveRuntimeFlags(role, runtimeType, member.skillOverrides, member.excludedRoleSkills);
1009
+ break;
1010
+ }
1011
+ }
1012
+ }
1013
+ catch (error) {
1014
+ this.logger.warn('Failed to get runtime type or flags from storage, using defaults', {
1015
+ sessionName,
1016
+ role,
1017
+ error: error instanceof Error ? error.message : String(error),
1018
+ });
1019
+ }
1020
+ }
1021
+ else if (role !== ORCHESTRATOR_ROLE) {
1022
+ // Config-provided runtimeType, still resolve flags
1023
+ try {
1024
+ const teams = await this.storageService.getTeams();
1025
+ for (const team of teams) {
1026
+ const member = team.members?.find((m) => m.sessionName === sessionName);
1027
+ if (member) {
1028
+ runtimeFlags = await this.resolveRuntimeFlags(role, runtimeType, member.skillOverrides, member.excludedRoleSkills);
1029
+ break;
1030
+ }
1031
+ }
1032
+ }
1033
+ catch (error) {
1034
+ this.logger.warn('Failed to resolve runtime flags', {
1035
+ sessionName, role,
1036
+ error: error instanceof Error ? error.message : String(error),
1037
+ });
1038
+ }
1039
+ }
1040
+ // For orchestrator, try to get runtime type from orchestrator status
1041
+ if (role === ORCHESTRATOR_ROLE && !config.runtimeType) {
1042
+ try {
1043
+ const orchestratorStatus = await this.storageService.getOrchestratorStatus();
1044
+ if (orchestratorStatus?.runtimeType) {
1045
+ runtimeType = orchestratorStatus.runtimeType;
1046
+ }
1047
+ }
1048
+ catch (error) {
1049
+ this.logger.warn('Failed to get orchestrator runtime type from storage, using default', {
1050
+ sessionName,
1051
+ role,
1052
+ error: error instanceof Error ? error.message : String(error),
1053
+ });
1054
+ }
1055
+ }
1056
+ try {
1057
+ this.logger.info('Creating agent session (unified approach)', {
1058
+ sessionName,
1059
+ role,
1060
+ runtimeType,
1061
+ projectPath,
1062
+ windowName,
1063
+ memberId,
1064
+ });
1065
+ // Get session helper first
1066
+ this.logger.debug('Getting session helper for session creation');
1067
+ const sessionHelper = await this.getSessionHelper();
1068
+ this.logger.debug('Session helper obtained', {
1069
+ hasHelper: !!sessionHelper,
1070
+ });
1071
+ // Check if session already exists
1072
+ const sessionExists = sessionHelper.sessionExists(sessionName);
1073
+ this.logger.debug('Checked if session exists', {
1074
+ sessionName,
1075
+ sessionExists,
1076
+ });
1077
+ if (!sessionExists) {
1078
+ // Session doesn't exist, go directly to creating a new session
1079
+ this.logger.info('Session does not exist, will create new session', { sessionName });
1080
+ }
1081
+ else {
1082
+ this.logger.info('Session already exists, attempting intelligent recovery instead of killing', {
1083
+ sessionName,
1084
+ });
1085
+ // Step 1: Try to detect if runtime is already running using slash command
1086
+ const runtimeService = this.createRuntimeService(runtimeType);
1087
+ let recoverySuccess = false;
1088
+ try {
1089
+ const runtimeRunning = await runtimeService.detectRuntimeWithCommand(sessionName);
1090
+ if (runtimeRunning) {
1091
+ this.logger.info('Runtime detected in existing session, attempting direct registration', {
1092
+ sessionName,
1093
+ });
1094
+ // Try to send registration prompt directly
1095
+ const registrationResult = await this.attemptRegistrationWithVerification(sessionName, role, 25000, // 25 second timeout
1096
+ memberId, 1, // single attempt for now
1097
+ true, // skip initial cleanup since runtime is confirmed running
1098
+ runtimeType);
1099
+ if (registrationResult) {
1100
+ recoverySuccess = true;
1101
+ this.logger.info('Successfully registered existing session with runtime', { sessionName });
1102
+ }
1103
+ }
1104
+ // Step 2: If runtime not detected or registration failed, try Ctrl+C restart
1105
+ if (!recoverySuccess) {
1106
+ this.logger.info('Runtime not detected or registration failed, attempting Ctrl+C restart', {
1107
+ sessionName,
1108
+ });
1109
+ // Send Ctrl+C twice to try to restart Claude
1110
+ await (await this.getSessionHelper()).sendCtrlC(sessionName);
1111
+ await delay(1000);
1112
+ await (await this.getSessionHelper()).sendCtrlC(sessionName);
1113
+ await delay(2000);
1114
+ // Clear runtime detection cache after Ctrl+C restart
1115
+ runtimeService.clearDetectionCache(sessionName);
1116
+ // Try registration after Ctrl+C restart
1117
+ const postCtrlCResult = await this.attemptRegistrationWithVerification(sessionName, role, 25000, memberId, 1, // single attempt
1118
+ false, // don't skip cleanup after Ctrl+C
1119
+ runtimeType);
1120
+ if (postCtrlCResult) {
1121
+ recoverySuccess = true;
1122
+ this.logger.info('Successfully recovered session after Ctrl+C restart', { sessionName });
1123
+ }
1124
+ }
1125
+ }
1126
+ catch (error) {
1127
+ this.logger.warn('Error during intelligent session recovery', {
1128
+ sessionName,
1129
+ error: error instanceof Error ? error.message : String(error),
1130
+ });
1131
+ }
1132
+ // If recovery succeeded, register for persistence and return early
1133
+ if (recoverySuccess) {
1134
+ // Register session for state persistence so it survives restarts
1135
+ try {
1136
+ const persistence = getSessionStatePersistence();
1137
+ persistence.registerSession(sessionName, {
1138
+ cwd: projectPath || process.cwd(),
1139
+ command: process.env.SHELL || '/bin/bash',
1140
+ args: [],
1141
+ }, runtimeType, role, config.teamId);
1142
+ }
1143
+ catch (persistError) {
1144
+ this.logger.warn('Failed to register recovered session for persistence (non-critical)', {
1145
+ sessionName,
1146
+ error: persistError instanceof Error ? persistError.message : String(persistError),
1147
+ });
1148
+ }
1149
+ return {
1150
+ success: true,
1151
+ sessionName,
1152
+ message: 'Agent session recovered and registered successfully',
1153
+ };
1154
+ }
1155
+ // Step 3: Last resort - fall back to killing session for clean restart
1156
+ this.logger.warn('All recovery attempts failed, falling back to session recreation', {
1157
+ sessionName,
1158
+ });
1159
+ await (await this.getSessionHelper()).killSession(sessionName);
1160
+ await delay(1000); // Wait for cleanup
1161
+ }
1162
+ // Create new session (same approach for both orchestrator and team members)
1163
+ const cwdToUse = projectPath || process.cwd();
1164
+ this.logger.info('Creating PTY session', {
1165
+ sessionName,
1166
+ cwd: cwdToUse,
1167
+ });
1168
+ try {
1169
+ const createdSession = await sessionHelper.createSession(sessionName, cwdToUse);
1170
+ this.logger.info('PTY session created successfully', {
1171
+ sessionName,
1172
+ pid: createdSession.pid,
1173
+ cwd: createdSession.cwd,
1174
+ });
1175
+ }
1176
+ catch (createError) {
1177
+ this.logger.error('Failed to create PTY session', {
1178
+ sessionName,
1179
+ cwd: cwdToUse,
1180
+ error: createError instanceof Error ? createError.message : String(createError),
1181
+ stack: createError instanceof Error ? createError.stack : undefined,
1182
+ });
1183
+ throw createError;
1184
+ }
1185
+ // Verify session was created
1186
+ const sessionCreatedCheck = sessionHelper.sessionExists(sessionName);
1187
+ this.logger.info('Session creation verification', {
1188
+ sessionName,
1189
+ exists: sessionCreatedCheck,
1190
+ });
1191
+ if (!sessionCreatedCheck) {
1192
+ throw new Error(`Session '${sessionName}' was not created successfully`);
1193
+ }
1194
+ // Register session for state persistence so it survives restarts
1195
+ try {
1196
+ const persistence = getSessionStatePersistence();
1197
+ persistence.registerSession(sessionName, {
1198
+ cwd: cwdToUse,
1199
+ command: process.env.SHELL || '/bin/bash',
1200
+ args: [],
1201
+ }, runtimeType, role, config.teamId);
1202
+ }
1203
+ catch (persistError) {
1204
+ this.logger.warn('Failed to register session for persistence (non-critical)', {
1205
+ sessionName,
1206
+ error: persistError instanceof Error ? persistError.message : String(persistError),
1207
+ });
1208
+ }
1209
+ // Set environment variables for MCP connection
1210
+ await sessionHelper.setEnvironmentVariable(sessionName, ENV_CONSTANTS.TMUX_SESSION_NAME, sessionName);
1211
+ await sessionHelper.setEnvironmentVariable(sessionName, ENV_CONSTANTS.CREWLY_ROLE, role);
1212
+ await sessionHelper.setEnvironmentVariable(sessionName, ENV_CONSTANTS.CREWLY_API_URL, `http://localhost:${WEB_CONSTANTS.PORTS.BACKEND}`);
1213
+ this.logger.info('Agent session created and environment variables set, initializing with registration', {
1214
+ sessionName,
1215
+ role,
1216
+ runtimeType,
1217
+ });
1218
+ // Use the existing unified registration system
1219
+ const timeout = role === ORCHESTRATOR_ROLE
1220
+ ? AGENT_TIMEOUTS.ORCHESTRATOR_INITIALIZATION
1221
+ : AGENT_TIMEOUTS.REGULAR_AGENT_INITIALIZATION;
1222
+ const initResult = await this.initializeAgentWithRegistration(sessionName, role, projectPath, timeout, memberId, runtimeType, runtimeFlags);
1223
+ if (!initResult.success) {
1224
+ return {
1225
+ success: false,
1226
+ sessionName,
1227
+ error: initResult.error || 'Failed to initialize and register agent',
1228
+ };
1229
+ }
1230
+ return {
1231
+ success: true,
1232
+ sessionName,
1233
+ message: initResult.message || 'Agent session created and registered successfully',
1234
+ };
1235
+ }
1236
+ catch (error) {
1237
+ const errorMessage = error instanceof Error ? error.message : String(error);
1238
+ this.logger.error('Failed to create agent session', {
1239
+ sessionName,
1240
+ role,
1241
+ error: errorMessage,
1242
+ });
1243
+ return {
1244
+ success: false,
1245
+ sessionName,
1246
+ error: errorMessage,
1247
+ };
1248
+ }
1249
+ }
1250
+ /**
1251
+ * Unified session termination that handles both orchestrator and team members
1252
+ * @param sessionName The session to terminate
1253
+ * @param role The role for proper status updates
1254
+ * @returns Promise with success/error information
1255
+ */
1256
+ async terminateAgentSession(sessionName, role = 'unknown') {
1257
+ try {
1258
+ this.logger.info('Terminating agent session (unified approach)', { sessionName, role });
1259
+ // Stop runtime exit monitoring before killing the session
1260
+ RuntimeExitMonitorService.getInstance().stopMonitoring(sessionName);
1261
+ // Get session helper once to avoid repeated async calls
1262
+ const sessionHelper = await this.getSessionHelper();
1263
+ const sessionExists = sessionHelper.sessionExists(sessionName);
1264
+ if (sessionExists) {
1265
+ // Kill the tmux session
1266
+ await sessionHelper.killSession(sessionName);
1267
+ this.logger.info('Session terminated successfully', { sessionName });
1268
+ }
1269
+ else {
1270
+ this.logger.info('Session already terminated or does not exist', { sessionName });
1271
+ }
1272
+ // Capture session end for memory persistence
1273
+ try {
1274
+ const sessionMemoryService = SessionMemoryService.getInstance();
1275
+ await sessionMemoryService.onSessionEnd(sessionName, role, process.cwd());
1276
+ this.logger.info('Session memory captured on termination', { sessionName, role });
1277
+ }
1278
+ catch (memoryError) {
1279
+ this.logger.warn('Failed to capture session memory on termination (non-critical)', {
1280
+ sessionName,
1281
+ error: memoryError instanceof Error ? memoryError.message : String(memoryError),
1282
+ });
1283
+ }
1284
+ // Update agent status to inactive (works for both orchestrator and team members)
1285
+ await this.storageService.updateAgentStatus(sessionName, CREWLY_CONSTANTS.AGENT_STATUSES.INACTIVE);
1286
+ this.logger.info('Agent status updated to inactive', { sessionName, role });
1287
+ // Unregister from persistence so explicitly stopped agents don't reappear in resume popup
1288
+ try {
1289
+ const persistence = getSessionStatePersistence();
1290
+ persistence.unregisterSession(sessionName);
1291
+ }
1292
+ catch (persistError) {
1293
+ this.logger.warn('Failed to unregister session from persistence (non-critical)', {
1294
+ sessionName,
1295
+ error: persistError instanceof Error ? persistError.message : String(persistError),
1296
+ });
1297
+ }
1298
+ return {
1299
+ success: true,
1300
+ message: sessionExists
1301
+ ? 'Agent session terminated successfully'
1302
+ : 'Agent session was already terminated',
1303
+ };
1304
+ }
1305
+ catch (error) {
1306
+ const errorMessage = error instanceof Error ? error.message : String(error);
1307
+ this.logger.error('Failed to terminate agent session', {
1308
+ sessionName,
1309
+ role,
1310
+ error: errorMessage,
1311
+ });
1312
+ return {
1313
+ success: false,
1314
+ error: errorMessage,
1315
+ };
1316
+ }
1317
+ }
1318
+ /**
1319
+ * Send a message to any agent session with reliable delivery.
1320
+ * Uses robust delivery mechanism with retry logic to ensure messages
1321
+ * are properly delivered to Claude Code's input.
1322
+ *
1323
+ * @param sessionName - The agent session name
1324
+ * @param message - The message to send
1325
+ * @returns Promise with success status and optional error message
1326
+ *
1327
+ * @example
1328
+ * ```typescript
1329
+ * const result = await agentRegistrationService.sendMessageToAgent(
1330
+ * 'crewly-orc',
1331
+ * '[CHAT:123] Hello, orchestrator!'
1332
+ * );
1333
+ * if (result.success) {
1334
+ * console.log('Message delivered');
1335
+ * } else {
1336
+ * console.error('Delivery failed:', result.error);
1337
+ * }
1338
+ * ```
1339
+ */
1340
+ async sendMessageToAgent(sessionName, message, runtimeType = RUNTIME_TYPES.CLAUDE_CODE) {
1341
+ try {
1342
+ if (!message || typeof message !== 'string') {
1343
+ return {
1344
+ success: false,
1345
+ error: 'Message is required and must be a string',
1346
+ };
1347
+ }
1348
+ // Get session helper once for this method
1349
+ const sessionHelper = await this.getSessionHelper();
1350
+ // Check if session exists
1351
+ if (!sessionHelper.sessionExists(sessionName)) {
1352
+ return {
1353
+ success: false,
1354
+ error: `Session '${sessionName}' does not exist`,
1355
+ };
1356
+ }
1357
+ // Use robust message delivery with proper waiting mechanism
1358
+ const delivered = await this.sendMessageWithRetry(sessionName, message, 3, runtimeType);
1359
+ if (!delivered) {
1360
+ return {
1361
+ success: false,
1362
+ error: 'Failed to deliver message after multiple attempts',
1363
+ };
1364
+ }
1365
+ this.logger.info('Message sent to agent successfully', {
1366
+ sessionName,
1367
+ messageLength: message.length,
1368
+ });
1369
+ return {
1370
+ success: true,
1371
+ message: 'Message sent to agent successfully',
1372
+ };
1373
+ }
1374
+ catch (error) {
1375
+ const errorMessage = error instanceof Error ? error.message : String(error);
1376
+ this.logger.error('Failed to send message to agent', {
1377
+ sessionName,
1378
+ error: errorMessage,
1379
+ });
1380
+ return {
1381
+ success: false,
1382
+ error: errorMessage,
1383
+ };
1384
+ }
1385
+ }
1386
+ /**
1387
+ * Wait for an agent session to be at a ready prompt before sending messages.
1388
+ *
1389
+ * Subscribes to terminal output and polls capturePane to detect when the
1390
+ * agent returns to an input prompt. This is critical for sequential message
1391
+ * processing: after the orchestrator responds to a message it may continue
1392
+ * working (managing agents, running commands) before returning to prompt.
1393
+ *
1394
+ * @param sessionName - The session name to wait on
1395
+ * @param timeoutMs - Maximum time to wait (default 120s)
1396
+ * @returns true if agent is ready, false if timed out
1397
+ */
1398
+ async waitForAgentReady(sessionName, timeoutMs = EVENT_DELIVERY_CONSTANTS.AGENT_READY_TIMEOUT, runtimeType) {
1399
+ const sessionHelper = await this.getSessionHelper();
1400
+ // Check if session exists
1401
+ if (!sessionHelper.sessionExists(sessionName)) {
1402
+ this.logger.warn('Session does not exist for waitForAgentReady', { sessionName });
1403
+ return false;
1404
+ }
1405
+ // Quick check - already at prompt?
1406
+ const currentOutput = sessionHelper.capturePane(sessionName);
1407
+ if (this.isClaudeAtPrompt(currentOutput, runtimeType)) {
1408
+ this.logger.debug('Agent already at prompt', { sessionName });
1409
+ return true;
1410
+ }
1411
+ this.logger.info('Waiting for agent to return to prompt', { sessionName, timeoutMs });
1412
+ const session = sessionHelper.getSession(sessionName);
1413
+ if (!session) {
1414
+ return false;
1415
+ }
1416
+ // Use runtime-specific pattern for stream detection to avoid false positives
1417
+ // (e.g. Gemini's `> ` pattern matching markdown blockquotes in Claude Code output)
1418
+ const isClaudeCode = runtimeType === RUNTIME_TYPES.CLAUDE_CODE;
1419
+ const isGemini = runtimeType === RUNTIME_TYPES.GEMINI_CLI;
1420
+ const streamPattern = isClaudeCode
1421
+ ? TERMINAL_PATTERNS.CLAUDE_CODE_PROMPT
1422
+ : isGemini
1423
+ ? TERMINAL_PATTERNS.GEMINI_CLI_PROMPT
1424
+ : TERMINAL_PATTERNS.PROMPT_STREAM;
1425
+ return new Promise((resolve) => {
1426
+ let resolved = false;
1427
+ const pollInterval = EVENT_DELIVERY_CONSTANTS.AGENT_READY_POLL_INTERVAL;
1428
+ const cleanup = () => {
1429
+ if (resolved)
1430
+ return;
1431
+ resolved = true;
1432
+ clearTimeout(timeoutId);
1433
+ clearInterval(pollId);
1434
+ unsubscribe();
1435
+ };
1436
+ // Timeout - give up waiting
1437
+ const timeoutId = setTimeout(() => {
1438
+ this.logger.warn('Timed out waiting for agent to be ready', { sessionName, timeoutMs });
1439
+ cleanup();
1440
+ resolve(false);
1441
+ }, timeoutMs);
1442
+ // Poll capturePane periodically as a fallback
1443
+ const pollId = setInterval(() => {
1444
+ if (resolved)
1445
+ return;
1446
+ const output = sessionHelper.capturePane(sessionName);
1447
+ if (this.isClaudeAtPrompt(output, runtimeType)) {
1448
+ this.logger.debug('Agent at prompt (detected via polling)', { sessionName });
1449
+ cleanup();
1450
+ resolve(true);
1451
+ }
1452
+ }, pollInterval);
1453
+ // Also subscribe to terminal data for faster detection
1454
+ const unsubscribe = session.onData((data) => {
1455
+ if (resolved)
1456
+ return;
1457
+ if (streamPattern.test(data)) {
1458
+ // Double-check with capturePane to avoid false positives from partial data
1459
+ const output = sessionHelper.capturePane(sessionName);
1460
+ if (this.isClaudeAtPrompt(output, runtimeType)) {
1461
+ this.logger.debug('Agent at prompt (detected via stream)', { sessionName });
1462
+ cleanup();
1463
+ resolve(true);
1464
+ }
1465
+ }
1466
+ });
1467
+ });
1468
+ }
1469
+ /**
1470
+ * @deprecated Replaced by SessionCommandHelper.sendMessage() in sendMessageWithRetry.
1471
+ * Complex event-driven state machine was fragile — Enter key often got lost.
1472
+ * Kept as dead code for reference during transition.
1473
+ */
1474
+ async _deprecated_sendMessageEventDriven(sessionName, message, timeoutMs = EVENT_DELIVERY_CONSTANTS.TOTAL_DELIVERY_TIMEOUT) {
1475
+ const sessionHelper = await this.getSessionHelper();
1476
+ const session = sessionHelper.getSession(sessionName);
1477
+ if (!session) {
1478
+ this.logger.error('Session not found for event-driven delivery', { sessionName });
1479
+ return false;
1480
+ }
1481
+ return new Promise((resolve) => {
1482
+ let buffer = '';
1483
+ let messageSent = false;
1484
+ let enterSent = false;
1485
+ let enterAccepted = false;
1486
+ let deliveryConfirmed = false;
1487
+ let resolved = false;
1488
+ // Track all timeouts to prevent memory leaks (P1.1 fix)
1489
+ const pendingTimeouts = [];
1490
+ const scheduleTimeout = (fn, delayMs) => {
1491
+ const id = setTimeout(fn, delayMs);
1492
+ pendingTimeouts.push(id);
1493
+ return id;
1494
+ };
1495
+ const cleanup = () => {
1496
+ // Immediately mark as resolved to prevent race conditions (P1.2 fix)
1497
+ const wasResolved = resolved;
1498
+ resolved = true;
1499
+ if (!wasResolved) {
1500
+ // Clear all pending timeouts to prevent memory leaks
1501
+ pendingTimeouts.forEach((id) => clearTimeout(id));
1502
+ clearTimeout(timeoutId);
1503
+ unsubscribe();
1504
+ }
1505
+ };
1506
+ // Use centralized patterns from TERMINAL_PATTERNS
1507
+ const PASTE_PATTERN = TERMINAL_PATTERNS.PASTE_INDICATOR;
1508
+ const PROCESSING_PATTERN = TERMINAL_PATTERNS.PROCESSING;
1509
+ // Use centralized timing from EVENT_DELIVERY_CONSTANTS
1510
+ const INITIAL_DELAY = EVENT_DELIVERY_CONSTANTS.INITIAL_MESSAGE_DELAY;
1511
+ const PASTE_CHECK_DELAY = EVENT_DELIVERY_CONSTANTS.PASTE_CHECK_DELAY;
1512
+ const ENTER_RETRY_DELAY = EVENT_DELIVERY_CONSTANTS.ENTER_RETRY_DELAY;
1513
+ const MAX_ENTER_RETRIES = EVENT_DELIVERY_CONSTANTS.MAX_ENTER_RETRIES;
1514
+ const MAX_BUFFER_SIZE = EVENT_DELIVERY_CONSTANTS.MAX_BUFFER_SIZE;
1515
+ // Helper to send the message when prompt is detected
1516
+ const sendMessageNow = () => {
1517
+ if (messageSent || resolved)
1518
+ return;
1519
+ this.logger.debug('Claude at prompt, sending message', {
1520
+ sessionName,
1521
+ messageLength: message.length,
1522
+ isMultiLine: message.includes('\n'),
1523
+ });
1524
+ // Send the message text
1525
+ session.write(message);
1526
+ messageSent = true;
1527
+ const isMultiLine = message.includes('\n');
1528
+ // Track Enter key state
1529
+ let enterAttempts = 0;
1530
+ let processingDetected = false;
1531
+ const bufferAtSend = buffer;
1532
+ // Function to send Enter and track attempts
1533
+ const sendEnterKey = (reason) => {
1534
+ if (resolved || processingDetected)
1535
+ return;
1536
+ enterAttempts++;
1537
+ session.write('\r');
1538
+ enterSent = true;
1539
+ this.logger.debug('Enter key sent', {
1540
+ sessionName,
1541
+ attempt: enterAttempts,
1542
+ reason,
1543
+ });
1544
+ };
1545
+ // Function to check if Enter was accepted (processing started)
1546
+ const checkProcessingStarted = () => {
1547
+ const newData = buffer.slice(bufferAtSend.length);
1548
+ return PROCESSING_PATTERN.test(newData);
1549
+ };
1550
+ // Function to check for paste indicator
1551
+ const checkPasteIndicator = () => {
1552
+ const newData = buffer.slice(bufferAtSend.length);
1553
+ return PASTE_PATTERN.test(newData);
1554
+ };
1555
+ // Strategy: Send Enter with progressive timing, retry if not accepted
1556
+ const attemptEnter = (attemptNum) => {
1557
+ if (resolved || processingDetected)
1558
+ return;
1559
+ // Check if processing already started
1560
+ if (checkProcessingStarted()) {
1561
+ processingDetected = true;
1562
+ enterAccepted = true;
1563
+ this.logger.debug('Processing detected, message accepted', { sessionName, attemptNum });
1564
+ buffer = ''; // Reset for processing indicator detection
1565
+ return;
1566
+ }
1567
+ if (attemptNum > MAX_ENTER_RETRIES) {
1568
+ this.logger.warn('Max Enter retries reached, verifying message acceptance', { sessionName });
1569
+ scheduleTimeout(async () => {
1570
+ if (resolved)
1571
+ return;
1572
+ const stuck = await this.isMessageStuckAtPrompt(sessionName, message);
1573
+ if (stuck) {
1574
+ this.logger.warn('Message stuck at prompt after all Enter retries', { sessionName });
1575
+ const stuckHelper = await this.getSessionHelper();
1576
+ await stuckHelper.clearCurrentCommandLine(sessionName);
1577
+ enterAccepted = false;
1578
+ }
1579
+ else {
1580
+ this.logger.debug('Message appears accepted (no longer at prompt)', { sessionName });
1581
+ enterAccepted = true;
1582
+ buffer = '';
1583
+ }
1584
+ }, EVENT_DELIVERY_CONSTANTS.POST_ENTER_VERIFICATION_DELAY);
1585
+ return;
1586
+ }
1587
+ sendEnterKey(attemptNum === 1 ? 'initial' : `retry-${attemptNum}`);
1588
+ // Schedule check and possible retry (using tracked timeout to prevent leaks)
1589
+ scheduleTimeout(() => {
1590
+ if (resolved)
1591
+ return;
1592
+ if (checkProcessingStarted()) {
1593
+ processingDetected = true;
1594
+ enterAccepted = true;
1595
+ this.logger.debug('Processing detected after Enter', { sessionName, attemptNum });
1596
+ buffer = '';
1597
+ }
1598
+ else {
1599
+ // Not accepted yet, retry
1600
+ this.logger.debug('Enter may not have been accepted, retrying', {
1601
+ sessionName,
1602
+ attemptNum,
1603
+ bufferLength: buffer.length,
1604
+ });
1605
+ attemptEnter(attemptNum + 1);
1606
+ }
1607
+ }, ENTER_RETRY_DELAY);
1608
+ };
1609
+ // For multi-line messages, wait longer for paste indicator
1610
+ // For single-line messages, send Enter sooner
1611
+ const initialWait = isMultiLine ? PASTE_CHECK_DELAY : INITIAL_DELAY;
1612
+ scheduleTimeout(() => {
1613
+ if (resolved)
1614
+ return;
1615
+ // For multi-line: check if paste indicator appeared
1616
+ if (isMultiLine && checkPasteIndicator()) {
1617
+ this.logger.debug('Paste indicator detected', { sessionName });
1618
+ }
1619
+ // Start Enter key attempts
1620
+ attemptEnter(1);
1621
+ }, initialWait);
1622
+ };
1623
+ const timeoutId = setTimeout(async () => {
1624
+ this.logger.debug('Event-driven delivery timed out', {
1625
+ sessionName,
1626
+ messageSent,
1627
+ enterSent,
1628
+ enterAccepted,
1629
+ deliveryConfirmed,
1630
+ bufferLength: buffer.length,
1631
+ });
1632
+ // If Enter was sent but not confirmed accepted, verify via terminal capture
1633
+ if (enterSent && !enterAccepted && !deliveryConfirmed) {
1634
+ const timeoutHelper = await this.getSessionHelper();
1635
+ const stuck = await this.isMessageStuckAtPrompt(sessionName, message);
1636
+ if (stuck) {
1637
+ this.logger.warn('Timeout: message stuck at prompt, clearing and failing', { sessionName });
1638
+ await timeoutHelper.clearCurrentCommandLine(sessionName);
1639
+ cleanup();
1640
+ resolve(false);
1641
+ return;
1642
+ }
1643
+ this.logger.debug('Timeout: message not at prompt, treating as accepted', { sessionName });
1644
+ }
1645
+ cleanup();
1646
+ resolve(enterAccepted || deliveryConfirmed);
1647
+ }, timeoutMs);
1648
+ // IMPORTANT: Check current terminal state, but wait for output to settle first.
1649
+ // If the orchestrator just finished outputting (greeting, notification, status bar),
1650
+ // the prompt may not be cleanly detectable. We capture the pane, wait briefly,
1651
+ // and re-capture. If output is still changing, wait again before checking prompt.
1652
+ // Use 50 lines to account for status bars and notifications that can
1653
+ // wrap across many lines and push the prompt out of a smaller window.
1654
+ const waitForSettled = async () => {
1655
+ let prevOutput = sessionHelper.capturePane(sessionName);
1656
+ for (let i = 0; i < 5; i++) { // Max 5 checks, 500ms apart = 2.5s max
1657
+ if (resolved)
1658
+ return;
1659
+ await delay(500);
1660
+ if (resolved)
1661
+ return;
1662
+ const currentOutput = sessionHelper.capturePane(sessionName);
1663
+ if (currentOutput === prevOutput) {
1664
+ // Output settled
1665
+ if (this.isClaudeAtPrompt(currentOutput)) {
1666
+ this.logger.debug('Claude at prompt after output settled', { sessionName, settleChecks: i + 1 });
1667
+ sendMessageNow();
1668
+ }
1669
+ return;
1670
+ }
1671
+ prevOutput = currentOutput;
1672
+ }
1673
+ // Output still changing after 2.5s - check anyway
1674
+ if (!resolved && this.isClaudeAtPrompt(prevOutput)) {
1675
+ this.logger.debug('Claude at prompt (output still changing, checking anyway)', { sessionName });
1676
+ sendMessageNow();
1677
+ }
1678
+ };
1679
+ waitForSettled();
1680
+ const unsubscribe = session.onData((data) => {
1681
+ if (resolved)
1682
+ return;
1683
+ // Accumulate data with size limit to prevent memory exhaustion (P2.3 fix)
1684
+ buffer += data;
1685
+ if (buffer.length > MAX_BUFFER_SIZE) {
1686
+ buffer = buffer.slice(-MAX_BUFFER_SIZE);
1687
+ }
1688
+ // Phase 1: Wait for Claude to be at prompt before sending
1689
+ if (!messageSent) {
1690
+ const isAtPrompt = AgentRegistrationService.CLAUDE_PROMPT_STREAM_PATTERN.test(buffer);
1691
+ if (isAtPrompt) {
1692
+ sendMessageNow();
1693
+ }
1694
+ return;
1695
+ }
1696
+ // Phase 2: Only check for processing indicators AFTER Enter has been sent
1697
+ if (!enterSent) {
1698
+ return; // Wait for Enter to be sent
1699
+ }
1700
+ // Look for processing indicators confirming delivery
1701
+ const hasProcessingIndicator = AgentRegistrationService.CLAUDE_PROCESSING_INDICATORS.some((pattern) => pattern.test(buffer));
1702
+ // Also check if prompt disappeared (Claude is working)
1703
+ const promptStillVisible = AgentRegistrationService.CLAUDE_PROMPT_STREAM_PATTERN.test(buffer);
1704
+ // Use constant for minimum buffer check (P3.2 fix)
1705
+ if (hasProcessingIndicator || (!promptStillVisible && buffer.length > EVENT_DELIVERY_CONSTANTS.MIN_BUFFER_FOR_PROCESSING_DETECTION)) {
1706
+ this.logger.debug('Message delivery confirmed (event-driven)', {
1707
+ sessionName,
1708
+ hasProcessingIndicator,
1709
+ promptStillVisible,
1710
+ bufferLength: buffer.length,
1711
+ });
1712
+ deliveryConfirmed = true;
1713
+ cleanup();
1714
+ resolve(true);
1715
+ }
1716
+ });
1717
+ });
1718
+ }
1719
+ /**
1720
+ * Send message with retry logic for reliable delivery to Claude Code.
1721
+ * Uses SessionCommandHelper.sendMessage() (proven two-step write pattern)
1722
+ * with stuck-message detection and retry on failure.
1723
+ *
1724
+ * @param sessionName - The session name
1725
+ * @param message - The message to send
1726
+ * @param maxAttempts - Maximum number of delivery attempts
1727
+ * @returns true if message was delivered successfully
1728
+ */
1729
+ async sendMessageWithRetry(sessionName, message, maxAttempts = 3, runtimeType = RUNTIME_TYPES.CLAUDE_CODE) {
1730
+ const sessionHelper = await this.getSessionHelper();
1731
+ const isClaudeCode = runtimeType === RUNTIME_TYPES.CLAUDE_CODE;
1732
+ // Register TUI sessions for TUI prompt-line scanning (Part 1 of scanner).
1733
+ // The scanner itself is started lazily by trackSentMessage() which
1734
+ // runs after every message send, covering all runtimes.
1735
+ if (!isClaudeCode) {
1736
+ this.tuiSessionRegistry.set(sessionName, runtimeType);
1737
+ }
1738
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1739
+ try {
1740
+ this.logger.debug('Attempting message delivery', {
1741
+ sessionName,
1742
+ attempt,
1743
+ maxAttempts,
1744
+ messageLength: message.length,
1745
+ runtimeType,
1746
+ });
1747
+ // Verify agent is at prompt before sending
1748
+ const output = sessionHelper.capturePane(sessionName);
1749
+ if (!this.isClaudeAtPrompt(output, runtimeType)) {
1750
+ this.logger.debug('Not at prompt, waiting before retry', { sessionName, attempt });
1751
+ await delay(SESSION_COMMAND_DELAYS.CLAUDE_RECOVERY_DELAY);
1752
+ continue;
1753
+ }
1754
+ // Gemini CLI shell mode guard: if the prompt shows `!` instead of `>`,
1755
+ // input will be executed as a shell command. Send Escape to exit first.
1756
+ if (runtimeType === RUNTIME_TYPES.GEMINI_CLI && this.isGeminiInShellMode(output)) {
1757
+ const escaped = await this.escapeGeminiShellMode(sessionName, sessionHelper);
1758
+ if (!escaped) {
1759
+ this.logger.warn('Could not exit Gemini shell mode, skipping attempt', {
1760
+ sessionName,
1761
+ attempt,
1762
+ });
1763
+ await delay(SESSION_COMMAND_DELAYS.MESSAGE_RETRY_DELAY);
1764
+ continue;
1765
+ }
1766
+ }
1767
+ // Clear any stale text before sending.
1768
+ // Claude Code: Ctrl+C to cancel any pending input — but ONLY on
1769
+ // retry attempts. On the first attempt, waitForAgentReady already
1770
+ // confirmed the agent is idle at the prompt, so Ctrl+C is
1771
+ // unnecessary and can disrupt Claude Code's input handler if the
1772
+ // 300ms settling delay isn't enough.
1773
+ // Gemini CLI (Ink TUI): escalating recovery to refocus input box.
1774
+ // The TUI input can lose focus after idle periods, auto-update
1775
+ // notifications, or dialog overlays. When defocused, writes are
1776
+ // silently consumed by the Ink framework but NOT routed to the
1777
+ // InputPrompt.
1778
+ // Do NOT send Escape (defocuses permanently), Ctrl+C (triggers
1779
+ // /quit on empty prompt), or Ctrl+U (ignored by TUI).
1780
+ //
1781
+ // Recovery strategies (escalating per attempt):
1782
+ // 1. Tab + Enter: Tab triggers Ink's focusNext() which cycles
1783
+ // focus through focusable components. If InputPrompt is the
1784
+ // only/next focusable element, it gets refocused. Enter then
1785
+ // dismisses any overlay or acts as safe no-op on empty prompt.
1786
+ // 2-3. PTY resize + Tab + Enter: Resize sends SIGWINCH to the
1787
+ // child process, forcing Ink to re-render the entire TUI.
1788
+ // This may restore the internal focus state. Then Tab + Enter
1789
+ // for focus cycling and overlay dismissal.
1790
+ if (isClaudeCode) {
1791
+ if (attempt > 1) {
1792
+ await sessionHelper.sendCtrlC(sessionName);
1793
+ await delay(300);
1794
+ }
1795
+ }
1796
+ else {
1797
+ // On retry attempts (2+), force a PTY resize to trigger SIGWINCH.
1798
+ // This makes Ink re-render the TUI, potentially restoring focus state.
1799
+ if (attempt > 1) {
1800
+ try {
1801
+ const session = sessionHelper.getSession(sessionName);
1802
+ if (session) {
1803
+ // Resize slightly then back to trigger SIGWINCH
1804
+ session.resize(81, 25);
1805
+ await delay(200);
1806
+ session.resize(80, 24);
1807
+ await delay(500);
1808
+ this.logger.debug('PTY resize sent to trigger TUI re-render', {
1809
+ sessionName,
1810
+ attempt,
1811
+ });
1812
+ }
1813
+ }
1814
+ catch (resizeErr) {
1815
+ this.logger.debug('PTY resize failed (non-fatal)', {
1816
+ sessionName,
1817
+ error: resizeErr instanceof Error ? resizeErr.message : String(resizeErr),
1818
+ });
1819
+ }
1820
+ }
1821
+ // Send Tab to cycle Ink focus. In Ink v6, Tab triggers
1822
+ // focusNext() in FocusContext, which moves focus to the next
1823
+ // focusable component (InputPrompt). This works even when the
1824
+ // input is defocused because the Tab handler runs at the Ink
1825
+ // framework level, not the component level.
1826
+ await sessionHelper.sendKey(sessionName, 'Tab');
1827
+ await delay(300);
1828
+ // Then Enter to dismiss any notification overlay and ensure
1829
+ // the input is engaged. Enter on an empty `> ` prompt is a
1830
+ // safe no-op (just shows a new blank prompt line).
1831
+ await sessionHelper.sendEnter(sessionName);
1832
+ await delay(500);
1833
+ }
1834
+ // Capture output BEFORE sending to detect changes for ALL runtimes.
1835
+ // Claude Code: progressive output-change detection prevents false-positive
1836
+ // Ctrl+C by giving Claude up to 6.5s to start rendering output.
1837
+ // TUI runtimes: same output-change detection as before.
1838
+ // Use a small pane capture (20 lines) to reduce noise from TUI
1839
+ // border redraws that can cause length changes unrelated to delivery.
1840
+ const beforeOutput = sessionHelper.capturePane(sessionName, 20);
1841
+ const beforeLength = beforeOutput.length;
1842
+ // Use SessionCommandHelper.sendMessage() — proven two-step write:
1843
+ // 1. session.write(message) — triggers bracketed paste
1844
+ // 2. await delay(scaled) — waits for paste processing
1845
+ // 3. session.write('\r') — sends Enter separately
1846
+ // 4. await delay(KEY_DELAY) — waits for key processing
1847
+ await sessionHelper.sendMessage(sessionName, message);
1848
+ // Register for background stuck-detection safety net (all runtimes).
1849
+ // If progressive verification below misses an Enter drop, the
1850
+ // background scanner will catch it within 30s.
1851
+ this.trackSentMessage(sessionName, message);
1852
+ // Wait for agent to start processing, then verify delivery.
1853
+ // TUI runtimes need a longer delay (3s) for the TUI to redraw
1854
+ // and show processing indicators after accepting input.
1855
+ const processingDelay = isClaudeCode
1856
+ ? SESSION_COMMAND_DELAYS.MESSAGE_PROCESSING_DELAY
1857
+ : 3000;
1858
+ await delay(processingDelay);
1859
+ // === Delivery verification ===
1860
+ // Claude Code: prompt disappears during processing, so check
1861
+ // isMessageStuckAtPrompt (text still at prompt = stuck).
1862
+ // TUI runtimes (Gemini CLI): use TWO-PHASE verification:
1863
+ // Phase 1: Direct check — is the message text sitting ON the
1864
+ // `> ` prompt line? If yes, Enter was dropped. Try
1865
+ // pressing Enter to recover before falling through to retry.
1866
+ // Phase 2: Output-change detection — compare before/after captures
1867
+ // to see if the agent started processing.
1868
+ if (isClaudeCode) {
1869
+ // Progressive verification for Claude Code.
1870
+ // Claude Code routinely takes 3-8s to start rendering with large
1871
+ // context. The old 2.5s window caused false-positive Ctrl+C that
1872
+ // cancelled valid in-progress prompts. Now we progressively check
1873
+ // at [1s, 2s, 3s] intervals (total ~6.5s including processing delay).
1874
+ //
1875
+ // Progressive verification: check at [1s, 2s, 3s] intervals whether
1876
+ // the agent accepted the message and started processing it.
1877
+ //
1878
+ // Uses runtime-agnostic detection — no hardcoded prompt characters.
1879
+ // This stays correct when the agent runtime upgrades its prompt.
1880
+ //
1881
+ // Three signals checked per interval:
1882
+ // 1. Processing indicators (⠋ ⏺ spinners) — definitive success
1883
+ // 2. isClaudeAtPrompt() — if still true, agent is idle, wait more
1884
+ // 3. Message text in bottom lines — if found, Enter was dropped
1885
+ // (message pasted at prompt but not submitted)
1886
+ // If prompt gone AND message text NOT at bottom → success
1887
+ let claudeDelivered = false;
1888
+ for (const intervalMs of SESSION_COMMAND_DELAYS.CLAUDE_VERIFICATION_INTERVALS) {
1889
+ const currentOutput = sessionHelper.capturePane(sessionName);
1890
+ // 1. Processing indicators (spinners, working marker) are
1891
+ // definitive proof the agent accepted and is working.
1892
+ // Only check spinner/⏺ chars — NOT text words like
1893
+ // "thinking" which appear in historical response text.
1894
+ if (TERMINAL_PATTERNS.PROCESSING.test(currentOutput)) {
1895
+ this.logger.debug('Processing indicators detected — message accepted', {
1896
+ sessionName,
1897
+ attempt,
1898
+ });
1899
+ claudeDelivered = true;
1900
+ break;
1901
+ }
1902
+ // 2. Is the agent still at its standard idle prompt?
1903
+ // Reuse isClaudeAtPrompt() — the single source of truth
1904
+ // for prompt detection. This avoids hardcoding prompt
1905
+ // characters and stays correct when the runtime upgrades.
1906
+ if (this.isClaudeAtPrompt(currentOutput, runtimeType)) {
1907
+ // Prompt is visible. Before just waiting, check if our
1908
+ // message text is also at the bottom — this means the
1909
+ // text was pasted but Enter was dropped. Press Enter.
1910
+ // Normalize whitespace: enhanced messages contain literal \n from
1911
+ // addContinuationInstructions(). join(' ') replaces line breaks with
1912
+ // spaces, but the snippet still has \n chars, so includes() fails.
1913
+ const promptMsgSnippet = (message.length > 20
1914
+ ? message.substring(0, 80)
1915
+ : message).replace(/\s+/g, ' ').trim();
1916
+ const promptBottomLines = currentOutput.split('\n').slice(-10).join(' ').replace(/\s+/g, ' ');
1917
+ if (promptBottomLines.includes(promptMsgSnippet)) {
1918
+ this.logger.warn('At prompt with message text at bottom — pressing Enter', {
1919
+ sessionName,
1920
+ attempt,
1921
+ intervalMs,
1922
+ });
1923
+ await sessionHelper.sendEnter(sessionName);
1924
+ await delay(500);
1925
+ await sessionHelper.sendEnter(sessionName); // backup
1926
+ await delay(SESSION_COMMAND_DELAYS.MESSAGE_PROCESSING_DELAY);
1927
+ // Verify recovery
1928
+ const postEnterOutput = sessionHelper.capturePane(sessionName);
1929
+ if (TERMINAL_PATTERNS.PROCESSING.test(postEnterOutput) ||
1930
+ !this.isClaudeAtPrompt(postEnterOutput, runtimeType)) {
1931
+ this.logger.info('Enter recovery from prompt successful', {
1932
+ sessionName,
1933
+ attempt,
1934
+ });
1935
+ claudeDelivered = true;
1936
+ break;
1937
+ }
1938
+ }
1939
+ this.logger.debug('Agent still at prompt, waiting before re-check', {
1940
+ sessionName,
1941
+ attempt,
1942
+ intervalMs,
1943
+ });
1944
+ await delay(intervalMs);
1945
+ continue;
1946
+ }
1947
+ // 3. Prompt not in its standard idle form. Before declaring
1948
+ // success, check if our message text is stuck at the
1949
+ // bottom of the terminal. When Enter is dropped, the
1950
+ // pasted text appears on the prompt line — the terminal
1951
+ // shows the prompt char followed by our message text.
1952
+ // This check is runtime-agnostic: it works regardless
1953
+ // of what prompt character the runtime uses.
1954
+ // Normalize whitespace in snippet (see Step 2 comment above).
1955
+ const msgSnippet = (message.length > 20
1956
+ ? message.substring(0, 80)
1957
+ : message).replace(/\s+/g, ' ').trim();
1958
+ const bottomLines = currentOutput.split('\n').slice(-10).join(' ').replace(/\s+/g, ' ');
1959
+ if (bottomLines.includes(msgSnippet)) {
1960
+ // Message text is at the bottom of the terminal but the
1961
+ // prompt is no longer in its idle form — Enter was dropped.
1962
+ // Instead of waiting and doing a full Ctrl+C + resend retry,
1963
+ // press Enter immediately to submit the already-pasted text.
1964
+ this.logger.warn('Message text stuck at bottom — pressing Enter to recover', {
1965
+ sessionName,
1966
+ attempt,
1967
+ intervalMs,
1968
+ });
1969
+ await sessionHelper.sendEnter(sessionName);
1970
+ await delay(500);
1971
+ await sessionHelper.sendEnter(sessionName); // backup Enter
1972
+ // Give the agent a moment to start processing after Enter
1973
+ await delay(SESSION_COMMAND_DELAYS.MESSAGE_PROCESSING_DELAY);
1974
+ // Verify recovery: check if processing started
1975
+ const recoveryOutput = sessionHelper.capturePane(sessionName);
1976
+ if (TERMINAL_PATTERNS.PROCESSING.test(recoveryOutput)) {
1977
+ this.logger.info('Enter recovery successful — processing started', {
1978
+ sessionName,
1979
+ attempt,
1980
+ });
1981
+ claudeDelivered = true;
1982
+ break;
1983
+ }
1984
+ // Check if prompt reappeared (Enter submitted but processed instantly)
1985
+ // or if output changed from the stuck state
1986
+ const recoveryBottom = recoveryOutput.split('\n').slice(-10).join(' ').replace(/\s+/g, ' ');
1987
+ if (!recoveryBottom.includes(msgSnippet)) {
1988
+ this.logger.info('Enter recovery successful — stuck text cleared', {
1989
+ sessionName,
1990
+ attempt,
1991
+ });
1992
+ claudeDelivered = true;
1993
+ break;
1994
+ }
1995
+ // Still stuck after Enter recovery — continue to next interval
1996
+ this.logger.debug('Still stuck after Enter recovery, continuing verification', {
1997
+ sessionName,
1998
+ attempt,
1999
+ });
2000
+ await delay(intervalMs);
2001
+ continue;
2002
+ }
2003
+ // Prompt gone AND no stuck text → agent started processing
2004
+ this.logger.debug('Prompt gone, no stuck text — message delivered', {
2005
+ sessionName,
2006
+ attempt,
2007
+ });
2008
+ claudeDelivered = true;
2009
+ break;
2010
+ }
2011
+ if (claudeDelivered) {
2012
+ return true;
2013
+ }
2014
+ }
2015
+ else {
2016
+ // --- Phase 1: Direct stuck-at-prompt detection ---
2017
+ // Check if our message text is literally sitting on the `> ` prompt
2018
+ // line. This is the definitive signal that Enter was not pressed or
2019
+ // was silently consumed by the TUI. Unlike output-change detection,
2020
+ // this has no false positives from TUI redraws or historical text.
2021
+ const stuckAtPrompt = this.isTextStuckAtTuiPrompt(sessionName, message);
2022
+ if (stuckAtPrompt) {
2023
+ // Attempt immediate recovery: press Enter to submit the text
2024
+ const recovered = await this.recoverStuckTuiMessage(sessionName, message);
2025
+ if (recovered) {
2026
+ this.logger.info('Message recovered via Enter re-press', {
2027
+ sessionName,
2028
+ attempt,
2029
+ });
2030
+ return true;
2031
+ }
2032
+ // Still stuck after recovery — fall through to retry with cleanup
2033
+ this.logger.warn('Message still stuck after Enter recovery, will retry', {
2034
+ sessionName,
2035
+ attempt,
2036
+ });
2037
+ // Skip the output-change check — we know it's stuck
2038
+ }
2039
+ else {
2040
+ // --- Phase 2: Output-change detection ---
2041
+ // Text is NOT on the prompt line. Either it was delivered (Enter
2042
+ // worked) or it was never written (TUI was defocused and the Ink
2043
+ // framework consumed the text silently). Compare output snapshots.
2044
+ const afterOutput = sessionHelper.capturePane(sessionName, 20);
2045
+ const lengthDiff = afterOutput.length - beforeLength;
2046
+ const contentChanged = beforeOutput !== afterOutput;
2047
+ // CRITICAL: Only check for processing indicators in NEW content
2048
+ // (the diff between before and after). Checking the full afterOutput
2049
+ // causes false positives because words like "generating", "searching"
2050
+ // commonly appear in the agent's previous response text visible in
2051
+ // the 20-line capture.
2052
+ let newContent = '';
2053
+ if (contentChanged && afterOutput.length > beforeOutput.length) {
2054
+ newContent = afterOutput.slice(beforeLength);
2055
+ }
2056
+ else if (contentChanged) {
2057
+ const beforeLines = new Set(beforeOutput.split('\n'));
2058
+ newContent = afterOutput
2059
+ .split('\n')
2060
+ .filter((line) => !beforeLines.has(line))
2061
+ .join('\n');
2062
+ }
2063
+ const hasProcessingIndicators = TERMINAL_PATTERNS.PROCESSING_WITH_TEXT.test(newContent || afterOutput.slice(-500));
2064
+ const hasGeminiIndicators = newContent.length > 0
2065
+ && /reading|thinking|processing|analyzing|generating|searching/i.test(newContent);
2066
+ const significantLengthChange = Math.abs(lengthDiff) > 10;
2067
+ const delivered = (lengthDiff > 20)
2068
+ || (contentChanged && significantLengthChange)
2069
+ || hasProcessingIndicators
2070
+ || hasGeminiIndicators;
2071
+ if (delivered) {
2072
+ this.logger.debug('Message delivered successfully (TUI output changed)', {
2073
+ sessionName,
2074
+ attempt,
2075
+ lengthDiff,
2076
+ contentChanged,
2077
+ hasProcessingIndicators,
2078
+ hasGeminiIndicators,
2079
+ newContentLength: newContent.length,
2080
+ });
2081
+ return true;
2082
+ }
2083
+ this.logger.warn('TUI output did not change after send — message may not have been accepted', {
2084
+ sessionName,
2085
+ attempt,
2086
+ lengthDiff,
2087
+ contentChanged,
2088
+ hasProcessingIndicators,
2089
+ hasGeminiIndicators,
2090
+ newContentLength: newContent.length,
2091
+ });
2092
+ }
2093
+ }
2094
+ // Message stuck at prompt — clear line and retry.
2095
+ this.logger.warn('Message stuck at prompt after send, clearing for retry', {
2096
+ sessionName,
2097
+ attempt,
2098
+ });
2099
+ if (isClaudeCode) {
2100
+ await sessionHelper.clearCurrentCommandLine(sessionName);
2101
+ }
2102
+ else {
2103
+ // Gemini CLI retry cleanup: be careful with cleanup keystrokes.
2104
+ // If output changed (contentChanged=true), text likely reached the
2105
+ // input box but wasn't submitted — Ctrl+C safely clears it.
2106
+ // If output did NOT change at all, the TUI input is likely defocused
2107
+ // and the input box is EMPTY. Ctrl+C on an empty Gemini CLI prompt
2108
+ // triggers /quit and exits the CLI entirely.
2109
+ const noOutputChange = !isClaudeCode && beforeOutput === sessionHelper.capturePane(sessionName, 20);
2110
+ if (noOutputChange) {
2111
+ this.logger.warn('No output change detected — TUI input likely defocused, using Tab to cycle Ink focus', {
2112
+ sessionName,
2113
+ attempt,
2114
+ });
2115
+ // Tab triggers focusNext() in Ink's FocusContext, which should
2116
+ // cycle focus back to the InputPrompt component even when it's
2117
+ // defocused. This is more reliable than Enter (which is silently
2118
+ // consumed when no component is focused).
2119
+ await sessionHelper.sendKey(sessionName, 'Tab');
2120
+ await delay(300);
2121
+ await sessionHelper.sendEnter(sessionName);
2122
+ await delay(300);
2123
+ }
2124
+ else {
2125
+ await sessionHelper.sendCtrlC(sessionName);
2126
+ await delay(200);
2127
+ }
2128
+ }
2129
+ await delay(SESSION_COMMAND_DELAYS.CLEAR_COMMAND_DELAY);
2130
+ if (attempt < maxAttempts) {
2131
+ await delay(SESSION_COMMAND_DELAYS.MESSAGE_RETRY_DELAY);
2132
+ }
2133
+ }
2134
+ catch (error) {
2135
+ this.logger.error('Error during message delivery', {
2136
+ sessionName,
2137
+ attempt,
2138
+ error: error instanceof Error ? error.message : String(error),
2139
+ });
2140
+ if (attempt < maxAttempts) {
2141
+ await delay(SESSION_COMMAND_DELAYS.MESSAGE_RETRY_DELAY);
2142
+ }
2143
+ }
2144
+ }
2145
+ this.logger.error('Message delivery failed after all retry attempts', {
2146
+ sessionName,
2147
+ maxAttempts,
2148
+ messageLength: message.length,
2149
+ });
2150
+ return false;
2151
+ }
2152
+ /**
2153
+ * Check if a sent message is stuck at the terminal prompt (Enter was not accepted).
2154
+ *
2155
+ * Captures the current terminal pane and looks for the message text still visible
2156
+ * on the last few lines. If the text is found, Enter was not processed and the
2157
+ * message is stuck.
2158
+ *
2159
+ * @param sessionName - The session to check
2160
+ * @param message - The original message that was sent
2161
+ * @returns true if the message text is still visible at the prompt (stuck)
2162
+ */
2163
+ async isMessageStuckAtPrompt(sessionName, message) {
2164
+ try {
2165
+ const sessionHelper = await this.getSessionHelper();
2166
+ const output = sessionHelper.capturePane(sessionName);
2167
+ if (!output || output.trim().length === 0) {
2168
+ return false;
2169
+ }
2170
+ // Extract a search token from the message:
2171
+ // Strip [CHAT:uuid] prefix if present, then take the first 40 chars
2172
+ const chatPrefixMatch = message.match(/^\[CHAT:[^\]]+\]\s*/);
2173
+ const contentAfterPrefix = chatPrefixMatch
2174
+ ? message.slice(chatPrefixMatch[0].length)
2175
+ : message;
2176
+ const searchToken = contentAfterPrefix.slice(0, 40).trim();
2177
+ // Also use [CHAT: as a secondary token if message has a CHAT prefix
2178
+ const chatToken = chatPrefixMatch ? '[CHAT:' : null;
2179
+ // Check last 20 non-empty lines for either token.
2180
+ // Gemini CLI TUI has status bars at the bottom (branch, sandbox, model info)
2181
+ // that push input content further up. 5 lines was insufficient.
2182
+ const lines = output.split('\n').filter((line) => line.trim().length > 0);
2183
+ const linesToCheck = lines.slice(-20);
2184
+ const isStuck = linesToCheck.some((line) => {
2185
+ // Strip TUI box-drawing borders before checking (Gemini CLI wraps content in │...│)
2186
+ const stripped = line.replace(/^[│┃║|\s]+/, '').replace(/[│┃║|\s]+$/, '');
2187
+ if (searchToken && (line.includes(searchToken) || stripped.includes(searchToken)))
2188
+ return true;
2189
+ if (chatToken && (line.includes(chatToken) || stripped.includes(chatToken)))
2190
+ return true;
2191
+ return false;
2192
+ });
2193
+ this.logger.debug('isMessageStuckAtPrompt result', {
2194
+ sessionName,
2195
+ isStuck,
2196
+ searchToken: searchToken.slice(0, 20),
2197
+ linesChecked: linesToCheck.length,
2198
+ });
2199
+ return isStuck;
2200
+ }
2201
+ catch (error) {
2202
+ this.logger.warn('Error checking if message stuck at prompt', {
2203
+ sessionName,
2204
+ error: error instanceof Error ? error.message : String(error),
2205
+ });
2206
+ return false;
2207
+ }
2208
+ }
2209
+ /**
2210
+ * Check if message text is stuck at the TUI prompt line (Enter was not pressed).
2211
+ *
2212
+ * Unlike `isMessageStuckAtPrompt` which checks the last 20 lines for the message
2213
+ * text ANYWHERE, this method specifically checks whether the message text appears
2214
+ * ON the prompt line itself (the line starting with `> ` or `│ > `).
2215
+ *
2216
+ * After Enter is successfully pressed, the text moves from the prompt line to the
2217
+ * chat history area. So if the text is still on the prompt line, Enter was dropped.
2218
+ *
2219
+ * This avoids the false positive problem where `isMessageStuckAtPrompt` matches
2220
+ * the message text in the TUI's chat history (which echoes submitted messages).
2221
+ *
2222
+ * @param sessionName - The session to check
2223
+ * @param message - The original message that was sent
2224
+ * @returns true if the message text is visible on the TUI prompt line (stuck)
2225
+ */
2226
+ isTextStuckAtTuiPrompt(sessionName, message) {
2227
+ try {
2228
+ const sessionHelper = this._sessionHelper;
2229
+ if (!sessionHelper)
2230
+ return false;
2231
+ const output = sessionHelper.capturePane(sessionName);
2232
+ if (!output || output.trim().length === 0)
2233
+ return false;
2234
+ // Extract search token: first 30 chars of the message content
2235
+ // (after stripping any [CHAT:uuid] prefix)
2236
+ const chatPrefixMatch = message.match(/^\[CHAT:[^\]]+\]\s*/);
2237
+ const contentAfterPrefix = chatPrefixMatch
2238
+ ? message.slice(chatPrefixMatch[0].length)
2239
+ : message;
2240
+ const searchToken = contentAfterPrefix.slice(0, 30).trim();
2241
+ if (!searchToken)
2242
+ return false;
2243
+ // Find lines that look like a TUI prompt with text after it.
2244
+ // Gemini CLI TUI wraps content in box-drawing borders: │ > text │
2245
+ // Or without borders: > text
2246
+ // The prompt line is the line with `> ` followed by actual content.
2247
+ const lines = output.split('\n');
2248
+ const promptLineRegex = /^[│┃║|\s]*>\s+(.+)/;
2249
+ for (let i = lines.length - 1; i >= Math.max(0, lines.length - 25); i--) {
2250
+ const line = lines[i];
2251
+ const match = line.match(promptLineRegex);
2252
+ if (match) {
2253
+ const promptContent = match[1].replace(/[│┃║|\s]+$/, '').trim();
2254
+ // Check if the prompt line content contains our message text
2255
+ if (promptContent.length > 5 && promptContent.includes(searchToken)) {
2256
+ this.logger.warn('Text stuck at TUI prompt — Enter was not pressed', {
2257
+ sessionName,
2258
+ searchToken: searchToken.slice(0, 20),
2259
+ promptContent: promptContent.slice(0, 60),
2260
+ });
2261
+ return true;
2262
+ }
2263
+ }
2264
+ }
2265
+ return false;
2266
+ }
2267
+ catch (error) {
2268
+ this.logger.debug('Error in isTextStuckAtTuiPrompt', {
2269
+ sessionName,
2270
+ error: error instanceof Error ? error.message : String(error),
2271
+ });
2272
+ return false;
2273
+ }
2274
+ }
2275
+ /**
2276
+ * Attempt to recover from text stuck at TUI prompt by pressing Enter.
2277
+ * Checks if text is stuck, sends Enter, waits, then verifies.
2278
+ *
2279
+ * @param sessionName - The session to recover
2280
+ * @param message - The original message
2281
+ * @returns true if recovery succeeded (text is no longer at prompt)
2282
+ */
2283
+ async recoverStuckTuiMessage(sessionName, message) {
2284
+ const sessionHelper = await this.getSessionHelper();
2285
+ // Press Enter to submit the stuck text
2286
+ this.logger.info('Pressing Enter to recover stuck TUI message', { sessionName });
2287
+ await sessionHelper.sendEnter(sessionName);
2288
+ await delay(500);
2289
+ // Double-tap: send a backup Enter in case the first was consumed
2290
+ await sessionHelper.sendEnter(sessionName);
2291
+ await delay(2000);
2292
+ // Verify text is no longer at prompt
2293
+ const stillStuck = this.isTextStuckAtTuiPrompt(sessionName, message);
2294
+ if (!stillStuck) {
2295
+ this.logger.info('TUI message recovery succeeded — Enter accepted', { sessionName });
2296
+ return true;
2297
+ }
2298
+ this.logger.warn('TUI message still stuck after Enter recovery', { sessionName });
2299
+ return false;
2300
+ }
2301
+ /**
2302
+ * Start a background scanner that periodically checks all registered TUI
2303
+ * sessions for text stuck at the prompt (Enter not pressed).
2304
+ *
2305
+ * This is a safety net that catches messages missed by the per-send
2306
+ * verification in `sendMessageWithRetry`. It scans every 30 seconds.
2307
+ *
2308
+ * When stuck text is detected, the scanner presses Enter to recover.
2309
+ * If text has been sitting at the prompt for multiple consecutive scans,
2310
+ * it escalates to Tab + Enter (TUI focus recovery).
2311
+ */
2312
+ startStuckMessageDetector() {
2313
+ if (this.stuckMessageDetectorTimer) {
2314
+ this.logger.debug('Stuck message detector already running');
2315
+ return;
2316
+ }
2317
+ const SCAN_INTERVAL_MS = 30000; // 30 seconds
2318
+ this.logger.info('Starting background stuck-message detector', {
2319
+ intervalMs: SCAN_INTERVAL_MS,
2320
+ });
2321
+ this.stuckMessageDetectorTimer = setInterval(async () => {
2322
+ try {
2323
+ await this.scanForStuckMessages();
2324
+ }
2325
+ catch (error) {
2326
+ this.logger.debug('Stuck message scan error (non-fatal)', {
2327
+ error: error instanceof Error ? error.message : String(error),
2328
+ });
2329
+ }
2330
+ }, SCAN_INTERVAL_MS);
2331
+ }
2332
+ /**
2333
+ * Stop the background stuck-message detector.
2334
+ */
2335
+ stopStuckMessageDetector() {
2336
+ if (this.stuckMessageDetectorTimer) {
2337
+ clearInterval(this.stuckMessageDetectorTimer);
2338
+ this.stuckMessageDetectorTimer = null;
2339
+ this.logger.info('Stopped background stuck-message detector');
2340
+ }
2341
+ }
2342
+ /**
2343
+ * Scan all sessions for stuck messages. Two complementary strategies:
2344
+ *
2345
+ * 1. TUI prompt-line scanning (existing): checks registered TUI sessions
2346
+ * for text sitting on the `> ` prompt line.
2347
+ * 2. Tracked-message scanning (new, all runtimes): checks if any recently
2348
+ * sent message text is still visible at the bottom of the terminal
2349
+ * after 15+ seconds — runtime-agnostic Enter-drop detection.
2350
+ */
2351
+ async scanForStuckMessages() {
2352
+ const sessionHelper = this._sessionHelper;
2353
+ if (!sessionHelper)
2354
+ return;
2355
+ // --- Part 1: Existing TUI prompt-line scanning (unchanged) ---
2356
+ for (const [sessionName] of this.tuiSessionRegistry) {
2357
+ try {
2358
+ // Skip sessions that no longer exist
2359
+ if (!sessionHelper.sessionExists(sessionName)) {
2360
+ this.tuiSessionRegistry.delete(sessionName);
2361
+ continue;
2362
+ }
2363
+ const output = sessionHelper.capturePane(sessionName);
2364
+ if (!output || output.trim().length === 0)
2365
+ continue;
2366
+ // Look for any text sitting on the prompt line
2367
+ const lines = output.split('\n');
2368
+ const promptLineRegex = /^[│┃║|\s]*>\s+(.+)/;
2369
+ for (let i = lines.length - 1; i >= Math.max(0, lines.length - 25); i--) {
2370
+ const match = lines[i].match(promptLineRegex);
2371
+ if (match) {
2372
+ const promptContent = match[1].replace(/[│┃║|\s]+$/, '').trim();
2373
+ // Only act on substantial text (> 10 chars) to avoid false positives
2374
+ // from TUI rendering artifacts or short status text
2375
+ if (promptContent.length > 10) {
2376
+ // Skip known Gemini CLI idle placeholder text that sits at
2377
+ // the `> ` prompt when no user input is present. These are
2378
+ // NOT stuck messages — they are TUI decoration.
2379
+ const isPlaceholder = /^Type your message/i.test(promptContent) ||
2380
+ /^@[\w/.]+/.test(promptContent); // e.g., "@path/to/file"
2381
+ if (isPlaceholder) {
2382
+ break;
2383
+ }
2384
+ this.logger.warn('Background scan: text stuck at TUI prompt, pressing Enter', {
2385
+ sessionName,
2386
+ promptContent: promptContent.slice(0, 80),
2387
+ });
2388
+ // Press Enter to submit the stuck text
2389
+ await sessionHelper.sendEnter(sessionName);
2390
+ await delay(500);
2391
+ // Backup Enter
2392
+ await sessionHelper.sendEnter(sessionName);
2393
+ }
2394
+ break; // Only check the first prompt line found from the bottom
2395
+ }
2396
+ }
2397
+ }
2398
+ catch (error) {
2399
+ this.logger.debug('Error scanning session for stuck messages', {
2400
+ sessionName,
2401
+ error: error instanceof Error ? error.message : String(error),
2402
+ });
2403
+ }
2404
+ }
2405
+ // --- Part 2: Tracked-message scanning (all runtimes) ---
2406
+ const now = Date.now();
2407
+ const MIN_AGE_MS = 15000; // Only check messages older than 15s
2408
+ for (const [sessionName, entries] of this.sentMessageTracker) {
2409
+ if (!sessionHelper.sessionExists(sessionName)) {
2410
+ this.sentMessageTracker.delete(sessionName);
2411
+ continue;
2412
+ }
2413
+ try {
2414
+ const output = sessionHelper.capturePane(sessionName);
2415
+ if (!output || output.trim().length === 0)
2416
+ continue;
2417
+ const bottomText = output.split('\n').slice(-15).join(' ').replace(/\s+/g, ' ');
2418
+ for (const entry of entries) {
2419
+ if (entry.recovered)
2420
+ continue;
2421
+ if (now - entry.sentAt < MIN_AGE_MS)
2422
+ continue;
2423
+ if (bottomText.includes(entry.snippet)) {
2424
+ this.logger.warn('Background scan: tracked message stuck, pressing Enter', {
2425
+ sessionName,
2426
+ snippet: entry.snippet.slice(0, 50),
2427
+ ageMs: now - entry.sentAt,
2428
+ });
2429
+ await sessionHelper.sendEnter(sessionName);
2430
+ await delay(500);
2431
+ await sessionHelper.sendEnter(sessionName); // backup
2432
+ entry.recovered = true;
2433
+ break; // One recovery per session per scan cycle
2434
+ }
2435
+ }
2436
+ }
2437
+ catch (error) {
2438
+ this.logger.debug('Error scanning tracked messages for session', {
2439
+ sessionName,
2440
+ error: error instanceof Error ? error.message : String(error),
2441
+ });
2442
+ }
2443
+ }
2444
+ // Clean up old tracked-message entries
2445
+ for (const [sessionName, entries] of this.sentMessageTracker) {
2446
+ const fresh = entries.filter(e => now - e.sentAt < 5 * 60 * 1000);
2447
+ if (fresh.length === 0) {
2448
+ this.sentMessageTracker.delete(sessionName);
2449
+ }
2450
+ else {
2451
+ this.sentMessageTracker.set(sessionName, fresh);
2452
+ }
2453
+ }
2454
+ }
2455
+ /**
2456
+ * Unregister a TUI session from the stuck-message detector.
2457
+ * Call this when a session is destroyed or agent is stopped.
2458
+ *
2459
+ * @param sessionName - The session to unregister
2460
+ */
2461
+ unregisterTuiSession(sessionName) {
2462
+ this.tuiSessionRegistry.delete(sessionName);
2463
+ this.sentMessageTracker.delete(sessionName);
2464
+ }
2465
+ /**
2466
+ * Register a message that was sent to a session for background
2467
+ * stuck-detection. The scanner will periodically check if the
2468
+ * message text is still visible at the bottom of the terminal.
2469
+ *
2470
+ * @param sessionName - The session the message was sent to
2471
+ * @param message - The full message text
2472
+ */
2473
+ trackSentMessage(sessionName, message) {
2474
+ // Extract a search snippet: skip [CHAT:uuid] prefix, take first 80 chars
2475
+ const prefixMatch = message.match(/^\[CHAT:[^\]]+\]\s*/);
2476
+ const contentStart = prefixMatch ? prefixMatch[0].length : 0;
2477
+ // Normalize whitespace: messages may contain \n from enhanced templates.
2478
+ // Terminal bottom text is join(' '), so \n in snippet would never match.
2479
+ const snippet = message.slice(contentStart, contentStart + 80).replace(/\s+/g, ' ').trim();
2480
+ if (snippet.length < 10)
2481
+ return; // Too short to reliably match
2482
+ const entries = this.sentMessageTracker.get(sessionName) || [];
2483
+ entries.push({ snippet, sentAt: Date.now(), recovered: false });
2484
+ // Keep only last 5 minutes of entries
2485
+ const cutoff = Date.now() - 5 * 60 * 1000;
2486
+ this.sentMessageTracker.set(sessionName, entries.filter(e => e.sentAt > cutoff));
2487
+ // Ensure the background scanner is running
2488
+ this.startStuckMessageDetector();
2489
+ }
2490
+ /**
2491
+ * Check if Claude Code appears to be at an input prompt.
2492
+ * Looks for common prompt indicators in terminal output.
2493
+ *
2494
+ * @param terminalOutput - The terminal output to check
2495
+ * @returns true if Claude Code appears to be at a prompt
2496
+ */
2497
+ isClaudeAtPrompt(terminalOutput, runtimeType) {
2498
+ // Handle null/undefined/empty input gracefully
2499
+ if (!terminalOutput || typeof terminalOutput !== 'string') {
2500
+ this.logger.debug('Terminal output is empty or invalid, assuming at prompt');
2501
+ return true; // Assume at prompt if no output (safer for message delivery)
2502
+ }
2503
+ // Only analyze the tail of the buffer to avoid matching historical prompts
2504
+ const tailSection = terminalOutput.slice(-2000);
2505
+ const isGemini = runtimeType === RUNTIME_TYPES.GEMINI_CLI;
2506
+ const isClaudeCode = runtimeType === RUNTIME_TYPES.CLAUDE_CODE;
2507
+ // Use runtime-specific regex when runtime is known, combined pattern otherwise
2508
+ const streamPattern = isClaudeCode
2509
+ ? TERMINAL_PATTERNS.CLAUDE_CODE_PROMPT
2510
+ : isGemini
2511
+ ? TERMINAL_PATTERNS.GEMINI_CLI_PROMPT
2512
+ : TERMINAL_PATTERNS.PROMPT_STREAM;
2513
+ // Check for prompt FIRST. Processing indicators like "thinking" or "analyzing"
2514
+ // can appear in the agent's previous response text and persist in the terminal
2515
+ // scroll buffer, causing false negatives if checked before the prompt.
2516
+ if (streamPattern.test(tailSection)) {
2517
+ return true;
2518
+ }
2519
+ // Fallback: check last several lines for prompt indicators.
2520
+ // The prompt may not be on the very last line due to status bars,
2521
+ // notifications, or terminal wrapping below the prompt.
2522
+ const lines = tailSection.split('\n').filter((line) => line.trim().length > 0);
2523
+ const linesToCheck = lines.slice(-10);
2524
+ const hasPrompt = linesToCheck.some((line) => {
2525
+ const trimmed = line.trim();
2526
+ // Strip TUI box-drawing borders (│, ┃, etc.) that Gemini CLI wraps around prompts
2527
+ const stripped = trimmed.replace(/^[│┃|]+\s*/, '').replace(/\s*[│┃|]+$/, '');
2528
+ // Claude Code prompts: ❯, ⏵, $ alone on a line
2529
+ if (!isGemini) {
2530
+ if (['❯', '⏵', '$'].some(ch => trimmed === ch || stripped === ch)) {
2531
+ return true;
2532
+ }
2533
+ // ❯❯ = bypass permissions prompt (idle).
2534
+ // Matches "❯❯", "❯❯ ", and "❯❯ bypass permissions on (shift+tab to cycle)".
2535
+ // This line disappears during processing and reappears when idle.
2536
+ if (trimmed.startsWith('❯❯')) {
2537
+ return true;
2538
+ }
2539
+ }
2540
+ // Gemini CLI prompts: > or ! followed by space
2541
+ if (!isClaudeCode) {
2542
+ if (trimmed.startsWith('> ') || trimmed.startsWith('! ') ||
2543
+ stripped.startsWith('> ') || stripped.startsWith('! ')) {
2544
+ return true;
2545
+ }
2546
+ }
2547
+ return false;
2548
+ });
2549
+ if (hasPrompt) {
2550
+ return true;
2551
+ }
2552
+ // No prompt found — check if still processing. Only check the last few
2553
+ // lines to avoid matching words like "thinking" in historical response text.
2554
+ const recentLines = linesToCheck.slice(-5).join('\n');
2555
+ if (TERMINAL_PATTERNS.PROCESSING_WITH_TEXT.test(recentLines)) {
2556
+ this.logger.debug('Processing indicators present near bottom of output');
2557
+ return false;
2558
+ }
2559
+ return false;
2560
+ }
2561
+ /**
2562
+ * Detect if Gemini CLI is currently in shell mode.
2563
+ *
2564
+ * In shell mode, Gemini CLI changes its prompt from `>` to `!`. Any input
2565
+ * sent in this mode is executed as a shell command instead of being passed
2566
+ * to the model. This method examines the last few lines of terminal output
2567
+ * for shell mode prompt indicators.
2568
+ *
2569
+ * @param terminalOutput - Captured terminal pane content
2570
+ * @returns true if the terminal shows a shell mode prompt
2571
+ */
2572
+ isGeminiInShellMode(terminalOutput) {
2573
+ if (!terminalOutput || typeof terminalOutput !== 'string') {
2574
+ return false;
2575
+ }
2576
+ const lines = terminalOutput.split('\n').filter((line) => line.trim().length > 0);
2577
+ const linesToCheck = lines.slice(-10);
2578
+ return linesToCheck.some((line) => {
2579
+ const trimmed = line.trim();
2580
+ // Strip TUI box-drawing borders
2581
+ const stripped = trimmed.replace(/^[│┃|]+\s*/, '').replace(/\s*[│┃|]+$/, '');
2582
+ // Shell mode prompt: `!` alone or `! ` with text (not `> ` which is normal mode)
2583
+ // Check stripped line — after removing box-drawing, if it starts with `! ` or equals `!`
2584
+ if (stripped === '!' || stripped.startsWith('! ')) {
2585
+ return true;
2586
+ }
2587
+ // Also check pattern-based detection for bordered prompts
2588
+ return GEMINI_SHELL_MODE_CONSTANTS.SHELL_MODE_PROMPT_PATTERNS.some((pattern) => pattern.test(trimmed));
2589
+ });
2590
+ }
2591
+ /**
2592
+ * Escape from Gemini CLI shell mode by sending Escape key.
2593
+ *
2594
+ * Sends Escape and waits for the prompt to change from `!` back to `>`.
2595
+ * Retries up to MAX_ESCAPE_ATTEMPTS times.
2596
+ *
2597
+ * @param sessionName - The session running Gemini CLI
2598
+ * @param sessionHelper - SessionCommandHelper instance
2599
+ * @returns true if successfully escaped shell mode, false if still in shell mode
2600
+ */
2601
+ async escapeGeminiShellMode(sessionName, sessionHelper) {
2602
+ for (let attempt = 1; attempt <= GEMINI_SHELL_MODE_CONSTANTS.MAX_ESCAPE_ATTEMPTS; attempt++) {
2603
+ this.logger.info('Gemini CLI in shell mode, sending Escape to exit', {
2604
+ sessionName,
2605
+ attempt,
2606
+ });
2607
+ await sessionHelper.sendEscape(sessionName);
2608
+ await delay(GEMINI_SHELL_MODE_CONSTANTS.ESCAPE_DELAY_MS);
2609
+ // Check if we're back to normal mode
2610
+ const output = sessionHelper.capturePane(sessionName);
2611
+ if (!this.isGeminiInShellMode(output)) {
2612
+ this.logger.info('Successfully exited Gemini CLI shell mode', {
2613
+ sessionName,
2614
+ attempt,
2615
+ });
2616
+ return true;
2617
+ }
2618
+ }
2619
+ this.logger.warn('Failed to exit Gemini CLI shell mode after max attempts', {
2620
+ sessionName,
2621
+ maxAttempts: GEMINI_SHELL_MODE_CONSTANTS.MAX_ESCAPE_ATTEMPTS,
2622
+ });
2623
+ return false;
2624
+ }
2625
+ /**
2626
+ * Generic key sending to any agent session
2627
+ * @param sessionName The agent session name
2628
+ * @param key The key to send (e.g., 'Enter', 'Ctrl+C')
2629
+ * @returns Promise with success/error information
2630
+ */
2631
+ async sendKeyToAgent(sessionName, key) {
2632
+ try {
2633
+ // Get session helper once to avoid repeated async calls
2634
+ const sessionHelper = await this.getSessionHelper();
2635
+ // Check if session exists
2636
+ const sessionExists = sessionHelper.sessionExists(sessionName);
2637
+ if (!sessionExists) {
2638
+ return {
2639
+ success: false,
2640
+ error: `Session '${sessionName}' does not exist`,
2641
+ };
2642
+ }
2643
+ // Send key using session command helper
2644
+ await sessionHelper.sendKey(sessionName, key);
2645
+ this.logger.info('Key sent to agent successfully', {
2646
+ sessionName,
2647
+ key,
2648
+ });
2649
+ return {
2650
+ success: true,
2651
+ message: `${key} key sent to agent successfully`,
2652
+ };
2653
+ }
2654
+ catch (error) {
2655
+ const errorMessage = error instanceof Error ? error.message : String(error);
2656
+ this.logger.error('Failed to send key to agent', {
2657
+ sessionName,
2658
+ key,
2659
+ error: errorMessage,
2660
+ });
2661
+ return {
2662
+ success: false,
2663
+ error: errorMessage,
2664
+ };
2665
+ }
2666
+ }
2667
+ /**
2668
+ * Generic health check for any agent session
2669
+ * @param sessionName The agent session name
2670
+ * @param role The agent role for additional context
2671
+ * @param timeout Timeout for health check in milliseconds
2672
+ * @returns Promise with health status information
2673
+ */
2674
+ async checkAgentHealth(sessionName, role, timeout = 1000) {
2675
+ try {
2676
+ // Lightweight health check with timeout
2677
+ const agentRunning = await Promise.race([
2678
+ (await this.getSessionHelper()).sessionExists(sessionName),
2679
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Health check timeout')), timeout)),
2680
+ ]).catch(() => false);
2681
+ return {
2682
+ success: true,
2683
+ data: {
2684
+ agent: {
2685
+ sessionName,
2686
+ role,
2687
+ running: agentRunning,
2688
+ status: agentRunning
2689
+ ? CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE
2690
+ : CREWLY_CONSTANTS.AGENT_STATUSES.INACTIVE,
2691
+ },
2692
+ timestamp: new Date().toISOString(),
2693
+ },
2694
+ };
2695
+ }
2696
+ catch (error) {
2697
+ const errorMessage = error instanceof Error ? error.message : String(error);
2698
+ this.logger.error('Failed to check agent health', {
2699
+ sessionName,
2700
+ role,
2701
+ error: errorMessage,
2702
+ });
2703
+ return {
2704
+ success: false,
2705
+ error: errorMessage,
2706
+ };
2707
+ }
2708
+ }
2709
+ /**
2710
+ * Write the prompt to a file and send a short instruction to the agent to read it.
2711
+ *
2712
+ * Instead of pasting large multi-line prompts directly into the terminal (which
2713
+ * causes bracketed paste issues, shell interpretation errors, and truncation),
2714
+ * we write the prompt to ~/.crewly/prompts/{sessionName}-init.md and send a
2715
+ * single-line instruction telling the agent to read that file.
2716
+ *
2717
+ * @param sessionName The session name
2718
+ * @param prompt The full system prompt to deliver
2719
+ * @param runtimeType The agent runtime type
2720
+ * @param abortSignal Optional signal to cancel the operation (e.g. on runtime exit)
2721
+ * @returns true if the instruction was delivered successfully
2722
+ */
2723
+ async sendPromptRobustly(sessionName, prompt, runtimeType = RUNTIME_TYPES.CLAUDE_CODE, abortSignal) {
2724
+ const isClaudeCode = runtimeType === RUNTIME_TYPES.CLAUDE_CODE;
2725
+ const maxAttempts = isClaudeCode ? 1 : 3;
2726
+ const sessionHelper = await this.getSessionHelper();
2727
+ // Step 1: Write prompt to a file.
2728
+ // Claude Code: write to ~/.crewly/prompts/ (always accessible).
2729
+ // Gemini CLI / other TUI runtimes: write INSIDE the project directory
2730
+ // so the file is within the workspace allowlist. Gemini CLI restricts
2731
+ // file reads to workspace directories, and the /directory add command
2732
+ // to add ~/.crewly may fail (e.g., auto-update notification
2733
+ // interferes during postInitialize).
2734
+ const promptsDir = isClaudeCode
2735
+ ? path.join(os.homedir(), CREWLY_CONSTANTS.PATHS.CREWLY_HOME, 'prompts')
2736
+ : path.join(this.projectRoot, '.crewly', 'prompts');
2737
+ const promptFilePath = path.join(promptsDir, `${sessionName}-init.md`);
2738
+ try {
2739
+ await mkdir(promptsDir, { recursive: true });
2740
+ await writeFile(promptFilePath, prompt, 'utf8');
2741
+ this.logger.debug('Wrote init prompt to file', {
2742
+ sessionName,
2743
+ promptFilePath,
2744
+ promptLength: prompt.length,
2745
+ });
2746
+ }
2747
+ catch (error) {
2748
+ this.logger.error('Failed to write init prompt file', {
2749
+ sessionName,
2750
+ promptFilePath,
2751
+ error: error instanceof Error ? error.message : String(error),
2752
+ });
2753
+ return false;
2754
+ }
2755
+ // Step 2: Send a short instruction to read the file
2756
+ const instruction = `Read the file at ${promptFilePath} and follow all instructions in it.`;
2757
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
2758
+ // Check abort before each attempt
2759
+ if (abortSignal?.aborted) {
2760
+ this.logger.info('Prompt delivery aborted (runtime exited)', { sessionName, attempt });
2761
+ return false;
2762
+ }
2763
+ try {
2764
+ this.logger.debug('Sending file-based prompt instruction', {
2765
+ sessionName,
2766
+ attempt,
2767
+ runtimeType,
2768
+ promptFilePath,
2769
+ });
2770
+ // Capture state before sending
2771
+ const beforeOutput = sessionHelper.capturePane(sessionName, 10);
2772
+ const beforeLength = beforeOutput.length;
2773
+ // Check abort before sending to terminal
2774
+ if (abortSignal?.aborted) {
2775
+ this.logger.info('Prompt delivery aborted before send (runtime exited)', { sessionName });
2776
+ return false;
2777
+ }
2778
+ // Clear any pending input before sending the instruction.
2779
+ // Claude Code: Escape closes slash menus + Ctrl+U clears line.
2780
+ // Gemini CLI (Ink TUI): Do NOT send any cleanup keystrokes.
2781
+ // - Escape defocuses the Ink TUI input permanently (no recovery).
2782
+ // - Ctrl+C at empty prompt triggers /quit and exits the CLI.
2783
+ // - Ctrl+U is ignored by the TUI's custom key handling.
2784
+ // - Shift+Tab toggles safety modes, not focus.
2785
+ // The prompt should be clean at this point (just initialized or
2786
+ // addProjectToAllowlist just ran without defocusing).
2787
+ if (isClaudeCode) {
2788
+ await sessionHelper.sendEscape(sessionName);
2789
+ await delay(200);
2790
+ await sessionHelper.sendKey(sessionName, 'C-u');
2791
+ await delay(300);
2792
+ }
2793
+ // Check abort right before writing instruction to terminal
2794
+ if (abortSignal?.aborted) {
2795
+ this.logger.info('Prompt delivery aborted before instruction send (runtime exited)', { sessionName });
2796
+ return false;
2797
+ }
2798
+ // Send the short instruction
2799
+ await sessionHelper.sendMessage(sessionName, instruction);
2800
+ if (isClaudeCode) {
2801
+ // Claude Code may need an extra Enter after bracketed paste
2802
+ await delay(1000);
2803
+ if (abortSignal?.aborted)
2804
+ return false;
2805
+ await sessionHelper.sendEnter(sessionName);
2806
+ }
2807
+ // Wait for agent to start processing
2808
+ await delay(3000);
2809
+ if (abortSignal?.aborted)
2810
+ return false;
2811
+ // Verify delivery
2812
+ const afterOutput = sessionHelper.capturePane(sessionName, 20);
2813
+ const afterLength = afterOutput.length;
2814
+ const lengthIncrease = afterLength - beforeLength;
2815
+ const hasProcessingIndicators = /thinking|processing|analyzing|registering|reading/i.test(afterOutput);
2816
+ // For Claude Code, also check if the prompt disappeared (meaning
2817
+ // Claude accepted the input and is processing). Claude's UI often
2818
+ // collapses/redraws, making the output shorter — a negative
2819
+ // lengthIncrease does NOT mean delivery failed.
2820
+ const promptGone = isClaudeCode
2821
+ && !this.isClaudeAtPrompt(sessionHelper.capturePane(sessionName), RUNTIME_TYPES.CLAUDE_CODE);
2822
+ if (lengthIncrease > 20 || hasProcessingIndicators || promptGone) {
2823
+ this.logger.debug('Prompt instruction delivered successfully', {
2824
+ sessionName,
2825
+ attempt,
2826
+ lengthIncrease,
2827
+ hasProcessingIndicators,
2828
+ promptGone,
2829
+ runtimeType,
2830
+ });
2831
+ return true;
2832
+ }
2833
+ this.logger.warn('Prompt instruction delivery may have failed - retrying', {
2834
+ sessionName,
2835
+ attempt,
2836
+ lengthIncrease,
2837
+ runtimeType,
2838
+ });
2839
+ if (attempt < maxAttempts) {
2840
+ await delay(1000);
2841
+ }
2842
+ }
2843
+ catch (error) {
2844
+ this.logger.error('Error during prompt instruction delivery', {
2845
+ sessionName,
2846
+ attempt,
2847
+ runtimeType,
2848
+ error: error instanceof Error ? error.message : String(error),
2849
+ });
2850
+ if (attempt === maxAttempts) {
2851
+ return false;
2852
+ }
2853
+ }
2854
+ }
2855
+ this.logger.error('Failed to deliver prompt instruction after all attempts', {
2856
+ sessionName,
2857
+ maxAttempts,
2858
+ runtimeType,
2859
+ });
2860
+ return false;
2861
+ }
2862
+ }
2863
+ //# sourceMappingURL=agent-registration.service.js.map