@sudocode-ai/local-server 0.1.0 → 0.1.2

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 (117) 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.d.ts.map +1 -1
  74. package/dist/index.js +357 -104
  75. package/dist/index.js.map +1 -7
  76. package/dist/routes/executions-stream.js +55 -0
  77. package/dist/routes/executions-stream.js.map +1 -0
  78. package/dist/routes/executions.js +267 -0
  79. package/dist/routes/executions.js.map +1 -0
  80. package/dist/routes/feedback.js +329 -0
  81. package/dist/routes/feedback.js.map +1 -0
  82. package/dist/routes/issues.js +280 -0
  83. package/dist/routes/issues.js.map +1 -0
  84. package/dist/routes/relationships.js +308 -0
  85. package/dist/routes/relationships.js.map +1 -0
  86. package/dist/routes/specs.js +270 -0
  87. package/dist/routes/specs.js.map +1 -0
  88. package/dist/services/db.js +85 -0
  89. package/dist/services/db.js.map +1 -0
  90. package/dist/services/execution-lifecycle.d.ts.map +1 -1
  91. package/dist/services/execution-lifecycle.js +291 -0
  92. package/dist/services/execution-lifecycle.js.map +1 -0
  93. package/dist/services/execution-service.js +676 -0
  94. package/dist/services/execution-service.js.map +1 -0
  95. package/dist/services/executions.js +164 -0
  96. package/dist/services/executions.js.map +1 -0
  97. package/dist/services/export.js +106 -0
  98. package/dist/services/export.js.map +1 -0
  99. package/dist/services/feedback.js +54 -0
  100. package/dist/services/feedback.js.map +1 -0
  101. package/dist/services/issues.js +35 -0
  102. package/dist/services/issues.js.map +1 -0
  103. package/dist/services/prompt-template-engine.js +212 -0
  104. package/dist/services/prompt-template-engine.js.map +1 -0
  105. package/dist/services/prompt-templates.js +236 -0
  106. package/dist/services/prompt-templates.js.map +1 -0
  107. package/dist/services/relationships.js +42 -0
  108. package/dist/services/relationships.js.map +1 -0
  109. package/dist/services/specs.js +35 -0
  110. package/dist/services/specs.js.map +1 -0
  111. package/dist/services/watcher.js +69 -0
  112. package/dist/services/watcher.js.map +1 -0
  113. package/dist/services/websocket.js +389 -0
  114. package/dist/services/websocket.js.map +1 -0
  115. package/dist/utils/sudocode-dir.js +9 -0
  116. package/dist/utils/sudocode-dir.js.map +1 -0
  117. package/package.json +4 -6
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Retry Logic and Backoff Strategies
3
+ *
4
+ * Implements retry logic with various backoff strategies including
5
+ * exponential, linear, and fixed delays with optional jitter.
6
+ *
7
+ * @module execution/resilience/retry
8
+ */
9
+ /**
10
+ * Calculate backoff delay for a given attempt
11
+ *
12
+ * Supports multiple backoff strategies:
13
+ * - Exponential: baseDelay * 2^(attempt-1) - e.g., 1s, 2s, 4s, 8s, 16s
14
+ * - Linear: baseDelay * attempt - e.g., 1s, 2s, 3s, 4s, 5s
15
+ * - Fixed: constant baseDelay - e.g., 1s, 1s, 1s, 1s, 1s
16
+ *
17
+ * Applies maxDelay cap and optional jitter to prevent thundering herd.
18
+ *
19
+ * @param attempt - Attempt number (1-indexed)
20
+ * @param config - Backoff configuration from retry policy
21
+ * @returns Delay in milliseconds
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Exponential backoff with jitter
26
+ * const delay = calculateBackoff(3, {
27
+ * type: 'exponential',
28
+ * baseDelayMs: 1000,
29
+ * maxDelayMs: 30000,
30
+ * jitter: true,
31
+ * });
32
+ * // Returns ~4000ms ± 10% jitter
33
+ * ```
34
+ */
35
+ export function calculateBackoff(attempt, config) {
36
+ let delay;
37
+ // Calculate base delay based on strategy
38
+ switch (config.type) {
39
+ case 'exponential':
40
+ // 2^(attempt-1) * baseDelay
41
+ // attempt 1: 2^0 = 1x, attempt 2: 2^1 = 2x, attempt 3: 2^2 = 4x
42
+ delay = config.baseDelayMs * Math.pow(2, attempt - 1);
43
+ break;
44
+ case 'linear':
45
+ // attempt * baseDelay
46
+ // attempt 1: 1x, attempt 2: 2x, attempt 3: 3x
47
+ delay = config.baseDelayMs * attempt;
48
+ break;
49
+ case 'fixed':
50
+ // constant baseDelay
51
+ delay = config.baseDelayMs;
52
+ break;
53
+ default:
54
+ // TypeScript should prevent this, but handle gracefully
55
+ delay = config.baseDelayMs;
56
+ }
57
+ // Enforce maximum delay cap
58
+ delay = Math.min(delay, config.maxDelayMs);
59
+ // Add jitter if configured (±10% randomness)
60
+ if (config.jitter) {
61
+ const jitterAmount = delay * 0.1; // 10% of delay
62
+ const jitterOffset = Math.random() * jitterAmount * 2 - jitterAmount;
63
+ delay += jitterOffset;
64
+ // Ensure delay stays positive and doesn't exceed max after jitter
65
+ delay = Math.max(0, Math.min(delay, config.maxDelayMs));
66
+ }
67
+ return Math.floor(delay);
68
+ }
69
+ /**
70
+ * Check if an error should trigger a retry
71
+ *
72
+ * Matches error message against the list of retryable error patterns
73
+ * defined in the retry policy.
74
+ *
75
+ * @param error - Error that occurred
76
+ * @param policy - Retry policy with retryable error patterns
77
+ * @returns True if error should be retried
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const error = new Error('Connection timeout');
82
+ * const shouldRetry = isRetryableError(error, {
83
+ * retryableErrors: ['timeout', 'ECONNREFUSED'],
84
+ * // ... other policy fields
85
+ * });
86
+ * // Returns true
87
+ * ```
88
+ */
89
+ export function isRetryableError(error, policy) {
90
+ const errorMessage = error.message || '';
91
+ // Check if error message contains any retryable pattern
92
+ for (const retryablePattern of policy.retryableErrors) {
93
+ if (errorMessage.includes(retryablePattern)) {
94
+ return true;
95
+ }
96
+ }
97
+ return false;
98
+ }
99
+ /**
100
+ * Check if an exit code should trigger a retry
101
+ *
102
+ * Matches exit code against the list of retryable exit codes
103
+ * defined in the retry policy.
104
+ *
105
+ * @param exitCode - Process exit code
106
+ * @param policy - Retry policy with retryable exit codes
107
+ * @returns True if exit code should be retried
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const shouldRetry = isRetryableExitCode(1, {
112
+ * retryableExitCodes: [1, 137],
113
+ * // ... other policy fields
114
+ * });
115
+ * // Returns true
116
+ * ```
117
+ */
118
+ export function isRetryableExitCode(exitCode, policy) {
119
+ return policy.retryableExitCodes.includes(exitCode);
120
+ }
121
+ /**
122
+ * Check if an execution result should trigger a retry
123
+ *
124
+ * Checks both the exit code and error message (if present) to determine
125
+ * if the execution should be retried.
126
+ *
127
+ * @param result - Execution result from task execution
128
+ * @param policy - Retry policy
129
+ * @returns True if execution should be retried
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * const result: ExecutionResult = {
134
+ * taskId: 'task-1',
135
+ * executionId: 'proc-123',
136
+ * success: false,
137
+ * exitCode: 1,
138
+ * error: 'Connection timeout',
139
+ * // ... other fields
140
+ * };
141
+ *
142
+ * const shouldRetry = isRetryableResult(result, policy);
143
+ * // Returns true if exitCode is retryable OR error contains retryable pattern
144
+ * ```
145
+ */
146
+ export function isRetryableResult(result, policy) {
147
+ // Check exit code
148
+ if (result.exitCode !== undefined && result.exitCode !== null) {
149
+ if (isRetryableExitCode(result.exitCode, policy)) {
150
+ return true;
151
+ }
152
+ }
153
+ // Check error message
154
+ if (result.error) {
155
+ const error = new Error(result.error);
156
+ if (isRetryableError(error, policy)) {
157
+ return true;
158
+ }
159
+ }
160
+ return false;
161
+ }
162
+ /**
163
+ * Promise-based sleep utility
164
+ *
165
+ * Returns a promise that resolves after the specified delay.
166
+ * Useful for implementing retry backoff.
167
+ *
168
+ * @param ms - Delay in milliseconds
169
+ * @returns Promise that resolves after delay
170
+ *
171
+ * @example
172
+ * ```typescript
173
+ * console.log('Starting...');
174
+ * await sleep(1000);
175
+ * console.log('1 second later');
176
+ * ```
177
+ */
178
+ export function sleep(ms) {
179
+ return new Promise((resolve) => setTimeout(resolve, ms));
180
+ }
181
+ /**
182
+ * Create an execution attempt record
183
+ *
184
+ * Helper function to create a properly structured ExecutionAttempt object.
185
+ *
186
+ * @param attemptNumber - Attempt number (1-indexed)
187
+ * @param success - Whether the attempt succeeded
188
+ * @param options - Optional fields for the attempt
189
+ * @returns ExecutionAttempt object
190
+ */
191
+ export function createAttempt(attemptNumber, success, options = {}) {
192
+ const now = new Date();
193
+ return {
194
+ attemptNumber,
195
+ startedAt: now,
196
+ completedAt: options.duration !== undefined ? now : undefined,
197
+ duration: options.duration,
198
+ success,
199
+ error: options.error,
200
+ exitCode: options.exitCode,
201
+ willRetry: options.willRetry || false,
202
+ nextRetryAt: options.nextRetryAt,
203
+ };
204
+ }
205
+ /**
206
+ * Calculate total delay from all retry attempts
207
+ *
208
+ * Sums up all the backoff delays that would be applied for a given
209
+ * number of retry attempts. Useful for timeout calculations.
210
+ *
211
+ * @param maxAttempts - Maximum number of attempts
212
+ * @param backoffConfig - Backoff configuration
213
+ * @returns Total delay in milliseconds
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * const totalDelay = calculateTotalRetryDelay(3, {
218
+ * type: 'exponential',
219
+ * baseDelayMs: 1000,
220
+ * maxDelayMs: 30000,
221
+ * jitter: false,
222
+ * });
223
+ * // Returns 7000ms (1s + 2s + 4s)
224
+ * ```
225
+ */
226
+ export function calculateTotalRetryDelay(maxAttempts, backoffConfig) {
227
+ let totalDelay = 0;
228
+ // Calculate delay for each attempt (excluding the first one)
229
+ for (let attempt = 2; attempt <= maxAttempts; attempt++) {
230
+ totalDelay += calculateBackoff(attempt, backoffConfig);
231
+ }
232
+ return totalDelay;
233
+ }
234
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../../src/execution/resilience/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,MAA8B;IAE9B,IAAI,KAAa,CAAC;IAElB,yCAAyC;IACzC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,aAAa;YAChB,4BAA4B;YAC5B,gEAAgE;YAChE,KAAK,GAAG,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;YACtD,MAAM;QAER,KAAK,QAAQ;YACX,sBAAsB;YACtB,8CAA8C;YAC9C,KAAK,GAAG,MAAM,CAAC,WAAW,GAAG,OAAO,CAAC;YACrC,MAAM;QAER,KAAK,OAAO;YACV,qBAAqB;YACrB,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC;YAC3B,MAAM;QAER;YACE,wDAAwD;YACxD,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC;IAC/B,CAAC;IAED,4BAA4B;IAC5B,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAE3C,6CAA6C;IAC7C,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,YAAY,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,eAAe;QACjD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,YAAY,GAAG,CAAC,GAAG,YAAY,CAAC;QACrE,KAAK,IAAI,YAAY,CAAC;QAEtB,kEAAkE;QAClE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAY,EAAE,MAAmB;IAChE,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;IAEzC,wDAAwD;IACxD,KAAK,MAAM,gBAAgB,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QACtD,IAAI,YAAY,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,MAAmB;IAEnB,OAAO,MAAM,CAAC,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAuB,EACvB,MAAmB;IAEnB,kBAAkB;IAClB,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC9D,IAAI,mBAAmB,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAC3B,aAAqB,EACrB,OAAgB,EAChB,UAMI,EAAE;IAEN,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,OAAO;QACL,aAAa;QACb,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;QAC7D,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,OAAO;QACP,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,KAAK;QACrC,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,wBAAwB,CACtC,WAAmB,EACnB,aAAqC;IAErC,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,6DAA6D;IAC7D,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,UAAU,IAAI,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Resilience Layer Types
3
+ *
4
+ * Core types for the Resilience Layer (Layer 3) that adds retry logic,
5
+ * circuit breakers, and fault tolerance to task execution.
6
+ *
7
+ * @module execution/resilience/types
8
+ */
9
+ /**
10
+ * Default retry policy for resilient execution
11
+ */
12
+ export const DEFAULT_RETRY_POLICY = {
13
+ maxAttempts: 3,
14
+ backoff: {
15
+ type: 'exponential',
16
+ baseDelayMs: 1000,
17
+ maxDelayMs: 30000,
18
+ jitter: true,
19
+ },
20
+ retryableErrors: [
21
+ 'ECONNREFUSED',
22
+ 'ETIMEDOUT',
23
+ 'ENOTFOUND',
24
+ 'timeout',
25
+ 'network',
26
+ 'Process execution timeout',
27
+ ],
28
+ retryableExitCodes: [1, 137], // Generic error, SIGKILL
29
+ };
30
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/execution/resilience/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsQH;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC/C,WAAW,EAAE,CAAC;IACd,OAAO,EAAE;QACP,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,IAAI;QACjB,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,IAAI;KACb;IACD,eAAe,EAAE;QACf,cAAc;QACd,WAAW;QACX,WAAW;QACX,SAAS;QACT,SAAS;QACT,2BAA2B;KAC5B;IACD,kBAAkB,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,yBAAyB;CACxD,CAAC"}
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Execution Event Buffer
3
+ *
4
+ * Stores AG-UI events for executions so they can be replayed to late-joining clients
5
+ * or retrieved for historical display.
6
+ *
7
+ * @module execution/transport/event-buffer
8
+ */
9
+ /**
10
+ * EventBuffer - In-memory storage for execution events
11
+ *
12
+ * Stores events for active executions and allows replay when clients connect.
13
+ * Events are automatically pruned after executions complete to prevent memory leaks.
14
+ */
15
+ export class EventBuffer {
16
+ buffers = new Map();
17
+ MAX_EVENTS_PER_EXECUTION = 10000; // Prevent unbounded growth
18
+ RETENTION_MS = 1000 * 60 * 60; // 1 hour after last update
19
+ /**
20
+ * Add an event to the buffer for an execution
21
+ *
22
+ * @param executionId - Execution ID
23
+ * @param event - AG-UI event to buffer
24
+ */
25
+ addEvent(executionId, event) {
26
+ let buffer = this.buffers.get(executionId);
27
+ if (!buffer) {
28
+ buffer = {
29
+ executionId,
30
+ events: [],
31
+ nextSequence: 0,
32
+ createdAt: Date.now(),
33
+ lastUpdatedAt: Date.now(),
34
+ };
35
+ this.buffers.set(executionId, buffer);
36
+ console.log("[EventBuffer] Created buffer for execution", {
37
+ executionId,
38
+ timestamp: new Date().toISOString(),
39
+ });
40
+ }
41
+ // Add event with sequence number
42
+ const bufferedEvent = {
43
+ event,
44
+ timestamp: Date.now(),
45
+ sequenceNumber: buffer.nextSequence++,
46
+ };
47
+ buffer.events.push(bufferedEvent);
48
+ buffer.lastUpdatedAt = Date.now();
49
+ // Enforce max events limit
50
+ if (buffer.events.length > this.MAX_EVENTS_PER_EXECUTION) {
51
+ // Remove oldest 10% of events
52
+ const toRemove = Math.floor(this.MAX_EVENTS_PER_EXECUTION * 0.1);
53
+ buffer.events.splice(0, toRemove);
54
+ console.warn("[EventBuffer] Buffer size limit reached, removing oldest events", {
55
+ executionId,
56
+ removedCount: toRemove,
57
+ remainingCount: buffer.events.length,
58
+ });
59
+ }
60
+ console.log("[EventBuffer] Event added to buffer", {
61
+ executionId,
62
+ eventType: event.type,
63
+ sequenceNumber: bufferedEvent.sequenceNumber,
64
+ totalEvents: buffer.events.length,
65
+ });
66
+ }
67
+ /**
68
+ * Get all buffered events for an execution
69
+ *
70
+ * @param executionId - Execution ID
71
+ * @param fromSequence - Optional: only return events >= this sequence number
72
+ * @returns Array of buffered events, or empty array if no buffer exists
73
+ */
74
+ getEvents(executionId, fromSequence) {
75
+ const buffer = this.buffers.get(executionId);
76
+ if (!buffer) {
77
+ return [];
78
+ }
79
+ if (fromSequence !== undefined) {
80
+ return buffer.events.filter((e) => e.sequenceNumber >= fromSequence);
81
+ }
82
+ return [...buffer.events];
83
+ }
84
+ /**
85
+ * Check if a buffer exists for an execution
86
+ *
87
+ * @param executionId - Execution ID
88
+ * @returns true if buffer exists
89
+ */
90
+ hasBuffer(executionId) {
91
+ return this.buffers.has(executionId);
92
+ }
93
+ /**
94
+ * Get buffer metadata without events
95
+ *
96
+ * @param executionId - Execution ID
97
+ * @returns Buffer metadata or null if not found
98
+ */
99
+ getBufferInfo(executionId) {
100
+ const buffer = this.buffers.get(executionId);
101
+ if (!buffer) {
102
+ return null;
103
+ }
104
+ return {
105
+ executionId: buffer.executionId,
106
+ nextSequence: buffer.nextSequence,
107
+ createdAt: buffer.createdAt,
108
+ lastUpdatedAt: buffer.lastUpdatedAt,
109
+ };
110
+ }
111
+ /**
112
+ * Remove a buffer for an execution
113
+ *
114
+ * @param executionId - Execution ID
115
+ * @returns true if buffer was removed, false if it didn't exist
116
+ */
117
+ removeBuffer(executionId) {
118
+ const existed = this.buffers.has(executionId);
119
+ if (existed) {
120
+ this.buffers.delete(executionId);
121
+ console.log("[EventBuffer] Buffer removed", {
122
+ executionId,
123
+ timestamp: new Date().toISOString(),
124
+ });
125
+ }
126
+ return existed;
127
+ }
128
+ /**
129
+ * Clear all buffers
130
+ */
131
+ clearAll() {
132
+ const count = this.buffers.size;
133
+ this.buffers.clear();
134
+ console.log("[EventBuffer] All buffers cleared", { count });
135
+ }
136
+ /**
137
+ * Prune stale buffers that haven't been updated recently
138
+ *
139
+ * Should be called periodically to prevent memory leaks.
140
+ *
141
+ * @returns Number of buffers pruned
142
+ */
143
+ pruneStale() {
144
+ const now = Date.now();
145
+ const threshold = now - this.RETENTION_MS;
146
+ let pruned = 0;
147
+ for (const [executionId, buffer] of this.buffers.entries()) {
148
+ if (buffer.lastUpdatedAt < threshold) {
149
+ this.buffers.delete(executionId);
150
+ pruned++;
151
+ }
152
+ }
153
+ if (pruned > 0) {
154
+ console.log("[EventBuffer] Pruned stale buffers", {
155
+ count: pruned,
156
+ remaining: this.buffers.size,
157
+ });
158
+ }
159
+ return pruned;
160
+ }
161
+ /**
162
+ * Get total number of buffers
163
+ *
164
+ * @returns Number of active buffers
165
+ */
166
+ getBufferCount() {
167
+ return this.buffers.size;
168
+ }
169
+ /**
170
+ * Get total number of events across all buffers
171
+ *
172
+ * @returns Total event count
173
+ */
174
+ getTotalEventCount() {
175
+ let total = 0;
176
+ for (const buffer of this.buffers.values()) {
177
+ total += buffer.events.length;
178
+ }
179
+ return total;
180
+ }
181
+ /**
182
+ * Get statistics about buffer usage
183
+ *
184
+ * @returns Buffer statistics
185
+ */
186
+ getStats() {
187
+ const bufferCount = this.buffers.size;
188
+ const totalEvents = this.getTotalEventCount();
189
+ let oldest = null;
190
+ let newest = null;
191
+ for (const buffer of this.buffers.values()) {
192
+ if (oldest === null || buffer.createdAt < oldest) {
193
+ oldest = buffer.createdAt;
194
+ }
195
+ if (newest === null || buffer.createdAt > newest) {
196
+ newest = buffer.createdAt;
197
+ }
198
+ }
199
+ return {
200
+ bufferCount,
201
+ totalEvents,
202
+ avgEventsPerBuffer: bufferCount > 0 ? totalEvents / bufferCount : 0,
203
+ oldestBuffer: oldest,
204
+ newestBuffer: newest,
205
+ };
206
+ }
207
+ }
208
+ //# sourceMappingURL=event-buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-buffer.js","sourceRoot":"","sources":["../../../src/execution/transport/event-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgCH;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IACd,OAAO,GAAG,IAAI,GAAG,EAAgC,CAAC;IACzC,wBAAwB,GAAG,KAAK,CAAC,CAAC,2BAA2B;IAC7D,YAAY,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,2BAA2B;IAE3E;;;;;OAKG;IACH,QAAQ,CAAC,WAAmB,EAAE,KAAgB;QAC5C,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAE3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG;gBACP,WAAW;gBACX,MAAM,EAAE,EAAE;gBACV,YAAY,EAAE,CAAC;gBACf,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE;aAC1B,CAAC;YACF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE;gBACxD,WAAW;gBACX,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAC;QACL,CAAC;QAED,iCAAiC;QACjC,MAAM,aAAa,GAAkB;YACnC,KAAK;YACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,cAAc,EAAE,MAAM,CAAC,YAAY,EAAE;SACtC,CAAC;QAEF,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAClC,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAElC,2BAA2B;QAC3B,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,wBAAwB,EAAE,CAAC;YACzD,8BAA8B;YAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,GAAG,GAAG,CAAC,CAAC;YACjE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YAClC,OAAO,CAAC,IAAI,CACV,iEAAiE,EACjE;gBACE,WAAW;gBACX,YAAY,EAAE,QAAQ;gBACtB,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM;aACrC,CACF,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE;YACjD,WAAW;YACX,SAAS,EAAE,KAAK,CAAC,IAAI;YACrB,cAAc,EAAE,aAAa,CAAC,cAAc;YAC5C,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM;SAClC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,WAAmB,EAAE,YAAqB;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,IAAI,YAAY,CAAC,CAAC;QACvE,CAAC;QAED,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,WAAmB;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAED;;;;;OAKG;IACH,aAAa,CACX,WAAmB;QAEnB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO;YACL,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,aAAa,EAAE,MAAM,CAAC,aAAa;SACpC,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,WAAmB;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE;gBAC1C,WAAW;gBACX,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QAChC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED;;;;;;OAMG;IACH,UAAU;QACR,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC;QAC1C,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,KAAK,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAC3D,IAAI,MAAM,CAAC,aAAa,GAAG,SAAS,EAAE,CAAC;gBACrC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;gBACjC,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC;QAED,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE;gBAChD,KAAK,EAAE,MAAM;gBACb,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;aAC7B,CAAC,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACH,kBAAkB;QAChB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;QAChC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACH,QAAQ;QAON,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QACtC,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAE9C,IAAI,MAAM,GAAkB,IAAI,CAAC;QACjC,IAAI,MAAM,GAAkB,IAAI,CAAC;QAEjC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,SAAS,GAAG,MAAM,EAAE,CAAC;gBACjD,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;YAC5B,CAAC;YACD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,SAAS,GAAG,MAAM,EAAE,CAAC;gBACjD,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,OAAO;YACL,WAAW;YACX,WAAW;YACX,kBAAkB,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YACnE,YAAY,EAAE,MAAM;YACpB,YAAY,EAAE,MAAM;SACrB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Transport Layer
3
+ *
4
+ * Exports transport implementations for streaming AG-UI events to clients.
5
+ *
6
+ * @module execution/transport
7
+ */
8
+ export { SseTransport } from './sse-transport.js';
9
+ export { TransportManager } from './transport-manager.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/execution/transport/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}