@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,239 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { DEFAULT_SSE_CONFIG, parseChannels, parseEventId } from '../types/sse.js';
3
+ import { formatSSEEvent, formatHeartbeat, createConnectedEvent } from './events.js';
4
+ /**
5
+ * SSE Stream Manager
6
+ * Manages individual SSE connections with heartbeat and event delivery
7
+ */
8
+ export class SSEStream {
9
+ connection;
10
+ config;
11
+ closed = false;
12
+ constructor(response, request, userId, options = {}, config = {}) {
13
+ this.config = { ...DEFAULT_SSE_CONFIG, ...config };
14
+ const connectionId = `conn_${randomUUID().slice(0, 8)}`;
15
+ const channels = options.channels || parseChannels();
16
+ this.connection = {
17
+ id: connectionId,
18
+ response,
19
+ request: request.raw,
20
+ userId,
21
+ subscription: {
22
+ channels: new Set(channels),
23
+ filters: options.filters || {},
24
+ lastEventId: options.lastEventId,
25
+ },
26
+ connectedAt: new Date(),
27
+ sequenceCounter: 0,
28
+ };
29
+ }
30
+ /**
31
+ * Get connection ID
32
+ */
33
+ get id() {
34
+ return this.connection.id;
35
+ }
36
+ /**
37
+ * Get user ID
38
+ */
39
+ get userId() {
40
+ return this.connection.userId;
41
+ }
42
+ /**
43
+ * Get subscribed channels
44
+ */
45
+ get channels() {
46
+ return Array.from(this.connection.subscription.channels);
47
+ }
48
+ /**
49
+ * Get subscription filters
50
+ */
51
+ get filters() {
52
+ return this.connection.subscription.filters;
53
+ }
54
+ /**
55
+ * Check if connection is closed
56
+ */
57
+ get isClosed() {
58
+ return this.closed;
59
+ }
60
+ /**
61
+ * Get last event ID
62
+ */
63
+ get lastEventId() {
64
+ return this.connection.subscription.lastEventId;
65
+ }
66
+ /**
67
+ * Get next sequence number
68
+ */
69
+ nextSequence() {
70
+ return ++this.connection.sequenceCounter;
71
+ }
72
+ /**
73
+ * Start the SSE stream
74
+ * Sets up headers, sends initial connected event, and starts heartbeat
75
+ */
76
+ start() {
77
+ if (this.closed)
78
+ return;
79
+ const res = this.connection.response;
80
+ // SSE headers
81
+ res.setHeader('Content-Type', 'text/event-stream');
82
+ res.setHeader('Cache-Control', 'no-cache, no-transform');
83
+ res.setHeader('Connection', 'keep-alive');
84
+ res.setHeader('X-Accel-Buffering', 'no'); // Disable nginx buffering
85
+ // Prevent compression which can buffer events
86
+ res.setHeader('Content-Encoding', 'identity');
87
+ // Send initial connected event
88
+ const connectedEvent = createConnectedEvent(this.connection.id, this.channels, this.nextSequence());
89
+ this.sendRaw(formatSSEEvent(connectedEvent));
90
+ // Start heartbeat
91
+ this.startHeartbeat();
92
+ }
93
+ /**
94
+ * Send an SSE event
95
+ */
96
+ send(event) {
97
+ if (this.closed)
98
+ return false;
99
+ return this.sendRaw(formatSSEEvent(event));
100
+ }
101
+ /**
102
+ * Send raw SSE data
103
+ */
104
+ sendRaw(data) {
105
+ if (this.closed)
106
+ return false;
107
+ try {
108
+ const res = this.connection.response;
109
+ if (res.writableEnded) {
110
+ this.closed = true;
111
+ return false;
112
+ }
113
+ res.write(data);
114
+ return true;
115
+ }
116
+ catch {
117
+ this.closed = true;
118
+ return false;
119
+ }
120
+ }
121
+ /**
122
+ * Send heartbeat
123
+ */
124
+ sendHeartbeat() {
125
+ return this.sendRaw(formatHeartbeat());
126
+ }
127
+ /**
128
+ * Start heartbeat timer
129
+ */
130
+ startHeartbeat() {
131
+ if (this.connection.heartbeatTimer) {
132
+ clearInterval(this.connection.heartbeatTimer);
133
+ }
134
+ this.connection.heartbeatTimer = setInterval(() => {
135
+ if (!this.sendHeartbeat()) {
136
+ this.close();
137
+ }
138
+ }, this.config.heartbeatInterval);
139
+ }
140
+ /**
141
+ * Stop heartbeat timer
142
+ */
143
+ stopHeartbeat() {
144
+ if (this.connection.heartbeatTimer) {
145
+ clearInterval(this.connection.heartbeatTimer);
146
+ this.connection.heartbeatTimer = undefined;
147
+ }
148
+ }
149
+ /**
150
+ * Check if connection is subscribed to a channel
151
+ */
152
+ isSubscribedTo(channel) {
153
+ return this.connection.subscription.channels.has(channel);
154
+ }
155
+ /**
156
+ * Check if event matches subscription filters
157
+ */
158
+ matchesFilters(workflowId, tags) {
159
+ const filters = this.connection.subscription.filters;
160
+ // No filters = receive all
161
+ if (!filters.workflowId && (!filters.tags || filters.tags.length === 0)) {
162
+ return true;
163
+ }
164
+ // Match workflow ID if filter is set
165
+ if (filters.workflowId && workflowId !== filters.workflowId) {
166
+ return false;
167
+ }
168
+ // Match tags if filter is set
169
+ if (filters.tags && filters.tags.length > 0 && tags) {
170
+ const hasMatchingTag = filters.tags.some((tag) => tags.includes(tag));
171
+ if (!hasMatchingTag) {
172
+ return false;
173
+ }
174
+ }
175
+ return true;
176
+ }
177
+ /**
178
+ * Update subscription channels
179
+ */
180
+ updateChannels(channels) {
181
+ this.connection.subscription.channels = new Set(channels);
182
+ }
183
+ /**
184
+ * Update subscription filters
185
+ */
186
+ updateFilters(filters) {
187
+ this.connection.subscription.filters = { ...this.connection.subscription.filters, ...filters };
188
+ }
189
+ /**
190
+ * Close the connection
191
+ */
192
+ close() {
193
+ if (this.closed)
194
+ return;
195
+ this.closed = true;
196
+ this.stopHeartbeat();
197
+ try {
198
+ if (!this.connection.response.writableEnded) {
199
+ this.connection.response.end();
200
+ }
201
+ }
202
+ catch {
203
+ // Ignore errors during close
204
+ }
205
+ }
206
+ /**
207
+ * Get connection info for logging
208
+ */
209
+ getInfo() {
210
+ return {
211
+ id: this.connection.id,
212
+ userId: this.connection.userId,
213
+ channels: this.channels,
214
+ connectedAt: this.connection.connectedAt,
215
+ filters: this.connection.subscription.filters,
216
+ };
217
+ }
218
+ }
219
+ /**
220
+ * Create SSE response and return stream manager
221
+ */
222
+ export function createSSEStream(reply, request, userId, options = {}, config = {}) {
223
+ // Access raw response - mark reply as sent to prevent Fastify from handling it
224
+ const response = reply.raw;
225
+ // Create stream manager
226
+ const stream = new SSEStream(response, request, userId, options, config);
227
+ return stream;
228
+ }
229
+ /**
230
+ * Parse Last-Event-ID header for reconnection support
231
+ */
232
+ export function parseLastEventId(request) {
233
+ const lastEventId = request.headers['last-event-id'];
234
+ if (!lastEventId || typeof lastEventId !== 'string') {
235
+ return null;
236
+ }
237
+ return parseEventId(lastEventId);
238
+ }
239
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/sse/stream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import type { SSEChannel, SSEFilters, SSEEvent, WorkflowSSEEvent, SSEStreamConfig } from '../types/sse.js';
2
+ import { SSEStream } from './stream.js';
3
+ /**
4
+ * SSE Subscription Manager
5
+ * Manages SSE connections, channel subscriptions, and event broadcasting
6
+ */
7
+ export declare class SSESubscriptionManager {
8
+ private connections;
9
+ private channelSubscribers;
10
+ private userConnections;
11
+ private eventBuffer;
12
+ private config;
13
+ constructor(config?: Partial<SSEStreamConfig>);
14
+ /**
15
+ * Add a new SSE connection
16
+ */
17
+ addConnection(stream: SSEStream): boolean;
18
+ /**
19
+ * Remove an SSE connection
20
+ */
21
+ removeConnection(connectionId: string): void;
22
+ /**
23
+ * Get connection by ID
24
+ */
25
+ getConnection(connectionId: string): SSEStream | undefined;
26
+ /**
27
+ * Get all connections for a user
28
+ */
29
+ getUserConnections(userId: string): SSEStream[];
30
+ /**
31
+ * Get subscribers for a channel
32
+ */
33
+ getChannelSubscribers(channel: SSEChannel): SSEStream[];
34
+ /**
35
+ * Broadcast event to all subscribers of a channel
36
+ */
37
+ broadcast<T>(channel: SSEChannel, event: SSEEvent<T>): number;
38
+ /**
39
+ * Broadcast event with filter matching
40
+ */
41
+ broadcastFiltered<T>(channel: SSEChannel, event: SSEEvent<T>, matcher: (filters: SSEFilters) => boolean): number;
42
+ /**
43
+ * Broadcast workflow event with filter matching
44
+ */
45
+ broadcastWorkflowEvent(event: WorkflowSSEEvent): number;
46
+ /**
47
+ * Send event to a specific connection
48
+ */
49
+ send<T>(connectionId: string, event: SSEEvent<T>): boolean;
50
+ /**
51
+ * Buffer event for reconnection replay
52
+ */
53
+ private bufferEvent;
54
+ /**
55
+ * Get missed events since last event ID for reconnection
56
+ */
57
+ getMissedEvents(lastEventId: string, channels: SSEChannel[]): SSEEvent<unknown>[];
58
+ /**
59
+ * Replay missed events to a connection
60
+ */
61
+ replayMissedEvents(stream: SSEStream): number;
62
+ /**
63
+ * Get total connection count
64
+ */
65
+ getTotalConnections(): number;
66
+ /**
67
+ * Get connection count per channel
68
+ */
69
+ getChannelCounts(): Record<SSEChannel, number>;
70
+ /**
71
+ * Get connection count per user
72
+ */
73
+ getUserCounts(): Map<string, number>;
74
+ /**
75
+ * Close all connections
76
+ */
77
+ closeAll(): void;
78
+ /**
79
+ * Clear all (for testing)
80
+ */
81
+ clear(): void;
82
+ }
83
+ /**
84
+ * Get the SSE subscription manager instance
85
+ */
86
+ export declare function getSSESubscriptionManager(): SSESubscriptionManager;
87
+ /**
88
+ * Reset SSE subscription manager (for testing)
89
+ */
90
+ export declare function resetSSESubscriptionManager(): void;
91
+ //# sourceMappingURL=subscriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.d.ts","sourceRoot":"","sources":["../../src/sse/subscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAWxC;;;GAGG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,WAAW,CAAqC;IACxD,OAAO,CAAC,kBAAkB,CAA2C;IACrE,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,MAAM,CAAkB;gBAEpB,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IASjD;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO;IAyBzC;;OAEG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAuB5C;;OAEG;IACH,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI1D;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE;IAS/C;;OAEG;IACH,qBAAqB,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,EAAE;IAOvD;;OAEG;IACH,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM;IAmB7D;;OAEG;IACH,iBAAiB,CAAC,CAAC,EACjB,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAClB,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,OAAO,GACxC,MAAM;IAuBT;;OAEG;IACH,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM;IAiBvD;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO;IAY1D;;OAEG;IACH,OAAO,CAAC,WAAW;IA2BnB;;OAEG;IACH,eAAe,CACb,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,UAAU,EAAE,GACrB,QAAQ,CAAC,OAAO,CAAC,EAAE;IAyBtB;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM;IAkB7C;;OAEG;IACH,mBAAmB,IAAI,MAAM;IAI7B;;OAEG;IACH,gBAAgB,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC;IAQ9C;;OAEG;IACH,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAQpC;;OAEG;IACH,QAAQ,IAAI,IAAI;IAYhB;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd;AAKD;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,sBAAsB,CAKlE;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAGlD"}
@@ -0,0 +1,299 @@
1
+ import { DEFAULT_SSE_CONFIG } from '../types/sse.js';
2
+ /**
3
+ * SSE Subscription Manager
4
+ * Manages SSE connections, channel subscriptions, and event broadcasting
5
+ */
6
+ export class SSESubscriptionManager {
7
+ connections = new Map();
8
+ channelSubscribers = new Map();
9
+ userConnections = new Map();
10
+ eventBuffer = [];
11
+ config;
12
+ constructor(config = {}) {
13
+ this.config = { ...DEFAULT_SSE_CONFIG, ...config };
14
+ // Initialize channel sets
15
+ this.channelSubscribers.set('workflows', new Set());
16
+ this.channelSubscribers.set('queue', new Set());
17
+ this.channelSubscribers.set('agents', new Set());
18
+ }
19
+ /**
20
+ * Add a new SSE connection
21
+ */
22
+ addConnection(stream) {
23
+ const connectionId = stream.id;
24
+ const userId = stream.userId;
25
+ // Check per-user connection limit
26
+ const userConns = this.userConnections.get(userId) || new Set();
27
+ if (userConns.size >= this.config.maxConnectionsPerClient) {
28
+ return false;
29
+ }
30
+ // Store connection
31
+ this.connections.set(connectionId, stream);
32
+ // Track per-user
33
+ userConns.add(connectionId);
34
+ this.userConnections.set(userId, userConns);
35
+ // Subscribe to channels
36
+ for (const channel of stream.channels) {
37
+ this.channelSubscribers.get(channel)?.add(connectionId);
38
+ }
39
+ return true;
40
+ }
41
+ /**
42
+ * Remove an SSE connection
43
+ */
44
+ removeConnection(connectionId) {
45
+ const stream = this.connections.get(connectionId);
46
+ if (!stream)
47
+ return;
48
+ // Remove from channel sets
49
+ for (const channel of stream.channels) {
50
+ this.channelSubscribers.get(channel)?.delete(connectionId);
51
+ }
52
+ // Remove from user tracking
53
+ const userConns = this.userConnections.get(stream.userId);
54
+ if (userConns) {
55
+ userConns.delete(connectionId);
56
+ if (userConns.size === 0) {
57
+ this.userConnections.delete(stream.userId);
58
+ }
59
+ }
60
+ // Close stream and remove
61
+ stream.close();
62
+ this.connections.delete(connectionId);
63
+ }
64
+ /**
65
+ * Get connection by ID
66
+ */
67
+ getConnection(connectionId) {
68
+ return this.connections.get(connectionId);
69
+ }
70
+ /**
71
+ * Get all connections for a user
72
+ */
73
+ getUserConnections(userId) {
74
+ const connectionIds = this.userConnections.get(userId);
75
+ if (!connectionIds)
76
+ return [];
77
+ return Array.from(connectionIds)
78
+ .map((id) => this.connections.get(id))
79
+ .filter((stream) => stream !== undefined);
80
+ }
81
+ /**
82
+ * Get subscribers for a channel
83
+ */
84
+ getChannelSubscribers(channel) {
85
+ const connectionIds = this.channelSubscribers.get(channel) || new Set();
86
+ return Array.from(connectionIds)
87
+ .map((id) => this.connections.get(id))
88
+ .filter((stream) => stream !== undefined && !stream.isClosed);
89
+ }
90
+ /**
91
+ * Broadcast event to all subscribers of a channel
92
+ */
93
+ broadcast(channel, event) {
94
+ const subscribers = this.getChannelSubscribers(channel);
95
+ let sentCount = 0;
96
+ for (const stream of subscribers) {
97
+ if (stream.send(event)) {
98
+ sentCount++;
99
+ }
100
+ else {
101
+ // Connection closed, remove it
102
+ this.removeConnection(stream.id);
103
+ }
104
+ }
105
+ // Buffer event for reconnection replay
106
+ this.bufferEvent(event, channel);
107
+ return sentCount;
108
+ }
109
+ /**
110
+ * Broadcast event with filter matching
111
+ */
112
+ broadcastFiltered(channel, event, matcher) {
113
+ const subscribers = this.getChannelSubscribers(channel);
114
+ let sentCount = 0;
115
+ for (const stream of subscribers) {
116
+ // Apply filter matching
117
+ if (!matcher(stream.filters)) {
118
+ continue;
119
+ }
120
+ if (stream.send(event)) {
121
+ sentCount++;
122
+ }
123
+ else {
124
+ this.removeConnection(stream.id);
125
+ }
126
+ }
127
+ // Buffer event for reconnection replay
128
+ this.bufferEvent(event, channel);
129
+ return sentCount;
130
+ }
131
+ /**
132
+ * Broadcast workflow event with filter matching
133
+ */
134
+ broadcastWorkflowEvent(event) {
135
+ return this.broadcastFiltered('workflows', event, (filters) => {
136
+ // No filters = receive all
137
+ if (!filters.workflowId && (!filters.tags || filters.tags.length === 0)) {
138
+ return true;
139
+ }
140
+ // Match workflow ID
141
+ if (filters.workflowId && filters.workflowId !== event.data.workflowId) {
142
+ return false;
143
+ }
144
+ // Tags would need to be in the message payload - for now, pass if workflow matches
145
+ return true;
146
+ });
147
+ }
148
+ /**
149
+ * Send event to a specific connection
150
+ */
151
+ send(connectionId, event) {
152
+ const stream = this.connections.get(connectionId);
153
+ if (!stream || stream.isClosed) {
154
+ if (stream) {
155
+ this.removeConnection(connectionId);
156
+ }
157
+ return false;
158
+ }
159
+ return stream.send(event);
160
+ }
161
+ /**
162
+ * Buffer event for reconnection replay
163
+ */
164
+ bufferEvent(event, channel) {
165
+ const now = Date.now();
166
+ // Add to buffer
167
+ this.eventBuffer.push({
168
+ event: event,
169
+ timestamp: now,
170
+ channel,
171
+ });
172
+ // Trim buffer by size
173
+ while (this.eventBuffer.length > this.config.eventBufferSize) {
174
+ this.eventBuffer.shift();
175
+ }
176
+ // Trim buffer by age
177
+ const cutoff = now - this.config.eventRetentionMs;
178
+ while (this.eventBuffer.length > 0) {
179
+ const oldest = this.eventBuffer[0];
180
+ if (oldest && oldest.timestamp < cutoff) {
181
+ this.eventBuffer.shift();
182
+ }
183
+ else {
184
+ break;
185
+ }
186
+ }
187
+ }
188
+ /**
189
+ * Get missed events since last event ID for reconnection
190
+ */
191
+ getMissedEvents(lastEventId, channels) {
192
+ // Parse the last event ID to get timestamp
193
+ const parts = lastEventId.split('_');
194
+ if (parts.length < 1)
195
+ return [];
196
+ const firstPart = parts[0];
197
+ if (!firstPart)
198
+ return [];
199
+ const lastTimestamp = parseInt(firstPart, 10);
200
+ if (isNaN(lastTimestamp))
201
+ return [];
202
+ // Find events after the last received
203
+ return this.eventBuffer
204
+ .filter((buffered) => {
205
+ // Must be after last event
206
+ if (buffered.timestamp <= lastTimestamp)
207
+ return false;
208
+ // Must be in subscribed channels
209
+ if (!channels.includes(buffered.channel))
210
+ return false;
211
+ return true;
212
+ })
213
+ .map((buffered) => buffered.event);
214
+ }
215
+ /**
216
+ * Replay missed events to a connection
217
+ */
218
+ replayMissedEvents(stream) {
219
+ const lastEventId = stream.lastEventId;
220
+ if (!lastEventId)
221
+ return 0;
222
+ const missedEvents = this.getMissedEvents(lastEventId, stream.channels);
223
+ let replayedCount = 0;
224
+ for (const event of missedEvents) {
225
+ if (stream.send(event)) {
226
+ replayedCount++;
227
+ }
228
+ else {
229
+ break;
230
+ }
231
+ }
232
+ return replayedCount;
233
+ }
234
+ /**
235
+ * Get total connection count
236
+ */
237
+ getTotalConnections() {
238
+ return this.connections.size;
239
+ }
240
+ /**
241
+ * Get connection count per channel
242
+ */
243
+ getChannelCounts() {
244
+ return {
245
+ workflows: this.channelSubscribers.get('workflows')?.size || 0,
246
+ queue: this.channelSubscribers.get('queue')?.size || 0,
247
+ agents: this.channelSubscribers.get('agents')?.size || 0,
248
+ };
249
+ }
250
+ /**
251
+ * Get connection count per user
252
+ */
253
+ getUserCounts() {
254
+ const counts = new Map();
255
+ for (const [userId, connections] of this.userConnections) {
256
+ counts.set(userId, connections.size);
257
+ }
258
+ return counts;
259
+ }
260
+ /**
261
+ * Close all connections
262
+ */
263
+ closeAll() {
264
+ for (const stream of this.connections.values()) {
265
+ stream.close();
266
+ }
267
+ this.connections.clear();
268
+ this.userConnections.clear();
269
+ this.channelSubscribers.get('workflows')?.clear();
270
+ this.channelSubscribers.get('queue')?.clear();
271
+ this.channelSubscribers.get('agents')?.clear();
272
+ this.eventBuffer = [];
273
+ }
274
+ /**
275
+ * Clear all (for testing)
276
+ */
277
+ clear() {
278
+ this.closeAll();
279
+ }
280
+ }
281
+ // Singleton instance
282
+ let subscriptionManager = null;
283
+ /**
284
+ * Get the SSE subscription manager instance
285
+ */
286
+ export function getSSESubscriptionManager() {
287
+ if (!subscriptionManager) {
288
+ subscriptionManager = new SSESubscriptionManager();
289
+ }
290
+ return subscriptionManager;
291
+ }
292
+ /**
293
+ * Reset SSE subscription manager (for testing)
294
+ */
295
+ export function resetSSESubscriptionManager() {
296
+ subscriptionManager?.clear();
297
+ subscriptionManager = null;
298
+ }
299
+ //# sourceMappingURL=subscriptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.js","sourceRoot":"","sources":["../../src/sse/subscriptions.ts"],"names":[],"mappings":"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"}