@darkiceinteractive/mcp-conductor 2.0.0-alpha.1 → 3.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -5
- package/dist/bin/cli.d.ts +20 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +260 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bridge/http-server.d.ts +35 -0
- package/dist/bridge/http-server.d.ts.map +1 -1
- package/dist/bridge/http-server.js +51 -2
- package/dist/bridge/http-server.js.map +1 -1
- package/dist/bridge/index.d.ts +1 -0
- package/dist/bridge/index.d.ts.map +1 -1
- package/dist/bridge/index.js +1 -0
- package/dist/bridge/index.js.map +1 -1
- package/dist/bridge/pool.d.ts +95 -0
- package/dist/bridge/pool.d.ts.map +1 -0
- package/dist/bridge/pool.js +384 -0
- package/dist/bridge/pool.js.map +1 -0
- package/dist/cache/cache.d.ts +64 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +209 -0
- package/dist/cache/cache.js.map +1 -0
- package/dist/cache/delta.d.ts +32 -0
- package/dist/cache/delta.d.ts.map +1 -0
- package/dist/cache/delta.js +131 -0
- package/dist/cache/delta.js.map +1 -0
- package/dist/cache/disk.d.ts +65 -0
- package/dist/cache/disk.d.ts.map +1 -0
- package/dist/cache/disk.js +238 -0
- package/dist/cache/disk.js.map +1 -0
- package/dist/cache/index.d.ts +53 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +12 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/key.d.ts +44 -0
- package/dist/cache/key.d.ts.map +1 -0
- package/dist/cache/key.js +83 -0
- package/dist/cache/key.js.map +1 -0
- package/dist/cache/lru.d.ts +57 -0
- package/dist/cache/lru.d.ts.map +1 -0
- package/dist/cache/lru.js +112 -0
- package/dist/cache/lru.js.map +1 -0
- package/dist/cache/policy.d.ts +34 -0
- package/dist/cache/policy.d.ts.map +1 -0
- package/dist/cache/policy.js +95 -0
- package/dist/cache/policy.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +33 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +135 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/export-servers.d.ts +22 -0
- package/dist/cli/commands/export-servers.d.ts.map +1 -0
- package/dist/cli/commands/export-servers.js +45 -0
- package/dist/cli/commands/export-servers.js.map +1 -0
- package/dist/cli/commands/import-servers.d.ts +57 -0
- package/dist/cli/commands/import-servers.d.ts.map +1 -0
- package/dist/cli/commands/import-servers.js +137 -0
- package/dist/cli/commands/import-servers.js.map +1 -0
- package/dist/cli/commands/routing.d.ts +34 -0
- package/dist/cli/commands/routing.d.ts.map +1 -0
- package/dist/cli/commands/routing.js +60 -0
- package/dist/cli/commands/routing.js.map +1 -0
- package/dist/cli/commands/test-server.d.ts +34 -0
- package/dist/cli/commands/test-server.d.ts.map +1 -0
- package/dist/cli/commands/test-server.js +86 -0
- package/dist/cli/commands/test-server.js.map +1 -0
- package/dist/cli/daemon.d.ts +60 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +244 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/replay.d.ts +16 -0
- package/dist/cli/replay.d.ts.map +1 -0
- package/dist/cli/replay.js +89 -0
- package/dist/cli/replay.js.map +1 -0
- package/dist/cli/wizard/setup.d.ts +12 -0
- package/dist/cli/wizard/setup.d.ts.map +1 -0
- package/dist/cli/wizard/setup.js +71 -0
- package/dist/cli/wizard/setup.js.map +1 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +4 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/schema.d.ts +34 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/daemon/client.d.ts +99 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +292 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/discovery.d.ts +50 -0
- package/dist/daemon/discovery.d.ts.map +1 -0
- package/dist/daemon/discovery.js +104 -0
- package/dist/daemon/discovery.js.map +1 -0
- package/dist/daemon/index.d.ts +16 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +11 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/sandbox-api.d.ts +45 -0
- package/dist/daemon/sandbox-api.d.ts.map +1 -0
- package/dist/daemon/sandbox-api.js +74 -0
- package/dist/daemon/sandbox-api.js.map +1 -0
- package/dist/daemon/server.d.ts +65 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +373 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/shared-kv.d.ts +81 -0
- package/dist/daemon/shared-kv.d.ts.map +1 -0
- package/dist/daemon/shared-kv.js +215 -0
- package/dist/daemon/shared-kv.js.map +1 -0
- package/dist/daemon/shared-lock.d.ts +71 -0
- package/dist/daemon/shared-lock.d.ts.map +1 -0
- package/dist/daemon/shared-lock.js +119 -0
- package/dist/daemon/shared-lock.js.map +1 -0
- package/dist/hub/mcp-hub.d.ts +23 -0
- package/dist/hub/mcp-hub.d.ts.map +1 -1
- package/dist/hub/mcp-hub.js +34 -1
- package/dist/hub/mcp-hub.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/observability/anomaly.d.ts +67 -0
- package/dist/observability/anomaly.d.ts.map +1 -0
- package/dist/observability/anomaly.js +141 -0
- package/dist/observability/anomaly.js.map +1 -0
- package/dist/observability/cost-predictor.d.ts +49 -0
- package/dist/observability/cost-predictor.d.ts.map +1 -0
- package/dist/observability/cost-predictor.js +145 -0
- package/dist/observability/cost-predictor.js.map +1 -0
- package/dist/observability/hot-path.d.ts +49 -0
- package/dist/observability/hot-path.d.ts.map +1 -0
- package/dist/observability/hot-path.js +125 -0
- package/dist/observability/hot-path.js.map +1 -0
- package/dist/observability/index.d.ts +10 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +10 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/replay.d.ts +104 -0
- package/dist/observability/replay.d.ts.map +1 -0
- package/dist/observability/replay.js +239 -0
- package/dist/observability/replay.js.map +1 -0
- package/dist/registry/built-in-recommendations.d.ts +54 -0
- package/dist/registry/built-in-recommendations.d.ts.map +1 -0
- package/dist/registry/built-in-recommendations.js +65 -0
- package/dist/registry/built-in-recommendations.js.map +1 -0
- package/dist/registry/events.d.ts +26 -0
- package/dist/registry/events.d.ts.map +1 -0
- package/dist/registry/events.js +22 -0
- package/dist/registry/events.js.map +1 -0
- package/dist/registry/index.d.ts +159 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +12 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/registry.d.ts +87 -0
- package/dist/registry/registry.d.ts.map +1 -0
- package/dist/registry/registry.js +294 -0
- package/dist/registry/registry.js.map +1 -0
- package/dist/registry/snapshot.d.ts +42 -0
- package/dist/registry/snapshot.d.ts.map +1 -0
- package/dist/registry/snapshot.js +71 -0
- package/dist/registry/snapshot.js.map +1 -0
- package/dist/registry/typegen.d.ts +48 -0
- package/dist/registry/typegen.d.ts.map +1 -0
- package/dist/registry/typegen.js +200 -0
- package/dist/registry/typegen.js.map +1 -0
- package/dist/registry/validator.d.ts +23 -0
- package/dist/registry/validator.d.ts.map +1 -0
- package/dist/registry/validator.js +50 -0
- package/dist/registry/validator.js.map +1 -0
- package/dist/reliability/breaker.d.ts +57 -0
- package/dist/reliability/breaker.d.ts.map +1 -0
- package/dist/reliability/breaker.js +130 -0
- package/dist/reliability/breaker.js.map +1 -0
- package/dist/reliability/errors.d.ts +78 -0
- package/dist/reliability/errors.d.ts.map +1 -0
- package/dist/reliability/errors.js +160 -0
- package/dist/reliability/errors.js.map +1 -0
- package/dist/reliability/gateway.d.ts +88 -0
- package/dist/reliability/gateway.d.ts.map +1 -0
- package/dist/reliability/gateway.js +180 -0
- package/dist/reliability/gateway.js.map +1 -0
- package/dist/reliability/index.d.ts +20 -0
- package/dist/reliability/index.d.ts.map +1 -0
- package/dist/reliability/index.js +16 -0
- package/dist/reliability/index.js.map +1 -0
- package/dist/reliability/profile.d.ts +49 -0
- package/dist/reliability/profile.d.ts.map +1 -0
- package/dist/reliability/profile.js +58 -0
- package/dist/reliability/profile.js.map +1 -0
- package/dist/reliability/retry.d.ts +39 -0
- package/dist/reliability/retry.d.ts.map +1 -0
- package/dist/reliability/retry.js +51 -0
- package/dist/reliability/retry.js.map +1 -0
- package/dist/reliability/timeout.d.ts +34 -0
- package/dist/reliability/timeout.d.ts.map +1 -0
- package/dist/reliability/timeout.js +53 -0
- package/dist/reliability/timeout.js.map +1 -0
- package/dist/runtime/executor.d.ts.map +1 -1
- package/dist/runtime/executor.js +122 -14
- package/dist/runtime/executor.js.map +1 -1
- package/dist/runtime/findtool/embed.d.ts +28 -0
- package/dist/runtime/findtool/embed.d.ts.map +1 -0
- package/dist/runtime/findtool/embed.js +85 -0
- package/dist/runtime/findtool/embed.js.map +1 -0
- package/dist/runtime/findtool/index.d.ts +52 -0
- package/dist/runtime/findtool/index.d.ts.map +1 -0
- package/dist/runtime/findtool/index.js +78 -0
- package/dist/runtime/findtool/index.js.map +1 -0
- package/dist/runtime/findtool/vector-index.d.ts +53 -0
- package/dist/runtime/findtool/vector-index.d.ts.map +1 -0
- package/dist/runtime/findtool/vector-index.js +71 -0
- package/dist/runtime/findtool/vector-index.js.map +1 -0
- package/dist/runtime/helpers/budget.d.ts +27 -0
- package/dist/runtime/helpers/budget.d.ts.map +1 -0
- package/dist/runtime/helpers/budget.js +103 -0
- package/dist/runtime/helpers/budget.js.map +1 -0
- package/dist/runtime/helpers/compact.d.ts +32 -0
- package/dist/runtime/helpers/compact.d.ts.map +1 -0
- package/dist/runtime/helpers/compact.js +93 -0
- package/dist/runtime/helpers/compact.js.map +1 -0
- package/dist/runtime/helpers/delta.d.ts +45 -0
- package/dist/runtime/helpers/delta.d.ts.map +1 -0
- package/dist/runtime/helpers/delta.js +116 -0
- package/dist/runtime/helpers/delta.js.map +1 -0
- package/dist/runtime/helpers/index.d.ts +16 -0
- package/dist/runtime/helpers/index.d.ts.map +1 -0
- package/dist/runtime/helpers/index.js +13 -0
- package/dist/runtime/helpers/index.js.map +1 -0
- package/dist/runtime/helpers/summarize.d.ts +24 -0
- package/dist/runtime/helpers/summarize.d.ts.map +1 -0
- package/dist/runtime/helpers/summarize.js +124 -0
- package/dist/runtime/helpers/summarize.js.map +1 -0
- package/dist/runtime/helpers/worker-preload.d.ts +25 -0
- package/dist/runtime/helpers/worker-preload.d.ts.map +1 -0
- package/dist/runtime/helpers/worker-preload.js +223 -0
- package/dist/runtime/helpers/worker-preload.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/pool/index.d.ts +11 -0
- package/dist/runtime/pool/index.d.ts.map +1 -0
- package/dist/runtime/pool/index.js +8 -0
- package/dist/runtime/pool/index.js.map +1 -0
- package/dist/runtime/pool/recycle.d.ts +44 -0
- package/dist/runtime/pool/recycle.d.ts.map +1 -0
- package/dist/runtime/pool/recycle.js +50 -0
- package/dist/runtime/pool/recycle.js.map +1 -0
- package/dist/runtime/pool/worker-pool.d.ts +77 -0
- package/dist/runtime/pool/worker-pool.d.ts.map +1 -0
- package/dist/runtime/pool/worker-pool.js +216 -0
- package/dist/runtime/pool/worker-pool.js.map +1 -0
- package/dist/runtime/pool/worker.d.ts +80 -0
- package/dist/runtime/pool/worker.d.ts.map +1 -0
- package/dist/runtime/pool/worker.js +324 -0
- package/dist/runtime/pool/worker.js.map +1 -0
- package/dist/server/mcp-server.d.ts +3 -0
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +457 -3
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/server/passthrough-registrar.d.ts +123 -0
- package/dist/server/passthrough-registrar.d.ts.map +1 -0
- package/dist/server/passthrough-registrar.js +199 -0
- package/dist/server/passthrough-registrar.js.map +1 -0
- package/dist/skills/skills-engine.d.ts +9 -1
- package/dist/skills/skills-engine.d.ts.map +1 -1
- package/dist/skills/skills-engine.js +20 -3
- package/dist/skills/skills-engine.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/tokenize.d.ts +55 -0
- package/dist/utils/tokenize.d.ts.map +1 -0
- package/dist/utils/tokenize.js +205 -0
- package/dist/utils/tokenize.js.map +1 -0
- package/dist/version.d.ts +3 -3
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +3 -3
- package/dist/version.js.map +1 -1
- package/package.json +13 -3
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured error classes for the reliability layer.
|
|
3
|
+
*
|
|
4
|
+
* All reliability errors carry `server`, `tool`, and `attempts` so the
|
|
5
|
+
* caller (hub, sandbox) can surface actionable context without string-parsing.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Structured wrapper for any error thrown by a backend MCP tool call.
|
|
9
|
+
*
|
|
10
|
+
* Hub.callTool re-throws every upstream error as MCPToolError so the sandbox
|
|
11
|
+
* can catch by class and inspect structured fields without string-parsing.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* try {
|
|
16
|
+
* const result = await mcp.ibkr.get_portfolio({});
|
|
17
|
+
* } catch (e) {
|
|
18
|
+
* if (e instanceof MCPToolError && e.code === 'contract_not_found') {
|
|
19
|
+
* // handle known error code
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare class MCPToolError extends Error {
|
|
25
|
+
/** Upstream error code string, if available. Falls back to 'UNKNOWN'. */
|
|
26
|
+
readonly code: string;
|
|
27
|
+
/** Backend server name (e.g. 'ibkr', 'github') */
|
|
28
|
+
readonly server: string;
|
|
29
|
+
/** Tool name (e.g. 'get_portfolio') */
|
|
30
|
+
readonly tool: string;
|
|
31
|
+
/** Original error object — preserve full upstream context */
|
|
32
|
+
readonly upstream: unknown;
|
|
33
|
+
readonly name = "MCPToolError";
|
|
34
|
+
constructor(
|
|
35
|
+
/** Upstream error code string, if available. Falls back to 'UNKNOWN'. */
|
|
36
|
+
code: string,
|
|
37
|
+
/** Backend server name (e.g. 'ibkr', 'github') */
|
|
38
|
+
server: string,
|
|
39
|
+
/** Tool name (e.g. 'get_portfolio') */
|
|
40
|
+
tool: string,
|
|
41
|
+
/** Original error object — preserve full upstream context */
|
|
42
|
+
upstream: unknown);
|
|
43
|
+
}
|
|
44
|
+
export declare class TimeoutError extends Error {
|
|
45
|
+
readonly server: string;
|
|
46
|
+
readonly tool: string;
|
|
47
|
+
readonly timeoutMs: number;
|
|
48
|
+
readonly attempts: number;
|
|
49
|
+
readonly name = "TimeoutError";
|
|
50
|
+
constructor(server: string, tool: string, timeoutMs: number, attempts: number);
|
|
51
|
+
}
|
|
52
|
+
export declare class RetryExhaustedError extends Error {
|
|
53
|
+
readonly server: string;
|
|
54
|
+
readonly tool: string;
|
|
55
|
+
readonly attempts: number;
|
|
56
|
+
readonly lastError: unknown;
|
|
57
|
+
readonly name = "RetryExhaustedError";
|
|
58
|
+
constructor(server: string, tool: string, attempts: number, lastError: unknown);
|
|
59
|
+
}
|
|
60
|
+
export declare class CircuitOpenError extends Error {
|
|
61
|
+
readonly server: string;
|
|
62
|
+
readonly tool: string;
|
|
63
|
+
readonly attempts: number;
|
|
64
|
+
readonly name = "CircuitOpenError";
|
|
65
|
+
constructor(server: string, tool: string, attempts?: number);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Extract an error code string from an unknown thrown value.
|
|
69
|
+
* Used by hub.callTool when constructing MCPToolError.
|
|
70
|
+
*/
|
|
71
|
+
export declare function extractErrorCode(err: unknown): string;
|
|
72
|
+
/**
|
|
73
|
+
* Returns true for errors that are safe to retry (transient failures).
|
|
74
|
+
* Mutations always receive retries=0 at the profile level, so this only
|
|
75
|
+
* matters for read operations.
|
|
76
|
+
*/
|
|
77
|
+
export declare function isRetryable(err: unknown): boolean;
|
|
78
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/reliability/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,YAAa,SAAQ,KAAK;IAInC,yEAAyE;aACzD,IAAI,EAAE,MAAM;IAC5B,kDAAkD;aAClC,MAAM,EAAE,MAAM;IAC9B,uCAAuC;aACvB,IAAI,EAAE,MAAM;IAC5B,6DAA6D;aAC7C,QAAQ,EAAE,OAAO;IAVnC,SAAkB,IAAI,kBAAkB;;IAGtC,yEAAyE;IACzD,IAAI,EAAE,MAAM;IAC5B,kDAAkD;IAClC,MAAM,EAAE,MAAM;IAC9B,uCAAuC;IACvB,IAAI,EAAE,MAAM;IAC5B,6DAA6D;IAC7C,QAAQ,EAAE,OAAO;CAMpC;AAMD,qBAAa,YAAa,SAAQ,KAAK;aAInB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;aACZ,SAAS,EAAE,MAAM;aACjB,QAAQ,EAAE,MAAM;IANlC,SAAkB,IAAI,kBAAkB;gBAGtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM;CAKnC;AAMD,qBAAa,mBAAoB,SAAQ,KAAK;aAI1B,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;aACZ,QAAQ,EAAE,MAAM;aAChB,SAAS,EAAE,OAAO;IANpC,SAAkB,IAAI,yBAAyB;gBAG7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,OAAO;CAOrC;AAMD,qBAAa,gBAAiB,SAAQ,KAAK;aAIvB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;aACZ,QAAQ,EAAE,MAAM;IALlC,SAAkB,IAAI,sBAAsB;gBAG1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAU;CAKvC;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAarD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAqBjD"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured error classes for the reliability layer.
|
|
3
|
+
*
|
|
4
|
+
* All reliability errors carry `server`, `tool`, and `attempts` so the
|
|
5
|
+
* caller (hub, sandbox) can surface actionable context without string-parsing.
|
|
6
|
+
*/
|
|
7
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
// MCPToolError — wraps upstream backend errors (amendment from consolidated plan)
|
|
9
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Structured wrapper for any error thrown by a backend MCP tool call.
|
|
12
|
+
*
|
|
13
|
+
* Hub.callTool re-throws every upstream error as MCPToolError so the sandbox
|
|
14
|
+
* can catch by class and inspect structured fields without string-parsing.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* try {
|
|
19
|
+
* const result = await mcp.ibkr.get_portfolio({});
|
|
20
|
+
* } catch (e) {
|
|
21
|
+
* if (e instanceof MCPToolError && e.code === 'contract_not_found') {
|
|
22
|
+
* // handle known error code
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export class MCPToolError extends Error {
|
|
28
|
+
code;
|
|
29
|
+
server;
|
|
30
|
+
tool;
|
|
31
|
+
upstream;
|
|
32
|
+
name = 'MCPToolError';
|
|
33
|
+
constructor(
|
|
34
|
+
/** Upstream error code string, if available. Falls back to 'UNKNOWN'. */
|
|
35
|
+
code,
|
|
36
|
+
/** Backend server name (e.g. 'ibkr', 'github') */
|
|
37
|
+
server,
|
|
38
|
+
/** Tool name (e.g. 'get_portfolio') */
|
|
39
|
+
tool,
|
|
40
|
+
/** Original error object — preserve full upstream context */
|
|
41
|
+
upstream) {
|
|
42
|
+
super(`[${server}.${tool}] ${code}`);
|
|
43
|
+
this.code = code;
|
|
44
|
+
this.server = server;
|
|
45
|
+
this.tool = tool;
|
|
46
|
+
this.upstream = upstream;
|
|
47
|
+
// Maintain proper prototype chain for instanceof checks across module boundaries
|
|
48
|
+
Object.setPrototypeOf(this, MCPToolError.prototype);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
52
|
+
// TimeoutError
|
|
53
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
54
|
+
export class TimeoutError extends Error {
|
|
55
|
+
server;
|
|
56
|
+
tool;
|
|
57
|
+
timeoutMs;
|
|
58
|
+
attempts;
|
|
59
|
+
name = 'TimeoutError';
|
|
60
|
+
constructor(server, tool, timeoutMs, attempts) {
|
|
61
|
+
super(`[${server}.${tool}] timed out after ${timeoutMs}ms (attempt ${attempts})`);
|
|
62
|
+
this.server = server;
|
|
63
|
+
this.tool = tool;
|
|
64
|
+
this.timeoutMs = timeoutMs;
|
|
65
|
+
this.attempts = attempts;
|
|
66
|
+
Object.setPrototypeOf(this, TimeoutError.prototype);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
70
|
+
// RetryExhaustedError
|
|
71
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
72
|
+
export class RetryExhaustedError extends Error {
|
|
73
|
+
server;
|
|
74
|
+
tool;
|
|
75
|
+
attempts;
|
|
76
|
+
lastError;
|
|
77
|
+
name = 'RetryExhaustedError';
|
|
78
|
+
constructor(server, tool, attempts, lastError) {
|
|
79
|
+
const cause = lastError instanceof Error ? lastError.message : String(lastError);
|
|
80
|
+
super(`[${server}.${tool}] exhausted ${attempts} attempt(s): ${cause}`);
|
|
81
|
+
this.server = server;
|
|
82
|
+
this.tool = tool;
|
|
83
|
+
this.attempts = attempts;
|
|
84
|
+
this.lastError = lastError;
|
|
85
|
+
Object.setPrototypeOf(this, RetryExhaustedError.prototype);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
89
|
+
// CircuitOpenError
|
|
90
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
91
|
+
export class CircuitOpenError extends Error {
|
|
92
|
+
server;
|
|
93
|
+
tool;
|
|
94
|
+
attempts;
|
|
95
|
+
name = 'CircuitOpenError';
|
|
96
|
+
constructor(server, tool, attempts = 0) {
|
|
97
|
+
super(`[${server}.${tool}] circuit open — failing fast`);
|
|
98
|
+
this.server = server;
|
|
99
|
+
this.tool = tool;
|
|
100
|
+
this.attempts = attempts;
|
|
101
|
+
Object.setPrototypeOf(this, CircuitOpenError.prototype);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
105
|
+
// Helpers
|
|
106
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
107
|
+
/**
|
|
108
|
+
* Extract an error code string from an unknown thrown value.
|
|
109
|
+
* Used by hub.callTool when constructing MCPToolError.
|
|
110
|
+
*/
|
|
111
|
+
export function extractErrorCode(err) {
|
|
112
|
+
if (err instanceof MCPToolError)
|
|
113
|
+
return err.code;
|
|
114
|
+
if (err instanceof TimeoutError)
|
|
115
|
+
return 'TIMEOUT';
|
|
116
|
+
if (err instanceof CircuitOpenError)
|
|
117
|
+
return 'CIRCUIT_OPEN';
|
|
118
|
+
if (err instanceof RetryExhaustedError)
|
|
119
|
+
return 'RETRY_EXHAUSTED';
|
|
120
|
+
if (err && typeof err === 'object') {
|
|
121
|
+
// MCP SDK errors often carry a `code` field
|
|
122
|
+
const obj = err;
|
|
123
|
+
if (typeof obj['code'] === 'string')
|
|
124
|
+
return obj['code'];
|
|
125
|
+
if (typeof obj['code'] === 'number')
|
|
126
|
+
return String(obj['code']);
|
|
127
|
+
}
|
|
128
|
+
if (err instanceof Error)
|
|
129
|
+
return err.message || 'ERROR';
|
|
130
|
+
return 'UNKNOWN';
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Returns true for errors that are safe to retry (transient failures).
|
|
134
|
+
* Mutations always receive retries=0 at the profile level, so this only
|
|
135
|
+
* matters for read operations.
|
|
136
|
+
*/
|
|
137
|
+
export function isRetryable(err) {
|
|
138
|
+
// Never retry if the circuit is already open — it's a fast-fail, not a transient error
|
|
139
|
+
if (err instanceof CircuitOpenError)
|
|
140
|
+
return false;
|
|
141
|
+
// Never double-wrap MCPToolErrors — let them propagate
|
|
142
|
+
if (err instanceof MCPToolError)
|
|
143
|
+
return false;
|
|
144
|
+
// Timeouts are retryable
|
|
145
|
+
if (err instanceof TimeoutError)
|
|
146
|
+
return true;
|
|
147
|
+
// Generic network-level errors are retryable
|
|
148
|
+
if (err instanceof Error) {
|
|
149
|
+
const msg = err.message.toLowerCase();
|
|
150
|
+
return (msg.includes('network') ||
|
|
151
|
+
msg.includes('econnreset') ||
|
|
152
|
+
msg.includes('enotfound') ||
|
|
153
|
+
msg.includes('etimedout') ||
|
|
154
|
+
msg.includes('socket') ||
|
|
155
|
+
msg.includes('timeout') ||
|
|
156
|
+
msg.includes('econnrefused'));
|
|
157
|
+
}
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/reliability/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReliabilityGateway — composes timeout, retry, and circuit breaker into a
|
|
3
|
+
* single call pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Wiring order (cache sits in front of this layer per Agent B):
|
|
6
|
+
* cache miss → ReliabilityGateway.call() → backend fn
|
|
7
|
+
*
|
|
8
|
+
* Profile resolution order:
|
|
9
|
+
* tool-level ToolDefinition.reliability → server-level config → global default
|
|
10
|
+
*/
|
|
11
|
+
import { CircuitOpenError, MCPToolError, RetryExhaustedError, TimeoutError, extractErrorCode } from './errors.js';
|
|
12
|
+
import { type CircuitState, type ReliabilityProfile } from './profile.js';
|
|
13
|
+
export interface ServerStats {
|
|
14
|
+
totalCalls: number;
|
|
15
|
+
successes: number;
|
|
16
|
+
failures: number;
|
|
17
|
+
timeouts: number;
|
|
18
|
+
retries: number;
|
|
19
|
+
circuitState: CircuitState;
|
|
20
|
+
lastTrip?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface ReliabilityStats {
|
|
23
|
+
byServer: Record<string, ServerStats>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Minimal tool-lookup interface so ReliabilityGateway can resolve per-tool
|
|
27
|
+
* profiles without importing the full ToolRegistry (avoids circular deps).
|
|
28
|
+
*/
|
|
29
|
+
export interface ToolLookup {
|
|
30
|
+
getToolReliability(server: string, tool: string): ReliabilityProfile | undefined;
|
|
31
|
+
}
|
|
32
|
+
export interface GatewayOptions {
|
|
33
|
+
/** Optional per-tool profile resolver (typically the ToolRegistry) */
|
|
34
|
+
toolLookup?: ToolLookup;
|
|
35
|
+
/** Global default profile override */
|
|
36
|
+
defaultProfile?: ReliabilityProfile;
|
|
37
|
+
/**
|
|
38
|
+
* Per-server profile overrides, keyed by server name.
|
|
39
|
+
* Corresponds to the `reliability.perServer` block in conductor config.
|
|
40
|
+
*/
|
|
41
|
+
serverProfiles?: Record<string, ReliabilityProfile>;
|
|
42
|
+
/**
|
|
43
|
+
* Per-tool profile overrides, keyed by "server.tool".
|
|
44
|
+
* Corresponds to the `reliability.perTool` block in conductor config.
|
|
45
|
+
*/
|
|
46
|
+
toolProfiles?: Record<string, ReliabilityProfile>;
|
|
47
|
+
}
|
|
48
|
+
export declare class ReliabilityGateway {
|
|
49
|
+
private readonly breakers;
|
|
50
|
+
private readonly stats;
|
|
51
|
+
private readonly options;
|
|
52
|
+
constructor(options?: GatewayOptions);
|
|
53
|
+
/**
|
|
54
|
+
* Execute `fn` with full reliability protection: timeout → retry → circuit breaker.
|
|
55
|
+
*
|
|
56
|
+
* Returns the resolved value of `fn` or throws one of:
|
|
57
|
+
* - CircuitOpenError (circuit OPEN, fast-fail)
|
|
58
|
+
* - TimeoutError (single attempt timed out, retries=0)
|
|
59
|
+
* - RetryExhaustedError (all attempts failed)
|
|
60
|
+
* - MCPToolError (non-retryable upstream error wrapped by hub)
|
|
61
|
+
* - original error (non-retryable, non-MCPToolError)
|
|
62
|
+
*/
|
|
63
|
+
call<T>(server: string, tool: string, fn: () => Promise<T>): Promise<T>;
|
|
64
|
+
/** Current circuit state for a server. Returns 'closed' if never seen. */
|
|
65
|
+
getCircuitState(server: string): CircuitState;
|
|
66
|
+
/** Aggregate stats snapshot across all servers seen so far. */
|
|
67
|
+
getStats(): ReliabilityStats;
|
|
68
|
+
/** Reset circuit breaker for a specific server back to CLOSED. */
|
|
69
|
+
resetCircuit(server: string): void;
|
|
70
|
+
private _breaker;
|
|
71
|
+
private _accumulator;
|
|
72
|
+
/**
|
|
73
|
+
* Resolve the effective profile for a specific server+tool combination.
|
|
74
|
+
*
|
|
75
|
+
* Priority (highest → lowest):
|
|
76
|
+
* 1. toolProfiles["server.tool"]
|
|
77
|
+
* 2. toolLookup.getToolReliability(server, tool) [ToolDefinition.reliability]
|
|
78
|
+
* 3. serverProfiles[server]
|
|
79
|
+
* 4. defaultProfile (global)
|
|
80
|
+
* 5. DEFAULT_PROFILE (hardcoded fallback)
|
|
81
|
+
*
|
|
82
|
+
* After resolution, mutation default is applied (retries forced to 0 if
|
|
83
|
+
* no explicit retries were set for a mutation-named tool).
|
|
84
|
+
*/
|
|
85
|
+
private _resolveProfile;
|
|
86
|
+
}
|
|
87
|
+
export { CircuitOpenError, MCPToolError, RetryExhaustedError, TimeoutError, extractErrorCode };
|
|
88
|
+
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/reliability/gateway.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACxB,MAAM,cAAc,CAAC;AAQtB,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACvC;AAMD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAAC;CAClF;AAED,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,sCAAsC;IACtC,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACpC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACpD;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CACnD;AAsBD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAEtB;gBAEU,OAAO,GAAE,cAAmB;IAWxC;;;;;;;;;OASG;IACG,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAoE7E,0EAA0E;IAC1E,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY;IAI7C,+DAA+D;IAC/D,QAAQ,IAAI,gBAAgB;IAoB5B,kEAAkE;IAClE,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAMlC,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,YAAY;IAOpB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,eAAe;CA6BxB;AAGD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReliabilityGateway — composes timeout, retry, and circuit breaker into a
|
|
3
|
+
* single call pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Wiring order (cache sits in front of this layer per Agent B):
|
|
6
|
+
* cache miss → ReliabilityGateway.call() → backend fn
|
|
7
|
+
*
|
|
8
|
+
* Profile resolution order:
|
|
9
|
+
* tool-level ToolDefinition.reliability → server-level config → global default
|
|
10
|
+
*/
|
|
11
|
+
import { CircuitBreaker } from './breaker.js';
|
|
12
|
+
import { CircuitOpenError, MCPToolError, RetryExhaustedError, TimeoutError, extractErrorCode, } from './errors.js';
|
|
13
|
+
import { DEFAULT_PROFILE, applyMutationDefault, resolveProfile, } from './profile.js';
|
|
14
|
+
import { withRetry } from './retry.js';
|
|
15
|
+
import { withTimeoutSimple } from './timeout.js';
|
|
16
|
+
function emptyMutableStats() {
|
|
17
|
+
return { totalCalls: 0, successes: 0, failures: 0, timeouts: 0, retries: 0 };
|
|
18
|
+
}
|
|
19
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
// ReliabilityGateway
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
export class ReliabilityGateway {
|
|
23
|
+
breakers = new Map();
|
|
24
|
+
stats = new Map();
|
|
25
|
+
options;
|
|
26
|
+
constructor(options = {}) {
|
|
27
|
+
this.options = {
|
|
28
|
+
toolLookup: options.toolLookup,
|
|
29
|
+
defaultProfile: options.defaultProfile ?? DEFAULT_PROFILE,
|
|
30
|
+
serverProfiles: options.serverProfiles ?? {},
|
|
31
|
+
toolProfiles: options.toolProfiles ?? {},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// ─── Public API ────────────────────────────────────────────────────────────
|
|
35
|
+
/**
|
|
36
|
+
* Execute `fn` with full reliability protection: timeout → retry → circuit breaker.
|
|
37
|
+
*
|
|
38
|
+
* Returns the resolved value of `fn` or throws one of:
|
|
39
|
+
* - CircuitOpenError (circuit OPEN, fast-fail)
|
|
40
|
+
* - TimeoutError (single attempt timed out, retries=0)
|
|
41
|
+
* - RetryExhaustedError (all attempts failed)
|
|
42
|
+
* - MCPToolError (non-retryable upstream error wrapped by hub)
|
|
43
|
+
* - original error (non-retryable, non-MCPToolError)
|
|
44
|
+
*/
|
|
45
|
+
async call(server, tool, fn) {
|
|
46
|
+
const profile = this._resolveProfile(server, tool);
|
|
47
|
+
const breaker = this._breaker(server, profile);
|
|
48
|
+
const acc = this._accumulator(server);
|
|
49
|
+
acc.totalCalls++;
|
|
50
|
+
// Fast-fail if circuit is open
|
|
51
|
+
breaker.allowCall(tool);
|
|
52
|
+
let attemptCount = 0;
|
|
53
|
+
const wrappedFn = async () => {
|
|
54
|
+
attemptCount++;
|
|
55
|
+
const attempt = attemptCount;
|
|
56
|
+
// Count retries (all attempts after the first)
|
|
57
|
+
if (attempt > 1) {
|
|
58
|
+
acc.retries++;
|
|
59
|
+
}
|
|
60
|
+
return withTimeoutSimple(fn, {
|
|
61
|
+
timeoutMs: profile.timeoutMs,
|
|
62
|
+
server,
|
|
63
|
+
tool,
|
|
64
|
+
attempt,
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
try {
|
|
68
|
+
const result = await withRetry(wrappedFn, {
|
|
69
|
+
retries: profile.retries,
|
|
70
|
+
retryDelayMs: profile.retryDelayMs,
|
|
71
|
+
retryMaxDelayMs: profile.retryMaxDelayMs,
|
|
72
|
+
server,
|
|
73
|
+
tool,
|
|
74
|
+
});
|
|
75
|
+
breaker.recordSuccess();
|
|
76
|
+
acc.successes++;
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
breaker.recordFailure();
|
|
81
|
+
acc.failures++;
|
|
82
|
+
// Count timeouts: either a direct TimeoutError or a RetryExhaustedError
|
|
83
|
+
// whose last underlying cause was a TimeoutError.
|
|
84
|
+
if (err instanceof TimeoutError) {
|
|
85
|
+
acc.timeouts++;
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
if (err instanceof RetryExhaustedError) {
|
|
89
|
+
if (err.lastError instanceof TimeoutError) {
|
|
90
|
+
acc.timeouts++;
|
|
91
|
+
}
|
|
92
|
+
// When there was only one attempt (retries=0), surface the underlying
|
|
93
|
+
// error directly so the sandbox sees the specific error type (TimeoutError,
|
|
94
|
+
// etc.) rather than the wrapping RetryExhaustedError.
|
|
95
|
+
if (err.attempts === 1 && err.lastError instanceof Error) {
|
|
96
|
+
throw err.lastError;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Current circuit state for a server. Returns 'closed' if never seen. */
|
|
103
|
+
getCircuitState(server) {
|
|
104
|
+
return this.breakers.get(server)?.getState() ?? 'closed';
|
|
105
|
+
}
|
|
106
|
+
/** Aggregate stats snapshot across all servers seen so far. */
|
|
107
|
+
getStats() {
|
|
108
|
+
const byServer = {};
|
|
109
|
+
for (const [server, acc] of this.stats) {
|
|
110
|
+
const breaker = this.breakers.get(server);
|
|
111
|
+
const breakerStats = breaker?.getStats();
|
|
112
|
+
byServer[server] = {
|
|
113
|
+
totalCalls: acc.totalCalls,
|
|
114
|
+
successes: acc.successes,
|
|
115
|
+
failures: acc.failures,
|
|
116
|
+
timeouts: acc.timeouts,
|
|
117
|
+
retries: acc.retries,
|
|
118
|
+
circuitState: breakerStats?.state ?? 'closed',
|
|
119
|
+
lastTrip: breakerStats?.lastTrip,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return { byServer };
|
|
123
|
+
}
|
|
124
|
+
/** Reset circuit breaker for a specific server back to CLOSED. */
|
|
125
|
+
resetCircuit(server) {
|
|
126
|
+
this.breakers.get(server)?.reset();
|
|
127
|
+
}
|
|
128
|
+
// ─── Private helpers ───────────────────────────────────────────────────────
|
|
129
|
+
_breaker(server, profile) {
|
|
130
|
+
if (!this.breakers.has(server)) {
|
|
131
|
+
this.breakers.set(server, new CircuitBreaker(server, profile));
|
|
132
|
+
}
|
|
133
|
+
return this.breakers.get(server);
|
|
134
|
+
}
|
|
135
|
+
_accumulator(server) {
|
|
136
|
+
if (!this.stats.has(server)) {
|
|
137
|
+
this.stats.set(server, emptyMutableStats());
|
|
138
|
+
}
|
|
139
|
+
return this.stats.get(server);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Resolve the effective profile for a specific server+tool combination.
|
|
143
|
+
*
|
|
144
|
+
* Priority (highest → lowest):
|
|
145
|
+
* 1. toolProfiles["server.tool"]
|
|
146
|
+
* 2. toolLookup.getToolReliability(server, tool) [ToolDefinition.reliability]
|
|
147
|
+
* 3. serverProfiles[server]
|
|
148
|
+
* 4. defaultProfile (global)
|
|
149
|
+
* 5. DEFAULT_PROFILE (hardcoded fallback)
|
|
150
|
+
*
|
|
151
|
+
* After resolution, mutation default is applied (retries forced to 0 if
|
|
152
|
+
* no explicit retries were set for a mutation-named tool).
|
|
153
|
+
*/
|
|
154
|
+
_resolveProfile(server, tool) {
|
|
155
|
+
const globalBase = resolveProfile(this.options.defaultProfile);
|
|
156
|
+
// Layer 3: server-level override
|
|
157
|
+
const serverOverride = this.options.serverProfiles[server];
|
|
158
|
+
const afterServer = serverOverride ? resolveProfile(serverOverride, globalBase) : globalBase;
|
|
159
|
+
// Layer 2: tool-level from ToolDefinition (via registry lookup)
|
|
160
|
+
const registryOverride = this.options.toolLookup?.getToolReliability(server, tool);
|
|
161
|
+
const afterRegistry = registryOverride
|
|
162
|
+
? resolveProfile(registryOverride, afterServer)
|
|
163
|
+
: afterServer;
|
|
164
|
+
// Layer 1: explicit tool profile key "server.tool"
|
|
165
|
+
const toolKey = `${server}.${tool}`;
|
|
166
|
+
const toolOverride = this.options.toolProfiles[toolKey];
|
|
167
|
+
const explicit = toolOverride ? resolveProfile(toolOverride, afterRegistry) : afterRegistry;
|
|
168
|
+
// Determine whether retries were explicitly set at a tool/server-specific
|
|
169
|
+
// override level. The global defaultProfile does NOT count as an explicit
|
|
170
|
+
// override — if only the global default has retries set, mutations still
|
|
171
|
+
// get retries forced to 0 by applyMutationDefault.
|
|
172
|
+
const explicitRetries = toolOverride?.retries !== undefined ||
|
|
173
|
+
registryOverride?.retries !== undefined ||
|
|
174
|
+
serverOverride?.retries !== undefined;
|
|
175
|
+
return applyMutationDefault(tool, explicit, explicitRetries);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Re-export error types at gateway level for convenience
|
|
179
|
+
export { CircuitOpenError, MCPToolError, RetryExhaustedError, TimeoutError, extractErrorCode };
|
|
180
|
+
//# sourceMappingURL=gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../src/reliability/gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/reliability — public API
|
|
3
|
+
*
|
|
4
|
+
* Everything a consumer needs is re-exported here. Internal modules should be
|
|
5
|
+
* imported directly only within the reliability package.
|
|
6
|
+
*
|
|
7
|
+
* @module reliability
|
|
8
|
+
*/
|
|
9
|
+
export type { ReliabilityProfile, CircuitState } from './profile.js';
|
|
10
|
+
export { DEFAULT_PROFILE, resolveProfile, isMutation, applyMutationDefault } from './profile.js';
|
|
11
|
+
export { MCPToolError, TimeoutError, RetryExhaustedError, CircuitOpenError, extractErrorCode, isRetryable, } from './errors.js';
|
|
12
|
+
export type { BreakerStats } from './breaker.js';
|
|
13
|
+
export { CircuitBreaker } from './breaker.js';
|
|
14
|
+
export type { RetryOptions } from './retry.js';
|
|
15
|
+
export { withRetry } from './retry.js';
|
|
16
|
+
export type { TimeoutOptions } from './timeout.js';
|
|
17
|
+
export { withTimeout, withTimeoutSimple } from './timeout.js';
|
|
18
|
+
export type { GatewayOptions, ReliabilityStats, ServerStats, ToolLookup, } from './gateway.js';
|
|
19
|
+
export { ReliabilityGateway } from './gateway.js';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reliability/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGjG,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,GACZ,MAAM,aAAa,CAAC;AAGrB,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAG9D,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,UAAU,GACX,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/reliability — public API
|
|
3
|
+
*
|
|
4
|
+
* Everything a consumer needs is re-exported here. Internal modules should be
|
|
5
|
+
* imported directly only within the reliability package.
|
|
6
|
+
*
|
|
7
|
+
* @module reliability
|
|
8
|
+
*/
|
|
9
|
+
export { DEFAULT_PROFILE, resolveProfile, isMutation, applyMutationDefault } from './profile.js';
|
|
10
|
+
// Structured error classes
|
|
11
|
+
export { MCPToolError, TimeoutError, RetryExhaustedError, CircuitOpenError, extractErrorCode, isRetryable, } from './errors.js';
|
|
12
|
+
export { CircuitBreaker } from './breaker.js';
|
|
13
|
+
export { withRetry } from './retry.js';
|
|
14
|
+
export { withTimeout, withTimeoutSimple } from './timeout.js';
|
|
15
|
+
export { ReliabilityGateway } from './gateway.js';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reliability/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEjG,2BAA2B;AAC3B,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,GACZ,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAI9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvC,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAS9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReliabilityProfile — per-tool/per-server/global reliability configuration.
|
|
3
|
+
*
|
|
4
|
+
* Resolution order:
|
|
5
|
+
* tool-level ToolDefinition.reliability → server-level config → global default
|
|
6
|
+
*/
|
|
7
|
+
export interface ReliabilityProfile {
|
|
8
|
+
/** Call timeout in ms. Default: 10000 */
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Number of retry attempts after the initial failure.
|
|
12
|
+
* Default: 2 for reads, 0 for mutations.
|
|
13
|
+
*/
|
|
14
|
+
retries?: number;
|
|
15
|
+
/** Initial retry delay in ms; doubles on each attempt. Default: 100 */
|
|
16
|
+
retryDelayMs?: number;
|
|
17
|
+
/** Maximum retry delay ceiling in ms. Default: 5000 */
|
|
18
|
+
retryMaxDelayMs?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Failure ratio (0–1) that trips the circuit OPEN when exceeded.
|
|
21
|
+
* Default: 0.5
|
|
22
|
+
*/
|
|
23
|
+
circuitBreakerThreshold?: number;
|
|
24
|
+
/** Rolling window for failure ratio tracking in ms. Default: 60000 */
|
|
25
|
+
circuitBreakerWindowMs?: number;
|
|
26
|
+
/** Minimum calls in the window before the circuit can trip. Default: 10 */
|
|
27
|
+
circuitBreakerMinCalls?: number;
|
|
28
|
+
/** How long to wait in OPEN state before allowing a probe. Default: 30000 */
|
|
29
|
+
halfOpenProbeIntervalMs?: number;
|
|
30
|
+
}
|
|
31
|
+
export type CircuitState = 'closed' | 'open' | 'half-open';
|
|
32
|
+
/** Global defaults applied when no profile field is provided. */
|
|
33
|
+
export declare const DEFAULT_PROFILE: Required<ReliabilityProfile>;
|
|
34
|
+
/**
|
|
35
|
+
* Merge profile overrides onto the global default, producing a fully-resolved
|
|
36
|
+
* profile with every field set.
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveProfile(override?: ReliabilityProfile, base?: Required<ReliabilityProfile>): Required<ReliabilityProfile>;
|
|
39
|
+
/** Returns true if the tool name matches a mutation pattern. */
|
|
40
|
+
export declare function isMutation(toolName: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Apply mutation override: if the tool is a mutation AND the resolved profile
|
|
43
|
+
* did not explicitly set `retries`, force retries to 0.
|
|
44
|
+
*
|
|
45
|
+
* We detect "explicitly set" by checking whether the override provided the
|
|
46
|
+
* `retries` field directly (i.e., override?.retries is a number).
|
|
47
|
+
*/
|
|
48
|
+
export declare function applyMutationDefault(toolName: string, profile: Required<ReliabilityProfile>, explicitRetries: boolean): Required<ReliabilityProfile>;
|
|
49
|
+
//# sourceMappingURL=profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/reliability/profile.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,kBAAkB;IACjC,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,sEAAsE;IACtE,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,2EAA2E;IAC3E,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,6EAA6E;IAC7E,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3D,iEAAiE;AACjE,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,kBAAkB,CASxD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,CAAC,EAAE,kBAAkB,EAC7B,IAAI,GAAE,QAAQ,CAAC,kBAAkB,CAAmB,GACnD,QAAQ,CAAC,kBAAkB,CAAC,CAY9B;AAQD,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EACrC,eAAe,EAAE,OAAO,GACvB,QAAQ,CAAC,kBAAkB,CAAC,CAK9B"}
|