@overlordai/server 1.0.1

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 (345) hide show
  1. package/database/migrations/001-init-schema.sql +226 -0
  2. package/database/migrations/002-add-indexes.sql +17 -0
  3. package/database/migrations/003-add-settings-table.sql +4 -0
  4. package/database/migrations/004-add-developer-id-index.sql +5 -0
  5. package/dist/adapters/adapter.interface.d.ts +41 -0
  6. package/dist/adapters/adapter.interface.d.ts.map +1 -0
  7. package/dist/adapters/adapter.interface.js +6 -0
  8. package/dist/adapters/adapter.interface.js.map +1 -0
  9. package/dist/adapters/adapter.module.d.ts +3 -0
  10. package/dist/adapters/adapter.module.d.ts.map +1 -0
  11. package/dist/adapters/adapter.module.js +54 -0
  12. package/dist/adapters/adapter.module.js.map +1 -0
  13. package/dist/adapters/adapter.registry.d.ts +19 -0
  14. package/dist/adapters/adapter.registry.d.ts.map +1 -0
  15. package/dist/adapters/adapter.registry.js +51 -0
  16. package/dist/adapters/adapter.registry.js.map +1 -0
  17. package/dist/adapters/lark/lark-card.builder.d.ts +48 -0
  18. package/dist/adapters/lark/lark-card.builder.d.ts.map +1 -0
  19. package/dist/adapters/lark/lark-card.builder.js +259 -0
  20. package/dist/adapters/lark/lark-card.builder.js.map +1 -0
  21. package/dist/adapters/lark/lark-message.parser.d.ts +51 -0
  22. package/dist/adapters/lark/lark-message.parser.d.ts.map +1 -0
  23. package/dist/adapters/lark/lark-message.parser.js +189 -0
  24. package/dist/adapters/lark/lark-message.parser.js.map +1 -0
  25. package/dist/adapters/lark/lark-signature.d.ts +13 -0
  26. package/dist/adapters/lark/lark-signature.d.ts.map +1 -0
  27. package/dist/adapters/lark/lark-signature.js +58 -0
  28. package/dist/adapters/lark/lark-signature.js.map +1 -0
  29. package/dist/adapters/lark/lark.adapter.d.ts +65 -0
  30. package/dist/adapters/lark/lark.adapter.d.ts.map +1 -0
  31. package/dist/adapters/lark/lark.adapter.js +565 -0
  32. package/dist/adapters/lark/lark.adapter.js.map +1 -0
  33. package/dist/adapters/lark/lark.controller.d.ts +21 -0
  34. package/dist/adapters/lark/lark.controller.d.ts.map +1 -0
  35. package/dist/adapters/lark/lark.controller.js +120 -0
  36. package/dist/adapters/lark/lark.controller.js.map +1 -0
  37. package/dist/adapters/slack/slack.adapter.d.ts +19 -0
  38. package/dist/adapters/slack/slack.adapter.d.ts.map +1 -0
  39. package/dist/adapters/slack/slack.adapter.js +42 -0
  40. package/dist/adapters/slack/slack.adapter.js.map +1 -0
  41. package/dist/app.module.d.ts +5 -0
  42. package/dist/app.module.d.ts.map +1 -0
  43. package/dist/app.module.js +48 -0
  44. package/dist/app.module.js.map +1 -0
  45. package/dist/auth/auth.controller.d.ts +15 -0
  46. package/dist/auth/auth.controller.d.ts.map +1 -0
  47. package/dist/auth/auth.controller.js +67 -0
  48. package/dist/auth/auth.controller.js.map +1 -0
  49. package/dist/auth/auth.module.d.ts +3 -0
  50. package/dist/auth/auth.module.d.ts.map +1 -0
  51. package/dist/auth/auth.module.js +46 -0
  52. package/dist/auth/auth.module.js.map +1 -0
  53. package/dist/auth/auth.service.d.ts +62 -0
  54. package/dist/auth/auth.service.d.ts.map +1 -0
  55. package/dist/auth/auth.service.js +307 -0
  56. package/dist/auth/auth.service.js.map +1 -0
  57. package/dist/auth/decorators/allow-totp-setup.decorator.d.ts +3 -0
  58. package/dist/auth/decorators/allow-totp-setup.decorator.d.ts.map +1 -0
  59. package/dist/auth/decorators/allow-totp-setup.decorator.js +8 -0
  60. package/dist/auth/decorators/allow-totp-setup.decorator.js.map +1 -0
  61. package/dist/auth/decorators/project-roles.decorator.d.ts +4 -0
  62. package/dist/auth/decorators/project-roles.decorator.d.ts.map +1 -0
  63. package/dist/auth/decorators/project-roles.decorator.js +8 -0
  64. package/dist/auth/decorators/project-roles.decorator.js.map +1 -0
  65. package/dist/auth/decorators/roles.decorator.d.ts +4 -0
  66. package/dist/auth/decorators/roles.decorator.d.ts.map +1 -0
  67. package/dist/auth/decorators/roles.decorator.js +8 -0
  68. package/dist/auth/decorators/roles.decorator.js.map +1 -0
  69. package/dist/auth/extract-user.middleware.d.ts +21 -0
  70. package/dist/auth/extract-user.middleware.d.ts.map +1 -0
  71. package/dist/auth/extract-user.middleware.js +57 -0
  72. package/dist/auth/extract-user.middleware.js.map +1 -0
  73. package/dist/auth/guards/jwt-auth.guard.d.ts +14 -0
  74. package/dist/auth/guards/jwt-auth.guard.d.ts.map +1 -0
  75. package/dist/auth/guards/jwt-auth.guard.js +139 -0
  76. package/dist/auth/guards/jwt-auth.guard.js.map +1 -0
  77. package/dist/auth/guards/project-role.guard.d.ts +10 -0
  78. package/dist/auth/guards/project-role.guard.d.ts.map +1 -0
  79. package/dist/auth/guards/project-role.guard.js +72 -0
  80. package/dist/auth/guards/project-role.guard.js.map +1 -0
  81. package/dist/auth/guards/roles.guard.d.ts +8 -0
  82. package/dist/auth/guards/roles.guard.d.ts.map +1 -0
  83. package/dist/auth/guards/roles.guard.js +56 -0
  84. package/dist/auth/guards/roles.guard.js.map +1 -0
  85. package/dist/auth/jwt.strategy.d.ts +23 -0
  86. package/dist/auth/jwt.strategy.d.ts.map +1 -0
  87. package/dist/auth/jwt.strategy.js +49 -0
  88. package/dist/auth/jwt.strategy.js.map +1 -0
  89. package/dist/common/crypto.service.d.ts +31 -0
  90. package/dist/common/crypto.service.d.ts.map +1 -0
  91. package/dist/common/crypto.service.js +120 -0
  92. package/dist/common/crypto.service.js.map +1 -0
  93. package/dist/common/error-filter.d.ts +6 -0
  94. package/dist/common/error-filter.d.ts.map +1 -0
  95. package/dist/common/error-filter.js +78 -0
  96. package/dist/common/error-filter.js.map +1 -0
  97. package/dist/common/health.controller.d.ts +13 -0
  98. package/dist/common/health.controller.d.ts.map +1 -0
  99. package/dist/common/health.controller.js +75 -0
  100. package/dist/common/health.controller.js.map +1 -0
  101. package/dist/common/logger.service.d.ts +11 -0
  102. package/dist/common/logger.service.d.ts.map +1 -0
  103. package/dist/common/logger.service.js +48 -0
  104. package/dist/common/logger.service.js.map +1 -0
  105. package/dist/common/pagination.d.ts +18 -0
  106. package/dist/common/pagination.d.ts.map +1 -0
  107. package/dist/common/pagination.js +39 -0
  108. package/dist/common/pagination.js.map +1 -0
  109. package/dist/common/rate-limit.guard.d.ts +48 -0
  110. package/dist/common/rate-limit.guard.d.ts.map +1 -0
  111. package/dist/common/rate-limit.guard.js +129 -0
  112. package/dist/common/rate-limit.guard.js.map +1 -0
  113. package/dist/common/sensitive-filter.d.ts +7 -0
  114. package/dist/common/sensitive-filter.d.ts.map +1 -0
  115. package/dist/common/sensitive-filter.js +20 -0
  116. package/dist/common/sensitive-filter.js.map +1 -0
  117. package/dist/database/database.module.d.ts +3 -0
  118. package/dist/database/database.module.d.ts.map +1 -0
  119. package/dist/database/database.module.js +22 -0
  120. package/dist/database/database.module.js.map +1 -0
  121. package/dist/database/database.service.d.ts +13 -0
  122. package/dist/database/database.service.d.ts.map +1 -0
  123. package/dist/database/database.service.js +107 -0
  124. package/dist/database/database.service.js.map +1 -0
  125. package/dist/database/migration-runner.d.ts +5 -0
  126. package/dist/database/migration-runner.d.ts.map +1 -0
  127. package/dist/database/migration-runner.js +86 -0
  128. package/dist/database/migration-runner.js.map +1 -0
  129. package/dist/database/repositories/audit-log.repository.d.ts +29 -0
  130. package/dist/database/repositories/audit-log.repository.d.ts.map +1 -0
  131. package/dist/database/repositories/audit-log.repository.js +80 -0
  132. package/dist/database/repositories/audit-log.repository.js.map +1 -0
  133. package/dist/database/repositories/bot.repository.d.ts +67 -0
  134. package/dist/database/repositories/bot.repository.d.ts.map +1 -0
  135. package/dist/database/repositories/bot.repository.js +133 -0
  136. package/dist/database/repositories/bot.repository.js.map +1 -0
  137. package/dist/database/repositories/developer-token.repository.d.ts +40 -0
  138. package/dist/database/repositories/developer-token.repository.d.ts.map +1 -0
  139. package/dist/database/repositories/developer-token.repository.js +84 -0
  140. package/dist/database/repositories/developer-token.repository.js.map +1 -0
  141. package/dist/database/repositories/developer.repository.d.ts +25 -0
  142. package/dist/database/repositories/developer.repository.d.ts.map +1 -0
  143. package/dist/database/repositories/developer.repository.js +139 -0
  144. package/dist/database/repositories/developer.repository.js.map +1 -0
  145. package/dist/database/repositories/machine.repository.d.ts +39 -0
  146. package/dist/database/repositories/machine.repository.d.ts.map +1 -0
  147. package/dist/database/repositories/machine.repository.js +176 -0
  148. package/dist/database/repositories/machine.repository.js.map +1 -0
  149. package/dist/database/repositories/notification.repository.d.ts +19 -0
  150. package/dist/database/repositories/notification.repository.d.ts.map +1 -0
  151. package/dist/database/repositories/notification.repository.js +94 -0
  152. package/dist/database/repositories/notification.repository.js.map +1 -0
  153. package/dist/database/repositories/project-member.repository.d.ts +30 -0
  154. package/dist/database/repositories/project-member.repository.d.ts.map +1 -0
  155. package/dist/database/repositories/project-member.repository.js +75 -0
  156. package/dist/database/repositories/project-member.repository.js.map +1 -0
  157. package/dist/database/repositories/project.repository.d.ts +24 -0
  158. package/dist/database/repositories/project.repository.d.ts.map +1 -0
  159. package/dist/database/repositories/project.repository.js +154 -0
  160. package/dist/database/repositories/project.repository.js.map +1 -0
  161. package/dist/database/repositories/session.repository.d.ts +19 -0
  162. package/dist/database/repositories/session.repository.d.ts.map +1 -0
  163. package/dist/database/repositories/session.repository.js +117 -0
  164. package/dist/database/repositories/session.repository.js.map +1 -0
  165. package/dist/database/repositories/task.repository.d.ts +37 -0
  166. package/dist/database/repositories/task.repository.d.ts.map +1 -0
  167. package/dist/database/repositories/task.repository.js +229 -0
  168. package/dist/database/repositories/task.repository.js.map +1 -0
  169. package/dist/database/repositories/worker-token.repository.d.ts +20 -0
  170. package/dist/database/repositories/worker-token.repository.d.ts.map +1 -0
  171. package/dist/database/repositories/worker-token.repository.js +94 -0
  172. package/dist/database/repositories/worker-token.repository.js.map +1 -0
  173. package/dist/database/repositories/workspace.repository.d.ts +19 -0
  174. package/dist/database/repositories/workspace.repository.d.ts.map +1 -0
  175. package/dist/database/repositories/workspace.repository.js +82 -0
  176. package/dist/database/repositories/workspace.repository.js.map +1 -0
  177. package/dist/dispatcher/capability.service.d.ts +50 -0
  178. package/dist/dispatcher/capability.service.d.ts.map +1 -0
  179. package/dist/dispatcher/capability.service.js +159 -0
  180. package/dist/dispatcher/capability.service.js.map +1 -0
  181. package/dist/dispatcher/cleanup.service.d.ts +23 -0
  182. package/dist/dispatcher/cleanup.service.d.ts.map +1 -0
  183. package/dist/dispatcher/cleanup.service.js +107 -0
  184. package/dist/dispatcher/cleanup.service.js.map +1 -0
  185. package/dist/dispatcher/dedup.service.d.ts +48 -0
  186. package/dist/dispatcher/dedup.service.d.ts.map +1 -0
  187. package/dist/dispatcher/dedup.service.js +189 -0
  188. package/dist/dispatcher/dedup.service.js.map +1 -0
  189. package/dist/dispatcher/dispatcher.module.d.ts +3 -0
  190. package/dist/dispatcher/dispatcher.module.d.ts.map +1 -0
  191. package/dist/dispatcher/dispatcher.module.js +76 -0
  192. package/dist/dispatcher/dispatcher.module.js.map +1 -0
  193. package/dist/dispatcher/dispatcher.service.d.ts +134 -0
  194. package/dist/dispatcher/dispatcher.service.d.ts.map +1 -0
  195. package/dist/dispatcher/dispatcher.service.js +1034 -0
  196. package/dist/dispatcher/dispatcher.service.js.map +1 -0
  197. package/dist/dispatcher/heartbeat.service.d.ts +50 -0
  198. package/dist/dispatcher/heartbeat.service.d.ts.map +1 -0
  199. package/dist/dispatcher/heartbeat.service.js +154 -0
  200. package/dist/dispatcher/heartbeat.service.js.map +1 -0
  201. package/dist/dispatcher/machine-selector.d.ts +18 -0
  202. package/dist/dispatcher/machine-selector.d.ts.map +1 -0
  203. package/dist/dispatcher/machine-selector.js +144 -0
  204. package/dist/dispatcher/machine-selector.js.map +1 -0
  205. package/dist/dispatcher/pty-relay.service.d.ts +75 -0
  206. package/dist/dispatcher/pty-relay.service.d.ts.map +1 -0
  207. package/dist/dispatcher/pty-relay.service.js +404 -0
  208. package/dist/dispatcher/pty-relay.service.js.map +1 -0
  209. package/dist/dispatcher/reconciler.d.ts +39 -0
  210. package/dist/dispatcher/reconciler.d.ts.map +1 -0
  211. package/dist/dispatcher/reconciler.js +556 -0
  212. package/dist/dispatcher/reconciler.js.map +1 -0
  213. package/dist/dispatcher/scheduler.service.d.ts +50 -0
  214. package/dist/dispatcher/scheduler.service.d.ts.map +1 -0
  215. package/dist/dispatcher/scheduler.service.js +287 -0
  216. package/dist/dispatcher/scheduler.service.js.map +1 -0
  217. package/dist/dispatcher/state-machine.d.ts +16 -0
  218. package/dist/dispatcher/state-machine.d.ts.map +1 -0
  219. package/dist/dispatcher/state-machine.js +77 -0
  220. package/dist/dispatcher/state-machine.js.map +1 -0
  221. package/dist/dispatcher/task-log-batcher.d.ts +50 -0
  222. package/dist/dispatcher/task-log-batcher.d.ts.map +1 -0
  223. package/dist/dispatcher/task-log-batcher.js +184 -0
  224. package/dist/dispatcher/task-log-batcher.js.map +1 -0
  225. package/dist/dispatcher/worker-connection.manager.d.ts +49 -0
  226. package/dist/dispatcher/worker-connection.manager.d.ts.map +1 -0
  227. package/dist/dispatcher/worker-connection.manager.js +128 -0
  228. package/dist/dispatcher/worker-connection.manager.js.map +1 -0
  229. package/dist/main.d.ts +2 -0
  230. package/dist/main.d.ts.map +1 -0
  231. package/dist/main.js +85 -0
  232. package/dist/main.js.map +1 -0
  233. package/dist/notifier/debouncer.d.ts +39 -0
  234. package/dist/notifier/debouncer.d.ts.map +1 -0
  235. package/dist/notifier/debouncer.js +123 -0
  236. package/dist/notifier/debouncer.js.map +1 -0
  237. package/dist/notifier/notification-consumer.d.ts +88 -0
  238. package/dist/notifier/notification-consumer.d.ts.map +1 -0
  239. package/dist/notifier/notification-consumer.js +186 -0
  240. package/dist/notifier/notification-consumer.js.map +1 -0
  241. package/dist/notifier/notifier.module.d.ts +9 -0
  242. package/dist/notifier/notifier.module.d.ts.map +1 -0
  243. package/dist/notifier/notifier.module.js +58 -0
  244. package/dist/notifier/notifier.module.js.map +1 -0
  245. package/dist/notifier/notifier.service.d.ts +40 -0
  246. package/dist/notifier/notifier.service.d.ts.map +1 -0
  247. package/dist/notifier/notifier.service.js +191 -0
  248. package/dist/notifier/notifier.service.js.map +1 -0
  249. package/dist/notifier/template.service.d.ts +42 -0
  250. package/dist/notifier/template.service.d.ts.map +1 -0
  251. package/dist/notifier/template.service.js +201 -0
  252. package/dist/notifier/template.service.js.map +1 -0
  253. package/dist/redis/redis.module.d.ts +3 -0
  254. package/dist/redis/redis.module.d.ts.map +1 -0
  255. package/dist/redis/redis.module.js +22 -0
  256. package/dist/redis/redis.module.js.map +1 -0
  257. package/dist/redis/redis.service.d.ts +19 -0
  258. package/dist/redis/redis.service.d.ts.map +1 -0
  259. package/dist/redis/redis.service.js +69 -0
  260. package/dist/redis/redis.service.js.map +1 -0
  261. package/dist/web/admin/admin-audit.controller.d.ts +7 -0
  262. package/dist/web/admin/admin-audit.controller.d.ts.map +1 -0
  263. package/dist/web/admin/admin-audit.controller.js +53 -0
  264. package/dist/web/admin/admin-audit.controller.js.map +1 -0
  265. package/dist/web/admin/admin-bot.controller.d.ts +79 -0
  266. package/dist/web/admin/admin-bot.controller.d.ts.map +1 -0
  267. package/dist/web/admin/admin-bot.controller.js +193 -0
  268. package/dist/web/admin/admin-bot.controller.js.map +1 -0
  269. package/dist/web/admin/admin-developer.controller.d.ts +52 -0
  270. package/dist/web/admin/admin-developer.controller.d.ts.map +1 -0
  271. package/dist/web/admin/admin-developer.controller.js +160 -0
  272. package/dist/web/admin/admin-developer.controller.js.map +1 -0
  273. package/dist/web/admin/admin-machine.controller.d.ts +64 -0
  274. package/dist/web/admin/admin-machine.controller.d.ts.map +1 -0
  275. package/dist/web/admin/admin-machine.controller.js +111 -0
  276. package/dist/web/admin/admin-machine.controller.js.map +1 -0
  277. package/dist/web/admin/admin-project.controller.d.ts +45 -0
  278. package/dist/web/admin/admin-project.controller.d.ts.map +1 -0
  279. package/dist/web/admin/admin-project.controller.js +207 -0
  280. package/dist/web/admin/admin-project.controller.js.map +1 -0
  281. package/dist/web/admin/admin-settings.controller.d.ts +18 -0
  282. package/dist/web/admin/admin-settings.controller.d.ts.map +1 -0
  283. package/dist/web/admin/admin-settings.controller.js +93 -0
  284. package/dist/web/admin/admin-settings.controller.js.map +1 -0
  285. package/dist/web/admin/admin-token.controller.d.ts +45 -0
  286. package/dist/web/admin/admin-token.controller.d.ts.map +1 -0
  287. package/dist/web/admin/admin-token.controller.js +182 -0
  288. package/dist/web/admin/admin-token.controller.js.map +1 -0
  289. package/dist/web/dashboard.controller.d.ts +16 -0
  290. package/dist/web/dashboard.controller.d.ts.map +1 -0
  291. package/dist/web/dashboard.controller.js +78 -0
  292. package/dist/web/dashboard.controller.js.map +1 -0
  293. package/dist/web/dashboard.service.d.ts +39 -0
  294. package/dist/web/dashboard.service.d.ts.map +1 -0
  295. package/dist/web/dashboard.service.js +234 -0
  296. package/dist/web/dashboard.service.js.map +1 -0
  297. package/dist/web/interaction.service.d.ts +42 -0
  298. package/dist/web/interaction.service.d.ts.map +1 -0
  299. package/dist/web/interaction.service.js +102 -0
  300. package/dist/web/interaction.service.js.map +1 -0
  301. package/dist/web/machine.controller.d.ts +102 -0
  302. package/dist/web/machine.controller.d.ts.map +1 -0
  303. package/dist/web/machine.controller.js +121 -0
  304. package/dist/web/machine.controller.js.map +1 -0
  305. package/dist/web/notification.controller.d.ts +22 -0
  306. package/dist/web/notification.controller.d.ts.map +1 -0
  307. package/dist/web/notification.controller.js +70 -0
  308. package/dist/web/notification.controller.js.map +1 -0
  309. package/dist/web/profile.controller.d.ts +70 -0
  310. package/dist/web/profile.controller.d.ts.map +1 -0
  311. package/dist/web/profile.controller.js +262 -0
  312. package/dist/web/profile.controller.js.map +1 -0
  313. package/dist/web/project.controller.d.ts +8 -0
  314. package/dist/web/project.controller.d.ts.map +1 -0
  315. package/dist/web/project.controller.js +54 -0
  316. package/dist/web/project.controller.js.map +1 -0
  317. package/dist/web/pty.gateway.d.ts +32 -0
  318. package/dist/web/pty.gateway.d.ts.map +1 -0
  319. package/dist/web/pty.gateway.js +358 -0
  320. package/dist/web/pty.gateway.js.map +1 -0
  321. package/dist/web/search.service.d.ts +34 -0
  322. package/dist/web/search.service.d.ts.map +1 -0
  323. package/dist/web/search.service.js +106 -0
  324. package/dist/web/search.service.js.map +1 -0
  325. package/dist/web/task.controller.d.ts +54 -0
  326. package/dist/web/task.controller.d.ts.map +1 -0
  327. package/dist/web/task.controller.js +266 -0
  328. package/dist/web/task.controller.js.map +1 -0
  329. package/dist/web/web.module.d.ts +3 -0
  330. package/dist/web/web.module.d.ts.map +1 -0
  331. package/dist/web/web.module.js +97 -0
  332. package/dist/web/web.module.js.map +1 -0
  333. package/dist/web/worker-channel.gateway.d.ts +45 -0
  334. package/dist/web/worker-channel.gateway.d.ts.map +1 -0
  335. package/dist/web/worker-channel.gateway.js +283 -0
  336. package/dist/web/worker-channel.gateway.js.map +1 -0
  337. package/dist/web/worker.controller.d.ts +14 -0
  338. package/dist/web/worker.controller.d.ts.map +1 -0
  339. package/dist/web/worker.controller.js +73 -0
  340. package/dist/web/worker.controller.js.map +1 -0
  341. package/dist/web/workspace.controller.d.ts +109 -0
  342. package/dist/web/workspace.controller.d.ts.map +1 -0
  343. package/dist/web/workspace.controller.js +386 -0
  344. package/dist/web/workspace.controller.js.map +1 -0
  345. package/package.json +61 -0
@@ -0,0 +1,287 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var SchedulerService_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.SchedulerService = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const bullmq_1 = require("bullmq");
16
+ const protocol_1 = require("@overlordai/protocol");
17
+ const redis_service_1 = require("../redis/redis.service");
18
+ const task_repository_1 = require("../database/repositories/task.repository");
19
+ const machine_repository_1 = require("../database/repositories/machine.repository");
20
+ const developer_repository_1 = require("../database/repositories/developer.repository");
21
+ const auth_service_1 = require("../auth/auth.service");
22
+ const machine_selector_1 = require("./machine-selector");
23
+ const worker_connection_manager_1 = require("./worker-connection.manager");
24
+ const QUEUE_NAME = 'task';
25
+ let SchedulerService = SchedulerService_1 = class SchedulerService {
26
+ redis;
27
+ taskRepo;
28
+ machineRepo;
29
+ machineSelector;
30
+ workerConnMgr;
31
+ authService;
32
+ developerRepo;
33
+ logger = new common_1.Logger(SchedulerService_1.name);
34
+ queue;
35
+ worker;
36
+ pollTimer = null;
37
+ constructor(redis, taskRepo, machineRepo, machineSelector, workerConnMgr, authService, developerRepo) {
38
+ this.redis = redis;
39
+ this.taskRepo = taskRepo;
40
+ this.machineRepo = machineRepo;
41
+ this.machineSelector = machineSelector;
42
+ this.workerConnMgr = workerConnMgr;
43
+ this.authService = authService;
44
+ this.developerRepo = developerRepo;
45
+ }
46
+ async onModuleInit() {
47
+ // Use the Redis URL to create fresh connections for BullMQ,
48
+ // avoiding ioredis version mismatch between the app and BullMQ's peer dep.
49
+ const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
50
+ this.queue = new bullmq_1.Queue(QUEUE_NAME, {
51
+ connection: { url: redisUrl, maxRetriesPerRequest: null },
52
+ defaultJobOptions: {
53
+ removeOnComplete: 100,
54
+ removeOnFail: 200,
55
+ attempts: 1,
56
+ },
57
+ });
58
+ this.worker = new bullmq_1.Worker(QUEUE_NAME, async (job) => {
59
+ await this.processJob(job.data);
60
+ }, {
61
+ connection: { url: redisUrl, maxRetriesPerRequest: null },
62
+ concurrency: 1, // SQLite single writer safety
63
+ });
64
+ this.worker.on('failed', (job, err) => {
65
+ this.logger.error(`Scheduler job ${job?.id} failed: ${err.message}`, err.stack);
66
+ });
67
+ // Start periodic polling for queued and suspended tasks
68
+ this.pollTimer = setInterval(() => {
69
+ this.pollQueuedTasks().catch((err) => this.logger.error(`Poll error: ${err.message}`, err.stack));
70
+ }, protocol_1.SCHEDULER_POLL_INTERVAL_MS);
71
+ // Run an initial poll immediately
72
+ this.pollQueuedTasks().catch((err) => this.logger.error(`Initial poll error: ${err.message}`, err.stack));
73
+ this.logger.log('Scheduler service initialized');
74
+ }
75
+ async onModuleDestroy() {
76
+ if (this.pollTimer) {
77
+ clearInterval(this.pollTimer);
78
+ this.pollTimer = null;
79
+ }
80
+ if (this.worker) {
81
+ await this.worker.close();
82
+ }
83
+ if (this.queue) {
84
+ await this.queue.close();
85
+ }
86
+ this.logger.log('Scheduler service destroyed');
87
+ }
88
+ /**
89
+ * Enqueue a task for immediate scheduling (used when a new task is created).
90
+ */
91
+ async enqueueTask(taskId) {
92
+ await this.queue.add('schedule', { taskId, type: 'schedule' }, {
93
+ jobId: `schedule-${taskId}-${Date.now()}`,
94
+ });
95
+ }
96
+ /**
97
+ * Enqueue a task for resume (used when a suspended task's machine comes back online).
98
+ */
99
+ async enqueueResume(taskId) {
100
+ await this.queue.add('resume', { taskId, type: 'resume' }, {
101
+ jobId: `resume-${taskId}-${Date.now()}`,
102
+ });
103
+ }
104
+ /**
105
+ * Poll for QUEUED tasks and enqueue them for processing.
106
+ * Also check SUSPENDED tasks whose machines are back online.
107
+ */
108
+ async pollQueuedTasks() {
109
+ // Admission control: check if we are at capacity
110
+ const activeCount = this.taskRepo.countActive();
111
+ if (activeCount >= protocol_1.MAX_CONCURRENT_TASKS) {
112
+ this.logger.debug(`At capacity: ${activeCount}/${protocol_1.MAX_CONCURRENT_TASKS} active tasks, skipping poll`);
113
+ return;
114
+ }
115
+ // Scan QUEUED tasks (oldest first, limited to SCHEDULER_SCAN_LIMIT)
116
+ const queuedTasks = this.taskRepo.findByStatus([protocol_1.TaskStatus.QUEUED]);
117
+ const toSchedule = queuedTasks.slice(0, protocol_1.SCHEDULER_SCAN_LIMIT);
118
+ for (const task of toSchedule) {
119
+ await this.queue.add('schedule', { taskId: task.id, type: 'schedule' }, {
120
+ jobId: `poll-schedule-${task.id}-${Date.now()}`,
121
+ });
122
+ }
123
+ // Check SUSPENDED tasks with online machines for resume
124
+ const suspendedTasks = this.taskRepo.findByStatus([protocol_1.TaskStatus.SUSPENDED]);
125
+ for (const task of suspendedTasks) {
126
+ if (!task.machineId) {
127
+ continue;
128
+ }
129
+ const machine = this.machineRepo.findById(task.machineId);
130
+ if (machine && machine.status === protocol_1.MachineStatus.ONLINE) {
131
+ await this.queue.add('resume', { taskId: task.id, type: 'resume' }, {
132
+ jobId: `poll-resume-${task.id}-${Date.now()}`,
133
+ });
134
+ }
135
+ }
136
+ }
137
+ /**
138
+ * Process a single scheduler job.
139
+ */
140
+ async processJob(data) {
141
+ const { taskId, type } = data;
142
+ const task = this.taskRepo.findById(taskId);
143
+ if (!task) {
144
+ this.logger.warn(`Task ${taskId} not found, skipping`);
145
+ return;
146
+ }
147
+ if (type === 'schedule') {
148
+ await this.processScheduleTask(task);
149
+ }
150
+ else if (type === 'resume') {
151
+ await this.processResumeTask(task);
152
+ }
153
+ }
154
+ /**
155
+ * Attempt to assign a QUEUED task to a machine and transition to ASSIGNED.
156
+ */
157
+ async processScheduleTask(task) {
158
+ // Re-check status (may have changed since enqueue)
159
+ if (task.status !== protocol_1.TaskStatus.QUEUED) {
160
+ this.logger.debug(`Task ${task.id} is no longer QUEUED (status=${task.status}), skipping`);
161
+ return;
162
+ }
163
+ // Admission control
164
+ const activeCount = this.taskRepo.countActive();
165
+ if (activeCount >= protocol_1.MAX_CONCURRENT_TASKS) {
166
+ this.logger.debug(`At capacity (${activeCount}/${protocol_1.MAX_CONCURRENT_TASKS}), keeping task ${task.id} QUEUED`);
167
+ return;
168
+ }
169
+ // Parse config snapshot to get agentType
170
+ let agentType = 'claude'; // default
171
+ let configSnapshot = null;
172
+ if (task.configSnapshot) {
173
+ try {
174
+ configSnapshot = JSON.parse(task.configSnapshot);
175
+ agentType = configSnapshot.agentType;
176
+ }
177
+ catch {
178
+ this.logger.warn(`Task ${task.id}: failed to parse configSnapshot, using default agentType`);
179
+ }
180
+ }
181
+ // Select a machine
182
+ const machine = this.machineSelector.select(agentType, undefined, // tags not stored on task; could be extended
183
+ task.machineId ?? undefined, // preferred machine if pre-set
184
+ task.projectKey);
185
+ if (!machine) {
186
+ this.logger.debug(`No suitable machine found for task ${task.id}, will retry next poll`);
187
+ return;
188
+ }
189
+ // Assign the task to the machine
190
+ const now = new Date().toISOString();
191
+ const updated = this.taskRepo.updateStatus(task.id, protocol_1.TaskStatus.ASSIGNED, task.revision, {
192
+ machineId: machine.id,
193
+ assignedAt: now,
194
+ });
195
+ if (!updated) {
196
+ this.logger.warn(`Task ${task.id}: CAS conflict during assignment (revision ${task.revision}), will retry`);
197
+ return;
198
+ }
199
+ this.logger.log(`Task ${task.id} assigned to machine ${machine.name} (${machine.id})`);
200
+ // Reload the task to get the updated revision after CAS
201
+ const assignedTask = this.taskRepo.findById(task.id);
202
+ if (!assignedTask) {
203
+ this.logger.error(`Task ${task.id} disappeared after assignment`);
204
+ return;
205
+ }
206
+ // Look up developer info for the execute frame
207
+ let gitName = 'unknown';
208
+ let gitEmail = 'unknown@unknown';
209
+ if (assignedTask.developerId) {
210
+ const developer = this.developerRepo.findById(assignedTask.developerId);
211
+ if (developer) {
212
+ gitName = developer.gitName;
213
+ gitEmail = developer.gitEmail;
214
+ }
215
+ else {
216
+ this.logger.warn(`Task ${task.id}: developer ${assignedTask.developerId} not found, using defaults`);
217
+ }
218
+ }
219
+ // Build the ExecuteTaskFrame
220
+ const msgId = this.workerConnMgr.generateMsgId();
221
+ const channelToken = this.authService.signChannelToken(task.id, 'worker');
222
+ const executeFrame = {
223
+ type: 'execute',
224
+ msgId,
225
+ taskId: task.id,
226
+ description: assignedTask.description,
227
+ projectKey: assignedTask.projectKey,
228
+ configSnapshot: configSnapshot ?? {},
229
+ developer: { gitName, gitEmail },
230
+ channelToken,
231
+ };
232
+ // Send the frame and wait for ack
233
+ try {
234
+ await this.workerConnMgr.sendWithAck(machine.id, executeFrame, protocol_1.EXECUTE_ACK_TIMEOUT_MS);
235
+ // Ack received — transition task to RUNNING
236
+ const runningUpdated = this.taskRepo.updateStatus(assignedTask.id, protocol_1.TaskStatus.RUNNING, assignedTask.revision, { startedAt: new Date().toISOString() });
237
+ if (!runningUpdated) {
238
+ this.logger.warn(`Task ${task.id}: CAS conflict transitioning to RUNNING (revision ${assignedTask.revision})`);
239
+ return;
240
+ }
241
+ this.logger.log(`Task ${task.id} is now RUNNING on machine ${machine.id}`);
242
+ }
243
+ catch (err) {
244
+ // Ack timeout or send failure — leave task as ASSIGNED for retry
245
+ this.logger.error(`Task ${task.id}: failed to send ExecuteTaskFrame to machine ${machine.id}: ${err instanceof Error ? err.message : String(err)}`);
246
+ }
247
+ }
248
+ /**
249
+ * Attempt to resume a SUSPENDED task on its assigned machine.
250
+ */
251
+ async processResumeTask(task) {
252
+ if (task.status !== protocol_1.TaskStatus.SUSPENDED) {
253
+ this.logger.debug(`Task ${task.id} is no longer SUSPENDED (status=${task.status}), skipping resume`);
254
+ return;
255
+ }
256
+ if (!task.machineId) {
257
+ this.logger.warn(`Suspended task ${task.id} has no machineId, skipping`);
258
+ return;
259
+ }
260
+ const machine = this.machineRepo.findById(task.machineId);
261
+ if (!machine || machine.status !== protocol_1.MachineStatus.ONLINE) {
262
+ this.logger.debug(`Machine ${task.machineId} for suspended task ${task.id} is not online, skipping`);
263
+ return;
264
+ }
265
+ // Transition back to RUNNING
266
+ const updated = this.taskRepo.updateStatus(task.id, protocol_1.TaskStatus.RUNNING, task.revision);
267
+ if (!updated) {
268
+ this.logger.warn(`Task ${task.id}: CAS conflict during resume (revision ${task.revision}), will retry`);
269
+ return;
270
+ }
271
+ this.logger.log(`Task ${task.id} resumed on machine ${machine.name} (${machine.id})`);
272
+ // Note: The actual "resume" frame is sent to the worker via the WebSocket
273
+ // channel gateway, which watches for status transitions.
274
+ }
275
+ };
276
+ exports.SchedulerService = SchedulerService;
277
+ exports.SchedulerService = SchedulerService = SchedulerService_1 = __decorate([
278
+ (0, common_1.Injectable)(),
279
+ __metadata("design:paramtypes", [redis_service_1.RedisService,
280
+ task_repository_1.TaskRepository,
281
+ machine_repository_1.MachineRepository,
282
+ machine_selector_1.MachineSelector,
283
+ worker_connection_manager_1.WorkerConnectionManager,
284
+ auth_service_1.AuthService,
285
+ developer_repository_1.DeveloperRepository])
286
+ ], SchedulerService);
287
+ //# sourceMappingURL=scheduler.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.service.js","sourceRoot":"","sources":["../../src/dispatcher/scheduler.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { TaskStatus } from '@overlordai/protocol';
2
+ export declare class TaskStateMachine {
3
+ /**
4
+ * Returns true if transitioning from `from` to `to` is a valid state change.
5
+ */
6
+ static canTransition(from: TaskStatus, to: TaskStatus): boolean;
7
+ /**
8
+ * Throws an HttpException (409 Conflict) if the transition is not valid.
9
+ */
10
+ static assertTransition(from: TaskStatus, to: TaskStatus): void;
11
+ /**
12
+ * Returns true if the given status is terminal (no further transitions allowed).
13
+ */
14
+ static isTerminal(status: TaskStatus): boolean;
15
+ }
16
+ //# sourceMappingURL=state-machine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../../src/dispatcher/state-machine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAgDlD,qBAAa,gBAAgB;IAC3B;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,GAAG,OAAO;IAQ/D;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI;IAS/D;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;CAG/C"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TaskStateMachine = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const protocol_1 = require("@overlordai/protocol");
6
+ const TRANSITIONS = new Map([
7
+ [
8
+ protocol_1.TaskStatus.QUEUED,
9
+ new Set([protocol_1.TaskStatus.ASSIGNED, protocol_1.TaskStatus.CANCELLED]),
10
+ ],
11
+ [
12
+ protocol_1.TaskStatus.ASSIGNED,
13
+ new Set([protocol_1.TaskStatus.RUNNING, protocol_1.TaskStatus.FAILED, protocol_1.TaskStatus.CANCELLED]),
14
+ ],
15
+ [
16
+ protocol_1.TaskStatus.RUNNING,
17
+ new Set([
18
+ protocol_1.TaskStatus.COMPLETED,
19
+ protocol_1.TaskStatus.FAILED,
20
+ protocol_1.TaskStatus.CANCELLED,
21
+ protocol_1.TaskStatus.SUSPENDED,
22
+ ]),
23
+ ],
24
+ [
25
+ protocol_1.TaskStatus.SUSPENDED,
26
+ new Set([
27
+ protocol_1.TaskStatus.RUNNING,
28
+ protocol_1.TaskStatus.COMPLETED,
29
+ protocol_1.TaskStatus.FAILED,
30
+ protocol_1.TaskStatus.CANCELLED,
31
+ ]),
32
+ ],
33
+ [
34
+ protocol_1.TaskStatus.FAILED,
35
+ new Set([protocol_1.TaskStatus.QUEUED, protocol_1.TaskStatus.COMPLETED]), // retry or reconnect-completed
36
+ ],
37
+ [
38
+ protocol_1.TaskStatus.COMPLETED,
39
+ new Set(), // terminal
40
+ ],
41
+ [
42
+ protocol_1.TaskStatus.CANCELLED,
43
+ new Set(), // terminal
44
+ ],
45
+ ]);
46
+ const TERMINAL_STATUSES = new Set([
47
+ protocol_1.TaskStatus.COMPLETED,
48
+ protocol_1.TaskStatus.CANCELLED,
49
+ ]);
50
+ class TaskStateMachine {
51
+ /**
52
+ * Returns true if transitioning from `from` to `to` is a valid state change.
53
+ */
54
+ static canTransition(from, to) {
55
+ const allowed = TRANSITIONS.get(from);
56
+ if (!allowed) {
57
+ return false;
58
+ }
59
+ return allowed.has(to);
60
+ }
61
+ /**
62
+ * Throws an HttpException (409 Conflict) if the transition is not valid.
63
+ */
64
+ static assertTransition(from, to) {
65
+ if (!TaskStateMachine.canTransition(from, to)) {
66
+ throw new common_1.HttpException(`Invalid task state transition: ${from} → ${to}`, common_1.HttpStatus.CONFLICT);
67
+ }
68
+ }
69
+ /**
70
+ * Returns true if the given status is terminal (no further transitions allowed).
71
+ */
72
+ static isTerminal(status) {
73
+ return TERMINAL_STATUSES.has(status);
74
+ }
75
+ }
76
+ exports.TaskStateMachine = TaskStateMachine;
77
+ //# sourceMappingURL=state-machine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-machine.js","sourceRoot":"","sources":["../../src/dispatcher/state-machine.ts"],"names":[],"mappings":";;;AAAA,2CAA2D;AAC3D,mDAAkD;AAElD,MAAM,WAAW,GAAqD,IAAI,GAAG,CAAC;IAC5E;QACE,qBAAU,CAAC,MAAM;QACjB,IAAI,GAAG,CAAC,CAAC,qBAAU,CAAC,QAAQ,EAAE,qBAAU,CAAC,SAAS,CAAC,CAAC;KACrD;IACD;QACE,qBAAU,CAAC,QAAQ;QACnB,IAAI,GAAG,CAAC,CAAC,qBAAU,CAAC,OAAO,EAAE,qBAAU,CAAC,MAAM,EAAE,qBAAU,CAAC,SAAS,CAAC,CAAC;KACvE;IACD;QACE,qBAAU,CAAC,OAAO;QAClB,IAAI,GAAG,CAAC;YACN,qBAAU,CAAC,SAAS;YACpB,qBAAU,CAAC,MAAM;YACjB,qBAAU,CAAC,SAAS;YACpB,qBAAU,CAAC,SAAS;SACrB,CAAC;KACH;IACD;QACE,qBAAU,CAAC,SAAS;QACpB,IAAI,GAAG,CAAC;YACN,qBAAU,CAAC,OAAO;YAClB,qBAAU,CAAC,SAAS;YACpB,qBAAU,CAAC,MAAM;YACjB,qBAAU,CAAC,SAAS;SACrB,CAAC;KACH;IACD;QACE,qBAAU,CAAC,MAAM;QACjB,IAAI,GAAG,CAAC,CAAC,qBAAU,CAAC,MAAM,EAAE,qBAAU,CAAC,SAAS,CAAC,CAAC,EAAE,+BAA+B;KACpF;IACD;QACE,qBAAU,CAAC,SAAS;QACpB,IAAI,GAAG,EAAc,EAAE,WAAW;KACnC;IACD;QACE,qBAAU,CAAC,SAAS;QACpB,IAAI,GAAG,EAAc,EAAE,WAAW;KACnC;CACF,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAA4B,IAAI,GAAG,CAAC;IACzD,qBAAU,CAAC,SAAS;IACpB,qBAAU,CAAC,SAAS;CACrB,CAAC,CAAC;AAEH,MAAa,gBAAgB;IAC3B;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,IAAgB,EAAE,EAAc;QACnD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAgB,EAAE,EAAc;QACtD,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,sBAAa,CACrB,kCAAkC,IAAI,MAAM,EAAE,EAAE,EAChD,mBAAU,CAAC,QAAQ,CACpB,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,MAAkB;QAClC,OAAO,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;CACF;AA9BD,4CA8BC"}
@@ -0,0 +1,50 @@
1
+ import { OnModuleDestroy, OnModuleInit } from '@nestjs/common';
2
+ import type { TaskLogType } from '@overlordai/protocol';
3
+ import { DatabaseService } from '../database/database.service';
4
+ export declare class TaskLogBatcher implements OnModuleInit, OnModuleDestroy {
5
+ private readonly db;
6
+ private readonly logger;
7
+ private buffer;
8
+ private timer;
9
+ private retentionTimer;
10
+ constructor(db: DatabaseService);
11
+ /** 24 hours in milliseconds. */
12
+ private static readonly RETENTION_CLEANUP_INTERVAL_MS;
13
+ onModuleInit(): void;
14
+ onModuleDestroy(): void;
15
+ /**
16
+ * Add a log entry to the buffer. The message is sanitized to remove sensitive
17
+ * patterns before buffering. If the buffer reaches TASK_LOGS_BATCH_SIZE, the
18
+ * buffer is flushed immediately.
19
+ */
20
+ add(taskId: number, type: TaskLogType, message: string): void;
21
+ /**
22
+ * Flush all buffered log entries to the database in a single transaction.
23
+ */
24
+ flush(): void;
25
+ /**
26
+ * Retrieve historical log lines for a task from the database.
27
+ * Flushes any buffered entries first so the result is up-to-date.
28
+ */
29
+ getTaskLogs(taskId: number, limit?: number, offset?: number): string[];
30
+ /**
31
+ * Retrieve structured log entries for a task with filtering and pagination.
32
+ * Flushes any buffered entries first so the result is up-to-date.
33
+ */
34
+ getStructuredLogs(taskId: number, opts: {
35
+ limit: number;
36
+ offset: number;
37
+ type?: string;
38
+ search?: string;
39
+ }): {
40
+ events: Array<{
41
+ id: number;
42
+ type: string;
43
+ message: string;
44
+ timestamp: string;
45
+ }>;
46
+ total: number;
47
+ };
48
+ cleanupRetention(): void;
49
+ }
50
+ //# sourceMappingURL=task-log-batcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-log-batcher.d.ts","sourceRoot":"","sources":["../../src/dispatcher/task-log-batcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAMnF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAU/D,qBACa,cAAe,YAAW,YAAY,EAAE,eAAe;IAMtD,OAAO,CAAC,QAAQ,CAAC,EAAE;IAL/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmC;IAC1D,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,cAAc,CAAkB;gBAEX,EAAE,EAAE,eAAe;IAEhD,gCAAgC;IAChC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,6BAA6B,CAAuB;IAE5E,YAAY,IAAI,IAAI;IAmBpB,eAAe,IAAI,IAAI;IAOvB;;;;OAIG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAc7D;;OAEG;IACH,KAAK,IAAI,IAAI;IAsDb;;;OAGG;IACH,WAAW,CACT,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAY,EACnB,MAAM,GAAE,MAAU,GACjB,MAAM,EAAE;IAiBX;;;OAGG;IACH,iBAAiB,CACf,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACtE;QACD,MAAM,EAAE,KAAK,CAAC;YACZ,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,MAAM,CAAC;YAChB,SAAS,EAAE,MAAM,CAAC;SACnB,CAAC,CAAC;QACH,KAAK,EAAE,MAAM,CAAC;KACf;IA4CD,gBAAgB,IAAI,IAAI;CAyBzB"}
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var TaskLogBatcher_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.TaskLogBatcher = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const protocol_1 = require("@overlordai/protocol");
16
+ const database_service_1 = require("../database/database.service");
17
+ const sensitive_filter_1 = require("../common/sensitive-filter");
18
+ let TaskLogBatcher = class TaskLogBatcher {
19
+ static { TaskLogBatcher_1 = this; }
20
+ db;
21
+ logger = new common_1.Logger(TaskLogBatcher_1.name);
22
+ buffer = [];
23
+ timer;
24
+ retentionTimer;
25
+ constructor(db) {
26
+ this.db = db;
27
+ }
28
+ /** 24 hours in milliseconds. */
29
+ static RETENTION_CLEANUP_INTERVAL_MS = 24 * 60 * 60 * 1000;
30
+ onModuleInit() {
31
+ this.timer = setInterval(() => this.flush(), protocol_1.TASK_LOGS_BATCH_INTERVAL_MS);
32
+ // Schedule daily retention cleanup
33
+ this.retentionTimer = setInterval(() => this.cleanupRetention(), TaskLogBatcher_1.RETENTION_CLEANUP_INTERVAL_MS);
34
+ // Run an initial retention cleanup on startup
35
+ this.cleanupRetention();
36
+ this.logger.log(`Task log batcher started (flush every ${protocol_1.TASK_LOGS_BATCH_INTERVAL_MS}ms or ${protocol_1.TASK_LOGS_BATCH_SIZE} entries)`);
37
+ }
38
+ onModuleDestroy() {
39
+ clearInterval(this.timer);
40
+ clearInterval(this.retentionTimer);
41
+ // Final flush on shutdown
42
+ this.flush();
43
+ }
44
+ /**
45
+ * Add a log entry to the buffer. The message is sanitized to remove sensitive
46
+ * patterns before buffering. If the buffer reaches TASK_LOGS_BATCH_SIZE, the
47
+ * buffer is flushed immediately.
48
+ */
49
+ add(taskId, type, message) {
50
+ const sanitizedMessage = (0, sensitive_filter_1.sanitize)(message);
51
+ this.buffer.push({
52
+ taskId,
53
+ type,
54
+ message: sanitizedMessage,
55
+ timestamp: new Date().toISOString(),
56
+ });
57
+ if (this.buffer.length >= protocol_1.TASK_LOGS_BATCH_SIZE) {
58
+ this.flush();
59
+ }
60
+ }
61
+ /**
62
+ * Flush all buffered log entries to the database in a single transaction.
63
+ */
64
+ flush() {
65
+ if (this.buffer.length === 0) {
66
+ return;
67
+ }
68
+ const entries = this.buffer.splice(0);
69
+ try {
70
+ const stmt = this.db.getDb().prepare(`
71
+ INSERT INTO task_logs (task_id, type, message, timestamp)
72
+ VALUES (@taskId, @type, @message, @timestamp)
73
+ `);
74
+ const insertBatch = this.db.getDb().transaction(() => {
75
+ for (const entry of entries) {
76
+ stmt.run({
77
+ taskId: entry.taskId,
78
+ type: entry.type,
79
+ message: entry.message,
80
+ timestamp: entry.timestamp,
81
+ });
82
+ }
83
+ });
84
+ insertBatch();
85
+ this.logger.debug(`Flushed ${entries.length} task log entries`);
86
+ }
87
+ catch (err) {
88
+ this.logger.error(`Failed to flush ${entries.length} task log entries`, err instanceof Error ? err.stack : String(err));
89
+ // Re-add entries to buffer so they are not lost, but cap at 10000
90
+ // to prevent unbounded memory growth under persistent DB errors
91
+ const MAX_BUFFER_SIZE = 10_000;
92
+ if (this.buffer.length + entries.length > MAX_BUFFER_SIZE) {
93
+ const spaceAvailable = MAX_BUFFER_SIZE - this.buffer.length;
94
+ if (spaceAvailable > 0) {
95
+ // Keep the newest entries (from the end of the failed batch)
96
+ const kept = entries.slice(entries.length - spaceAvailable);
97
+ this.buffer.unshift(...kept);
98
+ this.logger.warn(`Buffer limit reached (${MAX_BUFFER_SIZE}): dropped ${entries.length - spaceAvailable} oldest log entries`);
99
+ }
100
+ else {
101
+ this.logger.warn(`Buffer limit reached (${MAX_BUFFER_SIZE}): dropped all ${entries.length} failed flush entries`);
102
+ }
103
+ }
104
+ else {
105
+ this.buffer.unshift(...entries);
106
+ }
107
+ }
108
+ }
109
+ /**
110
+ * Retrieve historical log lines for a task from the database.
111
+ * Flushes any buffered entries first so the result is up-to-date.
112
+ */
113
+ getTaskLogs(taskId, limit = 100, offset = 0) {
114
+ // Flush buffer so any pending entries for this task are persisted
115
+ this.flush();
116
+ const rows = this.db
117
+ .getDb()
118
+ .prepare(`SELECT message FROM task_logs
119
+ WHERE task_id = @taskId
120
+ ORDER BY id ASC
121
+ LIMIT @limit OFFSET @offset`)
122
+ .all({ taskId, limit, offset });
123
+ return rows.map((r) => r.message);
124
+ }
125
+ /**
126
+ * Retrieve structured log entries for a task with filtering and pagination.
127
+ * Flushes any buffered entries first so the result is up-to-date.
128
+ */
129
+ getStructuredLogs(taskId, opts) {
130
+ // Flush buffer so any pending entries for this task are persisted
131
+ this.flush();
132
+ const db = this.db.getDb();
133
+ let whereClause = 'WHERE task_id = @taskId';
134
+ const params = { taskId };
135
+ if (opts.type) {
136
+ whereClause += ' AND type = @type';
137
+ params.type = opts.type;
138
+ }
139
+ if (opts.search) {
140
+ whereClause += ' AND message LIKE @search';
141
+ params.search = `%${opts.search}%`;
142
+ }
143
+ const countRow = db
144
+ .prepare(`SELECT COUNT(*) as count FROM task_logs ${whereClause}`)
145
+ .get(params);
146
+ const rows = db
147
+ .prepare(`SELECT id, type, message, timestamp FROM task_logs ${whereClause} ORDER BY id DESC LIMIT @limit OFFSET @offset`)
148
+ .all({ ...params, limit: opts.limit, offset: opts.offset });
149
+ return {
150
+ events: rows.map((r) => ({
151
+ id: r.id,
152
+ type: r.type,
153
+ message: r.message,
154
+ timestamp: r.timestamp,
155
+ })),
156
+ total: countRow.count,
157
+ };
158
+ }
159
+ cleanupRetention() {
160
+ const cutoffDate = new Date();
161
+ cutoffDate.setDate(cutoffDate.getDate() - protocol_1.TASK_LOGS_RETENTION_DAYS);
162
+ const cutoffIso = cutoffDate.toISOString();
163
+ try {
164
+ const result = this.db.getDb().prepare(`
165
+ DELETE FROM task_logs
166
+ WHERE timestamp < @cutoff
167
+ AND task_id IN (
168
+ SELECT id FROM tasks
169
+ WHERE status IN ('COMPLETED', 'FAILED', 'CANCELLED')
170
+ )
171
+ `).run({ cutoff: cutoffIso });
172
+ this.logger.log(`Retention cleanup: deleted ${result.changes} task log entries older than ${protocol_1.TASK_LOGS_RETENTION_DAYS} days`);
173
+ }
174
+ catch (err) {
175
+ this.logger.error('Failed to run task log retention cleanup', err instanceof Error ? err.stack : String(err));
176
+ }
177
+ }
178
+ };
179
+ exports.TaskLogBatcher = TaskLogBatcher;
180
+ exports.TaskLogBatcher = TaskLogBatcher = TaskLogBatcher_1 = __decorate([
181
+ (0, common_1.Injectable)(),
182
+ __metadata("design:paramtypes", [database_service_1.DatabaseService])
183
+ ], TaskLogBatcher);
184
+ //# sourceMappingURL=task-log-batcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-log-batcher.js","sourceRoot":"","sources":["../../src/dispatcher/task-log-batcher.ts"],"names":[],"mappings":"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"}