@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,225 @@
1
+ /**
2
+ * Receives GitHub webhook events from a smee.io channel via SSE.
3
+ * Feeds label events directly into the LabelMonitorService.
4
+ */
5
+ export class SmeeWebhookReceiver {
6
+ logger;
7
+ monitorService;
8
+ static BASE_RECONNECT_DELAY_MS = 5000;
9
+ static MAX_BACKOFF_MS = 300000; // 5 minutes
10
+ channelUrl;
11
+ watchedRepos;
12
+ baseReconnectDelayMs;
13
+ abortController = null;
14
+ running = false;
15
+ reconnectAttempt = 0;
16
+ constructor(logger, monitorService, options) {
17
+ this.logger = logger;
18
+ this.monitorService = monitorService;
19
+ this.channelUrl = options.channelUrl;
20
+ this.watchedRepos = options.watchedRepos;
21
+ this.baseReconnectDelayMs = options.baseReconnectDelayMs ?? SmeeWebhookReceiver.BASE_RECONNECT_DELAY_MS;
22
+ }
23
+ /**
24
+ * Start listening to the smee.io channel.
25
+ * Automatically reconnects on disconnect.
26
+ */
27
+ async start() {
28
+ if (this.running) {
29
+ this.logger.warn('Smee receiver already running');
30
+ return;
31
+ }
32
+ this.running = true;
33
+ this.abortController = new AbortController();
34
+ const { signal } = this.abortController;
35
+ this.logger.info({ channelUrl: this.channelUrl, watchedRepos: [...this.watchedRepos] }, 'Starting smee.io webhook receiver');
36
+ while (this.running && !signal.aborted) {
37
+ try {
38
+ await this.connect(signal);
39
+ // Reset backoff counter on successful connection
40
+ this.reconnectAttempt = 0;
41
+ }
42
+ catch (error) {
43
+ if (signal.aborted)
44
+ break;
45
+ const reconnectMs = this.reconnectDelayMs;
46
+ this.logger.warn({ err: String(error), reconnectMs, attempt: this.reconnectAttempt }, 'Smee connection lost, reconnecting...');
47
+ // Increment attempt counter for exponential backoff
48
+ this.reconnectAttempt++;
49
+ }
50
+ // Wait before reconnecting
51
+ if (this.running && !signal.aborted) {
52
+ await this.sleep(this.reconnectDelayMs, signal);
53
+ }
54
+ }
55
+ this.running = false;
56
+ this.logger.info('Smee receiver stopped');
57
+ }
58
+ /**
59
+ * Stop the receiver.
60
+ */
61
+ stop() {
62
+ this.running = false;
63
+ if (this.abortController) {
64
+ this.abortController.abort();
65
+ this.abortController = null;
66
+ }
67
+ this.logger.info('Smee receiver stop requested');
68
+ }
69
+ /**
70
+ * Connect to the smee.io channel and process events.
71
+ */
72
+ async connect(signal) {
73
+ const response = await fetch(this.channelUrl, {
74
+ headers: { Accept: 'text/event-stream' },
75
+ signal,
76
+ });
77
+ if (!response.ok) {
78
+ throw new Error(`Smee connection failed: ${response.status} ${response.statusText}`);
79
+ }
80
+ if (!response.body) {
81
+ throw new Error('Smee response has no body');
82
+ }
83
+ this.logger.info('Connected to smee.io channel');
84
+ const reader = response.body.getReader();
85
+ const decoder = new TextDecoder();
86
+ let buffer = '';
87
+ try {
88
+ while (!signal.aborted) {
89
+ const { done, value } = await reader.read();
90
+ if (done)
91
+ break;
92
+ buffer += decoder.decode(value, { stream: true });
93
+ // Process complete SSE events (separated by double newline)
94
+ const events = buffer.split('\n\n');
95
+ // Keep the last incomplete chunk in the buffer
96
+ buffer = events.pop() ?? '';
97
+ for (const eventBlock of events) {
98
+ if (!eventBlock.trim())
99
+ continue;
100
+ await this.processSSEEvent(eventBlock);
101
+ }
102
+ }
103
+ }
104
+ finally {
105
+ reader.releaseLock();
106
+ }
107
+ }
108
+ /**
109
+ * Parse and process a single SSE event block from smee.io.
110
+ *
111
+ * Smee.io SSE events have the format:
112
+ * event: message
113
+ * data: {"body": <webhook-payload>, "x-github-event": "issues", ...}
114
+ */
115
+ async processSSEEvent(eventBlock) {
116
+ let eventType = '';
117
+ const dataLines = [];
118
+ for (const line of eventBlock.split('\n')) {
119
+ if (line.startsWith('event:')) {
120
+ eventType = line.slice(6).trim();
121
+ }
122
+ else if (line.startsWith('data:')) {
123
+ dataLines.push(line.slice(5).trim());
124
+ }
125
+ }
126
+ // Only process message events
127
+ if (eventType !== 'message' && eventType !== '') {
128
+ // Smee sends 'ready' and 'ping' events — ignore them
129
+ return;
130
+ }
131
+ const dataStr = dataLines.join('\n');
132
+ if (!dataStr)
133
+ return;
134
+ let data;
135
+ try {
136
+ data = JSON.parse(dataStr);
137
+ }
138
+ catch {
139
+ return; // Skip malformed events
140
+ }
141
+ // Smee wraps the webhook payload in a 'body' field
142
+ const githubEvent = data['x-github-event'];
143
+ const body = data['body'];
144
+ if (!body || githubEvent !== 'issues') {
145
+ return; // Only interested in issue events
146
+ }
147
+ const payload = body;
148
+ // Only handle "labeled" action
149
+ if (payload.action !== 'labeled')
150
+ return;
151
+ // Check if this is a watched repository
152
+ if (!payload.repository?.owner?.login || !payload.repository?.name)
153
+ return;
154
+ const repoKey = `${payload.repository.owner.login}/${payload.repository.name}`;
155
+ if (!this.watchedRepos.has(repoKey))
156
+ return;
157
+ // Parse and process the label event
158
+ const issueLabels = payload.issue?.labels?.map(l => l.name) ?? [];
159
+ const event = this.monitorService.parseLabelEvent(payload.label.name, payload.repository.owner.login, payload.repository.name, payload.issue.number, issueLabels, 'webhook');
160
+ if (!event) {
161
+ // If this was a completed:* label that didn't match a waiting-for:*
162
+ // in the webhook payload, re-fetch from GitHub to handle stale payloads.
163
+ if (payload.label.name.startsWith('completed:')) {
164
+ this.logger.info({ label: payload.label.name, repo: repoKey, issue: payload.issue.number }, 'Webhook completed:* label has no matching waiting-for:* in payload, attempting re-fetch');
165
+ this.monitorService.recordWebhookEvent();
166
+ try {
167
+ await this.monitorService.verifyAndProcessCompletedLabel(payload.repository.owner.login, payload.repository.name, payload.issue.number, payload.label.name);
168
+ }
169
+ catch (error) {
170
+ this.logger.error({ err: String(error), repo: repoKey, issue: payload.issue.number }, 'Error during completed:* label re-fetch verification');
171
+ }
172
+ }
173
+ return;
174
+ }
175
+ this.logger.info({
176
+ type: event.type,
177
+ repo: repoKey,
178
+ issue: event.issueNumber,
179
+ label: event.labelName,
180
+ }, 'Smee webhook received label event');
181
+ // Record webhook event for adaptive polling health tracking
182
+ this.monitorService.recordWebhookEvent();
183
+ // Process the event
184
+ try {
185
+ await this.monitorService.processLabelEvent(event);
186
+ }
187
+ catch (error) {
188
+ this.logger.error({ err: String(error), repo: repoKey, issue: event.issueNumber }, 'Error processing smee webhook event');
189
+ }
190
+ }
191
+ /**
192
+ * Get the current reconnect delay based on the number of attempts.
193
+ * Uses exponential backoff with the current attempt count.
194
+ */
195
+ get reconnectDelayMs() {
196
+ return this.calculateBackoffDelay(this.reconnectAttempt);
197
+ }
198
+ /**
199
+ * Calculate exponential backoff delay for reconnection attempts.
200
+ * Formula: BASE_RECONNECT_DELAY_MS * 2^attempt, capped at MAX_BACKOFF_MS.
201
+ * Progression: 5s → 10s → 20s → 40s → 80s → 160s → 300s (capped).
202
+ *
203
+ * @param attempt - The current reconnection attempt number (0-indexed)
204
+ * @returns Delay in milliseconds before next reconnection attempt
205
+ */
206
+ calculateBackoffDelay(attempt) {
207
+ const delay = this.baseReconnectDelayMs * Math.pow(2, attempt);
208
+ return Math.min(delay, SmeeWebhookReceiver.MAX_BACKOFF_MS);
209
+ }
210
+ sleep(ms, signal) {
211
+ return new Promise((resolve) => {
212
+ if (signal.aborted) {
213
+ resolve();
214
+ return;
215
+ }
216
+ const timer = setTimeout(resolve, ms);
217
+ const onAbort = () => {
218
+ clearTimeout(timer);
219
+ resolve();
220
+ };
221
+ signal.addEventListener('abort', onAbort, { once: true });
222
+ });
223
+ }
224
+ }
225
+ //# sourceMappingURL=smee-receiver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smee-receiver.js","sourceRoot":"","sources":["../../src/services/smee-receiver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Logger interface matching Pino/Fastify logger shape.
3
+ *
4
+ * Supports both simple string messages and structured logging with context objects.
5
+ */
6
+ interface Logger {
7
+ /** Log informational message */
8
+ info(msg: string): void;
9
+ /** Log informational message with structured context */
10
+ info(obj: Record<string, unknown>, msg: string): void;
11
+ /** Log warning message */
12
+ warn(msg: string): void;
13
+ /** Log warning message with structured context */
14
+ warn(obj: Record<string, unknown>, msg: string): void;
15
+ /** Log error message */
16
+ error(msg: string): void;
17
+ /** Log error message with structured context */
18
+ error(obj: Record<string, unknown>, msg: string): void;
19
+ }
20
+ /**
21
+ * Repository configuration for webhook setup.
22
+ *
23
+ * Identifies a GitHub repository by owner and name for webhook management.
24
+ */
25
+ export interface RepositoryConfig {
26
+ /** Repository owner (organization or user) */
27
+ owner: string;
28
+ /** Repository name */
29
+ repo: string;
30
+ }
31
+ /**
32
+ * Minimal GitHub webhook response type.
33
+ *
34
+ * Only includes fields needed for matching and reactivation.
35
+ * See: https://docs.github.com/en/rest/webhooks/repos#list-repository-webhooks
36
+ */
37
+ export interface GitHubWebhook {
38
+ /** Webhook ID (unique identifier) */
39
+ id: number;
40
+ /** Whether webhook is active (receiving events) */
41
+ active: boolean;
42
+ /** Webhook configuration */
43
+ config: {
44
+ /** Target URL where webhook events are sent */
45
+ url: string;
46
+ };
47
+ /** Event types webhook subscribes to (e.g., ["issues", "pull_request"]) */
48
+ events: string[];
49
+ }
50
+ /**
51
+ * Result of webhook setup for a single repository.
52
+ *
53
+ * Captures the action taken and any relevant details or errors.
54
+ */
55
+ export interface WebhookSetupResult {
56
+ /** Repository owner (organization or user) */
57
+ owner: string;
58
+ /** Repository name */
59
+ repo: string;
60
+ /**
61
+ * Action taken during webhook setup
62
+ * - `created`: New webhook was created
63
+ * - `skipped`: Active webhook already exists
64
+ * - `reactivated`: Inactive webhook was reactivated
65
+ * - `failed`: Setup failed (see `error` field)
66
+ */
67
+ action: 'created' | 'skipped' | 'reactivated' | 'failed';
68
+ /** Webhook ID (present for created/skipped/reactivated, absent for failed) */
69
+ webhookId?: number;
70
+ /** Error message (only present when action === 'failed') */
71
+ error?: string;
72
+ }
73
+ /**
74
+ * Summary of webhook setup across all repositories.
75
+ *
76
+ * Provides aggregate counts and detailed per-repository results.
77
+ */
78
+ export interface WebhookSetupSummary {
79
+ /** Total number of repositories checked */
80
+ total: number;
81
+ /** Number of webhooks created (new) */
82
+ created: number;
83
+ /** Number of webhooks skipped (already active) */
84
+ skipped: number;
85
+ /** Number of webhooks reactivated (was inactive) */
86
+ reactivated: number;
87
+ /** Number of repositories that failed webhook setup */
88
+ failed: number;
89
+ /** Detailed results for each repository */
90
+ results: WebhookSetupResult[];
91
+ }
92
+ /**
93
+ * Service for auto-configuring GitHub webhooks for monitored repositories.
94
+ *
95
+ * When SMEE_CHANNEL_URL is configured, this service verifies and creates
96
+ * GitHub webhooks for all monitored repositories on orchestrator startup,
97
+ * ensuring near-instant label detection via Smee instead of 15-minute polling.
98
+ *
99
+ * Features:
100
+ * - Creates missing webhooks pointing to Smee channel URL
101
+ * - Skips existing active webhooks (idempotent)
102
+ * - Reactivates inactive webhooks and merges events
103
+ * - Graceful error handling (per-repo failures don't block startup)
104
+ * - Warns on event mismatches without modifying
105
+ * - Validates Smee URL format (warns on non-smee.io URLs)
106
+ *
107
+ * Error Handling:
108
+ * - 403/404 errors: Logged as warnings, system falls back to polling
109
+ * - Network/API errors: Logged and continue with next repo
110
+ * - All errors are non-fatal and don't block orchestrator startup
111
+ */
112
+ export declare class WebhookSetupService {
113
+ private readonly _logger;
114
+ /**
115
+ * Creates a new WebhookSetupService instance.
116
+ *
117
+ * @param logger - Logger instance for structured logging (Pino/Fastify compatible)
118
+ */
119
+ constructor(logger: Logger);
120
+ /**
121
+ * Ensure webhooks exist for all repositories.
122
+ *
123
+ * This is the main entry point for webhook setup. For each repository:
124
+ * 1. Lists existing webhooks via GitHub API
125
+ * 2. Checks if a webhook already exists for the Smee channel URL
126
+ * 3. Creates missing webhooks, reactivates inactive ones, or skips active ones
127
+ * 4. Logs results and continues on errors (graceful degradation)
128
+ *
129
+ * Per-repository errors are logged but don't block the overall process,
130
+ * allowing partial success when some repositories fail (e.g., due to
131
+ * insufficient permissions).
132
+ *
133
+ * @param smeeChannelUrl - The Smee channel URL to configure webhooks for
134
+ * (e.g., 'https://smee.io/abc123'). URL is validated
135
+ * and a warning is logged if it doesn't point to smee.io.
136
+ * @param repositories - List of repositories to ensure webhooks for. Each
137
+ * repository is processed sequentially to avoid rate limits.
138
+ * @returns Promise resolving to a summary of webhook setup results, including
139
+ * aggregate counts and detailed per-repository results.
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const service = new WebhookSetupService(logger);
144
+ * const summary = await service.ensureWebhooks(
145
+ * 'https://smee.io/abc123',
146
+ * [
147
+ * { owner: 'myorg', repo: 'myrepo' },
148
+ * { owner: 'myorg', repo: 'another-repo' }
149
+ * ]
150
+ * );
151
+ * console.log(`Created: ${summary.created}, Skipped: ${summary.skipped}, Failed: ${summary.failed}`);
152
+ * ```
153
+ *
154
+ * @see {@link WebhookSetupSummary} for the structure of the returned summary
155
+ */
156
+ ensureWebhooks(smeeChannelUrl: string, repositories: RepositoryConfig[]): Promise<WebhookSetupSummary>;
157
+ /**
158
+ * Ensure webhook exists for a single repository.
159
+ *
160
+ * Internal method that handles webhook verification and setup for one repository.
161
+ * All errors are caught and converted to a 'failed' result to allow graceful
162
+ * degradation.
163
+ *
164
+ * Logic flow:
165
+ * 1. List existing webhooks
166
+ * 2. Find webhook matching the Smee URL (case-insensitive)
167
+ * 3. If not found: Create new webhook → 'created'
168
+ * 4. If found and active: Skip → 'skipped' (warn on event mismatch)
169
+ * 5. If found but inactive: Reactivate and merge events → 'reactivated'
170
+ *
171
+ * @param owner - Repository owner (organization or user)
172
+ * @param repo - Repository name
173
+ * @param smeeChannelUrl - The Smee channel URL to configure
174
+ * @returns Promise resolving to the result of webhook setup for this repository
175
+ *
176
+ * @throws Never throws - all errors are caught and returned as 'failed' results
177
+ */
178
+ private _ensureWebhookForRepo;
179
+ /**
180
+ * Find a webhook matching the given URL.
181
+ *
182
+ * Uses case-insensitive URL comparison. No URL normalization is performed -
183
+ * simple string matching after lowercasing both URLs. This means that
184
+ * 'https://smee.io/ABC' and 'https://smee.io/abc' are considered equal,
185
+ * but trailing slashes or different protocols would not match.
186
+ *
187
+ * @param webhooks - Array of webhooks to search through
188
+ * @param targetUrl - The URL to match (typically the Smee channel URL)
189
+ * @returns The first matching webhook, or undefined if none found
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * const webhooks = [
194
+ * { id: 1, active: true, config: { url: 'https://smee.io/ABC' }, events: ['issues'] }
195
+ * ];
196
+ * const match = this._findMatchingWebhook(webhooks, 'https://smee.io/abc');
197
+ * // Returns the webhook with id: 1
198
+ * ```
199
+ */
200
+ private _findMatchingWebhook;
201
+ /**
202
+ * List webhooks for a repository via GitHub API.
203
+ *
204
+ * Uses the `gh` CLI to call `GET /repos/{owner}/{repo}/hooks`.
205
+ * Errors are logged and an empty array is returned for graceful degradation.
206
+ *
207
+ * @param owner - Repository owner (organization or user)
208
+ * @param repo - Repository name
209
+ * @returns Promise resolving to an array of webhooks (empty array on error)
210
+ *
211
+ * @see {@link https://docs.github.com/en/rest/webhooks/repos#list-repository-webhooks}
212
+ */
213
+ private _listRepoWebhooks;
214
+ /**
215
+ * Create a new webhook for a repository via GitHub API.
216
+ *
217
+ * Uses the `gh` CLI to call `POST /repos/{owner}/{repo}/hooks` with:
218
+ * - `config.url`: The Smee channel URL
219
+ * - `config.content_type`: 'json'
220
+ * - `events`: ['issues']
221
+ * - `active`: true
222
+ *
223
+ * @param owner - Repository owner (organization or user)
224
+ * @param repo - Repository name
225
+ * @param smeeChannelUrl - The Smee channel URL to configure
226
+ * @returns Promise resolving to the webhook ID on success
227
+ * @throws Error if webhook creation fails (caught and logged by caller)
228
+ *
229
+ * @see {@link https://docs.github.com/en/rest/webhooks/repos#create-a-repository-webhook}
230
+ */
231
+ private _createRepoWebhook;
232
+ /**
233
+ * Update an existing webhook (reactivate and/or merge events) via GitHub API.
234
+ *
235
+ * Uses the `gh` CLI to call `PATCH /repos/{owner}/{repo}/hooks/{webhookId}`.
236
+ * When reactivating an inactive webhook, this method also merges the 'issues'
237
+ * event with any existing events to preserve the webhook's original configuration.
238
+ *
239
+ * @param owner - Repository owner (organization or user)
240
+ * @param repo - Repository name
241
+ * @param webhookId - Webhook ID to update
242
+ * @param updates - Updates to apply
243
+ * @param updates.active - Set webhook active status (true to reactivate)
244
+ * @param updates.events - Event types to subscribe to (merged with existing)
245
+ * @returns Promise resolving to true on success
246
+ * @throws Error if webhook update fails (caught and logged by caller)
247
+ *
248
+ * @see {@link https://docs.github.com/en/rest/webhooks/repos#update-a-repository-webhook}
249
+ */
250
+ private _updateRepoWebhook;
251
+ }
252
+ export {};
253
+ //# sourceMappingURL=webhook-setup-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-setup-service.d.ts","sourceRoot":"","sources":["../../src/services/webhook-setup-service.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,UAAU,MAAM;IACd,gCAAgC;IAChC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,wDAAwD;IACxD,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,0BAA0B;IAC1B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kDAAkD;IAClD,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,wBAAwB;IACxB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gDAAgD;IAChD,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACxD;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,mDAAmD;IACnD,MAAM,EAAE,OAAO,CAAC;IAChB,4BAA4B;IAC5B,MAAM,EAAE;QACN,+CAA+C;QAC/C,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,2EAA2E;IAC3E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;IACzD,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC;;;;OAIG;gBACS,MAAM,EAAE,MAAM;IAI1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACG,cAAc,CAClB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,gBAAgB,EAAE,GAC/B,OAAO,CAAC,mBAAmB,CAAC;IAuD/B;;;;;;;;;;;;;;;;;;;;OAoBG;YACW,qBAAqB;IA6HnC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,oBAAoB;IAY5B;;;;;;;;;;;OAWG;YACW,iBAAiB;IA0C/B;;;;;;;;;;;;;;;;OAgBG;YACW,kBAAkB;IA0BhC;;;;;;;;;;;;;;;;;OAiBG;YACW,kBAAkB;CAoCjC"}