@sudocode-ai/local-server 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/cli.js +6 -104
  2. package/dist/cli.js.map +1 -7
  3. package/dist/execution/engine/engine.js +10 -0
  4. package/dist/execution/engine/engine.js.map +1 -0
  5. package/dist/execution/engine/simple-engine.js +611 -0
  6. package/dist/execution/engine/simple-engine.js.map +1 -0
  7. package/dist/execution/engine/types.js +10 -0
  8. package/dist/execution/engine/types.js.map +1 -0
  9. package/dist/execution/output/ag-ui-adapter.js +438 -0
  10. package/dist/execution/output/ag-ui-adapter.js.map +1 -0
  11. package/dist/execution/output/ag-ui-integration.js +96 -0
  12. package/dist/execution/output/ag-ui-integration.js.map +1 -0
  13. package/dist/execution/output/claude-code-output-processor.js +769 -0
  14. package/dist/execution/output/claude-code-output-processor.js.map +1 -0
  15. package/dist/execution/output/index.js +15 -0
  16. package/dist/execution/output/index.js.map +1 -0
  17. package/dist/execution/output/types.js +22 -0
  18. package/dist/execution/output/types.js.map +1 -0
  19. package/dist/execution/process/builders/claude.js +59 -0
  20. package/dist/execution/process/builders/claude.js.map +1 -0
  21. package/dist/execution/process/index.js +15 -0
  22. package/dist/execution/process/index.js.map +1 -0
  23. package/dist/execution/process/manager.js +10 -0
  24. package/dist/execution/process/manager.js.map +1 -0
  25. package/dist/execution/process/simple-manager.js +336 -0
  26. package/dist/execution/process/simple-manager.js.map +1 -0
  27. package/dist/execution/process/types.js +10 -0
  28. package/dist/execution/process/types.js.map +1 -0
  29. package/dist/execution/process/utils.js +97 -0
  30. package/dist/execution/process/utils.js.map +1 -0
  31. package/dist/execution/resilience/circuit-breaker.js +291 -0
  32. package/dist/execution/resilience/circuit-breaker.js.map +1 -0
  33. package/dist/execution/resilience/executor.js +10 -0
  34. package/dist/execution/resilience/executor.js.map +1 -0
  35. package/dist/execution/resilience/index.js +15 -0
  36. package/dist/execution/resilience/index.js.map +1 -0
  37. package/dist/execution/resilience/resilient-executor.js +261 -0
  38. package/dist/execution/resilience/resilient-executor.js.map +1 -0
  39. package/dist/execution/resilience/retry.js +234 -0
  40. package/dist/execution/resilience/retry.js.map +1 -0
  41. package/dist/execution/resilience/types.js +30 -0
  42. package/dist/execution/resilience/types.js.map +1 -0
  43. package/dist/execution/transport/event-buffer.js +208 -0
  44. package/dist/execution/transport/event-buffer.js.map +1 -0
  45. package/dist/execution/transport/index.js +10 -0
  46. package/dist/execution/transport/index.js.map +1 -0
  47. package/dist/execution/transport/sse-transport.js +282 -0
  48. package/dist/execution/transport/sse-transport.js.map +1 -0
  49. package/dist/execution/transport/transport-manager.js +231 -0
  50. package/dist/execution/transport/transport-manager.js.map +1 -0
  51. package/dist/execution/workflow/index.js +13 -0
  52. package/dist/execution/workflow/index.js.map +1 -0
  53. package/dist/execution/workflow/linear-orchestrator.js +683 -0
  54. package/dist/execution/workflow/linear-orchestrator.js.map +1 -0
  55. package/dist/execution/workflow/memory-storage.js +68 -0
  56. package/dist/execution/workflow/memory-storage.js.map +1 -0
  57. package/dist/execution/workflow/orchestrator.js +9 -0
  58. package/dist/execution/workflow/orchestrator.js.map +1 -0
  59. package/dist/execution/workflow/types.js +9 -0
  60. package/dist/execution/workflow/types.js.map +1 -0
  61. package/dist/execution/workflow/utils.js +152 -0
  62. package/dist/execution/workflow/utils.js.map +1 -0
  63. package/dist/execution/worktree/config.js +280 -0
  64. package/dist/execution/worktree/config.js.map +1 -0
  65. package/dist/execution/worktree/git-cli.js +189 -0
  66. package/dist/execution/worktree/git-cli.js.map +1 -0
  67. package/dist/execution/worktree/index.js +15 -0
  68. package/dist/execution/worktree/index.js.map +1 -0
  69. package/dist/execution/worktree/manager.js +452 -0
  70. package/dist/execution/worktree/manager.js.map +1 -0
  71. package/dist/execution/worktree/types.js +42 -0
  72. package/dist/execution/worktree/types.js.map +1 -0
  73. package/dist/index.js +356 -104
  74. package/dist/index.js.map +1 -7
  75. package/dist/routes/executions-stream.js +55 -0
  76. package/dist/routes/executions-stream.js.map +1 -0
  77. package/dist/routes/executions.js +267 -0
  78. package/dist/routes/executions.js.map +1 -0
  79. package/dist/routes/feedback.js +329 -0
  80. package/dist/routes/feedback.js.map +1 -0
  81. package/dist/routes/issues.js +280 -0
  82. package/dist/routes/issues.js.map +1 -0
  83. package/dist/routes/relationships.js +308 -0
  84. package/dist/routes/relationships.js.map +1 -0
  85. package/dist/routes/specs.js +270 -0
  86. package/dist/routes/specs.js.map +1 -0
  87. package/dist/services/db.js +85 -0
  88. package/dist/services/db.js.map +1 -0
  89. package/dist/services/execution-lifecycle.js +286 -0
  90. package/dist/services/execution-lifecycle.js.map +1 -0
  91. package/dist/services/execution-service.js +676 -0
  92. package/dist/services/execution-service.js.map +1 -0
  93. package/dist/services/executions.js +164 -0
  94. package/dist/services/executions.js.map +1 -0
  95. package/dist/services/export.js +106 -0
  96. package/dist/services/export.js.map +1 -0
  97. package/dist/services/feedback.js +54 -0
  98. package/dist/services/feedback.js.map +1 -0
  99. package/dist/services/issues.js +35 -0
  100. package/dist/services/issues.js.map +1 -0
  101. package/dist/services/prompt-template-engine.js +212 -0
  102. package/dist/services/prompt-template-engine.js.map +1 -0
  103. package/dist/services/prompt-templates.js +236 -0
  104. package/dist/services/prompt-templates.js.map +1 -0
  105. package/dist/services/relationships.js +42 -0
  106. package/dist/services/relationships.js.map +1 -0
  107. package/dist/services/specs.js +35 -0
  108. package/dist/services/specs.js.map +1 -0
  109. package/dist/services/watcher.js +69 -0
  110. package/dist/services/watcher.js.map +1 -0
  111. package/dist/services/websocket.js +389 -0
  112. package/dist/services/websocket.js.map +1 -0
  113. package/dist/utils/sudocode-dir.js +9 -0
  114. package/dist/utils/sudocode-dir.js.map +1 -0
  115. package/package.json +4 -6
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Server-Sent Events (SSE) Transport Layer
3
+ *
4
+ * Provides real-time streaming of AG-UI events to frontend clients using SSE.
5
+ * Supports connection management, heartbeat, and run-specific event filtering.
6
+ *
7
+ * @module execution/transport/sse-transport
8
+ */
9
+ /**
10
+ * SseTransport - Server-Sent Events transport for AG-UI events
11
+ *
12
+ * Manages SSE connections and streams AG-UI protocol events to connected clients.
13
+ * Supports multiple concurrent connections, heartbeat mechanism, and run-specific filtering.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const transport = new SseTransport();
18
+ *
19
+ * // Handle new connection
20
+ * app.get('/api/events', (req, res) => {
21
+ * const clientId = req.query.clientId as string;
22
+ * const runId = req.query.runId as string | undefined;
23
+ * transport.handleConnection(clientId, res, runId);
24
+ * });
25
+ *
26
+ * // Send event to specific client
27
+ * transport.sendToClient('client-123', {
28
+ * event: 'TOOL_CALL_START',
29
+ * data: { type: 'TOOL_CALL_START', toolCallId: 'tool-1' }
30
+ * });
31
+ *
32
+ * // Broadcast to all clients watching a specific run
33
+ * transport.broadcastToRun('run-123', {
34
+ * event: 'RUN_FINISHED',
35
+ * data: { type: 'RUN_FINISHED', runId: 'run-123' }
36
+ * });
37
+ * ```
38
+ */
39
+ export class SseTransport {
40
+ clients = new Map();
41
+ heartbeatInterval = null;
42
+ HEARTBEAT_INTERVAL_MS = 30000; // 30 seconds
43
+ /**
44
+ * Create a new SSE transport instance
45
+ */
46
+ constructor() {
47
+ this.startHeartbeat();
48
+ }
49
+ /**
50
+ * Handle a new SSE connection from a client
51
+ *
52
+ * Sets up proper SSE headers, registers the client, and handles cleanup on disconnect.
53
+ *
54
+ * @param clientId - Unique identifier for this client
55
+ * @param res - Express response object
56
+ * @param runId - Optional run ID to filter events
57
+ * @param replayEvents - Optional: buffered events to replay to this client
58
+ */
59
+ handleConnection(clientId, res, runId, replayEvents) {
60
+ // Set SSE headers
61
+ res.setHeader("Content-Type", "text/event-stream");
62
+ res.setHeader("Cache-Control", "no-cache");
63
+ res.setHeader("Connection", "keep-alive");
64
+ res.setHeader("X-Accel-Buffering", "no"); // Disable nginx buffering
65
+ // Enable CORS for SSE (if needed)
66
+ res.setHeader("Access-Control-Allow-Origin", "*");
67
+ // Disable compression for SSE
68
+ res.flushHeaders();
69
+ const client = {
70
+ clientId,
71
+ response: res,
72
+ runId,
73
+ connectedAt: new Date(),
74
+ lastActivity: new Date(),
75
+ };
76
+ this.clients.set(clientId, client);
77
+ // Send initial connection acknowledgment
78
+ this.sendToClient(clientId, {
79
+ event: "connected",
80
+ data: {
81
+ clientId,
82
+ runId,
83
+ timestamp: Date.now(),
84
+ },
85
+ });
86
+ // Replay buffered events if provided
87
+ if (replayEvents && replayEvents.length > 0) {
88
+ for (const event of replayEvents) {
89
+ this.sendToClient(clientId, event);
90
+ }
91
+ }
92
+ // Handle client disconnect
93
+ res.on("close", () => {
94
+ this.removeClient(clientId);
95
+ });
96
+ }
97
+ /**
98
+ * Send an event to a specific client
99
+ *
100
+ * @param clientId - Target client ID
101
+ * @param event - Event to send
102
+ * @returns true if sent successfully, false if client not found
103
+ */
104
+ sendToClient(clientId, event) {
105
+ const client = this.clients.get(clientId);
106
+ if (!client) {
107
+ return false;
108
+ }
109
+ return this.writeEvent(client, event);
110
+ }
111
+ /**
112
+ * Broadcast an event to all connected clients
113
+ *
114
+ * @param event - Event to broadcast
115
+ * @returns Number of clients that received the event
116
+ */
117
+ broadcast(event) {
118
+ let sentCount = 0;
119
+ for (const client of this.clients.values()) {
120
+ if (this.writeEvent(client, event)) {
121
+ sentCount++;
122
+ }
123
+ }
124
+ return sentCount;
125
+ }
126
+ /**
127
+ * Broadcast an event to all clients watching a specific run
128
+ *
129
+ * @param runId - Target run ID
130
+ * @param event - Event to send
131
+ * @returns Number of clients that received the event
132
+ */
133
+ broadcastToRun(runId, event) {
134
+ let sentCount = 0;
135
+ let matchingClients = 0;
136
+ for (const client of this.clients.values()) {
137
+ if (client.runId === runId) {
138
+ matchingClients++;
139
+ if (this.writeEvent(client, event)) {
140
+ sentCount++;
141
+ }
142
+ }
143
+ }
144
+ return sentCount;
145
+ }
146
+ /**
147
+ * Remove a client connection
148
+ *
149
+ * @param clientId - Client to remove
150
+ * @returns true if client was removed, false if not found
151
+ */
152
+ removeClient(clientId) {
153
+ const client = this.clients.get(clientId);
154
+ if (!client) {
155
+ return false;
156
+ }
157
+ // Try to close the response if it's still open
158
+ try {
159
+ if (!client.response.writableEnded) {
160
+ client.response.end();
161
+ }
162
+ }
163
+ catch (error) {
164
+ // Connection already closed, ignore
165
+ }
166
+ this.clients.delete(clientId);
167
+ return true;
168
+ }
169
+ /**
170
+ * Get the number of active connections
171
+ *
172
+ * @returns Number of connected clients
173
+ */
174
+ getClientCount() {
175
+ return this.clients.size;
176
+ }
177
+ /**
178
+ * Get the number of clients watching a specific run
179
+ *
180
+ * @param runId - Run ID to check
181
+ * @returns Number of clients watching this run
182
+ */
183
+ getRunClientCount(runId) {
184
+ let count = 0;
185
+ for (const client of this.clients.values()) {
186
+ if (client.runId === runId) {
187
+ count++;
188
+ }
189
+ }
190
+ return count;
191
+ }
192
+ /**
193
+ * Get all active client IDs
194
+ *
195
+ * @returns Array of client IDs
196
+ */
197
+ getClientIds() {
198
+ return Array.from(this.clients.keys());
199
+ }
200
+ /**
201
+ * Shutdown the transport and close all connections
202
+ */
203
+ shutdown() {
204
+ // Stop heartbeat
205
+ if (this.heartbeatInterval) {
206
+ clearInterval(this.heartbeatInterval);
207
+ this.heartbeatInterval = null;
208
+ }
209
+ // Close all client connections
210
+ for (const clientId of this.clients.keys()) {
211
+ this.removeClient(clientId);
212
+ }
213
+ }
214
+ /**
215
+ * Write an event to a client connection
216
+ *
217
+ * Formats the event according to SSE specification and writes it to the response.
218
+ *
219
+ * @param client - Target client
220
+ * @param event - Event to write
221
+ * @returns true if successful, false if write failed
222
+ */
223
+ writeEvent(client, event) {
224
+ try {
225
+ const { response } = client;
226
+ // Check if response is still writable
227
+ if (response.writableEnded || !response.writable) {
228
+ this.removeClient(client.clientId);
229
+ return false;
230
+ }
231
+ // Format SSE message
232
+ let message = "";
233
+ // Add event type if specified
234
+ if (event.event) {
235
+ message += `event: ${event.event}\n`;
236
+ }
237
+ // Add event ID if specified
238
+ if (event.id) {
239
+ message += `id: ${event.id}\n`;
240
+ }
241
+ // Add data (JSON stringify if object)
242
+ const dataString = typeof event.data === "string"
243
+ ? event.data
244
+ : JSON.stringify(event.data);
245
+ // SSE spec requires data to be on separate lines if multiline
246
+ const dataLines = dataString.split("\n");
247
+ for (const line of dataLines) {
248
+ message += `data: ${line}\n`;
249
+ }
250
+ // SSE messages end with double newline
251
+ message += "\n";
252
+ // Write to response
253
+ response.write(message);
254
+ // Update last activity
255
+ client.lastActivity = new Date();
256
+ return true;
257
+ }
258
+ catch (error) {
259
+ // Connection error, remove client
260
+ this.removeClient(client.clientId);
261
+ return false;
262
+ }
263
+ }
264
+ /**
265
+ * Start the heartbeat mechanism
266
+ *
267
+ * Sends periodic ping events to keep connections alive
268
+ */
269
+ startHeartbeat() {
270
+ this.heartbeatInterval = setInterval(() => {
271
+ const pingEvent = {
272
+ event: "ping",
273
+ data: { timestamp: Date.now() },
274
+ };
275
+ // Send ping to all clients
276
+ for (const client of this.clients.values()) {
277
+ this.writeEvent(client, pingEvent);
278
+ }
279
+ }, this.HEARTBEAT_INTERVAL_MS);
280
+ }
281
+ }
282
+ //# sourceMappingURL=sse-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-transport.js","sourceRoot":"","sources":["../../../src/execution/transport/sse-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAoCH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,OAAO,YAAY;IACf,OAAO,GAA2B,IAAI,GAAG,EAAE,CAAC;IAC5C,iBAAiB,GAA0B,IAAI,CAAC;IACvC,qBAAqB,GAAG,KAAK,CAAC,CAAC,aAAa;IAE7D;;OAEG;IACH;QACE,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED;;;;;;;;;OASG;IACH,gBAAgB,CACd,QAAgB,EAChB,GAAa,EACb,KAAc,EACd,YAAkD;QAElD,kBAAkB;QAClB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;QACnD,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QAC3C,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAC1C,GAAG,CAAC,SAAS,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC,CAAC,0BAA0B;QAEpE,kCAAkC;QAClC,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QAElD,8BAA8B;QAC9B,GAAG,CAAC,YAAY,EAAE,CAAC;QAEnB,MAAM,MAAM,GAAc;YACxB,QAAQ;YACR,QAAQ,EAAE,GAAG;YACb,KAAK;YACL,WAAW,EAAE,IAAI,IAAI,EAAE;YACvB,YAAY,EAAE,IAAI,IAAI,EAAE;SACzB,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAEnC,yCAAyC;QACzC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE;YAC1B,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE;gBACJ,QAAQ;gBACR,KAAK;gBACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB;SACF,CAAC,CAAC;QAEH,qCAAqC;QACrC,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5C,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;gBACjC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QAED,2BAA2B;QAC3B,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACnB,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,YAAY,CAAC,QAAgB,EAAE,KAAe;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,KAAe;QACvB,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;gBACnC,SAAS,EAAE,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;OAMG;IACH,cAAc,CAAC,KAAa,EAAE,KAAe;QAC3C,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,eAAe,GAAG,CAAC,CAAC;QAExB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;gBAC3B,eAAe,EAAE,CAAC;gBAClB,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;oBACnC,SAAS,EAAE,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,QAAgB;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC;QACf,CAAC;QAED,+CAA+C;QAC/C,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;gBACnC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;YACxB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,oCAAoC;QACtC,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACH,iBAAiB,CAAC,KAAa;QAC7B,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;gBAC3B,KAAK,EAAE,CAAC;YACV,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACH,YAAY;QACV,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,iBAAiB;QACjB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,aAAa,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACtC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAChC,CAAC;QAED,+BAA+B;QAC/B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACK,UAAU,CAAC,MAAiB,EAAE,KAAe;QACnD,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;YAE5B,sCAAsC;YACtC,IAAI,QAAQ,CAAC,aAAa,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACjD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACnC,OAAO,KAAK,CAAC;YACf,CAAC;YAED,qBAAqB;YACrB,IAAI,OAAO,GAAG,EAAE,CAAC;YAEjB,8BAA8B;YAC9B,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,OAAO,IAAI,UAAU,KAAK,CAAC,KAAK,IAAI,CAAC;YACvC,CAAC;YAED,4BAA4B;YAC5B,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;gBACb,OAAO,IAAI,OAAO,KAAK,CAAC,EAAE,IAAI,CAAC;YACjC,CAAC;YAED,sCAAsC;YACtC,MAAM,UAAU,GACd,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAC5B,CAAC,CAAC,KAAK,CAAC,IAAI;gBACZ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAEjC,8DAA8D;YAC9D,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,OAAO,IAAI,SAAS,IAAI,IAAI,CAAC;YAC/B,CAAC;YAED,uCAAuC;YACvC,OAAO,IAAI,IAAI,CAAC;YAEhB,oBAAoB;YACpB,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAExB,uBAAuB;YACvB,MAAM,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC;YAEjC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kCAAkC;YAClC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACnC,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,cAAc;QACpB,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC,GAAG,EAAE;YACxC,MAAM,SAAS,GAAa;gBAC1B,KAAK,EAAE,MAAM;gBACb,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;aAChC,CAAC;YAEF,2BAA2B;YAC3B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;gBAC3C,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YACrC,CAAC;QACH,CAAC,EAAE,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACjC,CAAC;CACF"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Transport Manager
3
+ *
4
+ * Coordinates between AG-UI adapter and SSE transport layer.
5
+ * Acts as a facade that routes adapter events to appropriate transport methods.
6
+ *
7
+ * @module execution/transport/transport-manager
8
+ */
9
+ import { SseTransport } from "./sse-transport.js";
10
+ import { EventBuffer } from "./event-buffer.js";
11
+ /**
12
+ * TransportManager - Coordinates AG-UI events with SSE transport
13
+ *
14
+ * Manages the connection between AG-UI adapters and SSE transport,
15
+ * routing events to appropriate broadcast methods based on run filtering.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const manager = new TransportManager();
20
+ * const adapter = new AgUiEventAdapter('run-123');
21
+ *
22
+ * // Connect adapter to transport
23
+ * manager.connectAdapter(adapter, 'run-123');
24
+ *
25
+ * // Events from adapter are now automatically broadcast via SSE
26
+ * ```
27
+ */
28
+ export class TransportManager {
29
+ sseTransport;
30
+ eventBuffer;
31
+ adapterListeners = new Map();
32
+ pruneInterval = null;
33
+ /**
34
+ * Create a new transport manager
35
+ *
36
+ * Initializes the SSE transport layer and event buffer
37
+ */
38
+ constructor() {
39
+ this.sseTransport = new SseTransport();
40
+ this.eventBuffer = new EventBuffer();
41
+ // Start periodic pruning of stale buffers (every 15 minutes)
42
+ this.pruneInterval = setInterval(() => {
43
+ this.eventBuffer.pruneStale();
44
+ }, 15 * 60 * 1000);
45
+ }
46
+ /**
47
+ * Connect AG-UI adapter to SSE transport
48
+ *
49
+ * Subscribes to adapter's event stream and routes events to SSE transport.
50
+ * If runId is provided, events are broadcast only to clients watching that run.
51
+ * Otherwise, events are broadcast to all connected clients.
52
+ *
53
+ * @param adapter - AG-UI event adapter to connect
54
+ * @param runId - Optional run ID for filtering events
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const adapter = new AgUiEventAdapter('run-123');
59
+ * manager.connectAdapter(adapter, 'run-123');
60
+ * ```
61
+ */
62
+ connectAdapter(adapter, runId) {
63
+ // Create listener function
64
+ const listener = (event) => {
65
+ // Buffer the event if runId is provided
66
+ if (runId) {
67
+ this.eventBuffer.addEvent(runId, event);
68
+ this.broadcastToRun(runId, event);
69
+ }
70
+ else {
71
+ this.broadcast(event);
72
+ }
73
+ };
74
+ // Store listener for cleanup
75
+ this.adapterListeners.set(adapter, listener);
76
+ // Subscribe to adapter events
77
+ adapter.onEvent(listener);
78
+ }
79
+ /**
80
+ * Disconnect AG-UI adapter from transport
81
+ *
82
+ * Removes the adapter's event listener and stops broadcasting its events.
83
+ *
84
+ * @param adapter - AG-UI event adapter to disconnect
85
+ * @returns true if adapter was disconnected, false if not found
86
+ */
87
+ disconnectAdapter(adapter) {
88
+ const listener = this.adapterListeners.get(adapter);
89
+ if (!listener) {
90
+ return false;
91
+ }
92
+ adapter.offEvent(listener);
93
+ this.adapterListeners.delete(adapter);
94
+ return true;
95
+ }
96
+ /**
97
+ * Broadcast event to all connected clients
98
+ *
99
+ * @param event - AG-UI event to broadcast
100
+ * @returns Number of clients that received the event
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * manager.broadcast({
105
+ * type: EventType.RUN_STARTED,
106
+ * runId: 'run-123',
107
+ * threadId: 'run-123',
108
+ * timestamp: Date.now()
109
+ * });
110
+ * ```
111
+ */
112
+ broadcast(event) {
113
+ return this.sseTransport.broadcast({
114
+ event: event.type,
115
+ data: event,
116
+ });
117
+ }
118
+ /**
119
+ * Broadcast event to clients watching a specific run
120
+ *
121
+ * @param runId - Target run ID
122
+ * @param event - AG-UI event to broadcast
123
+ * @returns Number of clients that received the event
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * manager.broadcastToRun('run-123', {
128
+ * type: EventType.TOOL_CALL_START,
129
+ * toolCallId: 'tool-1',
130
+ * toolCallName: 'Read',
131
+ * timestamp: Date.now()
132
+ * });
133
+ * ```
134
+ */
135
+ broadcastToRun(runId, event) {
136
+ const clientCount = this.sseTransport.broadcastToRun(runId, {
137
+ event: event.type,
138
+ data: event,
139
+ });
140
+ return clientCount;
141
+ }
142
+ /**
143
+ * Get underlying SSE transport
144
+ *
145
+ * Provides access to the SSE transport for route handlers
146
+ * that need to manage client connections.
147
+ *
148
+ * @returns SSE transport instance
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * const transport = manager.getSseTransport();
153
+ *
154
+ * // Handle SSE connection in route
155
+ * app.get('/api/events', (req, res) => {
156
+ * transport.handleConnection(clientId, res, runId);
157
+ * });
158
+ * ```
159
+ */
160
+ getSseTransport() {
161
+ return this.sseTransport;
162
+ }
163
+ /**
164
+ * Get number of connected adapters
165
+ *
166
+ * @returns Number of active adapter connections
167
+ */
168
+ getAdapterCount() {
169
+ return this.adapterListeners.size;
170
+ }
171
+ /**
172
+ * Get buffered events for an execution
173
+ *
174
+ * Returns all events that have been buffered for the specified execution.
175
+ * Useful for replaying events to late-joining clients.
176
+ *
177
+ * @param runId - Target run ID
178
+ * @param fromSequence - Optional: only return events >= this sequence number
179
+ * @returns Array of buffered events
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * const events = manager.getBufferedEvents('run-123');
184
+ * for (const buffered of events) {
185
+ * console.log(buffered.event.type, buffered.sequenceNumber);
186
+ * }
187
+ * ```
188
+ */
189
+ getBufferedEvents(runId, fromSequence) {
190
+ return this.eventBuffer.getEvents(runId, fromSequence);
191
+ }
192
+ /**
193
+ * Check if events are buffered for an execution
194
+ *
195
+ * @param runId - Target run ID
196
+ * @returns true if events are buffered
197
+ */
198
+ hasBufferedEvents(runId) {
199
+ return this.eventBuffer.hasBuffer(runId);
200
+ }
201
+ /**
202
+ * Get buffer statistics
203
+ *
204
+ * @returns Buffer statistics
205
+ */
206
+ getBufferStats() {
207
+ return this.eventBuffer.getStats();
208
+ }
209
+ /**
210
+ * Shutdown transport manager
211
+ *
212
+ * Disconnects all adapters and shuts down SSE transport.
213
+ * Closes all client connections and releases resources.
214
+ */
215
+ shutdown() {
216
+ // Stop pruning interval
217
+ if (this.pruneInterval) {
218
+ clearInterval(this.pruneInterval);
219
+ this.pruneInterval = null;
220
+ }
221
+ // Disconnect all adapters
222
+ for (const adapter of this.adapterListeners.keys()) {
223
+ this.disconnectAdapter(adapter);
224
+ }
225
+ // Shutdown SSE transport
226
+ this.sseTransport.shutdown();
227
+ // Clear event buffers
228
+ this.eventBuffer.clearAll();
229
+ }
230
+ }
231
+ //# sourceMappingURL=transport-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-manager.js","sourceRoot":"","sources":["../../../src/execution/transport/transport-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Workflow Layer Exports
3
+ *
4
+ * Layer 4: Task Execution Layer - Workflow Orchestration & State Management
5
+ *
6
+ * @module execution/workflow
7
+ */
8
+ // Utilities
9
+ export { generateId, renderTemplate, extractValue, mergeContext, evaluateCondition, createContext, } from './utils.js';
10
+ // Implementation
11
+ export { LinearOrchestrator } from './linear-orchestrator.js';
12
+ export { InMemoryWorkflowStorage } from './memory-storage.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/execution/workflow/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA0BH,YAAY;AACZ,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,iBAAiB;AACjB,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC"}