@overlordai/server 1.0.53 → 1.0.55

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 (533) hide show
  1. package/database/migrations/001-init-schema.sql +73 -9
  2. package/dist/adapters/adapter.interface.d.ts +1 -4
  3. package/dist/adapters/adapter.interface.d.ts.map +1 -1
  4. package/dist/adapters/adapter.interface.js.map +1 -1
  5. package/dist/adapters/adapter.module.d.ts.map +1 -1
  6. package/dist/adapters/adapter.module.js +8 -7
  7. package/dist/adapters/adapter.module.js.map +1 -1
  8. package/dist/adapters/lark/lark-card.builder.d.ts +1 -25
  9. package/dist/adapters/lark/lark-card.builder.d.ts.map +1 -1
  10. package/dist/adapters/lark/lark-card.builder.js +6 -110
  11. package/dist/adapters/lark/lark-card.builder.js.map +1 -1
  12. package/dist/adapters/lark/lark-message.parser.d.ts +4 -4
  13. package/dist/adapters/lark/lark-message.parser.d.ts.map +1 -1
  14. package/dist/adapters/lark/lark-message.parser.js +20 -13
  15. package/dist/adapters/lark/lark-message.parser.js.map +1 -1
  16. package/dist/adapters/lark/lark-signature.d.ts.map +1 -1
  17. package/dist/adapters/lark/lark-signature.js +6 -0
  18. package/dist/adapters/lark/lark-signature.js.map +1 -1
  19. package/dist/adapters/lark/lark.adapter.d.ts +14 -9
  20. package/dist/adapters/lark/lark.adapter.d.ts.map +1 -1
  21. package/dist/adapters/lark/lark.adapter.js +99 -177
  22. package/dist/adapters/lark/lark.adapter.js.map +1 -1
  23. package/dist/adapters/lark/lark.controller.d.ts +10 -1
  24. package/dist/adapters/lark/lark.controller.d.ts.map +1 -1
  25. package/dist/adapters/lark/lark.controller.js +48 -14
  26. package/dist/adapters/lark/lark.controller.js.map +1 -1
  27. package/dist/adapters/slack/slack-block.builder.d.ts +8 -0
  28. package/dist/adapters/slack/slack-block.builder.d.ts.map +1 -0
  29. package/dist/adapters/slack/slack-block.builder.js +117 -0
  30. package/dist/adapters/slack/slack-block.builder.js.map +1 -0
  31. package/dist/adapters/slack/slack-message.parser.d.ts +15 -0
  32. package/dist/adapters/slack/slack-message.parser.d.ts.map +1 -0
  33. package/dist/adapters/slack/slack-message.parser.js +158 -0
  34. package/dist/adapters/slack/slack-message.parser.js.map +1 -0
  35. package/dist/adapters/slack/slack-signature.d.ts +7 -0
  36. package/dist/adapters/slack/slack-signature.d.ts.map +1 -0
  37. package/dist/adapters/slack/slack-signature.js +59 -0
  38. package/dist/adapters/slack/slack-signature.js.map +1 -0
  39. package/dist/adapters/slack/slack.adapter.d.ts +67 -13
  40. package/dist/adapters/slack/slack.adapter.d.ts.map +1 -1
  41. package/dist/adapters/slack/slack.adapter.js +468 -19
  42. package/dist/adapters/slack/slack.adapter.js.map +1 -1
  43. package/dist/adapters/slack/slack.controller.d.ts +20 -0
  44. package/dist/adapters/slack/slack.controller.d.ts.map +1 -0
  45. package/dist/adapters/slack/slack.controller.js +257 -0
  46. package/dist/adapters/slack/slack.controller.js.map +1 -0
  47. package/dist/app.module.d.ts.map +1 -1
  48. package/dist/app.module.js +4 -0
  49. package/dist/app.module.js.map +1 -1
  50. package/dist/auth/auth.controller.d.ts.map +1 -1
  51. package/dist/auth/auth.controller.js +1 -0
  52. package/dist/auth/auth.controller.js.map +1 -1
  53. package/dist/auth/auth.module.d.ts.map +1 -1
  54. package/dist/auth/auth.module.js +4 -5
  55. package/dist/auth/auth.module.js.map +1 -1
  56. package/dist/auth/auth.service.d.ts +9 -2
  57. package/dist/auth/auth.service.d.ts.map +1 -1
  58. package/dist/auth/auth.service.js +50 -79
  59. package/dist/auth/auth.service.js.map +1 -1
  60. package/dist/auth/authenticated-request.d.ts +10 -0
  61. package/dist/auth/authenticated-request.d.ts.map +1 -0
  62. package/dist/auth/authenticated-request.js +3 -0
  63. package/dist/auth/authenticated-request.js.map +1 -0
  64. package/dist/auth/extract-user.middleware.d.ts.map +1 -1
  65. package/dist/auth/extract-user.middleware.js +2 -1
  66. package/dist/auth/extract-user.middleware.js.map +1 -1
  67. package/dist/auth/guards/jwt-auth.guard.d.ts.map +1 -1
  68. package/dist/auth/guards/jwt-auth.guard.js +5 -2
  69. package/dist/auth/guards/jwt-auth.guard.js.map +1 -1
  70. package/dist/auth/guards/project-role.guard.d.ts.map +1 -1
  71. package/dist/auth/guards/project-role.guard.js +6 -8
  72. package/dist/auth/guards/project-role.guard.js.map +1 -1
  73. package/dist/auth/jwt.strategy.d.ts +6 -3
  74. package/dist/auth/jwt.strategy.d.ts.map +1 -1
  75. package/dist/auth/jwt.strategy.js +15 -5
  76. package/dist/auth/jwt.strategy.js.map +1 -1
  77. package/dist/common/command-parser.d.ts +29 -0
  78. package/dist/common/command-parser.d.ts.map +1 -0
  79. package/dist/common/command-parser.js +133 -0
  80. package/dist/common/command-parser.js.map +1 -0
  81. package/dist/common/config.d.ts +17 -0
  82. package/dist/common/config.d.ts.map +1 -0
  83. package/dist/common/config.js +47 -0
  84. package/dist/common/config.js.map +1 -0
  85. package/dist/common/crypto.service.d.ts +4 -1
  86. package/dist/common/crypto.service.d.ts.map +1 -1
  87. package/dist/common/crypto.service.js +14 -7
  88. package/dist/common/crypto.service.js.map +1 -1
  89. package/dist/common/error-filter.d.ts +1 -0
  90. package/dist/common/error-filter.d.ts.map +1 -1
  91. package/dist/common/error-filter.js +6 -2
  92. package/dist/common/error-filter.js.map +1 -1
  93. package/dist/common/git-utils.d.ts +9 -0
  94. package/dist/common/git-utils.d.ts.map +1 -0
  95. package/dist/common/git-utils.js +41 -0
  96. package/dist/common/git-utils.js.map +1 -0
  97. package/dist/common/health.controller.d.ts.map +1 -1
  98. package/dist/common/health.controller.js +3 -5
  99. package/dist/common/health.controller.js.map +1 -1
  100. package/dist/common/machine-utils.d.ts +32 -0
  101. package/dist/common/machine-utils.d.ts.map +1 -0
  102. package/dist/common/machine-utils.js +12 -0
  103. package/dist/common/machine-utils.js.map +1 -0
  104. package/dist/common/pagination.d.ts +12 -5
  105. package/dist/common/pagination.d.ts.map +1 -1
  106. package/dist/common/pagination.js +27 -17
  107. package/dist/common/pagination.js.map +1 -1
  108. package/dist/common/project-validation.d.ts +7 -0
  109. package/dist/common/project-validation.d.ts.map +1 -0
  110. package/dist/common/project-validation.js +86 -0
  111. package/dist/common/project-validation.js.map +1 -0
  112. package/dist/common/rate-limit.guard.d.ts +4 -3
  113. package/dist/common/rate-limit.guard.d.ts.map +1 -1
  114. package/dist/common/rate-limit.guard.js +14 -5
  115. package/dist/common/rate-limit.guard.js.map +1 -1
  116. package/dist/common/sql-utils.d.ts +6 -0
  117. package/dist/common/sql-utils.d.ts.map +1 -0
  118. package/dist/common/sql-utils.js +11 -0
  119. package/dist/common/sql-utils.js.map +1 -0
  120. package/dist/common/string-utils.d.ts +6 -0
  121. package/dist/common/string-utils.d.ts.map +1 -0
  122. package/dist/common/string-utils.js +15 -0
  123. package/dist/common/string-utils.js.map +1 -0
  124. package/dist/common/worker-utils.d.ts +31 -0
  125. package/dist/common/worker-utils.d.ts.map +1 -0
  126. package/dist/common/worker-utils.js +12 -0
  127. package/dist/common/worker-utils.js.map +1 -0
  128. package/dist/database/base.repository.d.ts +56 -0
  129. package/dist/database/base.repository.d.ts.map +1 -0
  130. package/dist/database/base.repository.js +82 -0
  131. package/dist/database/base.repository.js.map +1 -0
  132. package/dist/database/database.service.d.ts.map +1 -1
  133. package/dist/database/database.service.js +9 -1
  134. package/dist/database/database.service.js.map +1 -1
  135. package/dist/database/migration-runner.d.ts.map +1 -1
  136. package/dist/database/migration-runner.js +2 -1
  137. package/dist/database/migration-runner.js.map +1 -1
  138. package/dist/database/repositories/audit-log.repository.d.ts.map +1 -1
  139. package/dist/database/repositories/audit-log.repository.js +16 -18
  140. package/dist/database/repositories/audit-log.repository.js.map +1 -1
  141. package/dist/database/repositories/bot.repository.d.ts +18 -32
  142. package/dist/database/repositories/bot.repository.d.ts.map +1 -1
  143. package/dist/database/repositories/bot.repository.js +42 -21
  144. package/dist/database/repositories/bot.repository.js.map +1 -1
  145. package/dist/database/repositories/developer-token.repository.d.ts +7 -17
  146. package/dist/database/repositories/developer-token.repository.d.ts.map +1 -1
  147. package/dist/database/repositories/developer-token.repository.js +24 -15
  148. package/dist/database/repositories/developer-token.repository.js.map +1 -1
  149. package/dist/database/repositories/developer.repository.d.ts +5 -1
  150. package/dist/database/repositories/developer.repository.d.ts.map +1 -1
  151. package/dist/database/repositories/developer.repository.js +60 -49
  152. package/dist/database/repositories/developer.repository.js.map +1 -1
  153. package/dist/database/repositories/machine.repository.d.ts.map +1 -1
  154. package/dist/database/repositories/machine.repository.js +2 -7
  155. package/dist/database/repositories/machine.repository.js.map +1 -1
  156. package/dist/database/repositories/notification.repository.d.ts +1 -0
  157. package/dist/database/repositories/notification.repository.d.ts.map +1 -1
  158. package/dist/database/repositories/notification.repository.js +25 -20
  159. package/dist/database/repositories/notification.repository.js.map +1 -1
  160. package/dist/database/repositories/project-member.repository.d.ts +7 -16
  161. package/dist/database/repositories/project-member.repository.d.ts.map +1 -1
  162. package/dist/database/repositories/project-member.repository.js +34 -24
  163. package/dist/database/repositories/project-member.repository.js.map +1 -1
  164. package/dist/database/repositories/project.repository.d.ts +2 -1
  165. package/dist/database/repositories/project.repository.d.ts.map +1 -1
  166. package/dist/database/repositories/project.repository.js +70 -71
  167. package/dist/database/repositories/project.repository.js.map +1 -1
  168. package/dist/database/repositories/session.repository.d.ts.map +1 -1
  169. package/dist/database/repositories/session.repository.js +22 -25
  170. package/dist/database/repositories/session.repository.js.map +1 -1
  171. package/dist/database/repositories/task.repository.d.ts +31 -7
  172. package/dist/database/repositories/task.repository.d.ts.map +1 -1
  173. package/dist/database/repositories/task.repository.js +134 -86
  174. package/dist/database/repositories/task.repository.js.map +1 -1
  175. package/dist/database/repositories/worker-token.repository.d.ts.map +1 -1
  176. package/dist/database/repositories/worker-token.repository.js +18 -16
  177. package/dist/database/repositories/worker-token.repository.js.map +1 -1
  178. package/dist/database/repositories/worker.repository.d.ts +50 -0
  179. package/dist/database/repositories/worker.repository.d.ts.map +1 -0
  180. package/dist/database/repositories/worker.repository.js +215 -0
  181. package/dist/database/repositories/worker.repository.js.map +1 -0
  182. package/dist/database/repositories/workspace.repository.d.ts +3 -2
  183. package/dist/database/repositories/workspace.repository.d.ts.map +1 -1
  184. package/dist/database/repositories/workspace.repository.js +29 -21
  185. package/dist/database/repositories/workspace.repository.js.map +1 -1
  186. package/dist/database/repository.module.d.ts +3 -0
  187. package/dist/database/repository.module.d.ts.map +1 -0
  188. package/dist/database/repository.module.js +45 -0
  189. package/dist/database/repository.module.js.map +1 -0
  190. package/dist/dispatcher/capability.service.d.ts +19 -14
  191. package/dist/dispatcher/capability.service.d.ts.map +1 -1
  192. package/dist/dispatcher/capability.service.js +77 -69
  193. package/dist/dispatcher/capability.service.js.map +1 -1
  194. package/dist/dispatcher/cleanup.service.d.ts +1 -1
  195. package/dist/dispatcher/cleanup.service.d.ts.map +1 -1
  196. package/dist/dispatcher/cleanup.service.js +13 -13
  197. package/dist/dispatcher/cleanup.service.js.map +1 -1
  198. package/dist/dispatcher/dedup.service.d.ts +17 -3
  199. package/dist/dispatcher/dedup.service.d.ts.map +1 -1
  200. package/dist/dispatcher/dedup.service.js +76 -82
  201. package/dist/dispatcher/dedup.service.js.map +1 -1
  202. package/dist/dispatcher/dispatcher.module.d.ts.map +1 -1
  203. package/dist/dispatcher/dispatcher.module.js +11 -18
  204. package/dist/dispatcher/dispatcher.module.js.map +1 -1
  205. package/dist/dispatcher/dispatcher.service.d.ts +14 -116
  206. package/dist/dispatcher/dispatcher.service.d.ts.map +1 -1
  207. package/dist/dispatcher/dispatcher.service.js +62 -940
  208. package/dist/dispatcher/dispatcher.service.js.map +1 -1
  209. package/dist/dispatcher/dispatcher.types.d.ts +33 -0
  210. package/dist/dispatcher/dispatcher.types.d.ts.map +1 -0
  211. package/dist/dispatcher/dispatcher.types.js +3 -0
  212. package/dist/dispatcher/dispatcher.types.js.map +1 -0
  213. package/dist/dispatcher/heartbeat.service.d.ts +17 -10
  214. package/dist/dispatcher/heartbeat.service.d.ts.map +1 -1
  215. package/dist/dispatcher/heartbeat.service.js +47 -51
  216. package/dist/dispatcher/heartbeat.service.js.map +1 -1
  217. package/dist/dispatcher/pty-relay.service.d.ts.map +1 -1
  218. package/dist/dispatcher/pty-relay.service.js +7 -15
  219. package/dist/dispatcher/pty-relay.service.js.map +1 -1
  220. package/dist/dispatcher/reconciler.d.ts +18 -8
  221. package/dist/dispatcher/reconciler.d.ts.map +1 -1
  222. package/dist/dispatcher/reconciler.js +219 -130
  223. package/dist/dispatcher/reconciler.js.map +1 -1
  224. package/dist/dispatcher/scheduler.service.d.ts +15 -9
  225. package/dist/dispatcher/scheduler.service.d.ts.map +1 -1
  226. package/dist/dispatcher/scheduler.service.js +95 -53
  227. package/dist/dispatcher/scheduler.service.js.map +1 -1
  228. package/dist/dispatcher/state-machine.d.ts.map +1 -1
  229. package/dist/dispatcher/state-machine.js +1 -5
  230. package/dist/dispatcher/state-machine.js.map +1 -1
  231. package/dist/dispatcher/task-creation.service.d.ts +30 -0
  232. package/dist/dispatcher/task-creation.service.d.ts.map +1 -0
  233. package/dist/dispatcher/task-creation.service.js +242 -0
  234. package/dist/dispatcher/task-creation.service.js.map +1 -0
  235. package/dist/dispatcher/task-lifecycle.service.d.ts +63 -0
  236. package/dist/dispatcher/task-lifecycle.service.d.ts.map +1 -0
  237. package/dist/dispatcher/task-lifecycle.service.js +584 -0
  238. package/dist/dispatcher/task-lifecycle.service.js.map +1 -0
  239. package/dist/dispatcher/task-log-batcher.d.ts.map +1 -1
  240. package/dist/dispatcher/task-log-batcher.js +4 -11
  241. package/dist/dispatcher/task-log-batcher.js.map +1 -1
  242. package/dist/dispatcher/worker-auth.service.d.ts +29 -0
  243. package/dist/dispatcher/worker-auth.service.d.ts.map +1 -0
  244. package/dist/dispatcher/worker-auth.service.js +296 -0
  245. package/dist/dispatcher/worker-auth.service.js.map +1 -0
  246. package/dist/dispatcher/worker-connection.manager.d.ts +15 -15
  247. package/dist/dispatcher/worker-connection.manager.d.ts.map +1 -1
  248. package/dist/dispatcher/worker-connection.manager.js +35 -43
  249. package/dist/dispatcher/worker-connection.manager.js.map +1 -1
  250. package/dist/dispatcher/worker-selector.d.ts +18 -0
  251. package/dist/dispatcher/worker-selector.d.ts.map +1 -0
  252. package/dist/dispatcher/worker-selector.js +150 -0
  253. package/dist/dispatcher/worker-selector.js.map +1 -0
  254. package/dist/events/event-types.d.ts +31 -0
  255. package/dist/events/event-types.d.ts.map +1 -0
  256. package/dist/events/event-types.js +16 -0
  257. package/dist/events/event-types.js.map +1 -0
  258. package/dist/events/events.module.d.ts +7 -0
  259. package/dist/events/events.module.d.ts.map +1 -0
  260. package/dist/events/events.module.js +26 -0
  261. package/dist/events/events.module.js.map +1 -0
  262. package/dist/main.js +22 -0
  263. package/dist/main.js.map +1 -1
  264. package/dist/notifier/debouncer.d.ts +1 -1
  265. package/dist/notifier/debouncer.d.ts.map +1 -1
  266. package/dist/notifier/debouncer.js +2 -1
  267. package/dist/notifier/debouncer.js.map +1 -1
  268. package/dist/notifier/notification-consumer.d.ts +1 -1
  269. package/dist/notifier/notification-consumer.d.ts.map +1 -1
  270. package/dist/notifier/notification-consumer.js +5 -5
  271. package/dist/notifier/notification-consumer.js.map +1 -1
  272. package/dist/notifier/notifier.module.d.ts.map +1 -1
  273. package/dist/notifier/notifier.module.js +0 -6
  274. package/dist/notifier/notifier.module.js.map +1 -1
  275. package/dist/notifier/notifier.service.d.ts +1 -1
  276. package/dist/notifier/notifier.service.d.ts.map +1 -1
  277. package/dist/notifier/notifier.service.js +7 -9
  278. package/dist/notifier/notifier.service.js.map +1 -1
  279. package/dist/notifier/template.service.d.ts +1 -1
  280. package/dist/notifier/template.service.d.ts.map +1 -1
  281. package/dist/notifier/template.service.js +6 -10
  282. package/dist/notifier/template.service.js.map +1 -1
  283. package/dist/redis/redis.service.d.ts.map +1 -1
  284. package/dist/redis/redis.service.js +2 -2
  285. package/dist/redis/redis.service.js.map +1 -1
  286. package/dist/web/admin/admin-audit.controller.d.ts.map +1 -1
  287. package/dist/web/admin/admin-audit.controller.js +2 -1
  288. package/dist/web/admin/admin-audit.controller.js.map +1 -1
  289. package/dist/web/admin/admin-bot.controller.d.ts +11 -48
  290. package/dist/web/admin/admin-bot.controller.d.ts.map +1 -1
  291. package/dist/web/admin/admin-bot.controller.js +50 -18
  292. package/dist/web/admin/admin-bot.controller.js.map +1 -1
  293. package/dist/web/admin/admin-developer.controller.d.ts +14 -27
  294. package/dist/web/admin/admin-developer.controller.d.ts.map +1 -1
  295. package/dist/web/admin/admin-developer.controller.js +62 -28
  296. package/dist/web/admin/admin-developer.controller.js.map +1 -1
  297. package/dist/web/admin/admin-machine.controller.d.ts +1 -8
  298. package/dist/web/admin/admin-machine.controller.d.ts.map +1 -1
  299. package/dist/web/admin/admin-machine.controller.js +3 -6
  300. package/dist/web/admin/admin-machine.controller.js.map +1 -1
  301. package/dist/web/admin/admin-project.controller.d.ts +9 -30
  302. package/dist/web/admin/admin-project.controller.d.ts.map +1 -1
  303. package/dist/web/admin/admin-project.controller.js +15 -60
  304. package/dist/web/admin/admin-project.controller.js.map +1 -1
  305. package/dist/web/admin/admin-settings.controller.d.ts +7 -10
  306. package/dist/web/admin/admin-settings.controller.d.ts.map +1 -1
  307. package/dist/web/admin/admin-settings.controller.js +14 -6
  308. package/dist/web/admin/admin-settings.controller.js.map +1 -1
  309. package/dist/web/admin/admin-token.controller.d.ts +6 -13
  310. package/dist/web/admin/admin-token.controller.d.ts.map +1 -1
  311. package/dist/web/admin/admin-token.controller.js +15 -27
  312. package/dist/web/admin/admin-token.controller.js.map +1 -1
  313. package/dist/web/admin/admin-worker.controller.d.ts +26 -0
  314. package/dist/web/admin/admin-worker.controller.d.ts.map +1 -0
  315. package/dist/web/admin/admin-worker.controller.js +184 -0
  316. package/dist/web/admin/admin-worker.controller.js.map +1 -0
  317. package/dist/web/dashboard.controller.d.ts +6 -12
  318. package/dist/web/dashboard.controller.d.ts.map +1 -1
  319. package/dist/web/dashboard.controller.js +30 -18
  320. package/dist/web/dashboard.controller.js.map +1 -1
  321. package/dist/web/dashboard.service.d.ts +21 -12
  322. package/dist/web/dashboard.service.d.ts.map +1 -1
  323. package/dist/web/dashboard.service.js +169 -119
  324. package/dist/web/dashboard.service.js.map +1 -1
  325. package/dist/web/event.gateway.d.ts +32 -0
  326. package/dist/web/event.gateway.d.ts.map +1 -0
  327. package/dist/web/event.gateway.js +168 -0
  328. package/dist/web/event.gateway.js.map +1 -0
  329. package/dist/web/frame-handlers/frame-handler.interface.d.ts +24 -0
  330. package/dist/web/frame-handlers/frame-handler.interface.d.ts.map +1 -0
  331. package/dist/web/frame-handlers/frame-handler.interface.js +3 -0
  332. package/dist/web/frame-handlers/frame-handler.interface.js.map +1 -0
  333. package/dist/web/frame-handlers/frame-handler.registry.d.ts +16 -0
  334. package/dist/web/frame-handlers/frame-handler.registry.d.ts.map +1 -0
  335. package/dist/web/frame-handlers/frame-handler.registry.js +39 -0
  336. package/dist/web/frame-handlers/frame-handler.registry.js.map +1 -0
  337. package/dist/web/frame-handlers/heartbeat.handler.d.ts +13 -0
  338. package/dist/web/frame-handlers/heartbeat.handler.d.ts.map +1 -0
  339. package/dist/web/frame-handlers/heartbeat.handler.js +35 -0
  340. package/dist/web/frame-handlers/heartbeat.handler.js.map +1 -0
  341. package/dist/web/frame-handlers/index.d.ts +7 -0
  342. package/dist/web/frame-handlers/index.d.ts.map +1 -0
  343. package/dist/web/frame-handlers/index.js +14 -0
  344. package/dist/web/frame-handlers/index.js.map +1 -0
  345. package/dist/web/frame-handlers/progress.handler.d.ts +25 -0
  346. package/dist/web/frame-handlers/progress.handler.d.ts.map +1 -0
  347. package/dist/web/frame-handlers/progress.handler.js +69 -0
  348. package/dist/web/frame-handlers/progress.handler.js.map +1 -0
  349. package/dist/web/frame-handlers/stage-confirm.handler.d.ts +15 -0
  350. package/dist/web/frame-handlers/stage-confirm.handler.d.ts.map +1 -0
  351. package/dist/web/frame-handlers/stage-confirm.handler.js +39 -0
  352. package/dist/web/frame-handlers/stage-confirm.handler.js.map +1 -0
  353. package/dist/web/frame-handlers/tunnel.handler.d.ts +10 -0
  354. package/dist/web/frame-handlers/tunnel.handler.d.ts.map +1 -0
  355. package/dist/web/frame-handlers/tunnel.handler.js +31 -0
  356. package/dist/web/frame-handlers/tunnel.handler.js.map +1 -0
  357. package/dist/web/interaction.service.d.ts +0 -4
  358. package/dist/web/interaction.service.d.ts.map +1 -1
  359. package/dist/web/interaction.service.js +0 -10
  360. package/dist/web/interaction.service.js.map +1 -1
  361. package/dist/web/machine.controller.d.ts +1 -8
  362. package/dist/web/machine.controller.d.ts.map +1 -1
  363. package/dist/web/machine.controller.js +6 -9
  364. package/dist/web/machine.controller.js.map +1 -1
  365. package/dist/web/notification.controller.d.ts +1 -8
  366. package/dist/web/notification.controller.d.ts.map +1 -1
  367. package/dist/web/notification.controller.js +3 -2
  368. package/dist/web/notification.controller.js.map +1 -1
  369. package/dist/web/profile.controller.d.ts +19 -10
  370. package/dist/web/profile.controller.d.ts.map +1 -1
  371. package/dist/web/profile.controller.js +100 -13
  372. package/dist/web/profile.controller.js.map +1 -1
  373. package/dist/web/project-member.service.d.ts +16 -0
  374. package/dist/web/project-member.service.d.ts.map +1 -0
  375. package/dist/web/project-member.service.js +90 -0
  376. package/dist/web/project-member.service.js.map +1 -0
  377. package/dist/web/project.controller.d.ts +43 -26
  378. package/dist/web/project.controller.d.ts.map +1 -1
  379. package/dist/web/project.controller.js +73 -46
  380. package/dist/web/project.controller.js.map +1 -1
  381. package/dist/web/pty.gateway.d.ts +9 -3
  382. package/dist/web/pty.gateway.d.ts.map +1 -1
  383. package/dist/web/pty.gateway.js +46 -18
  384. package/dist/web/pty.gateway.js.map +1 -1
  385. package/dist/web/search.service.d.ts +9 -2
  386. package/dist/web/search.service.d.ts.map +1 -1
  387. package/dist/web/search.service.js +53 -26
  388. package/dist/web/search.service.js.map +1 -1
  389. package/dist/web/task.controller.d.ts +15 -24
  390. package/dist/web/task.controller.d.ts.map +1 -1
  391. package/dist/web/task.controller.js +70 -53
  392. package/dist/web/task.controller.js.map +1 -1
  393. package/dist/web/tunnel.service.d.ts +74 -0
  394. package/dist/web/tunnel.service.d.ts.map +1 -0
  395. package/dist/web/tunnel.service.js +250 -0
  396. package/dist/web/tunnel.service.js.map +1 -0
  397. package/dist/web/web-event.service.d.ts +25 -0
  398. package/dist/web/web-event.service.d.ts.map +1 -0
  399. package/dist/web/web-event.service.js +116 -0
  400. package/dist/web/web-event.service.js.map +1 -0
  401. package/dist/web/web.module.d.ts.map +1 -1
  402. package/dist/web/web.module.js +13 -28
  403. package/dist/web/web.module.js.map +1 -1
  404. package/dist/web/worker-channel.gateway.d.ts +10 -18
  405. package/dist/web/worker-channel.gateway.d.ts.map +1 -1
  406. package/dist/web/worker-channel.gateway.js +70 -144
  407. package/dist/web/worker-channel.gateway.js.map +1 -1
  408. package/dist/web/worker-web.controller.d.ts +15 -0
  409. package/dist/web/worker-web.controller.d.ts.map +1 -0
  410. package/dist/web/worker-web.controller.js +143 -0
  411. package/dist/web/worker-web.controller.js.map +1 -0
  412. package/dist/web/worker.controller.d.ts +3 -3
  413. package/dist/web/worker.controller.d.ts.map +1 -1
  414. package/dist/web/worker.controller.js +8 -8
  415. package/dist/web/worker.controller.js.map +1 -1
  416. package/dist/web/workspace.controller.d.ts +8 -33
  417. package/dist/web/workspace.controller.d.ts.map +1 -1
  418. package/dist/web/workspace.controller.js +93 -205
  419. package/dist/web/workspace.controller.js.map +1 -1
  420. package/package.json +10 -2
  421. package/public/apple-touch-icon-120x120.png +0 -0
  422. package/public/apple-touch-icon-152x152.png +0 -0
  423. package/public/apple-touch-icon-180x180.png +0 -0
  424. package/public/assets/AccessTokensPage-DPQB2fbi.js +1 -0
  425. package/public/assets/AdminPage-BqVelYNu.js +1 -0
  426. package/public/assets/ApiReferencePage-CiGvbLxL.js +1 -0
  427. package/public/assets/AuditLogPage-DSo4jVYm.js +6 -0
  428. package/public/assets/BindPlatformPage-CTqzpOmt.js +1 -0
  429. package/public/assets/BotManage-CIR0rrK7.js +6 -0
  430. package/public/assets/CliReferencePage-C8GmlwUz.js +14 -0
  431. package/public/assets/DeveloperManage-r6y2AoB4.js +16 -0
  432. package/public/assets/EditProjectPage-7WCsNltj.js +2 -0
  433. package/public/assets/{EmptyState-CvmhFgWJ.js → EmptyState-D3foEiul.js} +1 -1
  434. package/public/assets/HomePage-D4yv4orb.js +1 -0
  435. package/public/assets/InfoRow-DhdTYoY9.js +1 -0
  436. package/public/assets/LandingPage-CqS0E2eC.js +43 -0
  437. package/public/assets/LoginPage-DDXkdcz_.js +1 -0
  438. package/public/assets/MetricBar-DMMHfS0A.js +1 -0
  439. package/public/assets/{NotFoundPage-BuiAS4g4.js → NotFoundPage-D5x5BrlX.js} +1 -1
  440. package/public/assets/OnboardingGuide-D8RyPcEd.js +1 -0
  441. package/public/assets/PipelineEditorPage-y2-Q8ofQ.js +3 -0
  442. package/public/assets/ProfilePage-DN7usHOi.js +1 -0
  443. package/public/assets/ProjectDetailPage-DJexg49z.js +7 -0
  444. package/public/assets/ProjectListPage-Bz7I2D0H.js +6 -0
  445. package/public/assets/QuickAuth-Dr0Q50ld.js +1 -0
  446. package/public/assets/{RemoveMemberConfirmDialog-DS9z6jQT.js → RemoveMemberConfirmDialog-BCrue0AP.js} +2 -2
  447. package/public/assets/Select-BnV8yZlD.js +6 -0
  448. package/public/assets/SettingsPage-HaUCcsgl.js +6 -0
  449. package/public/assets/{Skeleton-CcVqz28_.js → Skeleton-DUgWc2LJ.js} +1 -1
  450. package/public/assets/SkillPage-BInwZTQh.js +1 -0
  451. package/public/assets/TaskDetailPage-CfwEj1hy.js +31 -0
  452. package/public/assets/TaskListPage-Dh59ldSZ.js +1 -0
  453. package/public/assets/TaskStatusBadge-DuOoGIwE.js +1 -0
  454. package/public/assets/TerminalHomePage-BwXJjr-a.js +16 -0
  455. package/public/assets/TokenManage-B0Cpv6SO.js +1 -0
  456. package/public/assets/TotpSetupPage-MSCCURj9.js +9 -0
  457. package/public/assets/WorkerDetailPage-R2veIzKo.js +1 -0
  458. package/public/assets/WorkerListPage-CserMjGO.js +6 -0
  459. package/public/assets/WorkerSetupGuidePage-SqO2lzVa.js +11 -0
  460. package/public/assets/{arrow-left-CVKez32c.js → arrow-left-DklRsENx.js} +1 -1
  461. package/public/assets/{arrow-right-g7hTftEi.js → arrow-right-MDrzFe3K.js} +1 -1
  462. package/public/assets/{bot-DYvBcsZn.js → bot-DPaziJPf.js} +1 -1
  463. package/public/assets/{chevron-right-COxU2yxz.js → chevron-right-CqyufMDW.js} +1 -1
  464. package/public/assets/{copy-BGttVgA1.js → copy-BUH7P2Hf.js} +1 -1
  465. package/public/assets/date-BdNtiQTP.js +1 -0
  466. package/public/assets/{external-link-DXlCfUjE.js → external-link-ChPgQ7N_.js} +1 -1
  467. package/public/assets/index-BS0Fbx5V.css +1 -0
  468. package/public/assets/index-vL7aQJNr.js +225 -0
  469. package/public/assets/{key-3eDVdGih.js → key-CxvwwHnW.js} +1 -1
  470. package/public/assets/{loader-circle-DPm92ETj.js → loader-circle-DS5g1-Od.js} +1 -1
  471. package/public/assets/password-CHk45-jw.js +1 -0
  472. package/public/assets/{pencil-Bs3PwH2W.js → pencil-B6spIBcw.js} +1 -1
  473. package/public/assets/{plus-d-PLzbVX.js → plus-Bnd1Vz2Y.js} +1 -1
  474. package/public/assets/{rotate-ccw-Cus8CABi.js → rotate-ccw-CgcLAXNR.js} +1 -1
  475. package/public/assets/{scroll-text-CV3wlIy2.js → scroll-text-CecZ0Fk5.js} +1 -1
  476. package/public/assets/{settings-Ccijf48b.js → settings-C1uOD3PZ.js} +1 -1
  477. package/public/assets/status-colors-BPEUp90-.js +1 -0
  478. package/public/assets/string-B39tzdVK.js +1 -0
  479. package/public/assets/task-constants-BbFyCyKk.js +14 -0
  480. package/public/assets/task.store-BE6fEPu4.js +1 -0
  481. package/public/assets/{trash-2-bRJ-xwtq.js → trash-2-A2FsT1yG.js} +1 -1
  482. package/public/assets/useFetch-vGZMAvGi.js +1 -0
  483. package/public/assets/{users-LNQqKSEN.js → users-CEdRS_A3.js} +1 -1
  484. package/public/assets/wifi-D60NkK6F.js +6 -0
  485. package/public/assets/zap-DXw1NrWz.js +6 -0
  486. package/public/icon-192x192.png +0 -0
  487. package/public/icon-512x512.png +0 -0
  488. package/public/icon-maskable-192x192.png +0 -0
  489. package/public/icon-maskable-512x512.png +0 -0
  490. package/public/index.html +21 -4
  491. package/public/manifest.webmanifest +1 -0
  492. package/public/og-image.png +0 -0
  493. package/public/registerSW.js +1 -0
  494. package/public/sw.js +1 -0
  495. package/public/workbox-6e9b121d.js +1 -0
  496. package/database/migrations/002-add-indexes.sql +0 -17
  497. package/database/migrations/003-add-settings-table.sql +0 -4
  498. package/database/migrations/004-add-developer-id-index.sql +0 -5
  499. package/database/migrations/005-add-worker-version.sql +0 -2
  500. package/database/migrations/006-add-decommission-fields.sql +0 -2
  501. package/database/migrations/007-add-ssh-url.sql +0 -1
  502. package/public/assets/AccessTokensPage-Cb5hGBfN.js +0 -1
  503. package/public/assets/AdminPage-C7Xytkfo.js +0 -1
  504. package/public/assets/ApiReferencePage-DLGVc4xN.js +0 -1
  505. package/public/assets/AuditLogPage-BgqsUJ7x.js +0 -6
  506. package/public/assets/BotManage-Ds9DYQZA.js +0 -6
  507. package/public/assets/CliReferencePage-WXinn_69.js +0 -8
  508. package/public/assets/DeveloperManage-saSq3Hfx.js +0 -16
  509. package/public/assets/EditProjectPage-C4xWYLTo.js +0 -2
  510. package/public/assets/HomePage-y20pQ52r.js +0 -1
  511. package/public/assets/LandingPage-CB5BBbdI.js +0 -36
  512. package/public/assets/LoginPage-DLljhJkQ.js +0 -1
  513. package/public/assets/MachineDetailPage-CPm9tfdp.js +0 -1
  514. package/public/assets/MachineListPage-D-nhVz-m.js +0 -6
  515. package/public/assets/PipelineEditorPage-B9GgqAju.js +0 -3
  516. package/public/assets/ProfilePage-DASpeJq6.js +0 -1
  517. package/public/assets/ProjectDetailPage-DWZyNwTV.js +0 -7
  518. package/public/assets/ProjectListPage-BUMX3Dxa.js +0 -6
  519. package/public/assets/QuickAuth-B9mvq7ht.js +0 -1
  520. package/public/assets/Select-A7PXobk_.js +0 -6
  521. package/public/assets/SettingsPage-WGzxUbGp.js +0 -6
  522. package/public/assets/SkillPage-BIt2kF3W.js +0 -1
  523. package/public/assets/TaskDetailPage-CePyNfp6.js +0 -44
  524. package/public/assets/TaskListPage-MO4_PSve.js +0 -1
  525. package/public/assets/TaskStatusBadge-QtQUDscM.js +0 -1
  526. package/public/assets/TokenManage-Sf0RGymw.js +0 -1
  527. package/public/assets/TotpSetupPage-D-rbEYLf.js +0 -9
  528. package/public/assets/WorkerSetupGuidePage-D6Fv1MQo.js +0 -16
  529. package/public/assets/index-CDBuOPx4.js +0 -212
  530. package/public/assets/index-CQojj7Zu.css +0 -1
  531. package/public/assets/protocol-C5uQmiiB.js +0 -1
  532. package/public/assets/task.store-CvjSr507.js +0 -1
  533. /package/public/assets/{TaskDetailPage-Beg8tuEN.css → task-constants-Beg8tuEN.css} +0 -0
@@ -44,38 +44,79 @@ var __metadata = (this && this.__metadata) || function (k, v) {
44
44
  var Reconciler_1;
45
45
  Object.defineProperty(exports, "__esModule", { value: true });
46
46
  exports.Reconciler = void 0;
47
+ const protocol_1 = require("@overlordai/protocol");
47
48
  const common_1 = require("@nestjs/common");
48
49
  const crypto = __importStar(require("node:crypto"));
49
- const protocol_1 = require("@overlordai/protocol");
50
50
  const task_repository_1 = require("../database/repositories/task.repository");
51
- const machine_repository_1 = require("../database/repositories/machine.repository");
51
+ const worker_repository_1 = require("../database/repositories/worker.repository");
52
52
  const audit_log_repository_1 = require("../database/repositories/audit-log.repository");
53
53
  const workspace_repository_1 = require("../database/repositories/workspace.repository");
54
+ const event_emitter_1 = require("@nestjs/event-emitter");
55
+ const event_types_1 = require("../events/event-types");
54
56
  const scheduler_service_1 = require("./scheduler.service");
55
57
  const cleanup_service_1 = require("./cleanup.service");
56
58
  const worker_connection_manager_1 = require("./worker-connection.manager");
57
- let Reconciler = Reconciler_1 = class Reconciler {
59
+ let Reconciler = class Reconciler {
60
+ static { Reconciler_1 = this; }
58
61
  taskRepo;
59
- machineRepo;
62
+ workerRepo;
60
63
  auditLogRepo;
61
64
  workspaceRepo;
62
65
  schedulerService;
63
66
  cleanupService;
64
67
  workerConnectionManager;
68
+ eventEmitter;
65
69
  logger = new common_1.Logger(Reconciler_1.name);
66
- constructor(taskRepo, machineRepo, auditLogRepo, workspaceRepo, schedulerService, cleanupService, workerConnectionManager) {
70
+ failedCleanups = new Map();
71
+ cleanupRetryTimer = null;
72
+ static CLEANUP_RETRY_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
73
+ constructor(taskRepo, workerRepo, auditLogRepo, workspaceRepo, schedulerService, cleanupService, workerConnectionManager, eventEmitter) {
67
74
  this.taskRepo = taskRepo;
68
- this.machineRepo = machineRepo;
75
+ this.workerRepo = workerRepo;
69
76
  this.auditLogRepo = auditLogRepo;
70
77
  this.workspaceRepo = workspaceRepo;
71
78
  this.schedulerService = schedulerService;
72
79
  this.cleanupService = cleanupService;
73
80
  this.workerConnectionManager = workerConnectionManager;
81
+ this.eventEmitter = eventEmitter;
74
82
  }
75
83
  async onModuleInit() {
76
84
  this.logger.log('Running boot reconciliation...');
77
85
  await this.onBoot();
78
86
  this.logger.log('Boot reconciliation complete');
87
+ this.startCleanupRetryLoop();
88
+ }
89
+ onModuleDestroy() {
90
+ if (this.cleanupRetryTimer) {
91
+ clearInterval(this.cleanupRetryTimer);
92
+ this.cleanupRetryTimer = null;
93
+ }
94
+ }
95
+ startCleanupRetryLoop() {
96
+ this.cleanupRetryTimer = setInterval(() => {
97
+ void this.retryFailedCleanups();
98
+ }, Reconciler_1.CLEANUP_RETRY_INTERVAL_MS);
99
+ }
100
+ async retryFailedCleanups() {
101
+ if (this.failedCleanups.size === 0)
102
+ return;
103
+ this.logger.log(`Retrying ${this.failedCleanups.size} failed workspace cleanup(s)...`);
104
+ const entries = [...this.failedCleanups.entries()];
105
+ for (const [key, entry] of entries) {
106
+ const workspace = this.workspaceRepo.findByTaskId(entry.taskId);
107
+ if (!workspace) {
108
+ this.failedCleanups.delete(key);
109
+ continue;
110
+ }
111
+ try {
112
+ await this.cleanupService.scheduleCleanup(entry.taskId, entry.workerId, workspace.path);
113
+ this.failedCleanups.delete(key);
114
+ this.logger.log(`Successfully retried cleanup for task #${entry.taskId}`);
115
+ }
116
+ catch (err) {
117
+ this.logger.error(`Retry cleanup still failing for task #${entry.taskId}: ${(0, protocol_1.getErrorMessage)(err)}`);
118
+ }
119
+ }
79
120
  }
80
121
  // ---------------------------------------------------------------------------
81
122
  // onBoot — startup reconciliation
@@ -84,99 +125,137 @@ let Reconciler = Reconciler_1 = class Reconciler {
84
125
  const now = Date.now();
85
126
  let reEnqueuedCount = 0;
86
127
  let failedStaleCount = 0;
128
+ // Single query to fetch all active tasks instead of 4 separate findByStatus calls
129
+ const allActiveTasks = this.taskRepo.findByStatus([
130
+ protocol_1.TaskStatus.QUEUED,
131
+ protocol_1.TaskStatus.ASSIGNED,
132
+ protocol_1.TaskStatus.RUNNING,
133
+ protocol_1.TaskStatus.SUSPENDED,
134
+ ]);
135
+ // Group tasks by status in memory
136
+ const queuedTasks = [];
137
+ const assignedTasks = [];
138
+ const runningTasks = [];
139
+ const suspendedTasks = [];
140
+ for (const task of allActiveTasks) {
141
+ switch (task.status) {
142
+ case protocol_1.TaskStatus.QUEUED:
143
+ queuedTasks.push(task);
144
+ break;
145
+ case protocol_1.TaskStatus.ASSIGNED:
146
+ assignedTasks.push(task);
147
+ break;
148
+ case protocol_1.TaskStatus.RUNNING:
149
+ runningTasks.push(task);
150
+ break;
151
+ case protocol_1.TaskStatus.SUSPENDED:
152
+ suspendedTasks.push(task);
153
+ break;
154
+ }
155
+ }
156
+ // Pre-fetch all referenced workers in a single batch lookup
157
+ const workerIds = new Set();
158
+ for (const task of allActiveTasks) {
159
+ if (task.workerId)
160
+ workerIds.add(task.workerId);
161
+ }
162
+ const workerCache = new Map();
163
+ for (const wid of workerIds) {
164
+ workerCache.set(wid, this.workerRepo.findById(wid));
165
+ }
87
166
  // Step 1: Re-enqueue QUEUED/ASSIGNED tasks missing from BullMQ.
88
167
  // On boot we conservatively re-enqueue all QUEUED tasks since BullMQ
89
168
  // may have lost state during a restart.
90
- const queuedTasks = this.taskRepo.findByStatus([protocol_1.TaskStatus.QUEUED]);
91
169
  for (const task of queuedTasks) {
92
170
  await this.schedulerService.enqueueTask(task.id);
93
171
  reEnqueuedCount++;
94
172
  this.logger.log(`Re-enqueued QUEUED task #${task.id}`);
95
173
  }
96
- // ASSIGNED tasks with offline/missing machines get reset to QUEUED
97
- const assignedTasks = this.taskRepo.findByStatus([protocol_1.TaskStatus.ASSIGNED]);
174
+ // ASSIGNED tasks with offline/missing workers get reset to QUEUED
98
175
  for (const task of assignedTasks) {
99
- if (task.machineId) {
100
- const machine = this.machineRepo.findById(task.machineId);
101
- if (this.isMachineUnavailable(machine)) {
176
+ if (task.workerId) {
177
+ const worker = workerCache.get(task.workerId) ?? null;
178
+ if (this.isWorkerUnavailable(worker)) {
102
179
  this.updateTaskStatusSafe(task.id, protocol_1.TaskStatus.QUEUED, task.revision, {
103
- machineId: null,
180
+ workerId: null,
104
181
  assignedAt: null,
105
182
  });
106
183
  await this.schedulerService.enqueueTask(task.id);
107
184
  reEnqueuedCount++;
108
- this.logger.warn(`Reset ASSIGNED task #${task.id} to QUEUED (machine ${task.machineId} offline)`);
185
+ this.logger.warn(`Reset ASSIGNED task #${task.id} to QUEUED (worker ${task.workerId} offline)`);
109
186
  }
110
187
  else {
111
- // Machine online — re-enqueue so the scheduler can verify and re-dispatch
188
+ // Worker online — re-enqueue so the scheduler can verify and re-dispatch
112
189
  await this.schedulerService.enqueueTask(task.id);
113
190
  reEnqueuedCount++;
114
191
  }
115
192
  }
116
193
  else {
117
- // No machine assigned — reset to QUEUED
194
+ // No worker assigned — reset to QUEUED
118
195
  this.updateTaskStatusSafe(task.id, protocol_1.TaskStatus.QUEUED, task.revision);
119
196
  await this.schedulerService.enqueueTask(task.id);
120
197
  reEnqueuedCount++;
121
198
  }
122
199
  }
123
200
  // Step 2: Fail stale RUNNING/SUSPENDED tasks (grace 10 min).
124
- const runningTasks = this.taskRepo.findByStatus([protocol_1.TaskStatus.RUNNING]);
125
201
  for (const task of runningTasks) {
126
- if (!task.machineId) {
202
+ if (!task.workerId) {
127
203
  this.updateTaskStatusSafe(task.id, protocol_1.TaskStatus.FAILED, task.revision, {
128
- errorMessage: 'No machine assigned during boot reconciliation',
204
+ errorMessage: 'No worker assigned during boot reconciliation',
129
205
  completedAt: new Date().toISOString(),
130
206
  });
207
+ this.emitTaskStatusChanged(task.id, protocol_1.TaskStatus.FAILED, task.status, task.workerId, task.projectKey);
131
208
  failedStaleCount++;
132
209
  continue;
133
210
  }
134
- const machine = this.machineRepo.findById(task.machineId);
135
- if (this.isMachineUnavailable(machine)) {
136
- const lastHeartbeat = machine?.lastHeartbeat
137
- ? new Date(machine.lastHeartbeat).getTime()
211
+ const worker = workerCache.get(task.workerId) ?? null;
212
+ if (this.isWorkerUnavailable(worker)) {
213
+ const lastHeartbeat = worker?.lastHeartbeat
214
+ ? new Date(worker.lastHeartbeat).getTime()
138
215
  : 0;
139
216
  if (now - lastHeartbeat > protocol_1.GRACE_WINDOW_MS) {
140
217
  this.updateTaskStatusSafe(task.id, protocol_1.TaskStatus.FAILED, task.revision, {
141
- errorMessage: `Machine '${machine?.name ?? task.machineId}' offline beyond grace window (${Math.round((now - lastHeartbeat) / 1000)}s)`,
218
+ errorMessage: `Worker '${worker?.name ?? task.workerId}' offline beyond grace window (${Math.round((now - lastHeartbeat) / 1000)}s)`,
142
219
  completedAt: new Date().toISOString(),
143
220
  });
144
- if (task.machineId)
145
- this.scheduleWorkspaceCleanup(task.id, task.machineId);
221
+ this.emitTaskStatusChanged(task.id, protocol_1.TaskStatus.FAILED, task.status, task.workerId, task.projectKey);
222
+ if (task.workerId)
223
+ this.scheduleWorkspaceCleanup(task.id, task.workerId);
146
224
  failedStaleCount++;
147
- this.logger.warn(`Failed stale RUNNING task #${task.id} (machine ${task.machineId} offline > ${protocol_1.GRACE_WINDOW_MS / 1000}s)`);
225
+ this.logger.warn(`Failed stale RUNNING task #${task.id} (worker ${task.workerId} offline > ${protocol_1.GRACE_WINDOW_MS / 1000}s)`);
148
226
  }
149
227
  else {
150
228
  // Within grace window: suspend and await Worker recovery
151
229
  this.updateTaskStatusSafe(task.id, protocol_1.TaskStatus.SUSPENDED, task.revision);
152
- this.logger.warn(`Suspended RUNNING task #${task.id} (machine ${task.machineId} offline, within grace window)`);
230
+ this.logger.warn(`Suspended RUNNING task #${task.id} (worker ${task.workerId} offline, within grace window)`);
153
231
  }
154
232
  }
155
233
  }
156
- const suspendedTasks = this.taskRepo.findByStatus([protocol_1.TaskStatus.SUSPENDED]);
157
234
  for (const task of suspendedTasks) {
158
- if (!task.machineId) {
235
+ if (!task.workerId) {
159
236
  this.updateTaskStatusSafe(task.id, protocol_1.TaskStatus.FAILED, task.revision, {
160
- errorMessage: 'No machine assigned during boot reconciliation',
237
+ errorMessage: 'No worker assigned during boot reconciliation',
161
238
  completedAt: new Date().toISOString(),
162
239
  });
240
+ this.emitTaskStatusChanged(task.id, protocol_1.TaskStatus.FAILED, task.status, task.workerId, task.projectKey);
163
241
  failedStaleCount++;
164
242
  continue;
165
243
  }
166
- const machine = this.machineRepo.findById(task.machineId);
167
- if (this.isMachineUnavailable(machine)) {
168
- const lastHeartbeat = machine?.lastHeartbeat
169
- ? new Date(machine.lastHeartbeat).getTime()
244
+ const worker = workerCache.get(task.workerId) ?? null;
245
+ if (this.isWorkerUnavailable(worker)) {
246
+ const lastHeartbeat = worker?.lastHeartbeat
247
+ ? new Date(worker.lastHeartbeat).getTime()
170
248
  : 0;
171
249
  if (now - lastHeartbeat > protocol_1.GRACE_WINDOW_MS) {
172
250
  this.updateTaskStatusSafe(task.id, protocol_1.TaskStatus.FAILED, task.revision, {
173
- errorMessage: `Machine '${machine?.name ?? task.machineId}' offline beyond grace window`,
251
+ errorMessage: `Worker '${worker?.name ?? task.workerId}' offline beyond grace window`,
174
252
  completedAt: new Date().toISOString(),
175
253
  });
176
- if (task.machineId)
177
- this.scheduleWorkspaceCleanup(task.id, task.machineId);
254
+ this.emitTaskStatusChanged(task.id, protocol_1.TaskStatus.FAILED, task.status, task.workerId, task.projectKey);
255
+ if (task.workerId)
256
+ this.scheduleWorkspaceCleanup(task.id, task.workerId);
178
257
  failedStaleCount++;
179
- this.logger.warn(`Failed stale SUSPENDED task #${task.id} (machine ${task.machineId} offline > grace)`);
258
+ this.logger.warn(`Failed stale SUSPENDED task #${task.id} (worker ${task.workerId} offline > grace)`);
180
259
  }
181
260
  // Within grace: keep SUSPENDED, await Worker recovery
182
261
  }
@@ -184,13 +263,13 @@ let Reconciler = Reconciler_1 = class Reconciler {
184
263
  // Step 3: Remove stale BullMQ jobs for terminal tasks.
185
264
  // BullMQ removeOnComplete/removeOnFail handles most cleanup.
186
265
  // The scheduler's processJob re-checks status and skips stale tasks.
187
- // Step 4: Recalculate active_slots for all machines and update DB if mismatched.
188
- const allMachines = this.machineRepo.findAll();
189
- for (const machine of allMachines) {
190
- const actualSlots = this.machineRepo.countActiveSlots(machine.id);
191
- if (machine.activeSlots !== actualSlots) {
192
- this.machineRepo.updateActiveSlots(machine.id, actualSlots);
193
- this.logger.log(`Machine '${machine.name}' active_slots corrected: ${machine.activeSlots} → ${actualSlots}`);
266
+ // Step 4: Recalculate active_slots for all workers and update DB if mismatched.
267
+ const allWorkers = this.workerRepo.findAll();
268
+ for (const worker of allWorkers) {
269
+ const actualSlots = this.workerRepo.countActiveSlots(worker.id);
270
+ if (worker.activeSlots !== actualSlots) {
271
+ this.workerRepo.updateActiveSlots(worker.id, actualSlots);
272
+ this.logger.log(`Worker '${worker.name}' active_slots corrected: ${worker.activeSlots} → ${actualSlots}`);
194
273
  }
195
274
  }
196
275
  // Step 5: Write audit_log.
@@ -202,7 +281,7 @@ let Reconciler = Reconciler_1 = class Reconciler {
202
281
  reEnqueued: reEnqueuedCount,
203
282
  failedStale: failedStaleCount,
204
283
  globalActiveCount,
205
- machinesChecked: allMachines.length,
284
+ workersChecked: allWorkers.length,
206
285
  }),
207
286
  });
208
287
  // Step 6 (branch g): Re-enqueue cleanup for terminal tasks with active workspaces.
@@ -212,12 +291,12 @@ let Reconciler = Reconciler_1 = class Reconciler {
212
291
  let cleanupReEnqueuedCount = 0;
213
292
  for (const workspace of orphanedWorkspaces) {
214
293
  try {
215
- await this.cleanupService.scheduleCleanup(workspace.taskId, workspace.machineId, workspace.path, 0);
294
+ await this.cleanupService.scheduleCleanup(workspace.taskId, workspace.workerId, workspace.path, 0);
216
295
  cleanupReEnqueuedCount++;
217
- this.logger.warn(`Re-enqueued cleanup for workspace #${workspace.id} (task #${workspace.taskId}, machine ${workspace.machineId})`);
296
+ this.logger.warn(`Re-enqueued cleanup for workspace #${workspace.id} (task #${workspace.taskId}, worker ${workspace.workerId})`);
218
297
  }
219
298
  catch (err) {
220
- this.logger.error(`Failed to re-enqueue cleanup for workspace #${workspace.id} (task #${workspace.taskId}): ${err instanceof Error ? err.message : String(err)}`);
299
+ this.logger.error(`Failed to re-enqueue cleanup for workspace #${workspace.id} (task #${workspace.taskId}): ${(0, protocol_1.getErrorMessage)(err)}`);
221
300
  }
222
301
  }
223
302
  this.logger.log(`Boot reconciliation: re-enqueued=${reEnqueuedCount}, failed_stale=${failedStaleCount}, active_tasks=${globalActiveCount}, cleanup_re-enqueued=${cleanupReEnqueuedCount}`);
@@ -233,32 +312,32 @@ let Reconciler = Reconciler_1 = class Reconciler {
233
312
  // e. CANCELLED → notify Worker stop
234
313
  // f. Not reported → FAILED
235
314
  // ---------------------------------------------------------------------------
236
- async handleReconnect(machineId, tasks) {
237
- this.logger.log(`Reconciling reconnect for machine ${machineId} with ${tasks.length} reported task(s)`);
238
- const machine = this.machineRepo.findById(machineId);
239
- if (!machine) {
240
- this.logger.warn(`Reconnect from unknown machine ${machineId}, ignoring`);
315
+ async handleReconnect(workerId, tasks) {
316
+ this.logger.log(`Reconciling reconnect for worker ${workerId} with ${tasks.length} reported task(s)`);
317
+ const worker = this.workerRepo.findById(workerId);
318
+ if (!worker) {
319
+ this.logger.warn(`Reconnect from unknown worker ${workerId}, ignoring`);
241
320
  return [];
242
321
  }
243
322
  const actions = [];
244
323
  const reportedTaskIds = new Set(tasks.map((t) => t.taskId));
245
324
  const reportedTaskMap = new Map(tasks.map((t) => [t.taskId, t]));
246
- // Get all tasks assigned to this machine in active or recent terminal states
247
- const activeMachineTasks = this.taskRepo.findByMachineId(machineId, [
325
+ // Get all tasks assigned to this worker in active or recent terminal states
326
+ const activeWorkerTasks = this.taskRepo.findByWorkerId(workerId, [
248
327
  protocol_1.TaskStatus.RUNNING,
249
328
  protocol_1.TaskStatus.SUSPENDED,
250
329
  protocol_1.TaskStatus.ASSIGNED,
251
330
  ]);
252
- const terminalMachineTasks = this.taskRepo.findByMachineId(machineId, [
331
+ const terminalWorkerTasks = this.taskRepo.findByWorkerId(workerId, [
253
332
  protocol_1.TaskStatus.FAILED,
254
333
  protocol_1.TaskStatus.CANCELLED,
255
334
  ]);
256
- const allMachineTasks = [...activeMachineTasks, ...terminalMachineTasks];
257
- // Process each machine task against the Worker's report
258
- for (const task of allMachineTasks) {
335
+ const allWorkerTasks = [...activeWorkerTasks, ...terminalWorkerTasks];
336
+ // Process each worker task against the Worker's report
337
+ for (const task of allWorkerTasks) {
259
338
  const reported = reportedTaskMap.get(task.id);
260
339
  if (reported) {
261
- const action = this.reconcileReportedTask(machine, task, reported);
340
+ const action = this.reconcileReportedTask(worker, task, reported);
262
341
  actions.push({ taskId: task.id, action });
263
342
  }
264
343
  else if (task.status === protocol_1.TaskStatus.RUNNING ||
@@ -266,15 +345,16 @@ let Reconciler = Reconciler_1 = class Reconciler {
266
345
  // Branch (f): Dispatcher has task but Worker did not report it.
267
346
  // Worker lost execution context (process exited / Worker restarted).
268
347
  this.updateTaskStatusSafe(task.id, protocol_1.TaskStatus.FAILED, task.revision, {
269
- errorMessage: `Worker '${machine.name}' reconnected but did not report this task (execution context lost)`,
348
+ errorMessage: `Worker '${worker.name}' reconnected but did not report this task (execution context lost)`,
270
349
  completedAt: new Date().toISOString(),
271
350
  });
272
- if (task.machineId)
273
- this.scheduleWorkspaceCleanup(task.id, task.machineId);
351
+ if (task.workerId)
352
+ this.scheduleWorkspaceCleanup(task.id, task.workerId);
353
+ this.emitTaskStatusChanged(task.id, protocol_1.TaskStatus.FAILED, task.status, task.workerId, task.projectKey);
274
354
  this.auditLogRepo.create({
275
355
  action: 'reconcile_unreported_failed',
276
356
  resource: `task:${task.id}`,
277
- detail: `Task not reported by Worker '${machine.name}' during reconnect`,
357
+ detail: `Task not reported by Worker '${worker.name}' during reconnect`,
278
358
  });
279
359
  actions.push({ taskId: task.id, action: 'failed_unreported' });
280
360
  this.logger.warn(`Task #${task.id} (${task.status}) not reported by Worker, marked FAILED`);
@@ -282,7 +362,7 @@ let Reconciler = Reconciler_1 = class Reconciler {
282
362
  else if (task.status === protocol_1.TaskStatus.ASSIGNED) {
283
363
  // ASSIGNED but not reported — reset to QUEUED for rescheduling
284
364
  this.updateTaskStatusSafe(task.id, protocol_1.TaskStatus.QUEUED, task.revision, {
285
- machineId: null,
365
+ workerId: null,
286
366
  assignedAt: null,
287
367
  });
288
368
  await this.schedulerService.enqueueTask(task.id);
@@ -290,34 +370,34 @@ let Reconciler = Reconciler_1 = class Reconciler {
290
370
  this.logger.warn(`Task #${task.id} (ASSIGNED) not reported by Worker, reset to QUEUED`);
291
371
  }
292
372
  }
293
- // Handle tasks reported by Worker that Dispatcher doesn't have on this machine
373
+ // Handle tasks reported by Worker that Dispatcher doesn't have on this worker
294
374
  for (const reported of tasks) {
295
- if (allMachineTasks.some((t) => t.id === reported.taskId))
375
+ if (allWorkerTasks.some((t) => t.id === reported.taskId))
296
376
  continue;
297
377
  const task = this.taskRepo.findById(reported.taskId);
298
378
  if (!task) {
299
379
  this.logger.warn(`Worker reported unknown task #${reported.taskId}, requesting cleanup`);
300
- this.sendCleanupToWorker(machineId, reported.taskId);
380
+ this.sendCleanupToWorker(workerId, reported.taskId);
301
381
  actions.push({ taskId: reported.taskId, action: 'cleanup_unknown' });
302
382
  continue;
303
383
  }
304
- // Task exists but is assigned to a different machine or already processed
305
- const action = this.reconcileReportedTask(machine, task, reported);
384
+ // Task exists but is assigned to a different worker or already processed
385
+ const action = this.reconcileReportedTask(worker, task, reported);
306
386
  actions.push({ taskId: task.id, action });
307
387
  }
308
- this.logger.log(`Reconnect reconciliation for machine ${machineId}: ${actions.length} tasks processed`);
388
+ this.logger.log(`Reconnect reconciliation for worker ${workerId}: ${actions.length} tasks processed`);
309
389
  return actions;
310
390
  }
311
391
  // ---------------------------------------------------------------------------
312
392
  // Private: reconcile a single reported task (branches a-e)
313
393
  // ---------------------------------------------------------------------------
314
- reconcileReportedTask(machine, task, reported) {
394
+ reconcileReportedTask(worker, task, reported) {
315
395
  const { taskId, localStatus, currentStage, branch, mrUrl, errorMessage } = reported;
316
396
  switch (task.status) {
317
397
  // Branch (a): SUSPENDED + still_running → RUNNING (if admission ok)
318
398
  // Branch (b): SUSPENDED + completed_locally → COMPLETED
319
399
  case protocol_1.TaskStatus.SUSPENDED: {
320
- if (localStatus === 'still_running') {
400
+ if (localStatus === protocol_1.LocalStatus.STILL_RUNNING) {
321
401
  const activeCount = this.taskRepo.countActive();
322
402
  if (activeCount < protocol_1.MAX_CONCURRENT_TASKS) {
323
403
  const extra = {};
@@ -330,7 +410,8 @@ let Reconciler = Reconciler_1 = class Reconciler {
330
410
  msgId: crypto.randomUUID(),
331
411
  taskId,
332
412
  };
333
- this.workerConnectionManager.send(machine.id, resumeFrame);
413
+ this.workerConnectionManager.send(worker.id, resumeFrame);
414
+ this.emitTaskStatusChanged(taskId, protocol_1.TaskStatus.RUNNING, task.status, task.workerId, task.projectKey);
334
415
  this.logger.log(`Task #${taskId}: SUSPENDED → RUNNING (reconnect, admission ok)`);
335
416
  return 'resumed';
336
417
  }
@@ -343,7 +424,7 @@ let Reconciler = Reconciler_1 = class Reconciler {
343
424
  });
344
425
  return 'admission_blocked';
345
426
  }
346
- if (localStatus === 'completed_locally') {
427
+ if (localStatus === protocol_1.LocalStatus.COMPLETED_LOCALLY) {
347
428
  const extra = {
348
429
  completedAt: new Date().toISOString(),
349
430
  };
@@ -352,18 +433,20 @@ let Reconciler = Reconciler_1 = class Reconciler {
352
433
  if (mrUrl)
353
434
  extra['mrUrl'] = mrUrl;
354
435
  this.updateTaskStatusSafe(taskId, protocol_1.TaskStatus.COMPLETED, task.revision, extra);
355
- if (task.machineId)
356
- this.scheduleWorkspaceCleanup(taskId, task.machineId);
436
+ if (task.workerId)
437
+ this.scheduleWorkspaceCleanup(taskId, task.workerId);
438
+ this.emitTaskStatusChanged(taskId, protocol_1.TaskStatus.COMPLETED, task.status, task.workerId, task.projectKey);
357
439
  this.logger.log(`Task #${taskId}: SUSPENDED → COMPLETED (completed during disconnect)`);
358
440
  return 'completed';
359
441
  }
360
- if (localStatus === 'failed_locally') {
442
+ if (localStatus === protocol_1.LocalStatus.FAILED_LOCALLY) {
361
443
  this.updateTaskStatusSafe(taskId, protocol_1.TaskStatus.FAILED, task.revision, {
362
444
  errorMessage: errorMessage ?? 'Task failed locally during disconnect',
363
445
  completedAt: new Date().toISOString(),
364
446
  });
365
- if (task.machineId)
366
- this.scheduleWorkspaceCleanup(taskId, task.machineId);
447
+ if (task.workerId)
448
+ this.scheduleWorkspaceCleanup(taskId, task.workerId);
449
+ this.emitTaskStatusChanged(taskId, protocol_1.TaskStatus.FAILED, task.status, task.workerId, task.projectKey);
367
450
  this.logger.log(`Task #${taskId}: SUSPENDED → FAILED (failed during disconnect)`);
368
451
  return 'failed';
369
452
  }
@@ -372,12 +455,12 @@ let Reconciler = Reconciler_1 = class Reconciler {
372
455
  // Branch (c): FAILED + still_running → notify Worker cleanup
373
456
  // Branch (d): FAILED + completed_locally → restore to COMPLETED
374
457
  case protocol_1.TaskStatus.FAILED: {
375
- if (localStatus === 'still_running') {
458
+ if (localStatus === protocol_1.LocalStatus.STILL_RUNNING) {
376
459
  this.logger.log(`Task #${taskId}: FAILED but still running on Worker, sending cancel`);
377
- this.sendCancelToWorker(machine.id, taskId);
460
+ this.sendCancelToWorker(worker.id, taskId);
378
461
  return 'send_cancel';
379
462
  }
380
- if (localStatus === 'completed_locally') {
463
+ if (localStatus === protocol_1.LocalStatus.COMPLETED_LOCALLY) {
381
464
  const extra = {
382
465
  completedAt: new Date().toISOString(),
383
466
  errorMessage: null,
@@ -387,8 +470,9 @@ let Reconciler = Reconciler_1 = class Reconciler {
387
470
  if (mrUrl)
388
471
  extra['mrUrl'] = mrUrl;
389
472
  this.updateTaskStatusSafe(taskId, protocol_1.TaskStatus.COMPLETED, task.revision, extra);
390
- if (task.machineId)
391
- this.scheduleWorkspaceCleanup(taskId, task.machineId);
473
+ if (task.workerId)
474
+ this.scheduleWorkspaceCleanup(taskId, task.workerId);
475
+ this.emitTaskStatusChanged(taskId, protocol_1.TaskStatus.COMPLETED, task.status, task.workerId, task.projectKey);
392
476
  this.auditLogRepo.create({
393
477
  action: 'reconcile_restore_completed',
394
478
  resource: `task:${taskId}`,
@@ -401,12 +485,12 @@ let Reconciler = Reconciler_1 = class Reconciler {
401
485
  }
402
486
  // Branch (e): CANCELLED → notify Worker to stop
403
487
  case protocol_1.TaskStatus.CANCELLED: {
404
- if (localStatus === 'still_running' ||
405
- localStatus === 'completed_locally') {
488
+ if (localStatus === protocol_1.LocalStatus.STILL_RUNNING ||
489
+ localStatus === protocol_1.LocalStatus.COMPLETED_LOCALLY) {
406
490
  // Keep CANCELLED (user intent priority), notify Worker to stop
407
491
  this.logger.log(`Task #${taskId}: CANCELLED, notifying Worker to stop (localStatus=${localStatus})`);
408
- this.sendCancelToWorker(machine.id, taskId);
409
- if (localStatus === 'completed_locally') {
492
+ this.sendCancelToWorker(worker.id, taskId);
493
+ if (localStatus === protocol_1.LocalStatus.COMPLETED_LOCALLY) {
410
494
  this.auditLogRepo.create({
411
495
  action: 'reconcile_cancelled_but_completed',
412
496
  resource: `task:${taskId}`,
@@ -419,13 +503,13 @@ let Reconciler = Reconciler_1 = class Reconciler {
419
503
  }
420
504
  // RUNNING: Worker confirms still running or reports completion/failure
421
505
  case protocol_1.TaskStatus.RUNNING: {
422
- if (localStatus === 'still_running') {
506
+ if (localStatus === protocol_1.LocalStatus.STILL_RUNNING) {
423
507
  if (currentStage && currentStage !== task.currentStage) {
424
508
  this.updateTaskStatusSafe(taskId, protocol_1.TaskStatus.RUNNING, task.revision, { currentStage });
425
509
  }
426
510
  return 'no_op';
427
511
  }
428
- if (localStatus === 'completed_locally') {
512
+ if (localStatus === protocol_1.LocalStatus.COMPLETED_LOCALLY) {
429
513
  const extra = {
430
514
  completedAt: new Date().toISOString(),
431
515
  };
@@ -434,18 +518,20 @@ let Reconciler = Reconciler_1 = class Reconciler {
434
518
  if (mrUrl)
435
519
  extra['mrUrl'] = mrUrl;
436
520
  this.updateTaskStatusSafe(taskId, protocol_1.TaskStatus.COMPLETED, task.revision, extra);
437
- if (task.machineId)
438
- this.scheduleWorkspaceCleanup(taskId, task.machineId);
521
+ if (task.workerId)
522
+ this.scheduleWorkspaceCleanup(taskId, task.workerId);
523
+ this.emitTaskStatusChanged(taskId, protocol_1.TaskStatus.COMPLETED, task.status, task.workerId, task.projectKey);
439
524
  this.logger.log(`Task #${taskId}: RUNNING → COMPLETED (completed during disconnect)`);
440
525
  return 'completed';
441
526
  }
442
- if (localStatus === 'failed_locally') {
527
+ if (localStatus === protocol_1.LocalStatus.FAILED_LOCALLY) {
443
528
  this.updateTaskStatusSafe(taskId, protocol_1.TaskStatus.FAILED, task.revision, {
444
529
  errorMessage: errorMessage ?? 'Task failed locally during disconnect',
445
530
  completedAt: new Date().toISOString(),
446
531
  });
447
- if (task.machineId)
448
- this.scheduleWorkspaceCleanup(taskId, task.machineId);
532
+ if (task.workerId)
533
+ this.scheduleWorkspaceCleanup(taskId, task.workerId);
534
+ this.emitTaskStatusChanged(taskId, protocol_1.TaskStatus.FAILED, task.status, task.workerId, task.projectKey);
449
535
  this.logger.log(`Task #${taskId}: RUNNING → FAILED (failed during disconnect)`);
450
536
  return 'failed';
451
537
  }
@@ -453,14 +539,15 @@ let Reconciler = Reconciler_1 = class Reconciler {
453
539
  }
454
540
  // ASSIGNED: Worker may have started executing before we recorded RUNNING
455
541
  case protocol_1.TaskStatus.ASSIGNED: {
456
- if (localStatus === 'still_running') {
542
+ if (localStatus === protocol_1.LocalStatus.STILL_RUNNING) {
457
543
  this.updateTaskStatusSafe(taskId, protocol_1.TaskStatus.RUNNING, task.revision, {
458
544
  startedAt: new Date().toISOString(),
459
545
  });
546
+ this.emitTaskStatusChanged(taskId, protocol_1.TaskStatus.RUNNING, task.status, task.workerId, task.projectKey);
460
547
  this.logger.log(`Task #${taskId}: ASSIGNED → RUNNING (Worker reports still_running)`);
461
548
  return 'promoted_to_running';
462
549
  }
463
- if (localStatus === 'completed_locally') {
550
+ if (localStatus === protocol_1.LocalStatus.COMPLETED_LOCALLY) {
464
551
  const extra = {
465
552
  completedAt: new Date().toISOString(),
466
553
  startedAt: task.startedAt ?? new Date().toISOString(),
@@ -470,8 +557,9 @@ let Reconciler = Reconciler_1 = class Reconciler {
470
557
  if (mrUrl)
471
558
  extra['mrUrl'] = mrUrl;
472
559
  this.updateTaskStatusSafe(taskId, protocol_1.TaskStatus.COMPLETED, task.revision, extra);
473
- if (task.machineId)
474
- this.scheduleWorkspaceCleanup(taskId, task.machineId);
560
+ if (task.workerId)
561
+ this.scheduleWorkspaceCleanup(taskId, task.workerId);
562
+ this.emitTaskStatusChanged(taskId, protocol_1.TaskStatus.COMPLETED, task.status, task.workerId, task.projectKey);
475
563
  this.logger.log(`Task #${taskId}: ASSIGNED → COMPLETED (completed locally)`);
476
564
  return 'completed';
477
565
  }
@@ -492,35 +580,23 @@ let Reconciler = Reconciler_1 = class Reconciler {
492
580
  * Best-effort for reconciliation — continues processing other tasks on failure.
493
581
  */
494
582
  updateTaskStatusSafe(taskId, status, initialRevision, extra) {
495
- let revision = initialRevision;
496
- for (let attempt = 0; attempt < protocol_1.CAS_MAX_RETRIES; attempt++) {
497
- const success = this.taskRepo.updateStatus(taskId, status, revision, extra);
498
- if (success)
499
- return true;
500
- const freshTask = this.taskRepo.findById(taskId);
501
- if (!freshTask) {
502
- this.logger.error(`Task #${taskId} disappeared during CAS retry (reconciliation)`);
503
- return false;
504
- }
505
- // Already at target status — success
506
- if (freshTask.status === status)
507
- return true;
508
- revision = freshTask.revision;
583
+ const { success, task } = this.taskRepo.updateStatusWithCasRetry(taskId, status, initialRevision, extra);
584
+ if (!success) {
585
+ this.logger.error(`CAS retry exhausted for task #${taskId} → ${status} during reconciliation`);
509
586
  }
510
- this.logger.error(`CAS retry exhausted for task #${taskId} → ${status} during reconciliation (${protocol_1.CAS_MAX_RETRIES} attempts)`);
511
- return false;
587
+ return success;
512
588
  }
513
589
  /** Send cancel frame to a Worker for a specific task. */
514
- sendCancelToWorker(machineId, taskId) {
590
+ sendCancelToWorker(workerId, taskId) {
515
591
  const frame = {
516
592
  type: 'cancel',
517
593
  msgId: crypto.randomUUID(),
518
594
  taskId,
519
595
  };
520
- this.workerConnectionManager.send(machineId, frame);
596
+ this.workerConnectionManager.send(workerId, frame);
521
597
  }
522
598
  /** Send cleanup instruction to Worker for a specific task. */
523
- sendCleanupToWorker(machineId, taskId) {
599
+ sendCleanupToWorker(workerId, taskId) {
524
600
  const workspace = this.workspaceRepo.findByTaskId(taskId);
525
601
  const frame = {
526
602
  type: 'cleanup_workspace',
@@ -528,20 +604,32 @@ let Reconciler = Reconciler_1 = class Reconciler {
528
604
  taskId,
529
605
  workspacePath: workspace?.path ?? '',
530
606
  };
531
- this.workerConnectionManager.send(machineId, frame);
607
+ this.workerConnectionManager.send(workerId, frame);
608
+ }
609
+ /** Emit a TASK_STATUS_CHANGED domain event. */
610
+ emitTaskStatusChanged(taskId, status, previousStatus, workerId, projectKey) {
611
+ this.eventEmitter.emit(event_types_1.DomainEvents.TASK_STATUS_CHANGED, {
612
+ taskId,
613
+ status,
614
+ previousStatus,
615
+ workerId,
616
+ projectKey,
617
+ });
532
618
  }
533
- /** Check if a machine is unavailable (missing, offline, or decommissioned). */
534
- isMachineUnavailable(machine) {
535
- return !machine || machine.status === protocol_1.MachineStatus.OFFLINE || machine.status === protocol_1.MachineStatus.DECOMMISSIONED;
619
+ /** Check if a worker is unavailable (missing, offline, or decommissioned). */
620
+ isWorkerUnavailable(worker) {
621
+ return !worker || worker.status === protocol_1.WorkerStatus.OFFLINE || worker.status === protocol_1.WorkerStatus.DECOMMISSIONED;
536
622
  }
537
623
  /** Schedule workspace cleanup for a task that reached a terminal state. */
538
- scheduleWorkspaceCleanup(taskId, machineId) {
624
+ scheduleWorkspaceCleanup(taskId, workerId) {
539
625
  const workspace = this.workspaceRepo.findByTaskId(taskId);
540
626
  if (workspace) {
541
627
  this.cleanupService
542
- .scheduleCleanup(taskId, machineId, workspace.path)
628
+ .scheduleCleanup(taskId, workerId, workspace.path)
543
629
  .catch((err) => {
544
- this.logger.error(`Failed to schedule cleanup for task #${taskId}: ${err instanceof Error ? err.message : String(err)}`);
630
+ this.logger.error(`Failed to schedule cleanup for task #${taskId}: ${(0, protocol_1.getErrorMessage)(err)}. Marking workspace for cleanup and adding to retry set.`);
631
+ this.workspaceRepo.markForCleanup(taskId);
632
+ this.failedCleanups.set(`${taskId}:${workerId}`, { taskId, workerId });
545
633
  });
546
634
  }
547
635
  }
@@ -550,11 +638,12 @@ exports.Reconciler = Reconciler;
550
638
  exports.Reconciler = Reconciler = Reconciler_1 = __decorate([
551
639
  (0, common_1.Injectable)(),
552
640
  __metadata("design:paramtypes", [task_repository_1.TaskRepository,
553
- machine_repository_1.MachineRepository,
641
+ worker_repository_1.WorkerRepository,
554
642
  audit_log_repository_1.AuditLogRepository,
555
643
  workspace_repository_1.WorkspaceRepository,
556
644
  scheduler_service_1.SchedulerService,
557
645
  cleanup_service_1.CleanupService,
558
- worker_connection_manager_1.WorkerConnectionManager])
646
+ worker_connection_manager_1.WorkerConnectionManager,
647
+ event_emitter_1.EventEmitter2])
559
648
  ], Reconciler);
560
649
  //# sourceMappingURL=reconciler.js.map