@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.
- package/README.md +121 -22
- package/dist/SkippedTestDetector-AXTMWWHC.js +5 -0
- package/dist/SkippedTestDetector-QLSQV7K7.js +5 -0
- package/dist/analysis-6WTBZJH3.js +6 -0
- package/dist/analysis-C472LUGW.js +2475 -0
- package/dist/auth-UA7I3YE4.js +1446 -0
- package/dist/auto-provision-organization-6YF463TK.js +161 -0
- package/dist/{chunk-FVIYXFCL.js → chunk-4YTE4JEW.js} +2 -3
- package/dist/chunk-5EOPYJ4Y.js +12 -0
- package/dist/{chunk-ARVV3F4K.js → chunk-5SQA44V7.js} +1085 -18
- package/dist/{chunk-RB7H4UQJ.js → chunk-7ADPL4Q3.js} +10 -3
- package/dist/chunk-BE3HNVSV.js +2300 -0
- package/dist/chunk-BWWPGNZ5.js +5842 -0
- package/dist/chunk-CBGOC6RV.js +293 -0
- package/dist/{chunk-7JX6Y4TL.js → chunk-DPWFZNMY.js} +21 -34
- package/dist/{chunk-R7CUQ7CU.js → chunk-E6V6QKS7.js} +317 -33
- package/dist/chunk-GT4ZUCFR.js +111 -0
- package/dist/chunk-NOWJBG6X.js +3654 -0
- package/dist/chunk-O7HMAZ7L.js +3497 -0
- package/dist/chunk-PL4HF4M2.js +593 -0
- package/dist/chunk-V7B37PPD.js +4075 -0
- package/dist/chunk-YVZXPBSV.js +314 -0
- package/dist/chunk-ZBQDE6WJ.js +108 -0
- package/dist/client-RHDS6NOB.js +8 -0
- package/dist/dist-5LR7APG5.js +5 -0
- package/dist/dist-CUHOKNLS.js +12 -0
- package/dist/dist-RJE4RSZJ.js +9 -0
- package/dist/index.js +60568 -36578
- package/dist/local-service-adapter-AB3UYRUK.js +6 -0
- package/dist/pioneer-oauth-hook-V2JKEXM7.js +12 -0
- package/dist/{secure-credentials-IWQB6KU4.js → secure-credentials-UEPG7GWW.js} +2 -3
- package/dist/snapback-dir-MG7DTRMF.js +6 -0
- package/package.json +12 -11
- package/scripts/postinstall.mjs +2 -3
- package/dist/SkippedTestDetector-5WJZKZQ3.js +0 -5
- package/dist/SkippedTestDetector-5WJZKZQ3.js.map +0 -1
- package/dist/analysis-YI4UNUCM.js +0 -6
- package/dist/analysis-YI4UNUCM.js.map +0 -1
- package/dist/chunk-7JX6Y4TL.js.map +0 -1
- package/dist/chunk-ARVV3F4K.js.map +0 -1
- package/dist/chunk-EU2IZPOK.js +0 -13002
- package/dist/chunk-EU2IZPOK.js.map +0 -1
- package/dist/chunk-FVIYXFCL.js.map +0 -1
- package/dist/chunk-R7CUQ7CU.js.map +0 -1
- package/dist/chunk-RB7H4UQJ.js.map +0 -1
- package/dist/chunk-SOABQWAU.js +0 -385
- package/dist/chunk-SOABQWAU.js.map +0 -1
- package/dist/dist-O6EBXLN6.js +0 -5
- package/dist/dist-O6EBXLN6.js.map +0 -1
- package/dist/dist-PJVBBZTF.js +0 -5
- package/dist/dist-PJVBBZTF.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/learning-pruner-QC4CTJDX.js +0 -5
- package/dist/learning-pruner-QC4CTJDX.js.map +0 -1
- package/dist/secure-credentials-IWQB6KU4.js.map +0 -1
- package/dist/snapback-dir-V6MWXIW4.js +0 -5
- 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 };
|