nexus-agents 2.173.4 → 2.173.6
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/dist/{child-mcp-config-KD5FKDG7.js → child-mcp-config-CPBWB4TY.js} +2 -2
- package/dist/{chunk-V6ADQNN6.js → chunk-27JPMJAD.js} +5 -4
- package/dist/{chunk-V6ADQNN6.js.map → chunk-27JPMJAD.js.map} +1 -1
- package/dist/{chunk-MBTEWGZK.js → chunk-2TMWS6WT.js} +7 -7
- package/dist/{chunk-SUCOTX7I.js → chunk-5D4AXZCX.js} +4 -4
- package/dist/{chunk-6X26RTOA.js → chunk-6INAAUGD.js} +2 -2
- package/dist/{chunk-26PMOFR2.js → chunk-75MPLAEC.js} +2 -2
- package/dist/{chunk-G37IJILX.js → chunk-7N576XGX.js} +2 -2
- package/dist/{chunk-3DYABC5Y.js → chunk-AO5OIT2P.js} +4 -4
- package/dist/{chunk-XMG5D3LK.js → chunk-B3LK3YIF.js} +29 -11
- package/dist/{chunk-XMG5D3LK.js.map → chunk-B3LK3YIF.js.map} +1 -1
- package/dist/{chunk-N6UV7XFO.js → chunk-BQ3CWH5H.js} +3 -3
- package/dist/{chunk-YYCG236I.js → chunk-CMBIBZIY.js} +8 -8
- package/dist/{chunk-EL2O75ZS.js → chunk-E63P5GML.js} +2 -2
- package/dist/{chunk-O6VB54QJ.js → chunk-G66T2OIM.js} +2 -2
- package/dist/{chunk-4KURMOBY.js → chunk-GUKHGODJ.js} +2 -2
- package/dist/{chunk-HRTSIY4W.js → chunk-HT7IBYJL.js} +4 -4
- package/dist/{chunk-5WFHSWQG.js → chunk-I7HYMCVW.js} +5 -5
- package/dist/{chunk-HLCPLQFG.js → chunk-IPQW2QHU.js} +2 -2
- package/dist/{chunk-CGIT3MVV.js → chunk-K2D2IFR6.js} +5 -5
- package/dist/{chunk-XJ46NHDP.js → chunk-KU4HIPQ4.js} +5 -5
- package/dist/{chunk-3QY2YLJV.js → chunk-LZME2PGR.js} +3 -3
- package/dist/{chunk-5IDFZ2PC.js → chunk-N7LGY3C4.js} +2 -2
- package/dist/{chunk-R4ZINS62.js → chunk-NN6BBKJD.js} +91 -79
- package/dist/chunk-NN6BBKJD.js.map +1 -0
- package/dist/{chunk-LQHBSYNN.js → chunk-P52ISEJO.js} +4 -4
- package/dist/{chunk-FYYPW6EC.js → chunk-PCFVPWA5.js} +2 -2
- package/dist/{chunk-H245LNLT.js → chunk-PM35LR5P.js} +3 -3
- package/dist/{chunk-GKR7YE2E.js → chunk-QPG55YAU.js} +2 -2
- package/dist/{chunk-6OTA2VER.js → chunk-SORESQNO.js} +163 -8
- package/dist/chunk-SORESQNO.js.map +1 -0
- package/dist/{chunk-5LXKF34H.js → chunk-TRLXEYFT.js} +2 -2
- package/dist/{chunk-7FDHPEZ3.js → chunk-U2YQ2HG4.js} +2 -2
- package/dist/{chunk-M5VIIUM5.js → chunk-U3SXRK5O.js} +10 -10
- package/dist/{chunk-VK65G7MX.js → chunk-VIHP2LFY.js} +2 -2
- package/dist/{chunk-P6POKYSM.js → chunk-XDNDQ7M3.js} +2 -2
- package/dist/{chunk-NZKMPDZ4.js → chunk-YN7QDYG6.js} +3 -3
- package/dist/cli-circuit-breaker-RDVBTDIT.js +17 -0
- package/dist/cli.js +41 -42
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-XMSM4GXK.js → composite-router-YV3MIDYM.js} +2 -2
- package/dist/{consensus-vote-S7JBAHGL.js → consensus-vote-PBHH6JW6.js} +15 -15
- package/dist/{context-retriever-L2YJ6PYH.js → context-retriever-KTZ54F46.js} +8 -8
- package/dist/{doctor-deep-LMETROQX.js → doctor-deep-D2D3RPIR.js} +3 -3
- package/dist/{expert-bridge-Z6DC46Q3.js → expert-bridge-6SPKMPEG.js} +4 -4
- package/dist/{factory-LLFF3ZKV.js → factory-2UAMVT6O.js} +5 -5
- package/dist/{factory-UE63NFX6.js → factory-E2QXGLFH.js} +8 -8
- package/dist/{improvement-review-4ZE3NAST.js → improvement-review-BWWZDFOD.js} +5 -5
- package/dist/index.d.ts +15 -14
- package/dist/index.js +39 -40
- package/dist/index.js.map +1 -1
- package/dist/{init-opencode-7ZRU6CII.js → init-opencode-DJ42XZQZ.js} +5 -5
- package/dist/{issue-triage-OIKKI7AK.js → issue-triage-P3UA4CEX.js} +6 -6
- package/dist/model-registry.generated.json +1624 -1928
- package/dist/{pr-reviewer-helpers-5EAVCRYP.js → pr-reviewer-helpers-DCVX3GRQ.js} +4 -4
- package/dist/{registry-command-Q6K5EPGZ.js → registry-command-YXKTAFZX.js} +2 -2
- package/dist/{repo-security-plan-25AXO7FG.js → repo-security-plan-5EPAQMIO.js} +3 -3
- package/dist/{research-helpers-synthesize-F734REUK.js → research-helpers-synthesize-USLAWOD2.js} +4 -4
- package/dist/{routing-memory-5LU5WI5T.js → routing-memory-XGZ6T7GS.js} +2 -2
- package/dist/{session-memory-3FUIP2L6.js → session-memory-GZCB372F.js} +3 -3
- package/dist/{setup-command-EQGY5TZ5.js → setup-command-LOGCELQL.js} +13 -13
- package/dist/{setup-config-IHLHAX5G.js → setup-config-EPJD5N3U.js} +3 -3
- package/dist/{setup-custom-api-JM6Z2442.js → setup-custom-api-YXXKSX5F.js} +3 -3
- package/dist/{tool-memory-LPSFODBS.js → tool-memory-KADP6IQE.js} +5 -5
- package/dist/{unified-registry-7MDLPIIK.js → unified-registry-DZAIN5Q2.js} +9 -9
- package/dist/{weather-report-5HDPEOQ3.js → weather-report-MZMFDIDX.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-3Y5UUFZL.js +0 -155
- package/dist/chunk-3Y5UUFZL.js.map +0 -1
- package/dist/chunk-6OTA2VER.js.map +0 -1
- package/dist/chunk-R4ZINS62.js.map +0 -1
- package/dist/cli-circuit-breaker-C2DPF3IA.js +0 -14
- /package/dist/{child-mcp-config-KD5FKDG7.js.map → child-mcp-config-CPBWB4TY.js.map} +0 -0
- /package/dist/{chunk-MBTEWGZK.js.map → chunk-2TMWS6WT.js.map} +0 -0
- /package/dist/{chunk-SUCOTX7I.js.map → chunk-5D4AXZCX.js.map} +0 -0
- /package/dist/{chunk-6X26RTOA.js.map → chunk-6INAAUGD.js.map} +0 -0
- /package/dist/{chunk-26PMOFR2.js.map → chunk-75MPLAEC.js.map} +0 -0
- /package/dist/{chunk-G37IJILX.js.map → chunk-7N576XGX.js.map} +0 -0
- /package/dist/{chunk-3DYABC5Y.js.map → chunk-AO5OIT2P.js.map} +0 -0
- /package/dist/{chunk-N6UV7XFO.js.map → chunk-BQ3CWH5H.js.map} +0 -0
- /package/dist/{chunk-YYCG236I.js.map → chunk-CMBIBZIY.js.map} +0 -0
- /package/dist/{chunk-EL2O75ZS.js.map → chunk-E63P5GML.js.map} +0 -0
- /package/dist/{chunk-O6VB54QJ.js.map → chunk-G66T2OIM.js.map} +0 -0
- /package/dist/{chunk-4KURMOBY.js.map → chunk-GUKHGODJ.js.map} +0 -0
- /package/dist/{chunk-HRTSIY4W.js.map → chunk-HT7IBYJL.js.map} +0 -0
- /package/dist/{chunk-5WFHSWQG.js.map → chunk-I7HYMCVW.js.map} +0 -0
- /package/dist/{chunk-HLCPLQFG.js.map → chunk-IPQW2QHU.js.map} +0 -0
- /package/dist/{chunk-CGIT3MVV.js.map → chunk-K2D2IFR6.js.map} +0 -0
- /package/dist/{chunk-XJ46NHDP.js.map → chunk-KU4HIPQ4.js.map} +0 -0
- /package/dist/{chunk-3QY2YLJV.js.map → chunk-LZME2PGR.js.map} +0 -0
- /package/dist/{chunk-5IDFZ2PC.js.map → chunk-N7LGY3C4.js.map} +0 -0
- /package/dist/{chunk-LQHBSYNN.js.map → chunk-P52ISEJO.js.map} +0 -0
- /package/dist/{chunk-FYYPW6EC.js.map → chunk-PCFVPWA5.js.map} +0 -0
- /package/dist/{chunk-H245LNLT.js.map → chunk-PM35LR5P.js.map} +0 -0
- /package/dist/{chunk-GKR7YE2E.js.map → chunk-QPG55YAU.js.map} +0 -0
- /package/dist/{chunk-5LXKF34H.js.map → chunk-TRLXEYFT.js.map} +0 -0
- /package/dist/{chunk-7FDHPEZ3.js.map → chunk-U2YQ2HG4.js.map} +0 -0
- /package/dist/{chunk-M5VIIUM5.js.map → chunk-U3SXRK5O.js.map} +0 -0
- /package/dist/{chunk-VK65G7MX.js.map → chunk-VIHP2LFY.js.map} +0 -0
- /package/dist/{chunk-P6POKYSM.js.map → chunk-XDNDQ7M3.js.map} +0 -0
- /package/dist/{chunk-NZKMPDZ4.js.map → chunk-YN7QDYG6.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-C2DPF3IA.js.map → cli-circuit-breaker-RDVBTDIT.js.map} +0 -0
- /package/dist/{composite-router-XMSM4GXK.js.map → composite-router-YV3MIDYM.js.map} +0 -0
- /package/dist/{consensus-vote-S7JBAHGL.js.map → consensus-vote-PBHH6JW6.js.map} +0 -0
- /package/dist/{context-retriever-L2YJ6PYH.js.map → context-retriever-KTZ54F46.js.map} +0 -0
- /package/dist/{doctor-deep-LMETROQX.js.map → doctor-deep-D2D3RPIR.js.map} +0 -0
- /package/dist/{expert-bridge-Z6DC46Q3.js.map → expert-bridge-6SPKMPEG.js.map} +0 -0
- /package/dist/{factory-LLFF3ZKV.js.map → factory-2UAMVT6O.js.map} +0 -0
- /package/dist/{factory-UE63NFX6.js.map → factory-E2QXGLFH.js.map} +0 -0
- /package/dist/{improvement-review-4ZE3NAST.js.map → improvement-review-BWWZDFOD.js.map} +0 -0
- /package/dist/{init-opencode-7ZRU6CII.js.map → init-opencode-DJ42XZQZ.js.map} +0 -0
- /package/dist/{issue-triage-OIKKI7AK.js.map → issue-triage-P3UA4CEX.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-5EAVCRYP.js.map → pr-reviewer-helpers-DCVX3GRQ.js.map} +0 -0
- /package/dist/{registry-command-Q6K5EPGZ.js.map → registry-command-YXKTAFZX.js.map} +0 -0
- /package/dist/{repo-security-plan-25AXO7FG.js.map → repo-security-plan-5EPAQMIO.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-F734REUK.js.map → research-helpers-synthesize-USLAWOD2.js.map} +0 -0
- /package/dist/{routing-memory-5LU5WI5T.js.map → routing-memory-XGZ6T7GS.js.map} +0 -0
- /package/dist/{session-memory-3FUIP2L6.js.map → session-memory-GZCB372F.js.map} +0 -0
- /package/dist/{setup-command-EQGY5TZ5.js.map → setup-command-LOGCELQL.js.map} +0 -0
- /package/dist/{setup-config-IHLHAX5G.js.map → setup-config-EPJD5N3U.js.map} +0 -0
- /package/dist/{setup-custom-api-JM6Z2442.js.map → setup-custom-api-YXXKSX5F.js.map} +0 -0
- /package/dist/{tool-memory-LPSFODBS.js.map → tool-memory-KADP6IQE.js.map} +0 -0
- /package/dist/{unified-registry-7MDLPIIK.js.map → unified-registry-DZAIN5Q2.js.map} +0 -0
- /package/dist/{weather-report-5HDPEOQ3.js.map → weather-report-MZMFDIDX.js.map} +0 -0
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "./chunk-6T3EPABN.js";
|
|
6
6
|
import {
|
|
7
7
|
SessionMemory
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-QPG55YAU.js";
|
|
9
9
|
import {
|
|
10
10
|
StatsOnlyAdapter,
|
|
11
11
|
ensureSharedMemoryRegistry
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "./chunk-KSQSWEFH.js";
|
|
16
16
|
import {
|
|
17
17
|
generateId
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-E63P5GML.js";
|
|
19
19
|
import {
|
|
20
20
|
ErrorCode,
|
|
21
21
|
NexusError,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
getTimeProvider,
|
|
29
29
|
ok,
|
|
30
30
|
setSharedMobiMemDbPathResolver
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-27JPMJAD.js";
|
|
32
32
|
import {
|
|
33
33
|
nexusDataPath
|
|
34
34
|
} from "./chunk-DHVMSIT5.js";
|
|
@@ -5552,4 +5552,4 @@ export {
|
|
|
5552
5552
|
reinitializeMemoryBackends,
|
|
5553
5553
|
ToolMemoryManager
|
|
5554
5554
|
};
|
|
5555
|
-
//# sourceMappingURL=chunk-
|
|
5555
|
+
//# sourceMappingURL=chunk-P52ISEJO.js.map
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
isRateLimitLikeError,
|
|
12
12
|
lookupInTreeCapability,
|
|
13
13
|
ok
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-27JPMJAD.js";
|
|
15
15
|
|
|
16
16
|
// src/config/model-parameter-support.ts
|
|
17
17
|
function parseClaudeMajorMinor(bareId) {
|
|
@@ -828,4 +828,4 @@ export {
|
|
|
828
828
|
DEFAULT_COLLECT_STREAM_MAX_CHUNKS,
|
|
829
829
|
collectStream
|
|
830
830
|
};
|
|
831
|
-
//# sourceMappingURL=chunk-
|
|
831
|
+
//# sourceMappingURL=chunk-PCFVPWA5.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
toolStructuredError,
|
|
8
8
|
toolSuccessStructured,
|
|
9
9
|
wrapToolWithTimeout
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-YN7QDYG6.js";
|
|
11
11
|
import {
|
|
12
12
|
JsonlStore,
|
|
13
13
|
SECURITY_KEYWORDS,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
getPipelineEventBus,
|
|
20
20
|
getTimeProvider,
|
|
21
21
|
isDeclaredNeverDeprecate
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-27JPMJAD.js";
|
|
23
23
|
import {
|
|
24
24
|
getNexusDataDir,
|
|
25
25
|
nexusDataPath
|
|
@@ -2132,4 +2132,4 @@ export {
|
|
|
2132
2132
|
runImprovementReview,
|
|
2133
2133
|
registerImprovementReviewTool
|
|
2134
2134
|
};
|
|
2135
|
-
//# sourceMappingURL=chunk-
|
|
2135
|
+
//# sourceMappingURL=chunk-PM35LR5P.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getErrorMessage,
|
|
5
5
|
getTimeProvider,
|
|
6
6
|
ok
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-27JPMJAD.js";
|
|
8
8
|
|
|
9
9
|
// src/context/session-memory.ts
|
|
10
10
|
import * as fs from "fs";
|
|
@@ -352,4 +352,4 @@ export {
|
|
|
352
352
|
SessionMemory,
|
|
353
353
|
createSessionMemory
|
|
354
354
|
};
|
|
355
|
-
//# sourceMappingURL=chunk-
|
|
355
|
+
//# sourceMappingURL=chunk-QPG55YAU.js.map
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ErrorCode,
|
|
3
3
|
NexusError,
|
|
4
|
+
createLogger,
|
|
4
5
|
err,
|
|
5
6
|
getErrorMessage,
|
|
7
|
+
getFallbackChainForCategory,
|
|
6
8
|
getTimeProvider,
|
|
9
|
+
isRateLimitText,
|
|
7
10
|
ok
|
|
8
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-27JPMJAD.js";
|
|
9
12
|
|
|
10
13
|
// src/cli-adapters/circuit-breaker-types.ts
|
|
11
14
|
var CircuitErrorCode = {
|
|
@@ -54,7 +57,6 @@ var DEFAULT_CIRCUIT_BREAKER_CONFIG = {
|
|
|
54
57
|
};
|
|
55
58
|
var TIMEOUT_PATTERNS = ["timeout", "timed out"];
|
|
56
59
|
var AUTH_PATTERNS = ["auth", "unauthorized", "forbidden", "oauth"];
|
|
57
|
-
var RATE_LIMIT_PATTERNS = ["rate limit", "too many requests", "429"];
|
|
58
60
|
var CONNECTION_PATTERNS = [
|
|
59
61
|
"connection",
|
|
60
62
|
"econnrefused",
|
|
@@ -76,7 +78,7 @@ function categorizeError(error) {
|
|
|
76
78
|
const combined = `${message} ${name}`;
|
|
77
79
|
if (matchesPatterns(combined, TIMEOUT_PATTERNS)) return "timeout";
|
|
78
80
|
if (matchesPatterns(combined, AUTH_PATTERNS)) return "authentication";
|
|
79
|
-
if (
|
|
81
|
+
if (isRateLimitText(combined)) return "rate_limit";
|
|
80
82
|
if (matchesPatterns(combined, CONNECTION_PATTERNS)) return "connection";
|
|
81
83
|
if (matchesPatterns(combined, CRASH_PATTERNS)) return "crash";
|
|
82
84
|
return "unknown";
|
|
@@ -367,12 +369,165 @@ function mapModelErrorToCategory(error) {
|
|
|
367
369
|
}
|
|
368
370
|
}
|
|
369
371
|
|
|
372
|
+
// src/cli-adapters/cli-circuit-breaker.ts
|
|
373
|
+
var CATEGORY_TO_FALLBACK = {
|
|
374
|
+
code_generation: "code",
|
|
375
|
+
code_review: "code",
|
|
376
|
+
testing: "code",
|
|
377
|
+
research: "research",
|
|
378
|
+
exploration: "research",
|
|
379
|
+
documentation: "documentation",
|
|
380
|
+
architecture: "analysis",
|
|
381
|
+
security_review: "analysis",
|
|
382
|
+
planning: "analysis",
|
|
383
|
+
devops: "general"
|
|
384
|
+
};
|
|
385
|
+
var DEFAULT_FALLBACK_CHAIN = ["claude", "gemini", "codex", "opencode"];
|
|
386
|
+
var DEFAULT_CONFIG = {
|
|
387
|
+
perCliConfig: {},
|
|
388
|
+
fallbackChain: DEFAULT_FALLBACK_CHAIN,
|
|
389
|
+
enableFallback: true,
|
|
390
|
+
maxFallbackAttempts: 2
|
|
391
|
+
};
|
|
392
|
+
var defaultCliCircuitBreakerRegistry = new CircuitBreakerRegistry();
|
|
393
|
+
function getDefaultCliCircuitBreakerRegistry() {
|
|
394
|
+
return defaultCliCircuitBreakerRegistry;
|
|
395
|
+
}
|
|
396
|
+
function getCliCircuitBreakerSnapshot(cliName) {
|
|
397
|
+
return defaultCliCircuitBreakerRegistry.getAllSnapshots().get(cliName);
|
|
398
|
+
}
|
|
399
|
+
var CliCircuitBreakerIntegration = class {
|
|
400
|
+
registry;
|
|
401
|
+
adapters = /* @__PURE__ */ new Map();
|
|
402
|
+
config;
|
|
403
|
+
logger;
|
|
404
|
+
constructor(adapters, config, logger) {
|
|
405
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
406
|
+
this.logger = logger ?? createLogger({ component: "cli-circuit-breaker-integration" });
|
|
407
|
+
this.registry = config === void 0 ? defaultCliCircuitBreakerRegistry : new CircuitBreakerRegistry();
|
|
408
|
+
for (const adapter of adapters) {
|
|
409
|
+
this.adapters.set(adapter.name, adapter);
|
|
410
|
+
this.registry.getBreaker(adapter.name, this.config.perCliConfig[adapter.name]);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
async execute(adapter, task, taskCategory) {
|
|
414
|
+
const primaryCli = adapter.name;
|
|
415
|
+
const fallbackAttempts = [];
|
|
416
|
+
let lastError;
|
|
417
|
+
const primaryResult = await this.executeWithBreaker(adapter, task);
|
|
418
|
+
if (primaryResult.ok) {
|
|
419
|
+
return ok({ response: primaryResult.value, executedBy: primaryCli, usedFallback: false });
|
|
420
|
+
}
|
|
421
|
+
lastError = primaryResult.error;
|
|
422
|
+
if (!this.config.enableFallback || !(lastError instanceof CircuitError)) {
|
|
423
|
+
return err(lastError);
|
|
424
|
+
}
|
|
425
|
+
for (const cli of this.getFallbackClis(primaryCli, taskCategory).slice(
|
|
426
|
+
0,
|
|
427
|
+
this.config.maxFallbackAttempts
|
|
428
|
+
)) {
|
|
429
|
+
const fallbackAdapter = this.adapters.get(cli);
|
|
430
|
+
if (!fallbackAdapter) continue;
|
|
431
|
+
fallbackAttempts.push(cli);
|
|
432
|
+
this.logger.info("Attempting fallback", { from: primaryCli, to: cli });
|
|
433
|
+
const result = await this.executeWithBreaker(fallbackAdapter, task);
|
|
434
|
+
if (result.ok) {
|
|
435
|
+
return ok({
|
|
436
|
+
response: result.value,
|
|
437
|
+
executedBy: cli,
|
|
438
|
+
usedFallback: true,
|
|
439
|
+
fallbackAttempts
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
lastError = result.error;
|
|
443
|
+
}
|
|
444
|
+
this.logger.warn("All fallback attempts failed", { primaryCli, fallbackAttempts });
|
|
445
|
+
return err(lastError);
|
|
446
|
+
}
|
|
447
|
+
getHealthStatus() {
|
|
448
|
+
const snapshots = this.registry.getAllSnapshots();
|
|
449
|
+
const clis = [];
|
|
450
|
+
let healthyCount = 0;
|
|
451
|
+
for (const name of this.adapters.keys()) {
|
|
452
|
+
const snapshot = snapshots.get(name);
|
|
453
|
+
if (!snapshot) continue;
|
|
454
|
+
const healthy = snapshot.state === "closed";
|
|
455
|
+
if (healthy) healthyCount++;
|
|
456
|
+
clis.push({
|
|
457
|
+
name,
|
|
458
|
+
healthy,
|
|
459
|
+
circuitState: snapshot.state,
|
|
460
|
+
failureCount: snapshot.failureCount,
|
|
461
|
+
lastFailureTime: snapshot.lastFailureTime
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
clis,
|
|
466
|
+
systemHealthy: healthyCount > 0,
|
|
467
|
+
healthyCount,
|
|
468
|
+
timestamp: getTimeProvider().now()
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
getCircuitSnapshots() {
|
|
472
|
+
const allSnapshots = this.registry.getAllSnapshots();
|
|
473
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
474
|
+
for (const name of this.adapters.keys()) {
|
|
475
|
+
const snapshot = allSnapshots.get(name);
|
|
476
|
+
if (snapshot !== void 0) {
|
|
477
|
+
snapshots.set(name, snapshot);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return snapshots;
|
|
481
|
+
}
|
|
482
|
+
resetCircuit(cliName) {
|
|
483
|
+
this.registry.reset(cliName);
|
|
484
|
+
this.logger.info("Circuit reset", { cliName });
|
|
485
|
+
}
|
|
486
|
+
resetAllCircuits() {
|
|
487
|
+
this.registry.resetAll();
|
|
488
|
+
this.logger.info("All circuits reset");
|
|
489
|
+
}
|
|
490
|
+
addStateChangeListener(listener) {
|
|
491
|
+
this.registry.addGlobalStateChangeListener(listener);
|
|
492
|
+
}
|
|
493
|
+
async executeWithBreaker(adapter, task) {
|
|
494
|
+
const breaker = this.registry.getBreaker(adapter.name);
|
|
495
|
+
const result = await breaker.execute(async () => {
|
|
496
|
+
const execResult = await adapter.execute(task);
|
|
497
|
+
if (!execResult.ok) {
|
|
498
|
+
breaker.recordFailure(mapCliErrorToCategory(execResult.error.code));
|
|
499
|
+
const wrappedError = new Error(execResult.error.message);
|
|
500
|
+
wrappedError.cliError = execResult.error;
|
|
501
|
+
throw wrappedError;
|
|
502
|
+
}
|
|
503
|
+
return execResult.value;
|
|
504
|
+
});
|
|
505
|
+
if (!result.ok) {
|
|
506
|
+
if (result.error.circuitErrorCode === "CIRCUIT_OPEN") return err(result.error);
|
|
507
|
+
const wrapped = result.error.cause;
|
|
508
|
+
if (wrapped?.cliError) return err(wrapped.cliError);
|
|
509
|
+
return err(result.error);
|
|
510
|
+
}
|
|
511
|
+
return ok(result.value);
|
|
512
|
+
}
|
|
513
|
+
getFallbackClis(excludeCli, taskCategory) {
|
|
514
|
+
const chain = taskCategory !== void 0 ? getFallbackChainForCategory(taskCategory, CATEGORY_TO_FALLBACK[taskCategory]) : this.config.fallbackChain;
|
|
515
|
+
return [...chain].filter(
|
|
516
|
+
(cli) => cli !== excludeCli && !this.registry.isOpen(cli) && this.adapters.has(cli)
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
function createCliCircuitBreakerIntegration(adapters, config, logger) {
|
|
521
|
+
return new CliCircuitBreakerIntegration(adapters, config, logger);
|
|
522
|
+
}
|
|
523
|
+
|
|
370
524
|
export {
|
|
371
|
-
CircuitError,
|
|
372
525
|
DEFAULT_CIRCUIT_BREAKER_CONFIG,
|
|
373
526
|
CliCircuitBreaker,
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
527
|
+
mapModelErrorToCategory,
|
|
528
|
+
getDefaultCliCircuitBreakerRegistry,
|
|
529
|
+
getCliCircuitBreakerSnapshot,
|
|
530
|
+
CliCircuitBreakerIntegration,
|
|
531
|
+
createCliCircuitBreakerIntegration
|
|
377
532
|
};
|
|
378
|
-
//# sourceMappingURL=chunk-
|
|
533
|
+
//# sourceMappingURL=chunk-SORESQNO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-adapters/circuit-breaker-types.ts","../src/cli-adapters/circuit-breaker.ts","../src/cli-adapters/cli-circuit-breaker.ts"],"sourcesContent":["/**\n * nexus-agents/cli-adapters - Circuit Breaker Types\n *\n * Type definitions and error classes for the circuit breaker pattern.\n *\n * (Source: Issue #81 - Circuit breaker for CLI failures)\n */\n\nimport { NexusError, ErrorCode } from '../core/errors.js';\nimport { isRateLimitText } from '../adapters/rate-limit-detector.js';\nimport type { CliName } from './types.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Circuit breaker states.\n */\nexport type CircuitState = 'closed' | 'open' | 'half-open';\n\n/**\n * Categories of failures for circuit breaker decisions.\n */\nexport type FailureCategory =\n | 'timeout' // CLI didn't respond in time\n | 'crash' // Process crashed or exited unexpectedly\n | 'authentication' // OAuth/auth failure\n | 'rate_limit' // Rate limit exceeded\n | 'connection' // MCP connection failed\n | 'unknown'; // Uncategorized failure\n\n/**\n * Configuration options for circuit breaker.\n */\nexport interface CircuitBreakerConfig {\n /** Number of failures before opening circuit (default: 5) */\n readonly failureThreshold: number;\n /** Time in ms before attempting recovery (default: 30000) */\n readonly resetTimeoutMs: number;\n /** Successful calls needed in half-open to close (default: 2) */\n readonly halfOpenSuccessThreshold: number;\n /** Whether to count timeouts as failures (default: true) */\n readonly countTimeoutsAsFailures: boolean;\n /** Whether to count auth failures as failures (default: false) */\n readonly countAuthFailuresAsFailures: boolean;\n /** Whether to count rate limit errors as failures (default: false) */\n readonly countRateLimitsAsFailures: boolean;\n /** Maximum number of requests allowed in half-open state (default: 3) */\n readonly halfOpenMaxRequests: number;\n}\n\n/**\n * Circuit breaker state snapshot.\n */\nexport interface CircuitBreakerSnapshot {\n /** Current state */\n readonly state: CircuitState;\n /** Total failure count since last closed */\n readonly failureCount: number;\n /** Success count in half-open state */\n readonly successCount: number;\n /** Timestamp of last failure */\n readonly lastFailureTime: number | null;\n /** Timestamp of last state change */\n readonly lastStateChange: number;\n /** Requests in current half-open window */\n readonly halfOpenRequests: number;\n /** Configuration */\n readonly config: CircuitBreakerConfig;\n}\n\n/**\n * Event emitted on circuit state changes.\n */\nexport interface CircuitStateChangeEvent {\n /** CLI name */\n readonly cliName: CliName;\n /** Previous state */\n readonly previousState: CircuitState;\n /** New state */\n readonly newState: CircuitState;\n /** Timestamp of change */\n readonly timestamp: number;\n /** Failure count at time of change */\n readonly failureCount: number;\n /** Reason for state change */\n readonly reason: string;\n}\n\n/**\n * Event listener for circuit state changes.\n */\nexport type CircuitStateChangeListener = (event: CircuitStateChangeEvent) => void;\n\n/**\n * Interface for circuit breaker operations.\n */\nexport interface ICircuitBreaker {\n /**\n * Executes a function with circuit breaker protection.\n */\n execute<T>(fn: () => Promise<T>): Promise<import('../core/index.js').Result<T, CircuitError>>;\n\n /**\n * Gets the current circuit state.\n */\n getState(): CircuitState;\n\n /**\n * Gets a full snapshot of circuit breaker state.\n */\n getSnapshot(): CircuitBreakerSnapshot;\n\n /**\n * Manually resets the circuit breaker to closed state.\n */\n reset(): void;\n\n /**\n * Records a failure manually (for external failure detection).\n */\n recordFailure(category: FailureCategory): void;\n\n /**\n * Records a success manually (for external success detection).\n */\n recordSuccess(): void;\n}\n\n// ============================================================================\n// Error Codes\n// ============================================================================\n\n/**\n * Error codes specific to circuit breaker.\n */\nexport const CircuitErrorCode = {\n CIRCUIT_OPEN: 'CIRCUIT_OPEN',\n CIRCUIT_HALF_OPEN_REJECTED: 'CIRCUIT_HALF_OPEN_REJECTED',\n EXECUTION_FAILED: 'EXECUTION_FAILED',\n} as const;\n\nexport type CircuitErrorCode = (typeof CircuitErrorCode)[keyof typeof CircuitErrorCode];\n\n// ============================================================================\n// Error Class\n// ============================================================================\n\n/**\n * Error thrown when circuit breaker blocks a request.\n */\nexport class CircuitError extends NexusError {\n readonly circuitErrorCode: CircuitErrorCode;\n readonly cliName: CliName;\n readonly circuitState: CircuitState;\n readonly failureCategory?: FailureCategory;\n\n constructor(\n message: string,\n options: {\n circuitErrorCode: CircuitErrorCode;\n cliName: CliName;\n circuitState: CircuitState;\n failureCategory?: FailureCategory;\n cause?: Error;\n }\n ) {\n const baseOptions: { code: ErrorCode; cause?: Error; context: Record<string, unknown> } = {\n code: ErrorCode.INTERNAL_ERROR,\n context: {\n circuitErrorCode: options.circuitErrorCode,\n cliName: options.cliName,\n circuitState: options.circuitState,\n },\n };\n if (options.cause !== undefined) {\n baseOptions.cause = options.cause;\n }\n if (options.failureCategory !== undefined) {\n baseOptions.context['failureCategory'] = options.failureCategory;\n }\n super(message, baseOptions);\n this.name = 'CircuitError';\n this.circuitErrorCode = options.circuitErrorCode;\n this.cliName = options.cliName;\n this.circuitState = options.circuitState;\n if (options.failureCategory !== undefined) {\n this.failureCategory = options.failureCategory;\n }\n }\n}\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\n/**\n * Default circuit breaker configuration.\n */\nexport const DEFAULT_CIRCUIT_BREAKER_CONFIG: CircuitBreakerConfig = {\n failureThreshold: 5,\n resetTimeoutMs: 30_000,\n halfOpenSuccessThreshold: 2,\n countTimeoutsAsFailures: true,\n countAuthFailuresAsFailures: false,\n countRateLimitsAsFailures: true,\n halfOpenMaxRequests: 3,\n} as const;\n\n// ============================================================================\n// Error Categorization Patterns\n// ============================================================================\n\n/**\n * Pattern matchers for categorizing errors.\n */\nconst TIMEOUT_PATTERNS = ['timeout', 'timed out'];\nconst AUTH_PATTERNS = ['auth', 'unauthorized', 'forbidden', 'oauth'];\nconst CONNECTION_PATTERNS = [\n 'connection',\n 'econnrefused',\n 'enotfound',\n 'mcp',\n 'eaddrinuse',\n 'address already in use',\n];\nconst CRASH_PATTERNS = ['crash', 'exited', 'killed', 'sigterm', 'sigkill'];\n\n/**\n * Checks if text contains any of the patterns.\n */\nfunction matchesPatterns(text: string, patterns: string[]): boolean {\n return patterns.some((pattern) => text.includes(pattern));\n}\n\n/**\n * Categorizes an error into a failure category.\n */\nexport function categorizeError(error: unknown): FailureCategory {\n if (!(error instanceof Error)) {\n return 'unknown';\n }\n\n const message = error.message.toLowerCase();\n const name = error.name.toLowerCase();\n const combined = `${message} ${name}`;\n\n if (matchesPatterns(combined, TIMEOUT_PATTERNS)) return 'timeout';\n if (matchesPatterns(combined, AUTH_PATTERNS)) return 'authentication';\n if (isRateLimitText(combined)) return 'rate_limit';\n if (matchesPatterns(combined, CONNECTION_PATTERNS)) return 'connection';\n if (matchesPatterns(combined, CRASH_PATTERNS)) return 'crash';\n\n return 'unknown';\n}\n","/**\n * nexus-agents/cli-adapters - Circuit Breaker Implementation\n *\n * Implements the circuit breaker pattern to handle CLI failures gracefully\n * and prevent cascade failures in the multi-CLI mesh.\n *\n * (Source: Issue #81 - Circuit breaker for CLI failures)\n * (Source: Martin Fowler's Circuit Breaker pattern)\n */\n\nimport type { Result } from '../core/index.js';\nimport { getErrorMessage, err, ok, getTimeProvider } from '../core/index.js';\n\nimport { ErrorCode, type ModelError } from '../core/errors.js';\n\nimport type { CliName, CliErrorCode } from './types.js';\nimport {\n CircuitError,\n CircuitErrorCode,\n DEFAULT_CIRCUIT_BREAKER_CONFIG,\n categorizeError,\n type CircuitState,\n type FailureCategory,\n type CircuitBreakerConfig,\n type CircuitBreakerSnapshot,\n type CircuitStateChangeEvent,\n type CircuitStateChangeListener,\n type ICircuitBreaker,\n} from './circuit-breaker-types.js';\n\n// Re-export all types for convenience\nexport {\n CircuitError,\n CircuitErrorCode,\n DEFAULT_CIRCUIT_BREAKER_CONFIG,\n categorizeError,\n type CircuitState,\n type FailureCategory,\n type CircuitBreakerConfig,\n type CircuitBreakerSnapshot,\n type CircuitStateChangeEvent,\n type CircuitStateChangeListener,\n type ICircuitBreaker,\n} from './circuit-breaker-types.js';\n\n// ============================================================================\n// Circuit Breaker Implementation\n// ============================================================================\n\n/**\n * Circuit breaker implementation for CLI adapters.\n *\n * Provides protection against cascading failures by:\n * 1. Tracking failure counts\n * 2. Opening circuit when threshold exceeded\n * 3. Allowing gradual recovery through half-open state\n */\nexport class CliCircuitBreaker implements ICircuitBreaker {\n private state: CircuitState = 'closed';\n private failureCount = 0;\n private successCount = 0;\n private lastFailureTime: number | null = null;\n private lastStateChange: number;\n private halfOpenRequests = 0;\n private readonly listeners: Set<CircuitStateChangeListener> = new Set();\n\n constructor(\n private readonly cliName: CliName,\n private readonly config: CircuitBreakerConfig = DEFAULT_CIRCUIT_BREAKER_CONFIG\n ) {\n this.lastStateChange = getTimeProvider().now();\n }\n\n /**\n * Executes a function with circuit breaker protection.\n */\n async execute<T>(fn: () => Promise<T>): Promise<Result<T, CircuitError>> {\n const canExecute = this.canExecute();\n if (!canExecute.ok) {\n return canExecute;\n }\n\n try {\n const result = await fn();\n this.onSuccess();\n return ok(result);\n } catch (error) {\n const category = categorizeError(error);\n if (this.shouldCountFailure(category)) {\n this.onFailure(category);\n }\n return err(this.createExecutionError(error, category));\n }\n }\n\n getState(): CircuitState {\n this.checkStateTransition();\n return this.state;\n }\n\n getSnapshot(): CircuitBreakerSnapshot {\n this.checkStateTransition();\n return {\n state: this.state,\n failureCount: this.failureCount,\n successCount: this.successCount,\n lastFailureTime: this.lastFailureTime,\n lastStateChange: this.lastStateChange,\n halfOpenRequests: this.halfOpenRequests,\n config: this.config,\n };\n }\n\n reset(): void {\n const previousState = this.state;\n this.state = 'closed';\n this.failureCount = 0;\n this.successCount = 0;\n this.lastFailureTime = null;\n this.halfOpenRequests = 0;\n this.lastStateChange = getTimeProvider().now();\n\n if (previousState !== 'closed') {\n this.emitStateChange(previousState, 'closed', 'Manual reset');\n }\n }\n\n recordFailure(category: FailureCategory): void {\n if (this.shouldCountFailure(category)) {\n this.onFailure(category);\n }\n }\n\n recordSuccess(): void {\n this.onSuccess();\n }\n\n addStateChangeListener(listener: CircuitStateChangeListener): void {\n this.listeners.add(listener);\n }\n\n removeStateChangeListener(listener: CircuitStateChangeListener): void {\n this.listeners.delete(listener);\n }\n\n // -------------------------------------------------------------------------\n // Private Methods\n // -------------------------------------------------------------------------\n\n private canExecute(): Result<true, CircuitError> {\n this.checkStateTransition();\n\n if (this.state === 'closed') {\n return ok(true);\n }\n\n if (this.state === 'open') {\n return err(\n new CircuitError(`Circuit is open for CLI: ${this.cliName}`, {\n circuitErrorCode: CircuitErrorCode.CIRCUIT_OPEN,\n cliName: this.cliName,\n circuitState: this.state,\n })\n );\n }\n\n // half-open state\n if (this.halfOpenRequests >= this.config.halfOpenMaxRequests) {\n return err(\n new CircuitError(`Circuit half-open request limit reached for CLI: ${this.cliName}`, {\n circuitErrorCode: CircuitErrorCode.CIRCUIT_HALF_OPEN_REJECTED,\n cliName: this.cliName,\n circuitState: this.state,\n })\n );\n }\n this.halfOpenRequests++;\n return ok(true);\n }\n\n private checkStateTransition(): void {\n if (this.state === 'open' && this.lastFailureTime !== null) {\n const elapsed = getTimeProvider().now() - this.lastFailureTime;\n if (elapsed >= this.config.resetTimeoutMs) {\n this.transitionTo('half-open', 'Reset timeout elapsed');\n }\n }\n }\n\n private onSuccess(): void {\n if (this.state === 'closed') {\n this.failureCount = 0;\n } else if (this.state === 'half-open') {\n this.successCount++;\n if (this.successCount >= this.config.halfOpenSuccessThreshold) {\n const reason = `${String(this.successCount)} consecutive successes in half-open state`;\n this.transitionTo('closed', reason);\n }\n }\n }\n\n private onFailure(category: FailureCategory): void {\n this.failureCount++;\n this.lastFailureTime = getTimeProvider().now();\n\n if (this.state === 'closed' && this.failureCount >= this.config.failureThreshold) {\n const reason = `Failure threshold (${String(this.config.failureThreshold)}) exceeded`;\n this.transitionTo('open', reason);\n } else if (this.state === 'half-open') {\n this.transitionTo('open', `Failure during half-open recovery (category: ${category})`);\n }\n }\n\n private transitionTo(newState: CircuitState, reason: string): void {\n const previousState = this.state;\n this.state = newState;\n this.lastStateChange = getTimeProvider().now();\n\n if (newState === 'closed') {\n this.failureCount = 0;\n this.successCount = 0;\n this.halfOpenRequests = 0;\n } else if (newState === 'half-open') {\n // #3026 finding 5: pre-fix `failureCount` carried over across\n // recovery cycles. transitionTo('open',…) only zeroes counts on\n // 'closed', so a half-open→open→half-open flaky pattern grew\n // `failureCount` monotonically across cycles. The count served\n // its threshold purpose when we opened the circuit; resetting on\n // 'half-open' restores the documented per-cycle semantic that\n // operator dashboards / alerts read from `getSnapshot()`.\n this.failureCount = 0;\n this.successCount = 0;\n this.halfOpenRequests = 0;\n }\n\n this.emitStateChange(previousState, newState, reason);\n }\n\n private emitStateChange(\n previousState: CircuitState,\n newState: CircuitState,\n reason: string\n ): void {\n const event: CircuitStateChangeEvent = {\n cliName: this.cliName,\n previousState,\n newState,\n timestamp: this.lastStateChange,\n failureCount: this.failureCount,\n reason,\n };\n\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch {\n // Ignore listener errors to prevent cascade\n }\n }\n }\n\n private shouldCountFailure(category: FailureCategory): boolean {\n if (category === 'timeout') return this.config.countTimeoutsAsFailures;\n if (category === 'authentication') return this.config.countAuthFailuresAsFailures;\n if (category === 'rate_limit') return this.config.countRateLimitsAsFailures;\n return true;\n }\n\n private createExecutionError(error: unknown, category: FailureCategory): CircuitError {\n const message = getErrorMessage(error);\n const cause = error instanceof Error ? error : new Error(String(error));\n return new CircuitError(`CLI execution failed: ${message}`, {\n circuitErrorCode: CircuitErrorCode.EXECUTION_FAILED,\n cliName: this.cliName,\n circuitState: this.state,\n failureCategory: category,\n cause,\n });\n }\n}\n\n// ============================================================================\n// Registry\n// ============================================================================\n\n/**\n * Registry for managing per-CLI circuit breakers.\n */\nexport class CircuitBreakerRegistry {\n private readonly breakers: Map<CliName, CliCircuitBreaker> = new Map();\n private readonly globalListeners: Set<CircuitStateChangeListener> = new Set();\n\n constructor(private readonly defaultConfig: Partial<CircuitBreakerConfig> = {}) {}\n\n getBreaker(cliName: CliName, config?: Partial<CircuitBreakerConfig>): CliCircuitBreaker {\n let breaker = this.breakers.get(cliName);\n\n if (!breaker) {\n const mergedConfig: CircuitBreakerConfig = {\n ...DEFAULT_CIRCUIT_BREAKER_CONFIG,\n ...this.defaultConfig,\n ...config,\n };\n breaker = new CliCircuitBreaker(cliName, mergedConfig);\n\n for (const listener of this.globalListeners) {\n breaker.addStateChangeListener(listener);\n }\n\n this.breakers.set(cliName, breaker);\n }\n\n return breaker;\n }\n\n isOpen(cliName: CliName): boolean {\n return this.breakers.get(cliName)?.getState() === 'open';\n }\n\n getAllSnapshots(): Map<CliName, CircuitBreakerSnapshot> {\n const snapshots = new Map<CliName, CircuitBreakerSnapshot>();\n for (const [name, breaker] of this.breakers) {\n snapshots.set(name, breaker.getSnapshot());\n }\n return snapshots;\n }\n\n resetAll(): void {\n for (const breaker of this.breakers.values()) {\n breaker.reset();\n }\n }\n\n reset(cliName: CliName): void {\n this.breakers.get(cliName)?.reset();\n }\n\n addGlobalStateChangeListener(listener: CircuitStateChangeListener): void {\n this.globalListeners.add(listener);\n for (const breaker of this.breakers.values()) {\n breaker.addStateChangeListener(listener);\n }\n }\n\n removeGlobalStateChangeListener(listener: CircuitStateChangeListener): void {\n this.globalListeners.delete(listener);\n for (const breaker of this.breakers.values()) {\n breaker.removeStateChangeListener(listener);\n }\n }\n\n getHealthyClis(): CliName[] {\n const healthy: CliName[] = [];\n for (const [name, breaker] of this.breakers) {\n if (breaker.getState() === 'closed') {\n healthy.push(name);\n }\n }\n return healthy;\n }\n\n getUnhealthyClis(): CliName[] {\n const unhealthy: CliName[] = [];\n for (const [name, breaker] of this.breakers) {\n const state = breaker.getState();\n if (state === 'open' || state === 'half-open') {\n unhealthy.push(name);\n }\n }\n return unhealthy;\n }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Maps CLI error codes to failure categories.\n */\nexport function mapCliErrorToCategory(errorCode: CliErrorCode): FailureCategory {\n const mapping: Record<string, FailureCategory> = {\n TIMEOUT: 'timeout',\n NOT_AUTHENTICATED: 'authentication',\n RATE_LIMITED: 'rate_limit',\n CONNECTION_ERROR: 'connection',\n };\n return mapping[errorCode] ?? 'unknown';\n}\n\n/**\n * Maps a direct-API {@link ModelError} to a circuit-breaker failure category.\n *\n * Mirrors {@link mapCliErrorToCategory} for the IModelAdapter layer (#3423):\n * API failures must drive the same breaker degradation/failover learning that\n * CLI subprocess failures already get. Maps by the structured `error.code`\n * first, then falls back to message-pattern categorization via\n * {@link categorizeError} (which returns `'unknown'` if nothing matches).\n *\n * The fallback is what turns a generic `MODEL_ERROR` whose message reads\n * \"connection refused\" into a `connection` category instead of `unknown`.\n */\nexport function mapModelErrorToCategory(error: ModelError): FailureCategory {\n switch (error.code) {\n case ErrorCode.MODEL_TIMEOUT:\n case ErrorCode.TIMEOUT_ERROR:\n return 'timeout';\n case ErrorCode.UNAUTHORIZED:\n return 'authentication';\n case ErrorCode.MODEL_RATE_LIMITED:\n case ErrorCode.RATE_LIMIT_ERROR:\n return 'rate_limit';\n case ErrorCode.MODEL_UNAVAILABLE:\n case ErrorCode.MODEL_NOT_FOUND:\n // Intentional reuse of `connection`: there is no dedicated \"endpoint gone /\n // model retired\" category, and `connection` is a counted, failover-driving\n // category — the right behaviour for an unavailable/missing model.\n return 'connection';\n default:\n // MODEL_ERROR and any other code: fall back to message-pattern matching.\n return categorizeError(error);\n }\n}\n\n// `createCircuitBreakerRegistryWithMetrics` and the\n// `Capacity Monitor Integration` section\n// (`integrateCapacityMonitorWithCircuitBreaker` + the\n// `CapacityMonitorIntegrationConfig` interface and its default config)\n// were removed in #3018 — both had only test-file callers in the tree.\n// The `CircuitBreakerRegistry` above is what production adapters use;\n// if metrics-logging or capacity-monitor integration come back as real\n// requirements, reintroduce them alongside the consumer code in the\n// same PR (activation-or-delete YAGNI — same pattern as #2937–#2940).\n","/**\n * nexus-agents/cli-adapters - CLI Circuit Breaker Integration\n *\n * Wraps CLI adapter calls with circuit breaker pattern for resilient\n * multi-CLI execution with automatic fallback on failures.\n *\n * (Source: Issue #359 - Integrate circuit breaker with CLI adapters)\n */\n\nimport type { Result, ILogger } from '../core/index.js';\nimport { ok, err, createLogger, getTimeProvider } from '../core/index.js';\nimport type { TaskCategory } from '../config/task-specialization-types.js';\nimport type { FallbackTaskType } from './task-classifier.js';\nimport { getFallbackChainForCategory } from './fallback-chains.js';\nimport type { ICliAdapter, CliName, CliTask, CliResponse, CliError } from './types.js';\nimport {\n CircuitBreakerRegistry,\n CircuitError,\n mapCliErrorToCategory,\n type CircuitBreakerConfig,\n type CircuitBreakerSnapshot,\n type CircuitStateChangeListener,\n} from './circuit-breaker.js';\n\n/** Maps canonical TaskCategory (10 types) to FallbackTaskType (5 types). */\nconst CATEGORY_TO_FALLBACK: Record<TaskCategory, FallbackTaskType> = {\n code_generation: 'code',\n code_review: 'code',\n testing: 'code',\n research: 'research',\n exploration: 'research',\n documentation: 'documentation',\n architecture: 'analysis',\n security_review: 'analysis',\n planning: 'analysis',\n devops: 'general',\n};\n\n/** Configuration for CLI circuit breaker integration. */\nexport interface CliCircuitBreakerConfig {\n readonly perCliConfig?: Partial<Record<CliName, Partial<CircuitBreakerConfig>>>;\n readonly fallbackChain?: ReadonlyArray<CliName>;\n readonly enableFallback?: boolean;\n readonly maxFallbackAttempts?: number;\n}\n\n/** Result of a circuit-protected execution with fallback info. */\nexport interface CircuitProtectedResult {\n readonly response: CliResponse;\n readonly executedBy: CliName;\n readonly usedFallback: boolean;\n readonly fallbackAttempts?: ReadonlyArray<CliName>;\n}\n\n/** Health status for all CLIs with circuit state. */\nexport interface CliCircuitHealthStatus {\n readonly clis: ReadonlyArray<{\n readonly name: CliName;\n readonly healthy: boolean;\n readonly circuitState: 'closed' | 'open' | 'half-open';\n readonly failureCount: number;\n readonly lastFailureTime: number | null;\n }>;\n readonly systemHealthy: boolean;\n readonly healthyCount: number;\n readonly timestamp: number;\n}\n\n/** Interface for CLI circuit breaker integration. */\nexport interface ICliCircuitBreakerIntegration {\n execute(\n adapter: ICliAdapter,\n task: CliTask,\n taskCategory?: TaskCategory\n ): Promise<Result<CircuitProtectedResult, CircuitError | CliError>>;\n getHealthStatus(): CliCircuitHealthStatus;\n getCircuitSnapshots(): Map<CliName, CircuitBreakerSnapshot>;\n resetCircuit(cliName: CliName): void;\n resetAllCircuits(): void;\n addStateChangeListener(listener: CircuitStateChangeListener): void;\n}\n\nconst DEFAULT_FALLBACK_CHAIN: ReadonlyArray<CliName> = ['claude', 'gemini', 'codex', 'opencode'];\nconst DEFAULT_CONFIG: Required<CliCircuitBreakerConfig> = {\n perCliConfig: {},\n fallbackChain: DEFAULT_FALLBACK_CHAIN,\n enableFallback: true,\n maxFallbackAttempts: 2,\n};\nconst defaultCliCircuitBreakerRegistry = new CircuitBreakerRegistry();\n\n/** Returns the shared CLI circuit-breaker registry used by default integrations. */\nexport function getDefaultCliCircuitBreakerRegistry(): CircuitBreakerRegistry {\n return defaultCliCircuitBreakerRegistry;\n}\n\n/**\n * Reads the current snapshot for a CLI without creating a new breaker.\n *\n * `undefined` means no circuit state is known yet, so callers should fail open.\n */\nexport function getCliCircuitBreakerSnapshot(cliName: CliName): CircuitBreakerSnapshot | undefined {\n return defaultCliCircuitBreakerRegistry.getAllSnapshots().get(cliName);\n}\n\n/**\n * Integrates circuit breaker pattern with CLI adapters.\n * Provides automatic fallback when a CLI's circuit opens.\n */\nexport class CliCircuitBreakerIntegration implements ICliCircuitBreakerIntegration {\n private readonly registry: CircuitBreakerRegistry;\n private readonly adapters: Map<CliName, ICliAdapter> = new Map();\n private readonly config: Required<CliCircuitBreakerConfig>;\n private readonly logger: ILogger;\n\n constructor(\n adapters: ReadonlyArray<ICliAdapter>,\n config?: CliCircuitBreakerConfig,\n logger?: ILogger\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.logger = logger ?? createLogger({ component: 'cli-circuit-breaker-integration' });\n this.registry =\n config === undefined ? defaultCliCircuitBreakerRegistry : new CircuitBreakerRegistry();\n for (const adapter of adapters) {\n this.adapters.set(adapter.name, adapter);\n this.registry.getBreaker(adapter.name, this.config.perCliConfig[adapter.name]);\n }\n }\n\n async execute(\n adapter: ICliAdapter,\n task: CliTask,\n taskCategory?: TaskCategory\n ): Promise<Result<CircuitProtectedResult, CircuitError | CliError>> {\n const primaryCli = adapter.name;\n const fallbackAttempts: CliName[] = [];\n let lastError: CircuitError | CliError | undefined;\n\n const primaryResult = await this.executeWithBreaker(adapter, task);\n if (primaryResult.ok) {\n return ok({ response: primaryResult.value, executedBy: primaryCli, usedFallback: false });\n }\n lastError = primaryResult.error;\n\n if (!this.config.enableFallback || !(lastError instanceof CircuitError)) {\n return err(lastError);\n }\n\n for (const cli of this.getFallbackClis(primaryCli, taskCategory).slice(\n 0,\n this.config.maxFallbackAttempts\n )) {\n const fallbackAdapter = this.adapters.get(cli);\n if (!fallbackAdapter) continue;\n fallbackAttempts.push(cli);\n this.logger.info('Attempting fallback', { from: primaryCli, to: cli });\n const result = await this.executeWithBreaker(fallbackAdapter, task);\n if (result.ok) {\n return ok({\n response: result.value,\n executedBy: cli,\n usedFallback: true,\n fallbackAttempts,\n });\n }\n lastError = result.error;\n }\n\n this.logger.warn('All fallback attempts failed', { primaryCli, fallbackAttempts });\n return err(lastError);\n }\n\n getHealthStatus(): CliCircuitHealthStatus {\n const snapshots = this.registry.getAllSnapshots();\n const clis: CliCircuitHealthStatus['clis'][number][] = [];\n let healthyCount = 0;\n for (const name of this.adapters.keys()) {\n const snapshot = snapshots.get(name);\n if (!snapshot) continue;\n const healthy = snapshot.state === 'closed';\n if (healthy) healthyCount++;\n clis.push({\n name,\n healthy,\n circuitState: snapshot.state,\n failureCount: snapshot.failureCount,\n lastFailureTime: snapshot.lastFailureTime,\n });\n }\n return {\n clis,\n systemHealthy: healthyCount > 0,\n healthyCount,\n timestamp: getTimeProvider().now(),\n };\n }\n\n getCircuitSnapshots(): Map<CliName, CircuitBreakerSnapshot> {\n const allSnapshots = this.registry.getAllSnapshots();\n const snapshots = new Map<CliName, CircuitBreakerSnapshot>();\n for (const name of this.adapters.keys()) {\n const snapshot = allSnapshots.get(name);\n if (snapshot !== undefined) {\n snapshots.set(name, snapshot);\n }\n }\n return snapshots;\n }\n\n resetCircuit(cliName: CliName): void {\n this.registry.reset(cliName);\n this.logger.info('Circuit reset', { cliName });\n }\n\n resetAllCircuits(): void {\n this.registry.resetAll();\n this.logger.info('All circuits reset');\n }\n\n addStateChangeListener(listener: CircuitStateChangeListener): void {\n this.registry.addGlobalStateChangeListener(listener);\n }\n\n private async executeWithBreaker(\n adapter: ICliAdapter,\n task: CliTask\n ): Promise<Result<CliResponse, CircuitError | CliError>> {\n const breaker = this.registry.getBreaker(adapter.name);\n const result = await breaker.execute(async () => {\n const execResult = await adapter.execute(task);\n if (!execResult.ok) {\n breaker.recordFailure(mapCliErrorToCategory(execResult.error.code));\n const wrappedError = new Error(execResult.error.message);\n (wrappedError as Error & { cliError: CliError }).cliError = execResult.error;\n throw wrappedError;\n }\n return execResult.value;\n });\n\n if (!result.ok) {\n if (result.error.circuitErrorCode === 'CIRCUIT_OPEN') return err(result.error);\n const wrapped = result.error.cause as (Error & { cliError?: CliError }) | undefined;\n if (wrapped?.cliError) return err(wrapped.cliError);\n return err(result.error);\n }\n return ok(result.value);\n }\n\n private getFallbackClis(excludeCli: CliName, taskCategory?: TaskCategory): CliName[] {\n const chain =\n taskCategory !== undefined\n ? getFallbackChainForCategory(taskCategory, CATEGORY_TO_FALLBACK[taskCategory])\n : this.config.fallbackChain;\n return [...chain].filter(\n (cli) => cli !== excludeCli && !this.registry.isOpen(cli) && this.adapters.has(cli)\n );\n }\n}\n\n/** Creates a CLI circuit breaker integration with the specified adapters. */\nexport function createCliCircuitBreakerIntegration(\n adapters: ReadonlyArray<ICliAdapter>,\n config?: CliCircuitBreakerConfig,\n logger?: ILogger\n): CliCircuitBreakerIntegration {\n return new CliCircuitBreakerIntegration(adapters, config, logger);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
MODEL_IDS,
|
|
4
4
|
getTimeProvider,
|
|
5
5
|
resolveModelIdentitySync
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-27JPMJAD.js";
|
|
7
7
|
|
|
8
8
|
// src/config/model-availability.ts
|
|
9
9
|
var DEFAULT_TTL_MS = 6e4;
|
|
@@ -150,4 +150,4 @@ export {
|
|
|
150
150
|
resetAvailabilityCache,
|
|
151
151
|
filterAvailableModels
|
|
152
152
|
};
|
|
153
|
-
//# sourceMappingURL=chunk-
|
|
153
|
+
//# sourceMappingURL=chunk-TRLXEYFT.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getTimeProvider
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-27JPMJAD.js";
|
|
4
4
|
|
|
5
5
|
// src/security/audit-trail.ts
|
|
6
6
|
var MAX_EVENTS = 1e4;
|
|
@@ -205,4 +205,4 @@ export {
|
|
|
205
205
|
createGraphAuditBridge,
|
|
206
206
|
createAuditTrail
|
|
207
207
|
};
|
|
208
|
-
//# sourceMappingURL=chunk-
|
|
208
|
+
//# sourceMappingURL=chunk-U2YQ2HG4.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computeCostDetail
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-N7LGY3C4.js";
|
|
4
4
|
import {
|
|
5
5
|
DEFAULT_CONSENSUS_CONFIG,
|
|
6
6
|
DEFAULT_INCREMENTAL_QUORUM_CONFIG,
|
|
@@ -18,20 +18,20 @@ import {
|
|
|
18
18
|
toolSuccess,
|
|
19
19
|
withProgressHeartbeat,
|
|
20
20
|
wrapToolWithTimeout
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import {
|
|
23
|
-
getToolMemory
|
|
24
|
-
} from "./chunk-LQHBSYNN.js";
|
|
21
|
+
} from "./chunk-YN7QDYG6.js";
|
|
25
22
|
import {
|
|
26
23
|
createEvent,
|
|
27
24
|
getGlobalRegistry
|
|
28
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-HT7IBYJL.js";
|
|
26
|
+
import {
|
|
27
|
+
getToolMemory
|
|
28
|
+
} from "./chunk-P52ISEJO.js";
|
|
29
29
|
import {
|
|
30
30
|
authRemediation,
|
|
31
31
|
delay,
|
|
32
32
|
getAvailableClis,
|
|
33
33
|
withTimeout
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-B3LK3YIF.js";
|
|
35
35
|
import {
|
|
36
36
|
AgentError,
|
|
37
37
|
CLI_NAMES,
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
registerPersistentOutcomeStoreFactory,
|
|
60
60
|
resolveClassGuardMs,
|
|
61
61
|
resolveVoteTimeout
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-27JPMJAD.js";
|
|
63
63
|
import {
|
|
64
64
|
ensureLearningDir,
|
|
65
65
|
getOutcomesFile
|
|
@@ -5866,7 +5866,7 @@ async function processVotesWithCascade(engineVotes, opts) {
|
|
|
5866
5866
|
var CONTRARIAN_ESCALATION_THRESHOLD = 0.8;
|
|
5867
5867
|
async function runContrarianCheck(proposal, log) {
|
|
5868
5868
|
try {
|
|
5869
|
-
const { executeExpert } = await import("./expert-bridge-
|
|
5869
|
+
const { executeExpert } = await import("./expert-bridge-6SPKMPEG.js");
|
|
5870
5870
|
const prompt = [
|
|
5871
5871
|
"You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.",
|
|
5872
5872
|
"Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.",
|
|
@@ -6382,4 +6382,4 @@ export {
|
|
|
6382
6382
|
CONSENSUS_VOTE_OUTPUT_SCHEMA,
|
|
6383
6383
|
registerConsensusVoteTool
|
|
6384
6384
|
};
|
|
6385
|
-
//# sourceMappingURL=chunk-
|
|
6385
|
+
//# sourceMappingURL=chunk-U3SXRK5O.js.map
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
createLogger,
|
|
16
16
|
err,
|
|
17
17
|
ok
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-27JPMJAD.js";
|
|
19
19
|
|
|
20
20
|
// src/adapters/sdk/types.ts
|
|
21
21
|
var PROVIDER_ENV_KEYS = {
|
|
@@ -396,4 +396,4 @@ export {
|
|
|
396
396
|
CUSTOM_API_DEFAULT_MODEL,
|
|
397
397
|
DEFAULTS
|
|
398
398
|
};
|
|
399
|
-
//# sourceMappingURL=chunk-
|
|
399
|
+
//# sourceMappingURL=chunk-VIHP2LFY.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
createLogger,
|
|
6
6
|
getTimeProvider
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-27JPMJAD.js";
|
|
8
8
|
|
|
9
9
|
// src/mcp/tools/scanner-registry-fetcher.ts
|
|
10
10
|
import { z } from "zod";
|
|
@@ -721,4 +721,4 @@ export {
|
|
|
721
721
|
generateSecurityPlan,
|
|
722
722
|
buildPlanFromAnalysis
|
|
723
723
|
};
|
|
724
|
-
//# sourceMappingURL=chunk-
|
|
724
|
+
//# sourceMappingURL=chunk-XDNDQ7M3.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
emitClawGuardViolation
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-U2YQ2HG4.js";
|
|
4
4
|
import {
|
|
5
5
|
CACHE_TIMEOUTS,
|
|
6
6
|
MCP_TIMEOUTS,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
getTimeProvider,
|
|
17
17
|
ok,
|
|
18
18
|
resolveToolClassGuardMs
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-27JPMJAD.js";
|
|
20
20
|
import {
|
|
21
21
|
getNexusDataDir
|
|
22
22
|
} from "./chunk-DHVMSIT5.js";
|
|
@@ -2023,4 +2023,4 @@ export {
|
|
|
2023
2023
|
VOTING_THRESHOLDS,
|
|
2024
2024
|
ConsensusMetricsSchema
|
|
2025
2025
|
};
|
|
2026
|
-
//# sourceMappingURL=chunk-
|
|
2026
|
+
//# sourceMappingURL=chunk-YN7QDYG6.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliCircuitBreakerIntegration,
|
|
3
|
+
createCliCircuitBreakerIntegration,
|
|
4
|
+
getCliCircuitBreakerSnapshot,
|
|
5
|
+
getDefaultCliCircuitBreakerRegistry
|
|
6
|
+
} from "./chunk-SORESQNO.js";
|
|
7
|
+
import "./chunk-27JPMJAD.js";
|
|
8
|
+
import "./chunk-AXTD4TFK.js";
|
|
9
|
+
import "./chunk-DHVMSIT5.js";
|
|
10
|
+
import "./chunk-ZPWHCABL.js";
|
|
11
|
+
export {
|
|
12
|
+
CliCircuitBreakerIntegration,
|
|
13
|
+
createCliCircuitBreakerIntegration,
|
|
14
|
+
getCliCircuitBreakerSnapshot,
|
|
15
|
+
getDefaultCliCircuitBreakerRegistry
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=cli-circuit-breaker-RDVBTDIT.js.map
|