@generacy-ai/orchestrator 0.0.0-preview-20260304013206

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 (274) hide show
  1. package/LICENSE +191 -0
  2. package/dist/auth/api-key.d.ts +63 -0
  3. package/dist/auth/api-key.d.ts.map +1 -0
  4. package/dist/auth/api-key.js +102 -0
  5. package/dist/auth/api-key.js.map +1 -0
  6. package/dist/auth/github-oauth.d.ts +29 -0
  7. package/dist/auth/github-oauth.d.ts.map +1 -0
  8. package/dist/auth/github-oauth.js +136 -0
  9. package/dist/auth/github-oauth.js.map +1 -0
  10. package/dist/auth/index.d.ts +5 -0
  11. package/dist/auth/index.d.ts.map +1 -0
  12. package/dist/auth/index.js +9 -0
  13. package/dist/auth/index.js.map +1 -0
  14. package/dist/auth/jwt.d.ts +34 -0
  15. package/dist/auth/jwt.d.ts.map +1 -0
  16. package/dist/auth/jwt.js +74 -0
  17. package/dist/auth/jwt.js.map +1 -0
  18. package/dist/auth/middleware.d.ts +43 -0
  19. package/dist/auth/middleware.d.ts.map +1 -0
  20. package/dist/auth/middleware.js +101 -0
  21. package/dist/auth/middleware.js.map +1 -0
  22. package/dist/config/index.d.ts +3 -0
  23. package/dist/config/index.d.ts.map +1 -0
  24. package/dist/config/index.js +5 -0
  25. package/dist/config/index.js.map +1 -0
  26. package/dist/config/loader.d.ts +21 -0
  27. package/dist/config/loader.d.ts.map +1 -0
  28. package/dist/config/loader.js +295 -0
  29. package/dist/config/loader.js.map +1 -0
  30. package/dist/config/schema.d.ts +733 -0
  31. package/dist/config/schema.d.ts.map +1 -0
  32. package/dist/config/schema.js +174 -0
  33. package/dist/config/schema.js.map +1 -0
  34. package/dist/index.d.ts +24 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +33 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/middleware/error-handler.d.ts +30 -0
  39. package/dist/middleware/error-handler.d.ts.map +1 -0
  40. package/dist/middleware/error-handler.js +173 -0
  41. package/dist/middleware/error-handler.js.map +1 -0
  42. package/dist/middleware/index.d.ts +4 -0
  43. package/dist/middleware/index.d.ts.map +1 -0
  44. package/dist/middleware/index.js +4 -0
  45. package/dist/middleware/index.js.map +1 -0
  46. package/dist/middleware/rate-limit.d.ts +32 -0
  47. package/dist/middleware/rate-limit.d.ts.map +1 -0
  48. package/dist/middleware/rate-limit.js +92 -0
  49. package/dist/middleware/rate-limit.js.map +1 -0
  50. package/dist/middleware/request-logger.d.ts +31 -0
  51. package/dist/middleware/request-logger.d.ts.map +1 -0
  52. package/dist/middleware/request-logger.js +89 -0
  53. package/dist/middleware/request-logger.js.map +1 -0
  54. package/dist/routes/agents.d.ts +7 -0
  55. package/dist/routes/agents.d.ts.map +1 -0
  56. package/dist/routes/agents.js +78 -0
  57. package/dist/routes/agents.js.map +1 -0
  58. package/dist/routes/dispatch.d.ts +8 -0
  59. package/dist/routes/dispatch.d.ts.map +1 -0
  60. package/dist/routes/dispatch.js +46 -0
  61. package/dist/routes/dispatch.js.map +1 -0
  62. package/dist/routes/events.d.ts +14 -0
  63. package/dist/routes/events.d.ts.map +1 -0
  64. package/dist/routes/events.js +240 -0
  65. package/dist/routes/events.js.map +1 -0
  66. package/dist/routes/health.d.ts +14 -0
  67. package/dist/routes/health.d.ts.map +1 -0
  68. package/dist/routes/health.js +132 -0
  69. package/dist/routes/health.js.map +1 -0
  70. package/dist/routes/index.d.ts +36 -0
  71. package/dist/routes/index.d.ts.map +1 -0
  72. package/dist/routes/index.js +34 -0
  73. package/dist/routes/index.js.map +1 -0
  74. package/dist/routes/integrations.d.ts +34 -0
  75. package/dist/routes/integrations.d.ts.map +1 -0
  76. package/dist/routes/integrations.js +81 -0
  77. package/dist/routes/integrations.js.map +1 -0
  78. package/dist/routes/metrics.d.ts +31 -0
  79. package/dist/routes/metrics.d.ts.map +1 -0
  80. package/dist/routes/metrics.js +157 -0
  81. package/dist/routes/metrics.js.map +1 -0
  82. package/dist/routes/pr-webhooks.d.ts +15 -0
  83. package/dist/routes/pr-webhooks.d.ts.map +1 -0
  84. package/dist/routes/pr-webhooks.js +114 -0
  85. package/dist/routes/pr-webhooks.js.map +1 -0
  86. package/dist/routes/queue.d.ts +7 -0
  87. package/dist/routes/queue.d.ts.map +1 -0
  88. package/dist/routes/queue.js +94 -0
  89. package/dist/routes/queue.js.map +1 -0
  90. package/dist/routes/webhooks.d.ts +15 -0
  91. package/dist/routes/webhooks.d.ts.map +1 -0
  92. package/dist/routes/webhooks.js +117 -0
  93. package/dist/routes/webhooks.js.map +1 -0
  94. package/dist/routes/workflows.d.ts +7 -0
  95. package/dist/routes/workflows.d.ts.map +1 -0
  96. package/dist/routes/workflows.js +138 -0
  97. package/dist/routes/workflows.js.map +1 -0
  98. package/dist/server.d.ts +35 -0
  99. package/dist/server.d.ts.map +1 -0
  100. package/dist/server.js +264 -0
  101. package/dist/server.js.map +1 -0
  102. package/dist/services/agent-registry.d.ts +89 -0
  103. package/dist/services/agent-registry.d.ts.map +1 -0
  104. package/dist/services/agent-registry.js +173 -0
  105. package/dist/services/agent-registry.js.map +1 -0
  106. package/dist/services/epic-completion-monitor-service.d.ts +69 -0
  107. package/dist/services/epic-completion-monitor-service.d.ts.map +1 -0
  108. package/dist/services/epic-completion-monitor-service.js +200 -0
  109. package/dist/services/epic-completion-monitor-service.js.map +1 -0
  110. package/dist/services/identity.d.ts +41 -0
  111. package/dist/services/identity.d.ts.map +1 -0
  112. package/dist/services/identity.js +91 -0
  113. package/dist/services/identity.js.map +1 -0
  114. package/dist/services/index.d.ts +13 -0
  115. package/dist/services/index.d.ts.map +1 -0
  116. package/dist/services/index.js +13 -0
  117. package/dist/services/index.js.map +1 -0
  118. package/dist/services/label-monitor-service.d.ts +95 -0
  119. package/dist/services/label-monitor-service.d.ts.map +1 -0
  120. package/dist/services/label-monitor-service.js +414 -0
  121. package/dist/services/label-monitor-service.js.map +1 -0
  122. package/dist/services/label-sync-service.d.ts +76 -0
  123. package/dist/services/label-sync-service.d.ts.map +1 -0
  124. package/dist/services/label-sync-service.js +108 -0
  125. package/dist/services/label-sync-service.js.map +1 -0
  126. package/dist/services/phase-tracker-service.d.ts +32 -0
  127. package/dist/services/phase-tracker-service.d.ts.map +1 -0
  128. package/dist/services/phase-tracker-service.js +82 -0
  129. package/dist/services/phase-tracker-service.js.map +1 -0
  130. package/dist/services/pr-feedback-monitor-service.d.ts +86 -0
  131. package/dist/services/pr-feedback-monitor-service.d.ts.map +1 -0
  132. package/dist/services/pr-feedback-monitor-service.js +423 -0
  133. package/dist/services/pr-feedback-monitor-service.js.map +1 -0
  134. package/dist/services/queue-service.d.ts +62 -0
  135. package/dist/services/queue-service.d.ts.map +1 -0
  136. package/dist/services/queue-service.js +147 -0
  137. package/dist/services/queue-service.js.map +1 -0
  138. package/dist/services/redis-queue-adapter.d.ts +35 -0
  139. package/dist/services/redis-queue-adapter.d.ts.map +1 -0
  140. package/dist/services/redis-queue-adapter.js +218 -0
  141. package/dist/services/redis-queue-adapter.js.map +1 -0
  142. package/dist/services/smee-receiver.d.ts +87 -0
  143. package/dist/services/smee-receiver.d.ts.map +1 -0
  144. package/dist/services/smee-receiver.js +225 -0
  145. package/dist/services/smee-receiver.js.map +1 -0
  146. package/dist/services/webhook-setup-service.d.ts +253 -0
  147. package/dist/services/webhook-setup-service.d.ts.map +1 -0
  148. package/dist/services/webhook-setup-service.js +369 -0
  149. package/dist/services/webhook-setup-service.js.map +1 -0
  150. package/dist/services/worker-dispatcher.d.ts +57 -0
  151. package/dist/services/worker-dispatcher.d.ts.map +1 -0
  152. package/dist/services/worker-dispatcher.js +211 -0
  153. package/dist/services/worker-dispatcher.js.map +1 -0
  154. package/dist/services/workflow-service.d.ts +65 -0
  155. package/dist/services/workflow-service.d.ts.map +1 -0
  156. package/dist/services/workflow-service.js +164 -0
  157. package/dist/services/workflow-service.js.map +1 -0
  158. package/dist/sse/events.d.ts +50 -0
  159. package/dist/sse/events.d.ts.map +1 -0
  160. package/dist/sse/events.js +152 -0
  161. package/dist/sse/events.js.map +1 -0
  162. package/dist/sse/index.d.ts +4 -0
  163. package/dist/sse/index.d.ts.map +1 -0
  164. package/dist/sse/index.js +7 -0
  165. package/dist/sse/index.js.map +1 -0
  166. package/dist/sse/stream.d.ts +109 -0
  167. package/dist/sse/stream.d.ts.map +1 -0
  168. package/dist/sse/stream.js +239 -0
  169. package/dist/sse/stream.js.map +1 -0
  170. package/dist/sse/subscriptions.d.ts +91 -0
  171. package/dist/sse/subscriptions.d.ts.map +1 -0
  172. package/dist/sse/subscriptions.js +299 -0
  173. package/dist/sse/subscriptions.js.map +1 -0
  174. package/dist/types/api.d.ts +651 -0
  175. package/dist/types/api.d.ts.map +1 -0
  176. package/dist/types/api.js +169 -0
  177. package/dist/types/api.js.map +1 -0
  178. package/dist/types/index.d.ts +6 -0
  179. package/dist/types/index.d.ts.map +1 -0
  180. package/dist/types/index.js +27 -0
  181. package/dist/types/index.js.map +1 -0
  182. package/dist/types/monitor.d.ts +243 -0
  183. package/dist/types/monitor.d.ts.map +1 -0
  184. package/dist/types/monitor.js +2 -0
  185. package/dist/types/monitor.js.map +1 -0
  186. package/dist/types/problem-details.d.ts +63 -0
  187. package/dist/types/problem-details.d.ts.map +1 -0
  188. package/dist/types/problem-details.js +37 -0
  189. package/dist/types/problem-details.js.map +1 -0
  190. package/dist/types/sse.d.ts +224 -0
  191. package/dist/types/sse.d.ts.map +1 -0
  192. package/dist/types/sse.js +103 -0
  193. package/dist/types/sse.js.map +1 -0
  194. package/dist/types/webhook.d.ts +59 -0
  195. package/dist/types/webhook.d.ts.map +1 -0
  196. package/dist/types/webhook.js +2 -0
  197. package/dist/types/webhook.js.map +1 -0
  198. package/dist/utils/correlation.d.ts +30 -0
  199. package/dist/utils/correlation.d.ts.map +1 -0
  200. package/dist/utils/correlation.js +34 -0
  201. package/dist/utils/correlation.js.map +1 -0
  202. package/dist/utils/index.d.ts +3 -0
  203. package/dist/utils/index.d.ts.map +1 -0
  204. package/dist/utils/index.js +3 -0
  205. package/dist/utils/index.js.map +1 -0
  206. package/dist/utils/shutdown.d.ts +28 -0
  207. package/dist/utils/shutdown.d.ts.map +1 -0
  208. package/dist/utils/shutdown.js +86 -0
  209. package/dist/utils/shutdown.js.map +1 -0
  210. package/dist/worker/claude-cli-worker.d.ts +61 -0
  211. package/dist/worker/claude-cli-worker.d.ts.map +1 -0
  212. package/dist/worker/claude-cli-worker.js +330 -0
  213. package/dist/worker/claude-cli-worker.js.map +1 -0
  214. package/dist/worker/cli-spawner.d.ts +42 -0
  215. package/dist/worker/cli-spawner.d.ts.map +1 -0
  216. package/dist/worker/cli-spawner.js +183 -0
  217. package/dist/worker/cli-spawner.js.map +1 -0
  218. package/dist/worker/config.d.ts +76 -0
  219. package/dist/worker/config.d.ts.map +1 -0
  220. package/dist/worker/config.js +39 -0
  221. package/dist/worker/config.js.map +1 -0
  222. package/dist/worker/epic-post-tasks.d.ts +73 -0
  223. package/dist/worker/epic-post-tasks.d.ts.map +1 -0
  224. package/dist/worker/epic-post-tasks.js +266 -0
  225. package/dist/worker/epic-post-tasks.js.map +1 -0
  226. package/dist/worker/gate-checker.d.ts +22 -0
  227. package/dist/worker/gate-checker.d.ts.map +1 -0
  228. package/dist/worker/gate-checker.js +41 -0
  229. package/dist/worker/gate-checker.js.map +1 -0
  230. package/dist/worker/index.d.ts +13 -0
  231. package/dist/worker/index.d.ts.map +1 -0
  232. package/dist/worker/index.js +19 -0
  233. package/dist/worker/index.js.map +1 -0
  234. package/dist/worker/label-manager.d.ts +89 -0
  235. package/dist/worker/label-manager.d.ts.map +1 -0
  236. package/dist/worker/label-manager.js +200 -0
  237. package/dist/worker/label-manager.js.map +1 -0
  238. package/dist/worker/output-capture.d.ts +58 -0
  239. package/dist/worker/output-capture.d.ts.map +1 -0
  240. package/dist/worker/output-capture.js +153 -0
  241. package/dist/worker/output-capture.js.map +1 -0
  242. package/dist/worker/phase-loop.d.ts +64 -0
  243. package/dist/worker/phase-loop.d.ts.map +1 -0
  244. package/dist/worker/phase-loop.js +185 -0
  245. package/dist/worker/phase-loop.js.map +1 -0
  246. package/dist/worker/phase-resolver.d.ts +62 -0
  247. package/dist/worker/phase-resolver.d.ts.map +1 -0
  248. package/dist/worker/phase-resolver.js +144 -0
  249. package/dist/worker/phase-resolver.js.map +1 -0
  250. package/dist/worker/pr-feedback-handler.d.ts +105 -0
  251. package/dist/worker/pr-feedback-handler.d.ts.map +1 -0
  252. package/dist/worker/pr-feedback-handler.js +391 -0
  253. package/dist/worker/pr-feedback-handler.js.map +1 -0
  254. package/dist/worker/pr-linker.d.ts +69 -0
  255. package/dist/worker/pr-linker.d.ts.map +1 -0
  256. package/dist/worker/pr-linker.js +108 -0
  257. package/dist/worker/pr-linker.js.map +1 -0
  258. package/dist/worker/pr-manager.d.ts +61 -0
  259. package/dist/worker/pr-manager.d.ts.map +1 -0
  260. package/dist/worker/pr-manager.js +140 -0
  261. package/dist/worker/pr-manager.js.map +1 -0
  262. package/dist/worker/repo-checkout.d.ts +63 -0
  263. package/dist/worker/repo-checkout.d.ts.map +1 -0
  264. package/dist/worker/repo-checkout.js +160 -0
  265. package/dist/worker/repo-checkout.js.map +1 -0
  266. package/dist/worker/stage-comment-manager.d.ts +34 -0
  267. package/dist/worker/stage-comment-manager.d.ts.map +1 -0
  268. package/dist/worker/stage-comment-manager.js +114 -0
  269. package/dist/worker/stage-comment-manager.js.map +1 -0
  270. package/dist/worker/types.d.ts +192 -0
  271. package/dist/worker/types.d.ts.map +1 -0
  272. package/dist/worker/types.js +53 -0
  273. package/dist/worker/types.js.map +1 -0
  274. package/package.json +64 -0
@@ -0,0 +1,62 @@
1
+ import type { CreateDecisionRequest, DecisionQueueItem, DecisionResponse, DecisionResponseRequest, DecisionPriority, QueueQuery } from '../types/index.js';
2
+ /**
3
+ * Message router interface (facade over internal message router)
4
+ * This will be implemented by the actual MessageRouter from #5
5
+ */
6
+ export interface MessageRouter {
7
+ getQueue(query?: QueueQuery): Promise<DecisionQueueItem[]>;
8
+ getDecision(id: string): Promise<DecisionQueueItem | null>;
9
+ createDecision(request: CreateDecisionRequest): Promise<DecisionQueueItem>;
10
+ respondToDecision(id: string, response: DecisionResponseRequest, respondedBy: string): Promise<DecisionResponse>;
11
+ }
12
+ /**
13
+ * In-memory queue store for development/testing
14
+ */
15
+ export declare class InMemoryQueueStore implements MessageRouter {
16
+ private queue;
17
+ private responses;
18
+ getQueue(query?: QueueQuery): Promise<DecisionQueueItem[]>;
19
+ getDecision(id: string): Promise<DecisionQueueItem | null>;
20
+ createDecision(request: CreateDecisionRequest): Promise<DecisionQueueItem>;
21
+ respondToDecision(id: string, request: DecisionResponseRequest, respondedBy: string): Promise<DecisionResponse>;
22
+ /**
23
+ * Add a decision to the queue (for testing)
24
+ */
25
+ addDecision(decision: DecisionQueueItem): void;
26
+ /**
27
+ * Clear all decisions (for testing)
28
+ */
29
+ clear(): void;
30
+ /**
31
+ * Get queue size (for testing)
32
+ */
33
+ size(): number;
34
+ }
35
+ /**
36
+ * Queue service - facade over message router
37
+ */
38
+ export declare class QueueService {
39
+ private router;
40
+ constructor(router: MessageRouter);
41
+ /**
42
+ * Get all pending decisions
43
+ */
44
+ getQueue(query?: QueueQuery): Promise<DecisionQueueItem[]>;
45
+ /**
46
+ * Create a new decision in the queue
47
+ */
48
+ createDecision(request: CreateDecisionRequest): Promise<DecisionQueueItem>;
49
+ /**
50
+ * Get a specific decision by ID
51
+ */
52
+ getDecision(id: string): Promise<DecisionQueueItem>;
53
+ /**
54
+ * Respond to a decision
55
+ */
56
+ respond(id: string, request: DecisionResponseRequest, respondedBy: string): Promise<DecisionResponse>;
57
+ /**
58
+ * Get count of pending decisions by priority
59
+ */
60
+ getQueueStats(): Promise<Record<DecisionPriority, number>>;
61
+ }
62
+ //# sourceMappingURL=queue-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-service.d.ts","sourceRoot":"","sources":["../../src/services/queue-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,UAAU,EACX,MAAM,mBAAmB,CAAC;AAG3B;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC3D,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC3D,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC3E,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAClH;AAED;;GAEG;AACH,qBAAa,kBAAmB,YAAW,aAAa;IACtD,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,SAAS,CAA4C;IAEvD,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IA6B1D,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAI1D,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAkB1E,iBAAiB,CACrB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,uBAAuB,EAChC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC;IA8B5B;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAI9C;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,IAAI,IAAI,MAAM;CAGf;AAED;;GAEG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEzC;;OAEG;IACG,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAIhE;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIhF;;OAEG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAQzD;;OAEG;IACG,OAAO,CACX,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,uBAAuB,EAChC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC;IAI5B;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;CAcjE"}
@@ -0,0 +1,147 @@
1
+ import { Errors } from '../middleware/error-handler.js';
2
+ /**
3
+ * In-memory queue store for development/testing
4
+ */
5
+ export class InMemoryQueueStore {
6
+ queue = new Map();
7
+ responses = new Map();
8
+ async getQueue(query) {
9
+ let items = Array.from(this.queue.values());
10
+ // Filter by priority
11
+ if (query?.priority) {
12
+ items = items.filter((item) => item.priority === query.priority);
13
+ }
14
+ // Filter by workflow
15
+ if (query?.workflowId) {
16
+ items = items.filter((item) => item.workflowId === query.workflowId);
17
+ }
18
+ // Sort by priority (blocking_now first) and creation date
19
+ const priorityOrder = {
20
+ blocking_now: 0,
21
+ blocking_soon: 1,
22
+ when_available: 2,
23
+ };
24
+ items.sort((a, b) => {
25
+ const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
26
+ if (priorityDiff !== 0)
27
+ return priorityDiff;
28
+ return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
29
+ });
30
+ return items;
31
+ }
32
+ async getDecision(id) {
33
+ return this.queue.get(id) ?? null;
34
+ }
35
+ async createDecision(request) {
36
+ const item = {
37
+ id: crypto.randomUUID(),
38
+ workflowId: request.workflowId,
39
+ stepId: request.stepId,
40
+ type: request.type,
41
+ prompt: request.prompt,
42
+ options: request.options,
43
+ context: request.context,
44
+ priority: request.priority,
45
+ createdAt: new Date().toISOString(),
46
+ expiresAt: request.expiresAt ?? null,
47
+ };
48
+ this.queue.set(item.id, item);
49
+ return item;
50
+ }
51
+ async respondToDecision(id, request, respondedBy) {
52
+ const decision = this.queue.get(id);
53
+ if (!decision) {
54
+ throw Errors.notFound(`Decision ${id} not found`);
55
+ }
56
+ // Check if already responded
57
+ if (this.responses.has(id)) {
58
+ throw Errors.conflict(`Decision ${id} has already been responded to`);
59
+ }
60
+ // Check expiration
61
+ if (decision.expiresAt && new Date(decision.expiresAt) < new Date()) {
62
+ throw Errors.conflict(`Decision ${id} has expired`);
63
+ }
64
+ const response = {
65
+ id,
66
+ response: request.response,
67
+ comment: request.comment,
68
+ respondedBy,
69
+ respondedAt: new Date().toISOString(),
70
+ };
71
+ this.responses.set(id, response);
72
+ this.queue.delete(id);
73
+ return response;
74
+ }
75
+ /**
76
+ * Add a decision to the queue (for testing)
77
+ */
78
+ addDecision(decision) {
79
+ this.queue.set(decision.id, decision);
80
+ }
81
+ /**
82
+ * Clear all decisions (for testing)
83
+ */
84
+ clear() {
85
+ this.queue.clear();
86
+ this.responses.clear();
87
+ }
88
+ /**
89
+ * Get queue size (for testing)
90
+ */
91
+ size() {
92
+ return this.queue.size;
93
+ }
94
+ }
95
+ /**
96
+ * Queue service - facade over message router
97
+ */
98
+ export class QueueService {
99
+ router;
100
+ constructor(router) {
101
+ this.router = router;
102
+ }
103
+ /**
104
+ * Get all pending decisions
105
+ */
106
+ async getQueue(query) {
107
+ return this.router.getQueue(query);
108
+ }
109
+ /**
110
+ * Create a new decision in the queue
111
+ */
112
+ async createDecision(request) {
113
+ return this.router.createDecision(request);
114
+ }
115
+ /**
116
+ * Get a specific decision by ID
117
+ */
118
+ async getDecision(id) {
119
+ const decision = await this.router.getDecision(id);
120
+ if (!decision) {
121
+ throw Errors.notFound(`Decision ${id} not found`);
122
+ }
123
+ return decision;
124
+ }
125
+ /**
126
+ * Respond to a decision
127
+ */
128
+ async respond(id, request, respondedBy) {
129
+ return this.router.respondToDecision(id, request, respondedBy);
130
+ }
131
+ /**
132
+ * Get count of pending decisions by priority
133
+ */
134
+ async getQueueStats() {
135
+ const items = await this.router.getQueue();
136
+ const stats = {
137
+ blocking_now: 0,
138
+ blocking_soon: 0,
139
+ when_available: 0,
140
+ };
141
+ for (const item of items) {
142
+ stats[item.priority]++;
143
+ }
144
+ return stats;
145
+ }
146
+ }
147
+ //# sourceMappingURL=queue-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-service.js","sourceRoot":"","sources":["../../src/services/queue-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { Redis } from 'ioredis';
2
+ import type { QueueItem, QueueItemWithScore, QueueManager } from '../types/index.js';
3
+ import type { DispatchConfig } from '../config/index.js';
4
+ interface Logger {
5
+ info(msg: string): void;
6
+ info(obj: Record<string, unknown>, msg: string): void;
7
+ warn(msg: string): void;
8
+ warn(obj: Record<string, unknown>, msg: string): void;
9
+ error(msg: string): void;
10
+ error(obj: Record<string, unknown>, msg: string): void;
11
+ debug(msg: string): void;
12
+ debug(obj: Record<string, unknown>, msg: string): void;
13
+ }
14
+ /**
15
+ * Redis sorted-set backed queue adapter implementing QueueManager.
16
+ * Uses ZADD for priority ordering and a Lua script for atomic claim.
17
+ * Gracefully degrades on Redis errors (logs warnings, doesn't crash).
18
+ */
19
+ export declare class RedisQueueAdapter implements QueueManager {
20
+ private readonly redis;
21
+ private readonly logger;
22
+ private readonly maxRetries;
23
+ private claimCommandDefined;
24
+ constructor(redis: Redis, logger: Logger, config?: Pick<DispatchConfig, 'maxRetries'>);
25
+ private ensureClaimCommand;
26
+ enqueue(item: QueueItem): Promise<void>;
27
+ claim(workerId: string): Promise<QueueItem | null>;
28
+ release(workerId: string, item: QueueItem): Promise<void>;
29
+ complete(workerId: string, item: QueueItem): Promise<void>;
30
+ getQueueDepth(): Promise<number>;
31
+ getQueueItems(offset: number, limit: number): Promise<QueueItemWithScore[]>;
32
+ getActiveWorkerCount(): Promise<number>;
33
+ }
34
+ export {};
35
+ //# sourceMappingURL=redis-queue-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-queue-adapter.d.ts","sourceRoot":"","sources":["../../src/services/redis-queue-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,YAAY,EAAuB,MAAM,mBAAmB,CAAC;AAC1G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA6BzD,UAAU,MAAM;IACd,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACvD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACxD;AAcD;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,YAAY;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,mBAAmB,CAAS;gBAExB,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC;IAMrF,OAAO,CAAC,kBAAkB;IASpB,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBvC,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA4ClD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAmDzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB1D,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAShC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAsC3E,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CA2B9C"}
@@ -0,0 +1,218 @@
1
+ const PENDING_KEY = 'orchestrator:queue:pending';
2
+ const CLAIMED_KEY_PREFIX = 'orchestrator:queue:claimed:';
3
+ const HEARTBEAT_KEY_PREFIX = 'orchestrator:worker:';
4
+ const DEAD_LETTER_KEY = 'orchestrator:queue:dead-letter';
5
+ /**
6
+ * Lua script for atomic claim: ZPOPMIN + HSET claimed + SET heartbeat.
7
+ * KEYS[1] = pending sorted set
8
+ * KEYS[2] = claimed hash for this worker
9
+ * KEYS[3] = heartbeat key for this worker
10
+ * ARGV[1] = heartbeat TTL in seconds
11
+ *
12
+ * Returns the serialized item string, or nil if queue is empty.
13
+ */
14
+ const CLAIM_SCRIPT = `
15
+ local result = redis.call('ZPOPMIN', KEYS[1], 1)
16
+ if #result == 0 then
17
+ return nil
18
+ end
19
+ local member = result[1]
20
+ local parsed = cjson.decode(member)
21
+ local itemKey = parsed.itemKey
22
+ redis.call('HSET', KEYS[2], itemKey, member)
23
+ redis.call('SET', KEYS[3], '1', 'EX', tonumber(ARGV[1]))
24
+ return member
25
+ `;
26
+ function buildItemKey(item) {
27
+ return `${item.owner}/${item.repo}#${item.issueNumber}`;
28
+ }
29
+ function buildClaimedKey(workerId) {
30
+ return `${CLAIMED_KEY_PREFIX}${workerId}`;
31
+ }
32
+ function buildHeartbeatKey(workerId) {
33
+ return `${HEARTBEAT_KEY_PREFIX}${workerId}:heartbeat`;
34
+ }
35
+ /**
36
+ * Redis sorted-set backed queue adapter implementing QueueManager.
37
+ * Uses ZADD for priority ordering and a Lua script for atomic claim.
38
+ * Gracefully degrades on Redis errors (logs warnings, doesn't crash).
39
+ */
40
+ export class RedisQueueAdapter {
41
+ redis;
42
+ logger;
43
+ maxRetries;
44
+ claimCommandDefined = false;
45
+ constructor(redis, logger, config) {
46
+ this.redis = redis;
47
+ this.logger = logger;
48
+ this.maxRetries = config?.maxRetries ?? 3;
49
+ }
50
+ ensureClaimCommand() {
51
+ if (this.claimCommandDefined)
52
+ return;
53
+ this.redis.defineCommand('claimItem', {
54
+ numberOfKeys: 3,
55
+ lua: CLAIM_SCRIPT,
56
+ });
57
+ this.claimCommandDefined = true;
58
+ }
59
+ async enqueue(item) {
60
+ const itemKey = buildItemKey(item);
61
+ const serialized = {
62
+ ...item,
63
+ attemptCount: 0,
64
+ itemKey,
65
+ };
66
+ try {
67
+ await this.redis.zadd(PENDING_KEY, item.priority, JSON.stringify(serialized));
68
+ this.logger.info({ owner: item.owner, repo: item.repo, issue: item.issueNumber, priority: item.priority }, 'Item enqueued to Redis sorted set');
69
+ }
70
+ catch (error) {
71
+ this.logger.warn({ err: error, itemKey }, 'Redis error in enqueue, item not added to queue');
72
+ }
73
+ }
74
+ async claim(workerId) {
75
+ this.ensureClaimCommand();
76
+ const pendingKey = PENDING_KEY;
77
+ const claimedKey = buildClaimedKey(workerId);
78
+ const heartbeatKey = buildHeartbeatKey(workerId);
79
+ const ttlSeconds = Math.ceil(30000 / 1000); // Default; actual TTL managed by dispatcher's heartbeat refresh
80
+ try {
81
+ const result = await this.redis.claimItem(pendingKey, claimedKey, heartbeatKey, ttlSeconds);
82
+ if (!result) {
83
+ return null;
84
+ }
85
+ const serialized = JSON.parse(result);
86
+ this.logger.info({ workerId, itemKey: serialized.itemKey, attempt: serialized.attemptCount }, 'Item claimed from queue');
87
+ return {
88
+ owner: serialized.owner,
89
+ repo: serialized.repo,
90
+ issueNumber: serialized.issueNumber,
91
+ workflowName: serialized.workflowName,
92
+ command: serialized.command,
93
+ priority: serialized.priority,
94
+ enqueuedAt: serialized.enqueuedAt,
95
+ };
96
+ }
97
+ catch (error) {
98
+ this.logger.warn({ err: error, workerId }, 'Redis error in claim, returning null');
99
+ return null;
100
+ }
101
+ }
102
+ async release(workerId, item) {
103
+ const itemKey = buildItemKey(item);
104
+ const claimedKey = buildClaimedKey(workerId);
105
+ const heartbeatKey = buildHeartbeatKey(workerId);
106
+ try {
107
+ // Get the claimed item to check attempt count
108
+ const claimedRaw = await this.redis.hget(claimedKey, itemKey);
109
+ let attemptCount = 0;
110
+ if (claimedRaw) {
111
+ const parsed = JSON.parse(claimedRaw);
112
+ attemptCount = parsed.attemptCount + 1;
113
+ }
114
+ // Clean up claimed hash and heartbeat
115
+ await this.redis.hdel(claimedKey, itemKey);
116
+ await this.redis.del(heartbeatKey);
117
+ if (attemptCount >= this.maxRetries) {
118
+ // Dead-letter: too many retries
119
+ const deadLetterItem = {
120
+ ...item,
121
+ attemptCount,
122
+ itemKey,
123
+ };
124
+ await this.redis.zadd(DEAD_LETTER_KEY, Date.now(), JSON.stringify(deadLetterItem));
125
+ this.logger.warn({ workerId, itemKey, attemptCount, maxRetries: this.maxRetries }, 'Item dead-lettered after max retries');
126
+ }
127
+ else {
128
+ // Re-queue with original priority
129
+ const requeueItem = {
130
+ ...item,
131
+ attemptCount,
132
+ itemKey,
133
+ };
134
+ await this.redis.zadd(PENDING_KEY, item.priority, JSON.stringify(requeueItem));
135
+ this.logger.info({ workerId, itemKey, attemptCount }, 'Item released back to pending queue');
136
+ }
137
+ }
138
+ catch (error) {
139
+ this.logger.warn({ err: error, workerId, itemKey }, 'Redis error in release');
140
+ }
141
+ }
142
+ async complete(workerId, item) {
143
+ const itemKey = buildItemKey(item);
144
+ const claimedKey = buildClaimedKey(workerId);
145
+ const heartbeatKey = buildHeartbeatKey(workerId);
146
+ try {
147
+ await this.redis.hdel(claimedKey, itemKey);
148
+ await this.redis.del(heartbeatKey);
149
+ this.logger.info({ workerId, itemKey }, 'Item completed and removed from claimed set');
150
+ }
151
+ catch (error) {
152
+ this.logger.warn({ err: error, workerId, itemKey }, 'Redis error in complete');
153
+ }
154
+ }
155
+ async getQueueDepth() {
156
+ try {
157
+ return await this.redis.zcard(PENDING_KEY);
158
+ }
159
+ catch (error) {
160
+ this.logger.warn({ err: error }, 'Redis error in getQueueDepth');
161
+ return 0;
162
+ }
163
+ }
164
+ async getQueueItems(offset, limit) {
165
+ try {
166
+ const results = await this.redis.zrange(PENDING_KEY, offset, offset + limit - 1, 'WITHSCORES');
167
+ const items = [];
168
+ // Results come as [member, score, member, score, ...]
169
+ for (let i = 0; i + 1 < results.length; i += 2) {
170
+ const member = results[i];
171
+ const scoreStr = results[i + 1];
172
+ if (!member || !scoreStr)
173
+ continue;
174
+ const serialized = JSON.parse(member);
175
+ const score = parseFloat(scoreStr);
176
+ items.push({
177
+ item: {
178
+ owner: serialized.owner,
179
+ repo: serialized.repo,
180
+ issueNumber: serialized.issueNumber,
181
+ workflowName: serialized.workflowName,
182
+ command: serialized.command,
183
+ priority: serialized.priority,
184
+ enqueuedAt: serialized.enqueuedAt,
185
+ },
186
+ score,
187
+ });
188
+ }
189
+ return items;
190
+ }
191
+ catch (error) {
192
+ this.logger.warn({ err: error }, 'Redis error in getQueueItems');
193
+ return [];
194
+ }
195
+ }
196
+ async getActiveWorkerCount() {
197
+ try {
198
+ // Scan for all claimed hash keys and sum their lengths
199
+ const keys = [];
200
+ let cursor = '0';
201
+ do {
202
+ const [nextCursor, matchedKeys] = await this.redis.scan(cursor, 'MATCH', `${CLAIMED_KEY_PREFIX}*`, 'COUNT', 100);
203
+ cursor = nextCursor;
204
+ keys.push(...matchedKeys);
205
+ } while (cursor !== '0');
206
+ let count = 0;
207
+ for (const key of keys) {
208
+ count += await this.redis.hlen(key);
209
+ }
210
+ return count;
211
+ }
212
+ catch (error) {
213
+ this.logger.warn({ err: error }, 'Redis error in getActiveWorkerCount');
214
+ return 0;
215
+ }
216
+ }
217
+ }
218
+ //# sourceMappingURL=redis-queue-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-queue-adapter.js","sourceRoot":"","sources":["../../src/services/redis-queue-adapter.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,GAAG,4BAA4B,CAAC;AACjD,MAAM,kBAAkB,GAAG,6BAA6B,CAAC;AACzD,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AACpD,MAAM,eAAe,GAAG,gCAAgC,CAAC;AAEzD;;;;;;;;GAQG;AACH,MAAM,YAAY,GAAG;;;;;;;;;;;CAWpB,CAAC;AAaF,SAAS,YAAY,CAAC,IAAe;IACnC,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;AAC1D,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACvC,OAAO,GAAG,kBAAkB,GAAG,QAAQ,EAAE,CAAC;AAC5C,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB;IACzC,OAAO,GAAG,oBAAoB,GAAG,QAAQ,YAAY,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IACX,KAAK,CAAQ;IACb,MAAM,CAAS;IACf,UAAU,CAAS;IAC5B,mBAAmB,GAAG,KAAK,CAAC;IAEpC,YAAY,KAAY,EAAE,MAAc,EAAE,MAA2C;QACnF,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,MAAM,EAAE,UAAU,IAAI,CAAC,CAAC;IAC5C,CAAC;IAEO,kBAAkB;QACxB,IAAI,IAAI,CAAC,mBAAmB;YAAE,OAAO;QACrC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,EAAE;YACpC,YAAY,EAAE,CAAC;YACf,GAAG,EAAE,YAAY;SAClB,CAAC,CAAC;QACH,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAe;QAC3B,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,UAAU,GAAwB;YACtC,GAAG,IAAI;YACP,YAAY,EAAE,CAAC;YACf,OAAO;SACR,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;YAC9E,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,EACxF,mCAAmC,CACpC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,EACvB,iDAAiD,CAClD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB;QAC1B,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAE1B,MAAM,UAAU,GAAG,WAAW,CAAC;QAC/B,MAAM,UAAU,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,YAAY,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,gEAAgE;QAE5G,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAO,IAAI,CAAC,KAAa,CAAC,SAAS,CAChD,UAAU,EACV,UAAU,EACV,YAAY,EACZ,UAAU,CACX,CAAC;YAEF,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,UAAU,GAAwB,IAAI,CAAC,KAAK,CAAC,MAAgB,CAAC,CAAC;YACrE,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,YAAY,EAAE,EAC3E,yBAAyB,CAC1B,CAAC;YAEF,OAAO;gBACL,KAAK,EAAE,UAAU,CAAC,KAAK;gBACvB,IAAI,EAAE,UAAU,CAAC,IAAI;gBACrB,WAAW,EAAE,UAAU,CAAC,WAAW;gBACnC,YAAY,EAAE,UAAU,CAAC,YAAY;gBACrC,OAAO,EAAE,UAAU,CAAC,OAAO;gBAC3B,QAAQ,EAAE,UAAU,CAAC,QAAQ;gBAC7B,UAAU,EAAE,UAAU,CAAC,UAAU;aAClC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,EACxB,sCAAsC,CACvC,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB,EAAE,IAAe;QAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,UAAU,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,YAAY,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAEjD,IAAI,CAAC;YACH,8CAA8C;YAC9C,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC9D,IAAI,YAAY,GAAG,CAAC,CAAC;YACrB,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,MAAM,GAAwB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC3D,YAAY,GAAG,MAAM,CAAC,YAAY,GAAG,CAAC,CAAC;YACzC,CAAC;YAED,sCAAsC;YACtC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC3C,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAEnC,IAAI,YAAY,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpC,gCAAgC;gBAChC,MAAM,cAAc,GAAwB;oBAC1C,GAAG,IAAI;oBACP,YAAY;oBACZ,OAAO;iBACR,CAAC;gBACF,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC;gBACnF,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,EAChE,sCAAsC,CACvC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,kCAAkC;gBAClC,MAAM,WAAW,GAAwB;oBACvC,GAAG,IAAI;oBACP,YAAY;oBACZ,OAAO;iBACR,CAAC;gBACF,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;gBAC/E,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,EACnC,qCAAqC,CACtC,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EACjC,wBAAwB,CACzB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,IAAe;QAC9C,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,UAAU,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,YAAY,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC3C,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YACnC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,QAAQ,EAAE,OAAO,EAAE,EACrB,6CAA6C,CAC9C,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EACjC,yBAAyB,CAC1B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,8BAA8B,CAAC,CAAC;YACjE,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAAc,EAAE,KAAa;QAC/C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CACrC,WAAW,EACX,MAAM,EACN,MAAM,GAAG,KAAK,GAAG,CAAC,EAClB,YAAY,CACb,CAAC;YAEF,MAAM,KAAK,GAAyB,EAAE,CAAC;YACvC,sDAAsD;YACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAChC,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ;oBAAE,SAAS;gBACnC,MAAM,UAAU,GAAwB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC3D,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACnC,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE;wBACJ,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,IAAI,EAAE,UAAU,CAAC,IAAI;wBACrB,WAAW,EAAE,UAAU,CAAC,WAAW;wBACnC,YAAY,EAAE,UAAU,CAAC,YAAY;wBACrC,OAAO,EAAE,UAAU,CAAC,OAAO;wBAC3B,QAAQ,EAAE,UAAU,CAAC,QAAQ;wBAC7B,UAAU,EAAE,UAAU,CAAC,UAAU;qBAClC;oBACD,KAAK;iBACN,CAAC,CAAC;YACL,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,8BAA8B,CAAC,CAAC;YACjE,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,oBAAoB;QACxB,IAAI,CAAC;YACH,uDAAuD;YACvD,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,IAAI,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC;gBACF,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CACrD,MAAM,EACN,OAAO,EACP,GAAG,kBAAkB,GAAG,EACxB,OAAO,EACP,GAAG,CACJ,CAAC;gBACF,MAAM,GAAG,UAAU,CAAC;gBACpB,IAAI,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;YAC5B,CAAC,QAAQ,MAAM,KAAK,GAAG,EAAE;YAEzB,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,KAAK,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACtC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,qCAAqC,CAAC,CAAC;YACxE,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Smee.io webhook receiver for GitHub events.
3
+ *
4
+ * Connects to a smee.io channel URL via Server-Sent Events (SSE) using
5
+ * the native fetch API. Receives GitHub webhook payloads forwarded by
6
+ * smee.io and feeds them into the LabelMonitorService for processing.
7
+ *
8
+ * This eliminates the need for polling when a smee channel is configured,
9
+ * providing near-instant label event detection with zero GitHub API calls.
10
+ */
11
+ import type { LabelMonitorService } from './label-monitor-service.js';
12
+ interface Logger {
13
+ info(msg: string): void;
14
+ info(obj: Record<string, unknown>, msg: string): void;
15
+ warn(msg: string): void;
16
+ warn(obj: Record<string, unknown>, msg: string): void;
17
+ error(msg: string): void;
18
+ error(obj: Record<string, unknown>, msg: string): void;
19
+ }
20
+ export interface SmeeReceiverOptions {
21
+ /** The smee.io channel URL */
22
+ channelUrl: string;
23
+ /** Set of "owner/repo" strings to filter events */
24
+ watchedRepos: Set<string>;
25
+ /**
26
+ * Base delay before reconnecting after disconnect (ms).
27
+ * Uses exponential backoff: 5s → 10s → 20s → 40s → 80s → 160s → 300s (capped).
28
+ * Resets to base delay on successful connection.
29
+ * @default 5000
30
+ */
31
+ baseReconnectDelayMs?: number;
32
+ }
33
+ /**
34
+ * Receives GitHub webhook events from a smee.io channel via SSE.
35
+ * Feeds label events directly into the LabelMonitorService.
36
+ */
37
+ export declare class SmeeWebhookReceiver {
38
+ private readonly logger;
39
+ private readonly monitorService;
40
+ private static readonly BASE_RECONNECT_DELAY_MS;
41
+ private static readonly MAX_BACKOFF_MS;
42
+ private readonly channelUrl;
43
+ private readonly watchedRepos;
44
+ private readonly baseReconnectDelayMs;
45
+ private abortController;
46
+ private running;
47
+ private reconnectAttempt;
48
+ constructor(logger: Logger, monitorService: LabelMonitorService, options: SmeeReceiverOptions);
49
+ /**
50
+ * Start listening to the smee.io channel.
51
+ * Automatically reconnects on disconnect.
52
+ */
53
+ start(): Promise<void>;
54
+ /**
55
+ * Stop the receiver.
56
+ */
57
+ stop(): void;
58
+ /**
59
+ * Connect to the smee.io channel and process events.
60
+ */
61
+ private connect;
62
+ /**
63
+ * Parse and process a single SSE event block from smee.io.
64
+ *
65
+ * Smee.io SSE events have the format:
66
+ * event: message
67
+ * data: {"body": <webhook-payload>, "x-github-event": "issues", ...}
68
+ */
69
+ private processSSEEvent;
70
+ /**
71
+ * Get the current reconnect delay based on the number of attempts.
72
+ * Uses exponential backoff with the current attempt count.
73
+ */
74
+ private get reconnectDelayMs();
75
+ /**
76
+ * Calculate exponential backoff delay for reconnection attempts.
77
+ * Formula: BASE_RECONNECT_DELAY_MS * 2^attempt, capped at MAX_BACKOFF_MS.
78
+ * Progression: 5s → 10s → 20s → 40s → 80s → 160s → 300s (capped).
79
+ *
80
+ * @param attempt - The current reconnection attempt number (0-indexed)
81
+ * @returns Delay in milliseconds before next reconnection attempt
82
+ */
83
+ private calculateBackoffDelay;
84
+ private sleep;
85
+ }
86
+ export {};
87
+ //# sourceMappingURL=smee-receiver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smee-receiver.d.ts","sourceRoot":"","sources":["../../src/services/smee-receiver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGtE,UAAU,MAAM;IACd,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;GAGG;AACH,qBAAa,mBAAmB;IAY5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAZjC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAQ;IACvD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAU;IAEhD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,gBAAgB,CAAK;gBAGV,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,mBAAmB,EACpD,OAAO,EAAE,mBAAmB;IAO9B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA0C5B;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;YACW,OAAO;IA0CrB;;;;;;OAMG;YACW,eAAe;IA2G7B;;;OAGG;IACH,OAAO,KAAK,gBAAgB,GAE3B;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,KAAK;CAcd"}