@snapback/cli 1.6.0 → 3.0.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 (57) hide show
  1. package/README.md +121 -22
  2. package/dist/SkippedTestDetector-AXTMWWHC.js +5 -0
  3. package/dist/SkippedTestDetector-QLSQV7K7.js +5 -0
  4. package/dist/analysis-6WTBZJH3.js +6 -0
  5. package/dist/analysis-C472LUGW.js +2475 -0
  6. package/dist/auth-UA7I3YE4.js +1446 -0
  7. package/dist/auto-provision-organization-6YF463TK.js +161 -0
  8. package/dist/{chunk-FVIYXFCL.js → chunk-4YTE4JEW.js} +2 -3
  9. package/dist/chunk-5EOPYJ4Y.js +12 -0
  10. package/dist/{chunk-ARVV3F4K.js → chunk-5SQA44V7.js} +1085 -18
  11. package/dist/{chunk-RB7H4UQJ.js → chunk-7ADPL4Q3.js} +10 -3
  12. package/dist/chunk-BE3HNVSV.js +2300 -0
  13. package/dist/chunk-BWWPGNZ5.js +5842 -0
  14. package/dist/chunk-CBGOC6RV.js +293 -0
  15. package/dist/{chunk-7JX6Y4TL.js → chunk-DPWFZNMY.js} +21 -34
  16. package/dist/{chunk-R7CUQ7CU.js → chunk-E6V6QKS7.js} +317 -33
  17. package/dist/chunk-GT4ZUCFR.js +111 -0
  18. package/dist/chunk-NOWJBG6X.js +3654 -0
  19. package/dist/chunk-O7HMAZ7L.js +3497 -0
  20. package/dist/chunk-PL4HF4M2.js +593 -0
  21. package/dist/chunk-V7B37PPD.js +4075 -0
  22. package/dist/chunk-YVZXPBSV.js +314 -0
  23. package/dist/chunk-ZBQDE6WJ.js +108 -0
  24. package/dist/client-RHDS6NOB.js +8 -0
  25. package/dist/dist-5LR7APG5.js +5 -0
  26. package/dist/dist-CUHOKNLS.js +12 -0
  27. package/dist/dist-RJE4RSZJ.js +9 -0
  28. package/dist/index.js +60568 -36578
  29. package/dist/local-service-adapter-AB3UYRUK.js +6 -0
  30. package/dist/pioneer-oauth-hook-V2JKEXM7.js +12 -0
  31. package/dist/{secure-credentials-IWQB6KU4.js → secure-credentials-UEPG7GWW.js} +2 -3
  32. package/dist/snapback-dir-MG7DTRMF.js +6 -0
  33. package/package.json +12 -11
  34. package/scripts/postinstall.mjs +2 -3
  35. package/dist/SkippedTestDetector-5WJZKZQ3.js +0 -5
  36. package/dist/SkippedTestDetector-5WJZKZQ3.js.map +0 -1
  37. package/dist/analysis-YI4UNUCM.js +0 -6
  38. package/dist/analysis-YI4UNUCM.js.map +0 -1
  39. package/dist/chunk-7JX6Y4TL.js.map +0 -1
  40. package/dist/chunk-ARVV3F4K.js.map +0 -1
  41. package/dist/chunk-EU2IZPOK.js +0 -13002
  42. package/dist/chunk-EU2IZPOK.js.map +0 -1
  43. package/dist/chunk-FVIYXFCL.js.map +0 -1
  44. package/dist/chunk-R7CUQ7CU.js.map +0 -1
  45. package/dist/chunk-RB7H4UQJ.js.map +0 -1
  46. package/dist/chunk-SOABQWAU.js +0 -385
  47. package/dist/chunk-SOABQWAU.js.map +0 -1
  48. package/dist/dist-O6EBXLN6.js +0 -5
  49. package/dist/dist-O6EBXLN6.js.map +0 -1
  50. package/dist/dist-PJVBBZTF.js +0 -5
  51. package/dist/dist-PJVBBZTF.js.map +0 -1
  52. package/dist/index.js.map +0 -1
  53. package/dist/learning-pruner-QC4CTJDX.js +0 -5
  54. package/dist/learning-pruner-QC4CTJDX.js.map +0 -1
  55. package/dist/secure-credentials-IWQB6KU4.js.map +0 -1
  56. package/dist/snapback-dir-V6MWXIW4.js +0 -5
  57. package/dist/snapback-dir-V6MWXIW4.js.map +0 -1
@@ -0,0 +1,593 @@
1
+ #!/usr/bin/env node --no-warnings=ExperimentalWarning
2
+ import { __name, __export, __require } from './chunk-7ADPL4Q3.js';
3
+ import pino from 'pino';
4
+ import { LRUCache } from 'lru-cache';
5
+ import os from 'os';
6
+ import chokidar from 'chokidar';
7
+ import CircuitBreaker from 'opossum';
8
+ import PQueue from 'p-queue';
9
+ import pRetry, { AbortError } from 'p-retry';
10
+
11
+ process.env.SNAPBACK_CLI='true';
12
+ var MCP_QUIET = process.env.MCP_QUIET === "1" || process.env.MCP_QUIET === "true";
13
+ var isProduction = process.env.NODE_ENV === "production";
14
+ var isTest = process.env.NODE_ENV === "test" || process.env.VITEST === "true";
15
+ var isVSCodeExtension = process.env.VSCODE_EXTENSION === "true";
16
+ var isNextJS = typeof process.env.NEXT_RUNTIME !== "undefined" || typeof process.env.__NEXT_PRIVATE_ORIGIN !== "undefined";
17
+ var isBundled = typeof process.env.SNAPBACK_BUNDLED !== "undefined" || // Check if we're running from a bundled location (dist/server with no source)
18
+ typeof __dirname === "string" && !__dirname.includes("node_modules") && !__dirname.includes("packages/");
19
+ var serviceName = process.env.SERVICE_NAME || process.env.npm_package_name || "app";
20
+ var redactPaths = [
21
+ "user.email",
22
+ "user.password",
23
+ "apiKey",
24
+ "session.token",
25
+ "req.headers.authorization",
26
+ "auth.*.password",
27
+ "config.*.secret",
28
+ "env.*",
29
+ "password",
30
+ "token",
31
+ "secret",
32
+ "authorization",
33
+ "cookie",
34
+ "*.password",
35
+ "*.token",
36
+ "*.apiKey",
37
+ "*.secret",
38
+ "*.authorization",
39
+ "*.cookie",
40
+ "*.path",
41
+ "*.file",
42
+ "*.filePath"
43
+ ];
44
+ function traceContextMixin() {
45
+ try {
46
+ const api = __require("@opentelemetry/api");
47
+ const span = api.trace.getSpan(api.context.active());
48
+ if (span) {
49
+ const ctx = span.spanContext();
50
+ return {
51
+ trace_id: ctx.traceId,
52
+ span_id: ctx.spanId
53
+ };
54
+ }
55
+ } catch {
56
+ }
57
+ return {};
58
+ }
59
+ __name(traceContextMixin, "traceContextMixin");
60
+ var pinoLogger = pino({
61
+ // When MCP_QUIET=1, set level to 'silent' to suppress all output
62
+ level: MCP_QUIET ? "silent" : process.env.LOG_LEVEL || "info",
63
+ redact: {
64
+ paths: redactPaths,
65
+ censor: "[REDACTED]"
66
+ },
67
+ // Add service name as base context for terminal multiplexer clarity
68
+ base: {
69
+ service: serviceName
70
+ },
71
+ // Inject trace context into every log line
72
+ mixin: traceContextMixin,
73
+ // Only use transport in non-production AND non-VSCode AND non-Next.js AND non-test environments
74
+ // pino-pretty uses worker threads which fail in Next.js bundled contexts and vitest
75
+ // Also disable in bundled mode (MCPB) where worker threads don't work
76
+ ...isProduction || isTest || isVSCodeExtension || MCP_QUIET || isNextJS || isBundled ? {} : {
77
+ transport: {
78
+ target: "pino-pretty",
79
+ options: {
80
+ colorize: true,
81
+ translateTime: "SYS:HH:MM:ss.l",
82
+ ignore: "pid,hostname,service",
83
+ // Show service name in message prefix for terminal clarity
84
+ messageFormat: "[{service}] {msg}",
85
+ // Include trace context in output - this is your "local Grafana"
86
+ // trace_id will appear inline when OTel is active
87
+ include: "level,time,trace_id,span_id",
88
+ // Single line for better terminal readability
89
+ singleLine: true,
90
+ // Custom colors for level differentiation
91
+ levelColors: {
92
+ trace: "gray",
93
+ debug: "cyan",
94
+ info: "green",
95
+ warn: "yellow",
96
+ error: "red",
97
+ fatal: "bgRed"
98
+ }
99
+ }
100
+ }
101
+ }
102
+ }, pino.destination({
103
+ fd: 2
104
+ }));
105
+ var logger = {
106
+ debug: /* @__PURE__ */ __name((messageOrObj, metaOrMsg) => {
107
+ if (typeof messageOrObj === "string" && (!metaOrMsg || typeof metaOrMsg === "object")) {
108
+ if (metaOrMsg) {
109
+ pinoLogger.debug(metaOrMsg, messageOrObj);
110
+ } else {
111
+ pinoLogger.debug(messageOrObj);
112
+ }
113
+ } else if (typeof messageOrObj === "object" && typeof metaOrMsg === "string") {
114
+ pinoLogger.debug(messageOrObj, metaOrMsg);
115
+ }
116
+ }, "debug"),
117
+ info: /* @__PURE__ */ __name((messageOrObj, metaOrMsg) => {
118
+ if (typeof messageOrObj === "string" && (!metaOrMsg || typeof metaOrMsg === "object")) {
119
+ if (metaOrMsg) {
120
+ pinoLogger.info(metaOrMsg, messageOrObj);
121
+ } else {
122
+ pinoLogger.info(messageOrObj);
123
+ }
124
+ } else if (typeof messageOrObj === "object" && typeof metaOrMsg === "string") {
125
+ pinoLogger.info(messageOrObj, metaOrMsg);
126
+ }
127
+ }, "info"),
128
+ warn: /* @__PURE__ */ __name((messageOrObj, metaOrMsg) => {
129
+ if (typeof messageOrObj === "string" && (!metaOrMsg || typeof metaOrMsg === "object")) {
130
+ if (metaOrMsg) {
131
+ pinoLogger.warn(metaOrMsg, messageOrObj);
132
+ } else {
133
+ pinoLogger.warn(messageOrObj);
134
+ }
135
+ } else if (typeof messageOrObj === "object" && typeof metaOrMsg === "string") {
136
+ pinoLogger.warn(messageOrObj, metaOrMsg);
137
+ }
138
+ }, "warn"),
139
+ error: /* @__PURE__ */ __name((messageOrObj, metaOrMsg) => {
140
+ if (typeof messageOrObj === "string" && (!metaOrMsg || typeof metaOrMsg !== "string")) {
141
+ if (metaOrMsg) {
142
+ pinoLogger.error(metaOrMsg, messageOrObj);
143
+ } else {
144
+ pinoLogger.error(messageOrObj);
145
+ }
146
+ } else if (typeof messageOrObj === "object" && typeof metaOrMsg === "string") {
147
+ pinoLogger.error(messageOrObj, metaOrMsg);
148
+ }
149
+ }, "error"),
150
+ // Child method for creating scoped loggers
151
+ child: /* @__PURE__ */ __name((bindings) => {
152
+ const childLogger = pinoLogger.child(bindings);
153
+ return {
154
+ debug: /* @__PURE__ */ __name((messageOrObj, metaOrMsg) => {
155
+ if (typeof messageOrObj === "string" && (!metaOrMsg || typeof metaOrMsg === "object")) {
156
+ if (metaOrMsg) {
157
+ childLogger.debug(metaOrMsg, messageOrObj);
158
+ } else {
159
+ childLogger.debug(messageOrObj);
160
+ }
161
+ } else if (typeof messageOrObj === "object" && typeof metaOrMsg === "string") {
162
+ childLogger.debug(messageOrObj, metaOrMsg);
163
+ }
164
+ }, "debug"),
165
+ info: /* @__PURE__ */ __name((messageOrObj, metaOrMsg) => {
166
+ if (typeof messageOrObj === "string" && (!metaOrMsg || typeof metaOrMsg === "object")) {
167
+ if (metaOrMsg) {
168
+ childLogger.info(metaOrMsg, messageOrObj);
169
+ } else {
170
+ childLogger.info(messageOrObj);
171
+ }
172
+ } else if (typeof messageOrObj === "object" && typeof metaOrMsg === "string") {
173
+ childLogger.info(messageOrObj, metaOrMsg);
174
+ }
175
+ }, "info"),
176
+ warn: /* @__PURE__ */ __name((messageOrObj, metaOrMsg) => {
177
+ if (typeof messageOrObj === "string" && (!metaOrMsg || typeof metaOrMsg === "object")) {
178
+ if (metaOrMsg) {
179
+ childLogger.warn(metaOrMsg, messageOrObj);
180
+ } else {
181
+ childLogger.warn(messageOrObj);
182
+ }
183
+ } else if (typeof messageOrObj === "object" && typeof metaOrMsg === "string") {
184
+ childLogger.warn(messageOrObj, metaOrMsg);
185
+ }
186
+ }, "warn"),
187
+ error: /* @__PURE__ */ __name((messageOrObj, metaOrMsg) => {
188
+ if (typeof messageOrObj === "string" && (!metaOrMsg || typeof metaOrMsg !== "string")) {
189
+ if (metaOrMsg) {
190
+ childLogger.error(metaOrMsg, messageOrObj);
191
+ } else {
192
+ childLogger.error(messageOrObj);
193
+ }
194
+ } else if (typeof messageOrObj === "object" && typeof metaOrMsg === "string") {
195
+ childLogger.error(messageOrObj, metaOrMsg);
196
+ }
197
+ }, "error"),
198
+ level: childLogger.level,
199
+ child: /* @__PURE__ */ __name((nestedBindings) => logger.child({
200
+ ...bindings,
201
+ ...nestedBindings
202
+ }), "child")
203
+ };
204
+ }, "child")
205
+ };
206
+
207
+ // ../../packages/infrastructure/dist/cache/index.js
208
+ var cache_exports = {};
209
+ __export(cache_exports, {
210
+ cacheDefaults: () => cacheDefaults,
211
+ dashboardCache: () => dashboardCache,
212
+ docCache: () => docCache,
213
+ getDashboardCached: () => getDashboardCached,
214
+ getLibraryDocsCached: () => getLibraryDocsCached,
215
+ getLibraryDocsCachedWithHint: () => getLibraryDocsCachedWithHint,
216
+ invalidateDashboardCache: () => invalidateDashboardCache
217
+ });
218
+ var cacheDefaults = {
219
+ mcp: {
220
+ cache: {
221
+ maxEntries: 500,
222
+ ttlMs: 60 * 60 * 1e3
223
+ }
224
+ },
225
+ dashboard: {
226
+ cache: {
227
+ maxEntries: 1e3,
228
+ defaultTtlMs: 5 * 60 * 1e3
229
+ }
230
+ }
231
+ };
232
+ var docCache = new LRUCache({
233
+ max: cacheDefaults.mcp.cache.maxEntries,
234
+ ttl: cacheDefaults.mcp.cache.ttlMs,
235
+ allowStale: true,
236
+ updateAgeOnGet: true
237
+ });
238
+ var dashboardCache = new LRUCache({
239
+ max: cacheDefaults.dashboard.cache.maxEntries,
240
+ ttl: cacheDefaults.dashboard.cache.defaultTtlMs,
241
+ allowStale: true,
242
+ updateAgeOnGet: true
243
+ });
244
+ async function getLibraryDocsCached(key, fetcher, ttlMs) {
245
+ const hit = docCache.get(key);
246
+ if (hit) {
247
+ logger.debug(`Cache hit for key: ${key}`);
248
+ return hit;
249
+ }
250
+ try {
251
+ logger.debug(`Cache miss for key: ${key}, fetching data`);
252
+ const value = await fetcher();
253
+ if (ttlMs) {
254
+ docCache.set(key, value, {
255
+ ttl: ttlMs
256
+ });
257
+ } else {
258
+ docCache.set(key, value);
259
+ }
260
+ return value;
261
+ } catch (error) {
262
+ logger.error({
263
+ error
264
+ }, `Failed to fetch data for cache key: ${key}`);
265
+ throw error;
266
+ }
267
+ }
268
+ __name(getLibraryDocsCached, "getLibraryDocsCached");
269
+ async function getLibraryDocsCachedWithHint(cacheKey, ttlMs, fetcher) {
270
+ if (cacheKey) {
271
+ return await getLibraryDocsCached(cacheKey, fetcher, ttlMs);
272
+ }
273
+ return await fetcher();
274
+ }
275
+ __name(getLibraryDocsCachedWithHint, "getLibraryDocsCachedWithHint");
276
+ async function getDashboardCached(key, fetcher, ttlMs) {
277
+ const hit = dashboardCache.get(key);
278
+ if (hit) {
279
+ logger.debug(`Dashboard cache hit for key: ${key}`);
280
+ return hit;
281
+ }
282
+ try {
283
+ logger.debug(`Dashboard cache miss for key: ${key}, fetching data`);
284
+ const value = await fetcher();
285
+ dashboardCache.set(key, value, {
286
+ ttl: ttlMs ?? cacheDefaults.dashboard.cache.defaultTtlMs
287
+ });
288
+ return value;
289
+ } catch (error) {
290
+ logger.error({
291
+ error
292
+ }, `Failed to fetch dashboard data for cache key: ${key}`);
293
+ throw error;
294
+ }
295
+ }
296
+ __name(getDashboardCached, "getDashboardCached");
297
+ function invalidateDashboardCache(pattern) {
298
+ const keysToDelete = [];
299
+ for (const key of dashboardCache.keys()) {
300
+ if (key.includes(pattern)) {
301
+ keysToDelete.push(key);
302
+ }
303
+ }
304
+ for (const key of keysToDelete) {
305
+ dashboardCache.delete(key);
306
+ }
307
+ logger.info(`Invalidated ${keysToDelete.length} dashboard cache entries matching pattern: ${pattern}`);
308
+ }
309
+ __name(invalidateDashboardCache, "invalidateDashboardCache");
310
+ var watcherDefaults = {
311
+ watcher: {
312
+ awaitWriteFinish: {
313
+ stabilityThreshold: 200,
314
+ pollInterval: 50
315
+ },
316
+ ignored: [
317
+ "**/{node_modules,.git,.vscode,dist,.next,.nuxt,coverage}/**"
318
+ ]
319
+ }
320
+ };
321
+ function makeWatcher(root) {
322
+ os.platform() === "darwin";
323
+ return chokidar.watch(root, {
324
+ ignoreInitial: true,
325
+ ignored: [
326
+ ...watcherDefaults.watcher.ignored
327
+ ],
328
+ awaitWriteFinish: watcherDefaults.watcher.awaitWriteFinish,
329
+ ignorePermissionErrors: true,
330
+ depth: 10
331
+ });
332
+ }
333
+ __name(makeWatcher, "makeWatcher");
334
+
335
+ // ../../packages/infrastructure/dist/resiliency/index.js
336
+ var resiliency_exports = {};
337
+ __export(resiliency_exports, {
338
+ AbortError: () => AbortError,
339
+ RetryPresets: () => RetryPresets,
340
+ batchCall: () => batchCall,
341
+ calculateBackoff: () => calculateBackoff,
342
+ callTool: () => callTool,
343
+ getCircuitBreakerState: () => getCircuitBreakerState,
344
+ resilienceDefaults: () => resilienceDefaults,
345
+ withBreaker: () => withBreaker,
346
+ withRetry: () => withRetry
347
+ });
348
+ function sanitizeError(error) {
349
+ const message = error instanceof Error ? error.message : String(error);
350
+ return message.replace(/api[_-]?key[=:]\s*["']?\S+["']?/gi, "api_key=[REDACTED]").replace(/token[=:]\s*["']?\S+["']?/gi, "token=[REDACTED]").replace(/password[=:]\s*["']?\S+["']?/gi, "password=[REDACTED]").replace(/bearer\s+\S+/gi, "Bearer [REDACTED]").replace(/authorization[=:]\s*["']?\S+["']?/gi, "authorization=[REDACTED]").replace(/secret[=:]\s*["']?\S+["']?/gi, "secret=[REDACTED]").replace(/credential[s]?[=:]\s*["']?\S+["']?/gi, "credentials=[REDACTED]");
351
+ }
352
+ __name(sanitizeError, "sanitizeError");
353
+ var resilienceDefaults = {
354
+ mcp: {
355
+ timeoutMs: 5e3,
356
+ maxConcurrent: 4,
357
+ retry: {
358
+ maxAttempts: 2,
359
+ baseDelayMs: 250,
360
+ maxDelayMs: 1500,
361
+ jitter: true
362
+ },
363
+ circuit: {
364
+ enabled: true,
365
+ errorThresholdPercentage: 50,
366
+ volumeThreshold: 10,
367
+ timeoutMs: 5e3,
368
+ resetMs: 3e4,
369
+ rollingCountMs: 6e4,
370
+ rollingCountBuckets: 6
371
+ },
372
+ batch: {
373
+ size: 5,
374
+ maxWaitMs: 150
375
+ }
376
+ }
377
+ };
378
+ var circuitBreakers = /* @__PURE__ */ new Map();
379
+ function withBreaker(toolName, fn, cfg = resilienceDefaults.mcp.circuit) {
380
+ if (!circuitBreakers.has(toolName)) {
381
+ const br2 = new CircuitBreaker(fn, {
382
+ timeout: cfg.timeoutMs,
383
+ errorThresholdPercentage: cfg.errorThresholdPercentage,
384
+ resetTimeout: cfg.resetMs,
385
+ rollingCountTimeout: cfg.rollingCountMs,
386
+ rollingCountBuckets: cfg.rollingCountBuckets,
387
+ volumeThreshold: cfg.volumeThreshold
388
+ });
389
+ br2.on("open", () => {
390
+ logger.warn(`Circuit breaker opened for tool: ${toolName}`, {
391
+ tool: toolName,
392
+ state: "open",
393
+ stats: br2.stats
394
+ });
395
+ });
396
+ br2.on("halfOpen", () => {
397
+ logger.warn(`Circuit breaker half-open for tool: ${toolName}`, {
398
+ tool: toolName,
399
+ state: "half-open",
400
+ stats: br2.stats
401
+ });
402
+ });
403
+ br2.on("close", () => {
404
+ logger.info(`Circuit breaker closed for tool: ${toolName}`, {
405
+ tool: toolName,
406
+ state: "closed",
407
+ stats: br2.stats
408
+ });
409
+ });
410
+ br2.on("success", () => {
411
+ logger.debug(`Circuit breaker success for tool: ${toolName}`, {
412
+ tool: toolName,
413
+ event: "success",
414
+ successes: br2.stats.successes,
415
+ failures: br2.stats.failures
416
+ });
417
+ });
418
+ br2.on("failure", (error) => {
419
+ logger.warn(`Circuit breaker failure for tool: ${toolName}`, {
420
+ tool: toolName,
421
+ event: "failure",
422
+ error: sanitizeError(error),
423
+ successes: br2.stats.successes,
424
+ failures: br2.stats.failures
425
+ });
426
+ });
427
+ br2.on("timeout", () => {
428
+ logger.warn(`Circuit breaker timeout for tool: ${toolName}`, {
429
+ tool: toolName,
430
+ event: "timeout",
431
+ timeoutMs: cfg.timeoutMs
432
+ });
433
+ });
434
+ br2.on("reject", () => {
435
+ logger.warn(`Circuit breaker rejected call for tool: ${toolName}`, {
436
+ tool: toolName,
437
+ event: "reject",
438
+ state: br2.opened ? "open" : br2.halfOpen ? "half-open" : "closed"
439
+ });
440
+ });
441
+ circuitBreakers.set(toolName, br2);
442
+ }
443
+ const br = circuitBreakers.get(toolName);
444
+ if (!br) {
445
+ throw new Error(`Circuit breaker not found for tool: ${toolName}`);
446
+ }
447
+ return (input) => br.fire(input);
448
+ }
449
+ __name(withBreaker, "withBreaker");
450
+ function getCircuitBreakerState(toolName) {
451
+ const br = circuitBreakers.get(toolName);
452
+ if (!br) {
453
+ return null;
454
+ }
455
+ return {
456
+ isOpen: br.opened,
457
+ isHalfOpen: br.halfOpen,
458
+ isClosed: br.closed
459
+ };
460
+ }
461
+ __name(getCircuitBreakerState, "getCircuitBreakerState");
462
+ var RetryPresets = {
463
+ /** Fast retries for network requests (max 5s delay) */
464
+ network: {
465
+ maxAttempts: 3,
466
+ baseDelayMs: 1e3,
467
+ maxDelayMs: 5e3,
468
+ jitter: true
469
+ },
470
+ /** Medium retries for API calls (max 30s delay) */
471
+ api: {
472
+ maxAttempts: 5,
473
+ baseDelayMs: 2e3,
474
+ maxDelayMs: 3e4,
475
+ jitter: true
476
+ },
477
+ /** Aggressive retries for critical operations (max 1min delay) */
478
+ critical: {
479
+ maxAttempts: 10,
480
+ baseDelayMs: 1e3,
481
+ maxDelayMs: 6e4,
482
+ jitter: true
483
+ },
484
+ /** Quick retries for fast operations (max 2s delay) */
485
+ fast: {
486
+ maxAttempts: 3,
487
+ baseDelayMs: 100,
488
+ maxDelayMs: 2e3,
489
+ jitter: false
490
+ }
491
+ };
492
+ async function withRetry(operation, options) {
493
+ const { maxAttempts, baseDelayMs, maxDelayMs = 3e4, jitter = false, onRetry, shouldRetry } = options;
494
+ return pRetry(operation, {
495
+ retries: maxAttempts,
496
+ minTimeout: baseDelayMs,
497
+ maxTimeout: maxDelayMs,
498
+ randomize: jitter,
499
+ onFailedAttempt: /* @__PURE__ */ __name((error) => {
500
+ if (shouldRetry && !shouldRetry(error)) {
501
+ throw error;
502
+ }
503
+ if (onRetry) {
504
+ onRetry(error, error.attemptNumber);
505
+ }
506
+ }, "onFailedAttempt")
507
+ });
508
+ }
509
+ __name(withRetry, "withRetry");
510
+ function calculateBackoff(attempt, baseMs, maxMs, jitter) {
511
+ const exponential = baseMs * 2 ** (attempt - 1);
512
+ const capped = Math.min(exponential, maxMs);
513
+ if (jitter) {
514
+ const jitterAmount = Math.random() * capped;
515
+ return capped + jitterAmount;
516
+ }
517
+ return capped;
518
+ }
519
+ __name(calculateBackoff, "calculateBackoff");
520
+
521
+ // ../../packages/infrastructure/dist/resiliency/concurrency.js
522
+ var queue = new PQueue({
523
+ concurrency: resilienceDefaults.mcp.maxConcurrent
524
+ });
525
+ var batchQueues = /* @__PURE__ */ new Map();
526
+ var callTool = /* @__PURE__ */ __name((name, raw) => {
527
+ const wrapped = withBreaker(name, raw);
528
+ return (input) => queue.add(() => withRetry(() => wrapped(input), {
529
+ maxAttempts: resilienceDefaults.mcp.retry.maxAttempts,
530
+ baseDelayMs: resilienceDefaults.mcp.retry.baseDelayMs,
531
+ maxDelayMs: resilienceDefaults.mcp.retry.maxDelayMs,
532
+ jitter: resilienceDefaults.mcp.retry.jitter,
533
+ onRetry: /* @__PURE__ */ __name((e, n) => logger.warn({
534
+ error: e
535
+ }, `Retrying tool ${name} attempt ${n}: ${e.message}`), "onRetry")
536
+ }));
537
+ }, "callTool");
538
+ async function batchCall(batchKey, input, processor) {
539
+ if (!batchQueues.has(batchKey)) {
540
+ batchQueues.set(batchKey, []);
541
+ }
542
+ const queue2 = batchQueues.get(batchKey);
543
+ if (!queue2) {
544
+ throw new Error(`Batch queue not found for key: ${batchKey}`);
545
+ }
546
+ return new Promise((resolve, reject) => {
547
+ queue2.push({
548
+ input,
549
+ resolve,
550
+ reject
551
+ });
552
+ if (queue2.length >= resilienceDefaults.mcp.batch.size) {
553
+ processBatch(batchKey, processor);
554
+ return;
555
+ }
556
+ setTimeout(() => {
557
+ const queue3 = batchQueues.get(batchKey);
558
+ if (queue3 && queue3.length > 0) {
559
+ processBatch(batchKey, processor);
560
+ }
561
+ }, resilienceDefaults.mcp.batch.maxWaitMs);
562
+ });
563
+ }
564
+ __name(batchCall, "batchCall");
565
+ async function processBatch(batchKey, processor) {
566
+ const queue2 = batchQueues.get(batchKey);
567
+ if (!queue2 || queue2.length === 0) {
568
+ return;
569
+ }
570
+ const batch = queue2.splice(0, resilienceDefaults.mcp.batch.size);
571
+ const inputs = batch.map((item) => item.input);
572
+ try {
573
+ logger.debug(`Processing batch of ${inputs.length} requests for ${batchKey}`);
574
+ const results = await processor(inputs);
575
+ batch.forEach((item, index) => {
576
+ if (index < results.length) {
577
+ item.resolve(results[index]);
578
+ } else {
579
+ item.reject(new Error(`No result for batch item ${index}`));
580
+ }
581
+ });
582
+ } catch (error) {
583
+ for (const item of batch) {
584
+ item.reject(error);
585
+ }
586
+ logger.error({
587
+ error
588
+ }, `Batch processing failed for ${batchKey}: ${error.message}`);
589
+ }
590
+ }
591
+ __name(processBatch, "processBatch");
592
+
593
+ export { cache_exports, getCircuitBreakerState, logger, makeWatcher, resiliency_exports, withBreaker };