crewly 1.13.0 → 1.14.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 (985) hide show
  1. package/config/constants.ts +8 -0
  2. package/config/roles/orchestrator/prompt.md +23 -0
  3. package/config/skills/_common/complete-body-shape.test.sh +113 -0
  4. package/config/skills/_common/no-dangling-symlinks.test.sh +63 -0
  5. package/config/skills/_common/task-pool-body-shape.test.sh +471 -0
  6. package/config/skills/agent/core/accept-task/execute.sh +30 -5
  7. package/config/skills/agent/core/block-task/execute.sh +59 -6
  8. package/config/skills/agent/core/complete-task/SKILL.md +37 -5
  9. package/config/skills/agent/core/complete-task/execute.sh +40 -9
  10. package/config/skills/agent/core/complete-task/execute.test.sh +213 -0
  11. package/config/skills/agent/core/create-task/SKILL.md +33 -0
  12. package/config/skills/agent/core/create-task/execute.sh +82 -23
  13. package/config/skills/agent/core/delegate-task/execute.sh +46 -0
  14. package/config/skills/agent/core/get-team-norms/SKILL.md +1 -1
  15. package/config/skills/agent/core/get-team-norms/execute.sh +73 -2
  16. package/config/skills/agent/core/handoff-task/execute.sh +8 -1
  17. package/config/skills/agent/core/reply-channel/SKILL.md +6 -0
  18. package/config/skills/agent/core/reply-channel/execute.sh +14 -2
  19. package/config/skills/agent/core/report-status/SKILL.md +26 -0
  20. package/config/skills/agent/core/report-status/execute.sh +40 -5
  21. package/config/skills/agent/core/slack-post/SKILL.md +126 -0
  22. package/config/skills/agent/core/slack-post/execute.sh +127 -0
  23. package/config/skills/agent/remote-browser/SKILL.md +178 -0
  24. package/config/skills/agent/xiaoyuzhoufm-transcript/SKILL.md +46 -22
  25. package/config/skills/agent/xiaoyuzhoufm-transcript/execute.sh +82 -214
  26. package/config/skills/agent/xiaoyuzhoufm-transcript/skill.json +3 -3
  27. package/config/skills/orchestrator/delegate-task/SKILL.md +1 -1
  28. package/config/skills/orchestrator/delegate-task/execute.sh +45 -11
  29. package/config/skills/orchestrator/delegate-task/execute.test.sh +153 -1
  30. package/config/skills/orchestrator/get-team-status/SKILL.md +5 -1
  31. package/config/skills/orchestrator/get-team-status/execute.sh +28 -2
  32. package/config/skills/team-leader/aggregate-results/SKILL.md +1 -1
  33. package/config/skills/team-leader/decompose-goal/execute.sh +11 -16
  34. package/config/skills/team-leader/delegate-task/SKILL.md +14 -1
  35. package/config/skills/team-leader/delegate-task/execute.sh +132 -43
  36. package/config/skills/team-leader/delegate-task/execute.test.sh +180 -27
  37. package/config/slack-app-manifest.json +7 -1
  38. package/config/vitest-exclude.constants.ts +56 -0
  39. package/dist/backend/backend/src/config/oauth.config.d.ts +93 -19
  40. package/dist/backend/backend/src/config/oauth.config.d.ts.map +1 -1
  41. package/dist/backend/backend/src/config/oauth.config.js +121 -19
  42. package/dist/backend/backend/src/config/oauth.config.js.map +1 -1
  43. package/dist/backend/backend/src/constants.d.ts +60 -0
  44. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  45. package/dist/backend/backend/src/constants.js +74 -0
  46. package/dist/backend/backend/src/constants.js.map +1 -1
  47. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
  48. package/dist/backend/backend/src/controllers/chat/chat.controller.js +33 -4
  49. package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
  50. package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.d.ts.map +1 -1
  51. package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.js +27 -9
  52. package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.js.map +1 -1
  53. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
  54. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +18 -3
  55. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
  56. package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
  57. package/dist/backend/backend/src/controllers/slack/slack.controller.js +360 -15
  58. package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
  59. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +6 -1
  60. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
  61. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +19 -10
  62. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
  63. package/dist/backend/backend/src/index.d.ts.map +1 -1
  64. package/dist/backend/backend/src/index.js +43 -7
  65. package/dist/backend/backend/src/index.js.map +1 -1
  66. package/dist/backend/backend/src/scripts/stamp-build.d.ts +25 -0
  67. package/dist/backend/backend/src/scripts/stamp-build.d.ts.map +1 -0
  68. package/dist/backend/backend/src/scripts/stamp-build.js +48 -0
  69. package/dist/backend/backend/src/scripts/stamp-build.js.map +1 -0
  70. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  71. package/dist/backend/backend/src/services/agent/agent-registration.service.js +25 -0
  72. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  73. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
  74. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +9 -1
  75. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
  76. package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts +42 -3
  77. package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts.map +1 -1
  78. package/dist/backend/backend/src/services/agent/crewly-agent/types.js +22 -1
  79. package/dist/backend/backend/src/services/agent/crewly-agent/types.js.map +1 -1
  80. package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts +10 -0
  81. package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts.map +1 -1
  82. package/dist/backend/backend/src/services/agent/idle-detection.service.js +37 -0
  83. package/dist/backend/backend/src/services/agent/idle-detection.service.js.map +1 -1
  84. package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts.map +1 -1
  85. package/dist/backend/backend/src/services/browser/browser-bridge.service.js +13 -11
  86. package/dist/backend/backend/src/services/browser/browser-bridge.service.js.map +1 -1
  87. package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts +14 -0
  88. package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts.map +1 -1
  89. package/dist/backend/backend/src/services/browser/browser-proxy.service.js +56 -0
  90. package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
  91. package/dist/backend/backend/src/services/browser/browser-services.registry.d.ts +63 -0
  92. package/dist/backend/backend/src/services/browser/browser-services.registry.d.ts.map +1 -0
  93. package/dist/backend/backend/src/services/browser/browser-services.registry.js +74 -0
  94. package/dist/backend/backend/src/services/browser/browser-services.registry.js.map +1 -0
  95. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +25 -1
  96. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
  97. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +19 -7
  98. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  99. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +57 -0
  100. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  101. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +110 -1
  102. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  103. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +21 -0
  104. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
  105. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +43 -0
  106. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
  107. package/dist/backend/backend/src/services/core/storage.service.d.ts +6 -0
  108. package/dist/backend/backend/src/services/core/storage.service.d.ts.map +1 -1
  109. package/dist/backend/backend/src/services/core/storage.service.js +1 -1
  110. package/dist/backend/backend/src/services/core/storage.service.js.map +1 -1
  111. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -1
  112. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +6 -2
  113. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -1
  114. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts +15 -0
  115. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -1
  116. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +54 -0
  117. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -1
  118. package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.d.ts +8 -0
  119. package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.d.ts.map +1 -1
  120. package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.js +31 -3
  121. package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.js.map +1 -1
  122. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.d.ts +28 -3
  123. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.d.ts.map +1 -1
  124. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js +65 -8
  125. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js.map +1 -1
  126. package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts +214 -4
  127. package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts.map +1 -1
  128. package/dist/backend/backend/src/services/reconciler/reconcile-rules.js +330 -48
  129. package/dist/backend/backend/src/services/reconciler/reconcile-rules.js.map +1 -1
  130. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts +47 -1
  131. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts.map +1 -1
  132. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js +183 -15
  133. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js.map +1 -1
  134. package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts +14 -0
  135. package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
  136. package/dist/backend/backend/src/services/reconciler/reconciler.service.js +77 -3
  137. package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
  138. package/dist/backend/backend/src/services/slack/slack-agent-identity.service.d.ts +209 -0
  139. package/dist/backend/backend/src/services/slack/slack-agent-identity.service.d.ts.map +1 -0
  140. package/dist/backend/backend/src/services/slack/slack-agent-identity.service.js +416 -0
  141. package/dist/backend/backend/src/services/slack/slack-agent-identity.service.js.map +1 -0
  142. package/dist/backend/backend/src/services/slack/slack-agent-post.service.d.ts +124 -0
  143. package/dist/backend/backend/src/services/slack/slack-agent-post.service.d.ts.map +1 -0
  144. package/dist/backend/backend/src/services/slack/slack-agent-post.service.js +243 -0
  145. package/dist/backend/backend/src/services/slack/slack-agent-post.service.js.map +1 -0
  146. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts +11 -0
  147. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
  148. package/dist/backend/backend/src/services/slack/slack-initializer.js +56 -0
  149. package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
  150. package/dist/backend/backend/src/services/slack/slack-mention-resolver.d.ts +103 -0
  151. package/dist/backend/backend/src/services/slack/slack-mention-resolver.d.ts.map +1 -0
  152. package/dist/backend/backend/src/services/slack/slack-mention-resolver.js +197 -0
  153. package/dist/backend/backend/src/services/slack/slack-mention-resolver.js.map +1 -0
  154. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  155. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +18 -0
  156. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  157. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +329 -0
  158. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -0
  159. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +821 -0
  160. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -0
  161. package/dist/backend/backend/src/services/slack/slack.service.d.ts +116 -1
  162. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
  163. package/dist/backend/backend/src/services/slack/slack.service.js +297 -3
  164. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
  165. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +152 -7
  166. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  167. package/dist/backend/backend/src/services/task-pool/task-pool.service.js +268 -36
  168. package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  169. package/dist/backend/backend/src/services/v3/escalation-router.service.js +2 -2
  170. package/dist/backend/backend/src/services/v3/escalation-router.service.js.map +1 -1
  171. package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -1
  172. package/dist/backend/backend/src/services/v3/request-sla.subscriber.js +39 -2
  173. package/dist/backend/backend/src/services/v3/request-sla.subscriber.js.map +1 -1
  174. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts +22 -0
  175. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts.map +1 -1
  176. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +71 -0
  177. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
  178. package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.d.ts +20 -2
  179. package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.d.ts.map +1 -1
  180. package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.js +27 -2
  181. package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.js.map +1 -1
  182. package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.d.ts +15 -2
  183. package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.d.ts.map +1 -1
  184. package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.js +33 -7
  185. package/dist/backend/backend/src/services/wiki/wiki-reflect-trigger.service.js.map +1 -1
  186. package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.d.ts +37 -0
  187. package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.d.ts.map +1 -1
  188. package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.js +74 -8
  189. package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.js.map +1 -1
  190. package/dist/backend/backend/src/types/slack.types.d.ts +87 -0
  191. package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
  192. package/dist/backend/backend/src/types/slack.types.js.map +1 -1
  193. package/dist/backend/backend/src/types/v2/index.d.ts +1 -1
  194. package/dist/backend/backend/src/types/v2/index.d.ts.map +1 -1
  195. package/dist/backend/backend/src/types/v2/index.js +1 -1
  196. package/dist/backend/backend/src/types/v2/index.js.map +1 -1
  197. package/dist/backend/backend/src/types/v2/work-item.types.d.ts +181 -1
  198. package/dist/backend/backend/src/types/v2/work-item.types.d.ts.map +1 -1
  199. package/dist/backend/backend/src/types/v2/work-item.types.js +104 -17
  200. package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
  201. package/dist/backend/backend/src/utils/build-provenance.d.ts +150 -0
  202. package/dist/backend/backend/src/utils/build-provenance.d.ts.map +1 -0
  203. package/dist/backend/backend/src/utils/build-provenance.js +211 -0
  204. package/dist/backend/backend/src/utils/build-provenance.js.map +1 -0
  205. package/dist/backend/build-info.json +4 -0
  206. package/dist/backend/config/constants.d.ts +8 -0
  207. package/dist/backend/config/constants.d.ts.map +1 -1
  208. package/dist/backend/config/constants.js +8 -0
  209. package/dist/backend/config/constants.js.map +1 -1
  210. package/dist/backend/config/vitest-exclude.constants.d.ts +53 -0
  211. package/dist/backend/config/vitest-exclude.constants.d.ts.map +1 -0
  212. package/dist/backend/config/vitest-exclude.constants.js +55 -0
  213. package/dist/backend/config/vitest-exclude.constants.js.map +1 -0
  214. package/dist/cli/backend/src/config/oauth.config.d.ts +93 -19
  215. package/dist/cli/backend/src/config/oauth.config.d.ts.map +1 -1
  216. package/dist/cli/backend/src/config/oauth.config.js +121 -19
  217. package/dist/cli/backend/src/config/oauth.config.js.map +1 -1
  218. package/dist/cli/backend/src/constants.d.ts +60 -0
  219. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  220. package/dist/cli/backend/src/constants.js +74 -0
  221. package/dist/cli/backend/src/constants.js.map +1 -1
  222. package/dist/cli/backend/src/services/agent/active-work-briefing.service.d.ts +538 -0
  223. package/dist/cli/backend/src/services/agent/active-work-briefing.service.d.ts.map +1 -0
  224. package/dist/cli/backend/src/services/agent/active-work-briefing.service.js +802 -0
  225. package/dist/cli/backend/src/services/agent/active-work-briefing.service.js.map +1 -0
  226. package/dist/cli/backend/src/services/agent/agent-heartbeat.service.d.ts +240 -0
  227. package/dist/cli/backend/src/services/agent/agent-heartbeat.service.d.ts.map +1 -0
  228. package/dist/cli/backend/src/services/agent/agent-heartbeat.service.js +524 -0
  229. package/dist/cli/backend/src/services/agent/agent-heartbeat.service.js.map +1 -0
  230. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +629 -0
  231. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -0
  232. package/dist/cli/backend/src/services/agent/agent-registration.service.js +4548 -0
  233. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -0
  234. package/dist/cli/backend/src/services/agent/agent-suspend.service.d.ts +118 -0
  235. package/dist/cli/backend/src/services/agent/agent-suspend.service.d.ts.map +1 -0
  236. package/dist/cli/backend/src/services/agent/agent-suspend.service.js +304 -0
  237. package/dist/cli/backend/src/services/agent/agent-suspend.service.js.map +1 -0
  238. package/dist/cli/backend/src/services/agent/auditor-scheduler.service.d.ts +196 -0
  239. package/dist/cli/backend/src/services/agent/auditor-scheduler.service.d.ts.map +1 -0
  240. package/dist/cli/backend/src/services/agent/auditor-scheduler.service.js +504 -0
  241. package/dist/cli/backend/src/services/agent/auditor-scheduler.service.js.map +1 -0
  242. package/dist/cli/backend/src/services/agent/claude-runtime.service.d.ts +97 -0
  243. package/dist/cli/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -0
  244. package/dist/cli/backend/src/services/agent/claude-runtime.service.js +334 -0
  245. package/dist/cli/backend/src/services/agent/claude-runtime.service.js.map +1 -0
  246. package/dist/cli/backend/src/services/agent/codex-runtime.service.d.ts +47 -0
  247. package/dist/cli/backend/src/services/agent/codex-runtime.service.d.ts.map +1 -0
  248. package/dist/cli/backend/src/services/agent/codex-runtime.service.js +112 -0
  249. package/dist/cli/backend/src/services/agent/codex-runtime.service.js.map +1 -0
  250. package/dist/cli/backend/src/services/agent/context-window-monitor.service.d.ts +323 -0
  251. package/dist/cli/backend/src/services/agent/context-window-monitor.service.d.ts.map +1 -0
  252. package/dist/cli/backend/src/services/agent/context-window-monitor.service.js +1056 -0
  253. package/dist/cli/backend/src/services/agent/context-window-monitor.service.js.map +1 -0
  254. package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts +198 -0
  255. package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -0
  256. package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +816 -0
  257. package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -0
  258. package/dist/cli/backend/src/services/agent/crewly-agent/in-process-log-buffer.d.ts +155 -0
  259. package/dist/cli/backend/src/services/agent/crewly-agent/in-process-log-buffer.d.ts.map +1 -0
  260. package/dist/cli/backend/src/services/agent/crewly-agent/in-process-log-buffer.js +272 -0
  261. package/dist/cli/backend/src/services/agent/crewly-agent/in-process-log-buffer.js.map +1 -0
  262. package/dist/cli/backend/src/services/agent/crewly-agent/in-process-runtime-registry.d.ts +91 -0
  263. package/dist/cli/backend/src/services/agent/crewly-agent/in-process-runtime-registry.d.ts.map +1 -0
  264. package/dist/cli/backend/src/services/agent/crewly-agent/in-process-runtime-registry.js +120 -0
  265. package/dist/cli/backend/src/services/agent/crewly-agent/in-process-runtime-registry.js.map +1 -0
  266. package/dist/cli/backend/src/services/agent/crewly-agent/types.d.ts +536 -0
  267. package/dist/cli/backend/src/services/agent/crewly-agent/types.d.ts.map +1 -0
  268. package/dist/cli/backend/src/services/agent/crewly-agent/types.js +282 -0
  269. package/dist/cli/backend/src/services/agent/crewly-agent/types.js.map +1 -0
  270. package/dist/cli/backend/src/services/agent/disk-cleanup.service.d.ts +100 -0
  271. package/dist/cli/backend/src/services/agent/disk-cleanup.service.d.ts.map +1 -0
  272. package/dist/cli/backend/src/services/agent/disk-cleanup.service.js +149 -0
  273. package/dist/cli/backend/src/services/agent/disk-cleanup.service.js.map +1 -0
  274. package/dist/cli/backend/src/services/agent/gemini-runtime.service.d.ts +130 -0
  275. package/dist/cli/backend/src/services/agent/gemini-runtime.service.d.ts.map +1 -0
  276. package/dist/cli/backend/src/services/agent/gemini-runtime.service.js +758 -0
  277. package/dist/cli/backend/src/services/agent/gemini-runtime.service.js.map +1 -0
  278. package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts +216 -0
  279. package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts.map +1 -0
  280. package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.js +508 -0
  281. package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.js.map +1 -0
  282. package/dist/cli/backend/src/services/agent/pty-activity-tracker.service.d.ts +113 -0
  283. package/dist/cli/backend/src/services/agent/pty-activity-tracker.service.d.ts.map +1 -0
  284. package/dist/cli/backend/src/services/agent/pty-activity-tracker.service.js +161 -0
  285. package/dist/cli/backend/src/services/agent/pty-activity-tracker.service.js.map +1 -0
  286. package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.d.ts +156 -0
  287. package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -0
  288. package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js +641 -0
  289. package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -0
  290. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts +295 -0
  291. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -0
  292. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js +1166 -0
  293. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -0
  294. package/dist/cli/backend/src/services/agent/runtime-service.factory.d.ts +71 -0
  295. package/dist/cli/backend/src/services/agent/runtime-service.factory.d.ts.map +1 -0
  296. package/dist/cli/backend/src/services/agent/runtime-service.factory.js +174 -0
  297. package/dist/cli/backend/src/services/agent/runtime-service.factory.js.map +1 -0
  298. package/dist/cli/backend/src/services/ai/prompt-builder.service.d.ts +435 -0
  299. package/dist/cli/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -0
  300. package/dist/cli/backend/src/services/ai/prompt-builder.service.js +1331 -0
  301. package/dist/cli/backend/src/services/ai/prompt-builder.service.js.map +1 -0
  302. package/dist/cli/backend/src/services/ai/prompt-modules/capability-overlay.module.d.ts +33 -0
  303. package/dist/cli/backend/src/services/ai/prompt-modules/capability-overlay.module.d.ts.map +1 -0
  304. package/dist/cli/backend/src/services/ai/prompt-modules/capability-overlay.module.js +70 -0
  305. package/dist/cli/backend/src/services/ai/prompt-modules/capability-overlay.module.js.map +1 -0
  306. package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.d.ts +100 -0
  307. package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.d.ts.map +1 -0
  308. package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js +296 -0
  309. package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -0
  310. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts +59 -0
  311. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts.map +1 -0
  312. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.js +87 -0
  313. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.js.map +1 -0
  314. package/dist/cli/backend/src/services/ai/prompt-modules/default-execution-loop.module.d.ts +67 -0
  315. package/dist/cli/backend/src/services/ai/prompt-modules/default-execution-loop.module.d.ts.map +1 -0
  316. package/dist/cli/backend/src/services/ai/prompt-modules/default-execution-loop.module.js +84 -0
  317. package/dist/cli/backend/src/services/ai/prompt-modules/default-execution-loop.module.js.map +1 -0
  318. package/dist/cli/backend/src/services/ai/prompt-modules/domain-sop.module.d.ts +35 -0
  319. package/dist/cli/backend/src/services/ai/prompt-modules/domain-sop.module.d.ts.map +1 -0
  320. package/dist/cli/backend/src/services/ai/prompt-modules/domain-sop.module.js +50 -0
  321. package/dist/cli/backend/src/services/ai/prompt-modules/domain-sop.module.js.map +1 -0
  322. package/dist/cli/backend/src/services/ai/prompt-modules/expert-profile.module.d.ts +41 -0
  323. package/dist/cli/backend/src/services/ai/prompt-modules/expert-profile.module.d.ts.map +1 -0
  324. package/dist/cli/backend/src/services/ai/prompt-modules/expert-profile.module.js +95 -0
  325. package/dist/cli/backend/src/services/ai/prompt-modules/expert-profile.module.js.map +1 -0
  326. package/dist/cli/backend/src/services/ai/prompt-modules/identity.module.d.ts +28 -0
  327. package/dist/cli/backend/src/services/ai/prompt-modules/identity.module.d.ts.map +1 -0
  328. package/dist/cli/backend/src/services/ai/prompt-modules/identity.module.js +47 -0
  329. package/dist/cli/backend/src/services/ai/prompt-modules/identity.module.js.map +1 -0
  330. package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.d.ts +65 -0
  331. package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.d.ts.map +1 -0
  332. package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js +79 -0
  333. package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js.map +1 -0
  334. package/dist/cli/backend/src/services/ai/prompt-modules/learning-reference.module.d.ts +28 -0
  335. package/dist/cli/backend/src/services/ai/prompt-modules/learning-reference.module.d.ts.map +1 -0
  336. package/dist/cli/backend/src/services/ai/prompt-modules/learning-reference.module.js +55 -0
  337. package/dist/cli/backend/src/services/ai/prompt-modules/learning-reference.module.js.map +1 -0
  338. package/dist/cli/backend/src/services/ai/prompt-modules/lifecycle.module.d.ts +44 -0
  339. package/dist/cli/backend/src/services/ai/prompt-modules/lifecycle.module.d.ts.map +1 -0
  340. package/dist/cli/backend/src/services/ai/prompt-modules/lifecycle.module.js +120 -0
  341. package/dist/cli/backend/src/services/ai/prompt-modules/lifecycle.module.js.map +1 -0
  342. package/dist/cli/backend/src/services/ai/prompt-modules/markdown-file-module.d.ts +46 -0
  343. package/dist/cli/backend/src/services/ai/prompt-modules/markdown-file-module.d.ts.map +1 -0
  344. package/dist/cli/backend/src/services/ai/prompt-modules/markdown-file-module.js +44 -0
  345. package/dist/cli/backend/src/services/ai/prompt-modules/markdown-file-module.js.map +1 -0
  346. package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.d.ts +28 -0
  347. package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.d.ts.map +1 -0
  348. package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.js +46 -0
  349. package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.js.map +1 -0
  350. package/dist/cli/backend/src/services/ai/prompt-modules/mission-context.module.d.ts +60 -0
  351. package/dist/cli/backend/src/services/ai/prompt-modules/mission-context.module.d.ts.map +1 -0
  352. package/dist/cli/backend/src/services/ai/prompt-modules/mission-context.module.js +104 -0
  353. package/dist/cli/backend/src/services/ai/prompt-modules/mission-context.module.js.map +1 -0
  354. package/dist/cli/backend/src/services/ai/prompt-modules/project-reference.module.d.ts +29 -0
  355. package/dist/cli/backend/src/services/ai/prompt-modules/project-reference.module.d.ts.map +1 -0
  356. package/dist/cli/backend/src/services/ai/prompt-modules/project-reference.module.js +50 -0
  357. package/dist/cli/backend/src/services/ai/prompt-modules/project-reference.module.js.map +1 -0
  358. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.d.ts +103 -0
  359. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.d.ts.map +1 -0
  360. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.js +383 -0
  361. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-assembly.service.js.map +1 -0
  362. package/dist/cli/backend/src/services/ai/prompt-modules/recovery.module.d.ts +34 -0
  363. package/dist/cli/backend/src/services/ai/prompt-modules/recovery.module.d.ts.map +1 -0
  364. package/dist/cli/backend/src/services/ai/prompt-modules/recovery.module.js +96 -0
  365. package/dist/cli/backend/src/services/ai/prompt-modules/recovery.module.js.map +1 -0
  366. package/dist/cli/backend/src/services/ai/prompt-modules/request-contract.module.d.ts +106 -0
  367. package/dist/cli/backend/src/services/ai/prompt-modules/request-contract.module.d.ts.map +1 -0
  368. package/dist/cli/backend/src/services/ai/prompt-modules/request-contract.module.js +167 -0
  369. package/dist/cli/backend/src/services/ai/prompt-modules/request-contract.module.js.map +1 -0
  370. package/dist/cli/backend/src/services/ai/prompt-modules/risk-policy.module.d.ts +35 -0
  371. package/dist/cli/backend/src/services/ai/prompt-modules/risk-policy.module.d.ts.map +1 -0
  372. package/dist/cli/backend/src/services/ai/prompt-modules/risk-policy.module.js +50 -0
  373. package/dist/cli/backend/src/services/ai/prompt-modules/risk-policy.module.js.map +1 -0
  374. package/dist/cli/backend/src/services/ai/prompt-modules/role-boundary.module.d.ts +91 -0
  375. package/dist/cli/backend/src/services/ai/prompt-modules/role-boundary.module.d.ts.map +1 -0
  376. package/dist/cli/backend/src/services/ai/prompt-modules/role-boundary.module.js +411 -0
  377. package/dist/cli/backend/src/services/ai/prompt-modules/role-boundary.module.js.map +1 -0
  378. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts +62 -0
  379. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -0
  380. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +199 -0
  381. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -0
  382. package/dist/cli/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts +79 -0
  383. package/dist/cli/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts.map +1 -0
  384. package/dist/cli/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js +118 -0
  385. package/dist/cli/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js.map +1 -0
  386. package/dist/cli/backend/src/services/ai/prompt-modules/soul.module.d.ts +102 -0
  387. package/dist/cli/backend/src/services/ai/prompt-modules/soul.module.d.ts.map +1 -0
  388. package/dist/cli/backend/src/services/ai/prompt-modules/soul.module.js +229 -0
  389. package/dist/cli/backend/src/services/ai/prompt-modules/soul.module.js.map +1 -0
  390. package/dist/cli/backend/src/services/ai/prompt-modules/team-norms.module.d.ts +61 -0
  391. package/dist/cli/backend/src/services/ai/prompt-modules/team-norms.module.d.ts.map +1 -0
  392. package/dist/cli/backend/src/services/ai/prompt-modules/team-norms.module.js +197 -0
  393. package/dist/cli/backend/src/services/ai/prompt-modules/team-norms.module.js.map +1 -0
  394. package/dist/cli/backend/src/services/ai/prompt-modules/team-reference.module.d.ts +54 -0
  395. package/dist/cli/backend/src/services/ai/prompt-modules/team-reference.module.d.ts.map +1 -0
  396. package/dist/cli/backend/src/services/ai/prompt-modules/team-reference.module.js +149 -0
  397. package/dist/cli/backend/src/services/ai/prompt-modules/team-reference.module.js.map +1 -0
  398. package/dist/cli/backend/src/services/ai/prompt-modules/user-profile-reference.module.d.ts +32 -0
  399. package/dist/cli/backend/src/services/ai/prompt-modules/user-profile-reference.module.d.ts.map +1 -0
  400. package/dist/cli/backend/src/services/ai/prompt-modules/user-profile-reference.module.js +69 -0
  401. package/dist/cli/backend/src/services/ai/prompt-modules/user-profile-reference.module.js.map +1 -0
  402. package/dist/cli/backend/src/services/ai/prompt-modules/working-memory.module.d.ts +91 -0
  403. package/dist/cli/backend/src/services/ai/prompt-modules/working-memory.module.d.ts.map +1 -0
  404. package/dist/cli/backend/src/services/ai/prompt-modules/working-memory.module.js +136 -0
  405. package/dist/cli/backend/src/services/ai/prompt-modules/working-memory.module.js.map +1 -0
  406. package/dist/cli/backend/src/services/ai/self-improvement/growth-areas.service.d.ts +81 -0
  407. package/dist/cli/backend/src/services/ai/self-improvement/growth-areas.service.d.ts.map +1 -0
  408. package/dist/cli/backend/src/services/ai/self-improvement/growth-areas.service.js +135 -0
  409. package/dist/cli/backend/src/services/ai/self-improvement/growth-areas.service.js.map +1 -0
  410. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +292 -0
  411. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -0
  412. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +420 -0
  413. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -0
  414. package/dist/cli/backend/src/services/chat-v2/chat-v2.mention-resolver.d.ts +134 -0
  415. package/dist/cli/backend/src/services/chat-v2/chat-v2.mention-resolver.d.ts.map +1 -0
  416. package/dist/cli/backend/src/services/chat-v2/chat-v2.mention-resolver.js +232 -0
  417. package/dist/cli/backend/src/services/chat-v2/chat-v2.mention-resolver.js.map +1 -0
  418. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts +794 -0
  419. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -0
  420. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js +1322 -0
  421. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js.map +1 -0
  422. package/dist/cli/backend/src/services/chat-v2/chat-v2.singleton.d.ts +27 -0
  423. package/dist/cli/backend/src/services/chat-v2/chat-v2.singleton.d.ts.map +1 -0
  424. package/dist/cli/backend/src/services/chat-v2/chat-v2.singleton.js +57 -0
  425. package/dist/cli/backend/src/services/chat-v2/chat-v2.singleton.js.map +1 -0
  426. package/dist/cli/backend/src/services/chat-v2/config.d.ts +100 -0
  427. package/dist/cli/backend/src/services/chat-v2/config.d.ts.map +1 -0
  428. package/dist/cli/backend/src/services/chat-v2/config.js +174 -0
  429. package/dist/cli/backend/src/services/chat-v2/config.js.map +1 -0
  430. package/dist/cli/backend/src/services/chat-v2/legacy-dto.utils.d.ts +118 -0
  431. package/dist/cli/backend/src/services/chat-v2/legacy-dto.utils.d.ts.map +1 -0
  432. package/dist/cli/backend/src/services/chat-v2/legacy-dto.utils.js +171 -0
  433. package/dist/cli/backend/src/services/chat-v2/legacy-dto.utils.js.map +1 -0
  434. package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.d.ts +188 -0
  435. package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.d.ts.map +1 -0
  436. package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.js +317 -0
  437. package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.js.map +1 -0
  438. package/dist/cli/backend/src/services/chat-v2/sqlite/chat-db.d.ts +119 -0
  439. package/dist/cli/backend/src/services/chat-v2/sqlite/chat-db.d.ts.map +1 -0
  440. package/dist/cli/backend/src/services/chat-v2/sqlite/chat-db.js +551 -0
  441. package/dist/cli/backend/src/services/chat-v2/sqlite/chat-db.js.map +1 -0
  442. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts +229 -0
  443. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -0
  444. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js +448 -0
  445. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -0
  446. package/dist/cli/backend/src/services/chat-v2/types.d.ts +341 -0
  447. package/dist/cli/backend/src/services/chat-v2/types.d.ts.map +1 -0
  448. package/dist/cli/backend/src/services/chat-v2/types.js +61 -0
  449. package/dist/cli/backend/src/services/chat-v2/types.js.map +1 -0
  450. package/dist/cli/backend/src/services/continuation/patterns/idle-patterns.d.ts +37 -0
  451. package/dist/cli/backend/src/services/continuation/patterns/idle-patterns.d.ts.map +1 -0
  452. package/dist/cli/backend/src/services/continuation/patterns/idle-patterns.js +63 -0
  453. package/dist/cli/backend/src/services/continuation/patterns/idle-patterns.js.map +1 -0
  454. package/dist/cli/backend/src/services/core/storage.service.d.ts +6 -0
  455. package/dist/cli/backend/src/services/core/storage.service.d.ts.map +1 -1
  456. package/dist/cli/backend/src/services/core/storage.service.js +1 -1
  457. package/dist/cli/backend/src/services/core/storage.service.js.map +1 -1
  458. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -1
  459. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +6 -2
  460. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -1
  461. package/dist/cli/backend/src/services/intent-task/intent-classifier.rules.d.ts +335 -0
  462. package/dist/cli/backend/src/services/intent-task/intent-classifier.rules.d.ts.map +1 -0
  463. package/dist/cli/backend/src/services/intent-task/intent-classifier.rules.js +421 -0
  464. package/dist/cli/backend/src/services/intent-task/intent-classifier.rules.js.map +1 -0
  465. package/dist/cli/backend/src/services/mcp-client.d.ts +233 -0
  466. package/dist/cli/backend/src/services/mcp-client.d.ts.map +1 -0
  467. package/dist/cli/backend/src/services/mcp-client.js +302 -0
  468. package/dist/cli/backend/src/services/mcp-client.js.map +1 -0
  469. package/dist/cli/backend/src/services/memory/mission-context.service.d.ts +168 -0
  470. package/dist/cli/backend/src/services/memory/mission-context.service.d.ts.map +1 -0
  471. package/dist/cli/backend/src/services/memory/mission-context.service.js +365 -0
  472. package/dist/cli/backend/src/services/memory/mission-context.service.js.map +1 -0
  473. package/dist/cli/backend/src/services/memory/session-memory.service.d.ts +197 -0
  474. package/dist/cli/backend/src/services/memory/session-memory.service.d.ts.map +1 -0
  475. package/dist/cli/backend/src/services/memory/session-memory.service.js +369 -0
  476. package/dist/cli/backend/src/services/memory/session-memory.service.js.map +1 -0
  477. package/dist/cli/backend/src/services/memory/user-profile.service.d.ts +77 -0
  478. package/dist/cli/backend/src/services/memory/user-profile.service.d.ts.map +1 -0
  479. package/dist/cli/backend/src/services/memory/user-profile.service.js +171 -0
  480. package/dist/cli/backend/src/services/memory/user-profile.service.js.map +1 -0
  481. package/dist/cli/backend/src/services/memory/working-memory.service.d.ts +232 -0
  482. package/dist/cli/backend/src/services/memory/working-memory.service.d.ts.map +1 -0
  483. package/dist/cli/backend/src/services/memory/working-memory.service.js +417 -0
  484. package/dist/cli/backend/src/services/memory/working-memory.service.js.map +1 -0
  485. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +84 -0
  486. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -0
  487. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js +136 -0
  488. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -0
  489. package/dist/cli/backend/src/services/messaging/thread-status-queue.service.d.ts +358 -0
  490. package/dist/cli/backend/src/services/messaging/thread-status-queue.service.d.ts.map +1 -0
  491. package/dist/cli/backend/src/services/messaging/thread-status-queue.service.js +755 -0
  492. package/dist/cli/backend/src/services/messaging/thread-status-queue.service.js.map +1 -0
  493. package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts +269 -0
  494. package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -0
  495. package/dist/cli/backend/src/services/monitoring/token-usage.service.js +391 -0
  496. package/dist/cli/backend/src/services/monitoring/token-usage.service.js.map +1 -0
  497. package/dist/cli/backend/src/services/observability/agent-behavior-log.service.d.ts +132 -0
  498. package/dist/cli/backend/src/services/observability/agent-behavior-log.service.d.ts.map +1 -0
  499. package/dist/cli/backend/src/services/observability/agent-behavior-log.service.js +284 -0
  500. package/dist/cli/backend/src/services/observability/agent-behavior-log.service.js.map +1 -0
  501. package/dist/cli/backend/src/services/observability/agent-behavior-log.singleton.d.ts +70 -0
  502. package/dist/cli/backend/src/services/observability/agent-behavior-log.singleton.d.ts.map +1 -0
  503. package/dist/cli/backend/src/services/observability/agent-behavior-log.singleton.js +121 -0
  504. package/dist/cli/backend/src/services/observability/agent-behavior-log.singleton.js.map +1 -0
  505. package/dist/cli/backend/src/services/observability/agent-behavior-log.types.d.ts +130 -0
  506. package/dist/cli/backend/src/services/observability/agent-behavior-log.types.d.ts.map +1 -0
  507. package/dist/cli/backend/src/services/observability/agent-behavior-log.types.js +48 -0
  508. package/dist/cli/backend/src/services/observability/agent-behavior-log.types.js.map +1 -0
  509. package/dist/cli/backend/src/services/observability/observability-db.d.ts +84 -0
  510. package/dist/cli/backend/src/services/observability/observability-db.d.ts.map +1 -0
  511. package/dist/cli/backend/src/services/observability/observability-db.js +165 -0
  512. package/dist/cli/backend/src/services/observability/observability-db.js.map +1 -0
  513. package/dist/cli/backend/src/services/onboarding/content-approval.service.d.ts +124 -0
  514. package/dist/cli/backend/src/services/onboarding/content-approval.service.d.ts.map +1 -0
  515. package/dist/cli/backend/src/services/onboarding/content-approval.service.js +256 -0
  516. package/dist/cli/backend/src/services/onboarding/content-approval.service.js.map +1 -0
  517. package/dist/cli/backend/src/services/onboarding/content-approval.types.d.ts +80 -0
  518. package/dist/cli/backend/src/services/onboarding/content-approval.types.d.ts.map +1 -0
  519. package/dist/cli/backend/src/services/onboarding/content-approval.types.js +16 -0
  520. package/dist/cli/backend/src/services/onboarding/content-approval.types.js.map +1 -0
  521. package/dist/cli/backend/src/services/orc/orc-delivery-enforcer.service.d.ts +150 -0
  522. package/dist/cli/backend/src/services/orc/orc-delivery-enforcer.service.d.ts.map +1 -0
  523. package/dist/cli/backend/src/services/orc/orc-delivery-enforcer.service.js +293 -0
  524. package/dist/cli/backend/src/services/orc/orc-delivery-enforcer.service.js.map +1 -0
  525. package/dist/cli/backend/src/services/orchestrator/improvement-marker.service.d.ts +231 -0
  526. package/dist/cli/backend/src/services/orchestrator/improvement-marker.service.d.ts.map +1 -0
  527. package/dist/cli/backend/src/services/orchestrator/improvement-marker.service.js +353 -0
  528. package/dist/cli/backend/src/services/orchestrator/improvement-marker.service.js.map +1 -0
  529. package/dist/cli/backend/src/services/orchestrator/improvement-startup.service.d.ts +157 -0
  530. package/dist/cli/backend/src/services/orchestrator/improvement-startup.service.d.ts.map +1 -0
  531. package/dist/cli/backend/src/services/orchestrator/improvement-startup.service.js +483 -0
  532. package/dist/cli/backend/src/services/orchestrator/improvement-startup.service.js.map +1 -0
  533. package/dist/cli/backend/src/services/orchestrator/index.d.ts +16 -0
  534. package/dist/cli/backend/src/services/orchestrator/index.d.ts.map +1 -0
  535. package/dist/cli/backend/src/services/orchestrator/index.js +16 -0
  536. package/dist/cli/backend/src/services/orchestrator/index.js.map +1 -0
  537. package/dist/cli/backend/src/services/orchestrator/orchestrator-restart.service.d.ts +117 -0
  538. package/dist/cli/backend/src/services/orchestrator/orchestrator-restart.service.d.ts.map +1 -0
  539. package/dist/cli/backend/src/services/orchestrator/orchestrator-restart.service.js +300 -0
  540. package/dist/cli/backend/src/services/orchestrator/orchestrator-restart.service.js.map +1 -0
  541. package/dist/cli/backend/src/services/orchestrator/orchestrator-setup.service.d.ts +114 -0
  542. package/dist/cli/backend/src/services/orchestrator/orchestrator-setup.service.d.ts.map +1 -0
  543. package/dist/cli/backend/src/services/orchestrator/orchestrator-setup.service.js +195 -0
  544. package/dist/cli/backend/src/services/orchestrator/orchestrator-setup.service.js.map +1 -0
  545. package/dist/cli/backend/src/services/orchestrator/orchestrator-status.service.d.ts +94 -0
  546. package/dist/cli/backend/src/services/orchestrator/orchestrator-status.service.d.ts.map +1 -0
  547. package/dist/cli/backend/src/services/orchestrator/orchestrator-status.service.js +279 -0
  548. package/dist/cli/backend/src/services/orchestrator/orchestrator-status.service.js.map +1 -0
  549. package/dist/cli/backend/src/services/orchestrator/safe-restart.service.d.ts +192 -0
  550. package/dist/cli/backend/src/services/orchestrator/safe-restart.service.d.ts.map +1 -0
  551. package/dist/cli/backend/src/services/orchestrator/safe-restart.service.js +395 -0
  552. package/dist/cli/backend/src/services/orchestrator/safe-restart.service.js.map +1 -0
  553. package/dist/cli/backend/src/services/orchestrator/self-improvement.service.d.ts +201 -0
  554. package/dist/cli/backend/src/services/orchestrator/self-improvement.service.d.ts.map +1 -0
  555. package/dist/cli/backend/src/services/orchestrator/self-improvement.service.js +396 -0
  556. package/dist/cli/backend/src/services/orchestrator/self-improvement.service.js.map +1 -0
  557. package/dist/cli/backend/src/services/orchestrator/slack-bridge-lazy.d.ts +17 -0
  558. package/dist/cli/backend/src/services/orchestrator/slack-bridge-lazy.d.ts.map +1 -0
  559. package/dist/cli/backend/src/services/orchestrator/slack-bridge-lazy.js +30 -0
  560. package/dist/cli/backend/src/services/orchestrator/slack-bridge-lazy.js.map +1 -0
  561. package/dist/cli/backend/src/services/orchestrator/state-persistence.service.d.ts +249 -0
  562. package/dist/cli/backend/src/services/orchestrator/state-persistence.service.d.ts.map +1 -0
  563. package/dist/cli/backend/src/services/orchestrator/state-persistence.service.js +569 -0
  564. package/dist/cli/backend/src/services/orchestrator/state-persistence.service.js.map +1 -0
  565. package/dist/cli/backend/src/services/session/index.d.ts +47 -0
  566. package/dist/cli/backend/src/services/session/index.d.ts.map +1 -0
  567. package/dist/cli/backend/src/services/session/index.js +50 -0
  568. package/dist/cli/backend/src/services/session/index.js.map +1 -0
  569. package/dist/cli/backend/src/services/session/log-rotation.service.d.ts +163 -0
  570. package/dist/cli/backend/src/services/session/log-rotation.service.d.ts.map +1 -0
  571. package/dist/cli/backend/src/services/session/log-rotation.service.js +362 -0
  572. package/dist/cli/backend/src/services/session/log-rotation.service.js.map +1 -0
  573. package/dist/cli/backend/src/services/session/pty/index.d.ts +11 -0
  574. package/dist/cli/backend/src/services/session/pty/index.d.ts.map +1 -0
  575. package/dist/cli/backend/src/services/session/pty/index.js +11 -0
  576. package/dist/cli/backend/src/services/session/pty/index.js.map +1 -0
  577. package/dist/cli/backend/src/services/session/pty/pty-session-backend.d.ts +445 -0
  578. package/dist/cli/backend/src/services/session/pty/pty-session-backend.d.ts.map +1 -0
  579. package/dist/cli/backend/src/services/session/pty/pty-session-backend.js +804 -0
  580. package/dist/cli/backend/src/services/session/pty/pty-session-backend.js.map +1 -0
  581. package/dist/cli/backend/src/services/session/pty/pty-session.d.ts +252 -0
  582. package/dist/cli/backend/src/services/session/pty/pty-session.d.ts.map +1 -0
  583. package/dist/cli/backend/src/services/session/pty/pty-session.js +611 -0
  584. package/dist/cli/backend/src/services/session/pty/pty-session.js.map +1 -0
  585. package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.d.ts +275 -0
  586. package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.d.ts.map +1 -0
  587. package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.js +403 -0
  588. package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.js.map +1 -0
  589. package/dist/cli/backend/src/services/session/runtime-pid-registry.service.d.ts +86 -0
  590. package/dist/cli/backend/src/services/session/runtime-pid-registry.service.d.ts.map +1 -0
  591. package/dist/cli/backend/src/services/session/runtime-pid-registry.service.js +214 -0
  592. package/dist/cli/backend/src/services/session/runtime-pid-registry.service.js.map +1 -0
  593. package/dist/cli/backend/src/services/session/session-backend.factory.d.ts +127 -0
  594. package/dist/cli/backend/src/services/session/session-backend.factory.d.ts.map +1 -0
  595. package/dist/cli/backend/src/services/session/session-backend.factory.js +226 -0
  596. package/dist/cli/backend/src/services/session/session-backend.factory.js.map +1 -0
  597. package/dist/cli/backend/src/services/session/session-backend.interface.d.ts +390 -0
  598. package/dist/cli/backend/src/services/session/session-backend.interface.d.ts.map +1 -0
  599. package/dist/cli/backend/src/services/session/session-backend.interface.js +19 -0
  600. package/dist/cli/backend/src/services/session/session-backend.interface.js.map +1 -0
  601. package/dist/cli/backend/src/services/session/session-command-helper.d.ts +350 -0
  602. package/dist/cli/backend/src/services/session/session-command-helper.d.ts.map +1 -0
  603. package/dist/cli/backend/src/services/session/session-command-helper.js +810 -0
  604. package/dist/cli/backend/src/services/session/session-command-helper.js.map +1 -0
  605. package/dist/cli/backend/src/services/session/session-handoff.service.d.ts +307 -0
  606. package/dist/cli/backend/src/services/session/session-handoff.service.d.ts.map +1 -0
  607. package/dist/cli/backend/src/services/session/session-handoff.service.js +742 -0
  608. package/dist/cli/backend/src/services/session/session-handoff.service.js.map +1 -0
  609. package/dist/cli/backend/src/services/session/session-state-persistence.d.ts +231 -0
  610. package/dist/cli/backend/src/services/session/session-state-persistence.d.ts.map +1 -0
  611. package/dist/cli/backend/src/services/session/session-state-persistence.js +407 -0
  612. package/dist/cli/backend/src/services/session/session-state-persistence.js.map +1 -0
  613. package/dist/cli/backend/src/services/settings/role.service.d.ts +277 -0
  614. package/dist/cli/backend/src/services/settings/role.service.d.ts.map +1 -0
  615. package/dist/cli/backend/src/services/settings/role.service.js +728 -0
  616. package/dist/cli/backend/src/services/settings/role.service.js.map +1 -0
  617. package/dist/cli/backend/src/services/slack/cross-machine-message.service.d.ts +152 -0
  618. package/dist/cli/backend/src/services/slack/cross-machine-message.service.d.ts.map +1 -0
  619. package/dist/cli/backend/src/services/slack/cross-machine-message.service.js +354 -0
  620. package/dist/cli/backend/src/services/slack/cross-machine-message.service.js.map +1 -0
  621. package/dist/cli/backend/src/services/slack/slack-agent-identity.service.d.ts +209 -0
  622. package/dist/cli/backend/src/services/slack/slack-agent-identity.service.d.ts.map +1 -0
  623. package/dist/cli/backend/src/services/slack/slack-agent-identity.service.js +416 -0
  624. package/dist/cli/backend/src/services/slack/slack-agent-identity.service.js.map +1 -0
  625. package/dist/cli/backend/src/services/slack/slack-image.service.d.ts +114 -0
  626. package/dist/cli/backend/src/services/slack/slack-image.service.d.ts.map +1 -0
  627. package/dist/cli/backend/src/services/slack/slack-image.service.js +331 -0
  628. package/dist/cli/backend/src/services/slack/slack-image.service.js.map +1 -0
  629. package/dist/cli/backend/src/services/slack/slack-mention-resolver.d.ts +103 -0
  630. package/dist/cli/backend/src/services/slack/slack-mention-resolver.d.ts.map +1 -0
  631. package/dist/cli/backend/src/services/slack/slack-mention-resolver.js +197 -0
  632. package/dist/cli/backend/src/services/slack/slack-mention-resolver.js.map +1 -0
  633. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts +499 -0
  634. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -0
  635. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +1946 -0
  636. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -0
  637. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +329 -0
  638. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -0
  639. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +821 -0
  640. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -0
  641. package/dist/cli/backend/src/services/slack/slack.service.d.ts +430 -0
  642. package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -0
  643. package/dist/cli/backend/src/services/slack/slack.service.js +1388 -0
  644. package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -0
  645. package/dist/cli/backend/src/services/sop/sop.service.d.ts +364 -0
  646. package/dist/cli/backend/src/services/sop/sop.service.d.ts.map +1 -0
  647. package/dist/cli/backend/src/services/sop/sop.service.js +734 -0
  648. package/dist/cli/backend/src/services/sop/sop.service.js.map +1 -0
  649. package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +152 -7
  650. package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  651. package/dist/cli/backend/src/services/task-pool/task-pool.service.js +268 -36
  652. package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  653. package/dist/cli/backend/src/services/v3/escalation-router.service.d.ts +178 -0
  654. package/dist/cli/backend/src/services/v3/escalation-router.service.d.ts.map +1 -0
  655. package/dist/cli/backend/src/services/v3/escalation-router.service.js +692 -0
  656. package/dist/cli/backend/src/services/v3/escalation-router.service.js.map +1 -0
  657. package/dist/cli/backend/src/services/v3/kr-tracking.service.d.ts +200 -0
  658. package/dist/cli/backend/src/services/v3/kr-tracking.service.d.ts.map +1 -0
  659. package/dist/cli/backend/src/services/v3/kr-tracking.service.js +482 -0
  660. package/dist/cli/backend/src/services/v3/kr-tracking.service.js.map +1 -0
  661. package/dist/cli/backend/src/services/v3/mission-executor.service.d.ts +117 -0
  662. package/dist/cli/backend/src/services/v3/mission-executor.service.d.ts.map +1 -0
  663. package/dist/cli/backend/src/services/v3/mission-executor.service.js +321 -0
  664. package/dist/cli/backend/src/services/v3/mission-executor.service.js.map +1 -0
  665. package/dist/cli/backend/src/services/v3/request-sla.subscriber.d.ts +610 -0
  666. package/dist/cli/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -0
  667. package/dist/cli/backend/src/services/v3/request-sla.subscriber.js +1529 -0
  668. package/dist/cli/backend/src/services/v3/request-sla.subscriber.js.map +1 -0
  669. package/dist/cli/backend/src/services/v3/request-tracker.service.d.ts +78 -0
  670. package/dist/cli/backend/src/services/v3/request-tracker.service.d.ts.map +1 -0
  671. package/dist/cli/backend/src/services/v3/request-tracker.service.js +108 -0
  672. package/dist/cli/backend/src/services/v3/request-tracker.service.js.map +1 -0
  673. package/dist/cli/backend/src/services/v3/request.service.d.ts +295 -0
  674. package/dist/cli/backend/src/services/v3/request.service.d.ts.map +1 -0
  675. package/dist/cli/backend/src/services/v3/request.service.js +534 -0
  676. package/dist/cli/backend/src/services/v3/request.service.js.map +1 -0
  677. package/dist/cli/backend/src/services/v3/v3-data.service.d.ts +340 -0
  678. package/dist/cli/backend/src/services/v3/v3-data.service.d.ts.map +1 -0
  679. package/dist/cli/backend/src/services/v3/v3-data.service.js +1113 -0
  680. package/dist/cli/backend/src/services/v3/v3-data.service.js.map +1 -0
  681. package/dist/cli/backend/src/types/cross-machine.types.d.ts +103 -0
  682. package/dist/cli/backend/src/types/cross-machine.types.d.ts.map +1 -0
  683. package/dist/cli/backend/src/types/cross-machine.types.js +47 -0
  684. package/dist/cli/backend/src/types/cross-machine.types.js.map +1 -0
  685. package/dist/cli/backend/src/types/intent-task.types.d.ts +402 -0
  686. package/dist/cli/backend/src/types/intent-task.types.d.ts.map +1 -0
  687. package/dist/cli/backend/src/types/intent-task.types.js +403 -0
  688. package/dist/cli/backend/src/types/intent-task.types.js.map +1 -0
  689. package/dist/cli/backend/src/types/orchestrator-state.types.d.ts +531 -0
  690. package/dist/cli/backend/src/types/orchestrator-state.types.d.ts.map +1 -0
  691. package/dist/cli/backend/src/types/orchestrator-state.types.js +110 -0
  692. package/dist/cli/backend/src/types/orchestrator-state.types.js.map +1 -0
  693. package/dist/cli/backend/src/types/slack.types.d.ts +87 -0
  694. package/dist/cli/backend/src/types/slack.types.d.ts.map +1 -1
  695. package/dist/cli/backend/src/types/slack.types.js.map +1 -1
  696. package/dist/cli/backend/src/types/v2/index.d.ts +30 -0
  697. package/dist/cli/backend/src/types/v2/index.d.ts.map +1 -0
  698. package/dist/cli/backend/src/types/v2/index.js +22 -0
  699. package/dist/cli/backend/src/types/v2/index.js.map +1 -0
  700. package/dist/cli/backend/src/types/v2/key-result.types.d.ts +279 -0
  701. package/dist/cli/backend/src/types/v2/key-result.types.d.ts.map +1 -0
  702. package/dist/cli/backend/src/types/v2/key-result.types.js +264 -0
  703. package/dist/cli/backend/src/types/v2/key-result.types.js.map +1 -0
  704. package/dist/cli/backend/src/types/v2/mission.types.d.ts +661 -0
  705. package/dist/cli/backend/src/types/v2/mission.types.d.ts.map +1 -0
  706. package/dist/cli/backend/src/types/v2/mission.types.js +713 -0
  707. package/dist/cli/backend/src/types/v2/mission.types.js.map +1 -0
  708. package/dist/cli/backend/src/types/v2/reconcile.types.d.ts +204 -0
  709. package/dist/cli/backend/src/types/v2/reconcile.types.d.ts.map +1 -0
  710. package/dist/cli/backend/src/types/v2/reconcile.types.js +121 -0
  711. package/dist/cli/backend/src/types/v2/reconcile.types.js.map +1 -0
  712. package/dist/cli/backend/src/types/v2/request.types.d.ts +192 -0
  713. package/dist/cli/backend/src/types/v2/request.types.d.ts.map +1 -0
  714. package/dist/cli/backend/src/types/v2/request.types.js +179 -0
  715. package/dist/cli/backend/src/types/v2/request.types.js.map +1 -0
  716. package/dist/cli/backend/src/types/v2/work-item.types.d.ts +181 -1
  717. package/dist/cli/backend/src/types/v2/work-item.types.d.ts.map +1 -1
  718. package/dist/cli/backend/src/types/v2/work-item.types.js +104 -17
  719. package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
  720. package/dist/cli/backend/src/types/v2/workspace.types.d.ts +157 -0
  721. package/dist/cli/backend/src/types/v2/workspace.types.d.ts.map +1 -0
  722. package/dist/cli/backend/src/types/v2/workspace.types.js +173 -0
  723. package/dist/cli/backend/src/types/v2/workspace.types.js.map +1 -0
  724. package/dist/cli/backend/src/utils/async.utils.d.ts +68 -0
  725. package/dist/cli/backend/src/utils/async.utils.d.ts.map +1 -0
  726. package/dist/cli/backend/src/utils/async.utils.js +80 -0
  727. package/dist/cli/backend/src/utils/async.utils.js.map +1 -0
  728. package/dist/cli/backend/src/utils/native-binding.utils.d.ts +128 -0
  729. package/dist/cli/backend/src/utils/native-binding.utils.d.ts.map +1 -0
  730. package/dist/cli/backend/src/utils/native-binding.utils.js +206 -0
  731. package/dist/cli/backend/src/utils/native-binding.utils.js.map +1 -0
  732. package/dist/cli/backend/src/utils/team.utils.d.ts +40 -0
  733. package/dist/cli/backend/src/utils/team.utils.d.ts.map +1 -0
  734. package/dist/cli/backend/src/utils/team.utils.js +66 -0
  735. package/dist/cli/backend/src/utils/team.utils.js.map +1 -0
  736. package/dist/cli/backend/src/websocket/chat.gateway.d.ts +142 -0
  737. package/dist/cli/backend/src/websocket/chat.gateway.d.ts.map +1 -0
  738. package/dist/cli/backend/src/websocket/chat.gateway.js +327 -0
  739. package/dist/cli/backend/src/websocket/chat.gateway.js.map +1 -0
  740. package/dist/cli/backend/src/websocket/terminal.gateway.d.ts +341 -0
  741. package/dist/cli/backend/src/websocket/terminal.gateway.d.ts.map +1 -0
  742. package/dist/cli/backend/src/websocket/terminal.gateway.js +933 -0
  743. package/dist/cli/backend/src/websocket/terminal.gateway.js.map +1 -0
  744. package/dist/cli/cli/src/index.js +0 -0
  745. package/dist/cli/config/constants.d.ts +8 -0
  746. package/dist/cli/config/constants.d.ts.map +1 -1
  747. package/dist/cli/config/constants.js +8 -0
  748. package/dist/cli/config/constants.js.map +1 -1
  749. package/dist/cli/config/vitest-exclude.constants.d.ts +53 -0
  750. package/dist/cli/config/vitest-exclude.constants.d.ts.map +1 -0
  751. package/dist/cli/config/vitest-exclude.constants.js +55 -0
  752. package/dist/cli/config/vitest-exclude.constants.js.map +1 -0
  753. package/frontend/dist/assets/index-190a957f.js +4961 -0
  754. package/frontend/dist/assets/{index-8205ea5e.css → index-88feb412.css} +1 -1
  755. package/frontend/dist/index.html +2 -2
  756. package/package.json +2 -2
  757. package/packages/crewly-agent/src/runtime/agent-runner.service.test.ts +174 -30
  758. package/packages/crewly-agent/src/runtime/agent-runner.service.ts +121 -6
  759. package/packages/crewly-agent/src/runtime/types.ts +56 -5
  760. package/dist/backend/backend/src/controllers/knowledge/index.d.ts +0 -7
  761. package/dist/backend/backend/src/controllers/knowledge/index.d.ts.map +0 -1
  762. package/dist/backend/backend/src/controllers/knowledge/index.js +0 -7
  763. package/dist/backend/backend/src/controllers/knowledge/index.js.map +0 -1
  764. package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.d.ts +0 -71
  765. package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.d.ts.map +0 -1
  766. package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.js +0 -237
  767. package/dist/backend/backend/src/controllers/knowledge/knowledge.controller.js.map +0 -1
  768. package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.d.ts +0 -24
  769. package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.d.ts.map +0 -1
  770. package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.js +0 -34
  771. package/dist/backend/backend/src/controllers/knowledge/knowledge.routes.js.map +0 -1
  772. package/dist/backend/backend/src/controllers/scheduler/unified-scheduler.controller.d.ts +0 -91
  773. package/dist/backend/backend/src/controllers/scheduler/unified-scheduler.controller.d.ts.map +0 -1
  774. package/dist/backend/backend/src/controllers/scheduler/unified-scheduler.controller.js +0 -290
  775. package/dist/backend/backend/src/controllers/scheduler/unified-scheduler.controller.js.map +0 -1
  776. package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +0 -169
  777. package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +0 -1
  778. package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +0 -1779
  779. package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +0 -1
  780. package/dist/backend/backend/src/index.js.orc-bak-20260529 +0 -3130
  781. package/dist/backend/backend/src/routes/modules/unified-scheduler.routes.d.ts +0 -27
  782. package/dist/backend/backend/src/routes/modules/unified-scheduler.routes.d.ts.map +0 -1
  783. package/dist/backend/backend/src/routes/modules/unified-scheduler.routes.js +0 -40
  784. package/dist/backend/backend/src/routes/modules/unified-scheduler.routes.js.map +0 -1
  785. package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts +0 -513
  786. package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts.map +0 -1
  787. package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js +0 -1568
  788. package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js.map +0 -1
  789. package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts +0 -86
  790. package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts.map +0 -1
  791. package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js +0 -147
  792. package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js.map +0 -1
  793. package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts +0 -68
  794. package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts.map +0 -1
  795. package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js +0 -131
  796. package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js.map +0 -1
  797. package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts +0 -130
  798. package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts.map +0 -1
  799. package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js +0 -263
  800. package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js.map +0 -1
  801. package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts +0 -74
  802. package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts.map +0 -1
  803. package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js +0 -140
  804. package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js.map +0 -1
  805. package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts +0 -29
  806. package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts.map +0 -1
  807. package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js +0 -279
  808. package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js.map +0 -1
  809. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts +0 -340
  810. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts.map +0 -1
  811. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js +0 -1176
  812. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js.map +0 -1
  813. package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts +0 -79
  814. package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts.map +0 -1
  815. package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js +0 -145
  816. package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js.map +0 -1
  817. package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts +0 -79
  818. package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts.map +0 -1
  819. package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js +0 -218
  820. package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js.map +0 -1
  821. package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts +0 -16
  822. package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts.map +0 -1
  823. package/dist/backend/backend/src/services/agent/crewly-agent/index.js +0 -16
  824. package/dist/backend/backend/src/services/agent/crewly-agent/index.js.map +0 -1
  825. package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts +0 -135
  826. package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts.map +0 -1
  827. package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js +0 -185
  828. package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js.map +0 -1
  829. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +0 -141
  830. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts.map +0 -1
  831. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js +0 -310
  832. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js.map +0 -1
  833. package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts +0 -91
  834. package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts.map +0 -1
  835. package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js +0 -143
  836. package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js.map +0 -1
  837. package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts +0 -103
  838. package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts.map +0 -1
  839. package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js +0 -256
  840. package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js.map +0 -1
  841. package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts +0 -143
  842. package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts.map +0 -1
  843. package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js +0 -264
  844. package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js.map +0 -1
  845. package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts +0 -13
  846. package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts.map +0 -1
  847. package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js +0 -91
  848. package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js.map +0 -1
  849. package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts +0 -135
  850. package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts.map +0 -1
  851. package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js +0 -1937
  852. package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js.map +0 -1
  853. package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts +0 -429
  854. package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts.map +0 -1
  855. package/dist/backend/backend/src/services/autonomous/auto-assign.service.js +0 -852
  856. package/dist/backend/backend/src/services/autonomous/auto-assign.service.js.map +0 -1
  857. package/dist/backend/backend/src/services/knowledge/embedding-provider.d.ts +0 -78
  858. package/dist/backend/backend/src/services/knowledge/embedding-provider.d.ts.map +0 -1
  859. package/dist/backend/backend/src/services/knowledge/embedding-provider.js +0 -179
  860. package/dist/backend/backend/src/services/knowledge/embedding-provider.js.map +0 -1
  861. package/dist/backend/backend/src/services/knowledge/fts5-index.service.d.ts +0 -118
  862. package/dist/backend/backend/src/services/knowledge/fts5-index.service.d.ts.map +0 -1
  863. package/dist/backend/backend/src/services/knowledge/fts5-index.service.js +0 -241
  864. package/dist/backend/backend/src/services/knowledge/fts5-index.service.js.map +0 -1
  865. package/dist/backend/backend/src/services/knowledge/fts5-query-sanitizer.d.ts +0 -102
  866. package/dist/backend/backend/src/services/knowledge/fts5-query-sanitizer.d.ts.map +0 -1
  867. package/dist/backend/backend/src/services/knowledge/fts5-query-sanitizer.js +0 -118
  868. package/dist/backend/backend/src/services/knowledge/fts5-query-sanitizer.js.map +0 -1
  869. package/dist/backend/backend/src/services/knowledge/index.d.ts +0 -8
  870. package/dist/backend/backend/src/services/knowledge/index.d.ts.map +0 -1
  871. package/dist/backend/backend/src/services/knowledge/index.js +0 -8
  872. package/dist/backend/backend/src/services/knowledge/index.js.map +0 -1
  873. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts +0 -241
  874. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts.map +0 -1
  875. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js +0 -590
  876. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +0 -1
  877. package/dist/backend/backend/src/services/knowledge/knowledge.service.d.ts +0 -153
  878. package/dist/backend/backend/src/services/knowledge/knowledge.service.d.ts.map +0 -1
  879. package/dist/backend/backend/src/services/knowledge/knowledge.service.js +0 -409
  880. package/dist/backend/backend/src/services/knowledge/knowledge.service.js.map +0 -1
  881. package/dist/backend/backend/src/services/knowledge/vector-store.service.d.ts +0 -331
  882. package/dist/backend/backend/src/services/knowledge/vector-store.service.d.ts.map +0 -1
  883. package/dist/backend/backend/src/services/knowledge/vector-store.service.js +0 -830
  884. package/dist/backend/backend/src/services/knowledge/vector-store.service.js.map +0 -1
  885. package/dist/backend/backend/src/services/knowledge/wiki-compiler.service.d.ts +0 -115
  886. package/dist/backend/backend/src/services/knowledge/wiki-compiler.service.d.ts.map +0 -1
  887. package/dist/backend/backend/src/services/knowledge/wiki-compiler.service.js +0 -215
  888. package/dist/backend/backend/src/services/knowledge/wiki-compiler.service.js.map +0 -1
  889. package/dist/backend/backend/src/services/memory/embedding-provider.d.ts +0 -78
  890. package/dist/backend/backend/src/services/memory/embedding-provider.d.ts.map +0 -1
  891. package/dist/backend/backend/src/services/memory/embedding-provider.js +0 -185
  892. package/dist/backend/backend/src/services/memory/embedding-provider.js.map +0 -1
  893. package/dist/backend/backend/src/services/memory/vector-store.service.d.ts +0 -331
  894. package/dist/backend/backend/src/services/memory/vector-store.service.d.ts.map +0 -1
  895. package/dist/backend/backend/src/services/memory/vector-store.service.js +0 -825
  896. package/dist/backend/backend/src/services/memory/vector-store.service.js.map +0 -1
  897. package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +0 -171
  898. package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +0 -1
  899. package/dist/backend/backend/src/services/project/task-tracking.service.js +0 -725
  900. package/dist/backend/backend/src/services/project/task-tracking.service.js.map +0 -1
  901. package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts +0 -118
  902. package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts.map +0 -1
  903. package/dist/backend/backend/src/services/v3/project-task-watcher.service.js +0 -326
  904. package/dist/backend/backend/src/services/v3/project-task-watcher.service.js.map +0 -1
  905. package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts +0 -74
  906. package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts.map +0 -1
  907. package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js +0 -154
  908. package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js.map +0 -1
  909. package/dist/backend/backend/src/services/workflow/unified-scheduler.service.d.ts +0 -234
  910. package/dist/backend/backend/src/services/workflow/unified-scheduler.service.d.ts.map +0 -1
  911. package/dist/backend/backend/src/services/workflow/unified-scheduler.service.js +0 -636
  912. package/dist/backend/backend/src/services/workflow/unified-scheduler.service.js.map +0 -1
  913. package/dist/backend/backend/src/services/workflow/unified-scheduler.types.d.ts +0 -156
  914. package/dist/backend/backend/src/services/workflow/unified-scheduler.types.d.ts.map +0 -1
  915. package/dist/backend/backend/src/services/workflow/unified-scheduler.types.js +0 -81
  916. package/dist/backend/backend/src/services/workflow/unified-scheduler.types.js.map +0 -1
  917. package/dist/backend/backend/src/types/auto-assign.types.d.ts +0 -271
  918. package/dist/backend/backend/src/types/auto-assign.types.d.ts.map +0 -1
  919. package/dist/backend/backend/src/types/auto-assign.types.js +0 -136
  920. package/dist/backend/backend/src/types/auto-assign.types.js.map +0 -1
  921. package/dist/backend/backend/src/types/knowledge.types.d.ts +0 -195
  922. package/dist/backend/backend/src/types/knowledge.types.d.ts.map +0 -1
  923. package/dist/backend/backend/src/types/knowledge.types.js +0 -38
  924. package/dist/backend/backend/src/types/knowledge.types.js.map +0 -1
  925. package/dist/backend/backend/src/utils/esm-require.utils.d.ts +0 -111
  926. package/dist/backend/backend/src/utils/esm-require.utils.d.ts.map +0 -1
  927. package/dist/backend/backend/src/utils/esm-require.utils.js +0 -124
  928. package/dist/backend/backend/src/utils/esm-require.utils.js.map +0 -1
  929. package/dist/cli/backend/src/services/knowledge/embedding-provider.d.ts +0 -78
  930. package/dist/cli/backend/src/services/knowledge/embedding-provider.d.ts.map +0 -1
  931. package/dist/cli/backend/src/services/knowledge/embedding-provider.js +0 -179
  932. package/dist/cli/backend/src/services/knowledge/embedding-provider.js.map +0 -1
  933. package/dist/cli/backend/src/services/knowledge/fts5-index.service.d.ts +0 -118
  934. package/dist/cli/backend/src/services/knowledge/fts5-index.service.d.ts.map +0 -1
  935. package/dist/cli/backend/src/services/knowledge/fts5-index.service.js +0 -241
  936. package/dist/cli/backend/src/services/knowledge/fts5-index.service.js.map +0 -1
  937. package/dist/cli/backend/src/services/knowledge/fts5-query-sanitizer.d.ts +0 -102
  938. package/dist/cli/backend/src/services/knowledge/fts5-query-sanitizer.d.ts.map +0 -1
  939. package/dist/cli/backend/src/services/knowledge/fts5-query-sanitizer.js +0 -118
  940. package/dist/cli/backend/src/services/knowledge/fts5-query-sanitizer.js.map +0 -1
  941. package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts +0 -56
  942. package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts.map +0 -1
  943. package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js +0 -91
  944. package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js.map +0 -1
  945. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts +0 -241
  946. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts.map +0 -1
  947. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js +0 -590
  948. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js.map +0 -1
  949. package/dist/cli/backend/src/services/knowledge/knowledge.service.d.ts +0 -153
  950. package/dist/cli/backend/src/services/knowledge/knowledge.service.d.ts.map +0 -1
  951. package/dist/cli/backend/src/services/knowledge/knowledge.service.js +0 -409
  952. package/dist/cli/backend/src/services/knowledge/knowledge.service.js.map +0 -1
  953. package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts +0 -159
  954. package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts.map +0 -1
  955. package/dist/cli/backend/src/services/knowledge/learnings-index.service.js +0 -304
  956. package/dist/cli/backend/src/services/knowledge/learnings-index.service.js.map +0 -1
  957. package/dist/cli/backend/src/services/knowledge/vector-store.service.d.ts +0 -331
  958. package/dist/cli/backend/src/services/knowledge/vector-store.service.d.ts.map +0 -1
  959. package/dist/cli/backend/src/services/knowledge/vector-store.service.js +0 -830
  960. package/dist/cli/backend/src/services/knowledge/vector-store.service.js.map +0 -1
  961. package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts +0 -115
  962. package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts.map +0 -1
  963. package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js +0 -215
  964. package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js.map +0 -1
  965. package/dist/cli/backend/src/services/memory/embedding-provider.d.ts +0 -78
  966. package/dist/cli/backend/src/services/memory/embedding-provider.d.ts.map +0 -1
  967. package/dist/cli/backend/src/services/memory/embedding-provider.js +0 -179
  968. package/dist/cli/backend/src/services/memory/embedding-provider.js.map +0 -1
  969. package/dist/cli/backend/src/services/memory/vector-store.service.d.ts +0 -331
  970. package/dist/cli/backend/src/services/memory/vector-store.service.d.ts.map +0 -1
  971. package/dist/cli/backend/src/services/memory/vector-store.service.js +0 -814
  972. package/dist/cli/backend/src/services/memory/vector-store.service.js.map +0 -1
  973. package/dist/cli/backend/src/services/project/task-tracking.service.d.ts +0 -171
  974. package/dist/cli/backend/src/services/project/task-tracking.service.d.ts.map +0 -1
  975. package/dist/cli/backend/src/services/project/task-tracking.service.js +0 -725
  976. package/dist/cli/backend/src/services/project/task-tracking.service.js.map +0 -1
  977. package/dist/cli/backend/src/types/auto-assign.types.d.ts +0 -271
  978. package/dist/cli/backend/src/types/auto-assign.types.d.ts.map +0 -1
  979. package/dist/cli/backend/src/types/auto-assign.types.js +0 -136
  980. package/dist/cli/backend/src/types/auto-assign.types.js.map +0 -1
  981. package/dist/cli/backend/src/types/knowledge.types.d.ts +0 -195
  982. package/dist/cli/backend/src/types/knowledge.types.d.ts.map +0 -1
  983. package/dist/cli/backend/src/types/knowledge.types.js +0 -38
  984. package/dist/cli/backend/src/types/knowledge.types.js.map +0 -1
  985. package/frontend/dist/assets/index-aa737fd3.js +0 -5254
@@ -0,0 +1,1946 @@
1
+ /**
2
+ * Slack-Orchestrator Bridge
3
+ *
4
+ * Routes messages between Slack and the Crewly orchestrator,
5
+ * enabling mobile control of AI teams.
6
+ *
7
+ * @module services/slack/bridge
8
+ */
9
+ import { EventEmitter } from 'events';
10
+ import { promises as fs, createWriteStream } from 'fs';
11
+ import path from 'path';
12
+ import os from 'os';
13
+ import { Readable } from 'stream';
14
+ import { pipeline } from 'stream/promises';
15
+ import { PDFParse } from 'pdf-parse';
16
+ import { getSlackService } from './slack.service.js';
17
+ import { getChatV2Service } from '../chat-v2/chat-v2.singleton.js';
18
+ import { synthesizeSlackConversationId } from '../chat-v2/legacy-dto.utils.js';
19
+ import { isOrchestratorActive, isAgentActive, getOrchestratorOfflineMessage, triggerOrchestratorSetup, } from '../orchestrator/index.js';
20
+ import { parseCommandIntent, } from '../../types/slack.types.js';
21
+ import { ContentApprovalService } from '../onboarding/content-approval.service.js';
22
+ import { getSlackImageService } from './slack-image.service.js';
23
+ import { ORCHESTRATOR_SESSION_NAME, MESSAGE_QUEUE_CONSTANTS, SLACK_IMAGE_CONSTANTS, SLACK_FILE_DOWNLOAD_CONSTANTS, SLACK_BRIDGE_CONSTANTS, AUDITOR_SCHEDULER_CONSTANTS, THREAD_STATUS_CONSTANTS } from '../../constants.js';
24
+ import { LoggerService } from '../core/logger.service.js';
25
+ import { CROSS_MACHINE_PREFIX } from '../../types/cross-machine.types.js';
26
+ import { getCrossMachineMessageService } from './cross-machine-message.service.js';
27
+ import { getSlackTeamChannelService } from './slack-team-channel.service.js';
28
+ import { TERMINAL_REQUEST_STATUSES } from '../../types/v2/request.types.js';
29
+ /**
30
+ * Default bridge configuration
31
+ */
32
+ const DEFAULT_CONFIG = {
33
+ orchestratorSession: ORCHESTRATOR_SESSION_NAME,
34
+ showTypingIndicator: true,
35
+ maxResponseLength: 3000,
36
+ enableNotifications: true,
37
+ responseTimeoutMs: (MESSAGE_QUEUE_CONSTANTS?.DEFAULT_MESSAGE_TIMEOUT ?? 120000) + 5000,
38
+ skillDeliveryWaitMs: SLACK_BRIDGE_CONSTANTS?.SKILL_DELIVERY_WAIT_MS ?? 3000,
39
+ };
40
+ /**
41
+ * Maximum time to wait for an auto-recovery setup attempt before giving
42
+ * up and falling through to the offline path. Capped tight to avoid
43
+ * blocking the message ingress thread when setup is wedged.
44
+ */
45
+ const AUTO_RECOVERY_TIMEOUT_MS = 5_000;
46
+ // ---------------------------------------------------------------------------
47
+ // Auto-Request suppression gates (Pipeline-#4 fix, Patch D)
48
+ //
49
+ // Spec: 2026-05-05-request-decompose-pipeline-gap.md §4 Patch D.
50
+ // Live data measured ~80% of auto-Requests in D0AC7NF5N7L matched one of
51
+ // these gates and were never actionable.
52
+ // ---------------------------------------------------------------------------
53
+ /**
54
+ * Minimum trimmed text length required to create an auto-Request. Anything
55
+ * shorter is treated as "trivial" (length-gate). Set deliberately tight so a
56
+ * one-sentence command like "fix the build" (15 chars) still passes.
57
+ */
58
+ const MIN_AUTO_REQUEST_TEXT_LENGTH = 12;
59
+ /**
60
+ * Trimmed-text regex for trivial acknowledgement messages — anchored,
61
+ * case-insensitive, allows trailing punctuation/emoji whitespace. Matches
62
+ * "ok", "好的", "thx", "👍", etc. Add new locale tokens here as needed.
63
+ */
64
+ const TRIVIAL_ACK_PATTERN = /^(ok|好的|收到|thx|thanks|谢谢|👍|✅|got it|sure|yes|是|对|对的)\W*$/i;
65
+ /**
66
+ * Trimmed-text regex matching the synthetic `[Slack File: …]` titles
67
+ * generated by the file-handling path when a user uploads a file with no
68
+ * narrative. Caught before the thread-continuation gate to avoid the lookup.
69
+ */
70
+ const FILE_ONLY_TITLE_PATTERN = /^\[Slack File:[^\]]*\]\.?\s*$/;
71
+ /**
72
+ * Pure pre-fetch gates for auto-Request suppression (Patch D). Exported for
73
+ * focused unit testing — the full thread-continuation gate also lives in
74
+ * {@link SlackOrchestratorBridge.shouldSuppressAutoRequest} but requires a
75
+ * RequestService lookup so cannot be a pure function.
76
+ *
77
+ * Each function returns the suppression reason string (matches the values
78
+ * logged at debug level) or `null` when the gate does not match.
79
+ */
80
+ export function suppressTrivialOrShort(rawText) {
81
+ const trimmed = rawText.trim();
82
+ if (trimmed.length < MIN_AUTO_REQUEST_TEXT_LENGTH || TRIVIAL_ACK_PATTERN.test(trimmed)) {
83
+ return 'trivial_or_short';
84
+ }
85
+ return null;
86
+ }
87
+ export function suppressFileOnly(rawText) {
88
+ const trimmed = rawText.trim();
89
+ return FILE_ONLY_TITLE_PATTERN.test(trimmed) ? 'file_only' : null;
90
+ }
91
+ /**
92
+ * Slack-Orchestrator Bridge singleton
93
+ */
94
+ let bridgeInstance = null;
95
+ /**
96
+ * Derive a short, readable chat-v2 channel name from a Slack thread's first
97
+ * message — so the consolidated chat shows a meaningful title rather than the
98
+ * synthesized `slack-<chan>-<ts>` id (which is identical across a channel's
99
+ * threads). Collapses whitespace and truncates; falls back to "Slack thread".
100
+ *
101
+ * @param content - The first inbound message of the thread.
102
+ * @returns A title like `Slack: ship the v2 launch deck`.
103
+ */
104
+ export function deriveSlackThreadName(content) {
105
+ const oneLine = (content ?? '').replace(/\s+/g, ' ').trim();
106
+ if (!oneLine)
107
+ return 'Slack thread';
108
+ const snippet = oneLine.length > 48 ? `${oneLine.slice(0, 48)}…` : oneLine;
109
+ return `Slack: ${snippet}`;
110
+ }
111
+ /**
112
+ * SlackOrchestratorBridge class
113
+ *
114
+ * Routes messages between Slack and the Crewly orchestrator.
115
+ * Handles command parsing, response formatting, and proactive notifications.
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const bridge = getSlackOrchestratorBridge();
120
+ * await bridge.initialize();
121
+ *
122
+ * // Send notification when task completes
123
+ * await bridge.notifyTaskCompleted('Fix bug', 'Developer', 'MyProject');
124
+ * ```
125
+ */
126
+ export class SlackOrchestratorBridge extends EventEmitter {
127
+ logger = LoggerService.getInstance().createComponentLogger('SlackBridge');
128
+ slackService;
129
+ chatV2;
130
+ messageQueueService = null;
131
+ threadStatusQueue = null;
132
+ threadStore = null;
133
+ config;
134
+ initialized = false;
135
+ /** Track if we've already logged the missing scope warning */
136
+ loggedMissingScope = false;
137
+ /**
138
+ * Pending completion reactions keyed by "channelId:threadTs".
139
+ * Stores the original message ts so that the ✅ reaction is added to the
140
+ * correct message when the reply-slack skill delivers a response.
141
+ */
142
+ pendingReactions = new Map();
143
+ /**
144
+ * Track channel+thread pairs where Slack delivery was already handled
145
+ * by the reply-slack skill (execute.sh). Used by sendSlackResponse to
146
+ * avoid sending a duplicate fallback message to the same thread.
147
+ */
148
+ /**
149
+ * Create a new SlackOrchestratorBridge
150
+ *
151
+ * @param config - Partial configuration to override defaults
152
+ */
153
+ constructor(config = {}) {
154
+ super();
155
+ this.slackService = getSlackService();
156
+ this.chatV2 = getChatV2Service();
157
+ this.config = { ...DEFAULT_CONFIG, ...config };
158
+ }
159
+ /**
160
+ * Initialize the bridge
161
+ *
162
+ * Sets up message listeners and orchestrator subscriptions.
163
+ *
164
+ * @returns Promise that resolves when initialized
165
+ */
166
+ async initialize() {
167
+ if (this.initialized)
168
+ return;
169
+ // Listen for Slack messages
170
+ this.slackService.on('message', this.handleSlackMessage.bind(this));
171
+ // Initialize cross-machine messaging and route received messages to orchestrator
172
+ try {
173
+ const crossMachineService = getCrossMachineMessageService();
174
+ await crossMachineService.initialize();
175
+ crossMachineService.on('message', (msg) => {
176
+ this.handleCrossMachineMessage(msg);
177
+ });
178
+ this.logger.info('Cross-machine message listener registered');
179
+ }
180
+ catch (err) {
181
+ this.logger.warn('Cross-machine messaging not available', {
182
+ error: err instanceof Error ? err.message : String(err),
183
+ });
184
+ }
185
+ this.initialized = true;
186
+ this.logger.info('Initialized');
187
+ }
188
+ /**
189
+ * Check if bridge is initialized
190
+ *
191
+ * @returns True if initialized
192
+ */
193
+ isInitialized() {
194
+ return this.initialized;
195
+ }
196
+ /**
197
+ * Set the message queue service for enqueuing messages to the orchestrator.
198
+ * Called during server initialization.
199
+ *
200
+ * @param service - The MessageQueueService instance
201
+ */
202
+ setMessageQueueService(service) {
203
+ this.messageQueueService = service;
204
+ }
205
+ /**
206
+ * Set the thread status queue service for tracking inbound message lifecycle.
207
+ * Called during server initialization.
208
+ *
209
+ * @param service - The ThreadStatusQueueService instance
210
+ */
211
+ setThreadStatusQueue(service) {
212
+ this.threadStatusQueue = service;
213
+ }
214
+ /**
215
+ * Set the Slack thread store service for persisting thread conversations.
216
+ * Called during server initialization.
217
+ *
218
+ * @param store - The SlackThreadStoreService instance
219
+ */
220
+ setSlackThreadStore(store) {
221
+ this.threadStore = store;
222
+ }
223
+ /**
224
+ * Get current configuration
225
+ *
226
+ * @returns A copy of the current configuration
227
+ */
228
+ getConfig() {
229
+ return { ...this.config };
230
+ }
231
+ /**
232
+ * Handle incoming Slack message
233
+ *
234
+ * Parses the command, routes to appropriate handler, and sends response.
235
+ *
236
+ * @param message - Incoming Slack message
237
+ */
238
+ async handleSlackMessage(message) {
239
+ this.logger.info('Received message', {
240
+ preview: (message.text || '').substring(0, 50),
241
+ hasImages: message.hasImages,
242
+ hasFiles: message.hasFiles,
243
+ fileCount: message.files?.length || 0,
244
+ });
245
+ try {
246
+ // Cross-machine message intercept — detect and route before normal processing
247
+ if (message.text && message.text.startsWith(CROSS_MACHINE_PREFIX)) {
248
+ const crossMachineService = getCrossMachineMessageService();
249
+ if (crossMachineService.isEnabled()) {
250
+ const handled = crossMachineService.handleIncomingMessage(message);
251
+ if (handled) {
252
+ this.logger.debug('Cross-machine message handled', {
253
+ preview: message.text.substring(0, 80),
254
+ });
255
+ return; // Don't process as a normal message
256
+ }
257
+ }
258
+ }
259
+ // Download files if present (both images and non-image files)
260
+ if (message.hasFiles && message.files) {
261
+ const imageFiles = message.files.filter(f => f.mimetype?.startsWith('image/'));
262
+ const nonImageFiles = message.files.filter(f => !f.mimetype?.startsWith('image/'));
263
+ // Download images via existing path (pass only imageFiles to avoid redundant API calls)
264
+ if (imageFiles.length > 0) {
265
+ await this.downloadMessageImages(message, imageFiles);
266
+ }
267
+ // Download non-image files
268
+ if (nonImageFiles.length > 0) {
269
+ await this.downloadMessageFiles(message, nonImageFiles);
270
+ }
271
+ }
272
+ // Get or create conversation context
273
+ const context = this.slackService.getConversationContext(message.threadTs || message.ts, message.channelId, message.userId);
274
+ // Build enriched text with file references for the agent
275
+ const enrichedText = this.enrichTextWithFiles(message);
276
+ // Store inbound message in thread file (with image metadata)
277
+ if (this.threadStore) {
278
+ const threadTs = message.threadTs || message.ts;
279
+ try {
280
+ const userName = message.user?.realName || message.user?.name || message.userId;
281
+ await this.threadStore.appendUserMessage(message.channelId, threadTs, userName, enrichedText, message.images);
282
+ }
283
+ catch (err) {
284
+ this.logger.warn('Failed to store thread message', { error: err instanceof Error ? err.message : String(err) });
285
+ }
286
+ }
287
+ // Override message text with enriched version for downstream processing
288
+ message.text = enrichedText;
289
+ // Slack team channels: a channel mapped to a Crewly team goes to that
290
+ // team's huddle (every member sees it, @'d members must reply) and
291
+ // never to the orchestrator. Unmapped channels and DMs fall through
292
+ // to the existing routing below.
293
+ const teamChannels = getSlackTeamChannelService();
294
+ if (teamChannels && teamChannels.findBySlackChannelId(message.channelId)) {
295
+ const routed = await teamChannels.routeInbound(message);
296
+ if (routed) {
297
+ this.emit('message_handled', {
298
+ message,
299
+ response: '',
300
+ routedTo: 'team-channel',
301
+ teamId: routed.mapping.teamId,
302
+ });
303
+ return;
304
+ }
305
+ }
306
+ // Auditor prefix routing — intercept "auditor ...", "/auditor ...", or "@auditor ..." messages
307
+ const auditorMatch = enrichedText.match(/^[/@]?auditor[\s:]+(.+)/is);
308
+ if (auditorMatch) {
309
+ const auditorMessage = auditorMatch[1].trim();
310
+ try {
311
+ if (this.config.showTypingIndicator) {
312
+ await this.addTypingIndicator(message);
313
+ }
314
+ const { AuditorSchedulerService } = await import('../agent/auditor-scheduler.service.js');
315
+ const scheduler = AuditorSchedulerService.getInstance();
316
+ await scheduler.handleUserMessage(auditorMessage, {
317
+ channelId: message.channelId,
318
+ threadTs: message.threadTs || message.ts,
319
+ });
320
+ if (this.config.showTypingIndicator) {
321
+ await this.markComplete(message);
322
+ }
323
+ }
324
+ catch (error) {
325
+ await this.sendErrorResponse(message, error);
326
+ }
327
+ return;
328
+ }
329
+ // #177: @mention routing — route to specific agent if @name is detected
330
+ const mentionTarget = await this.resolveMentionTarget(enrichedText);
331
+ if (mentionTarget) {
332
+ const isActive = await isAgentActive(mentionTarget.sessionName);
333
+ if (isActive) {
334
+ this.logger.info('Routing message to mentioned agent', {
335
+ agent: mentionTarget.name,
336
+ session: mentionTarget.sessionName,
337
+ });
338
+ if (this.config.showTypingIndicator) {
339
+ await this.addTypingIndicator(message);
340
+ }
341
+ // Strip the @mention prefix and send to the target agent
342
+ const cleanMessage = enrichedText.replace(new RegExp(`^@${mentionTarget.name}\\s*`, 'i'), '').trim();
343
+ const agentResponse = await this.sendToAgent(mentionTarget.sessionName, cleanMessage || enrichedText, context);
344
+ // Issue #394: `fromOrcReply` comes from the envelope — only
345
+ // `true` when slackResolve fired with a non-empty body. The
346
+ // pre-fix `response.length > 0` proxy false-positived on the
347
+ // 3 placeholder strings (timeout, direct-delivery, error),
348
+ // any of which would have auto-resolved the SLA tracker on a
349
+ // non-reply.
350
+ await this.sendSlackResponse(message, agentResponse.response, agentResponse.fromOrcReply);
351
+ if (this.config.showTypingIndicator) {
352
+ await this.markComplete(message);
353
+ }
354
+ return;
355
+ }
356
+ else {
357
+ this.logger.info('Mentioned agent is inactive, falling back to orchestrator', {
358
+ agent: mentionTarget.name,
359
+ });
360
+ }
361
+ }
362
+ // Parse command intent
363
+ const command = this.parseCommand(message.text);
364
+ // Add typing indicator
365
+ if (this.config.showTypingIndicator) {
366
+ await this.addTypingIndicator(message);
367
+ }
368
+ // Handle based on intent.
369
+ // `response` is the user-visible text; `fromOrcReply` tracks whether
370
+ // the response came from the orc's reply-slack callback (true) or a
371
+ // local string / fallback / placeholder (false). Only true responses
372
+ // may auto-resolve the V3 SLA tracker downstream.
373
+ let response;
374
+ let fromOrcReply = false;
375
+ let isOrchestratorRoute = false;
376
+ switch (command.intent) {
377
+ case 'help':
378
+ response = this.getHelpMessage();
379
+ break;
380
+ case 'status': {
381
+ const r = await this.handleStatusCommand(command, context);
382
+ response = r.response;
383
+ fromOrcReply = r.fromOrcReply;
384
+ break;
385
+ }
386
+ case 'list_projects':
387
+ case 'list_teams':
388
+ case 'list_agents': {
389
+ const r = await this.handleListCommand(command, context);
390
+ response = r.response;
391
+ fromOrcReply = r.fromOrcReply;
392
+ break;
393
+ }
394
+ case 'pause':
395
+ case 'resume': {
396
+ const r = await this.handleControlCommand(command, context);
397
+ response = r.response;
398
+ fromOrcReply = r.fromOrcReply;
399
+ break;
400
+ }
401
+ default:
402
+ // V3 Request creation for Slack user messages — fire-and-forget
403
+ setImmediate(async () => {
404
+ try {
405
+ const { RequestService } = await import('../v3/request.service.js');
406
+ const svc = RequestService.getInstance();
407
+ // 2026-05-13 dogfood fix: encode BOTH thread root AND message
408
+ // ts in sourceConversationItemId. The previous form was
409
+ // `slack-{channel}-{message.ts}`, which made
410
+ // `extractSlackThreadTs(sourceConv)` return the per-message
411
+ // ts — never the actual Slack thread root. The SLA
412
+ // threadIndex therefore mapped per-message ts → requestId,
413
+ // but when orc replied via reply-slack → POST /api/slack/send
414
+ // → markResolvedByThread(realThreadRoot), the lookup missed
415
+ // and the Request never auto-closed (PR #538 hook was a
416
+ // no-op for thread-reply messages).
417
+ //
418
+ // New form:
419
+ // Top-level message (msg.ts == thread root):
420
+ // `slack-{channelId}-{ts}` (unchanged)
421
+ // Reply within an existing thread:
422
+ // `slack-{channelId}-{threadRoot}-msg-{messageTs}`
423
+ //
424
+ // The `-msg-{...}` suffix preserves per-message uniqueness
425
+ // so `findBySourceConversationItemId` still works. The
426
+ // updated `parseSlackThreadContext` strips the suffix
427
+ // before extracting the threadTs, so the SLA's threadIndex
428
+ // now keys on the actual thread root for both shapes.
429
+ const threadRoot = message.threadTs || message.ts;
430
+ const msgId = message.threadTs && message.threadTs !== message.ts
431
+ ? `slack-${message.channelId}-${threadRoot}-msg-${message.ts}`
432
+ : `slack-${message.channelId}-${message.ts}`;
433
+ const existing = await svc.findBySourceConversationItemId(msgId);
434
+ if (existing)
435
+ return;
436
+ const rawText = message.text || '';
437
+ // Pipeline-#4 fix (spec 2026-05-05-request-decompose-pipeline-gap.md,
438
+ // Patch D): suppress trivial / continuation / file-only Slack messages
439
+ // that pollute the Request stream without ever becoming actionable
440
+ // work. ~80% of historical auto-Requests in D0AC7NF5N7L matched one
441
+ // of these gates (dogfood data 2026-05-05).
442
+ const suppressionReason = await this.shouldSuppressAutoRequest(message, rawText, svc);
443
+ if (suppressionReason) {
444
+ this.logger.debug('V3 Request creation suppressed', { msgId, reason: suppressionReason });
445
+ return;
446
+ }
447
+ const { generateRequestTitle, classifyIntent } = await import('../v3/v3-data.service.js');
448
+ // Auto-classify so request-decompose.subscriber sees correct
449
+ // intentLevel/intentCategory. Without this, every Slack-auto
450
+ // Request defaulted to L1+other and was never decomposed
451
+ // into delegation WorkItems — the entire Slack→WorkItem
452
+ // pipeline was silently no-op.
453
+ const { intentLevel, intentCategory } = classifyIntent(rawText);
454
+ const request = await svc.create({
455
+ title: generateRequestTitle(rawText, intentCategory),
456
+ description: rawText,
457
+ sourceConversationItemId: msgId,
458
+ priority: 'normal',
459
+ tags: ['slack'],
460
+ intentLevel,
461
+ intentCategory,
462
+ });
463
+ // P2-2: RequestTracker.setActiveRequest write removed. The
464
+ // companion read in v3-data.service.ts no longer falls back
465
+ // to time-window correlation; downstream delegate-task
466
+ // skills must now pass requestId explicitly.
467
+ this.logger.debug('V3 Request created from Slack message', { msgId, requestId: request.id });
468
+ }
469
+ catch (err) {
470
+ this.logger.warn('V3 Request creation from Slack failed (non-critical)', {
471
+ error: err instanceof Error ? err.message : String(err),
472
+ });
473
+ }
474
+ });
475
+ // Send to orchestrator for processing
476
+ {
477
+ const r = await this.sendToOrchestrator(message.text, context);
478
+ response = r.response;
479
+ fromOrcReply = r.fromOrcReply;
480
+ }
481
+ isOrchestratorRoute = true;
482
+ }
483
+ // Send response back to Slack. The `fromOrcReply` flag gates the V3
484
+ // SLA auto-resolve hook inside sendSlackResponse — placeholders and
485
+ // fallbacks must NOT mark the respond_to_user WI as resolved.
486
+ await this.sendSlackResponse(message, response, fromOrcReply);
487
+ // For orchestrator-routed messages, defer ✅ until reply-slack delivers
488
+ // the actual response. Store pending reaction keyed by channel+thread
489
+ // so addCompletionReaction() can find it when the reply arrives.
490
+ if (isOrchestratorRoute && this.config.showTypingIndicator) {
491
+ const threadTs = message.threadTs || message.ts;
492
+ const key = `${message.channelId}:${threadTs}`;
493
+ this.pendingReactions.set(key, message.ts);
494
+ }
495
+ else if (this.config.showTypingIndicator) {
496
+ // Non-orchestrator commands complete immediately
497
+ await this.markComplete(message);
498
+ }
499
+ this.emit('message_handled', { message, response });
500
+ }
501
+ catch (error) {
502
+ this.logger.error('Error handling message', { error: error instanceof Error ? error.message : String(error) });
503
+ await this.sendErrorResponse(message, error);
504
+ this.emit('error', error);
505
+ }
506
+ }
507
+ /**
508
+ * Handle an incoming cross-machine message.
509
+ * Routes the message payload to the local orchestrator via the message queue.
510
+ *
511
+ * @param msg - Parsed cross-machine message
512
+ */
513
+ async handleCrossMachineMessage(msg) {
514
+ this.logger.info('Routing cross-machine message to orchestrator', {
515
+ from: msg.fromName,
516
+ type: msg.type,
517
+ messageId: msg.messageId,
518
+ });
519
+ // Format as a human-readable message for the orchestrator
520
+ const orchestratorMessage = [
521
+ `[Cross-Machine] from ${msg.fromName} (${msg.from})`,
522
+ `Type: ${msg.type}`,
523
+ msg.payload.message ? `Message: ${msg.payload.message}` : '',
524
+ msg.payload.task ? `Task: ${msg.payload.task}` : '',
525
+ msg.payload.priority ? `Priority: ${msg.payload.priority}` : '',
526
+ msg.payload.context ? `Context: ${msg.payload.context}` : '',
527
+ msg.payload.summary ? `Summary: ${msg.payload.summary}` : '',
528
+ ].filter(Boolean).join('\n');
529
+ if (this.messageQueueService) {
530
+ try {
531
+ this.messageQueueService.enqueue({
532
+ content: orchestratorMessage,
533
+ conversationId: `x-machine-${msg.from}-${Date.now()}`,
534
+ source: 'cross-machine',
535
+ sourceMetadata: {
536
+ fromDevice: msg.from,
537
+ fromDeviceName: msg.fromName,
538
+ messageType: msg.type,
539
+ messageId: msg.messageId,
540
+ },
541
+ });
542
+ this.logger.info('Cross-machine message enqueued to orchestrator');
543
+ }
544
+ catch (err) {
545
+ this.logger.error('Failed to enqueue cross-machine message', {
546
+ error: err instanceof Error ? err.message : String(err),
547
+ });
548
+ }
549
+ }
550
+ else {
551
+ this.logger.warn('Cannot route cross-machine message — MessageQueueService not available');
552
+ }
553
+ }
554
+ /**
555
+ * Parse command from message text
556
+ *
557
+ * Cleans the message and extracts the command intent.
558
+ *
559
+ * @param text - Raw message text
560
+ * @returns Parsed command with intent and parameters
561
+ */
562
+ parseCommand(text) {
563
+ // Remove bot mention if present
564
+ const cleanedText = text.replace(/<@[A-Z0-9]+>/g, '').trim();
565
+ return {
566
+ intent: parseCommandIntent(cleanedText),
567
+ rawText: cleanedText,
568
+ parameters: this.extractParameters(cleanedText),
569
+ };
570
+ }
571
+ /**
572
+ * Extract parameters from command text
573
+ *
574
+ * @param text - Command text
575
+ * @returns Extracted parameters
576
+ */
577
+ extractParameters(text) {
578
+ const params = {};
579
+ // Extract quoted strings
580
+ const quotedMatch = text.match(/"([^"]+)"/);
581
+ if (quotedMatch) {
582
+ params.quoted = quotedMatch[1];
583
+ }
584
+ // Extract @mentions
585
+ const mentionMatch = text.match(/@(\w+)/);
586
+ if (mentionMatch) {
587
+ params.mention = mentionMatch[1];
588
+ }
589
+ // Extract project/team names after keywords
590
+ const forMatch = text.match(/(?:for|on|in)\s+(\w+)/i);
591
+ if (forMatch) {
592
+ params.target = forMatch[1];
593
+ }
594
+ return params;
595
+ }
596
+ /**
597
+ * Get help message
598
+ *
599
+ * @returns Formatted help message for Slack
600
+ */
601
+ getHelpMessage() {
602
+ return `*Crewly Commands:*
603
+
604
+ :clipboard: *Status*
605
+ • \`status\` - Get overall status
606
+ • \`status [project name]\` - Get project status
607
+ • \`how is [team] doing\` - Get team progress
608
+
609
+ :page_facing_up: *Lists*
610
+ • \`list projects\` - Show all projects
611
+ • \`list teams\` - Show all teams
612
+ • \`list agents\` or \`who's working\` - Show active agents
613
+
614
+ :gear: *Actions*
615
+ • \`assign [task] to [agent/team]\` - Assign work
616
+ • \`create task: [description]\` - Create a new task
617
+ • \`pause [agent/team]\` - Pause work
618
+ • \`resume [agent/team]\` - Resume work
619
+
620
+ :speech_balloon: *Chat*
621
+ Just type naturally to chat with the orchestrator!`;
622
+ }
623
+ /**
624
+ * Determine whether an inbound Slack message should be suppressed from
625
+ * auto-Request creation. Returns a reason string when the message should
626
+ * be skipped, or `null` when a Request should be created normally.
627
+ *
628
+ * Three gates (Pipeline-#4 fix, spec
629
+ * 2026-05-05-request-decompose-pipeline-gap.md, Patch D):
630
+ *
631
+ * 1. **Length / acknowledgement gate.** Trimmed text is shorter than
632
+ * {@link MIN_AUTO_REQUEST_TEXT_LENGTH} OR matches the trivial
633
+ * acknowledgement allowlist ({@link TRIVIAL_ACK_PATTERN}). Catches
634
+ * "好的", "ok", "👍", "thx" — class noise that is never actionable.
635
+ *
636
+ * 2. **Thread continuation gate.** When the inbound message is a reply
637
+ * inside an existing thread (`message.threadTs` ≠ `message.ts`) AND a
638
+ * Request already exists for the **parent** message, suppress to
639
+ * prevent every "are we still in this thread?" follow-up from creating
640
+ * a new sibling Request. Existing Request continues to receive
641
+ * orchestrator routing.
642
+ *
643
+ * 3. **File-only / synthetic-title gate.** Messages whose text is a
644
+ * synthetic `[Slack File: …]` placeholder with no narrative are
645
+ * artefacts of slack-bridge file-handling, not user requests.
646
+ *
647
+ * Each gate returns a stable reason string for log auditability. The
648
+ * caller logs at `debug` so suppression decisions are observable without
649
+ * noise.
650
+ *
651
+ * @param message - The incoming Slack message (already validated)
652
+ * @param rawText - The raw text body, trimmed by caller if needed
653
+ * @param svc - The RequestService instance for the thread-continuation lookup
654
+ * @returns A reason string when suppressed; `null` when allowed
655
+ */
656
+ async shouldSuppressAutoRequest(message, rawText, svc) {
657
+ const trimmed = rawText.trim();
658
+ // Gate 1 — length + ack allowlist
659
+ if (trimmed.length < MIN_AUTO_REQUEST_TEXT_LENGTH || TRIVIAL_ACK_PATTERN.test(trimmed)) {
660
+ return 'trivial_or_short';
661
+ }
662
+ // Gate 3 — file-only synthetic title (run before gate 2 to skip the I/O)
663
+ if (FILE_ONLY_TITLE_PATTERN.test(trimmed)) {
664
+ return 'file_only';
665
+ }
666
+ // Gate 2 — thread continuation: this message is a reply, and the parent
667
+ // message already has a NON-TERMINAL Request. Cheaper than threading
668
+ // detection at the SLA layer.
669
+ //
670
+ // ARCH 2026-05-05 PR #453 review (NC-1): the gate MUST check
671
+ // `parentRequest.status` is non-terminal — otherwise a thread that
672
+ // completed (parent → done via orc_reply / orc_reply_recheck) and then
673
+ // received a NEW actionable user message would silently suppress the new
674
+ // Request, re-opening the user-visible reliability gap that INBOUND-1
675
+ // was built to close. Terminal-parent threads release suppression so the
676
+ // child message creates a fresh Request.
677
+ const threadTs = message.threadTs;
678
+ if (threadTs && threadTs !== message.ts) {
679
+ const parentMsgId = `slack-${message.channelId}-${threadTs}`;
680
+ const parentRequest = await svc.findBySourceConversationItemId(parentMsgId);
681
+ if (parentRequest && !TERMINAL_REQUEST_STATUSES.has(parentRequest.status)) {
682
+ return 'thread_continuation';
683
+ }
684
+ }
685
+ return null;
686
+ }
687
+ /**
688
+ * Handle status command
689
+ *
690
+ * @param command - Parsed command
691
+ * @param context - Conversation context
692
+ * @returns Status response
693
+ */
694
+ async handleStatusCommand(command, context) {
695
+ return await this.sendToOrchestrator(`Give me a brief status update. ${command.rawText}`, context);
696
+ }
697
+ /**
698
+ * Handle list commands (projects, teams, agents)
699
+ *
700
+ * @param command - Parsed command
701
+ * @param context - Conversation context
702
+ * @returns List response
703
+ */
704
+ async handleListCommand(command, context) {
705
+ const prompts = {
706
+ list_projects: 'List all active projects with their status.',
707
+ list_teams: 'List all teams and their current assignments.',
708
+ list_agents: 'List all agents, their status, and what they are working on.',
709
+ };
710
+ return await this.sendToOrchestrator(prompts[command.intent] || command.rawText, context);
711
+ }
712
+ /**
713
+ * Handle control commands (pause, resume)
714
+ *
715
+ * @param command - Parsed command
716
+ * @param context - Conversation context
717
+ * @returns Control response
718
+ */
719
+ async handleControlCommand(command, context) {
720
+ const action = command.intent === 'pause' ? 'Pause' : 'Resume';
721
+ const target = command.parameters.target || command.parameters.mention || 'all agents';
722
+ return await this.sendToOrchestrator(`${action} ${target}.`, context);
723
+ }
724
+ /**
725
+ * Attempt to auto-recover the orchestrator with a hard timeout.
726
+ *
727
+ * Calls `triggerOrchestratorSetup()` from the orchestrator service module
728
+ * directly (bypassing HTTP). Wraps the attempt in a 5-second deadline so
729
+ * a wedged setup cannot stall the Slack message ingress thread.
730
+ *
731
+ * Behavior:
732
+ * - Timeout: rejects with a TimeoutError-like message after 5s.
733
+ * - Setup error: rejects with the underlying error.
734
+ * - Setup returning `success: false`: rejects with the recorded error
735
+ * (the caller treats this the same as a thrown error and falls
736
+ * through to the offline path).
737
+ *
738
+ * Caller is expected to wrap the call in try/catch and continue down
739
+ * the offline path on rejection — auto-recovery is best-effort.
740
+ *
741
+ * @returns Resolves when setup completes successfully (or was skipped
742
+ * because the orc was already healthy)
743
+ * @throws Error on timeout or setup failure
744
+ * @internal Visible for tests via class member access.
745
+ */
746
+ async attemptAutoRecovery() {
747
+ let timeoutHandle;
748
+ const timeoutPromise = new Promise((_, reject) => {
749
+ timeoutHandle = setTimeout(() => {
750
+ reject(new Error(`auto-recovery setup timed out after ${AUTO_RECOVERY_TIMEOUT_MS}ms`));
751
+ }, AUTO_RECOVERY_TIMEOUT_MS);
752
+ // Don't keep the process alive just for this timer
753
+ timeoutHandle.unref?.();
754
+ });
755
+ try {
756
+ const result = await Promise.race([triggerOrchestratorSetup(), timeoutPromise]);
757
+ if (!result.success) {
758
+ throw new Error(result.error || 'orchestrator setup returned success=false');
759
+ }
760
+ }
761
+ finally {
762
+ if (timeoutHandle) {
763
+ clearTimeout(timeoutHandle);
764
+ }
765
+ }
766
+ }
767
+ /**
768
+ * Send message to orchestrator via the message queue and wait for response.
769
+ *
770
+ * Checks if the orchestrator is active before sending. Enqueues the message
771
+ * and waits for the response via a resolve callback injected into sourceMetadata.
772
+ *
773
+ * @param message - Message to send
774
+ * @param context - Optional conversation context
775
+ * @returns Orchestrator response or offline/error message
776
+ */
777
+ async sendToOrchestrator(message, context) {
778
+ try {
779
+ // Check if orchestrator is active before attempting to send
780
+ let isActive = await isOrchestratorActive();
781
+ // Auto-recovery (B0 hot-fix, defense-in-depth):
782
+ // ESTestNode regression — `isActive` falsely reports offline when the
783
+ // orchestrator is an in-process Crewly Agent runtime that has lost its
784
+ // status registration but is otherwise healthy. Before falling
785
+ // through to the offline path, attempt one synchronous setup call.
786
+ // This is intentionally once-per-message (not retry-loop). On
787
+ // success we re-check isActive and proceed normally; on failure we
788
+ // continue down the existing offline branch (Auditor + queue).
789
+ if (!isActive) {
790
+ const recoveryStart = Date.now();
791
+ this.logger.info('Orchestrator offline — attempting auto-recovery via triggerOrchestratorSetup', {
792
+ timeoutMs: AUTO_RECOVERY_TIMEOUT_MS,
793
+ });
794
+ try {
795
+ await this.attemptAutoRecovery();
796
+ isActive = await isOrchestratorActive();
797
+ this.logger.info('Auto-recovery setup attempt complete', {
798
+ elapsedMs: Date.now() - recoveryStart,
799
+ isActiveAfter: isActive,
800
+ });
801
+ }
802
+ catch (err) {
803
+ this.logger.warn('Auto-recovery setup attempt failed (falling through to offline path)', {
804
+ elapsedMs: Date.now() - recoveryStart,
805
+ error: err instanceof Error ? err.message : String(err),
806
+ });
807
+ }
808
+ }
809
+ if (!isActive) {
810
+ // Fallback: route to Auditor agent if it's active
811
+ const auditorSession = AUDITOR_SCHEDULER_CONSTANTS.AUDITOR_SESSION_NAME;
812
+ const auditorActive = await isAgentActive(auditorSession);
813
+ if (auditorActive) {
814
+ this.logger.info('Orchestrator offline — routing message to Auditor agent');
815
+ // Auditor fallback is NOT an orc reply — caller must not auto-resolve SLA.
816
+ const fallback = await this.sendToAuditorFallback(message, context);
817
+ return { response: fallback, fromOrcReply: false };
818
+ }
819
+ // #247: Queue the message for replay when orchestrator comes back online,
820
+ // instead of silently dropping it. The queue processor defers delivery
821
+ // until the orchestrator registers (agentStatus === 'active').
822
+ // NOTE: This is an offline-path acknowledgement, NOT a real orc reply —
823
+ // every return from this branch must set `fromOrcReply: false`.
824
+ if (this.messageQueueService) {
825
+ this.logger.info('Orchestrator offline — queuing message for replay when it comes back online');
826
+ // Enrich message with thread file path hint for orchestrator context
827
+ let enrichedMessage = message;
828
+ if (this.threadStore && context) {
829
+ const threadFilePath = this.threadStore.getThreadFilePath(context.channelId, context.threadTs);
830
+ enrichedMessage = `${message}\n\n[Thread context file: ${threadFilePath}]`;
831
+ }
832
+ // Store in canonical chat-v2 for persistence
833
+ const result = {
834
+ conversation: {
835
+ id: this.persistSlackInbound({
836
+ content: enrichedMessage,
837
+ conversationId: context?.conversationId,
838
+ agentSession: 'crewly-orc',
839
+ channelId: context?.channelId,
840
+ threadTs: context?.threadTs,
841
+ userId: context?.userId,
842
+ }).conversationId,
843
+ },
844
+ };
845
+ try {
846
+ this.messageQueueService.enqueue({
847
+ content: enrichedMessage,
848
+ conversationId: result.conversation.id,
849
+ source: 'slack',
850
+ sourceMetadata: {
851
+ userId: context?.userId,
852
+ channelId: context?.channelId,
853
+ threadTs: context?.threadTs,
854
+ },
855
+ });
856
+ // Track inbound thread for offline message recovery
857
+ if (this.threadStatusQueue && context?.channelId) {
858
+ try {
859
+ const threadKey = context.threadTs
860
+ ? `${context.channelId}:${context.threadTs}`
861
+ : `${context.channelId}:${Date.now()}`;
862
+ this.threadStatusQueue.trackInbound({
863
+ source: 'slack',
864
+ threadKey,
865
+ conversationId: result.conversation.id,
866
+ messagePreview: message.slice(0, THREAD_STATUS_CONSTANTS.MAX_PREVIEW_LENGTH),
867
+ sourceMetadata: {
868
+ channelId: context.channelId,
869
+ threadTs: context.threadTs,
870
+ userId: context.userId,
871
+ },
872
+ });
873
+ }
874
+ catch (trackErr) {
875
+ this.logger.warn('Failed to track inbound thread status (offline path)', {
876
+ error: trackErr instanceof Error ? trackErr.message : String(trackErr),
877
+ });
878
+ }
879
+ }
880
+ return {
881
+ response: 'The orchestrator is currently offline. Your message has been queued and will be processed when it comes back online.',
882
+ fromOrcReply: false,
883
+ };
884
+ }
885
+ catch (enqueueErr) {
886
+ this.logger.warn('Failed to queue message for offline orchestrator', {
887
+ error: enqueueErr instanceof Error ? enqueueErr.message : String(enqueueErr),
888
+ });
889
+ }
890
+ }
891
+ this.logger.info('Orchestrator is not active, returning offline message');
892
+ return { response: getOrchestratorOfflineMessage(true), fromOrcReply: false };
893
+ }
894
+ // Check if message queue service is available
895
+ if (!this.messageQueueService) {
896
+ this.logger.error('Message queue service not configured');
897
+ return {
898
+ response: 'The Slack bridge is not properly configured. Please restart the server.',
899
+ fromOrcReply: false,
900
+ };
901
+ }
902
+ // Enrich message with thread file path hint for orchestrator context
903
+ let enrichedMessage = message;
904
+ if (this.threadStore && context) {
905
+ const threadFilePath = this.threadStore.getThreadFilePath(context.channelId, context.threadTs);
906
+ enrichedMessage = `${message}\n\n[Thread context file: ${threadFilePath}]`;
907
+ }
908
+ // Persist user message in canonical chat-v2 store
909
+ const result = {
910
+ conversation: {
911
+ id: this.persistSlackInbound({
912
+ content: enrichedMessage,
913
+ conversationId: context?.conversationId,
914
+ agentSession: 'crewly-orc',
915
+ channelId: context?.channelId,
916
+ threadTs: context?.threadTs,
917
+ userId: context?.userId,
918
+ }).conversationId,
919
+ },
920
+ };
921
+ // Enqueue the message with a resolve callback for response routing.
922
+ // The QueueProcessorService will call slackResolve() when the
923
+ // orchestrator responds, unblocking this promise.
924
+ //
925
+ // The promise resolves with `{response, fromOrcReply}`. `fromOrcReply`
926
+ // is `true` ONLY when slackResolve fires (orc's reply-slack skill
927
+ // delivered an actual reply). On responseTimeoutMs or enqueue failure
928
+ // it is `false` — the placeholder must NOT auto-resolve the SLA
929
+ // tracker (Steve 2026-04-30 incident: false-done Request cascade).
930
+ const orcResponse = await new Promise((resolve) => {
931
+ let resolved = false;
932
+ const timeoutId = setTimeout(() => {
933
+ if (!resolved) {
934
+ resolved = true;
935
+ resolve({
936
+ response: 'The orchestrator is still processing your request. It will reply here when ready — no need to resend.',
937
+ fromOrcReply: false,
938
+ });
939
+ }
940
+ }, this.config.responseTimeoutMs);
941
+ try {
942
+ this.messageQueueService.enqueue({
943
+ content: enrichedMessage,
944
+ conversationId: result.conversation.id,
945
+ source: 'slack',
946
+ sourceMetadata: {
947
+ slackResolve: (resp) => {
948
+ if (!resolved) {
949
+ resolved = true;
950
+ clearTimeout(timeoutId);
951
+ // 2026-05-12 dogfood bug: the QueueProcessor fires
952
+ // `routeResponse(message, '')` immediately after PTY
953
+ // delivery to unblock this promise (see
954
+ // queue-processor.service.ts:692 "fire-and-forget"
955
+ // comment). That call carries an EMPTY response — orc
956
+ // has only RECEIVED the message, not REPLIED. The
957
+ // previous shape of this callback always returned
958
+ // `fromOrcReply: true`, so every Slack delivery
959
+ // triggered `markResolvedByThread('orc_reply')` →
960
+ // `maybeCloseRequest` → Request cascaded to `done`
961
+ // with `result: "Auto-closed by SLA: orc_reply"`
962
+ // before the user ever saw a reply.
963
+ //
964
+ // Real orc replies (via the reply-slack skill) come
965
+ // through a different route — the orc invokes
966
+ // `POST /slack/send`, which posts to Slack directly;
967
+ // the SLA tracker is resolved when the
968
+ // `respond_to_user` WI transitions to `verified` and
969
+ // the cascade subscriber picks it up. That path
970
+ // produces a non-empty response payload only when
971
+ // a worker explicitly drives reply text back through
972
+ // the queue (rare; most orc replies are direct API).
973
+ //
974
+ // Gate: treat empty resp as a delivery ack ONLY
975
+ // (fromOrcReply=false). Non-empty resp keeps the
976
+ // legacy `true` semantics for any worker path that
977
+ // does echo a reply through the queue.
978
+ const fromOrcReply = resp.length > 0;
979
+ resolve({ response: resp, fromOrcReply });
980
+ }
981
+ },
982
+ userId: context?.userId,
983
+ channelId: context?.channelId,
984
+ threadTs: context?.threadTs,
985
+ },
986
+ });
987
+ // Track inbound thread for lifecycle monitoring and restart recovery
988
+ if (this.threadStatusQueue && context?.channelId) {
989
+ try {
990
+ const threadKey = context.threadTs
991
+ ? `${context.channelId}:${context.threadTs}`
992
+ : `${context.channelId}:${Date.now()}`;
993
+ this.threadStatusQueue.trackInbound({
994
+ source: 'slack',
995
+ threadKey,
996
+ conversationId: result.conversation.id,
997
+ messagePreview: message.slice(0, THREAD_STATUS_CONSTANTS.MAX_PREVIEW_LENGTH),
998
+ sourceMetadata: {
999
+ channelId: context.channelId,
1000
+ threadTs: context.threadTs,
1001
+ userId: context.userId,
1002
+ },
1003
+ });
1004
+ }
1005
+ catch (trackErr) {
1006
+ this.logger.warn('Failed to track inbound thread status', {
1007
+ error: trackErr instanceof Error ? trackErr.message : String(trackErr),
1008
+ });
1009
+ }
1010
+ }
1011
+ }
1012
+ catch (enqueueErr) {
1013
+ if (!resolved) {
1014
+ resolved = true;
1015
+ clearTimeout(timeoutId);
1016
+ resolve({
1017
+ response: `Failed to enqueue message: ${enqueueErr instanceof Error ? enqueueErr.message : String(enqueueErr)}`,
1018
+ fromOrcReply: false,
1019
+ });
1020
+ }
1021
+ }
1022
+ });
1023
+ return orcResponse;
1024
+ }
1025
+ catch (error) {
1026
+ this.logger.error('Error sending to orchestrator', { error: error instanceof Error ? error.message : String(error) });
1027
+ throw error;
1028
+ }
1029
+ }
1030
+ /**
1031
+ * Route a message to the Auditor agent as a fallback when the orchestrator is offline.
1032
+ *
1033
+ * Enqueues the message targeting the Auditor's session so the queue processor
1034
+ * delivers it to the Auditor PTY instead of the orchestrator. Includes Slack
1035
+ * context (channel, thread) so the Auditor can respond.
1036
+ *
1037
+ * **Thread file enrichment (parity with `sendToOrchestrator` ~line 712):**
1038
+ * When a `threadStore` and Slack `context` are available, the enriched
1039
+ * message also carries a `[Thread context file: <path>]` line. Without
1040
+ * this, the Auditor receives only the bare `[SLACK_CONTEXT:...]` prefix
1041
+ * and cannot read prior thread history, causing context-blind replies.
1042
+ * This is the bug Steve hit on 2026-04-25 (StevesPrompt deploy thread):
1043
+ * orchestrator dropped, Slack fell through here, Auditor responded with
1044
+ * "I cannot see the rest of the conversation" because the thread file
1045
+ * pointer was missing. Bringing the enrichment in line with the
1046
+ * orchestrator path closes the gap.
1047
+ *
1048
+ * @param message - Original user message
1049
+ * @param context - Slack conversation context
1050
+ * @returns Acknowledgement message to the user
1051
+ */
1052
+ async sendToAuditorFallback(message, context) {
1053
+ const auditorSession = AUDITOR_SCHEDULER_CONSTANTS.AUDITOR_SESSION_NAME;
1054
+ // Build a context-enriched message so the Auditor knows the source
1055
+ const slackPrefix = context
1056
+ ? `[SLACK_CONTEXT:channelId=${context.channelId},threadTs=${context.threadTs || ''}]`
1057
+ : '';
1058
+ let enrichedMessage = `${slackPrefix} [FALLBACK] Orchestrator is offline. User message:\n${message}`;
1059
+ if (this.threadStore && context) {
1060
+ const threadFilePath = this.threadStore.getThreadFilePath(context.channelId, context.threadTs);
1061
+ enrichedMessage += `\n\n[Thread context file: ${threadFilePath}]`;
1062
+ }
1063
+ // Try to enqueue via the message queue (same path as orchestrator delivery)
1064
+ if (this.messageQueueService) {
1065
+ try {
1066
+ const result = {
1067
+ conversation: {
1068
+ id: this.persistSlackInbound({
1069
+ content: enrichedMessage,
1070
+ conversationId: context?.conversationId,
1071
+ agentSession: auditorSession,
1072
+ channelId: context?.channelId,
1073
+ threadTs: context?.threadTs,
1074
+ userId: context?.userId,
1075
+ }).conversationId,
1076
+ },
1077
+ };
1078
+ this.messageQueueService.enqueue({
1079
+ content: enrichedMessage,
1080
+ conversationId: result.conversation.id,
1081
+ source: 'slack',
1082
+ targetSession: auditorSession,
1083
+ sourceMetadata: {
1084
+ slackResolve: undefined,
1085
+ userId: context?.userId,
1086
+ channelId: context?.channelId,
1087
+ },
1088
+ });
1089
+ this.logger.info('Message routed to Auditor agent via queue', { auditorSession });
1090
+ return 'The orchestrator is currently offline. Your message has been forwarded to the Auditor agent.';
1091
+ }
1092
+ catch (err) {
1093
+ this.logger.error('Failed to route message to Auditor via queue', {
1094
+ error: err instanceof Error ? err.message : String(err),
1095
+ });
1096
+ }
1097
+ }
1098
+ // Last resort: direct delivery via AuditorSchedulerService
1099
+ try {
1100
+ const { AuditorSchedulerService } = await import('../agent/auditor-scheduler.service.js');
1101
+ const scheduler = AuditorSchedulerService.getInstance();
1102
+ await scheduler.handleUserMessage(`[FALLBACK] Orchestrator is offline. User message: ${message}`, { channelId: context?.channelId || '', threadTs: context?.threadTs || '' });
1103
+ return 'The orchestrator is currently offline. Your message has been forwarded to the Auditor agent.';
1104
+ }
1105
+ catch (err) {
1106
+ this.logger.error('Failed to route message to Auditor via scheduler', {
1107
+ error: err instanceof Error ? err.message : String(err),
1108
+ });
1109
+ }
1110
+ return getOrchestratorOfflineMessage(true);
1111
+ }
1112
+ /**
1113
+ * Refresh file download URLs via the Slack files.info API.
1114
+ * The event payload URLs may not work with just the bot token — the
1115
+ * files.info API returns authenticated URLs and validates scope.
1116
+ *
1117
+ * @param files - Slack file objects to refresh URLs for (mutated in place)
1118
+ * @returns true if downloads can proceed, false if scope is missing
1119
+ */
1120
+ async refreshFileUrls(files) {
1121
+ for (const file of files) {
1122
+ try {
1123
+ const freshInfo = await this.slackService.getFileInfo(file.id);
1124
+ if (freshInfo.url_private_download) {
1125
+ file.url_private_download = freshInfo.url_private_download;
1126
+ }
1127
+ if (freshInfo.url_private) {
1128
+ file.url_private = freshInfo.url_private;
1129
+ }
1130
+ }
1131
+ catch (err) {
1132
+ const errMsg = err instanceof Error ? err.message : String(err);
1133
+ if (errMsg.includes('missing_scope') || errMsg.includes('not_allowed_token_type')) {
1134
+ this.logger.error('Bot token lacks files:read scope — cannot download files. Add the "files:read" scope to your Slack app.');
1135
+ return false;
1136
+ }
1137
+ this.logger.warn('Could not refresh URL via files.info', { fileName: file.name, error: errMsg });
1138
+ }
1139
+ }
1140
+ return true;
1141
+ }
1142
+ /**
1143
+ * Download image files from a Slack message using SlackImageService.
1144
+ * Populates `message.images` with successfully downloaded image info.
1145
+ * Downloads are batched with a concurrency limit of MAX_CONCURRENT_DOWNLOADS.
1146
+ *
1147
+ * @param message - Incoming message to attach downloaded images to
1148
+ * @param imageFiles - Pre-filtered list of image files to download
1149
+ */
1150
+ async downloadMessageImages(message, imageFiles) {
1151
+ const botToken = this.slackService.getBotToken();
1152
+ if (!botToken) {
1153
+ this.logger.warn('Cannot download images: no bot token available');
1154
+ return;
1155
+ }
1156
+ if (imageFiles.length === 0) {
1157
+ return;
1158
+ }
1159
+ const slackImageService = getSlackImageService();
1160
+ const files = imageFiles;
1161
+ const downloadedImages = [];
1162
+ const maxConcurrent = SLACK_IMAGE_CONSTANTS.MAX_CONCURRENT_DOWNLOADS;
1163
+ const rejectionMessages = [];
1164
+ // Refresh file URLs via files.info API before downloading.
1165
+ const canProceed = await this.refreshFileUrls(files);
1166
+ if (!canProceed)
1167
+ return;
1168
+ for (let i = 0; i < files.length; i += maxConcurrent) {
1169
+ const batch = files.slice(i, i + maxConcurrent);
1170
+ const results = await Promise.allSettled(batch.map((file) => slackImageService.downloadImage(file, botToken)));
1171
+ for (let j = 0; j < results.length; j++) {
1172
+ const result = results[j];
1173
+ if (result.status === 'fulfilled') {
1174
+ downloadedImages.push(result.value);
1175
+ }
1176
+ else {
1177
+ const fileName = batch[j].name;
1178
+ const reason = result.reason instanceof Error ? result.reason.message : String(result.reason);
1179
+ this.logger.warn('Failed to download image', { fileName, reason });
1180
+ // Track files rejected due to validation (size/type) to warn the Slack user.
1181
+ // These match the error prefixes from SlackImageService.downloadImage().
1182
+ if (reason.startsWith('File too large:') || reason.startsWith('Unsupported image type:')) {
1183
+ rejectionMessages.push(`${fileName}: ${reason}`);
1184
+ }
1185
+ }
1186
+ }
1187
+ }
1188
+ if (downloadedImages.length > 0) {
1189
+ message.images = downloadedImages;
1190
+ }
1191
+ // Send a warning back to Slack if any files were rejected
1192
+ if (rejectionMessages.length > 0) {
1193
+ try {
1194
+ const maxMB = Math.round(SLACK_IMAGE_CONSTANTS.MAX_FILE_SIZE / (1024 * 1024));
1195
+ const supportedTypes = SLACK_IMAGE_CONSTANTS.SUPPORTED_MIMES.map(m => m.replace('image/', '').toUpperCase()).join(', ');
1196
+ const warningText = `:warning: Some image(s) could not be processed:\n${rejectionMessages.map(f => `• ${f}`).join('\n')}\n\nSupported types: ${supportedTypes}. Max size: ${maxMB} MB.`;
1197
+ await this.slackService.sendMessage({
1198
+ channelId: message.channelId,
1199
+ text: warningText,
1200
+ threadTs: message.threadTs || message.ts,
1201
+ });
1202
+ }
1203
+ catch (err) {
1204
+ this.logger.warn('Failed to send rejection warning to Slack', { error: err instanceof Error ? err.message : String(err) });
1205
+ }
1206
+ }
1207
+ }
1208
+ /**
1209
+ * Download non-image file attachments from a Slack message.
1210
+ * Uses authenticated fetch (same pattern as SlackImageService) to download
1211
+ * files to a temp directory. Populates `message.attachments` with results.
1212
+ * Skips magic-byte validation since these are generic files.
1213
+ *
1214
+ * @param message - Incoming message to populate with downloaded file info
1215
+ * @param nonImageFiles - Non-image SlackFile objects to download
1216
+ */
1217
+ async downloadMessageFiles(message, nonImageFiles) {
1218
+ const botToken = this.slackService.getBotToken();
1219
+ if (!botToken) {
1220
+ this.logger.warn('Cannot download files: no bot token available');
1221
+ return;
1222
+ }
1223
+ const crewlyHome = path.join(os.homedir(), '.crewly');
1224
+ const tempDir = path.join(crewlyHome, SLACK_FILE_DOWNLOAD_CONSTANTS.TEMP_DIR);
1225
+ await fs.mkdir(tempDir, { recursive: true });
1226
+ const downloadedFiles = [];
1227
+ const rejectionMessages = [];
1228
+ const maxConcurrent = SLACK_FILE_DOWNLOAD_CONSTANTS.MAX_CONCURRENT_DOWNLOADS;
1229
+ // Refresh file URLs via files.info API
1230
+ const canProceed = await this.refreshFileUrls(nonImageFiles);
1231
+ if (!canProceed)
1232
+ return;
1233
+ for (let i = 0; i < nonImageFiles.length; i += maxConcurrent) {
1234
+ const batch = nonImageFiles.slice(i, i + maxConcurrent);
1235
+ const results = await Promise.allSettled(batch.map(async (file) => {
1236
+ // Size check
1237
+ if (file.size > SLACK_FILE_DOWNLOAD_CONSTANTS.MAX_FILE_SIZE) {
1238
+ const maxMB = Math.round(SLACK_FILE_DOWNLOAD_CONSTANTS.MAX_FILE_SIZE / (1024 * 1024));
1239
+ throw new Error(`File too large: ${file.size} bytes (max ${maxMB} MB)`);
1240
+ }
1241
+ const safeName = file.name.replace(/[^a-zA-Z0-9._-]/g, '_');
1242
+ const localPath = path.join(tempDir, `${file.id}-${safeName}`);
1243
+ const downloadUrl = file.url_private_download || file.url_private;
1244
+ // Authenticated fetch with manual redirect handling, timeout, and resource cleanup
1245
+ const maxRedirects = SLACK_FILE_DOWNLOAD_CONSTANTS.MAX_DOWNLOAD_REDIRECTS;
1246
+ const timeoutMs = SLACK_FILE_DOWNLOAD_CONSTANTS.DOWNLOAD_TIMEOUT_MS;
1247
+ const controller = new AbortController();
1248
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
1249
+ let currentUrl = downloadUrl;
1250
+ let response = null;
1251
+ try {
1252
+ let exhaustedRedirects = true;
1253
+ for (let r = 0; r <= maxRedirects; r++) {
1254
+ response = await fetch(currentUrl, {
1255
+ headers: { 'Authorization': `Bearer ${botToken}` },
1256
+ redirect: 'manual',
1257
+ signal: controller.signal,
1258
+ });
1259
+ if (response.status >= 300 && response.status < 400) {
1260
+ const location = response.headers.get('location');
1261
+ if (!location)
1262
+ throw new Error(`Redirect without Location header`);
1263
+ // Drain response body to free the socket before following redirect
1264
+ await response.body?.cancel();
1265
+ currentUrl = location;
1266
+ continue;
1267
+ }
1268
+ exhaustedRedirects = false;
1269
+ break;
1270
+ }
1271
+ if (exhaustedRedirects) {
1272
+ throw new Error(`Too many redirects (${maxRedirects}) while downloading file from Slack`);
1273
+ }
1274
+ if (!response || !response.ok) {
1275
+ throw new Error(`Download failed with status ${response?.status || 'unknown'}`);
1276
+ }
1277
+ if (!response.body) {
1278
+ throw new Error('Empty response body from Slack');
1279
+ }
1280
+ const fileStream = createWriteStream(localPath);
1281
+ const nodeStream = Readable.fromWeb(response.body);
1282
+ await pipeline(nodeStream, fileStream);
1283
+ }
1284
+ catch (downloadErr) {
1285
+ // Clean up partial file on failure
1286
+ try {
1287
+ await fs.unlink(localPath);
1288
+ }
1289
+ catch { /* ignore if file doesn't exist */ }
1290
+ throw downloadErr;
1291
+ }
1292
+ finally {
1293
+ clearTimeout(timeoutId);
1294
+ }
1295
+ // Extract text from PDFs after download
1296
+ let extractedText;
1297
+ if (SLACK_FILE_DOWNLOAD_CONSTANTS.EXTRACTABLE_MIMES.includes(file.mimetype)) {
1298
+ extractedText = await this.extractPdfText(localPath, file.name);
1299
+ }
1300
+ return {
1301
+ id: file.id,
1302
+ name: file.name,
1303
+ mimetype: file.mimetype,
1304
+ localPath,
1305
+ size: file.size,
1306
+ permalink: file.permalink,
1307
+ extractedText,
1308
+ };
1309
+ }));
1310
+ for (let j = 0; j < results.length; j++) {
1311
+ const result = results[j];
1312
+ if (result.status === 'fulfilled') {
1313
+ downloadedFiles.push(result.value);
1314
+ }
1315
+ else {
1316
+ const fileName = batch[j].name;
1317
+ const reason = result.reason instanceof Error ? result.reason.message : String(result.reason);
1318
+ this.logger.warn('Failed to download file', { fileName, reason });
1319
+ if (reason.startsWith('File too large:')) {
1320
+ rejectionMessages.push(`${fileName}: ${reason}`);
1321
+ }
1322
+ }
1323
+ }
1324
+ }
1325
+ if (downloadedFiles.length > 0) {
1326
+ message.attachments = downloadedFiles;
1327
+ }
1328
+ if (rejectionMessages.length > 0) {
1329
+ try {
1330
+ const maxMB = Math.round(SLACK_FILE_DOWNLOAD_CONSTANTS.MAX_FILE_SIZE / (1024 * 1024));
1331
+ const warningText = `:warning: Some file(s) could not be downloaded:\n${rejectionMessages.map(f => `• ${f}`).join('\n')}\n\nMax size: ${maxMB} MB.`;
1332
+ await this.slackService.sendMessage({
1333
+ channelId: message.channelId,
1334
+ text: warningText,
1335
+ threadTs: message.threadTs || message.ts,
1336
+ });
1337
+ }
1338
+ catch (err) {
1339
+ this.logger.warn('Failed to send file rejection warning to Slack', { error: err instanceof Error ? err.message : String(err) });
1340
+ }
1341
+ }
1342
+ }
1343
+ /**
1344
+ * Enrich message text with file path references so agents
1345
+ * can read them via their file-reading tools (Claude Code Read, Gemini @file).
1346
+ * Includes both images and non-image file attachments.
1347
+ *
1348
+ * @param message - Message with optional downloaded images and files
1349
+ * @returns Enriched text with file references appended
1350
+ */
1351
+ enrichTextWithFiles(message) {
1352
+ let text = message.text || '';
1353
+ if (message.images && message.images.length > 0) {
1354
+ for (const img of message.images) {
1355
+ const dims = img.width && img.height ? ` (${img.width}x${img.height})` : '';
1356
+ text += `\n[Slack Image: ${img.localPath}${dims}, ${img.mimetype}]`;
1357
+ }
1358
+ }
1359
+ if (message.attachments && message.attachments.length > 0) {
1360
+ for (const file of message.attachments) {
1361
+ const sizeStr = file.size < 1024 ? `${file.size}B` : `${Math.round(file.size / 1024)}KB`;
1362
+ text += `\n[Slack File: ${file.localPath} (${file.name}, ${file.mimetype}, ${sizeStr})]`;
1363
+ if (file.extractedText) {
1364
+ text += `\n--- Extracted content from ${file.name} ---\n${file.extractedText}\n--- End of ${file.name} ---`;
1365
+ }
1366
+ }
1367
+ }
1368
+ return text;
1369
+ }
1370
+ /**
1371
+ * Extract text content from a downloaded PDF file.
1372
+ * Returns undefined if extraction fails or produces no text.
1373
+ *
1374
+ * @param filePath - Absolute path to the downloaded PDF
1375
+ * @param fileName - Original file name (for logging)
1376
+ * @returns Extracted text (possibly truncated) or undefined
1377
+ */
1378
+ async extractPdfText(filePath, fileName) {
1379
+ try {
1380
+ const fileBuffer = await fs.readFile(filePath);
1381
+ const parser = new PDFParse({ data: fileBuffer });
1382
+ const pdfData = await parser.getText();
1383
+ const rawText = typeof pdfData === 'string' ? pdfData : pdfData?.text;
1384
+ if (rawText && rawText.trim().length > 0) {
1385
+ const maxLen = SLACK_FILE_DOWNLOAD_CONSTANTS.MAX_EXTRACTED_TEXT_LENGTH;
1386
+ return rawText.trim().length > maxLen
1387
+ ? rawText.trim().substring(0, maxLen) + '\n... [truncated]'
1388
+ : rawText.trim();
1389
+ }
1390
+ return undefined;
1391
+ }
1392
+ catch (extractErr) {
1393
+ this.logger.warn('Failed to extract text from PDF', {
1394
+ fileName,
1395
+ error: extractErr instanceof Error ? extractErr.message : String(extractErr),
1396
+ });
1397
+ return undefined;
1398
+ }
1399
+ }
1400
+ /**
1401
+ * Add typing indicator to message
1402
+ *
1403
+ * @param message - Message to add indicator to
1404
+ */
1405
+ async addTypingIndicator(message) {
1406
+ try {
1407
+ await this.slackService.addReaction(message.channelId, message.ts, 'eyes');
1408
+ }
1409
+ catch (error) {
1410
+ // Non-critical - reactions require 'reactions:write' scope which is optional
1411
+ const errorMessage = error instanceof Error ? error.message : String(error);
1412
+ if (errorMessage.includes('missing_scope')) {
1413
+ // Only log once about missing scope, not on every message
1414
+ if (!this.loggedMissingScope) {
1415
+ this.logger.warn('Reactions disabled - add reactions:write scope to Slack app for typing indicators');
1416
+ this.loggedMissingScope = true;
1417
+ }
1418
+ }
1419
+ else {
1420
+ this.logger.warn('Could not add typing indicator', { error: errorMessage });
1421
+ }
1422
+ }
1423
+ }
1424
+ /**
1425
+ * Mark message as complete
1426
+ *
1427
+ * @param message - Message to mark complete
1428
+ */
1429
+ async markComplete(message) {
1430
+ try {
1431
+ await this.slackService.addReaction(message.channelId, message.ts, 'white_check_mark');
1432
+ }
1433
+ catch (error) {
1434
+ // Non-critical - reactions require 'reactions:write' scope which is optional
1435
+ const errorMessage = error instanceof Error ? error.message : String(error);
1436
+ if (!errorMessage.includes('missing_scope')) {
1437
+ this.logger.warn('Could not add completion indicator', { error: errorMessage });
1438
+ }
1439
+ // Silent fail for missing_scope since we already logged about it
1440
+ }
1441
+ }
1442
+ /**
1443
+ * Add a completion reaction (✅) to a message that was previously
1444
+ * stored as a pending reaction. Consumes the pending reaction.
1445
+ *
1446
+ * @param channelId - Slack channel ID
1447
+ * @param threadTs - Thread timestamp (key for lookup)
1448
+ */
1449
+ async addCompletionReaction(channelId, threadTs) {
1450
+ const key = `${channelId}:${threadTs}`;
1451
+ const messageTs = this.pendingReactions.get(key);
1452
+ if (messageTs) {
1453
+ // Consume the pending reaction
1454
+ this.pendingReactions.delete(key);
1455
+ try {
1456
+ await this.slackService.addReaction(channelId, messageTs, 'white_check_mark');
1457
+ }
1458
+ catch (error) {
1459
+ const errMsg = error instanceof Error ? error.message : String(error);
1460
+ // Suppress "already_reacted" errors as they are common and non-fatal
1461
+ if (errMsg.includes('already_reacted')) {
1462
+ return;
1463
+ }
1464
+ // Suppress "missing_scope" since we already log/warn about that elsewhere
1465
+ if (!errMsg.includes('missing_scope')) {
1466
+ this.logger.warn('Failed to add completion reaction', { channelId, messageTs, error: errMsg });
1467
+ }
1468
+ }
1469
+ }
1470
+ }
1471
+ /**
1472
+ * Record response to thread store. Slack delivery is handled exclusively
1473
+ * by the reply-slack skill via the API — no terminal output fallback needed.
1474
+ *
1475
+ * The `fromOrcReply` flag gates the V3 SLA auto-resolve hook
1476
+ * (`markResolvedByThread`). Only real orc replies (delivered via the
1477
+ * orc's reply-slack skill → `slackResolve` callback) may auto-resolve
1478
+ * the SLA tracker. Placeholder / timeout / offline / fallback responses
1479
+ * must NOT trigger the cascade — doing so closes the parent Request to
1480
+ * `done` even though the orc never actually replied (Steve 2026-04-30
1481
+ * incident: false-done Request, paired with Bug 1 silent-drop in
1482
+ * agent-registration.service.ts).
1483
+ *
1484
+ * Default `fromOrcReply = true` preserves the legacy behaviour for the
1485
+ * mention-routing call site (line ~327) which currently has no
1486
+ * placeholder semantics — its `sendToAgent` path delivers a direct
1487
+ * agent reply when reachable. If that path later grows a timeout
1488
+ * fallback, the call site should pass `false` explicitly.
1489
+ *
1490
+ * @param originalMessage - Original incoming message
1491
+ * @param response - Response content (real reply or placeholder)
1492
+ * @param fromOrcReply - `true` only when the response came from a
1493
+ * real agent/orc reply path. `false` for any timeout / fallback /
1494
+ * offline acknowledgement. Drives whether the SLA tracker is
1495
+ * auto-resolved for the matching Slack thread.
1496
+ */
1497
+ async sendSlackResponse(originalMessage, response, fromOrcReply = true) {
1498
+ await this.recordThreadReply(originalMessage, response);
1499
+ // INBOUND-1.4: notify the RequestSlaSubscriber that the orc replied to
1500
+ // this Slack thread so any tracked respond_to_user WorkItem can
1501
+ // auto-transition and the SLA timers no-op. Lazy import breaks the
1502
+ // static cycle (subscriber boot wires this bridge).
1503
+ if (!fromOrcReply) {
1504
+ this.logger.debug('Skipping SLA auto-resolve — response is not a real orc reply', {
1505
+ threadTs: originalMessage.ts,
1506
+ responsePreview: response.slice(0, 60),
1507
+ });
1508
+ return;
1509
+ }
1510
+ try {
1511
+ const { getRequestSlaSubscriber } = await import('../v3/request-sla.subscriber.js');
1512
+ const sub = getRequestSlaSubscriber();
1513
+ if (sub) {
1514
+ // sourceConversationItemId for slack messages is `slack-${channelId}-${ts}`
1515
+ // (see line ~372 above); the threadTs we index on is the original
1516
+ // user message ts. originalMessage.ts is exactly that.
1517
+ await sub.markResolvedByThread(originalMessage.ts);
1518
+ }
1519
+ }
1520
+ catch (err) {
1521
+ this.logger.debug('SLA auto-resolve hook failed (non-critical)', {
1522
+ error: err instanceof Error ? err.message : String(err),
1523
+ });
1524
+ }
1525
+ }
1526
+ /**
1527
+ * Send error response
1528
+ *
1529
+ * @param message - Original message
1530
+ * @param error - Error that occurred
1531
+ */
1532
+ async sendErrorResponse(message, error) {
1533
+ await this.slackService.sendMessage({
1534
+ channelId: message.channelId,
1535
+ text: `:warning: Sorry, I encountered an error: ${error.message}`,
1536
+ threadTs: message.threadTs || message.ts,
1537
+ });
1538
+ }
1539
+ /**
1540
+ * Format response for Slack
1541
+ *
1542
+ * Converts markdown to Slack-compatible formatting.
1543
+ *
1544
+ * @param text - Text to format
1545
+ * @returns Formatted text
1546
+ */
1547
+ formatForSlack(text) {
1548
+ // Convert markdown headers to bold
1549
+ let formatted = text.replace(/^### (.+)$/gm, '*$1*');
1550
+ formatted = formatted.replace(/^## (.+)$/gm, '*$1*');
1551
+ formatted = formatted.replace(/^# (.+)$/gm, '*$1*');
1552
+ // Slack already supports backtick code formatting
1553
+ // Convert code blocks (simplified)
1554
+ formatted = formatted.replace(/```[\w]*\n([\s\S]*?)```/g, '```$1```');
1555
+ return formatted;
1556
+ }
1557
+ /**
1558
+ * Persist Slack reply content to the thread store when available.
1559
+ */
1560
+ async recordThreadReply(originalMessage, content) {
1561
+ if (!this.threadStore)
1562
+ return;
1563
+ const trimmed = content?.trim();
1564
+ if (!trimmed)
1565
+ return;
1566
+ const threadTs = originalMessage.threadTs || originalMessage.ts;
1567
+ if (!threadTs)
1568
+ return;
1569
+ try {
1570
+ await this.threadStore.appendOrchestratorReply(originalMessage.channelId, threadTs, trimmed);
1571
+ }
1572
+ catch (err) {
1573
+ this.logger.warn('Failed to store thread reply', { error: err instanceof Error ? err.message : String(err) });
1574
+ }
1575
+ }
1576
+ /**
1577
+ * Send proactive notification to Slack
1578
+ *
1579
+ * @param notification - Notification to send
1580
+ */
1581
+ async sendNotification(notification) {
1582
+ if (!this.config.enableNotifications)
1583
+ return;
1584
+ await this.slackService.sendNotification(notification);
1585
+ }
1586
+ /**
1587
+ * Send a content approval notification to Slack with Block Kit buttons.
1588
+ *
1589
+ * Posts a rich message with content preview and approve/reject buttons.
1590
+ * Links the Slack message back to the approval record so interactive
1591
+ * button clicks can resolve the approval.
1592
+ *
1593
+ * @param approvalId - The content approval ID
1594
+ * @param channelId - Slack channel ID
1595
+ * @param threadTs - Optional thread timestamp
1596
+ * @returns The Slack message timestamp, or null if failed
1597
+ */
1598
+ async sendContentApproval(approvalId, channelId, threadTs) {
1599
+ if (!channelId)
1600
+ return null;
1601
+ try {
1602
+ const approval = ContentApprovalService.getInstance().get(approvalId);
1603
+ const fallbackText = `Content approval requested (ID: ${approvalId.slice(0, 8)}). Use the buttons to approve/reject.`;
1604
+ const blocks = [
1605
+ {
1606
+ type: 'header',
1607
+ text: { type: 'plain_text', text: '\ud83d\udccb Content Approval Required', emoji: true },
1608
+ },
1609
+ {
1610
+ type: 'section',
1611
+ fields: [
1612
+ { type: 'mrkdwn', text: `*Platform:*\n${approval?.platform ?? 'N/A'}` },
1613
+ { type: 'mrkdwn', text: `*Type:*\n${approval?.contentType ?? 'N/A'}` },
1614
+ { type: 'mrkdwn', text: `*Submitted by:*\n${approval?.submittedBy ?? 'Unknown'}` },
1615
+ { type: 'mrkdwn', text: `*ID:*\n${approvalId.slice(0, 8)}` },
1616
+ ],
1617
+ },
1618
+ {
1619
+ type: 'section',
1620
+ text: {
1621
+ type: 'mrkdwn',
1622
+ text: `*Content Preview:*\n${(approval?.content ?? '').slice(0, 300)}${(approval?.content ?? '').length > 300 ? '...' : ''}`,
1623
+ },
1624
+ },
1625
+ ];
1626
+ // Add hashtags and scheduled time if present
1627
+ const metaFields = [];
1628
+ if (approval?.hashtags && approval.hashtags.length > 0) {
1629
+ metaFields.push({ type: 'mrkdwn', text: `*Hashtags:*\n${approval.hashtags.join(' ')}` });
1630
+ }
1631
+ if (approval?.scheduledTime) {
1632
+ metaFields.push({ type: 'mrkdwn', text: `*Scheduled:*\n${approval.scheduledTime}` });
1633
+ }
1634
+ if (metaFields.length > 0) {
1635
+ blocks.push({ type: 'section', fields: metaFields });
1636
+ }
1637
+ blocks.push({ type: 'divider' });
1638
+ // Actions block with approve/reject buttons
1639
+ blocks.push({
1640
+ type: 'actions',
1641
+ block_id: `content_approval_${approvalId}`,
1642
+ elements: [
1643
+ {
1644
+ type: 'button',
1645
+ action_id: 'content_approval_approve',
1646
+ text: { type: 'plain_text', text: '\u2705 Approve', emoji: true },
1647
+ value: approvalId,
1648
+ style: 'primary',
1649
+ },
1650
+ {
1651
+ type: 'button',
1652
+ action_id: 'content_approval_reject',
1653
+ text: { type: 'plain_text', text: '\u274c Reject', emoji: true },
1654
+ value: approvalId,
1655
+ style: 'danger',
1656
+ },
1657
+ ],
1658
+ });
1659
+ const messageTs = await this.slackService.sendMessage({
1660
+ channelId,
1661
+ text: fallbackText,
1662
+ threadTs,
1663
+ blocks,
1664
+ });
1665
+ // Link the Slack message to the approval for tracking
1666
+ if (messageTs) {
1667
+ ContentApprovalService.getInstance().linkSlackMessage(approvalId, channelId, messageTs);
1668
+ }
1669
+ return messageTs ?? null;
1670
+ }
1671
+ catch (err) {
1672
+ this.logger.warn('Failed to send content approval to Slack', {
1673
+ approvalId: approvalId.slice(0, 8),
1674
+ error: err instanceof Error ? err.message : String(err),
1675
+ });
1676
+ return null;
1677
+ }
1678
+ }
1679
+ /**
1680
+ * Notify about task completion
1681
+ *
1682
+ * @param taskTitle - Title of completed task
1683
+ * @param agentName - Name of agent that completed the task
1684
+ * @param projectName - Name of the project
1685
+ */
1686
+ async notifyTaskCompleted(taskTitle, agentName, projectName) {
1687
+ await this.sendNotification({
1688
+ type: 'task_completed',
1689
+ title: 'Task Completed',
1690
+ message: `*${taskTitle}*\n\nCompleted by ${agentName} on project ${projectName}`,
1691
+ urgency: 'normal',
1692
+ timestamp: new Date().toISOString(),
1693
+ metadata: { projectId: projectName },
1694
+ });
1695
+ }
1696
+ /**
1697
+ * Notify about agent needing assistance
1698
+ *
1699
+ * @param agentName - Name of agent with question
1700
+ * @param question - The question from the agent
1701
+ * @param projectName - Name of the project
1702
+ */
1703
+ async notifyAgentQuestion(agentName, question, projectName) {
1704
+ await this.sendNotification({
1705
+ type: 'agent_question',
1706
+ title: 'Agent Needs Input',
1707
+ message: `*${agentName}* has a question:\n\n_${question}_`,
1708
+ urgency: 'high',
1709
+ timestamp: new Date().toISOString(),
1710
+ metadata: { agentId: agentName, projectId: projectName },
1711
+ });
1712
+ }
1713
+ /**
1714
+ * Notify about errors
1715
+ *
1716
+ * @param errorMessage - Error message
1717
+ * @param agentName - Optional agent name
1718
+ * @param projectName - Optional project name
1719
+ */
1720
+ async notifyError(errorMessage, agentName, projectName) {
1721
+ await this.sendNotification({
1722
+ type: 'agent_error',
1723
+ title: 'Error Occurred',
1724
+ message: errorMessage,
1725
+ urgency: 'critical',
1726
+ timestamp: new Date().toISOString(),
1727
+ metadata: { agentId: agentName, projectId: projectName },
1728
+ });
1729
+ }
1730
+ /**
1731
+ * Notify about daily summary
1732
+ *
1733
+ * @param summary - Summary content
1734
+ */
1735
+ async notifyDailySummary(summary) {
1736
+ await this.sendNotification({
1737
+ type: 'daily_summary',
1738
+ title: 'Daily Summary',
1739
+ message: summary,
1740
+ urgency: 'low',
1741
+ timestamp: new Date().toISOString(),
1742
+ });
1743
+ }
1744
+ /**
1745
+ * Resolve @mention in message text to an agent session (#177).
1746
+ *
1747
+ * Matches patterns: @assistant, @auditor, @sam, @leo, etc.
1748
+ * Looks up the agent name in team configs to find the session name.
1749
+ *
1750
+ * @param text - Message text to scan for @mentions
1751
+ * @returns Target agent info, or null if no mention found
1752
+ */
1753
+ async resolveMentionTarget(text) {
1754
+ // Match @name at the start of the message
1755
+ const mentionMatch = text.match(/^@(\w+)\s/i);
1756
+ if (!mentionMatch)
1757
+ return null;
1758
+ const mentionedName = mentionMatch[1].toLowerCase();
1759
+ // Built-in aliases
1760
+ const aliases = {
1761
+ assistant: 'crewly-orc-assistant',
1762
+ auditor: 'crewly-auditor',
1763
+ orc: 'crewly-orc',
1764
+ orchestrator: 'crewly-orc',
1765
+ };
1766
+ if (aliases[mentionedName]) {
1767
+ return { name: mentionedName, sessionName: aliases[mentionedName] };
1768
+ }
1769
+ // Look up in team configs
1770
+ try {
1771
+ const StorageService = (await import('../core/storage.service.js')).StorageService;
1772
+ const storage = StorageService.getInstance();
1773
+ const teams = await storage.getTeams();
1774
+ for (const team of teams) {
1775
+ for (const member of (team.members || [])) {
1776
+ // Match by name (case-insensitive) or session name fragment
1777
+ const memberName = member.name?.toLowerCase() || '';
1778
+ const sessionParts = (member.sessionName || '').split('-');
1779
+ const shortName = sessionParts.length >= 3 ? sessionParts[2] : '';
1780
+ if (memberName === mentionedName || shortName === mentionedName) {
1781
+ return { name: mentionedName, sessionName: member.sessionName };
1782
+ }
1783
+ }
1784
+ }
1785
+ }
1786
+ catch (err) {
1787
+ this.logger.warn('Failed to look up mention target', {
1788
+ mention: mentionedName,
1789
+ error: err instanceof Error ? err.message : String(err),
1790
+ });
1791
+ }
1792
+ return null;
1793
+ }
1794
+ /**
1795
+ * Send a message to a specific agent session via terminal deliver (#177).
1796
+ *
1797
+ * @param sessionName - Target agent session
1798
+ * @param message - Message to send
1799
+ * @param context - Slack context for response routing
1800
+ * @returns OrcResponse envelope — `fromOrcReply` is `true` ONLY when the
1801
+ * reply came from the agent's `slackResolve` callback (a real reply
1802
+ * via the reply-slack skill). Timeout / direct-delivery / error
1803
+ * placeholders return `fromOrcReply: false` so callers can gate the
1804
+ * SLA cascade. Issue #394.
1805
+ */
1806
+ async sendToAgent(sessionName, message, context) {
1807
+ try {
1808
+ // Enrich with Slack context for reply routing
1809
+ let enrichedMessage = message;
1810
+ if (context) {
1811
+ enrichedMessage = `[SLACK_CONTEXT:channelId=${context.channelId},threadTs=${context.threadTs || ''}]\n${message}`;
1812
+ }
1813
+ // Use message queue for agents that support it, or deliver directly
1814
+ if (this.messageQueueService) {
1815
+ const chatResult = {
1816
+ conversation: {
1817
+ id: this.persistSlackInbound({
1818
+ content: enrichedMessage,
1819
+ conversationId: context?.conversationId,
1820
+ agentSession: sessionName,
1821
+ channelId: context?.channelId,
1822
+ threadTs: context?.threadTs,
1823
+ userId: context?.userId,
1824
+ }).conversationId,
1825
+ },
1826
+ };
1827
+ return new Promise((resolve) => {
1828
+ let resolved = false;
1829
+ const timeoutId = setTimeout(() => {
1830
+ if (!resolved) {
1831
+ resolved = true;
1832
+ // Timeout placeholder — explicitly NOT a real reply.
1833
+ resolve({
1834
+ response: 'Agent is processing your message. Check back shortly.',
1835
+ fromOrcReply: false,
1836
+ });
1837
+ }
1838
+ }, this.config.responseTimeoutMs);
1839
+ this.messageQueueService.enqueue({
1840
+ content: enrichedMessage,
1841
+ conversationId: chatResult.conversation.id,
1842
+ source: 'slack',
1843
+ targetSession: sessionName,
1844
+ sourceMetadata: {
1845
+ slackResolve: (resp) => {
1846
+ if (!resolved) {
1847
+ resolved = true;
1848
+ clearTimeout(timeoutId);
1849
+ // Real agent reply path. Empty `resp` is the
1850
+ // QueueProcessor fire-and-forget delivery ack — treat
1851
+ // it as a non-reply too (mirrors the orchestrator
1852
+ // path's empty-string gate in sendToOrchestrator).
1853
+ resolve({ response: resp, fromOrcReply: resp.length > 0 });
1854
+ }
1855
+ },
1856
+ channelId: context?.channelId,
1857
+ threadTs: context?.threadTs,
1858
+ },
1859
+ });
1860
+ });
1861
+ }
1862
+ // Fallback: direct terminal delivery — the agent acknowledges the
1863
+ // write, but the actual reply hasn't been generated yet. Return a
1864
+ // placeholder with fromOrcReply=false so the SLA cascade does NOT
1865
+ // close on this.
1866
+ const { default: fetch } = await import('node-fetch').catch(() => ({ default: globalThis.fetch }));
1867
+ const apiUrl = process.env.CREWLY_API_URL || 'http://localhost:8787';
1868
+ await fetch(`${apiUrl}/api/terminal/${sessionName}/deliver`, {
1869
+ method: 'POST',
1870
+ headers: { 'Content-Type': 'application/json' },
1871
+ body: JSON.stringify({ message: enrichedMessage, force: true }),
1872
+ });
1873
+ return {
1874
+ response: 'Message delivered to agent. Response will arrive shortly.',
1875
+ fromOrcReply: false,
1876
+ };
1877
+ }
1878
+ catch (err) {
1879
+ this.logger.error('Failed to send to agent', {
1880
+ session: sessionName,
1881
+ error: err instanceof Error ? err.message : String(err),
1882
+ });
1883
+ return {
1884
+ response: `Failed to reach agent. Error: ${err instanceof Error ? err.message : String(err)}`,
1885
+ fromOrcReply: false,
1886
+ };
1887
+ }
1888
+ }
1889
+ /**
1890
+ * Persist a Slack inbound user message to chat-v2 and return the
1891
+ * `(conversationId, messageId)` pair callers thread downstream
1892
+ * into `MessageQueueService.enqueue` and `ThreadStatusQueueService.trackInbound`.
1893
+ *
1894
+ * Phase 6c of unified-chat-message-store spec: replaces the
1895
+ * legacy `chatService.sendMessage` call sites on this bridge.
1896
+ * Synthesizes a stable conversationId from Slack channel + thread
1897
+ * ts when the caller didn't supply one, so re-enqueue paths
1898
+ * (offline replay, recovery) reuse the same channel.
1899
+ *
1900
+ * @param args - Persistence inputs (content + slack context + recipient agent)
1901
+ * @returns The chat-v2 channelId and the freshly persisted messageId
1902
+ */
1903
+ persistSlackInbound(args) {
1904
+ const cid = args.conversationId ??
1905
+ synthesizeSlackConversationId(args.channelId ?? 'unknown', args.threadTs ?? String(Date.now()));
1906
+ const channel = this.chatV2.ensureChannelForLegacyConversation({
1907
+ conversationId: cid,
1908
+ agentSession: args.agentSession,
1909
+ // Name the thread by its first message so the consolidated chat shows a
1910
+ // readable title (e.g. "Slack: ship the v2 launch…") instead of N
1911
+ // identical synthesized ids. ensure… only sets the name on create, so
1912
+ // this stamps the thread's opening message. Falls back to the id.
1913
+ name: deriveSlackThreadName(args.content),
1914
+ });
1915
+ const { message } = this.chatV2.recordTurn({
1916
+ channelId: channel.id,
1917
+ senderType: 'user',
1918
+ senderId: args.userId ?? 'slack-user',
1919
+ content: args.content,
1920
+ metadata: {
1921
+ source: 'slack',
1922
+ slackChannelId: args.channelId,
1923
+ slackThreadTs: args.threadTs,
1924
+ },
1925
+ });
1926
+ return { conversationId: channel.id, messageId: message.id };
1927
+ }
1928
+ }
1929
+ /**
1930
+ * Get bridge singleton
1931
+ *
1932
+ * @returns SlackOrchestratorBridge instance
1933
+ */
1934
+ export function getSlackOrchestratorBridge() {
1935
+ if (!bridgeInstance) {
1936
+ bridgeInstance = new SlackOrchestratorBridge();
1937
+ }
1938
+ return bridgeInstance;
1939
+ }
1940
+ /**
1941
+ * Reset bridge (for testing)
1942
+ */
1943
+ export function resetSlackOrchestratorBridge() {
1944
+ bridgeInstance = null;
1945
+ }
1946
+ //# sourceMappingURL=slack-orchestrator-bridge.js.map