@crabeye-ai/crabeye-mcp-bridge 0.5.0 → 1.0.0
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 +17 -4
- package/dist/index.js +53 -15
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ Then rename `mcpServers` to `upstreamMcpServers`, add the bridge, and replace ha
|
|
|
81
81
|
|
|
82
82
|
That's it. Your AI assistant now has access to all tools from all configured servers through a single connection. The bridge automatically excludes itself from `mcpServers` to avoid recursion, so pointing `--config` at the same file is safe.
|
|
83
83
|
|
|
84
|
-
The bridge also reads `servers` (VS Code Copilot) and `context_servers` (Zed) as input keys. On duplicate names, earlier sources win: `upstreamMcpServers` > `servers` > `context_servers` > `mcpServers`. Self-exclusion applies to `mcpServers` and `context_servers`.
|
|
84
|
+
The bridge also reads `upstreamServers` (shorthand), `servers` (VS Code Copilot), and `context_servers` (Zed) as input keys. On duplicate names, earlier sources win: `upstreamMcpServers` > `upstreamServers` > `servers` > `context_servers` > `mcpServers`. Self-exclusion applies to `mcpServers` and `context_servers`.
|
|
85
85
|
|
|
86
86
|
Alternatively, you can add the bridge alongside your existing `mcpServers` entries without renaming anything:
|
|
87
87
|
|
|
@@ -124,7 +124,7 @@ The AI assistant calls `search_tools` automatically when it detects a relevant i
|
|
|
124
124
|
|
|
125
125
|
When `search_tools` is called, the assistant receives the matching tools and their input schemas. The bridge also directly exposes the searched tools to the assistant so they can be called natively. Some assistants don't refresh their tool list mid-session, so they may not see the newly exposed tools — but they can still call them through `run_tool` and the call is executed exactly as if made directly on the original tool.
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
The bridge tracks how many tokens it saves compared to exposing all upstream tool definitions directly. Token savings are always logged to stderr after each search. To also include them in `search_tools` responses, pass `--stats`:
|
|
128
128
|
|
|
129
129
|
```json
|
|
130
130
|
{
|
|
@@ -141,7 +141,7 @@ Every `search_tools` response includes a `session_stats` object showing how many
|
|
|
141
141
|
- **`bridge_tokens`** — cumulative tokens used by the bridge's two meta-tools plus all search results returned so far
|
|
142
142
|
- **`tokens_saved`** — the difference (baseline − bridge)
|
|
143
143
|
|
|
144
|
-
Token counts are estimated using a chars/4 heuristic.
|
|
144
|
+
Token counts are estimated using a chars/4 heuristic.
|
|
145
145
|
|
|
146
146
|
## Examples
|
|
147
147
|
|
|
@@ -495,6 +495,18 @@ In this example, the bridge allows at most 30 tool calls to the `github` server
|
|
|
495
495
|
|
|
496
496
|
Rate limit configuration is hot-reloadable — changes take effect without restarting the bridge.
|
|
497
497
|
|
|
498
|
+
### Discovery mode
|
|
499
|
+
|
|
500
|
+
Control how searched tools are surfaced to the assistant with `--discovery-mode`:
|
|
501
|
+
|
|
502
|
+
- **`both`** (default) — Search results include tool names, descriptions, and full input schemas. Matching tools are also added to the MCP tools list so the assistant can call them directly.
|
|
503
|
+
- **`search`** — Search results include full tool details, but tools are NOT added to the MCP tools list. The assistant must use `run_tool` to execute them. Use this when your client doesn't handle dynamic tool list changes well.
|
|
504
|
+
- **`tools_list`** — Matching tools are added to the MCP tools list with full schemas, but search results omit `input_schema` to avoid duplication. The assistant calls discovered tools directly by their namespaced name, or via `run_tool`.
|
|
505
|
+
|
|
506
|
+
```bash
|
|
507
|
+
npx @crabeye-ai/crabeye-mcp-bridge --config config.json --discovery-mode search
|
|
508
|
+
```
|
|
509
|
+
|
|
498
510
|
## CLI
|
|
499
511
|
|
|
500
512
|
```
|
|
@@ -505,7 +517,8 @@ npx @crabeye-ai/crabeye-mcp-bridge --config <path>
|
|
|
505
517
|
|-------------------|-------------|
|
|
506
518
|
| `-c, --config <path>` | Path to config file (required, or set `MCP_BRIDGE_CONFIG`) |
|
|
507
519
|
| `--validate` | Validate config and list upstream servers, then exit |
|
|
508
|
-
| `--
|
|
520
|
+
| `--stats` | Include `session_stats` in `search_tools` responses (always logged to stderr) |
|
|
521
|
+
| `--discovery-mode <mode>` | How searched tools are surfaced: `search`, `tools_list`, or `both` (default) |
|
|
509
522
|
| `-V, --version` | Print version |
|
|
510
523
|
| `-h, --help` | Print help |
|
|
511
524
|
| `credential set <key> [value]` | Store a credential (plain string, `--json` for typed, or pipe stdin) |
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { Command } from "commander";
|
|
2
|
+
import { Command, Option } from "commander";
|
|
3
3
|
|
|
4
4
|
// src/config/schema.ts
|
|
5
5
|
import { z } from "zod";
|
|
@@ -61,6 +61,7 @@ var GlobalBridgeConfigSchema = z.object({
|
|
|
61
61
|
var BridgeConfigSchema = z.object({
|
|
62
62
|
mcpServers: z.record(z.string(), ServerConfigSchema).default({}),
|
|
63
63
|
upstreamMcpServers: z.record(z.string(), ServerConfigSchema).optional(),
|
|
64
|
+
upstreamServers: z.record(z.string(), ServerConfigSchema).optional(),
|
|
64
65
|
servers: z.record(z.string(), ServerConfigSchema).optional(),
|
|
65
66
|
context_servers: z.record(z.string(), ServerConfigSchema).optional(),
|
|
66
67
|
_bridge: GlobalBridgeConfigSchema.default(
|
|
@@ -92,6 +93,9 @@ function resolveUpstreams(config) {
|
|
|
92
93
|
if (config.servers) {
|
|
93
94
|
Object.assign(result, config.servers);
|
|
94
95
|
}
|
|
96
|
+
if (config.upstreamServers) {
|
|
97
|
+
Object.assign(result, config.upstreamServers);
|
|
98
|
+
}
|
|
95
99
|
if (config.upstreamMcpServers) {
|
|
96
100
|
Object.assign(result, config.upstreamMcpServers);
|
|
97
101
|
}
|
|
@@ -692,9 +696,11 @@ var ToolSearchService = class {
|
|
|
692
696
|
listeners = /* @__PURE__ */ new Set();
|
|
693
697
|
unsubscribeRegistry;
|
|
694
698
|
policyEngine;
|
|
695
|
-
|
|
699
|
+
discoveryMode;
|
|
700
|
+
constructor(registry, policyEngine, discoveryMode = "both") {
|
|
696
701
|
this.registry = registry;
|
|
697
702
|
this.policyEngine = policyEngine;
|
|
703
|
+
this.discoveryMode = discoveryMode;
|
|
698
704
|
this.index = this.createIndex();
|
|
699
705
|
this.rebuildIndex();
|
|
700
706
|
this.unsubscribeRegistry = this.registry.onChanged(() => {
|
|
@@ -940,12 +946,25 @@ var ToolSearchService = class {
|
|
|
940
946
|
}
|
|
941
947
|
}
|
|
942
948
|
}
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
+
if (this.discoveryMode !== "search") {
|
|
950
|
+
const cappedEnabled = allEnabled.slice(0, MAX_LIMIT);
|
|
951
|
+
const newEnabled = new Set(cappedEnabled);
|
|
952
|
+
const changed = !setsEqual(this.enabledTools, newEnabled);
|
|
953
|
+
this.enabledTools = newEnabled;
|
|
954
|
+
if (changed) {
|
|
955
|
+
this.notifyVisibleToolsChanged();
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
if (this.discoveryMode === "tools_list") {
|
|
959
|
+
for (const queryResult of results) {
|
|
960
|
+
for (const provider of queryResult.providers) {
|
|
961
|
+
for (const tool of provider.tools) {
|
|
962
|
+
if (!tool.disabled) {
|
|
963
|
+
tool.input_schema = {};
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
}
|
|
949
968
|
}
|
|
950
969
|
return { results };
|
|
951
970
|
}
|
|
@@ -957,7 +976,11 @@ var ToolSearchService = class {
|
|
|
957
976
|
|
|
958
977
|
Available integrations: ${sources.join(", ")}`
|
|
959
978
|
} : searchToolDefinition;
|
|
960
|
-
const
|
|
979
|
+
const runTool = this.enabledTools.size > 0 ? {
|
|
980
|
+
...runToolDefinition,
|
|
981
|
+
description: runToolDefinition.description + "\nYou can also call the discovered tools directly by their namespaced name."
|
|
982
|
+
} : runToolDefinition;
|
|
983
|
+
const tools = [searchTool, runTool];
|
|
961
984
|
for (const name of this.enabledTools) {
|
|
962
985
|
const registered = this.registry.getTool(name);
|
|
963
986
|
if (registered) {
|
|
@@ -1033,8 +1056,7 @@ var BridgeServer = class {
|
|
|
1033
1056
|
this.toolRegistry = options?.toolRegistry ?? new ToolRegistry();
|
|
1034
1057
|
this.toolSearchService = options?.toolSearchService;
|
|
1035
1058
|
this.policyEngine = options?.policyEngine;
|
|
1036
|
-
|
|
1037
|
-
if (showStats && this.toolSearchService) {
|
|
1059
|
+
if (this.toolSearchService) {
|
|
1038
1060
|
this.sessionStats = new SessionStats(
|
|
1039
1061
|
this.toolRegistry,
|
|
1040
1062
|
[searchToolDefinition, runToolDefinition]
|
|
@@ -1106,7 +1128,11 @@ var BridgeServer = class {
|
|
|
1106
1128
|
if (this.sessionStats) {
|
|
1107
1129
|
const responseJson = JSON.stringify(result);
|
|
1108
1130
|
this.sessionStats.recordSearchResponse(responseJson);
|
|
1109
|
-
|
|
1131
|
+
const snapshot = this.sessionStats.getSnapshot();
|
|
1132
|
+
if (this.options.showStats) {
|
|
1133
|
+
response = { session_stats: snapshot, ...result };
|
|
1134
|
+
}
|
|
1135
|
+
this.options.onSearchStats?.(snapshot);
|
|
1110
1136
|
}
|
|
1111
1137
|
return {
|
|
1112
1138
|
content: [{ type: "text", text: JSON.stringify(response) }]
|
|
@@ -2391,7 +2417,12 @@ function buildServerBridgeConfigs(upstreams) {
|
|
|
2391
2417
|
var program = new Command();
|
|
2392
2418
|
program.name(APP_NAME).description(
|
|
2393
2419
|
"Aggregates multiple MCP servers behind a single STDIO interface"
|
|
2394
|
-
).version(APP_VERSION).option("-c, --config <path>", "path to config file").option("--validate", "validate config and list upstream servers, then exit").option("--
|
|
2420
|
+
).version(APP_VERSION).option("-c, --config <path>", "path to config file").option("--validate", "validate config and list upstream servers, then exit").option("--stats", "include session_stats in search_tools responses").addOption(
|
|
2421
|
+
new Option(
|
|
2422
|
+
"--discovery-mode <mode>",
|
|
2423
|
+
"how searched tools are surfaced: search (response only), tools_list (native MCP tools list only), both (default)"
|
|
2424
|
+
).choices(["search", "tools_list", "both"]).default("both")
|
|
2425
|
+
).action(async (options) => {
|
|
2395
2426
|
let server;
|
|
2396
2427
|
let upstreamManager;
|
|
2397
2428
|
let toolSearchService;
|
|
@@ -2426,7 +2457,8 @@ program.name(APP_NAME).description(
|
|
|
2426
2457
|
config._bridge.toolPolicy,
|
|
2427
2458
|
serverBridgeConfigs
|
|
2428
2459
|
);
|
|
2429
|
-
|
|
2460
|
+
const discoveryMode = options.discoveryMode;
|
|
2461
|
+
toolSearchService = new ToolSearchService(toolRegistry, policyEngine, discoveryMode);
|
|
2430
2462
|
for (const [name, serverConfig] of Object.entries(upstreams)) {
|
|
2431
2463
|
if (serverConfig._bridge?.rateLimit) {
|
|
2432
2464
|
rateLimiters.set(name, new RateLimiter(serverConfig._bridge.rateLimit));
|
|
@@ -2438,7 +2470,13 @@ program.name(APP_NAME).description(
|
|
|
2438
2470
|
policyEngine,
|
|
2439
2471
|
getUpstreamClient: (name) => upstreamManager.getClient(name),
|
|
2440
2472
|
getRateLimiter: (name) => rateLimiters.get(name),
|
|
2441
|
-
showStats: options.stats
|
|
2473
|
+
showStats: options.stats === true,
|
|
2474
|
+
onSearchStats: (stats) => {
|
|
2475
|
+
logger.info(
|
|
2476
|
+
`tokens saved: ${stats.tokens_saved.toLocaleString()} (baseline: ${stats.baseline_tokens.toLocaleString()}, bridge: ${stats.bridge_tokens.toLocaleString()})`,
|
|
2477
|
+
{ component: "stats" }
|
|
2478
|
+
);
|
|
2479
|
+
}
|
|
2442
2480
|
});
|
|
2443
2481
|
await server.start();
|
|
2444
2482
|
const serverCount = Object.keys(upstreams).length;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config/schema.ts","../src/constants.ts","../src/config/loader.ts","../src/config/json-schema.ts","../src/config/config-diff.ts","../src/config/config-watcher.ts","../src/logging/index.ts","../src/server/bridge-server.ts","../src/server/tool-registry.ts","../src/server/tool-namespacing.ts","../src/search/tool-search-service.ts","../src/server/session-stats.ts","../src/server/rate-limiter.ts","../src/policy/policy-engine.ts","../src/upstream/base-client.ts","../src/upstream/http-client.ts","../src/credentials/errors.ts","../src/credentials/types.ts","../src/credentials/resolve-templates.ts","../src/upstream/stdio-client.ts","../src/upstream/upstream-manager.ts","../src/credentials/keychain.ts","../src/credentials/credential-store.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport {\n loadConfig,\n ConfigError,\n resolveConfigPath,\n diffConfigs,\n ConfigWatcher,\n} from \"./config/index.js\";\nimport { resolveUpstreams, isStdioServer } from \"./config/schema.js\";\nimport type { ServerBridgeConfig, ServerConfig, HttpServerConfig } from \"./config/schema.js\";\nimport { BridgeServer } from \"./server/index.js\";\nimport { RateLimiter } from \"./server/rate-limiter.js\";\nimport { ToolRegistry } from \"./server/tool-registry.js\";\nimport { ToolSearchService } from \"./search/index.js\";\nimport { PolicyEngine } from \"./policy/index.js\";\nimport { UpstreamManager } from \"./upstream/index.js\";\nimport { APP_NAME, APP_VERSION } from \"./constants.js\";\nimport { createLogger } from \"./logging/index.js\";\nimport {\n CredentialStore,\n CredentialSchema,\n CredentialError,\n createKeychainAdapter,\n type Credential,\n} from \"./credentials/index.js\";\n\nfunction buildServerBridgeConfigs(\n upstreams: Record<string, ServerConfig>,\n): Record<string, ServerBridgeConfig> {\n const result: Record<string, ServerBridgeConfig> = {};\n for (const [name, serverConfig] of Object.entries(upstreams)) {\n if (\"_bridge\" in serverConfig && serverConfig._bridge) {\n result[name] = serverConfig._bridge;\n }\n }\n return result;\n}\n\nconst program = new Command();\n\nprogram\n .name(APP_NAME)\n .description(\n \"Aggregates multiple MCP servers behind a single STDIO interface\",\n )\n .version(APP_VERSION)\n .option(\"-c, --config <path>\", \"path to config file\")\n .option(\"--validate\", \"validate config and list upstream servers, then exit\")\n .option(\"--no-stats\", \"suppress session_stats from search_tools responses\")\n .action(async (options) => {\n let server: BridgeServer | undefined;\n let upstreamManager: UpstreamManager | undefined;\n let toolSearchService: ToolSearchService | undefined;\n let configWatcher: ConfigWatcher | undefined;\n const rateLimiters = new Map<string, RateLimiter>();\n\n try {\n const configPath = resolveConfigPath({ configPath: options.config });\n let config = await loadConfig({ configPath });\n const upstreams = resolveUpstreams(config);\n\n const logger = createLogger({\n level: config._bridge.logLevel,\n format: config._bridge.logFormat,\n });\n\n // --validate: print config summary and exit (always human-readable CLI output)\n if (options.validate) {\n const entries = Object.entries(upstreams);\n process.stderr.write(`Config OK — ${entries.length} upstream server${entries.length === 1 ? \"\" : \"s\"}\\n`);\n for (const [name, serverConfig] of entries) {\n const transport = isStdioServer(serverConfig)\n ? \"stdio\"\n : (serverConfig as HttpServerConfig).type;\n const category = serverConfig._bridge?.category;\n const suffix = category ? ` [${category}]` : \"\";\n process.stderr.write(` ${name} (${transport})${suffix}\\n`);\n }\n return;\n }\n\n const toolRegistry = new ToolRegistry();\n const credentialStore = new CredentialStore({ keychain: createKeychainAdapter() });\n upstreamManager = new UpstreamManager({ config, toolRegistry, logger, credentialStore });\n\n const serverBridgeConfigs = buildServerBridgeConfigs(upstreams);\n\n const policyEngine = new PolicyEngine(\n config._bridge.toolPolicy,\n serverBridgeConfigs,\n );\n\n toolSearchService = new ToolSearchService(toolRegistry, policyEngine);\n\n for (const [name, serverConfig] of Object.entries(upstreams)) {\n if (serverConfig._bridge?.rateLimit) {\n rateLimiters.set(name, new RateLimiter(serverConfig._bridge.rateLimit));\n }\n }\n\n server = new BridgeServer({\n toolRegistry,\n toolSearchService,\n policyEngine,\n getUpstreamClient: (name) => upstreamManager!.getClient(name),\n getRateLimiter: (name) => rateLimiters.get(name),\n showStats: options.stats,\n });\n await server.start();\n\n const serverCount = Object.keys(upstreams).length;\n logger.info(`${APP_NAME} running — connecting to ${serverCount} upstream server${serverCount === 1 ? \"\" : \"s\"}`, { component: \"bridge\" });\n\n // Config hot-reload handler\n const onConfigReload = async (newConfig: typeof config) => {\n const diff = diffConfigs(config, newConfig);\n\n // Bridge-level hot-reloadable settings\n if (diff.bridge.logLevel) {\n logger.setLevel(diff.bridge.logLevel);\n logger.info(`log level changed to ${diff.bridge.logLevel}`, { component: \"reload\" });\n }\n\n if (diff.bridge.healthCheckInterval !== undefined) {\n upstreamManager!.restartHealthChecks(diff.bridge.healthCheckInterval);\n logger.info(`health check interval changed to ${diff.bridge.healthCheckInterval}s`, { component: \"reload\" });\n }\n\n if (diff.bridge.requiresRestart.length > 0) {\n logger.warn(\n `config changed for ${diff.bridge.requiresRestart.join(\", \")} — restart required`,\n { component: \"reload\" },\n );\n }\n\n // Always update the policy engine with the full new state\n const newUpstreams = resolveUpstreams(newConfig);\n const newBridgeConfigs = buildServerBridgeConfigs(newUpstreams);\n policyEngine.update(newConfig._bridge.toolPolicy, newBridgeConfigs);\n\n if (diff.bridge.toolPolicy) {\n logger.info(`tool policy changed to ${diff.bridge.toolPolicy}`, { component: \"reload\" });\n }\n\n // Update rate limiters from new config\n for (const [name, serverConfig] of Object.entries(newUpstreams)) {\n const rl = serverConfig._bridge?.rateLimit;\n const existing = rateLimiters.get(name);\n if (rl && existing) {\n existing.reconfigure(rl);\n } else if (rl) {\n rateLimiters.set(name, new RateLimiter(rl));\n } else if (existing) {\n existing.dispose();\n rateLimiters.delete(name);\n }\n }\n // Remove rate limiters for servers no longer in config\n for (const name of rateLimiters.keys()) {\n if (!(name in newUpstreams)) {\n rateLimiters.get(name)!.dispose();\n rateLimiters.delete(name);\n }\n }\n\n // Server-level changes\n const hasServerChanges =\n diff.servers.added.length > 0 ||\n diff.servers.removed.length > 0 ||\n diff.servers.reconnect.length > 0 ||\n diff.servers.updated.length > 0;\n\n if (hasServerChanges) {\n await upstreamManager!.applyConfigDiff(diff, newConfig);\n }\n\n config = newConfig;\n };\n\n // Connect upstreams in the background — tools appear as each server connects.\n // Config watching starts only after initial connections settle to avoid\n // race conditions between connectAll and applyConfigDiff.\n upstreamManager.connectAll().then((result) => {\n const tools = toolRegistry.listRegisteredTools().length;\n if (result.failed.length === 0) {\n logger.info(`${APP_NAME} ready — ${tools} tools from ${result.connected} servers`, { component: \"bridge\" });\n } else {\n logger.warn(`${APP_NAME} ready — ${tools} tools from ${result.connected} servers (${result.failed.length} failed)`, { component: \"bridge\" });\n for (const f of result.failed) {\n logger.error(`${f.name}: ${f.error}`, { component: \"bridge\" });\n }\n }\n upstreamManager?.startHealthChecks();\n }).catch(() => {\n // Individual failures already logged by UpstreamManager.\n }).finally(() => {\n // Start config watching after initial connections settle to avoid\n // race conditions between connectAll and applyConfigDiff.\n configWatcher = new ConfigWatcher({ configPath, logger });\n configWatcher.start(onConfigReload, config);\n });\n } catch (err) {\n if (err instanceof ConfigError) {\n process.stderr.write(`Error: ${err.message}\\n`);\n for (const issue of err.issues) {\n process.stderr.write(` ${issue.path}: ${issue.message}\\n`);\n }\n process.exitCode = 1;\n return;\n } else {\n throw err;\n }\n }\n\n let shuttingDown = false;\n const shutdown = async () => {\n if (shuttingDown) return;\n shuttingDown = true;\n try {\n configWatcher?.stop();\n toolSearchService?.dispose();\n for (const rl of rateLimiters.values()) {\n rl.dispose();\n }\n rateLimiters.clear();\n if (upstreamManager) {\n await upstreamManager.closeAll();\n }\n if (server) {\n await server.close();\n }\n } catch {\n // Don't prevent exit on close error\n }\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n });\n\n// --- Credential helpers ---\n\nfunction readStdin(): Promise<string> {\n const MAX_STDIN_BYTES = 1024 * 1024; // 1 MB\n if (process.stdin.isTTY) {\n return Promise.resolve(\"\");\n }\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let total = 0;\n process.stdin.on(\"data\", (chunk: Buffer) => {\n total += chunk.length;\n if (total > MAX_STDIN_BYTES) {\n process.stdin.destroy();\n reject(new Error(\"stdin input too large (max 1 MB)\"));\n return;\n }\n chunks.push(chunk);\n });\n process.stdin.on(\"end\", () =>\n resolve(Buffer.concat(chunks).toString(\"utf-8\").trim()),\n );\n process.stdin.on(\"error\", reject);\n });\n}\n\nfunction redact(credential: Credential): Credential {\n const mask = (value: string): string => {\n // Tokens under 20 chars are fully masked to avoid leaking most of the value.\n // Longer tokens show first 4 and last 4 characters.\n if (value.length < 20) return \"****\";\n return value.slice(0, 4) + \"****\" + value.slice(-4);\n };\n\n if (credential.type === \"secret\") {\n return { ...credential, value: mask(credential.value) };\n }\n\n const result = { ...credential };\n result.access_token = mask(result.access_token);\n if (\"refresh_token\" in result && result.refresh_token) {\n result.refresh_token = mask(result.refresh_token);\n }\n return result;\n}\n\n// --- Credential subcommand ---\n\nconst credential = program\n .command(\"credential\")\n .description(\"Manage stored credentials\");\n\ncredential\n .command(\"set <key> [value]\")\n .description(\"Store a credential (plain string, --json for typed, or pipe to stdin)\")\n .option(\"--json <json>\", \"typed credential JSON (bearer/oauth2/secret)\")\n .action(async (key: string, value: string | undefined, options: { json?: string }) => {\n try {\n let cred: Credential;\n\n if (options.json) {\n // --json flag: parse as typed credential\n let parsed: unknown;\n try {\n parsed = JSON.parse(options.json);\n } catch {\n process.stderr.write(\"Error: invalid JSON\\n\");\n process.exitCode = 1;\n return;\n }\n const result = CredentialSchema.safeParse(parsed);\n if (!result.success) {\n process.stderr.write(`Error: invalid credential: ${result.error.message}\\n`);\n process.exitCode = 1;\n return;\n }\n cred = result.data;\n } else if (value) {\n // Positional arg: store as simple secret\n cred = { type: \"secret\", value };\n } else {\n // Read from stdin\n const input = await readStdin();\n if (!input) {\n process.stderr.write(\"Error: no credential provided (pass as argument, use --json, or pipe to stdin)\\n\");\n process.exitCode = 1;\n return;\n }\n // Try JSON parse first; if it fails, treat as plain string\n try {\n const parsed = JSON.parse(input);\n const result = CredentialSchema.safeParse(parsed);\n if (result.success) {\n cred = result.data;\n } else {\n cred = { type: \"secret\", value: input };\n }\n } catch {\n cred = { type: \"secret\", value: input };\n }\n }\n\n const keychain = createKeychainAdapter();\n const store = new CredentialStore({ keychain });\n await store.set(key, cred);\n process.stderr.write(`Credential \"${key}\" stored\\n`);\n } catch (err) {\n const message = err instanceof CredentialError ? err.message : String(err);\n process.stderr.write(`Error: ${message}\\n`);\n process.exitCode = 1;\n }\n });\n\ncredential\n .command(\"get <key>\")\n .description(\"Retrieve a stored credential\")\n .option(\"--show-secret\", \"show full secret values\")\n .action(async (key: string, options: { showSecret?: boolean }) => {\n try {\n const keychain = createKeychainAdapter();\n const store = new CredentialStore({ keychain });\n const cred = await store.get(key);\n\n if (!cred) {\n process.stderr.write(`Credential \"${key}\" not found\\n`);\n process.exitCode = 1;\n return;\n }\n\n const output = options.showSecret ? cred : redact(cred);\n process.stdout.write(JSON.stringify(output, null, 2) + \"\\n\");\n } catch (err) {\n const message = err instanceof CredentialError ? err.message : String(err);\n process.stderr.write(`Error: ${message}\\n`);\n process.exitCode = 1;\n }\n });\n\ncredential\n .command(\"delete <key>\")\n .description(\"Delete a stored credential\")\n .action(async (key: string) => {\n try {\n const keychain = createKeychainAdapter();\n const store = new CredentialStore({ keychain });\n const deleted = await store.delete(key);\n\n if (deleted) {\n process.stderr.write(`Credential \"${key}\" deleted\\n`);\n } else {\n process.stderr.write(`Credential \"${key}\" not found\\n`);\n process.exitCode = 1;\n }\n } catch (err) {\n const message = err instanceof CredentialError ? err.message : String(err);\n process.stderr.write(`Error: ${message}\\n`);\n process.exitCode = 1;\n }\n });\n\ncredential\n .command(\"list\")\n .description(\"List all stored credential keys\")\n .action(async () => {\n try {\n const keychain = createKeychainAdapter();\n const store = new CredentialStore({ keychain });\n const keys = await store.list();\n\n for (const k of keys) {\n process.stdout.write(k + \"\\n\");\n }\n } catch (err) {\n const message = err instanceof CredentialError ? err.message : String(err);\n process.stderr.write(`Error: ${message}\\n`);\n process.exitCode = 1;\n }\n });\n\nprogram.parse();\n","import { z } from \"zod\";\nimport { APP_NAME } from \"../constants.js\";\n\n// --- Tool policy ---\n\nexport const ToolPolicySchema = z.enum([\"always\", \"never\", \"prompt\"]);\n\n// --- Per-server auth config ---\n\nexport const ServerOAuthConfigSchema = z.object({\n type: z.literal(\"oauth2\"),\n clientId: z.string(),\n endpoints: z.object({\n authorization: z.string().url(),\n token: z.string().url(),\n }),\n scopes: z.array(z.string()).optional(),\n});\n\nexport const RateLimitConfigSchema = z.object({\n maxCalls: z.number().int().positive(),\n windowSeconds: z.number().int().positive(),\n});\n\nexport const ServerBridgeConfigSchema = z\n .object({\n auth: ServerOAuthConfigSchema.optional(),\n toolPolicy: ToolPolicySchema.optional(),\n tools: z.record(z.string(), ToolPolicySchema).optional(),\n category: z.string().optional(),\n rateLimit: RateLimitConfigSchema.optional(),\n })\n .strict();\n\n// --- Server configs ---\n\nexport const StdioServerConfigSchema = z.object({\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n _bridge: ServerBridgeConfigSchema.optional(),\n});\n\nexport const HttpServerConfigSchema = z.object({\n type: z\n .enum([\"streamable-http\", \"http\", \"streamableHttp\", \"sse\"])\n .default(\"streamable-http\"),\n url: z.string().url(),\n headers: z.record(z.string(), z.string()).optional(),\n _bridge: ServerBridgeConfigSchema.optional(),\n});\n\n// HTTP first: it has a required `type` field that disambiguates\nexport const ServerConfigSchema = z.union([\n HttpServerConfigSchema,\n StdioServerConfigSchema,\n]);\n\n// --- Global bridge config ---\n\nexport const GlobalBridgeConfigSchema = z\n .object({\n port: z.number().int().min(1).max(65535).default(19875),\n logLevel: z\n .enum([\"debug\", \"info\", \"warn\", \"error\"])\n .default(\"info\"),\n logFormat: z.enum([\"text\", \"json\"]).default(\"text\"),\n maxUpstreamConnections: z.number().int().positive().default(1000),\n connectionTimeout: z.number().int().positive().default(30),\n idleTimeout: z.number().int().positive().default(600),\n healthCheckInterval: z.number().int().min(0).default(30),\n toolPolicy: ToolPolicySchema.default(\"always\"),\n })\n .strict();\n\n// --- Top-level config ---\n\nexport const BridgeConfigSchema = z.object({\n mcpServers: z.record(z.string(), ServerConfigSchema).default({}),\n upstreamMcpServers: z.record(z.string(), ServerConfigSchema).optional(),\n servers: z.record(z.string(), ServerConfigSchema).optional(),\n context_servers: z.record(z.string(), ServerConfigSchema).optional(),\n _bridge: GlobalBridgeConfigSchema.default(\n GlobalBridgeConfigSchema.parse({}),\n ),\n});\n\n// --- Inferred types ---\n\nexport type ToolPolicy = z.infer<typeof ToolPolicySchema>;\nexport type RateLimitConfig = z.infer<typeof RateLimitConfigSchema>;\nexport type ServerOAuthConfig = z.infer<typeof ServerOAuthConfigSchema>;\nexport type ServerBridgeConfig = z.infer<typeof ServerBridgeConfigSchema>;\nexport type StdioServerConfig = z.infer<typeof StdioServerConfigSchema>;\nexport type HttpServerConfig = z.infer<typeof HttpServerConfigSchema>;\nexport type ServerConfig = z.infer<typeof ServerConfigSchema>;\nexport type GlobalBridgeConfig = z.infer<typeof GlobalBridgeConfigSchema>;\nexport type BridgeConfig = z.infer<typeof BridgeConfigSchema>;\n\n// --- Upstream resolution ---\n\n/**\n * Resolves which servers to use as upstreams.\n *\n * Returns the union of all present config keys. On duplicate names,\n * earlier sources win:\n * `upstreamMcpServers` > `servers` > `context_servers` > `mcpServers`.\n *\n * Self-exclusion: entries from `mcpServers` and `context_servers` whose\n * `command` or `args` contain the app name are filtered out.\n */\nexport function resolveUpstreams(\n config: BridgeConfig,\n): Record<string, ServerConfig> {\n const result: Record<string, ServerConfig> = {};\n\n // mcpServers (lowest priority, with self-exclusion)\n for (const [name, server] of Object.entries(config.mcpServers)) {\n if (isStdioServer(server)) {\n const tokens = [server.command, ...(server.args ?? [])];\n if (tokens.some((t) => t.includes(APP_NAME))) {\n continue;\n }\n }\n result[name] = server;\n }\n\n // context_servers (with self-exclusion, above mcpServers)\n if (config.context_servers) {\n for (const [name, server] of Object.entries(config.context_servers)) {\n if (isStdioServer(server)) {\n const tokens = [server.command, ...(server.args ?? [])];\n if (tokens.some((t) => t.includes(APP_NAME))) {\n continue;\n }\n }\n result[name] = server;\n }\n }\n\n // servers (above context_servers)\n if (config.servers) {\n Object.assign(result, config.servers);\n }\n\n // upstreamMcpServers (highest priority)\n if (config.upstreamMcpServers) {\n Object.assign(result, config.upstreamMcpServers);\n }\n\n return result;\n}\n\n// --- Type guards ---\n\nexport function isHttpServer(config: ServerConfig): config is HttpServerConfig {\n return \"type\" in config;\n}\n\nexport function isStdioServer(\n config: ServerConfig,\n): config is StdioServerConfig {\n return \"command\" in config;\n}\n","export const APP_NAME = \"crabeye-mcp-bridge\";\nexport const APP_VERSION = \"0.1.0\";\n\nexport const CREDENTIALS_DIR = `.${APP_NAME}`;\nexport const CREDENTIALS_FILENAME = \"credentials.enc\";\n","import { readFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport { BridgeConfigSchema, type BridgeConfig } from \"./schema.js\";\n\nexport interface ConfigIssue {\n path: string;\n message: string;\n}\n\nexport class ConfigError extends Error {\n readonly issues: ConfigIssue[];\n\n constructor(message: string, issues: ConfigIssue[] = []) {\n super(message);\n this.name = \"ConfigError\";\n this.issues = issues;\n }\n}\n\nfunction flattenZodIssue(\n issue: z.ZodIssue,\n parentPath: string[] = [],\n): ConfigIssue[] {\n const fullPath = [...parentPath, ...issue.path.map(String)];\n\n // Union errors: dig into each branch and surface the specifics\n if (issue.code === \"invalid_union\" && \"errors\" in issue) {\n const unionErrors = issue.errors as z.ZodIssue[][];\n return unionErrors.flatMap((branchErrors) =>\n branchErrors.flatMap((e) => flattenZodIssue(e, fullPath)),\n );\n }\n\n return [{ path: fullPath.join(\".\"), message: issue.message }];\n}\n\nfunction formatZodIssues(error: z.ZodError): ConfigIssue[] {\n return error.issues.flatMap((issue) => flattenZodIssue(issue));\n}\n\nexport interface LoadConfigOptions {\n configPath?: string;\n}\n\nexport function resolveConfigPath(options?: LoadConfigOptions): string {\n if (options?.configPath) {\n return options.configPath;\n }\n\n const envPath = process.env.MCP_BRIDGE_CONFIG;\n if (envPath) {\n return envPath;\n }\n\n throw new ConfigError(\n \"No config file specified. Use --config <path> or set MCP_BRIDGE_CONFIG.\",\n );\n}\n\nexport async function loadConfig(\n options?: LoadConfigOptions,\n): Promise<BridgeConfig> {\n const configPath = resolveConfigPath(options);\n\n let raw: string;\n try {\n raw = await readFile(configPath, \"utf-8\");\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n throw new ConfigError(`Config file not found: ${configPath}`);\n }\n throw new ConfigError(\n `Failed to read config file: ${configPath} (${code ?? \"unknown error\"})`,\n );\n }\n\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch {\n throw new ConfigError(`Invalid JSON in config file: ${configPath}`);\n }\n\n const result = BridgeConfigSchema.safeParse(json);\n if (!result.success) {\n throw new ConfigError(\n \"Config validation failed\",\n formatZodIssues(result.error),\n );\n }\n\n return result.data;\n}\n","import { z } from \"zod\";\nimport { BridgeConfigSchema } from \"./schema.js\";\n\nexport function generateJsonSchema(): Record<string, unknown> {\n return z.toJSONSchema(BridgeConfigSchema) as Record<string, unknown>;\n}\n","import type { BridgeConfig, ServerConfig, ToolPolicy } from \"./schema.js\";\nimport { resolveUpstreams, isStdioServer } from \"./schema.js\";\nimport type { LogLevel } from \"../logging/index.js\";\n\nexport interface ConfigDiff {\n servers: {\n added: Array<{ name: string; config: ServerConfig }>;\n removed: string[];\n reconnect: Array<{ name: string; config: ServerConfig }>;\n updated: Array<{ name: string; config: ServerConfig }>;\n };\n bridge: {\n logLevel?: LogLevel;\n healthCheckInterval?: number;\n toolPolicy?: ToolPolicy;\n requiresRestart: string[];\n };\n}\n\nfunction connectionFields(config: ServerConfig): Record<string, unknown> {\n if (isStdioServer(config)) {\n return {\n command: config.command,\n args: config.args,\n env: config.env,\n };\n }\n return {\n type: config.type,\n url: config.url,\n headers: config.headers,\n };\n}\n\n/** Key-order-independent stringify for deep comparison. */\nfunction stableStringify(value: unknown): string {\n if (value === undefined) return \"undefined\";\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) {\n return \"[\" + value.map(stableStringify).join(\",\") + \"]\";\n }\n const keys = Object.keys(value as Record<string, unknown>).sort();\n return (\n \"{\" +\n keys\n .map(\n (k) =>\n JSON.stringify(k) +\n \":\" +\n stableStringify((value as Record<string, unknown>)[k]),\n )\n .join(\",\") +\n \"}\"\n );\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return stableStringify(a) === stableStringify(b);\n}\n\nexport function diffConfigs(oldConfig: BridgeConfig, newConfig: BridgeConfig): ConfigDiff {\n const oldServers = resolveUpstreams(oldConfig);\n const newServers = resolveUpstreams(newConfig);\n\n const oldNames = new Set(Object.keys(oldServers));\n const newNames = new Set(Object.keys(newServers));\n\n const added: ConfigDiff[\"servers\"][\"added\"] = [];\n const removed: string[] = [];\n const reconnect: ConfigDiff[\"servers\"][\"reconnect\"] = [];\n const updated: ConfigDiff[\"servers\"][\"updated\"] = [];\n\n for (const name of newNames) {\n if (!oldNames.has(name)) {\n added.push({ name, config: newServers[name] });\n }\n }\n\n for (const name of oldNames) {\n if (!newNames.has(name)) {\n removed.push(name);\n }\n }\n\n for (const name of newNames) {\n if (!oldNames.has(name)) continue;\n const oldCfg = oldServers[name];\n const newCfg = newServers[name];\n\n if (!deepEqual(connectionFields(oldCfg), connectionFields(newCfg))) {\n reconnect.push({ name, config: newCfg });\n } else if (!deepEqual(oldCfg._bridge, newCfg._bridge)) {\n updated.push({ name, config: newCfg });\n }\n }\n\n // Bridge-level changes\n const ob = oldConfig._bridge;\n const nb = newConfig._bridge;\n const bridge: ConfigDiff[\"bridge\"] = { requiresRestart: [] };\n\n if (ob.logLevel !== nb.logLevel) bridge.logLevel = nb.logLevel;\n if (ob.healthCheckInterval !== nb.healthCheckInterval) bridge.healthCheckInterval = nb.healthCheckInterval;\n if (ob.toolPolicy !== nb.toolPolicy) bridge.toolPolicy = nb.toolPolicy;\n\n const restartFields = [\"port\", \"logFormat\", \"maxUpstreamConnections\", \"connectionTimeout\", \"idleTimeout\"] as const;\n for (const field of restartFields) {\n if (ob[field] !== nb[field]) {\n bridge.requiresRestart.push(field);\n }\n }\n\n return {\n servers: { added, removed, reconnect, updated },\n bridge,\n };\n}\n","import { watch, type FSWatcher } from \"node:fs\";\nimport { dirname, basename } from \"node:path\";\nimport type { Logger } from \"../logging/index.js\";\nimport { createNoopLogger } from \"../logging/index.js\";\nimport { loadConfig } from \"./loader.js\";\nimport type { BridgeConfig } from \"./schema.js\";\n\nexport interface ConfigWatcherOptions {\n configPath: string;\n debounceMs?: number;\n logger?: Logger;\n}\n\nexport class ConfigWatcher {\n private _configPath: string;\n private _debounceMs: number;\n private _logger: Logger;\n private _watcher: FSWatcher | undefined;\n private _timer: ReturnType<typeof setTimeout> | undefined;\n private _listener: ((config: BridgeConfig) => void | Promise<void>) | undefined;\n private _lastJson: string | undefined;\n private _reloading = false;\n private _pendingReload = false;\n\n constructor(options: ConfigWatcherOptions) {\n this._configPath = options.configPath;\n this._debounceMs = options.debounceMs ?? 500;\n this._logger = options.logger ?? createNoopLogger();\n }\n\n start(\n listener: (config: BridgeConfig) => void | Promise<void>,\n initialConfig?: BridgeConfig,\n ): void {\n if (this._watcher) return;\n\n this._listener = listener;\n\n if (initialConfig) {\n this._lastJson = JSON.stringify(initialConfig);\n }\n\n this._logger.debug(\"watching config file\", {\n component: \"config-watcher\",\n path: this._configPath,\n });\n\n // Watch the directory — more reliable across platforms when files are\n // atomically replaced (write-to-temp + rename).\n const dir = dirname(this._configPath);\n const fileName = basename(this._configPath);\n\n this._watcher = watch(dir, (eventType, changedFile) => {\n // changedFile matches our config, or platform didn't provide a filename\n if (changedFile === fileName || (eventType === \"rename\" && !changedFile)) {\n this._scheduleReload();\n }\n });\n }\n\n stop(): void {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n if (this._watcher) {\n this._watcher.close();\n this._watcher = undefined;\n }\n this._listener = undefined;\n this._reloading = false;\n this._pendingReload = false;\n }\n\n private _scheduleReload(): void {\n if (this._timer) clearTimeout(this._timer);\n this._timer = setTimeout(() => {\n this._timer = undefined;\n this._reload();\n }, this._debounceMs);\n }\n\n private _reload(): void {\n if (this._reloading) {\n this._pendingReload = true;\n return;\n }\n this._reloading = true;\n\n loadConfig({ configPath: this._configPath }).then(\n async (config) => {\n const json = JSON.stringify(config);\n if (json === this._lastJson) {\n this._logger.debug(\"config unchanged, skipping reload\", {\n component: \"config-watcher\",\n });\n this._finishReload();\n return;\n }\n this._logger.info(\"config changed, reloading\", {\n component: \"config-watcher\",\n });\n try {\n await this._listener?.(config);\n this._lastJson = json;\n } catch (err) {\n this._logger.error(\"reload listener threw\", {\n component: \"config-watcher\",\n error: err instanceof Error ? err.message : String(err),\n });\n }\n this._finishReload();\n },\n (err) => {\n this._logger.warn(\"failed to reload config\", {\n component: \"config-watcher\",\n error: err instanceof Error ? err.message : String(err),\n });\n this._finishReload();\n },\n );\n }\n\n private _finishReload(): void {\n this._reloading = false;\n if (this._pendingReload) {\n this._pendingReload = false;\n this._reload();\n }\n }\n}\n","export type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nexport interface Logger {\n debug(message: string, context?: Record<string, unknown>): void;\n info(message: string, context?: Record<string, unknown>): void;\n warn(message: string, context?: Record<string, unknown>): void;\n error(message: string, context?: Record<string, unknown>): void;\n child(defaultContext: Record<string, unknown>): Logger;\n setLevel(level: LogLevel): void;\n}\n\nconst LEVEL_VALUE: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface CreateLoggerOptions {\n level: LogLevel;\n format: \"text\" | \"json\";\n}\n\nfunction pad(n: number, width: number): string {\n return String(n).padStart(width, \"0\");\n}\n\nfunction formatTime(): string {\n const d = new Date();\n return `${pad(d.getHours(), 2)}:${pad(d.getMinutes(), 2)}:${pad(d.getSeconds(), 2)}.${pad(d.getMilliseconds(), 3)}`;\n}\n\nfunction formatText(\n level: LogLevel,\n message: string,\n context: Record<string, unknown>,\n): string {\n const tag = level.toUpperCase().padEnd(5);\n const component = context.component as string | undefined;\n const server = context.server as string | undefined;\n let prefix = \"\";\n if (component && server) {\n prefix = `[${component}:${server}] `;\n } else if (component) {\n prefix = `[${component}] `;\n } else if (server) {\n prefix = `[${server}] `;\n }\n\n // Collect extra keys (everything except component/server)\n const extra: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(context)) {\n if (k !== \"component\" && k !== \"server\" && v !== undefined) {\n extra[k] = v;\n }\n }\n const suffix = Object.keys(extra).length > 0\n ? \" \" + Object.entries(extra).map(([k, v]) => `${k}=${typeof v === \"object\" && v !== null ? JSON.stringify(v) : String(v)}`).join(\" \")\n : \"\";\n\n const safeMessage = message.replace(/\\n/g, \"\\\\n\");\n return `${formatTime()} ${tag} ${prefix}${safeMessage}${suffix}\\n`;\n}\n\nfunction formatJson(\n level: LogLevel,\n message: string,\n context: Record<string, unknown>,\n): string {\n return JSON.stringify({\n ...context,\n time: new Date().toISOString(),\n level,\n msg: message,\n }) + \"\\n\";\n}\n\nclass LoggerImpl implements Logger {\n private _shared: { threshold: number };\n private _format: \"text\" | \"json\";\n private _defaultContext: Record<string, unknown>;\n\n constructor(\n options: CreateLoggerOptions,\n defaultContext: Record<string, unknown> = {},\n shared?: { threshold: number },\n ) {\n this._shared = shared ?? { threshold: LEVEL_VALUE[options.level] };\n this._format = options.format;\n this._defaultContext = defaultContext;\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this._log(\"debug\", message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this._log(\"info\", message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this._log(\"warn\", message, context);\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n this._log(\"error\", message, context);\n }\n\n setLevel(level: LogLevel): void {\n this._shared.threshold = LEVEL_VALUE[level];\n }\n\n child(defaultContext: Record<string, unknown>): Logger {\n return new LoggerImpl(\n { level: \"debug\", format: this._format },\n { ...this._defaultContext, ...defaultContext },\n this._shared,\n );\n }\n\n private _log(\n level: LogLevel,\n message: string,\n context?: Record<string, unknown>,\n ): void {\n if (LEVEL_VALUE[level] < this._shared.threshold) return;\n const merged = context\n ? { ...this._defaultContext, ...context }\n : this._defaultContext;\n const line =\n this._format === \"json\"\n ? formatJson(level, message, merged)\n : formatText(level, message, merged);\n process.stderr.write(line);\n }\n}\n\nexport function createLogger(options: CreateLoggerOptions): Logger {\n return new LoggerImpl(options);\n}\n\n/** A logger that discards all output. Useful in tests. */\nexport function createNoopLogger(): Logger {\n const noop = () => {};\n const logger: Logger = {\n debug: noop,\n info: noop,\n warn: noop,\n error: noop,\n child: () => logger,\n setLevel: noop,\n };\n return logger;\n}\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n ListToolsRequestSchema,\n CallToolRequestSchema,\n ErrorCode,\n McpError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { Readable, Writable } from \"node:stream\";\nimport { ToolRegistry } from \"./tool-registry.js\";\nimport { parseNamespacedName } from \"./tool-namespacing.js\";\nimport type { UpstreamClient } from \"../upstream/types.js\";\nimport {\n ToolSearchService,\n SEARCH_TOOL_NAME,\n RUN_TOOL_NAME,\n searchToolDefinition,\n runToolDefinition,\n} from \"../search/index.js\";\nimport type { SearchToolsParams } from \"../search/index.js\";\nimport type { PolicyEngine } from \"../policy/index.js\";\nimport { SessionStats } from \"./session-stats.js\";\nimport type { RateLimiter } from \"./rate-limiter.js\";\nimport { APP_NAME, APP_VERSION } from \"../constants.js\";\n\nexport interface BridgeServerOptions {\n stdin?: Readable;\n stdout?: Writable;\n toolRegistry?: ToolRegistry;\n toolSearchService?: ToolSearchService;\n policyEngine?: PolicyEngine;\n getUpstreamClient?: (name: string) => UpstreamClient | undefined;\n getRateLimiter?: (name: string) => RateLimiter | undefined;\n showStats?: boolean;\n}\n\nexport class BridgeServer {\n private server: Server;\n private toolRegistry: ToolRegistry;\n private toolSearchService: ToolSearchService | undefined;\n private policyEngine: PolicyEngine | undefined;\n private sessionStats: SessionStats | undefined;\n private unsubscribe: (() => void) | undefined;\n private options: BridgeServerOptions;\n\n constructor(options?: BridgeServerOptions) {\n this.options = options ?? {};\n this.toolRegistry = options?.toolRegistry ?? new ToolRegistry();\n this.toolSearchService = options?.toolSearchService;\n this.policyEngine = options?.policyEngine;\n\n const showStats = options?.showStats !== false;\n if (showStats && this.toolSearchService) {\n this.sessionStats = new SessionStats(\n this.toolRegistry,\n [searchToolDefinition, runToolDefinition],\n );\n }\n\n const instructions = [\n \"This MCP bridge connects you to many external tools and services.\",\n \"You MUST call search_tools BEFORE any of the following:\",\n \"- The user mentions a service, tool, or MCP server by name\",\n \"- The user says 'use X', 'with X', 'in X', 'on X', 'via X', or 'through X'\",\n \"- The user asks you to perform an action that might be handled by an external service (create, update, query, send, manage, etc.)\",\n \"- The user asks what tools or integrations are available, or what you can do\",\n \"- The user asks 'can you...?' about a capability that could involve an external service\",\n \"- You are about to claim a tool is unavailable or that you cannot perform an action — search first, then answer\",\n \"- You are about to fall back to a web search for something that might be available as a tool\",\n \"\",\n \"Discovery workflow:\",\n '1. Start broad: search by provider or category to get summaries: { \"queries\": [{ \"provider\": \"linear\" }] }',\n '2. Drill in: use a tool filter or expand_tools to get full definitions: { \"queries\": [{ \"provider\": \"linear\", \"expand_tools\": true }] } or { \"queries\": [{ \"tool\": \"create\", \"provider\": \"linear\" }] }',\n \"\",\n \"Results are always grouped by provider: results[].providers[].tools[]\",\n \"After discovering tools, use run_tool to execute them. You can also call auto-enabled tools directly by their namespaced name.\",\n \"When in doubt, search — it is always better to search and find nothing than to miss an available tool.\",\n ].join(\"\\n\");\n\n this.server = new Server(\n { name: APP_NAME, version: APP_VERSION },\n {\n capabilities: { tools: { listChanged: true } },\n instructions,\n },\n );\n\n this.server.setRequestHandler(ListToolsRequestSchema, () => {\n if (this.toolSearchService) {\n return { tools: this.toolSearchService.getVisibleTools() };\n }\n return { tools: this.toolRegistry.listTools() };\n });\n\n this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n // Handle search_tools call\n if (this.toolSearchService && name === SEARCH_TOOL_NAME) {\n const params = (args ?? {}) as unknown as SearchToolsParams;\n\n if (!Array.isArray(params.queries) || params.queries.length === 0) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Error: 'queries' must be a non-empty array of query objects.\",\n },\n ],\n isError: true,\n };\n }\n\n for (let i = 0; i < params.queries.length; i++) {\n const q = params.queries[i];\n if (!q.tool && !q.provider && !q.category) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Error: queries[${i}] must have at least one of 'tool', 'provider', or 'category'.`,\n },\n ],\n isError: true,\n };\n }\n }\n\n const result = this.toolSearchService.search(params);\n let response: object = result;\n if (this.sessionStats) {\n const responseJson = JSON.stringify(result);\n this.sessionStats.recordSearchResponse(responseJson);\n response = { session_stats: this.sessionStats.getSnapshot(), ...result };\n }\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(response) }],\n };\n }\n\n // Handle run_tool call\n if (this.toolSearchService && name === RUN_TOOL_NAME) {\n const toolName = (args as { name?: string })?.name;\n const toolArgs = (args as { arguments?: Record<string, unknown> })?.arguments;\n\n if (!toolName) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Error: 'name' is required — provide the full namespaced tool name (e.g. 'linear__create_issue').\",\n },\n ],\n isError: true,\n };\n }\n\n return this.routeToUpstream(toolName, toolArgs);\n }\n\n // Direct tool call (tool must be in registry)\n const registered = this.toolRegistry.getTool(name);\n if (!registered) {\n throw new McpError(\n ErrorCode.InvalidParams,\n `Unknown tool: ${name}`,\n );\n }\n\n return this.routeToUpstream(name, args);\n });\n\n if (this.toolSearchService) {\n this.unsubscribe = this.toolSearchService.onVisibleToolsChanged(() => {\n this.server.sendToolListChanged().catch(() => {\n // Ignore errors when no client is connected\n });\n });\n } else {\n this.unsubscribe = this.toolRegistry.onChanged(() => {\n this.server.sendToolListChanged().catch(() => {\n // Ignore errors when no client is connected\n });\n });\n }\n }\n\n private async routeToUpstream(\n name: string,\n args?: Record<string, unknown>,\n ): Promise<CallToolResult> {\n const parsed = parseNamespacedName(name);\n if (!parsed) {\n throw new McpError(\n ErrorCode.InvalidParams,\n `Invalid tool name (missing namespace): ${name}`,\n );\n }\n\n if (this.policyEngine) {\n const elicitFn = this.server.elicitInput.bind(this.server);\n await this.policyEngine.enforce(parsed.source, parsed.toolName, args, elicitFn);\n }\n\n const getClient = this.options.getUpstreamClient;\n if (!getClient) {\n throw new McpError(\n ErrorCode.InternalError,\n `No upstream client resolver configured`,\n );\n }\n\n const client = getClient(parsed.source);\n if (!client) {\n throw new McpError(\n ErrorCode.InternalError,\n `Upstream server not found: ${parsed.source}`,\n );\n }\n\n if (client.status !== \"connected\") {\n throw new McpError(\n ErrorCode.InternalError,\n `Upstream server \"${parsed.source}\" is not connected (status: ${client.status})`,\n );\n }\n\n const rateLimiter = this.options.getRateLimiter?.(parsed.source);\n if (rateLimiter) {\n try {\n await rateLimiter.acquire();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new McpError(ErrorCode.InternalError, message);\n }\n }\n\n try {\n return await client.callTool({\n name: parsed.toolName,\n arguments: args,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new McpError(\n ErrorCode.InternalError,\n `Upstream server \"${parsed.source}\" error: ${message}`,\n );\n }\n }\n\n async connect(transport: Transport): Promise<void> {\n await this.server.connect(transport);\n }\n\n async start(): Promise<void> {\n const transport = new StdioServerTransport(\n this.options.stdin,\n this.options.stdout,\n );\n await this.connect(transport);\n }\n\n async close(): Promise<void> {\n this.unsubscribe?.();\n this.unsubscribe = undefined;\n this.sessionStats?.dispose();\n await this.server.close();\n }\n\n getToolRegistry(): ToolRegistry {\n return this.toolRegistry;\n }\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport interface RegisteredTool {\n source: string;\n tool: Tool;\n}\n\nexport type ToolListChangedCallback = () => void;\n\nexport class ToolRegistry {\n private tools = new Map<string, RegisteredTool>();\n private sourceIndex = new Map<string, Set<string>>();\n private sourceCategories = new Map<string, string>();\n private listeners = new Set<ToolListChangedCallback>();\n\n listTools(): Tool[] {\n return Array.from(this.tools.values()).map((r) => r.tool);\n }\n\n listRegisteredTools(): RegisteredTool[] {\n return Array.from(this.tools.values());\n }\n\n listSources(): { name: string; toolCount: number }[] {\n const result: { name: string; toolCount: number }[] = [];\n for (const [name, toolNames] of this.sourceIndex) {\n result.push({ name, toolCount: toolNames.size });\n }\n return result;\n }\n\n getTool(name: string): RegisteredTool | undefined {\n return this.tools.get(name);\n }\n\n setCategoryForSource(source: string, category: string): void {\n this.sourceCategories.set(source, category);\n }\n\n getCategoryForSource(source: string): string | undefined {\n return this.sourceCategories.get(source);\n }\n\n removeCategoryForSource(source: string): void {\n this.sourceCategories.delete(source);\n }\n\n setToolsForSource(source: string, tools: Tool[]): void {\n const oldNames = this.sourceIndex.get(source);\n if (oldNames) {\n for (const name of oldNames) {\n this.tools.delete(name);\n }\n }\n\n const newNames = new Set<string>();\n for (const tool of tools) {\n this.tools.set(tool.name, { source, tool });\n newNames.add(tool.name);\n }\n this.sourceIndex.set(source, newNames);\n\n this.notify();\n }\n\n removeSource(source: string): void {\n const names = this.sourceIndex.get(source);\n if (!names || names.size === 0) {\n this.sourceIndex.delete(source);\n return;\n }\n\n let removed = false;\n for (const name of names) {\n const current = this.tools.get(name);\n if (current && current.source === source) {\n this.tools.delete(name);\n removed = true;\n }\n }\n this.sourceIndex.delete(source);\n this.sourceCategories.delete(source);\n\n if (removed) {\n this.notify();\n }\n }\n\n onChanged(callback: ToolListChangedCallback): () => void {\n this.listeners.add(callback);\n return () => {\n this.listeners.delete(callback);\n };\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n try {\n listener();\n } catch {\n // Listeners must not throw, but don't let one block others\n }\n }\n }\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport const NAMESPACE_SEPARATOR = \"__\";\n\n/**\n * Returns a shallow clone of `tool` with name prefixed as `${source}__${tool.name}`.\n */\nexport function namespaceTool(source: string, tool: Tool): Tool {\n return { ...tool, name: `${source}${NAMESPACE_SEPARATOR}${tool.name}` };\n}\n\n/**\n * Splits a namespaced tool name on the first `__` separator.\n * Returns `undefined` if the name contains no separator.\n */\nexport function parseNamespacedName(\n name: string,\n): { source: string; toolName: string } | undefined {\n const idx = name.indexOf(NAMESPACE_SEPARATOR);\n if (idx === -1) return undefined;\n return {\n source: name.slice(0, idx),\n toolName: name.slice(idx + NAMESPACE_SEPARATOR.length),\n };\n}\n","import MiniSearch from \"minisearch\";\nimport type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ToolRegistry } from \"../server/tool-registry.js\";\nimport { parseNamespacedName } from \"../server/tool-namespacing.js\";\nimport type { PolicyEngine } from \"../policy/index.js\";\n\nexport interface SearchQuery {\n tool?: string;\n provider?: string;\n category?: string;\n expand_tools?: boolean;\n limit?: number;\n offset?: number;\n}\n\nexport interface SearchToolsParams {\n queries: SearchQuery[];\n}\n\nexport interface SearchToolResult {\n tool_name: string;\n source: string;\n description: string;\n input_schema: object;\n disabled?: true;\n}\n\nexport interface ProviderResult {\n name: string;\n category?: string;\n tool_count: number;\n tools: SearchToolResult[];\n}\n\nexport interface QueryResult {\n providers: ProviderResult[];\n total: number;\n count: number;\n remaining: number;\n offset: number;\n limit: number;\n}\n\nexport interface SearchToolsResponse {\n results: QueryResult[];\n}\n\ntype VisibleToolsChangedCallback = () => void;\n\ninterface IndexedTool {\n id: string;\n name: string;\n originalName: string;\n description: string;\n source: string;\n category: string;\n}\n\nconst MAX_LIMIT = 50;\nconst DEFAULT_LIMIT = 10;\nconst SCORE_CUTOFF = 0.3;\n\nconst MAX_REGEX_LEN = 200;\n\nfunction parseRegex(input: string): RegExp | null {\n // Support \"regex:pattern\" prefix (preferred) and legacy /pattern/flags format\n let pattern: string;\n let flags = \"\";\n\n if (input.startsWith(\"regex:\")) {\n pattern = input.slice(6);\n } else {\n const match = /^\\/(.+)\\/([gimsuy]*)$/.exec(input);\n if (!match) return null;\n pattern = match[1];\n flags = match[2];\n }\n\n if (!pattern || pattern.length > MAX_REGEX_LEN) return null;\n\n try {\n // Use 'v' flag (unicode sets) for linear-time guarantee where available,\n // fall back to plain construction on older runtimes.\n try {\n return new RegExp(pattern, flags + \"v\");\n } catch {\n return new RegExp(pattern, flags);\n }\n } catch {\n return null;\n }\n}\n\nfunction setsEqual(a: Set<string>, b: Set<string>): boolean {\n if (a.size !== b.size) return false;\n for (const item of a) {\n if (!b.has(item)) return false;\n }\n return true;\n}\n\nfunction matchesPrefixOrRegex(value: string, pattern: string): boolean {\n const regex = parseRegex(pattern);\n if (regex) return regex.test(value);\n return value.toLowerCase().startsWith(pattern.toLowerCase());\n}\n\nexport const SEARCH_TOOL_NAME = \"search_tools\";\nexport const RUN_TOOL_NAME = \"run_tool\";\n\nexport const searchToolDefinition: Tool = {\n name: SEARCH_TOOL_NAME,\n description: [\n \"Search for available tools across all connected MCP servers. ALWAYS call this BEFORE claiming a tool is unavailable, before web search fallback, or when the user mentions any service/tool/integration.\",\n \"\",\n \"Discovery workflow:\",\n \"1. Search by provider or category to get provider summaries (tool counts, no details)\",\n \"2. If you need the tools, drill in with a tool filter or expand_tools: true to get full tool definitions\",\n \"\",\n \"When to use:\",\n \"- User mentions a service or tool by name — search by provider name first\",\n \"- User wants to perform an action (create, update, query, etc.) — search by tool keyword\",\n \"- User asks what tools or integrations are available — search by provider or category for summaries\",\n \"- User asks 'can you...?' about external capabilities — search before answering\",\n \"- You need a tool you haven't seen yet — many tools are available but not listed until searched\",\n \"\",\n \"Response shape: results[].providers[].tools[]\",\n \"Without a tool filter, only provider summaries are returned (name, category, tool_count). Use a tool query or expand_tools: true to get full tool definitions.\",\n \"Use text queries for fuzzy search or prefix with regex: for precise pattern matching.\",\n \"Each query object can have its own filters and pagination.\",\n ].join(\"\\n\"),\n inputSchema: {\n type: \"object\" as const,\n properties: {\n queries: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n tool: {\n type: \"string\",\n description:\n \"Text search query to match tool names and descriptions. \" +\n \"Prefix with regex: for regex matching (e.g. \\\"regex:.*issue.*\\\"). \" +\n \"Prefer passing several queries covering synonyms and related terms to minimize round-trips.\",\n },\n provider: {\n type: \"string\",\n description:\n \"Filter by upstream server/provider name. \" +\n \"Prefix match by default (e.g. \\\"git\\\" matches \\\"github\\\"). \" +\n \"Use regex: prefix for patterns (e.g. \\\"regex:^(linear|figma)$\\\").\",\n },\n category: {\n type: \"string\",\n description:\n \"Filter by tool category (configured via _bridge.category in server config). \" +\n \"Prefix match by default. Use regex: prefix for patterns.\",\n },\n expand_tools: {\n type: \"boolean\",\n description:\n \"When true, return full tool definitions for all tools from matched providers. \" +\n \"Without this, provider-only queries return summaries (name, tool_count) without tool details. \" +\n \"Ignored when a tool filter is present (tool filter always returns details).\",\n },\n limit: {\n type: \"number\",\n description: `Maximum number of tool results for this query (default ${DEFAULT_LIMIT}, max ${MAX_LIMIT})`,\n },\n offset: {\n type: \"number\",\n description: \"Number of tool results to skip for pagination (default 0)\",\n },\n },\n },\n description:\n \"Array of query objects. Each query is self-contained with its own filters and pagination. \" +\n \"Results are deduplicated across queries — first query wins. \" +\n \"Each query must have at least one of: tool, provider, category.\",\n },\n },\n required: [\"queries\"],\n },\n};\n\nexport const runToolDefinition: Tool = {\n name: RUN_TOOL_NAME,\n description: [\n \"Execute any tool from any connected MCP server by its full namespaced name (provider__tool_name format).\",\n \"Use this after discovering tools via search_tools. The tool does not need to be enabled first.\",\n \"Pass the exact namespaced name from search results and the required arguments.\",\n ].join(\"\\n\"),\n inputSchema: {\n type: \"object\" as const,\n properties: {\n name: {\n type: \"string\",\n description:\n \"The full namespaced tool name to call (e.g. 'linear__create_issue')\",\n },\n arguments: {\n type: \"object\",\n description: \"Arguments to pass to the tool\",\n },\n },\n required: [\"name\"],\n },\n};\n\nexport class ToolSearchService {\n private registry: ToolRegistry;\n private index: MiniSearch<IndexedTool>;\n private indexedTools = new Map<string, IndexedTool>();\n private enabledTools = new Set<string>();\n private listeners = new Set<VisibleToolsChangedCallback>();\n private unsubscribeRegistry: () => void;\n private policyEngine: PolicyEngine | undefined;\n\n constructor(registry: ToolRegistry, policyEngine?: PolicyEngine) {\n this.registry = registry;\n this.policyEngine = policyEngine;\n this.index = this.createIndex();\n this.rebuildIndex();\n this.unsubscribeRegistry = this.registry.onChanged(() => {\n this.rebuildIndex();\n });\n }\n\n private createIndex(): MiniSearch<IndexedTool> {\n return new MiniSearch<IndexedTool>({\n fields: [\"name\", \"originalName\", \"description\", \"source\"],\n storeFields: [\"name\", \"originalName\", \"description\", \"source\", \"category\"],\n searchOptions: {\n boost: { name: 3, originalName: 3, description: 1, source: 0.5 },\n prefix: (term) => term.length >= 3,\n fuzzy: (term) => (term.length >= 5 ? 0.2 : false),\n combineWith: \"AND\",\n },\n tokenize: (text) => text.split(/[\\s_\\-./]+/).filter(Boolean),\n });\n }\n\n private rebuildIndex(): void {\n this.index.removeAll();\n this.indexedTools.clear();\n\n const registered = this.registry.listRegisteredTools();\n for (const { source, tool } of registered) {\n const parsed = parseNamespacedName(tool.name);\n const originalName = parsed?.toolName ?? tool.name;\n const category = this.registry.getCategoryForSource(source) ?? \"\";\n\n const doc: IndexedTool = {\n id: tool.name,\n name: tool.name,\n originalName,\n description: tool.description ?? \"\",\n source,\n category,\n };\n this.indexedTools.set(tool.name, doc);\n this.index.add(doc);\n }\n\n // Prune enabled tools that no longer exist\n let pruned = false;\n for (const name of this.enabledTools) {\n if (!this.indexedTools.has(name)) {\n this.enabledTools.delete(name);\n pruned = true;\n }\n }\n\n if (pruned) {\n this.notifyVisibleToolsChanged();\n }\n }\n\n search(params: SearchToolsParams): SearchToolsResponse {\n const queries = params.queries;\n\n if (!queries || queries.length === 0) {\n return { results: [] };\n }\n\n // Compute total tool count per source (for ProviderResult.tool_count)\n const sourceToolCounts = new Map<string, number>();\n for (const doc of this.indexedTools.values()) {\n sourceToolCounts.set(doc.source, (sourceToolCounts.get(doc.source) ?? 0) + 1);\n }\n\n const seenTools = new Set<string>();\n const allEnabled: string[] = [];\n const results: QueryResult[] = [];\n\n for (const query of queries) {\n const hasToolFilter = query.tool !== undefined && query.tool !== \"\";\n const hasProviderFilter = query.provider !== undefined && query.provider !== \"\";\n const hasCategoryFilter = query.category !== undefined && query.category !== \"\";\n const expandTools = query.expand_tools === true;\n\n // Query with no filters: return empty result for this slot\n if (!hasToolFilter && !hasProviderFilter && !hasCategoryFilter) {\n results.push({\n providers: [],\n total: 0,\n count: 0,\n remaining: 0,\n offset: query.offset ?? 0,\n limit: query.limit ?? DEFAULT_LIMIT,\n });\n continue;\n }\n\n const limit = Math.min(\n Math.max(1, query.limit ?? DEFAULT_LIMIT),\n MAX_LIMIT,\n );\n const offset = Math.max(0, query.offset ?? 0);\n const isSummary = !hasToolFilter && !expandTools;\n\n if (isSummary) {\n // Summary mode: provider summaries only, no tool details\n const matchedSources = new Set<string>();\n for (const doc of this.indexedTools.values()) {\n if (hasProviderFilter && !matchesPrefixOrRegex(doc.source, query.provider!)) continue;\n if (hasCategoryFilter && (!doc.category || !matchesPrefixOrRegex(doc.category, query.category!))) continue;\n matchedSources.add(doc.source);\n }\n\n const providers: ProviderResult[] = [];\n let totalToolCount = 0;\n for (const source of matchedSources) {\n const count = sourceToolCounts.get(source) ?? 0;\n const category = this.registry.getCategoryForSource(source);\n providers.push({\n name: source,\n ...(category ? { category } : {}),\n tool_count: count,\n tools: [],\n });\n totalToolCount += count;\n }\n\n results.push({\n providers,\n total: totalToolCount,\n count: 0,\n remaining: 0,\n offset,\n limit,\n });\n // Do NOT add to seenTools or allEnabled in summary mode\n continue;\n }\n\n // Detail mode: collect candidate tools, then group by provider\n let toolCandidates: Set<string> | null = null;\n let providerCandidates: Set<string> | null = null;\n let categoryCandidates: Set<string> | null = null;\n\n if (hasToolFilter) {\n toolCandidates = new Set<string>();\n const regex = parseRegex(query.tool!);\n if (regex) {\n for (const [name, doc] of this.indexedTools) {\n if (\n regex.test(doc.name) ||\n regex.test(doc.originalName) ||\n regex.test(doc.description) ||\n regex.test(doc.source)\n ) {\n toolCandidates.add(name);\n }\n }\n } else {\n const searchResults = this.index.search(query.tool!);\n if (searchResults.length > 0) {\n const topScore = searchResults[0].score;\n const threshold = topScore * SCORE_CUTOFF;\n for (const r of searchResults) {\n if (r.score >= threshold) {\n toolCandidates.add(r.id as string);\n }\n }\n }\n }\n }\n\n if (hasProviderFilter) {\n providerCandidates = new Set<string>();\n for (const [name, doc] of this.indexedTools) {\n if (matchesPrefixOrRegex(doc.source, query.provider!)) {\n providerCandidates.add(name);\n }\n }\n }\n\n if (hasCategoryFilter) {\n categoryCandidates = new Set<string>();\n for (const [name, doc] of this.indexedTools) {\n if (doc.category && matchesPrefixOrRegex(doc.category, query.category!)) {\n categoryCandidates.add(name);\n }\n }\n }\n\n // Intersect all non-null filter sets (AND logic within a query)\n const filterSets = [toolCandidates, providerCandidates, categoryCandidates].filter(\n (s): s is Set<string> => s !== null,\n );\n\n let candidates: Set<string>;\n if (filterSets.length === 0) {\n candidates = new Set();\n } else if (filterSets.length === 1) {\n candidates = filterSets[0];\n } else {\n // Intersect: start with smallest set for efficiency\n const sorted = filterSets.sort((a, b) => a.size - b.size);\n candidates = new Set<string>();\n for (const name of sorted[0]) {\n if (sorted.every((s) => s.has(name))) {\n candidates.add(name);\n }\n }\n }\n\n // Deduplicate across queries — remove tools already seen\n const deduped: string[] = [];\n for (const name of candidates) {\n if (!seenTools.has(name)) {\n deduped.push(name);\n }\n }\n\n const total = deduped.length;\n const paged = deduped.slice(offset, offset + limit);\n\n // Pre-compute policy for each tool on the page\n const disabledSet = new Set<string>();\n if (this.policyEngine) {\n for (const name of paged) {\n const parsed = parseNamespacedName(name);\n if (parsed && this.policyEngine.resolvePolicy(parsed.source, parsed.toolName) === \"never\") {\n disabledSet.add(name);\n }\n }\n }\n\n // Build tools grouped by provider\n const providerToolsMap = new Map<string, SearchToolResult[]>();\n const providerOrder: string[] = [];\n\n for (const name of paged) {\n const doc = this.indexedTools.get(name);\n if (!doc) continue;\n const registered = this.registry.getTool(name);\n if (!registered) continue;\n\n if (!providerToolsMap.has(doc.source)) {\n providerToolsMap.set(doc.source, []);\n providerOrder.push(doc.source);\n }\n\n if (disabledSet.has(name)) {\n providerToolsMap.get(doc.source)!.push({\n tool_name: name,\n source: doc.source,\n description: \"\",\n input_schema: {},\n disabled: true,\n });\n } else {\n providerToolsMap.get(doc.source)!.push({\n tool_name: name,\n source: doc.source,\n description: doc.description,\n input_schema: registered.tool.inputSchema,\n });\n }\n }\n\n const providers: ProviderResult[] = [];\n for (const source of providerOrder) {\n const category = this.registry.getCategoryForSource(source);\n providers.push({\n name: source,\n ...(category ? { category } : {}),\n tool_count: sourceToolCounts.get(source) ?? 0,\n tools: providerToolsMap.get(source) ?? [],\n });\n }\n\n const toolCount = providers.reduce((sum, p) => sum + p.tools.length, 0);\n const remaining = Math.max(0, total - offset - toolCount);\n\n results.push({\n providers,\n total,\n count: toolCount,\n remaining,\n offset,\n limit,\n });\n\n // Mark tools as seen for deduplication, collect enabled tools\n for (const name of deduped) {\n seenTools.add(name);\n }\n\n // Only enable tools in the current page (skip disabled ones)\n for (const name of paged) {\n if (!disabledSet.has(name) && this.indexedTools.has(name) && this.registry.getTool(name)) {\n allEnabled.push(name);\n }\n }\n }\n\n // Cap total enabled tools at MAX_LIMIT\n const cappedEnabled = allEnabled.slice(0, MAX_LIMIT);\n\n const newEnabled = new Set(cappedEnabled);\n const changed = !setsEqual(this.enabledTools, newEnabled);\n this.enabledTools = newEnabled;\n\n if (changed) {\n this.notifyVisibleToolsChanged();\n }\n\n return { results };\n }\n\n getVisibleTools(): Tool[] {\n const sources = this.registry.listSources().map((s) => s.name);\n const searchTool: Tool =\n sources.length > 0\n ? {\n ...searchToolDefinition,\n description:\n searchToolDefinition.description +\n `\\n\\nAvailable integrations: ${sources.join(\", \")}`,\n }\n : searchToolDefinition;\n\n const tools: Tool[] = [searchTool, runToolDefinition];\n for (const name of this.enabledTools) {\n const registered = this.registry.getTool(name);\n if (registered) {\n tools.push(registered.tool);\n }\n }\n return tools;\n }\n\n onVisibleToolsChanged(callback: VisibleToolsChangedCallback): () => void {\n this.listeners.add(callback);\n return () => {\n this.listeners.delete(callback);\n };\n }\n\n dispose(): void {\n this.unsubscribeRegistry();\n this.listeners.clear();\n }\n\n private notifyVisibleToolsChanged(): void {\n for (const listener of this.listeners) {\n try {\n listener();\n } catch {\n // Listeners must not throw, but don't let one block others\n }\n }\n }\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ToolRegistry } from \"./tool-registry.js\";\n\nexport interface SessionStatsSnapshot {\n tokens_saved: number;\n baseline_tokens: number;\n bridge_tokens: number;\n}\n\nfunction estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\nexport class SessionStats {\n private registry: ToolRegistry;\n private metaToolTokens: number = 0;\n private cumulativeSearchTokens: number = 0;\n private unsubscribe: () => void;\n\n constructor(registry: ToolRegistry, metaTools: Tool[]) {\n this.registry = registry;\n this.metaToolTokens = estimateTokens(JSON.stringify(metaTools));\n this.unsubscribe = this.registry.onChanged(() => {\n // Baseline recalculated on every snapshot, nothing to cache\n });\n }\n\n recordSearchResponse(responseJson: string): void {\n this.cumulativeSearchTokens += estimateTokens(responseJson);\n }\n\n getSnapshot(): SessionStatsSnapshot {\n const allTools = this.registry.listTools();\n const baselineTokens = estimateTokens(JSON.stringify(allTools));\n const bridgeTokens = this.metaToolTokens + this.cumulativeSearchTokens;\n return {\n tokens_saved: Math.max(0, baselineTokens - bridgeTokens),\n baseline_tokens: baselineTokens,\n bridge_tokens: bridgeTokens,\n };\n }\n\n dispose(): void {\n this.unsubscribe();\n }\n}\n","import type { RateLimitConfig } from \"../config/schema.js\";\n\nexport type { RateLimitConfig };\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\ninterface Waiter {\n resolve: () => void;\n reject: (err: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\nexport class RateLimiter {\n private maxCalls: number;\n private windowMs: number;\n private timeoutMs: number;\n private timestamps: number[] = [];\n private queue: Waiter[] = [];\n private drainTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(config: RateLimitConfig, timeoutMs = DEFAULT_TIMEOUT_MS) {\n this.maxCalls = config.maxCalls;\n this.windowMs = config.windowSeconds * 1000;\n this.timeoutMs = timeoutMs;\n }\n\n async acquire(): Promise<void> {\n this.prune();\n\n if (this.timestamps.length < this.maxCalls) {\n this.timestamps.push(Date.now());\n return;\n }\n\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n const idx = this.queue.findIndex((w) => w.resolve === resolve);\n if (idx !== -1) this.queue.splice(idx, 1);\n reject(new Error(\"Rate limit timeout: too many calls queued\"));\n }, this.timeoutMs);\n\n this.queue.push({ resolve, reject, timer });\n this.scheduleDrain();\n });\n }\n\n reconfigure(config: RateLimitConfig): void {\n this.maxCalls = config.maxCalls;\n this.windowMs = config.windowSeconds * 1000;\n this.tryDrain();\n }\n\n dispose(): void {\n if (this.drainTimer !== undefined) {\n clearTimeout(this.drainTimer);\n this.drainTimer = undefined;\n }\n for (const waiter of this.queue) {\n clearTimeout(waiter.timer);\n waiter.reject(new Error(\"Rate limiter disposed\"));\n }\n this.queue = [];\n this.timestamps = [];\n }\n\n private prune(): void {\n const cutoff = Date.now() - this.windowMs;\n let i = 0;\n while (i < this.timestamps.length && this.timestamps[i] <= cutoff) i++;\n if (i > 0) this.timestamps.splice(0, i);\n }\n\n private tryDrain(): void {\n this.prune();\n while (this.queue.length > 0 && this.timestamps.length < this.maxCalls) {\n const waiter = this.queue.shift()!;\n clearTimeout(waiter.timer);\n this.timestamps.push(Date.now());\n waiter.resolve();\n }\n this.scheduleDrain();\n }\n\n private scheduleDrain(): void {\n if (this.drainTimer !== undefined) {\n clearTimeout(this.drainTimer);\n this.drainTimer = undefined;\n }\n if (this.queue.length === 0 || this.timestamps.length === 0) return;\n\n const oldestExpiry = this.timestamps[0] + this.windowMs - Date.now();\n const delay = Math.max(1, oldestExpiry);\n this.drainTimer = setTimeout(() => {\n this.drainTimer = undefined;\n this.tryDrain();\n }, delay);\n }\n}\n","import {\n ErrorCode,\n McpError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n ElicitRequestFormParams,\n ElicitResult,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ToolPolicy, ServerBridgeConfig } from \"../config/schema.js\";\n\nexport type ElicitFn = (\n params: ElicitRequestFormParams,\n) => Promise<ElicitResult>;\n\nexport class PolicyEngine {\n private globalPolicy: ToolPolicy;\n private serverConfigs: Record<string, ServerBridgeConfig>;\n\n constructor(\n globalPolicy: ToolPolicy,\n serverConfigs: Record<string, ServerBridgeConfig>,\n ) {\n this.globalPolicy = globalPolicy;\n this.serverConfigs = serverConfigs;\n }\n\n update(\n globalPolicy: ToolPolicy,\n serverConfigs: Record<string, ServerBridgeConfig>,\n ): void {\n this.globalPolicy = globalPolicy;\n this.serverConfigs = serverConfigs;\n }\n\n resolvePolicy(source: string, toolName: string): ToolPolicy {\n const serverConfig = this.serverConfigs[source];\n if (serverConfig) {\n const perTool = serverConfig.tools?.[toolName];\n if (perTool) return perTool;\n\n if (serverConfig.toolPolicy) return serverConfig.toolPolicy;\n }\n\n return this.globalPolicy;\n }\n\n async enforce(\n source: string,\n toolName: string,\n args: Record<string, unknown> | undefined,\n elicitFn: ElicitFn,\n ): Promise<void> {\n const policy = this.resolvePolicy(source, toolName);\n\n if (policy === \"always\") return;\n\n if (policy === \"never\") {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Tool ${source}__${toolName} is disabled by policy`,\n );\n }\n\n // policy === \"prompt\"\n try {\n const result = await elicitFn({\n message: `Allow ${source}__${toolName} to run?\\n\\nArguments:\\n${JSON.stringify(args ?? {}, null, 2)}`,\n requestedSchema: { type: \"object\", properties: {} },\n });\n\n if (result.action !== \"accept\") {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Tool ${source}__${toolName} was declined by user`,\n );\n }\n } catch (err) {\n if (err instanceof McpError) throw err;\n // Client doesn't support elicitation — block the call\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Tool ${source}__${toolName} requires confirmation but the client does not support elicitation`,\n );\n }\n }\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { Tool, CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { APP_NAME, APP_VERSION } from \"../constants.js\";\nimport type { Logger } from \"../logging/index.js\";\nimport { createNoopLogger } from \"../logging/index.js\";\nimport type {\n UpstreamClient,\n ConnectionStatus,\n StatusChangeEvent,\n StatusChangeCallback,\n ToolsChangedCallback,\n} from \"./types.js\";\n\nexport interface BaseUpstreamClientOptions {\n name: string;\n logger?: Logger;\n maxReconnectAttempts?: number;\n reconnectBaseDelay?: number;\n reconnectMaxDelay?: number;\n /** Injectable transport factory for testing. */\n _transportFactory?: () => Transport;\n}\n\nexport abstract class BaseUpstreamClient implements UpstreamClient {\n readonly name: string;\n\n private _status: ConnectionStatus = \"disconnected\";\n private _tools: Tool[] = [];\n private _client: Client | undefined;\n private _closed = false;\n private _epoch = 0;\n private _connectPromise: Promise<void> | undefined;\n private _reconnectAttempt = 0;\n private _reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n private _maxReconnectAttempts: number;\n private _reconnectBaseDelay: number;\n private _reconnectMaxDelay: number;\n private _transportFactory: (() => Transport) | undefined;\n protected _logger: Logger;\n private _statusListeners = new Set<StatusChangeCallback>();\n private _toolsListeners = new Set<ToolsChangedCallback>();\n\n constructor(options: BaseUpstreamClientOptions) {\n this.name = options.name;\n this._maxReconnectAttempts = options.maxReconnectAttempts ?? 5;\n this._reconnectBaseDelay = options.reconnectBaseDelay ?? 1000;\n this._reconnectMaxDelay = options.reconnectMaxDelay ?? 30000;\n this._transportFactory = options._transportFactory;\n this._logger = options.logger ?? createNoopLogger();\n }\n\n get status(): ConnectionStatus {\n return this._status;\n }\n\n get tools(): ReadonlyArray<Tool> {\n return this._tools;\n }\n\n async connect(): Promise<void> {\n if (this._connectPromise) return this._connectPromise;\n this._connectPromise = this._doConnect().finally(() => {\n this._connectPromise = undefined;\n });\n return this._connectPromise;\n }\n\n private async _doConnect(): Promise<void> {\n this._closed = false;\n this._clearReconnectTimer();\n this._epoch++;\n const myEpoch = this._epoch;\n\n // Clean up stale connection before creating a new one\n if (this._client) {\n const old = this._client;\n this._client = undefined;\n await old.close().catch(() => {});\n }\n\n this._setStatus(\"connecting\");\n this._logger.debug(\"connecting\");\n\n try {\n await this._prepareConnect();\n const transport = this._createTransport();\n const client = new Client(\n { name: `${APP_NAME}/${this.name}`, version: APP_VERSION },\n {\n listChanged: {\n tools: {\n autoRefresh: true,\n onChanged: (error, tools) => {\n if (error || !tools || this._epoch !== myEpoch) return;\n this._tools = tools;\n this._notifyToolsChanged();\n },\n },\n },\n },\n );\n\n transport.onclose = () => {\n if (this._closed || this._epoch !== myEpoch) return;\n this._client = undefined;\n this._setStatus(\"disconnected\");\n this._scheduleReconnect();\n };\n\n await client.connect(transport);\n\n const result = await client.listTools();\n this._tools = result.tools;\n this._client = client;\n this._reconnectAttempt = 0;\n this._setStatus(\"connected\");\n this._notifyToolsChanged();\n } catch (err) {\n this._logger.debug(\"connection failed\", {\n error: err instanceof Error ? err.message : String(err),\n });\n this._setStatus(\"disconnected\");\n throw err;\n }\n }\n\n async callTool(params: {\n name: string;\n arguments?: Record<string, unknown>;\n }): Promise<CallToolResult> {\n if (!this._client || this._status !== \"connected\") {\n throw new Error(\n `Cannot call tool \"${params.name}\": client \"${this.name}\" is not connected`,\n );\n }\n return this._client.callTool(params) as Promise<CallToolResult>;\n }\n\n async close(): Promise<void> {\n this._closed = true;\n this._clearReconnectTimer();\n\n if (this._client) {\n const client = this._client;\n this._client = undefined;\n await client.close();\n }\n\n this._tools = [];\n this._setStatus(\"disconnected\");\n }\n\n async ping(timeoutMs = 5000): Promise<void> {\n if (!this._client || this._status !== \"connected\") {\n throw new Error(`Cannot ping: client \"${this.name}\" is not connected`);\n }\n await this._client.ping({ signal: AbortSignal.timeout(timeoutMs) });\n }\n\n async reconnect(): Promise<void> {\n this._reconnectAttempt = 0;\n this._closed = false;\n this._clearReconnectTimer();\n this._epoch++;\n\n if (this._client) {\n const old = this._client;\n this._client = undefined;\n await old.close().catch(() => {});\n }\n\n this._logger.info(\"reconnecting\");\n await this.connect();\n }\n\n onStatusChange(callback: StatusChangeCallback): () => void {\n this._statusListeners.add(callback);\n return () => {\n this._statusListeners.delete(callback);\n };\n }\n\n onToolsChanged(callback: ToolsChangedCallback): () => void {\n this._toolsListeners.add(callback);\n return () => {\n this._toolsListeners.delete(callback);\n };\n }\n\n private _createTransport(): Transport {\n if (this._transportFactory) {\n return this._transportFactory();\n }\n return this._buildTransport();\n }\n\n /** Async hook called before transport creation in _doConnect(). Override for async setup. */\n protected async _prepareConnect(): Promise<void> {}\n\n /** Subclasses create the real transport here. */\n protected abstract _buildTransport(): Transport;\n\n private _setStatus(next: ConnectionStatus, error?: Error): void {\n const previous = this._status;\n if (previous === next) return;\n this._status = next;\n\n const event: StatusChangeEvent = {\n previous,\n current: next,\n ...(error && { error }),\n };\n for (const listener of this._statusListeners) {\n try {\n listener(event);\n } catch {\n // Listeners must not throw\n }\n }\n }\n\n private _notifyToolsChanged(): void {\n for (const listener of this._toolsListeners) {\n try {\n listener(this._tools);\n } catch {\n // Listeners must not throw\n }\n }\n }\n\n private _scheduleReconnect(): void {\n if (this._closed) return;\n if (this._reconnectTimer !== undefined) return;\n if (this._connectPromise) return;\n\n if (this._reconnectAttempt >= this._maxReconnectAttempts) {\n this._logger.warn(\"max reconnect attempts reached\");\n this._setStatus(\"error\", new Error(\"Max reconnect attempts exceeded\"));\n return;\n }\n\n const delay = Math.min(\n this._reconnectBaseDelay * Math.pow(2, this._reconnectAttempt),\n this._reconnectMaxDelay,\n );\n this._reconnectAttempt++;\n this._logger.debug(`reconnecting in ${delay}ms`, { attempt: this._reconnectAttempt });\n\n this._reconnectTimer = setTimeout(() => {\n this._reconnectTimer = undefined;\n this.connect().catch(() => {\n this._scheduleReconnect();\n });\n }, delay);\n }\n\n private _clearReconnectTimer(): void {\n if (this._reconnectTimer !== undefined) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = undefined;\n }\n }\n}\n","import { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { HttpServerConfig } from \"../config/schema.js\";\nimport type { CredentialStore } from \"../credentials/credential-store.js\";\nimport { hasCredentialTemplates, resolveCredentialTemplates } from \"../credentials/resolve-templates.js\";\nimport { BaseUpstreamClient } from \"./base-client.js\";\nimport type { BaseUpstreamClientOptions } from \"./base-client.js\";\n\nexport interface HttpUpstreamClientOptions extends BaseUpstreamClientOptions {\n config: HttpServerConfig;\n credentialStore?: CredentialStore;\n}\n\nexport class HttpUpstreamClient extends BaseUpstreamClient {\n private _config: HttpServerConfig;\n private _credentialStore: CredentialStore | undefined;\n private _resolvedHeaders: Record<string, string> | undefined;\n\n constructor(options: HttpUpstreamClientOptions) {\n super(options);\n this._config = options.config;\n this._credentialStore = options.credentialStore;\n }\n\n protected override async _prepareConnect(): Promise<void> {\n this._resolvedHeaders = undefined;\n if (\n this._credentialStore &&\n this._config.headers &&\n hasCredentialTemplates(this._config.headers as Record<string, string>)\n ) {\n this._resolvedHeaders = await resolveCredentialTemplates(\n this._config.headers as Record<string, string>,\n this._credentialStore,\n );\n }\n }\n\n protected _buildTransport(): Transport {\n const url = new URL(this._config.url);\n const headers = this._resolvedHeaders ?? this._config.headers;\n const requestInit: RequestInit | undefined = headers\n ? { headers: headers as Record<string, string> }\n : undefined;\n\n if (this._config.type !== \"sse\") {\n return new StreamableHTTPClientTransport(url, { requestInit });\n }\n return new SSEClientTransport(url, { requestInit });\n }\n}\n","export class CredentialError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"CredentialError\";\n }\n}\n","import { z } from \"zod\";\n\n// --- Credential schemas ---\n\nexport const BearerCredentialSchema = z.object({\n type: z.literal(\"bearer\"),\n access_token: z.string().min(1),\n});\n\nexport const OAuth2CredentialSchema = z.object({\n type: z.literal(\"oauth2\"),\n access_token: z.string().min(1),\n refresh_token: z.string().min(1).optional(),\n token_endpoint: z.string().url().optional(),\n client_id: z.string().min(1).optional(),\n expires_at: z.number().int().nonnegative().finite().optional(),\n});\n\nexport const SecretCredentialSchema = z.object({\n type: z.literal(\"secret\"),\n value: z.string().min(1),\n});\n\nexport const CredentialSchema = z.union([\n BearerCredentialSchema,\n OAuth2CredentialSchema,\n SecretCredentialSchema,\n]);\n\nexport const CredentialStoreFileSchema = z.object({\n version: z.literal(1),\n credentials: z.record(z.string(), CredentialSchema),\n});\n\n// --- Inferred types ---\n\nexport type BearerCredential = z.infer<typeof BearerCredentialSchema>;\nexport type OAuth2Credential = z.infer<typeof OAuth2CredentialSchema>;\nexport type SecretCredential = z.infer<typeof SecretCredentialSchema>;\nexport type Credential = z.infer<typeof CredentialSchema>;\nexport type CredentialStoreFile = z.infer<typeof CredentialStoreFileSchema>;\n\n// --- Helpers ---\n\n/** Extract the resolved string value from any credential type. */\nexport function resolveCredentialValue(credential: Credential): string {\n if (credential.type === \"secret\") return credential.value;\n return credential.access_token;\n}\n","import type { CredentialStore } from \"./credential-store.js\";\nimport { CredentialError } from \"./errors.js\";\nimport { resolveCredentialValue } from \"./types.js\";\n\nconst TEMPLATE_RE = /\\$\\{credential:([^}]+)\\}/g;\nconst TEMPLATE_TEST_RE = /\\$\\{credential:[^}]+\\}/;\n\n/** Fast check: does any value in the record contain a `${credential:...}` template? */\nexport function hasCredentialTemplates(\n record: Record<string, string> | undefined,\n): boolean {\n if (!record) return false;\n for (const value of Object.values(record)) {\n if (TEMPLATE_TEST_RE.test(value)) return true;\n }\n return false;\n}\n\n/**\n * Replace all `${credential:key}` templates in a string→string record.\n * Supports mixed content (e.g. `\"Bearer ${credential:token}\"`) and\n * multiple templates per value.\n *\n * Uses index-based replacement (processed in reverse) to avoid\n * `String.replace` interpreting `$`-patterns in credential values\n * and to handle duplicate templates correctly.\n */\nexport async function resolveCredentialTemplates(\n record: Record<string, string>,\n store: CredentialStore,\n): Promise<Record<string, string>> {\n const resolved: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(record)) {\n const matches = [...value.matchAll(TEMPLATE_RE)];\n if (matches.length === 0) {\n resolved[key] = value;\n continue;\n }\n\n // Resolve all credentials first (fail-fast on missing keys)\n const replacements: Array<{ start: number; end: number; resolved: string }> = [];\n for (const match of matches) {\n const credKey = match[1];\n const credential = await store.get(credKey);\n if (!credential) {\n throw new CredentialError(\n `Credential \"${credKey}\" not found in credential store`,\n );\n }\n replacements.push({\n start: match.index!,\n end: match.index! + match[0].length,\n resolved: resolveCredentialValue(credential),\n });\n }\n\n // Apply in reverse so earlier indices stay valid\n let result = value;\n for (let i = replacements.length - 1; i >= 0; i--) {\n const { start, end, resolved: val } = replacements[i];\n result = result.slice(0, start) + val + result.slice(end);\n }\n resolved[key] = result;\n }\n\n return resolved;\n}\n","import { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { StdioServerConfig } from \"../config/schema.js\";\nimport type { CredentialStore } from \"../credentials/credential-store.js\";\nimport { hasCredentialTemplates, resolveCredentialTemplates } from \"../credentials/resolve-templates.js\";\nimport { BaseUpstreamClient } from \"./base-client.js\";\nimport type { BaseUpstreamClientOptions } from \"./base-client.js\";\n\nexport interface StdioUpstreamClientOptions extends BaseUpstreamClientOptions {\n config: StdioServerConfig;\n credentialStore?: CredentialStore;\n}\n\nexport class StdioUpstreamClient extends BaseUpstreamClient {\n private _config: StdioServerConfig;\n private _credentialStore: CredentialStore | undefined;\n private _resolvedEnv: Record<string, string> | undefined;\n\n constructor(options: StdioUpstreamClientOptions) {\n super(options);\n this._config = options.config;\n this._credentialStore = options.credentialStore;\n }\n\n protected override async _prepareConnect(): Promise<void> {\n this._resolvedEnv = undefined;\n if (\n this._credentialStore &&\n this._config.env &&\n hasCredentialTemplates(this._config.env as Record<string, string>)\n ) {\n this._resolvedEnv = await resolveCredentialTemplates(\n this._config.env as Record<string, string>,\n this._credentialStore,\n );\n }\n }\n\n protected _buildTransport(): Transport {\n const env = this._resolvedEnv ?? this._config.env;\n const transport = new StdioClientTransport({\n command: this._config.command,\n args: this._config.args,\n env: { ...process.env, ...env } as Record<string, string>,\n stderr: \"pipe\",\n });\n\n // Forward subprocess stderr through the logger\n transport.stderr?.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString().trimEnd();\n if (text) {\n for (const line of text.split(\"\\n\")) {\n this._logger.debug(line, { stream: \"stderr\" });\n }\n }\n });\n\n return transport;\n }\n}\n","import type { BridgeConfig, ServerConfig, HttpServerConfig } from \"../config/schema.js\";\nimport { isStdioServer, resolveUpstreams } from \"../config/schema.js\";\nimport type { ConfigDiff } from \"../config/config-diff.js\";\nimport type { CredentialStore } from \"../credentials/credential-store.js\";\nimport type { Logger } from \"../logging/index.js\";\nimport { createNoopLogger } from \"../logging/index.js\";\nimport type { ToolRegistry } from \"../server/tool-registry.js\";\nimport { namespaceTool } from \"../server/tool-namespacing.js\";\nimport { HttpUpstreamClient } from \"./http-client.js\";\nimport { StdioUpstreamClient } from \"./stdio-client.js\";\nimport type { UpstreamClient, ConnectionStatus, HealthState } from \"./types.js\";\n\nexport interface UpstreamManagerOptions {\n config: BridgeConfig;\n toolRegistry: ToolRegistry;\n logger?: Logger;\n credentialStore?: CredentialStore;\n /** Health check interval in seconds. 0 to disable. Overrides config value. */\n healthCheckInterval?: number;\n /** Injectable client factory for testing. */\n _clientFactory?: (name: string, config: ServerConfig, logger: Logger) => UpstreamClient;\n}\n\nexport interface UpstreamStatus {\n name: string;\n status: ConnectionStatus;\n health: HealthState;\n toolCount: number;\n lastPingAt?: number;\n}\n\ninterface HealthTracking {\n consecutiveFailures: number;\n lastPingAt?: number;\n health: HealthState;\n}\n\nexport interface ConnectAllResult {\n total: number;\n connected: number;\n failed: Array<{ name: string; error: string }>;\n}\n\nexport class UpstreamManager {\n private _config: BridgeConfig;\n private _toolRegistry: ToolRegistry;\n private _logger: Logger;\n private _clientFactory: (name: string, config: ServerConfig, logger: Logger) => UpstreamClient;\n private _clients = new Map<string, UpstreamClient>();\n private _unsubscribers = new Map<string, Array<() => void>>();\n private _healthCheckInterval: number;\n private _healthTimer: ReturnType<typeof setInterval> | undefined;\n private _healthTracking = new Map<string, HealthTracking>();\n private _pingsInFlight = new Set<string>();\n private _pingTimeoutMs = 5000;\n private _unhealthyThreshold = 3;\n\n constructor(options: UpstreamManagerOptions) {\n this._config = options.config;\n this._toolRegistry = options.toolRegistry;\n this._logger = options.logger ?? createNoopLogger();\n this._healthCheckInterval =\n options.healthCheckInterval ?? options.config._bridge.healthCheckInterval;\n const credentialStore = options.credentialStore;\n this._clientFactory =\n options._clientFactory ??\n ((name, config, logger) => {\n if (isStdioServer(config)) {\n return new StdioUpstreamClient({ name, config, logger, credentialStore });\n }\n return new HttpUpstreamClient({ name, config: config as HttpServerConfig, logger, credentialStore });\n });\n }\n\n private _addClient(\n name: string,\n serverConfig: ServerConfig,\n ): Promise<{ name: string; error?: string }> {\n const log = this._logger.child({ component: \"upstream\", server: name });\n const transport = isStdioServer(serverConfig)\n ? \"stdio\"\n : (serverConfig as HttpServerConfig).type;\n log.info(`connecting (${transport})`);\n\n const client = this._clientFactory(name, serverConfig, log);\n this._clients.set(name, client);\n\n const category = serverConfig._bridge?.category;\n if (category) {\n this._toolRegistry.setCategoryForSource(name, category);\n }\n\n const unsubTools = client.onToolsChanged((tools) => {\n const namespaced = tools.map((t) => namespaceTool(name, t));\n this._toolRegistry.setToolsForSource(name, namespaced);\n log.info(\n `${tools.length} tool${tools.length === 1 ? \"\" : \"s\"} discovered: ${namespaced.map((t) => t.name).join(\", \")}`,\n );\n });\n\n const unsubStatus = client.onStatusChange((event) => {\n if (event.current === \"error\") {\n log.error(\n `error: ${event.error?.message ?? \"unknown\"}`,\n );\n this._toolRegistry.removeSource(name);\n } else {\n log.debug(`${event.current}`);\n }\n });\n\n this._unsubscribers.set(name, [unsubTools, unsubStatus]);\n\n return client.connect().then(\n () => ({ name }),\n (err) => {\n const message = err instanceof Error ? err.message : String(err);\n log.error(`failed to connect: ${message}`);\n return { name, error: message };\n },\n );\n }\n\n private async _removeClient(name: string): Promise<void> {\n const unsubs = this._unsubscribers.get(name);\n if (unsubs) {\n for (const unsub of unsubs) unsub();\n this._unsubscribers.delete(name);\n }\n\n const client = this._clients.get(name);\n if (client) {\n await client.close().catch(() => {});\n this._clients.delete(name);\n }\n\n this._toolRegistry.removeSource(name);\n this._healthTracking.delete(name);\n this._pingsInFlight.delete(name);\n }\n\n async connectAll(): Promise<ConnectAllResult> {\n const entries = Object.entries(resolveUpstreams(this._config));\n const connectPromises: Promise<{ name: string; error?: string }>[] = [];\n\n for (const [name, serverConfig] of entries) {\n connectPromises.push(this._addClient(name, serverConfig));\n }\n\n const outcomes = await Promise.all(connectPromises);\n const failed = outcomes.filter((o) => o.error !== undefined) as Array<{ name: string; error: string }>;\n return {\n total: entries.length,\n connected: entries.length - failed.length,\n failed,\n };\n }\n\n async closeAll(): Promise<void> {\n this.stopHealthChecks();\n\n for (const unsubs of this._unsubscribers.values()) {\n for (const unsub of unsubs) unsub();\n }\n this._unsubscribers.clear();\n\n const names = Array.from(this._clients.keys());\n\n const closePromises = Array.from(this._clients.values()).map((client) =>\n client.close().catch(() => {\n // Ignore close errors\n }),\n );\n await Promise.all(closePromises);\n\n for (const name of names) {\n this._toolRegistry.removeSource(name);\n }\n\n this._clients.clear();\n this._healthTracking.clear();\n this._pingsInFlight.clear();\n }\n\n async applyConfigDiff(diff: ConfigDiff, newConfig: BridgeConfig): Promise<void> {\n // 1. Remove deleted servers\n for (const name of diff.servers.removed) {\n this._logger.info(`removing server`, { component: \"reload\", server: name });\n await this._removeClient(name);\n }\n\n // 2. Reconnect servers with changed connection fields\n for (const { name, config } of diff.servers.reconnect) {\n this._logger.info(`reconnecting server`, { component: \"reload\", server: name });\n await this._removeClient(name);\n const result = await this._addClient(name, config);\n if (result.error) {\n this._logger.warn(`server failed to connect after reload`, {\n component: \"reload\", server: name, error: result.error,\n });\n }\n }\n\n // 3. Add new servers\n for (const { name, config } of diff.servers.added) {\n this._logger.info(`adding server`, { component: \"reload\", server: name });\n const result = await this._addClient(name, config);\n if (result.error) {\n this._logger.warn(`server failed to connect after reload`, {\n component: \"reload\", server: name, error: result.error,\n });\n }\n }\n\n // 4. Update metadata-only servers (policy changes handled separately via PolicyEngine.update)\n for (const { name, config } of diff.servers.updated) {\n this._logger.info(`updating metadata`, { component: \"reload\", server: name });\n const category = config._bridge?.category;\n if (category) {\n this._toolRegistry.setCategoryForSource(name, category);\n } else {\n this._toolRegistry.removeCategoryForSource(name);\n }\n }\n\n this._config = newConfig;\n }\n\n restartHealthChecks(interval: number): void {\n this.stopHealthChecks();\n this._healthCheckInterval = interval;\n this.startHealthChecks();\n }\n\n getClient(name: string): UpstreamClient | undefined {\n return this._clients.get(name);\n }\n\n getStatuses(): UpstreamStatus[] {\n return Array.from(this._clients.values()).map((client) => {\n const tracking = this._healthTracking.get(client.name);\n return {\n name: client.name,\n status: client.status,\n health: tracking?.health ?? \"unknown\",\n toolCount: client.tools.length,\n lastPingAt: tracking?.lastPingAt,\n };\n });\n }\n\n startHealthChecks(): void {\n if (this._healthCheckInterval <= 0) return;\n if (this._healthTimer) return;\n\n this._logger.debug(\"starting health checks\", {\n component: \"health\",\n interval: this._healthCheckInterval,\n });\n\n this._healthTimer = setInterval(() => {\n this._runHealthCheck();\n }, this._healthCheckInterval * 1000);\n }\n\n stopHealthChecks(): void {\n if (this._healthTimer) {\n clearInterval(this._healthTimer);\n this._healthTimer = undefined;\n }\n }\n\n private _runHealthCheck(): void {\n for (const [name, client] of this._clients) {\n if (client.status !== \"connected\") continue;\n if (this._pingsInFlight.has(name)) continue;\n\n let tracking = this._healthTracking.get(name);\n if (!tracking) {\n tracking = { consecutiveFailures: 0, health: \"unknown\" };\n this._healthTracking.set(name, tracking);\n }\n\n this._pingsInFlight.add(name);\n\n client.ping(this._pingTimeoutMs).then(\n () => {\n this._pingsInFlight.delete(name);\n const t = this._healthTracking.get(name);\n if (!t) return;\n const wasUnhealthy = t.health === \"unhealthy\";\n t.consecutiveFailures = 0;\n t.lastPingAt = Date.now();\n t.health = \"healthy\";\n if (wasUnhealthy) {\n this._logger.info(\"recovered\", {\n component: \"health\",\n server: name,\n });\n }\n },\n (err) => {\n this._pingsInFlight.delete(name);\n const t = this._healthTracking.get(name);\n if (!t) return;\n t.consecutiveFailures++;\n t.health = \"unhealthy\";\n\n this._logger.warn(\"ping failed\", {\n component: \"health\",\n server: name,\n error: err instanceof Error ? err.message : String(err),\n failures: t.consecutiveFailures,\n });\n\n if (t.consecutiveFailures >= this._unhealthyThreshold) {\n this._logger.error(\n `${t.consecutiveFailures} consecutive ping failures, reconnecting`,\n { component: \"health\", server: name },\n );\n t.consecutiveFailures = 0;\n t.health = \"unknown\";\n client.reconnect().catch((reconnectErr) => {\n this._logger.error(\"reconnect failed\", {\n component: \"health\",\n server: name,\n error:\n reconnectErr instanceof Error\n ? reconnectErr.message\n : String(reconnectErr),\n });\n });\n }\n },\n );\n }\n }\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir, platform } from \"node:os\";\nimport { APP_NAME, CREDENTIALS_DIR } from \"../constants.js\";\nimport { CredentialError } from \"./errors.js\";\n\nconst SERVICE = APP_NAME;\nconst ACCOUNT = \"master-key\";\nconst EXEC_TIMEOUT = 10_000;\n\nexport interface KeychainAdapter {\n /** Returns the key, or undefined if no key has been stored yet. */\n getKey(): Promise<Buffer | undefined>;\n setKey(key: Buffer): Promise<void>;\n deleteKey(): Promise<void>;\n}\n\n// --- Helpers ---\n\nfunction execCommand(\n command: string,\n args: string[],\n): Promise<string> {\n return new Promise((resolve, reject) => {\n execFile(\n command,\n args,\n { timeout: EXEC_TIMEOUT },\n (error, stdout, stderr) => {\n if (error) {\n reject(\n new CredentialError(\n `${command} failed: ${stderr?.trim() || error.message}`,\n { cause: error },\n ),\n );\n return;\n }\n resolve(stdout.trim());\n },\n );\n });\n}\n\nfunction spawnWithStdin(\n command: string,\n args: string[],\n stdin: string,\n): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, { timeout: EXEC_TIMEOUT });\n let stdout = \"\";\n let stderr = \"\";\n let settled = false;\n\n child.stdout.on(\"data\", (data: Buffer) => {\n stdout += data.toString();\n });\n child.stderr.on(\"data\", (data: Buffer) => {\n stderr += data.toString();\n });\n child.on(\"error\", (error) => {\n if (settled) return;\n settled = true;\n reject(\n new CredentialError(`${command} failed: ${error.message}`, {\n cause: error,\n }),\n );\n });\n child.on(\"close\", (code) => {\n if (settled) return;\n settled = true;\n if (code !== 0) {\n reject(\n new CredentialError(\n `${command} exited with code ${code}: ${stderr.trim()}`,\n ),\n );\n return;\n }\n resolve(stdout.trim());\n });\n\n // Suppress EPIPE if child exits before we finish writing.\n // The actual exit code/error is handled by the 'close'/'error' listeners.\n child.stdin.on(\"error\", () => {});\n child.stdin.write(stdin);\n child.stdin.end();\n });\n}\n\nfunction parseHexKey(hex: string, source: string): Buffer {\n const cleaned = hex.trim();\n if (!/^[0-9a-fA-F]{64}$/.test(cleaned)) {\n throw new CredentialError(\n `Invalid master key from ${source}: expected exactly 64 hex characters (32 bytes), got ${cleaned.length}`,\n );\n }\n return Buffer.from(cleaned, \"hex\");\n}\n\n// --- EnvKeychain ---\n\nexport class EnvKeychain implements KeychainAdapter {\n private readonly key: Buffer;\n\n constructor(hex: string) {\n this.key = parseHexKey(hex, \"MCP_BRIDGE_MASTER_KEY\");\n }\n\n async getKey(): Promise<Buffer> {\n return this.key;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async setKey(key: Buffer): Promise<void> {\n throw new CredentialError(\n \"Cannot set master key when using MCP_BRIDGE_MASTER_KEY environment variable\",\n );\n }\n\n async deleteKey(): Promise<void> {\n throw new CredentialError(\n \"Cannot delete master key when using MCP_BRIDGE_MASTER_KEY environment variable\",\n );\n }\n}\n\n// --- MacKeychain ---\n\nexport class MacKeychain implements KeychainAdapter {\n async getKey(): Promise<Buffer | undefined> {\n try {\n const hex = await execCommand(\"security\", [\n \"find-generic-password\",\n \"-s\",\n SERVICE,\n \"-a\",\n ACCOUNT,\n \"-w\",\n ]);\n return parseHexKey(hex, \"macOS keychain\");\n } catch (err) {\n // security exits 44 with \"could not be found\" when item doesn't exist\n if (err instanceof CredentialError && /could not be found/i.test(err.message)) {\n return undefined;\n }\n throw err;\n }\n }\n\n async setKey(key: Buffer): Promise<void> {\n const hex = key.toString(\"hex\");\n await execCommand(\"security\", [\n \"add-generic-password\",\n \"-s\",\n SERVICE,\n \"-a\",\n ACCOUNT,\n \"-w\",\n hex,\n \"-U\",\n ]);\n }\n\n async deleteKey(): Promise<void> {\n await execCommand(\"security\", [\n \"delete-generic-password\",\n \"-s\",\n SERVICE,\n \"-a\",\n ACCOUNT,\n ]);\n }\n}\n\n// --- LinuxKeychain ---\n\nexport class LinuxKeychain implements KeychainAdapter {\n async getKey(): Promise<Buffer | undefined> {\n try {\n const hex = await execCommand(\"secret-tool\", [\n \"lookup\",\n \"service\",\n SERVICE,\n \"account\",\n ACCOUNT,\n ]);\n // secret-tool returns empty stdout when key not found (before exiting 1)\n if (!hex) return undefined;\n return parseHexKey(hex, \"secret-tool\");\n } catch (err) {\n // secret-tool exits 1 with empty stderr when key doesn't exist.\n // execCommand formats this as \"secret-tool failed: Command failed: ...\"\n if (err instanceof CredentialError && /secret-tool failed:.*Command failed/i.test(err.message)) {\n return undefined;\n }\n throw err;\n }\n }\n\n async setKey(key: Buffer): Promise<void> {\n const hex = key.toString(\"hex\");\n await spawnWithStdin(\n \"secret-tool\",\n [\n \"store\",\n \"--label\",\n `${APP_NAME} master key`,\n \"service\",\n SERVICE,\n \"account\",\n ACCOUNT,\n ],\n hex,\n );\n }\n\n async deleteKey(): Promise<void> {\n await execCommand(\"secret-tool\", [\n \"clear\",\n \"service\",\n SERVICE,\n \"account\",\n ACCOUNT,\n ]);\n }\n}\n\n// --- WindowsKeychain ---\n\nexport class WindowsKeychain implements KeychainAdapter {\n private get filePath(): string {\n return join(homedir(), CREDENTIALS_DIR, \"master-key.dpapi\");\n }\n\n private escapeSingleQuote(s: string): string {\n return s.replace(/'/g, \"''\");\n }\n\n private encodedCommand(script: string): string[] {\n // -EncodedCommand accepts a Base64-encoded UTF-16LE string, avoiding\n // any injection via interpolated paths or values.\n const encoded = Buffer.from(script, \"utf16le\").toString(\"base64\");\n return [\"-NoProfile\", \"-NonInteractive\", \"-EncodedCommand\", encoded];\n }\n\n async getKey(): Promise<Buffer | undefined> {\n try {\n const script =\n `$bytes = [IO.File]::ReadAllBytes('${this.escapeSingleQuote(this.filePath)}')\\n` +\n `$decrypted = [Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'CurrentUser')\\n` +\n `[BitConverter]::ToString($decrypted).Replace('-','')`;\n const hex = await execCommand(\"powershell\", this.encodedCommand(script));\n return parseHexKey(hex, \"DPAPI\");\n } catch (err) {\n // FileNotFoundException when the DPAPI file doesn't exist yet\n if (err instanceof CredentialError && /Could not find|does not exist|FileNotFound/i.test(err.message)) {\n return undefined;\n }\n throw err;\n }\n }\n\n async setKey(key: Buffer): Promise<void> {\n const dir = join(homedir(), CREDENTIALS_DIR);\n await mkdir(dir, { recursive: true });\n const hex = key.toString(\"hex\");\n const escapedPath = this.escapeSingleQuote(this.filePath);\n const script =\n `$hex = '${hex}'\\n` +\n `$bytes = [byte[]]::new($hex.Length / 2)\\n` +\n `for ($i = 0; $i -lt $bytes.Length; $i++) { $bytes[$i] = [Convert]::ToByte($hex.Substring($i*2, 2), 16) }\\n` +\n `$encrypted = [Security.Cryptography.ProtectedData]::Protect($bytes, $null, 'CurrentUser')\\n` +\n `[IO.File]::WriteAllBytes('${escapedPath}', $encrypted)`;\n await execCommand(\"powershell\", this.encodedCommand(script));\n }\n\n async deleteKey(): Promise<void> {\n const script = `Remove-Item -LiteralPath '${this.escapeSingleQuote(this.filePath)}' -Force -ErrorAction Stop`;\n await execCommand(\"powershell\", this.encodedCommand(script));\n }\n}\n\n// --- Factory ---\n\nexport interface CreateKeychainOptions {\n _adapter?: KeychainAdapter;\n _platform?: NodeJS.Platform;\n}\n\nexport function createKeychainAdapter(\n options?: CreateKeychainOptions,\n): KeychainAdapter {\n if (options?._adapter) {\n return options._adapter;\n }\n\n const envKey = process.env.MCP_BRIDGE_MASTER_KEY;\n if (envKey) {\n return new EnvKeychain(envKey);\n }\n\n const os = options?._platform ?? platform();\n switch (os) {\n case \"darwin\":\n return new MacKeychain();\n case \"linux\":\n return new LinuxKeychain();\n case \"win32\":\n return new WindowsKeychain();\n default:\n throw new CredentialError(`Unsupported platform for keychain: ${os}`);\n }\n}\n","import { randomBytes, createCipheriv, createDecipheriv } from \"node:crypto\";\nimport { access, readFile, writeFile, rename, mkdir } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { CREDENTIALS_DIR, CREDENTIALS_FILENAME } from \"../constants.js\";\nimport { CredentialStoreFileSchema, type Credential, type CredentialStoreFile } from \"./types.js\";\nimport { CredentialError } from \"./errors.js\";\nimport type { KeychainAdapter } from \"./keychain.js\";\n\nconst ALGORITHM = \"aes-256-gcm\";\nconst IV_LENGTH = 12;\nconst AUTH_TAG_LENGTH = 16;\nconst MAX_KEY_LENGTH = 256;\n\nexport interface CredentialStoreOptions {\n keychain: KeychainAdapter;\n filePath?: string;\n}\n\n// Note: CredentialStore is not concurrency-safe. Concurrent read-modify-write\n// cycles (e.g. two `set()` calls in parallel) may lose writes. This is\n// acceptable for CLI usage; callers requiring concurrency should serialize\n// access externally.\n\nexport class CredentialStore {\n private readonly keychain: KeychainAdapter;\n private readonly filePath: string;\n\n constructor(options: CredentialStoreOptions) {\n this.keychain = options.keychain;\n this.filePath =\n options.filePath ??\n join(homedir(), CREDENTIALS_DIR, CREDENTIALS_FILENAME);\n }\n\n async get(key: string): Promise<Credential | undefined> {\n this._validateKey(key);\n if (!await this._storeFileExists()) return undefined;\n const masterKey = await this._getExistingMasterKey();\n const store = await this._readStore(masterKey);\n return Object.hasOwn(store.credentials, key)\n ? store.credentials[key]\n : undefined;\n }\n\n async set(key: string, credential: Credential): Promise<void> {\n this._validateKey(key);\n const masterKey = await this._getOrCreateMasterKey();\n const store = await this._readStore(masterKey);\n store.credentials[key] = credential;\n await this._writeStore(store, masterKey);\n }\n\n async delete(key: string): Promise<boolean> {\n this._validateKey(key);\n if (!await this._storeFileExists()) return false;\n const masterKey = await this._getExistingMasterKey();\n const store = await this._readStore(masterKey);\n if (!Object.hasOwn(store.credentials, key)) {\n return false;\n }\n delete store.credentials[key];\n await this._writeStore(store, masterKey);\n return true;\n }\n\n async list(): Promise<string[]> {\n if (!await this._storeFileExists()) return [];\n const masterKey = await this._getExistingMasterKey();\n const store = await this._readStore(masterKey);\n return Object.keys(store.credentials);\n }\n\n // --- Internal ---\n\n private _validateKey(key: string): void {\n if (!key) {\n throw new CredentialError(\"Credential key must not be empty\");\n }\n if (key === \"__proto__\") {\n throw new CredentialError(\n `Credential key \"${key}\" is reserved and cannot be used`,\n );\n }\n if (key.length > MAX_KEY_LENGTH) {\n throw new CredentialError(\n `Credential key too long: ${key.length} characters (max ${MAX_KEY_LENGTH})`,\n );\n }\n }\n\n private async _storeFileExists(): Promise<boolean> {\n try {\n await access(this.filePath);\n return true;\n } catch {\n return false;\n }\n }\n\n private async _getOrCreateMasterKey(): Promise<Buffer> {\n const existing = await this.keychain.getKey();\n if (existing) return existing;\n const key = randomBytes(32);\n await this.keychain.setKey(key);\n return key;\n }\n\n private async _getExistingMasterKey(): Promise<Buffer> {\n const existing = await this.keychain.getKey();\n if (!existing) {\n throw new CredentialError(\n \"No master key found in keychain — cannot decrypt credential store. \" +\n \"If the keychain was reset, the credential store must be recreated.\",\n );\n }\n return existing;\n }\n\n private _encrypt(data: Buffer, key: Buffer): Buffer {\n const iv = randomBytes(IV_LENGTH);\n const cipher = createCipheriv(ALGORITHM, key, iv);\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);\n const authTag = cipher.getAuthTag();\n return Buffer.concat([iv, encrypted, authTag]);\n }\n\n private _decrypt(blob: Buffer, key: Buffer): Buffer {\n const minLength = IV_LENGTH + AUTH_TAG_LENGTH;\n if (blob.length < minLength) {\n throw new CredentialError(\n \"Credential store file is corrupted: data too short\",\n );\n }\n\n const iv = blob.subarray(0, IV_LENGTH);\n const authTag = blob.subarray(blob.length - AUTH_TAG_LENGTH);\n const ciphertext = blob.subarray(IV_LENGTH, blob.length - AUTH_TAG_LENGTH);\n\n try {\n const decipher = createDecipheriv(ALGORITHM, key, iv);\n decipher.setAuthTag(authTag);\n return Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n } catch (err) {\n throw new CredentialError(\n \"Failed to decrypt credential store: wrong key or corrupted data\",\n { cause: err },\n );\n }\n }\n\n private async _readStore(masterKey: Buffer): Promise<CredentialStoreFile> {\n let raw: Buffer;\n try {\n raw = await readFile(this.filePath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return { version: 1, credentials: {} };\n }\n throw new CredentialError(\n `Failed to read credential store: ${(err as Error).message}`,\n { cause: err },\n );\n }\n\n const decrypted = this._decrypt(raw, masterKey);\n\n let json: unknown;\n try {\n json = JSON.parse(decrypted.toString(\"utf-8\"));\n } catch (err) {\n throw new CredentialError(\n \"Credential store contains invalid JSON\",\n { cause: err },\n );\n }\n\n const result = CredentialStoreFileSchema.safeParse(json);\n if (!result.success) {\n throw new CredentialError(\n \"Credential store has invalid schema\",\n { cause: result.error },\n );\n }\n\n return result.data;\n }\n\n private async _writeStore(store: CredentialStoreFile, masterKey: Buffer): Promise<void> {\n const data = Buffer.from(JSON.stringify(store), \"utf-8\");\n const encrypted = this._encrypt(data, masterKey);\n\n const dir = dirname(this.filePath);\n await mkdir(dir, { recursive: true });\n\n const tmpPath = `${this.filePath}.tmp.${process.pid}`;\n await writeFile(tmpPath, encrypted, { mode: 0o600 });\n await rename(tmpPath, this.filePath);\n }\n}\n"],"mappings":";AAAA,SAAS,eAAe;;;ACAxB,SAAS,SAAS;;;ACAX,IAAM,WAAW;AACjB,IAAM,cAAc;AAEpB,IAAM,kBAAkB,IAAI,QAAQ;AACpC,IAAM,uBAAuB;;;ADC7B,IAAM,mBAAmB,EAAE,KAAK,CAAC,UAAU,SAAS,QAAQ,CAAC;AAI7D,IAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,MAAM,EAAE,QAAQ,QAAQ;AAAA,EACxB,UAAU,EAAE,OAAO;AAAA,EACnB,WAAW,EAAE,OAAO;AAAA,IAClB,eAAe,EAAE,OAAO,EAAE,IAAI;AAAA,IAC9B,OAAO,EAAE,OAAO,EAAE,IAAI;AAAA,EACxB,CAAC;AAAA,EACD,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AACvC,CAAC;AAEM,IAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACpC,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAC3C,CAAC;AAEM,IAAM,2BAA2B,EACrC,OAAO;AAAA,EACN,MAAM,wBAAwB,SAAS;AAAA,EACvC,YAAY,iBAAiB,SAAS;AAAA,EACtC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,gBAAgB,EAAE,SAAS;AAAA,EACvD,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,WAAW,sBAAsB,SAAS;AAC5C,CAAC,EACA,OAAO;AAIH,IAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,SAAS,EAAE,OAAO;AAAA,EAClB,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACnC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EAC/C,SAAS,yBAAyB,SAAS;AAC7C,CAAC;AAEM,IAAM,yBAAyB,EAAE,OAAO;AAAA,EAC7C,MAAM,EACH,KAAK,CAAC,mBAAmB,QAAQ,kBAAkB,KAAK,CAAC,EACzD,QAAQ,iBAAiB;AAAA,EAC5B,KAAK,EAAE,OAAO,EAAE,IAAI;AAAA,EACpB,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACnD,SAAS,yBAAyB,SAAS;AAC7C,CAAC;AAGM,IAAM,qBAAqB,EAAE,MAAM;AAAA,EACxC;AAAA,EACA;AACF,CAAC;AAIM,IAAM,2BAA2B,EACrC,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,KAAK,EAAE,QAAQ,KAAK;AAAA,EACtD,UAAU,EACP,KAAK,CAAC,SAAS,QAAQ,QAAQ,OAAO,CAAC,EACvC,QAAQ,MAAM;AAAA,EACjB,WAAW,EAAE,KAAK,CAAC,QAAQ,MAAM,CAAC,EAAE,QAAQ,MAAM;AAAA,EAClD,wBAAwB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,GAAI;AAAA,EAChE,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE;AAAA,EACzD,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,GAAG;AAAA,EACpD,qBAAqB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,EAAE;AAAA,EACvD,YAAY,iBAAiB,QAAQ,QAAQ;AAC/C,CAAC,EACA,OAAO;AAIH,IAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AAAA,EAC/D,oBAAoB,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,EAAE,SAAS;AAAA,EACtE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,EAAE,SAAS;AAAA,EAC3D,iBAAiB,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,EAAE,SAAS;AAAA,EACnE,SAAS,yBAAyB;AAAA,IAChC,yBAAyB,MAAM,CAAC,CAAC;AAAA,EACnC;AACF,CAAC;AA0BM,SAAS,iBACd,QAC8B;AAC9B,QAAM,SAAuC,CAAC;AAG9C,aAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AAC9D,QAAI,cAAc,MAAM,GAAG;AACzB,YAAM,SAAS,CAAC,OAAO,SAAS,GAAI,OAAO,QAAQ,CAAC,CAAE;AACtD,UAAI,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,CAAC,GAAG;AAC5C;AAAA,MACF;AAAA,IACF;AACA,WAAO,IAAI,IAAI;AAAA,EACjB;AAGA,MAAI,OAAO,iBAAiB;AAC1B,eAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,eAAe,GAAG;AACnE,UAAI,cAAc,MAAM,GAAG;AACzB,cAAM,SAAS,CAAC,OAAO,SAAS,GAAI,OAAO,QAAQ,CAAC,CAAE;AACtD,YAAI,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,CAAC,GAAG;AAC5C;AAAA,QACF;AAAA,MACF;AACA,aAAO,IAAI,IAAI;AAAA,IACjB;AAAA,EACF;AAGA,MAAI,OAAO,SAAS;AAClB,WAAO,OAAO,QAAQ,OAAO,OAAO;AAAA,EACtC;AAGA,MAAI,OAAO,oBAAoB;AAC7B,WAAO,OAAO,QAAQ,OAAO,kBAAkB;AAAA,EACjD;AAEA,SAAO;AACT;AAQO,SAAS,cACd,QAC6B;AAC7B,SAAO,aAAa;AACtB;;;AEnKA,SAAS,gBAAgB;AASlB,IAAM,cAAN,cAA0B,MAAM;AAAA,EAC5B;AAAA,EAET,YAAY,SAAiB,SAAwB,CAAC,GAAG;AACvD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AACF;AAEA,SAAS,gBACP,OACA,aAAuB,CAAC,GACT;AACf,QAAM,WAAW,CAAC,GAAG,YAAY,GAAG,MAAM,KAAK,IAAI,MAAM,CAAC;AAG1D,MAAI,MAAM,SAAS,mBAAmB,YAAY,OAAO;AACvD,UAAM,cAAc,MAAM;AAC1B,WAAO,YAAY;AAAA,MAAQ,CAAC,iBAC1B,aAAa,QAAQ,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,SAAO,CAAC,EAAE,MAAM,SAAS,KAAK,GAAG,GAAG,SAAS,MAAM,QAAQ,CAAC;AAC9D;AAEA,SAAS,gBAAgB,OAAkC;AACzD,SAAO,MAAM,OAAO,QAAQ,CAAC,UAAU,gBAAgB,KAAK,CAAC;AAC/D;AAMO,SAAS,kBAAkB,SAAqC;AACrE,MAAI,SAAS,YAAY;AACvB,WAAO,QAAQ;AAAA,EACjB;AAEA,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,SAAS;AACX,WAAO;AAAA,EACT;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAEA,eAAsB,WACpB,SACuB;AACvB,QAAM,aAAa,kBAAkB,OAAO;AAE5C,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,SAAS,YAAY,OAAO;AAAA,EAC1C,SAAS,KAAK;AACZ,UAAM,OAAQ,IAA8B;AAC5C,QAAI,SAAS,UAAU;AACrB,YAAM,IAAI,YAAY,0BAA0B,UAAU,EAAE;AAAA,IAC9D;AACA,UAAM,IAAI;AAAA,MACR,+BAA+B,UAAU,KAAK,QAAQ,eAAe;AAAA,IACvE;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACF,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,UAAM,IAAI,YAAY,gCAAgC,UAAU,EAAE;AAAA,EACpE;AAEA,QAAM,SAAS,mBAAmB,UAAU,IAAI;AAChD,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI;AAAA,MACR;AAAA,MACA,gBAAgB,OAAO,KAAK;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO,OAAO;AAChB;;;AC7FA,SAAS,KAAAA,UAAS;;;ACmBlB,SAAS,iBAAiB,QAA+C;AACvE,MAAI,cAAc,MAAM,GAAG;AACzB,WAAO;AAAA,MACL,SAAS,OAAO;AAAA,MAChB,MAAM,OAAO;AAAA,MACb,KAAK,OAAO;AAAA,IACd;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,IACZ,SAAS,OAAO;AAAA,EAClB;AACF;AAGA,SAAS,gBAAgB,OAAwB;AAC/C,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,MAAM,IAAI,eAAe,EAAE,KAAK,GAAG,IAAI;AAAA,EACtD;AACA,QAAM,OAAO,OAAO,KAAK,KAAgC,EAAE,KAAK;AAChE,SACE,MACA,KACG;AAAA,IACC,CAAC,MACC,KAAK,UAAU,CAAC,IAChB,MACA,gBAAiB,MAAkC,CAAC,CAAC;AAAA,EACzD,EACC,KAAK,GAAG,IACX;AAEJ;AAEA,SAAS,UAAU,GAAY,GAAqB;AAClD,SAAO,gBAAgB,CAAC,MAAM,gBAAgB,CAAC;AACjD;AAEO,SAAS,YAAY,WAAyB,WAAqC;AACxF,QAAM,aAAa,iBAAiB,SAAS;AAC7C,QAAM,aAAa,iBAAiB,SAAS;AAE7C,QAAM,WAAW,IAAI,IAAI,OAAO,KAAK,UAAU,CAAC;AAChD,QAAM,WAAW,IAAI,IAAI,OAAO,KAAK,UAAU,CAAC;AAEhD,QAAM,QAAwC,CAAC;AAC/C,QAAM,UAAoB,CAAC;AAC3B,QAAM,YAAgD,CAAC;AACvD,QAAM,UAA4C,CAAC;AAEnD,aAAW,QAAQ,UAAU;AAC3B,QAAI,CAAC,SAAS,IAAI,IAAI,GAAG;AACvB,YAAM,KAAK,EAAE,MAAM,QAAQ,WAAW,IAAI,EAAE,CAAC;AAAA,IAC/C;AAAA,EACF;AAEA,aAAW,QAAQ,UAAU;AAC3B,QAAI,CAAC,SAAS,IAAI,IAAI,GAAG;AACvB,cAAQ,KAAK,IAAI;AAAA,IACnB;AAAA,EACF;AAEA,aAAW,QAAQ,UAAU;AAC3B,QAAI,CAAC,SAAS,IAAI,IAAI,EAAG;AACzB,UAAM,SAAS,WAAW,IAAI;AAC9B,UAAM,SAAS,WAAW,IAAI;AAE9B,QAAI,CAAC,UAAU,iBAAiB,MAAM,GAAG,iBAAiB,MAAM,CAAC,GAAG;AAClE,gBAAU,KAAK,EAAE,MAAM,QAAQ,OAAO,CAAC;AAAA,IACzC,WAAW,CAAC,UAAU,OAAO,SAAS,OAAO,OAAO,GAAG;AACrD,cAAQ,KAAK,EAAE,MAAM,QAAQ,OAAO,CAAC;AAAA,IACvC;AAAA,EACF;AAGA,QAAM,KAAK,UAAU;AACrB,QAAM,KAAK,UAAU;AACrB,QAAM,SAA+B,EAAE,iBAAiB,CAAC,EAAE;AAE3D,MAAI,GAAG,aAAa,GAAG,SAAU,QAAO,WAAW,GAAG;AACtD,MAAI,GAAG,wBAAwB,GAAG,oBAAqB,QAAO,sBAAsB,GAAG;AACvF,MAAI,GAAG,eAAe,GAAG,WAAY,QAAO,aAAa,GAAG;AAE5D,QAAM,gBAAgB,CAAC,QAAQ,aAAa,0BAA0B,qBAAqB,aAAa;AACxG,aAAW,SAAS,eAAe;AACjC,QAAI,GAAG,KAAK,MAAM,GAAG,KAAK,GAAG;AAC3B,aAAO,gBAAgB,KAAK,KAAK;AAAA,IACnC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,EAAE,OAAO,SAAS,WAAW,QAAQ;AAAA,IAC9C;AAAA,EACF;AACF;;;ACtHA,SAAS,aAA6B;AACtC,SAAS,SAAS,gBAAgB;;;ACUlC,IAAM,cAAwC;AAAA,EAC5C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAOA,SAAS,IAAI,GAAW,OAAuB;AAC7C,SAAO,OAAO,CAAC,EAAE,SAAS,OAAO,GAAG;AACtC;AAEA,SAAS,aAAqB;AAC5B,QAAM,IAAI,oBAAI,KAAK;AACnB,SAAO,GAAG,IAAI,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,WAAW,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,WAAW,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,gBAAgB,GAAG,CAAC,CAAC;AACnH;AAEA,SAAS,WACP,OACA,SACA,SACQ;AACR,QAAM,MAAM,MAAM,YAAY,EAAE,OAAO,CAAC;AACxC,QAAM,YAAY,QAAQ;AAC1B,QAAM,SAAS,QAAQ;AACvB,MAAI,SAAS;AACb,MAAI,aAAa,QAAQ;AACvB,aAAS,IAAI,SAAS,IAAI,MAAM;AAAA,EAClC,WAAW,WAAW;AACpB,aAAS,IAAI,SAAS;AAAA,EACxB,WAAW,QAAQ;AACjB,aAAS,IAAI,MAAM;AAAA,EACrB;AAGA,QAAM,QAAiC,CAAC;AACxC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,OAAO,GAAG;AAC5C,QAAI,MAAM,eAAe,MAAM,YAAY,MAAM,QAAW;AAC1D,YAAM,CAAC,IAAI;AAAA,IACb;AAAA,EACF;AACA,QAAM,SAAS,OAAO,KAAK,KAAK,EAAE,SAAS,IACvC,MAAM,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,MAAM,YAAY,MAAM,OAAO,KAAK,UAAU,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG,IACnI;AAEJ,QAAM,cAAc,QAAQ,QAAQ,OAAO,KAAK;AAChD,SAAO,GAAG,WAAW,CAAC,IAAI,GAAG,IAAI,MAAM,GAAG,WAAW,GAAG,MAAM;AAAA;AAChE;AAEA,SAAS,WACP,OACA,SACA,SACQ;AACR,SAAO,KAAK,UAAU;AAAA,IACpB,GAAG;AAAA,IACH,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC7B;AAAA,IACA,KAAK;AAAA,EACP,CAAC,IAAI;AACP;AAEA,IAAM,aAAN,MAAM,YAA6B;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EAER,YACE,SACA,iBAA0C,CAAC,GAC3C,QACA;AACA,SAAK,UAAU,UAAU,EAAE,WAAW,YAAY,QAAQ,KAAK,EAAE;AACjE,SAAK,UAAU,QAAQ;AACvB,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,MAAM,SAAiB,SAAyC;AAC9D,SAAK,KAAK,SAAS,SAAS,OAAO;AAAA,EACrC;AAAA,EAEA,KAAK,SAAiB,SAAyC;AAC7D,SAAK,KAAK,QAAQ,SAAS,OAAO;AAAA,EACpC;AAAA,EAEA,KAAK,SAAiB,SAAyC;AAC7D,SAAK,KAAK,QAAQ,SAAS,OAAO;AAAA,EACpC;AAAA,EAEA,MAAM,SAAiB,SAAyC;AAC9D,SAAK,KAAK,SAAS,SAAS,OAAO;AAAA,EACrC;AAAA,EAEA,SAAS,OAAuB;AAC9B,SAAK,QAAQ,YAAY,YAAY,KAAK;AAAA,EAC5C;AAAA,EAEA,MAAM,gBAAiD;AACrD,WAAO,IAAI;AAAA,MACT,EAAE,OAAO,SAAS,QAAQ,KAAK,QAAQ;AAAA,MACvC,EAAE,GAAG,KAAK,iBAAiB,GAAG,eAAe;AAAA,MAC7C,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEQ,KACN,OACA,SACA,SACM;AACN,QAAI,YAAY,KAAK,IAAI,KAAK,QAAQ,UAAW;AACjD,UAAM,SAAS,UACX,EAAE,GAAG,KAAK,iBAAiB,GAAG,QAAQ,IACtC,KAAK;AACT,UAAM,OACJ,KAAK,YAAY,SACb,WAAW,OAAO,SAAS,MAAM,IACjC,WAAW,OAAO,SAAS,MAAM;AACvC,YAAQ,OAAO,MAAM,IAAI;AAAA,EAC3B;AACF;AAEO,SAAS,aAAa,SAAsC;AACjE,SAAO,IAAI,WAAW,OAAO;AAC/B;AAGO,SAAS,mBAA2B;AACzC,QAAM,OAAO,MAAM;AAAA,EAAC;AACpB,QAAM,SAAiB;AAAA,IACrB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,MAAM;AAAA,IACb,UAAU;AAAA,EACZ;AACA,SAAO;AACT;;;AD5IO,IAAM,gBAAN,MAAoB;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,iBAAiB;AAAA,EAEzB,YAAY,SAA+B;AACzC,SAAK,cAAc,QAAQ;AAC3B,SAAK,cAAc,QAAQ,cAAc;AACzC,SAAK,UAAU,QAAQ,UAAU,iBAAiB;AAAA,EACpD;AAAA,EAEA,MACE,UACA,eACM;AACN,QAAI,KAAK,SAAU;AAEnB,SAAK,YAAY;AAEjB,QAAI,eAAe;AACjB,WAAK,YAAY,KAAK,UAAU,aAAa;AAAA,IAC/C;AAEA,SAAK,QAAQ,MAAM,wBAAwB;AAAA,MACzC,WAAW;AAAA,MACX,MAAM,KAAK;AAAA,IACb,CAAC;AAID,UAAM,MAAM,QAAQ,KAAK,WAAW;AACpC,UAAM,WAAW,SAAS,KAAK,WAAW;AAE1C,SAAK,WAAW,MAAM,KAAK,CAAC,WAAW,gBAAgB;AAErD,UAAI,gBAAgB,YAAa,cAAc,YAAY,CAAC,aAAc;AACxE,aAAK,gBAAgB;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,QAAQ;AACf,mBAAa,KAAK,MAAM;AACxB,WAAK,SAAS;AAAA,IAChB;AACA,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,MAAM;AACpB,WAAK,WAAW;AAAA,IAClB;AACA,SAAK,YAAY;AACjB,SAAK,aAAa;AAClB,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEQ,kBAAwB;AAC9B,QAAI,KAAK,OAAQ,cAAa,KAAK,MAAM;AACzC,SAAK,SAAS,WAAW,MAAM;AAC7B,WAAK,SAAS;AACd,WAAK,QAAQ;AAAA,IACf,GAAG,KAAK,WAAW;AAAA,EACrB;AAAA,EAEQ,UAAgB;AACtB,QAAI,KAAK,YAAY;AACnB,WAAK,iBAAiB;AACtB;AAAA,IACF;AACA,SAAK,aAAa;AAElB,eAAW,EAAE,YAAY,KAAK,YAAY,CAAC,EAAE;AAAA,MAC3C,OAAO,WAAW;AAChB,cAAM,OAAO,KAAK,UAAU,MAAM;AAClC,YAAI,SAAS,KAAK,WAAW;AAC3B,eAAK,QAAQ,MAAM,qCAAqC;AAAA,YACtD,WAAW;AAAA,UACb,CAAC;AACD,eAAK,cAAc;AACnB;AAAA,QACF;AACA,aAAK,QAAQ,KAAK,6BAA6B;AAAA,UAC7C,WAAW;AAAA,QACb,CAAC;AACD,YAAI;AACF,gBAAM,KAAK,YAAY,MAAM;AAC7B,eAAK,YAAY;AAAA,QACnB,SAAS,KAAK;AACZ,eAAK,QAAQ,MAAM,yBAAyB;AAAA,YAC1C,WAAW;AAAA,YACX,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,UACxD,CAAC;AAAA,QACH;AACA,aAAK,cAAc;AAAA,MACrB;AAAA,MACA,CAAC,QAAQ;AACP,aAAK,QAAQ,KAAK,2BAA2B;AAAA,UAC3C,WAAW;AAAA,UACX,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,QACxD,CAAC;AACD,aAAK,cAAc;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAsB;AAC5B,SAAK,aAAa;AAClB,QAAI,KAAK,gBAAgB;AACvB,WAAK,iBAAiB;AACtB,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AACF;;;AElIA,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACEA,IAAM,eAAN,MAAmB;AAAA,EAChB,QAAQ,oBAAI,IAA4B;AAAA,EACxC,cAAc,oBAAI,IAAyB;AAAA,EAC3C,mBAAmB,oBAAI,IAAoB;AAAA,EAC3C,YAAY,oBAAI,IAA6B;AAAA,EAErD,YAAoB;AAClB,WAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EAC1D;AAAA,EAEA,sBAAwC;AACtC,WAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC;AAAA,EACvC;AAAA,EAEA,cAAqD;AACnD,UAAM,SAAgD,CAAC;AACvD,eAAW,CAAC,MAAM,SAAS,KAAK,KAAK,aAAa;AAChD,aAAO,KAAK,EAAE,MAAM,WAAW,UAAU,KAAK,CAAC;AAAA,IACjD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,MAA0C;AAChD,WAAO,KAAK,MAAM,IAAI,IAAI;AAAA,EAC5B;AAAA,EAEA,qBAAqB,QAAgB,UAAwB;AAC3D,SAAK,iBAAiB,IAAI,QAAQ,QAAQ;AAAA,EAC5C;AAAA,EAEA,qBAAqB,QAAoC;AACvD,WAAO,KAAK,iBAAiB,IAAI,MAAM;AAAA,EACzC;AAAA,EAEA,wBAAwB,QAAsB;AAC5C,SAAK,iBAAiB,OAAO,MAAM;AAAA,EACrC;AAAA,EAEA,kBAAkB,QAAgB,OAAqB;AACrD,UAAM,WAAW,KAAK,YAAY,IAAI,MAAM;AAC5C,QAAI,UAAU;AACZ,iBAAW,QAAQ,UAAU;AAC3B,aAAK,MAAM,OAAO,IAAI;AAAA,MACxB;AAAA,IACF;AAEA,UAAM,WAAW,oBAAI,IAAY;AACjC,eAAW,QAAQ,OAAO;AACxB,WAAK,MAAM,IAAI,KAAK,MAAM,EAAE,QAAQ,KAAK,CAAC;AAC1C,eAAS,IAAI,KAAK,IAAI;AAAA,IACxB;AACA,SAAK,YAAY,IAAI,QAAQ,QAAQ;AAErC,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,aAAa,QAAsB;AACjC,UAAM,QAAQ,KAAK,YAAY,IAAI,MAAM;AACzC,QAAI,CAAC,SAAS,MAAM,SAAS,GAAG;AAC9B,WAAK,YAAY,OAAO,MAAM;AAC9B;AAAA,IACF;AAEA,QAAI,UAAU;AACd,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,MAAM,IAAI,IAAI;AACnC,UAAI,WAAW,QAAQ,WAAW,QAAQ;AACxC,aAAK,MAAM,OAAO,IAAI;AACtB,kBAAU;AAAA,MACZ;AAAA,IACF;AACA,SAAK,YAAY,OAAO,MAAM;AAC9B,SAAK,iBAAiB,OAAO,MAAM;AAEnC,QAAI,SAAS;AACX,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA,EAEA,UAAU,UAA+C;AACvD,SAAK,UAAU,IAAI,QAAQ;AAC3B,WAAO,MAAM;AACX,WAAK,UAAU,OAAO,QAAQ;AAAA,IAChC;AAAA,EACF;AAAA,EAEQ,SAAe;AACrB,eAAW,YAAY,KAAK,WAAW;AACrC,UAAI;AACF,iBAAS;AAAA,MACX,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;;;ACtGO,IAAM,sBAAsB;AAK5B,SAAS,cAAc,QAAgB,MAAkB;AAC9D,SAAO,EAAE,GAAG,MAAM,MAAM,GAAG,MAAM,GAAG,mBAAmB,GAAG,KAAK,IAAI,GAAG;AACxE;AAMO,SAAS,oBACd,MACkD;AAClD,QAAM,MAAM,KAAK,QAAQ,mBAAmB;AAC5C,MAAI,QAAQ,GAAI,QAAO;AACvB,SAAO;AAAA,IACL,QAAQ,KAAK,MAAM,GAAG,GAAG;AAAA,IACzB,UAAU,KAAK,MAAM,MAAM,oBAAoB,MAAM;AAAA,EACvD;AACF;;;ACxBA,OAAO,gBAAgB;AA0DvB,IAAM,YAAY;AAClB,IAAM,gBAAgB;AACtB,IAAM,eAAe;AAErB,IAAM,gBAAgB;AAEtB,SAAS,WAAW,OAA8B;AAEhD,MAAI;AACJ,MAAI,QAAQ;AAEZ,MAAI,MAAM,WAAW,QAAQ,GAAG;AAC9B,cAAU,MAAM,MAAM,CAAC;AAAA,EACzB,OAAO;AACL,UAAM,QAAQ,wBAAwB,KAAK,KAAK;AAChD,QAAI,CAAC,MAAO,QAAO;AACnB,cAAU,MAAM,CAAC;AACjB,YAAQ,MAAM,CAAC;AAAA,EACjB;AAEA,MAAI,CAAC,WAAW,QAAQ,SAAS,cAAe,QAAO;AAEvD,MAAI;AAGF,QAAI;AACF,aAAO,IAAI,OAAO,SAAS,QAAQ,GAAG;AAAA,IACxC,QAAQ;AACN,aAAO,IAAI,OAAO,SAAS,KAAK;AAAA,IAClC;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,GAAgB,GAAyB;AAC1D,MAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,aAAW,QAAQ,GAAG;AACpB,QAAI,CAAC,EAAE,IAAI,IAAI,EAAG,QAAO;AAAA,EAC3B;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,OAAe,SAA0B;AACrE,QAAM,QAAQ,WAAW,OAAO;AAChC,MAAI,MAAO,QAAO,MAAM,KAAK,KAAK;AAClC,SAAO,MAAM,YAAY,EAAE,WAAW,QAAQ,YAAY,CAAC;AAC7D;AAEO,IAAM,mBAAmB;AACzB,IAAM,gBAAgB;AAEtB,IAAM,uBAA6B;AAAA,EACxC,MAAM;AAAA,EACN,aAAa;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAAA,EACX,aAAa;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,MACV,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,YACV,MAAM;AAAA,cACJ,MAAM;AAAA,cACN,aACE;AAAA,YAGJ;AAAA,YACA,UAAU;AAAA,cACR,MAAM;AAAA,cACN,aACE;AAAA,YAGJ;AAAA,YACA,UAAU;AAAA,cACR,MAAM;AAAA,cACN,aACE;AAAA,YAEJ;AAAA,YACA,cAAc;AAAA,cACZ,MAAM;AAAA,cACN,aACE;AAAA,YAGJ;AAAA,YACA,OAAO;AAAA,cACL,MAAM;AAAA,cACN,aAAa,0DAA0D,aAAa,SAAS,SAAS;AAAA,YACxG;AAAA,YACA,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAAA,QACA,aACE;AAAA,MAGJ;AAAA,IACF;AAAA,IACA,UAAU,CAAC,SAAS;AAAA,EACtB;AACF;AAEO,IAAM,oBAA0B;AAAA,EACrC,MAAM;AAAA,EACN,aAAa;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAAA,EACX,aAAa;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,MACV,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA,WAAW;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,UAAU,CAAC,MAAM;AAAA,EACnB;AACF;AAEO,IAAM,oBAAN,MAAwB;AAAA,EACrB;AAAA,EACA;AAAA,EACA,eAAe,oBAAI,IAAyB;AAAA,EAC5C,eAAe,oBAAI,IAAY;AAAA,EAC/B,YAAY,oBAAI,IAAiC;AAAA,EACjD;AAAA,EACA;AAAA,EAER,YAAY,UAAwB,cAA6B;AAC/D,SAAK,WAAW;AAChB,SAAK,eAAe;AACpB,SAAK,QAAQ,KAAK,YAAY;AAC9B,SAAK,aAAa;AAClB,SAAK,sBAAsB,KAAK,SAAS,UAAU,MAAM;AACvD,WAAK,aAAa;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEQ,cAAuC;AAC7C,WAAO,IAAI,WAAwB;AAAA,MACjC,QAAQ,CAAC,QAAQ,gBAAgB,eAAe,QAAQ;AAAA,MACxD,aAAa,CAAC,QAAQ,gBAAgB,eAAe,UAAU,UAAU;AAAA,MACzE,eAAe;AAAA,QACb,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,aAAa,GAAG,QAAQ,IAAI;AAAA,QAC/D,QAAQ,CAAC,SAAS,KAAK,UAAU;AAAA,QACjC,OAAO,CAAC,SAAU,KAAK,UAAU,IAAI,MAAM;AAAA,QAC3C,aAAa;AAAA,MACf;AAAA,MACA,UAAU,CAAC,SAAS,KAAK,MAAM,YAAY,EAAE,OAAO,OAAO;AAAA,IAC7D,CAAC;AAAA,EACH;AAAA,EAEQ,eAAqB;AAC3B,SAAK,MAAM,UAAU;AACrB,SAAK,aAAa,MAAM;AAExB,UAAM,aAAa,KAAK,SAAS,oBAAoB;AACrD,eAAW,EAAE,QAAQ,KAAK,KAAK,YAAY;AACzC,YAAM,SAAS,oBAAoB,KAAK,IAAI;AAC5C,YAAM,eAAe,QAAQ,YAAY,KAAK;AAC9C,YAAM,WAAW,KAAK,SAAS,qBAAqB,MAAM,KAAK;AAE/D,YAAM,MAAmB;AAAA,QACvB,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX;AAAA,QACA,aAAa,KAAK,eAAe;AAAA,QACjC;AAAA,QACA;AAAA,MACF;AACA,WAAK,aAAa,IAAI,KAAK,MAAM,GAAG;AACpC,WAAK,MAAM,IAAI,GAAG;AAAA,IACpB;AAGA,QAAI,SAAS;AACb,eAAW,QAAQ,KAAK,cAAc;AACpC,UAAI,CAAC,KAAK,aAAa,IAAI,IAAI,GAAG;AAChC,aAAK,aAAa,OAAO,IAAI;AAC7B,iBAAS;AAAA,MACX;AAAA,IACF;AAEA,QAAI,QAAQ;AACV,WAAK,0BAA0B;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,OAAO,QAAgD;AACrD,UAAM,UAAU,OAAO;AAEvB,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AACpC,aAAO,EAAE,SAAS,CAAC,EAAE;AAAA,IACvB;AAGA,UAAM,mBAAmB,oBAAI,IAAoB;AACjD,eAAW,OAAO,KAAK,aAAa,OAAO,GAAG;AAC5C,uBAAiB,IAAI,IAAI,SAAS,iBAAiB,IAAI,IAAI,MAAM,KAAK,KAAK,CAAC;AAAA,IAC9E;AAEA,UAAM,YAAY,oBAAI,IAAY;AAClC,UAAM,aAAuB,CAAC;AAC9B,UAAM,UAAyB,CAAC;AAEhC,eAAW,SAAS,SAAS;AAC3B,YAAM,gBAAgB,MAAM,SAAS,UAAa,MAAM,SAAS;AACjE,YAAM,oBAAoB,MAAM,aAAa,UAAa,MAAM,aAAa;AAC7E,YAAM,oBAAoB,MAAM,aAAa,UAAa,MAAM,aAAa;AAC7E,YAAM,cAAc,MAAM,iBAAiB;AAG3C,UAAI,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,mBAAmB;AAC9D,gBAAQ,KAAK;AAAA,UACX,WAAW,CAAC;AAAA,UACZ,OAAO;AAAA,UACP,OAAO;AAAA,UACP,WAAW;AAAA,UACX,QAAQ,MAAM,UAAU;AAAA,UACxB,OAAO,MAAM,SAAS;AAAA,QACxB,CAAC;AACD;AAAA,MACF;AAEA,YAAM,QAAQ,KAAK;AAAA,QACjB,KAAK,IAAI,GAAG,MAAM,SAAS,aAAa;AAAA,QACxC;AAAA,MACF;AACA,YAAM,SAAS,KAAK,IAAI,GAAG,MAAM,UAAU,CAAC;AAC5C,YAAM,YAAY,CAAC,iBAAiB,CAAC;AAErC,UAAI,WAAW;AAEb,cAAM,iBAAiB,oBAAI,IAAY;AACvC,mBAAW,OAAO,KAAK,aAAa,OAAO,GAAG;AAC5C,cAAI,qBAAqB,CAAC,qBAAqB,IAAI,QAAQ,MAAM,QAAS,EAAG;AAC7E,cAAI,sBAAsB,CAAC,IAAI,YAAY,CAAC,qBAAqB,IAAI,UAAU,MAAM,QAAS,GAAI;AAClG,yBAAe,IAAI,IAAI,MAAM;AAAA,QAC/B;AAEA,cAAMC,aAA8B,CAAC;AACrC,YAAI,iBAAiB;AACrB,mBAAW,UAAU,gBAAgB;AACnC,gBAAM,QAAQ,iBAAiB,IAAI,MAAM,KAAK;AAC9C,gBAAM,WAAW,KAAK,SAAS,qBAAqB,MAAM;AAC1D,UAAAA,WAAU,KAAK;AAAA,YACb,MAAM;AAAA,YACN,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,YAC/B,YAAY;AAAA,YACZ,OAAO,CAAC;AAAA,UACV,CAAC;AACD,4BAAkB;AAAA,QACpB;AAEA,gBAAQ,KAAK;AAAA,UACX,WAAAA;AAAA,UACA,OAAO;AAAA,UACP,OAAO;AAAA,UACP,WAAW;AAAA,UACX;AAAA,UACA;AAAA,QACF,CAAC;AAED;AAAA,MACF;AAGA,UAAI,iBAAqC;AACzC,UAAI,qBAAyC;AAC7C,UAAI,qBAAyC;AAE7C,UAAI,eAAe;AACjB,yBAAiB,oBAAI,IAAY;AACjC,cAAM,QAAQ,WAAW,MAAM,IAAK;AACpC,YAAI,OAAO;AACT,qBAAW,CAAC,MAAM,GAAG,KAAK,KAAK,cAAc;AAC3C,gBACE,MAAM,KAAK,IAAI,IAAI,KACnB,MAAM,KAAK,IAAI,YAAY,KAC3B,MAAM,KAAK,IAAI,WAAW,KAC1B,MAAM,KAAK,IAAI,MAAM,GACrB;AACA,6BAAe,IAAI,IAAI;AAAA,YACzB;AAAA,UACF;AAAA,QACF,OAAO;AACL,gBAAM,gBAAgB,KAAK,MAAM,OAAO,MAAM,IAAK;AACnD,cAAI,cAAc,SAAS,GAAG;AAC5B,kBAAM,WAAW,cAAc,CAAC,EAAE;AAClC,kBAAM,YAAY,WAAW;AAC7B,uBAAW,KAAK,eAAe;AAC7B,kBAAI,EAAE,SAAS,WAAW;AACxB,+BAAe,IAAI,EAAE,EAAY;AAAA,cACnC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,mBAAmB;AACrB,6BAAqB,oBAAI,IAAY;AACrC,mBAAW,CAAC,MAAM,GAAG,KAAK,KAAK,cAAc;AAC3C,cAAI,qBAAqB,IAAI,QAAQ,MAAM,QAAS,GAAG;AACrD,+BAAmB,IAAI,IAAI;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAEA,UAAI,mBAAmB;AACrB,6BAAqB,oBAAI,IAAY;AACrC,mBAAW,CAAC,MAAM,GAAG,KAAK,KAAK,cAAc;AAC3C,cAAI,IAAI,YAAY,qBAAqB,IAAI,UAAU,MAAM,QAAS,GAAG;AACvE,+BAAmB,IAAI,IAAI;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAGA,YAAM,aAAa,CAAC,gBAAgB,oBAAoB,kBAAkB,EAAE;AAAA,QAC1E,CAAC,MAAwB,MAAM;AAAA,MACjC;AAEA,UAAI;AACJ,UAAI,WAAW,WAAW,GAAG;AAC3B,qBAAa,oBAAI,IAAI;AAAA,MACvB,WAAW,WAAW,WAAW,GAAG;AAClC,qBAAa,WAAW,CAAC;AAAA,MAC3B,OAAO;AAEL,cAAM,SAAS,WAAW,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI;AACxD,qBAAa,oBAAI,IAAY;AAC7B,mBAAW,QAAQ,OAAO,CAAC,GAAG;AAC5B,cAAI,OAAO,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,GAAG;AACpC,uBAAW,IAAI,IAAI;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAGA,YAAM,UAAoB,CAAC;AAC3B,iBAAW,QAAQ,YAAY;AAC7B,YAAI,CAAC,UAAU,IAAI,IAAI,GAAG;AACxB,kBAAQ,KAAK,IAAI;AAAA,QACnB;AAAA,MACF;AAEA,YAAM,QAAQ,QAAQ;AACtB,YAAM,QAAQ,QAAQ,MAAM,QAAQ,SAAS,KAAK;AAGlD,YAAM,cAAc,oBAAI,IAAY;AACpC,UAAI,KAAK,cAAc;AACrB,mBAAW,QAAQ,OAAO;AACxB,gBAAM,SAAS,oBAAoB,IAAI;AACvC,cAAI,UAAU,KAAK,aAAa,cAAc,OAAO,QAAQ,OAAO,QAAQ,MAAM,SAAS;AACzF,wBAAY,IAAI,IAAI;AAAA,UACtB;AAAA,QACF;AAAA,MACF;AAGA,YAAM,mBAAmB,oBAAI,IAAgC;AAC7D,YAAM,gBAA0B,CAAC;AAEjC,iBAAW,QAAQ,OAAO;AACxB,cAAM,MAAM,KAAK,aAAa,IAAI,IAAI;AACtC,YAAI,CAAC,IAAK;AACV,cAAM,aAAa,KAAK,SAAS,QAAQ,IAAI;AAC7C,YAAI,CAAC,WAAY;AAEjB,YAAI,CAAC,iBAAiB,IAAI,IAAI,MAAM,GAAG;AACrC,2BAAiB,IAAI,IAAI,QAAQ,CAAC,CAAC;AACnC,wBAAc,KAAK,IAAI,MAAM;AAAA,QAC/B;AAEA,YAAI,YAAY,IAAI,IAAI,GAAG;AACzB,2BAAiB,IAAI,IAAI,MAAM,EAAG,KAAK;AAAA,YACrC,WAAW;AAAA,YACX,QAAQ,IAAI;AAAA,YACZ,aAAa;AAAA,YACb,cAAc,CAAC;AAAA,YACf,UAAU;AAAA,UACZ,CAAC;AAAA,QACH,OAAO;AACL,2BAAiB,IAAI,IAAI,MAAM,EAAG,KAAK;AAAA,YACrC,WAAW;AAAA,YACX,QAAQ,IAAI;AAAA,YACZ,aAAa,IAAI;AAAA,YACjB,cAAc,WAAW,KAAK;AAAA,UAChC,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,YAA8B,CAAC;AACrC,iBAAW,UAAU,eAAe;AAClC,cAAM,WAAW,KAAK,SAAS,qBAAqB,MAAM;AAC1D,kBAAU,KAAK;AAAA,UACb,MAAM;AAAA,UACN,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,UAC/B,YAAY,iBAAiB,IAAI,MAAM,KAAK;AAAA,UAC5C,OAAO,iBAAiB,IAAI,MAAM,KAAK,CAAC;AAAA,QAC1C,CAAC;AAAA,MACH;AAEA,YAAM,YAAY,UAAU,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,MAAM,QAAQ,CAAC;AACtE,YAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,SAAS,SAAS;AAExD,cAAQ,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAGD,iBAAW,QAAQ,SAAS;AAC1B,kBAAU,IAAI,IAAI;AAAA,MACpB;AAGA,iBAAW,QAAQ,OAAO;AACxB,YAAI,CAAC,YAAY,IAAI,IAAI,KAAK,KAAK,aAAa,IAAI,IAAI,KAAK,KAAK,SAAS,QAAQ,IAAI,GAAG;AACxF,qBAAW,KAAK,IAAI;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,gBAAgB,WAAW,MAAM,GAAG,SAAS;AAEnD,UAAM,aAAa,IAAI,IAAI,aAAa;AACxC,UAAM,UAAU,CAAC,UAAU,KAAK,cAAc,UAAU;AACxD,SAAK,eAAe;AAEpB,QAAI,SAAS;AACX,WAAK,0BAA0B;AAAA,IACjC;AAEA,WAAO,EAAE,QAAQ;AAAA,EACnB;AAAA,EAEA,kBAA0B;AACxB,UAAM,UAAU,KAAK,SAAS,YAAY,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAC7D,UAAM,aACJ,QAAQ,SAAS,IACb;AAAA,MACE,GAAG;AAAA,MACH,aACE,qBAAqB,cACrB;AAAA;AAAA,0BAA+B,QAAQ,KAAK,IAAI,CAAC;AAAA,IACrD,IACA;AAEN,UAAM,QAAgB,CAAC,YAAY,iBAAiB;AACpD,eAAW,QAAQ,KAAK,cAAc;AACpC,YAAM,aAAa,KAAK,SAAS,QAAQ,IAAI;AAC7C,UAAI,YAAY;AACd,cAAM,KAAK,WAAW,IAAI;AAAA,MAC5B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,sBAAsB,UAAmD;AACvE,SAAK,UAAU,IAAI,QAAQ;AAC3B,WAAO,MAAM;AACX,WAAK,UAAU,OAAO,QAAQ;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,oBAAoB;AACzB,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA,EAEQ,4BAAkC;AACxC,eAAW,YAAY,KAAK,WAAW;AACrC,UAAI;AACF,iBAAS;AAAA,MACX,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;;;ACxjBA,SAAS,eAAe,MAAsB;AAC5C,SAAO,KAAK,KAAK,KAAK,SAAS,CAAC;AAClC;AAEO,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EACA,iBAAyB;AAAA,EACzB,yBAAiC;AAAA,EACjC;AAAA,EAER,YAAY,UAAwB,WAAmB;AACrD,SAAK,WAAW;AAChB,SAAK,iBAAiB,eAAe,KAAK,UAAU,SAAS,CAAC;AAC9D,SAAK,cAAc,KAAK,SAAS,UAAU,MAAM;AAAA,IAEjD,CAAC;AAAA,EACH;AAAA,EAEA,qBAAqB,cAA4B;AAC/C,SAAK,0BAA0B,eAAe,YAAY;AAAA,EAC5D;AAAA,EAEA,cAAoC;AAClC,UAAM,WAAW,KAAK,SAAS,UAAU;AACzC,UAAM,iBAAiB,eAAe,KAAK,UAAU,QAAQ,CAAC;AAC9D,UAAM,eAAe,KAAK,iBAAiB,KAAK;AAChD,WAAO;AAAA,MACL,cAAc,KAAK,IAAI,GAAG,iBAAiB,YAAY;AAAA,MACvD,iBAAiB;AAAA,MACjB,eAAe;AAAA,IACjB;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,YAAY;AAAA,EACnB;AACF;;;AJPO,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,SAA+B;AACzC,SAAK,UAAU,WAAW,CAAC;AAC3B,SAAK,eAAe,SAAS,gBAAgB,IAAI,aAAa;AAC9D,SAAK,oBAAoB,SAAS;AAClC,SAAK,eAAe,SAAS;AAE7B,UAAM,YAAY,SAAS,cAAc;AACzC,QAAI,aAAa,KAAK,mBAAmB;AACvC,WAAK,eAAe,IAAI;AAAA,QACtB,KAAK;AAAA,QACL,CAAC,sBAAsB,iBAAiB;AAAA,MAC1C;AAAA,IACF;AAEA,UAAM,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAEX,SAAK,SAAS,IAAI;AAAA,MAChB,EAAE,MAAM,UAAU,SAAS,YAAY;AAAA,MACvC;AAAA,QACE,cAAc,EAAE,OAAO,EAAE,aAAa,KAAK,EAAE;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAEA,SAAK,OAAO,kBAAkB,wBAAwB,MAAM;AAC1D,UAAI,KAAK,mBAAmB;AAC1B,eAAO,EAAE,OAAO,KAAK,kBAAkB,gBAAgB,EAAE;AAAA,MAC3D;AACA,aAAO,EAAE,OAAO,KAAK,aAAa,UAAU,EAAE;AAAA,IAChD,CAAC;AAED,SAAK,OAAO,kBAAkB,uBAAuB,OAAO,YAAY;AACtE,YAAM,EAAE,MAAM,WAAW,KAAK,IAAI,QAAQ;AAG1C,UAAI,KAAK,qBAAqB,SAAS,kBAAkB;AACvD,cAAM,SAAU,QAAQ,CAAC;AAEzB,YAAI,CAAC,MAAM,QAAQ,OAAO,OAAO,KAAK,OAAO,QAAQ,WAAW,GAAG;AACjE,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAEA,iBAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,KAAK;AAC9C,gBAAM,IAAI,OAAO,QAAQ,CAAC;AAC1B,cAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,YAAY,CAAC,EAAE,UAAU;AACzC,mBAAO;AAAA,cACL,SAAS;AAAA,gBACP;AAAA,kBACE,MAAM;AAAA,kBACN,MAAM,kBAAkB,CAAC;AAAA,gBAC3B;AAAA,cACF;AAAA,cACA,SAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAEA,cAAM,SAAS,KAAK,kBAAkB,OAAO,MAAM;AACnD,YAAI,WAAmB;AACvB,YAAI,KAAK,cAAc;AACrB,gBAAM,eAAe,KAAK,UAAU,MAAM;AAC1C,eAAK,aAAa,qBAAqB,YAAY;AACnD,qBAAW,EAAE,eAAe,KAAK,aAAa,YAAY,GAAG,GAAG,OAAO;AAAA,QACzE;AACA,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,QAAQ,EAAE,CAAC;AAAA,QACrE;AAAA,MACF;AAGA,UAAI,KAAK,qBAAqB,SAAS,eAAe;AACpD,cAAM,WAAY,MAA4B;AAC9C,cAAM,WAAY,MAAkD;AAEpE,YAAI,CAAC,UAAU;AACb,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAEA,eAAO,KAAK,gBAAgB,UAAU,QAAQ;AAAA,MAChD;AAGA,YAAM,aAAa,KAAK,aAAa,QAAQ,IAAI;AACjD,UAAI,CAAC,YAAY;AACf,cAAM,IAAI;AAAA,UACR,UAAU;AAAA,UACV,iBAAiB,IAAI;AAAA,QACvB;AAAA,MACF;AAEA,aAAO,KAAK,gBAAgB,MAAM,IAAI;AAAA,IACxC,CAAC;AAED,QAAI,KAAK,mBAAmB;AAC1B,WAAK,cAAc,KAAK,kBAAkB,sBAAsB,MAAM;AACpE,aAAK,OAAO,oBAAoB,EAAE,MAAM,MAAM;AAAA,QAE9C,CAAC;AAAA,MACH,CAAC;AAAA,IACH,OAAO;AACL,WAAK,cAAc,KAAK,aAAa,UAAU,MAAM;AACnD,aAAK,OAAO,oBAAoB,EAAE,MAAM,MAAM;AAAA,QAE9C,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAc,gBACZ,MACA,MACyB;AACzB,UAAM,SAAS,oBAAoB,IAAI;AACvC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV,0CAA0C,IAAI;AAAA,MAChD;AAAA,IACF;AAEA,QAAI,KAAK,cAAc;AACrB,YAAM,WAAW,KAAK,OAAO,YAAY,KAAK,KAAK,MAAM;AACzD,YAAM,KAAK,aAAa,QAAQ,OAAO,QAAQ,OAAO,UAAU,MAAM,QAAQ;AAAA,IAChF;AAEA,UAAM,YAAY,KAAK,QAAQ;AAC/B,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,UAAU,OAAO,MAAM;AACtC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV,8BAA8B,OAAO,MAAM;AAAA,MAC7C;AAAA,IACF;AAEA,QAAI,OAAO,WAAW,aAAa;AACjC,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV,oBAAoB,OAAO,MAAM,+BAA+B,OAAO,MAAM;AAAA,MAC/E;AAAA,IACF;AAEA,UAAM,cAAc,KAAK,QAAQ,iBAAiB,OAAO,MAAM;AAC/D,QAAI,aAAa;AACf,UAAI;AACF,cAAM,YAAY,QAAQ;AAAA,MAC5B,SAAS,KAAK;AACZ,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,cAAM,IAAI,SAAS,UAAU,eAAe,OAAO;AAAA,MACrD;AAAA,IACF;AAEA,QAAI;AACF,aAAO,MAAM,OAAO,SAAS;AAAA,QAC3B,MAAM,OAAO;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV,oBAAoB,OAAO,MAAM,YAAY,OAAO;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,WAAqC;AACjD,UAAM,KAAK,OAAO,QAAQ,SAAS;AAAA,EACrC;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,YAAY,IAAI;AAAA,MACpB,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,IACf;AACA,UAAM,KAAK,QAAQ,SAAS;AAAA,EAC9B;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,cAAc;AACnB,SAAK,cAAc;AACnB,SAAK,cAAc,QAAQ;AAC3B,UAAM,KAAK,OAAO,MAAM;AAAA,EAC1B;AAAA,EAEA,kBAAgC;AAC9B,WAAO,KAAK;AAAA,EACd;AACF;;;AK/QA,IAAM,qBAAqB;AAQpB,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAuB,CAAC;AAAA,EACxB,QAAkB,CAAC;AAAA,EACnB;AAAA,EAER,YAAY,QAAyB,YAAY,oBAAoB;AACnE,SAAK,WAAW,OAAO;AACvB,SAAK,WAAW,OAAO,gBAAgB;AACvC,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAM,UAAyB;AAC7B,SAAK,MAAM;AAEX,QAAI,KAAK,WAAW,SAAS,KAAK,UAAU;AAC1C,WAAK,WAAW,KAAK,KAAK,IAAI,CAAC;AAC/B;AAAA,IACF;AAEA,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,YAAM,QAAQ,WAAW,MAAM;AAC7B,cAAM,MAAM,KAAK,MAAM,UAAU,CAAC,MAAM,EAAE,YAAY,OAAO;AAC7D,YAAI,QAAQ,GAAI,MAAK,MAAM,OAAO,KAAK,CAAC;AACxC,eAAO,IAAI,MAAM,2CAA2C,CAAC;AAAA,MAC/D,GAAG,KAAK,SAAS;AAEjB,WAAK,MAAM,KAAK,EAAE,SAAS,QAAQ,MAAM,CAAC;AAC1C,WAAK,cAAc;AAAA,IACrB,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,QAA+B;AACzC,SAAK,WAAW,OAAO;AACvB,SAAK,WAAW,OAAO,gBAAgB;AACvC,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,eAAe,QAAW;AACjC,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AACA,eAAW,UAAU,KAAK,OAAO;AAC/B,mBAAa,OAAO,KAAK;AACzB,aAAO,OAAO,IAAI,MAAM,uBAAuB,CAAC;AAAA,IAClD;AACA,SAAK,QAAQ,CAAC;AACd,SAAK,aAAa,CAAC;AAAA,EACrB;AAAA,EAEQ,QAAc;AACpB,UAAM,SAAS,KAAK,IAAI,IAAI,KAAK;AACjC,QAAI,IAAI;AACR,WAAO,IAAI,KAAK,WAAW,UAAU,KAAK,WAAW,CAAC,KAAK,OAAQ;AACnE,QAAI,IAAI,EAAG,MAAK,WAAW,OAAO,GAAG,CAAC;AAAA,EACxC;AAAA,EAEQ,WAAiB;AACvB,SAAK,MAAM;AACX,WAAO,KAAK,MAAM,SAAS,KAAK,KAAK,WAAW,SAAS,KAAK,UAAU;AACtE,YAAM,SAAS,KAAK,MAAM,MAAM;AAChC,mBAAa,OAAO,KAAK;AACzB,WAAK,WAAW,KAAK,KAAK,IAAI,CAAC;AAC/B,aAAO,QAAQ;AAAA,IACjB;AACA,SAAK,cAAc;AAAA,EACrB;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,eAAe,QAAW;AACjC,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AACA,QAAI,KAAK,MAAM,WAAW,KAAK,KAAK,WAAW,WAAW,EAAG;AAE7D,UAAM,eAAe,KAAK,WAAW,CAAC,IAAI,KAAK,WAAW,KAAK,IAAI;AACnE,UAAM,QAAQ,KAAK,IAAI,GAAG,YAAY;AACtC,SAAK,aAAa,WAAW,MAAM;AACjC,WAAK,aAAa;AAClB,WAAK,SAAS;AAAA,IAChB,GAAG,KAAK;AAAA,EACV;AACF;;;ACjGA;AAAA,EACE,aAAAC;AAAA,EACA,YAAAC;AAAA,OACK;AAWA,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EACA;AAAA,EAER,YACE,cACA,eACA;AACA,SAAK,eAAe;AACpB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,OACE,cACA,eACM;AACN,SAAK,eAAe;AACpB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,cAAc,QAAgB,UAA8B;AAC1D,UAAM,eAAe,KAAK,cAAc,MAAM;AAC9C,QAAI,cAAc;AAChB,YAAM,UAAU,aAAa,QAAQ,QAAQ;AAC7C,UAAI,QAAS,QAAO;AAEpB,UAAI,aAAa,WAAY,QAAO,aAAa;AAAA,IACnD;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QACJ,QACA,UACA,MACA,UACe;AACf,UAAM,SAAS,KAAK,cAAc,QAAQ,QAAQ;AAElD,QAAI,WAAW,SAAU;AAEzB,QAAI,WAAW,SAAS;AACtB,YAAM,IAAIA;AAAA,QACRD,WAAU;AAAA,QACV,QAAQ,MAAM,KAAK,QAAQ;AAAA,MAC7B;AAAA,IACF;AAGA,QAAI;AACF,YAAM,SAAS,MAAM,SAAS;AAAA,QAC5B,SAAS,SAAS,MAAM,KAAK,QAAQ;AAAA;AAAA;AAAA,EAA2B,KAAK,UAAU,QAAQ,CAAC,GAAG,MAAM,CAAC,CAAC;AAAA,QACnG,iBAAiB,EAAE,MAAM,UAAU,YAAY,CAAC,EAAE;AAAA,MACpD,CAAC;AAED,UAAI,OAAO,WAAW,UAAU;AAC9B,cAAM,IAAIC;AAAA,UACRD,WAAU;AAAA,UACV,QAAQ,MAAM,KAAK,QAAQ;AAAA,QAC7B;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAeC,UAAU,OAAM;AAEnC,YAAM,IAAIA;AAAA,QACRD,WAAU;AAAA,QACV,QAAQ,MAAM,KAAK,QAAQ;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AACF;;;ACrFA,SAAS,cAAc;AAwBhB,IAAe,qBAAf,MAA4D;AAAA,EACxD;AAAA,EAED,UAA4B;AAAA,EAC5B,SAAiB,CAAC;AAAA,EAClB;AAAA,EACA,UAAU;AAAA,EACV,SAAS;AAAA,EACT;AAAA,EACA,oBAAoB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACE;AAAA,EACF,mBAAmB,oBAAI,IAA0B;AAAA,EACjD,kBAAkB,oBAAI,IAA0B;AAAA,EAExD,YAAY,SAAoC;AAC9C,SAAK,OAAO,QAAQ;AACpB,SAAK,wBAAwB,QAAQ,wBAAwB;AAC7D,SAAK,sBAAsB,QAAQ,sBAAsB;AACzD,SAAK,qBAAqB,QAAQ,qBAAqB;AACvD,SAAK,oBAAoB,QAAQ;AACjC,SAAK,UAAU,QAAQ,UAAU,iBAAiB;AAAA,EACpD;AAAA,EAEA,IAAI,SAA2B;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,QAA6B;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI,KAAK,gBAAiB,QAAO,KAAK;AACtC,SAAK,kBAAkB,KAAK,WAAW,EAAE,QAAQ,MAAM;AACrD,WAAK,kBAAkB;AAAA,IACzB,CAAC;AACD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,aAA4B;AACxC,SAAK,UAAU;AACf,SAAK,qBAAqB;AAC1B,SAAK;AACL,UAAM,UAAU,KAAK;AAGrB,QAAI,KAAK,SAAS;AAChB,YAAM,MAAM,KAAK;AACjB,WAAK,UAAU;AACf,YAAM,IAAI,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAClC;AAEA,SAAK,WAAW,YAAY;AAC5B,SAAK,QAAQ,MAAM,YAAY;AAE/B,QAAI;AACF,YAAM,KAAK,gBAAgB;AAC3B,YAAM,YAAY,KAAK,iBAAiB;AACxC,YAAM,SAAS,IAAI;AAAA,QACjB,EAAE,MAAM,GAAG,QAAQ,IAAI,KAAK,IAAI,IAAI,SAAS,YAAY;AAAA,QACzD;AAAA,UACE,aAAa;AAAA,YACX,OAAO;AAAA,cACL,aAAa;AAAA,cACb,WAAW,CAAC,OAAO,UAAU;AAC3B,oBAAI,SAAS,CAAC,SAAS,KAAK,WAAW,QAAS;AAChD,qBAAK,SAAS;AACd,qBAAK,oBAAoB;AAAA,cAC3B;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,gBAAU,UAAU,MAAM;AACxB,YAAI,KAAK,WAAW,KAAK,WAAW,QAAS;AAC7C,aAAK,UAAU;AACf,aAAK,WAAW,cAAc;AAC9B,aAAK,mBAAmB;AAAA,MAC1B;AAEA,YAAM,OAAO,QAAQ,SAAS;AAE9B,YAAM,SAAS,MAAM,OAAO,UAAU;AACtC,WAAK,SAAS,OAAO;AACrB,WAAK,UAAU;AACf,WAAK,oBAAoB;AACzB,WAAK,WAAW,WAAW;AAC3B,WAAK,oBAAoB;AAAA,IAC3B,SAAS,KAAK;AACZ,WAAK,QAAQ,MAAM,qBAAqB;AAAA,QACtC,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD,CAAC;AACD,WAAK,WAAW,cAAc;AAC9B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,QAGa;AAC1B,QAAI,CAAC,KAAK,WAAW,KAAK,YAAY,aAAa;AACjD,YAAM,IAAI;AAAA,QACR,qBAAqB,OAAO,IAAI,cAAc,KAAK,IAAI;AAAA,MACzD;AAAA,IACF;AACA,WAAO,KAAK,QAAQ,SAAS,MAAM;AAAA,EACrC;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,UAAU;AACf,SAAK,qBAAqB;AAE1B,QAAI,KAAK,SAAS;AAChB,YAAM,SAAS,KAAK;AACpB,WAAK,UAAU;AACf,YAAM,OAAO,MAAM;AAAA,IACrB;AAEA,SAAK,SAAS,CAAC;AACf,SAAK,WAAW,cAAc;AAAA,EAChC;AAAA,EAEA,MAAM,KAAK,YAAY,KAAqB;AAC1C,QAAI,CAAC,KAAK,WAAW,KAAK,YAAY,aAAa;AACjD,YAAM,IAAI,MAAM,wBAAwB,KAAK,IAAI,oBAAoB;AAAA,IACvE;AACA,UAAM,KAAK,QAAQ,KAAK,EAAE,QAAQ,YAAY,QAAQ,SAAS,EAAE,CAAC;AAAA,EACpE;AAAA,EAEA,MAAM,YAA2B;AAC/B,SAAK,oBAAoB;AACzB,SAAK,UAAU;AACf,SAAK,qBAAqB;AAC1B,SAAK;AAEL,QAAI,KAAK,SAAS;AAChB,YAAM,MAAM,KAAK;AACjB,WAAK,UAAU;AACf,YAAM,IAAI,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAClC;AAEA,SAAK,QAAQ,KAAK,cAAc;AAChC,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,eAAe,UAA4C;AACzD,SAAK,iBAAiB,IAAI,QAAQ;AAClC,WAAO,MAAM;AACX,WAAK,iBAAiB,OAAO,QAAQ;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,eAAe,UAA4C;AACzD,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM;AACX,WAAK,gBAAgB,OAAO,QAAQ;AAAA,IACtC;AAAA,EACF;AAAA,EAEQ,mBAA8B;AACpC,QAAI,KAAK,mBAAmB;AAC1B,aAAO,KAAK,kBAAkB;AAAA,IAChC;AACA,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA;AAAA,EAGA,MAAgB,kBAAiC;AAAA,EAAC;AAAA,EAK1C,WAAW,MAAwB,OAAqB;AAC9D,UAAM,WAAW,KAAK;AACtB,QAAI,aAAa,KAAM;AACvB,SAAK,UAAU;AAEf,UAAM,QAA2B;AAAA,MAC/B;AAAA,MACA,SAAS;AAAA,MACT,GAAI,SAAS,EAAE,MAAM;AAAA,IACvB;AACA,eAAW,YAAY,KAAK,kBAAkB;AAC5C,UAAI;AACF,iBAAS,KAAK;AAAA,MAChB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,sBAA4B;AAClC,eAAW,YAAY,KAAK,iBAAiB;AAC3C,UAAI;AACF,iBAAS,KAAK,MAAM;AAAA,MACtB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,qBAA2B;AACjC,QAAI,KAAK,QAAS;AAClB,QAAI,KAAK,oBAAoB,OAAW;AACxC,QAAI,KAAK,gBAAiB;AAE1B,QAAI,KAAK,qBAAqB,KAAK,uBAAuB;AACxD,WAAK,QAAQ,KAAK,gCAAgC;AAClD,WAAK,WAAW,SAAS,IAAI,MAAM,iCAAiC,CAAC;AACrE;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK;AAAA,MACjB,KAAK,sBAAsB,KAAK,IAAI,GAAG,KAAK,iBAAiB;AAAA,MAC7D,KAAK;AAAA,IACP;AACA,SAAK;AACL,SAAK,QAAQ,MAAM,mBAAmB,KAAK,MAAM,EAAE,SAAS,KAAK,kBAAkB,CAAC;AAEpF,SAAK,kBAAkB,WAAW,MAAM;AACtC,WAAK,kBAAkB;AACvB,WAAK,QAAQ,EAAE,MAAM,MAAM;AACzB,aAAK,mBAAmB;AAAA,MAC1B,CAAC;AAAA,IACH,GAAG,KAAK;AAAA,EACV;AAAA,EAEQ,uBAA6B;AACnC,QAAI,KAAK,oBAAoB,QAAW;AACtC,mBAAa,KAAK,eAAe;AACjC,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AACF;;;ACxQA,SAAS,qCAAqC;AAC9C,SAAS,0BAA0B;;;ACD5B,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YAAY,SAAiB,SAA+B;AAC1D,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;;;ACLA,SAAS,KAAAE,UAAS;AAIX,IAAM,yBAAyBA,GAAE,OAAO;AAAA,EAC7C,MAAMA,GAAE,QAAQ,QAAQ;AAAA,EACxB,cAAcA,GAAE,OAAO,EAAE,IAAI,CAAC;AAChC,CAAC;AAEM,IAAM,yBAAyBA,GAAE,OAAO;AAAA,EAC7C,MAAMA,GAAE,QAAQ,QAAQ;AAAA,EACxB,cAAcA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC9B,eAAeA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC1C,gBAAgBA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAC1C,WAAWA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACtC,YAAYA,GAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS;AAC/D,CAAC;AAEM,IAAM,yBAAyBA,GAAE,OAAO;AAAA,EAC7C,MAAMA,GAAE,QAAQ,QAAQ;AAAA,EACxB,OAAOA,GAAE,OAAO,EAAE,IAAI,CAAC;AACzB,CAAC;AAEM,IAAM,mBAAmBA,GAAE,MAAM;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,4BAA4BA,GAAE,OAAO;AAAA,EAChD,SAASA,GAAE,QAAQ,CAAC;AAAA,EACpB,aAAaA,GAAE,OAAOA,GAAE,OAAO,GAAG,gBAAgB;AACpD,CAAC;AAaM,SAAS,uBAAuBC,aAAgC;AACrE,MAAIA,YAAW,SAAS,SAAU,QAAOA,YAAW;AACpD,SAAOA,YAAW;AACpB;;;AC5CA,IAAM,cAAc;AACpB,IAAM,mBAAmB;AAGlB,SAAS,uBACd,QACS;AACT,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,SAAS,OAAO,OAAO,MAAM,GAAG;AACzC,QAAI,iBAAiB,KAAK,KAAK,EAAG,QAAO;AAAA,EAC3C;AACA,SAAO;AACT;AAWA,eAAsB,2BACpB,QACA,OACiC;AACjC,QAAM,WAAmC,CAAC;AAE1C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAM,UAAU,CAAC,GAAG,MAAM,SAAS,WAAW,CAAC;AAC/C,QAAI,QAAQ,WAAW,GAAG;AACxB,eAAS,GAAG,IAAI;AAChB;AAAA,IACF;AAGA,UAAM,eAAwE,CAAC;AAC/E,eAAW,SAAS,SAAS;AAC3B,YAAM,UAAU,MAAM,CAAC;AACvB,YAAMC,cAAa,MAAM,MAAM,IAAI,OAAO;AAC1C,UAAI,CAACA,aAAY;AACf,cAAM,IAAI;AAAA,UACR,eAAe,OAAO;AAAA,QACxB;AAAA,MACF;AACA,mBAAa,KAAK;AAAA,QAChB,OAAO,MAAM;AAAA,QACb,KAAK,MAAM,QAAS,MAAM,CAAC,EAAE;AAAA,QAC7B,UAAU,uBAAuBA,WAAU;AAAA,MAC7C,CAAC;AAAA,IACH;AAGA,QAAI,SAAS;AACb,aAAS,IAAI,aAAa,SAAS,GAAG,KAAK,GAAG,KAAK;AACjD,YAAM,EAAE,OAAO,KAAK,UAAU,IAAI,IAAI,aAAa,CAAC;AACpD,eAAS,OAAO,MAAM,GAAG,KAAK,IAAI,MAAM,OAAO,MAAM,GAAG;AAAA,IAC1D;AACA,aAAS,GAAG,IAAI;AAAA,EAClB;AAEA,SAAO;AACT;;;AHrDO,IAAM,qBAAN,cAAiC,mBAAmB;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,SAAoC;AAC9C,UAAM,OAAO;AACb,SAAK,UAAU,QAAQ;AACvB,SAAK,mBAAmB,QAAQ;AAAA,EAClC;AAAA,EAEA,MAAyB,kBAAiC;AACxD,SAAK,mBAAmB;AACxB,QACE,KAAK,oBACL,KAAK,QAAQ,WACb,uBAAuB,KAAK,QAAQ,OAAiC,GACrE;AACA,WAAK,mBAAmB,MAAM;AAAA,QAC5B,KAAK,QAAQ;AAAA,QACb,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAEU,kBAA6B;AACrC,UAAM,MAAM,IAAI,IAAI,KAAK,QAAQ,GAAG;AACpC,UAAM,UAAU,KAAK,oBAAoB,KAAK,QAAQ;AACtD,UAAM,cAAuC,UACzC,EAAE,QAA2C,IAC7C;AAEJ,QAAI,KAAK,QAAQ,SAAS,OAAO;AAC/B,aAAO,IAAI,8BAA8B,KAAK,EAAE,YAAY,CAAC;AAAA,IAC/D;AACA,WAAO,IAAI,mBAAmB,KAAK,EAAE,YAAY,CAAC;AAAA,EACpD;AACF;;;AInDA,SAAS,4BAA4B;AAa9B,IAAM,sBAAN,cAAkC,mBAAmB;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,SAAqC;AAC/C,UAAM,OAAO;AACb,SAAK,UAAU,QAAQ;AACvB,SAAK,mBAAmB,QAAQ;AAAA,EAClC;AAAA,EAEA,MAAyB,kBAAiC;AACxD,SAAK,eAAe;AACpB,QACE,KAAK,oBACL,KAAK,QAAQ,OACb,uBAAuB,KAAK,QAAQ,GAA6B,GACjE;AACA,WAAK,eAAe,MAAM;AAAA,QACxB,KAAK,QAAQ;AAAA,QACb,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAEU,kBAA6B;AACrC,UAAM,MAAM,KAAK,gBAAgB,KAAK,QAAQ;AAC9C,UAAM,YAAY,IAAI,qBAAqB;AAAA,MACzC,SAAS,KAAK,QAAQ;AAAA,MACtB,MAAM,KAAK,QAAQ;AAAA,MACnB,KAAK,EAAE,GAAG,QAAQ,KAAK,GAAG,IAAI;AAAA,MAC9B,QAAQ;AAAA,IACV,CAAC;AAGD,cAAU,QAAQ,GAAG,QAAQ,CAAC,UAAkB;AAC9C,YAAM,OAAO,MAAM,SAAS,EAAE,QAAQ;AACtC,UAAI,MAAM;AACR,mBAAW,QAAQ,KAAK,MAAM,IAAI,GAAG;AACnC,eAAK,QAAQ,MAAM,MAAM,EAAE,QAAQ,SAAS,CAAC;AAAA,QAC/C;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AACF;;;AChBO,IAAM,kBAAN,MAAsB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW,oBAAI,IAA4B;AAAA,EAC3C,iBAAiB,oBAAI,IAA+B;AAAA,EACpD;AAAA,EACA;AAAA,EACA,kBAAkB,oBAAI,IAA4B;AAAA,EAClD,iBAAiB,oBAAI,IAAY;AAAA,EACjC,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EAE9B,YAAY,SAAiC;AAC3C,SAAK,UAAU,QAAQ;AACvB,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,UAAU,QAAQ,UAAU,iBAAiB;AAClD,SAAK,uBACH,QAAQ,uBAAuB,QAAQ,OAAO,QAAQ;AACxD,UAAM,kBAAkB,QAAQ;AAChC,SAAK,iBACH,QAAQ,mBACP,CAAC,MAAM,QAAQ,WAAW;AACzB,UAAI,cAAc,MAAM,GAAG;AACzB,eAAO,IAAI,oBAAoB,EAAE,MAAM,QAAQ,QAAQ,gBAAgB,CAAC;AAAA,MAC1E;AACA,aAAO,IAAI,mBAAmB,EAAE,MAAM,QAAoC,QAAQ,gBAAgB,CAAC;AAAA,IACrG;AAAA,EACJ;AAAA,EAEQ,WACN,MACA,cAC2C;AAC3C,UAAM,MAAM,KAAK,QAAQ,MAAM,EAAE,WAAW,YAAY,QAAQ,KAAK,CAAC;AACtE,UAAM,YAAY,cAAc,YAAY,IACxC,UACC,aAAkC;AACvC,QAAI,KAAK,eAAe,SAAS,GAAG;AAEpC,UAAM,SAAS,KAAK,eAAe,MAAM,cAAc,GAAG;AAC1D,SAAK,SAAS,IAAI,MAAM,MAAM;AAE9B,UAAM,WAAW,aAAa,SAAS;AACvC,QAAI,UAAU;AACZ,WAAK,cAAc,qBAAqB,MAAM,QAAQ;AAAA,IACxD;AAEA,UAAM,aAAa,OAAO,eAAe,CAAC,UAAU;AAClD,YAAM,aAAa,MAAM,IAAI,CAAC,MAAM,cAAc,MAAM,CAAC,CAAC;AAC1D,WAAK,cAAc,kBAAkB,MAAM,UAAU;AACrD,UAAI;AAAA,QACF,GAAG,MAAM,MAAM,QAAQ,MAAM,WAAW,IAAI,KAAK,GAAG,gBAAgB,WAAW,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;AAAA,MAC9G;AAAA,IACF,CAAC;AAED,UAAM,cAAc,OAAO,eAAe,CAAC,UAAU;AACnD,UAAI,MAAM,YAAY,SAAS;AAC7B,YAAI;AAAA,UACF,UAAU,MAAM,OAAO,WAAW,SAAS;AAAA,QAC7C;AACA,aAAK,cAAc,aAAa,IAAI;AAAA,MACtC,OAAO;AACL,YAAI,MAAM,GAAG,MAAM,OAAO,EAAE;AAAA,MAC9B;AAAA,IACF,CAAC;AAED,SAAK,eAAe,IAAI,MAAM,CAAC,YAAY,WAAW,CAAC;AAEvD,WAAO,OAAO,QAAQ,EAAE;AAAA,MACtB,OAAO,EAAE,KAAK;AAAA,MACd,CAAC,QAAQ;AACP,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAI,MAAM,sBAAsB,OAAO,EAAE;AACzC,eAAO,EAAE,MAAM,OAAO,QAAQ;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,MAA6B;AACvD,UAAM,SAAS,KAAK,eAAe,IAAI,IAAI;AAC3C,QAAI,QAAQ;AACV,iBAAW,SAAS,OAAQ,OAAM;AAClC,WAAK,eAAe,OAAO,IAAI;AAAA,IACjC;AAEA,UAAM,SAAS,KAAK,SAAS,IAAI,IAAI;AACrC,QAAI,QAAQ;AACV,YAAM,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACnC,WAAK,SAAS,OAAO,IAAI;AAAA,IAC3B;AAEA,SAAK,cAAc,aAAa,IAAI;AACpC,SAAK,gBAAgB,OAAO,IAAI;AAChC,SAAK,eAAe,OAAO,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,aAAwC;AAC5C,UAAM,UAAU,OAAO,QAAQ,iBAAiB,KAAK,OAAO,CAAC;AAC7D,UAAM,kBAA+D,CAAC;AAEtE,eAAW,CAAC,MAAM,YAAY,KAAK,SAAS;AAC1C,sBAAgB,KAAK,KAAK,WAAW,MAAM,YAAY,CAAC;AAAA,IAC1D;AAEA,UAAM,WAAW,MAAM,QAAQ,IAAI,eAAe;AAClD,UAAM,SAAS,SAAS,OAAO,CAAC,MAAM,EAAE,UAAU,MAAS;AAC3D,WAAO;AAAA,MACL,OAAO,QAAQ;AAAA,MACf,WAAW,QAAQ,SAAS,OAAO;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,WAA0B;AAC9B,SAAK,iBAAiB;AAEtB,eAAW,UAAU,KAAK,eAAe,OAAO,GAAG;AACjD,iBAAW,SAAS,OAAQ,OAAM;AAAA,IACpC;AACA,SAAK,eAAe,MAAM;AAE1B,UAAM,QAAQ,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC;AAE7C,UAAM,gBAAgB,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC,EAAE;AAAA,MAAI,CAAC,WAC5D,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,MAE3B,CAAC;AAAA,IACH;AACA,UAAM,QAAQ,IAAI,aAAa;AAE/B,eAAW,QAAQ,OAAO;AACxB,WAAK,cAAc,aAAa,IAAI;AAAA,IACtC;AAEA,SAAK,SAAS,MAAM;AACpB,SAAK,gBAAgB,MAAM;AAC3B,SAAK,eAAe,MAAM;AAAA,EAC5B;AAAA,EAEA,MAAM,gBAAgB,MAAkB,WAAwC;AAE9E,eAAW,QAAQ,KAAK,QAAQ,SAAS;AACvC,WAAK,QAAQ,KAAK,mBAAmB,EAAE,WAAW,UAAU,QAAQ,KAAK,CAAC;AAC1E,YAAM,KAAK,cAAc,IAAI;AAAA,IAC/B;AAGA,eAAW,EAAE,MAAM,OAAO,KAAK,KAAK,QAAQ,WAAW;AACrD,WAAK,QAAQ,KAAK,uBAAuB,EAAE,WAAW,UAAU,QAAQ,KAAK,CAAC;AAC9E,YAAM,KAAK,cAAc,IAAI;AAC7B,YAAM,SAAS,MAAM,KAAK,WAAW,MAAM,MAAM;AACjD,UAAI,OAAO,OAAO;AAChB,aAAK,QAAQ,KAAK,yCAAyC;AAAA,UACzD,WAAW;AAAA,UAAU,QAAQ;AAAA,UAAM,OAAO,OAAO;AAAA,QACnD,CAAC;AAAA,MACH;AAAA,IACF;AAGA,eAAW,EAAE,MAAM,OAAO,KAAK,KAAK,QAAQ,OAAO;AACjD,WAAK,QAAQ,KAAK,iBAAiB,EAAE,WAAW,UAAU,QAAQ,KAAK,CAAC;AACxE,YAAM,SAAS,MAAM,KAAK,WAAW,MAAM,MAAM;AACjD,UAAI,OAAO,OAAO;AAChB,aAAK,QAAQ,KAAK,yCAAyC;AAAA,UACzD,WAAW;AAAA,UAAU,QAAQ;AAAA,UAAM,OAAO,OAAO;AAAA,QACnD,CAAC;AAAA,MACH;AAAA,IACF;AAGA,eAAW,EAAE,MAAM,OAAO,KAAK,KAAK,QAAQ,SAAS;AACnD,WAAK,QAAQ,KAAK,qBAAqB,EAAE,WAAW,UAAU,QAAQ,KAAK,CAAC;AAC5E,YAAM,WAAW,OAAO,SAAS;AACjC,UAAI,UAAU;AACZ,aAAK,cAAc,qBAAqB,MAAM,QAAQ;AAAA,MACxD,OAAO;AACL,aAAK,cAAc,wBAAwB,IAAI;AAAA,MACjD;AAAA,IACF;AAEA,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,oBAAoB,UAAwB;AAC1C,SAAK,iBAAiB;AACtB,SAAK,uBAAuB;AAC5B,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,UAAU,MAA0C;AAClD,WAAO,KAAK,SAAS,IAAI,IAAI;AAAA,EAC/B;AAAA,EAEA,cAAgC;AAC9B,WAAO,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC,EAAE,IAAI,CAAC,WAAW;AACxD,YAAM,WAAW,KAAK,gBAAgB,IAAI,OAAO,IAAI;AACrD,aAAO;AAAA,QACL,MAAM,OAAO;AAAA,QACb,QAAQ,OAAO;AAAA,QACf,QAAQ,UAAU,UAAU;AAAA,QAC5B,WAAW,OAAO,MAAM;AAAA,QACxB,YAAY,UAAU;AAAA,MACxB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,oBAA0B;AACxB,QAAI,KAAK,wBAAwB,EAAG;AACpC,QAAI,KAAK,aAAc;AAEvB,SAAK,QAAQ,MAAM,0BAA0B;AAAA,MAC3C,WAAW;AAAA,MACX,UAAU,KAAK;AAAA,IACjB,CAAC;AAED,SAAK,eAAe,YAAY,MAAM;AACpC,WAAK,gBAAgB;AAAA,IACvB,GAAG,KAAK,uBAAuB,GAAI;AAAA,EACrC;AAAA,EAEA,mBAAyB;AACvB,QAAI,KAAK,cAAc;AACrB,oBAAc,KAAK,YAAY;AAC/B,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,kBAAwB;AAC9B,eAAW,CAAC,MAAM,MAAM,KAAK,KAAK,UAAU;AAC1C,UAAI,OAAO,WAAW,YAAa;AACnC,UAAI,KAAK,eAAe,IAAI,IAAI,EAAG;AAEnC,UAAI,WAAW,KAAK,gBAAgB,IAAI,IAAI;AAC5C,UAAI,CAAC,UAAU;AACb,mBAAW,EAAE,qBAAqB,GAAG,QAAQ,UAAU;AACvD,aAAK,gBAAgB,IAAI,MAAM,QAAQ;AAAA,MACzC;AAEA,WAAK,eAAe,IAAI,IAAI;AAE5B,aAAO,KAAK,KAAK,cAAc,EAAE;AAAA,QAC/B,MAAM;AACJ,eAAK,eAAe,OAAO,IAAI;AAC/B,gBAAM,IAAI,KAAK,gBAAgB,IAAI,IAAI;AACvC,cAAI,CAAC,EAAG;AACR,gBAAM,eAAe,EAAE,WAAW;AAClC,YAAE,sBAAsB;AACxB,YAAE,aAAa,KAAK,IAAI;AACxB,YAAE,SAAS;AACX,cAAI,cAAc;AAChB,iBAAK,QAAQ,KAAK,aAAa;AAAA,cAC7B,WAAW;AAAA,cACX,QAAQ;AAAA,YACV,CAAC;AAAA,UACH;AAAA,QACF;AAAA,QACA,CAAC,QAAQ;AACP,eAAK,eAAe,OAAO,IAAI;AAC/B,gBAAM,IAAI,KAAK,gBAAgB,IAAI,IAAI;AACvC,cAAI,CAAC,EAAG;AACR,YAAE;AACF,YAAE,SAAS;AAEX,eAAK,QAAQ,KAAK,eAAe;AAAA,YAC/B,WAAW;AAAA,YACX,QAAQ;AAAA,YACR,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,YACtD,UAAU,EAAE;AAAA,UACd,CAAC;AAED,cAAI,EAAE,uBAAuB,KAAK,qBAAqB;AACrD,iBAAK,QAAQ;AAAA,cACX,GAAG,EAAE,mBAAmB;AAAA,cACxB,EAAE,WAAW,UAAU,QAAQ,KAAK;AAAA,YACtC;AACA,cAAE,sBAAsB;AACxB,cAAE,SAAS;AACX,mBAAO,UAAU,EAAE,MAAM,CAAC,iBAAiB;AACzC,mBAAK,QAAQ,MAAM,oBAAoB;AAAA,gBACrC,WAAW;AAAA,gBACX,QAAQ;AAAA,gBACR,OACE,wBAAwB,QACpB,aAAa,UACb,OAAO,YAAY;AAAA,cAC3B,CAAC;AAAA,YACH,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACjVA,SAAS,UAAU,aAAa;AAChC,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,SAAS,gBAAgB;AAIlC,IAAM,UAAU;AAChB,IAAM,UAAU;AAChB,IAAM,eAAe;AAWrB,SAAS,YACP,SACA,MACiB;AACjB,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC;AAAA,MACE;AAAA,MACA;AAAA,MACA,EAAE,SAAS,aAAa;AAAA,MACxB,CAAC,OAAO,QAAQ,WAAW;AACzB,YAAI,OAAO;AACT;AAAA,YACE,IAAI;AAAA,cACF,GAAG,OAAO,YAAY,QAAQ,KAAK,KAAK,MAAM,OAAO;AAAA,cACrD,EAAE,OAAO,MAAM;AAAA,YACjB;AAAA,UACF;AACA;AAAA,QACF;AACA,gBAAQ,OAAO,KAAK,CAAC;AAAA,MACvB;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,SAAS,eACP,SACA,MACA,OACiB;AACjB,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,QAAQ,MAAM,SAAS,MAAM,EAAE,SAAS,aAAa,CAAC;AAC5D,QAAI,SAAS;AACb,QAAI,SAAS;AACb,QAAI,UAAU;AAEd,UAAM,OAAO,GAAG,QAAQ,CAAC,SAAiB;AACxC,gBAAU,KAAK,SAAS;AAAA,IAC1B,CAAC;AACD,UAAM,OAAO,GAAG,QAAQ,CAAC,SAAiB;AACxC,gBAAU,KAAK,SAAS;AAAA,IAC1B,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,UAAU;AAC3B,UAAI,QAAS;AACb,gBAAU;AACV;AAAA,QACE,IAAI,gBAAgB,GAAG,OAAO,YAAY,MAAM,OAAO,IAAI;AAAA,UACzD,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,UAAI,QAAS;AACb,gBAAU;AACV,UAAI,SAAS,GAAG;AACd;AAAA,UACE,IAAI;AAAA,YACF,GAAG,OAAO,qBAAqB,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,UACvD;AAAA,QACF;AACA;AAAA,MACF;AACA,cAAQ,OAAO,KAAK,CAAC;AAAA,IACvB,CAAC;AAID,UAAM,MAAM,GAAG,SAAS,MAAM;AAAA,IAAC,CAAC;AAChC,UAAM,MAAM,MAAM,KAAK;AACvB,UAAM,MAAM,IAAI;AAAA,EAClB,CAAC;AACH;AAEA,SAAS,YAAY,KAAa,QAAwB;AACxD,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,oBAAoB,KAAK,OAAO,GAAG;AACtC,UAAM,IAAI;AAAA,MACR,2BAA2B,MAAM,wDAAwD,QAAQ,MAAM;AAAA,IACzG;AAAA,EACF;AACA,SAAO,OAAO,KAAK,SAAS,KAAK;AACnC;AAIO,IAAM,cAAN,MAA6C;AAAA,EACjC;AAAA,EAEjB,YAAY,KAAa;AACvB,SAAK,MAAM,YAAY,KAAK,uBAAuB;AAAA,EACrD;AAAA,EAEA,MAAM,SAA0B;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,OAAO,KAA4B;AACvC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,YAA2B;AAC/B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAIO,IAAM,cAAN,MAA6C;AAAA,EAClD,MAAM,SAAsC;AAC1C,QAAI;AACF,YAAM,MAAM,MAAM,YAAY,YAAY;AAAA,QACxC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,YAAY,KAAK,gBAAgB;AAAA,IAC1C,SAAS,KAAK;AAEZ,UAAI,eAAe,mBAAmB,sBAAsB,KAAK,IAAI,OAAO,GAAG;AAC7E,eAAO;AAAA,MACT;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,KAA4B;AACvC,UAAM,MAAM,IAAI,SAAS,KAAK;AAC9B,UAAM,YAAY,YAAY;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YAA2B;AAC/B,UAAM,YAAY,YAAY;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAIO,IAAM,gBAAN,MAA+C;AAAA,EACpD,MAAM,SAAsC;AAC1C,QAAI;AACF,YAAM,MAAM,MAAM,YAAY,eAAe;AAAA,QAC3C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,UAAI,CAAC,IAAK,QAAO;AACjB,aAAO,YAAY,KAAK,aAAa;AAAA,IACvC,SAAS,KAAK;AAGZ,UAAI,eAAe,mBAAmB,uCAAuC,KAAK,IAAI,OAAO,GAAG;AAC9F,eAAO;AAAA,MACT;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,KAA4B;AACvC,UAAM,MAAM,IAAI,SAAS,KAAK;AAC9B,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QACA,GAAG,QAAQ;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,YAA2B;AAC/B,UAAM,YAAY,eAAe;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAIO,IAAM,kBAAN,MAAiD;AAAA,EACtD,IAAY,WAAmB;AAC7B,WAAO,KAAK,QAAQ,GAAG,iBAAiB,kBAAkB;AAAA,EAC5D;AAAA,EAEQ,kBAAkB,GAAmB;AAC3C,WAAO,EAAE,QAAQ,MAAM,IAAI;AAAA,EAC7B;AAAA,EAEQ,eAAe,QAA0B;AAG/C,UAAM,UAAU,OAAO,KAAK,QAAQ,SAAS,EAAE,SAAS,QAAQ;AAChE,WAAO,CAAC,cAAc,mBAAmB,mBAAmB,OAAO;AAAA,EACrE;AAAA,EAEA,MAAM,SAAsC;AAC1C,QAAI;AACF,YAAM,SACJ,qCAAqC,KAAK,kBAAkB,KAAK,QAAQ,CAAC;AAAA;AAAA;AAG5E,YAAM,MAAM,MAAM,YAAY,cAAc,KAAK,eAAe,MAAM,CAAC;AACvE,aAAO,YAAY,KAAK,OAAO;AAAA,IACjC,SAAS,KAAK;AAEZ,UAAI,eAAe,mBAAmB,8CAA8C,KAAK,IAAI,OAAO,GAAG;AACrG,eAAO;AAAA,MACT;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,KAA4B;AACvC,UAAM,MAAM,KAAK,QAAQ,GAAG,eAAe;AAC3C,UAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,UAAM,MAAM,IAAI,SAAS,KAAK;AAC9B,UAAM,cAAc,KAAK,kBAAkB,KAAK,QAAQ;AACxD,UAAM,SACJ,WAAW,GAAG;AAAA;AAAA;AAAA;AAAA,4BAIe,WAAW;AAC1C,UAAM,YAAY,cAAc,KAAK,eAAe,MAAM,CAAC;AAAA,EAC7D;AAAA,EAEA,MAAM,YAA2B;AAC/B,UAAM,SAAS,6BAA6B,KAAK,kBAAkB,KAAK,QAAQ,CAAC;AACjF,UAAM,YAAY,cAAc,KAAK,eAAe,MAAM,CAAC;AAAA,EAC7D;AACF;AASO,SAAS,sBACd,SACiB;AACjB,MAAI,SAAS,UAAU;AACrB,WAAO,QAAQ;AAAA,EACjB;AAEA,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,QAAQ;AACV,WAAO,IAAI,YAAY,MAAM;AAAA,EAC/B;AAEA,QAAM,KAAK,SAAS,aAAa,SAAS;AAC1C,UAAQ,IAAI;AAAA,IACV,KAAK;AACH,aAAO,IAAI,YAAY;AAAA,IACzB,KAAK;AACH,aAAO,IAAI,cAAc;AAAA,IAC3B,KAAK;AACH,aAAO,IAAI,gBAAgB;AAAA,IAC7B;AACE,YAAM,IAAI,gBAAgB,sCAAsC,EAAE,EAAE;AAAA,EACxE;AACF;;;AC5TA,SAAS,aAAa,gBAAgB,wBAAwB;AAC9D,SAAS,QAAQ,YAAAC,WAAU,WAAW,QAAQ,SAAAC,cAAa;AAC3D,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAC9B,SAAS,WAAAC,gBAAe;AAMxB,IAAM,YAAY;AAClB,IAAM,YAAY;AAClB,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AAYhB,IAAM,kBAAN,MAAsB;AAAA,EACV;AAAA,EACA;AAAA,EAEjB,YAAY,SAAiC;AAC3C,SAAK,WAAW,QAAQ;AACxB,SAAK,WACH,QAAQ,YACRC,MAAKC,SAAQ,GAAG,iBAAiB,oBAAoB;AAAA,EACzD;AAAA,EAEA,MAAM,IAAI,KAA8C;AACtD,SAAK,aAAa,GAAG;AACrB,QAAI,CAAC,MAAM,KAAK,iBAAiB,EAAG,QAAO;AAC3C,UAAM,YAAY,MAAM,KAAK,sBAAsB;AACnD,UAAM,QAAQ,MAAM,KAAK,WAAW,SAAS;AAC7C,WAAO,OAAO,OAAO,MAAM,aAAa,GAAG,IACvC,MAAM,YAAY,GAAG,IACrB;AAAA,EACN;AAAA,EAEA,MAAM,IAAI,KAAaC,aAAuC;AAC5D,SAAK,aAAa,GAAG;AACrB,UAAM,YAAY,MAAM,KAAK,sBAAsB;AACnD,UAAM,QAAQ,MAAM,KAAK,WAAW,SAAS;AAC7C,UAAM,YAAY,GAAG,IAAIA;AACzB,UAAM,KAAK,YAAY,OAAO,SAAS;AAAA,EACzC;AAAA,EAEA,MAAM,OAAO,KAA+B;AAC1C,SAAK,aAAa,GAAG;AACrB,QAAI,CAAC,MAAM,KAAK,iBAAiB,EAAG,QAAO;AAC3C,UAAM,YAAY,MAAM,KAAK,sBAAsB;AACnD,UAAM,QAAQ,MAAM,KAAK,WAAW,SAAS;AAC7C,QAAI,CAAC,OAAO,OAAO,MAAM,aAAa,GAAG,GAAG;AAC1C,aAAO;AAAA,IACT;AACA,WAAO,MAAM,YAAY,GAAG;AAC5B,UAAM,KAAK,YAAY,OAAO,SAAS;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAA0B;AAC9B,QAAI,CAAC,MAAM,KAAK,iBAAiB,EAAG,QAAO,CAAC;AAC5C,UAAM,YAAY,MAAM,KAAK,sBAAsB;AACnD,UAAM,QAAQ,MAAM,KAAK,WAAW,SAAS;AAC7C,WAAO,OAAO,KAAK,MAAM,WAAW;AAAA,EACtC;AAAA;AAAA,EAIQ,aAAa,KAAmB;AACtC,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,gBAAgB,kCAAkC;AAAA,IAC9D;AACA,QAAI,QAAQ,aAAa;AACvB,YAAM,IAAI;AAAA,QACR,mBAAmB,GAAG;AAAA,MACxB;AAAA,IACF;AACA,QAAI,IAAI,SAAS,gBAAgB;AAC/B,YAAM,IAAI;AAAA,QACR,4BAA4B,IAAI,MAAM,oBAAoB,cAAc;AAAA,MAC1E;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,mBAAqC;AACjD,QAAI;AACF,YAAM,OAAO,KAAK,QAAQ;AAC1B,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,wBAAyC;AACrD,UAAM,WAAW,MAAM,KAAK,SAAS,OAAO;AAC5C,QAAI,SAAU,QAAO;AACrB,UAAM,MAAM,YAAY,EAAE;AAC1B,UAAM,KAAK,SAAS,OAAO,GAAG;AAC9B,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,wBAAyC;AACrD,UAAM,WAAW,MAAM,KAAK,SAAS,OAAO;AAC5C,QAAI,CAAC,UAAU;AACb,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,SAAS,MAAc,KAAqB;AAClD,UAAM,KAAK,YAAY,SAAS;AAChC,UAAM,SAAS,eAAe,WAAW,KAAK,EAAE;AAChD,UAAM,YAAY,OAAO,OAAO,CAAC,OAAO,OAAO,IAAI,GAAG,OAAO,MAAM,CAAC,CAAC;AACrE,UAAM,UAAU,OAAO,WAAW;AAClC,WAAO,OAAO,OAAO,CAAC,IAAI,WAAW,OAAO,CAAC;AAAA,EAC/C;AAAA,EAEQ,SAAS,MAAc,KAAqB;AAClD,UAAM,YAAY,YAAY;AAC9B,QAAI,KAAK,SAAS,WAAW;AAC3B,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,KAAK,KAAK,SAAS,GAAG,SAAS;AACrC,UAAM,UAAU,KAAK,SAAS,KAAK,SAAS,eAAe;AAC3D,UAAM,aAAa,KAAK,SAAS,WAAW,KAAK,SAAS,eAAe;AAEzE,QAAI;AACF,YAAM,WAAW,iBAAiB,WAAW,KAAK,EAAE;AACpD,eAAS,WAAW,OAAO;AAC3B,aAAO,OAAO,OAAO,CAAC,SAAS,OAAO,UAAU,GAAG,SAAS,MAAM,CAAC,CAAC;AAAA,IACtE,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR;AAAA,QACA,EAAE,OAAO,IAAI;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,WAAW,WAAiD;AACxE,QAAI;AACJ,QAAI;AACF,YAAM,MAAMC,UAAS,KAAK,QAAQ;AAAA,IACpC,SAAS,KAAK;AACZ,UAAK,IAA8B,SAAS,UAAU;AACpD,eAAO,EAAE,SAAS,GAAG,aAAa,CAAC,EAAE;AAAA,MACvC;AACA,YAAM,IAAI;AAAA,QACR,oCAAqC,IAAc,OAAO;AAAA,QAC1D,EAAE,OAAO,IAAI;AAAA,MACf;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,SAAS,KAAK,SAAS;AAE9C,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,UAAU,SAAS,OAAO,CAAC;AAAA,IAC/C,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR;AAAA,QACA,EAAE,OAAO,IAAI;AAAA,MACf;AAAA,IACF;AAEA,UAAM,SAAS,0BAA0B,UAAU,IAAI;AACvD,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,EAAE,OAAO,OAAO,MAAM;AAAA,MACxB;AAAA,IACF;AAEA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAc,YAAY,OAA4B,WAAkC;AACtF,UAAM,OAAO,OAAO,KAAK,KAAK,UAAU,KAAK,GAAG,OAAO;AACvD,UAAM,YAAY,KAAK,SAAS,MAAM,SAAS;AAE/C,UAAM,MAAMC,SAAQ,KAAK,QAAQ;AACjC,UAAMC,OAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AAEpC,UAAM,UAAU,GAAG,KAAK,QAAQ,QAAQ,QAAQ,GAAG;AACnD,UAAM,UAAU,SAAS,WAAW,EAAE,MAAM,IAAM,CAAC;AACnD,UAAM,OAAO,SAAS,KAAK,QAAQ;AAAA,EACrC;AACF;;;AvB7KA,SAAS,yBACP,WACoC;AACpC,QAAM,SAA6C,CAAC;AACpD,aAAW,CAAC,MAAM,YAAY,KAAK,OAAO,QAAQ,SAAS,GAAG;AAC5D,QAAI,aAAa,gBAAgB,aAAa,SAAS;AACrD,aAAO,IAAI,IAAI,aAAa;AAAA,IAC9B;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,QAAQ,EACb;AAAA,EACC;AACF,EACC,QAAQ,WAAW,EACnB,OAAO,uBAAuB,qBAAqB,EACnD,OAAO,cAAc,sDAAsD,EAC3E,OAAO,cAAc,oDAAoD,EACzE,OAAO,OAAO,YAAY;AACzB,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,QAAM,eAAe,oBAAI,IAAyB;AAElD,MAAI;AACF,UAAM,aAAa,kBAAkB,EAAE,YAAY,QAAQ,OAAO,CAAC;AACnE,QAAI,SAAS,MAAM,WAAW,EAAE,WAAW,CAAC;AAC5C,UAAM,YAAY,iBAAiB,MAAM;AAEzC,UAAM,SAAS,aAAa;AAAA,MAC1B,OAAO,OAAO,QAAQ;AAAA,MACtB,QAAQ,OAAO,QAAQ;AAAA,IACzB,CAAC;AAGD,QAAI,QAAQ,UAAU;AACpB,YAAM,UAAU,OAAO,QAAQ,SAAS;AACxC,cAAQ,OAAO,MAAM,oBAAe,QAAQ,MAAM,mBAAmB,QAAQ,WAAW,IAAI,KAAK,GAAG;AAAA,CAAI;AACxG,iBAAW,CAAC,MAAM,YAAY,KAAK,SAAS;AAC1C,cAAM,YAAY,cAAc,YAAY,IACxC,UACC,aAAkC;AACvC,cAAM,WAAW,aAAa,SAAS;AACvC,cAAM,SAAS,WAAW,KAAK,QAAQ,MAAM;AAC7C,gBAAQ,OAAO,MAAM,KAAK,IAAI,KAAK,SAAS,IAAI,MAAM;AAAA,CAAI;AAAA,MAC5D;AACA;AAAA,IACF;AAEA,UAAM,eAAe,IAAI,aAAa;AACtC,UAAM,kBAAkB,IAAI,gBAAgB,EAAE,UAAU,sBAAsB,EAAE,CAAC;AACjF,sBAAkB,IAAI,gBAAgB,EAAE,QAAQ,cAAc,QAAQ,gBAAgB,CAAC;AAEvF,UAAM,sBAAsB,yBAAyB,SAAS;AAE9D,UAAM,eAAe,IAAI;AAAA,MACvB,OAAO,QAAQ;AAAA,MACf;AAAA,IACF;AAEA,wBAAoB,IAAI,kBAAkB,cAAc,YAAY;AAEpE,eAAW,CAAC,MAAM,YAAY,KAAK,OAAO,QAAQ,SAAS,GAAG;AAC5D,UAAI,aAAa,SAAS,WAAW;AACnC,qBAAa,IAAI,MAAM,IAAI,YAAY,aAAa,QAAQ,SAAS,CAAC;AAAA,MACxE;AAAA,IACF;AAEA,aAAS,IAAI,aAAa;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB,CAAC,SAAS,gBAAiB,UAAU,IAAI;AAAA,MAC5D,gBAAgB,CAAC,SAAS,aAAa,IAAI,IAAI;AAAA,MAC/C,WAAW,QAAQ;AAAA,IACrB,CAAC;AACD,UAAM,OAAO,MAAM;AAEnB,UAAM,cAAc,OAAO,KAAK,SAAS,EAAE;AAC3C,WAAO,KAAK,GAAG,QAAQ,iCAA4B,WAAW,mBAAmB,gBAAgB,IAAI,KAAK,GAAG,IAAI,EAAE,WAAW,SAAS,CAAC;AAGxI,UAAM,iBAAiB,OAAO,cAA6B;AACzD,YAAM,OAAO,YAAY,QAAQ,SAAS;AAG1C,UAAI,KAAK,OAAO,UAAU;AACxB,eAAO,SAAS,KAAK,OAAO,QAAQ;AACpC,eAAO,KAAK,wBAAwB,KAAK,OAAO,QAAQ,IAAI,EAAE,WAAW,SAAS,CAAC;AAAA,MACrF;AAEA,UAAI,KAAK,OAAO,wBAAwB,QAAW;AACjD,wBAAiB,oBAAoB,KAAK,OAAO,mBAAmB;AACpE,eAAO,KAAK,oCAAoC,KAAK,OAAO,mBAAmB,KAAK,EAAE,WAAW,SAAS,CAAC;AAAA,MAC7G;AAEA,UAAI,KAAK,OAAO,gBAAgB,SAAS,GAAG;AAC1C,eAAO;AAAA,UACL,sBAAsB,KAAK,OAAO,gBAAgB,KAAK,IAAI,CAAC;AAAA,UAC5D,EAAE,WAAW,SAAS;AAAA,QACxB;AAAA,MACF;AAGA,YAAM,eAAe,iBAAiB,SAAS;AAC/C,YAAM,mBAAmB,yBAAyB,YAAY;AAC9D,mBAAa,OAAO,UAAU,QAAQ,YAAY,gBAAgB;AAElE,UAAI,KAAK,OAAO,YAAY;AAC1B,eAAO,KAAK,0BAA0B,KAAK,OAAO,UAAU,IAAI,EAAE,WAAW,SAAS,CAAC;AAAA,MACzF;AAGA,iBAAW,CAAC,MAAM,YAAY,KAAK,OAAO,QAAQ,YAAY,GAAG;AAC/D,cAAM,KAAK,aAAa,SAAS;AACjC,cAAM,WAAW,aAAa,IAAI,IAAI;AACtC,YAAI,MAAM,UAAU;AAClB,mBAAS,YAAY,EAAE;AAAA,QACzB,WAAW,IAAI;AACb,uBAAa,IAAI,MAAM,IAAI,YAAY,EAAE,CAAC;AAAA,QAC5C,WAAW,UAAU;AACnB,mBAAS,QAAQ;AACjB,uBAAa,OAAO,IAAI;AAAA,QAC1B;AAAA,MACF;AAEA,iBAAW,QAAQ,aAAa,KAAK,GAAG;AACtC,YAAI,EAAE,QAAQ,eAAe;AAC3B,uBAAa,IAAI,IAAI,EAAG,QAAQ;AAChC,uBAAa,OAAO,IAAI;AAAA,QAC1B;AAAA,MACF;AAGA,YAAM,mBACJ,KAAK,QAAQ,MAAM,SAAS,KAC5B,KAAK,QAAQ,QAAQ,SAAS,KAC9B,KAAK,QAAQ,UAAU,SAAS,KAChC,KAAK,QAAQ,QAAQ,SAAS;AAEhC,UAAI,kBAAkB;AACpB,cAAM,gBAAiB,gBAAgB,MAAM,SAAS;AAAA,MACxD;AAEA,eAAS;AAAA,IACX;AAKA,oBAAgB,WAAW,EAAE,KAAK,CAAC,WAAW;AAC5C,YAAM,QAAQ,aAAa,oBAAoB,EAAE;AACjD,UAAI,OAAO,OAAO,WAAW,GAAG;AAC9B,eAAO,KAAK,GAAG,QAAQ,iBAAY,KAAK,eAAe,OAAO,SAAS,YAAY,EAAE,WAAW,SAAS,CAAC;AAAA,MAC5G,OAAO;AACL,eAAO,KAAK,GAAG,QAAQ,iBAAY,KAAK,eAAe,OAAO,SAAS,aAAa,OAAO,OAAO,MAAM,YAAY,EAAE,WAAW,SAAS,CAAC;AAC3I,mBAAW,KAAK,OAAO,QAAQ;AAC7B,iBAAO,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,KAAK,IAAI,EAAE,WAAW,SAAS,CAAC;AAAA,QAC/D;AAAA,MACF;AACA,uBAAiB,kBAAkB;AAAA,IACrC,CAAC,EAAE,MAAM,MAAM;AAAA,IAEf,CAAC,EAAE,QAAQ,MAAM;AAGf,sBAAgB,IAAI,cAAc,EAAE,YAAY,OAAO,CAAC;AACxD,oBAAc,MAAM,gBAAgB,MAAM;AAAA,IAC5C,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,QAAI,eAAe,aAAa;AAC9B,cAAQ,OAAO,MAAM,UAAU,IAAI,OAAO;AAAA,CAAI;AAC9C,iBAAW,SAAS,IAAI,QAAQ;AAC9B,gBAAQ,OAAO,MAAM,KAAK,MAAM,IAAI,KAAK,MAAM,OAAO;AAAA,CAAI;AAAA,MAC5D;AACA,cAAQ,WAAW;AACnB;AAAA,IACF,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AAEA,MAAI,eAAe;AACnB,QAAM,WAAW,YAAY;AAC3B,QAAI,aAAc;AAClB,mBAAe;AACf,QAAI;AACF,qBAAe,KAAK;AACpB,yBAAmB,QAAQ;AAC3B,iBAAW,MAAM,aAAa,OAAO,GAAG;AACtC,WAAG,QAAQ;AAAA,MACb;AACA,mBAAa,MAAM;AACnB,UAAI,iBAAiB;AACnB,cAAM,gBAAgB,SAAS;AAAA,MACjC;AACA,UAAI,QAAQ;AACV,cAAM,OAAO,MAAM;AAAA,MACrB;AAAA,IACF,QAAQ;AAAA,IAER;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,GAAG,UAAU,QAAQ;AAC7B,UAAQ,GAAG,WAAW,QAAQ;AAChC,CAAC;AAIH,SAAS,YAA6B;AACpC,QAAM,kBAAkB,OAAO;AAC/B,MAAI,QAAQ,MAAM,OAAO;AACvB,WAAO,QAAQ,QAAQ,EAAE;AAAA,EAC3B;AACA,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAmB,CAAC;AAC1B,QAAI,QAAQ;AACZ,YAAQ,MAAM,GAAG,QAAQ,CAAC,UAAkB;AAC1C,eAAS,MAAM;AACf,UAAI,QAAQ,iBAAiB;AAC3B,gBAAQ,MAAM,QAAQ;AACtB,eAAO,IAAI,MAAM,kCAAkC,CAAC;AACpD;AAAA,MACF;AACA,aAAO,KAAK,KAAK;AAAA,IACnB,CAAC;AACD,YAAQ,MAAM;AAAA,MAAG;AAAA,MAAO,MACtB,QAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO,EAAE,KAAK,CAAC;AAAA,IACxD;AACA,YAAQ,MAAM,GAAG,SAAS,MAAM;AAAA,EAClC,CAAC;AACH;AAEA,SAAS,OAAOC,aAAoC;AAClD,QAAM,OAAO,CAAC,UAA0B;AAGtC,QAAI,MAAM,SAAS,GAAI,QAAO;AAC9B,WAAO,MAAM,MAAM,GAAG,CAAC,IAAI,SAAS,MAAM,MAAM,EAAE;AAAA,EACpD;AAEA,MAAIA,YAAW,SAAS,UAAU;AAChC,WAAO,EAAE,GAAGA,aAAY,OAAO,KAAKA,YAAW,KAAK,EAAE;AAAA,EACxD;AAEA,QAAM,SAAS,EAAE,GAAGA,YAAW;AAC/B,SAAO,eAAe,KAAK,OAAO,YAAY;AAC9C,MAAI,mBAAmB,UAAU,OAAO,eAAe;AACrD,WAAO,gBAAgB,KAAK,OAAO,aAAa;AAAA,EAClD;AACA,SAAO;AACT;AAIA,IAAM,aAAa,QAChB,QAAQ,YAAY,EACpB,YAAY,2BAA2B;AAE1C,WACG,QAAQ,mBAAmB,EAC3B,YAAY,uEAAuE,EACnF,OAAO,iBAAiB,8CAA8C,EACtE,OAAO,OAAO,KAAa,OAA2B,YAA+B;AACpF,MAAI;AACF,QAAI;AAEJ,QAAI,QAAQ,MAAM;AAEhB,UAAI;AACJ,UAAI;AACF,iBAAS,KAAK,MAAM,QAAQ,IAAI;AAAA,MAClC,QAAQ;AACN,gBAAQ,OAAO,MAAM,uBAAuB;AAC5C,gBAAQ,WAAW;AACnB;AAAA,MACF;AACA,YAAM,SAAS,iBAAiB,UAAU,MAAM;AAChD,UAAI,CAAC,OAAO,SAAS;AACnB,gBAAQ,OAAO,MAAM,8BAA8B,OAAO,MAAM,OAAO;AAAA,CAAI;AAC3E,gBAAQ,WAAW;AACnB;AAAA,MACF;AACA,aAAO,OAAO;AAAA,IAChB,WAAW,OAAO;AAEhB,aAAO,EAAE,MAAM,UAAU,MAAM;AAAA,IACjC,OAAO;AAEL,YAAM,QAAQ,MAAM,UAAU;AAC9B,UAAI,CAAC,OAAO;AACV,gBAAQ,OAAO,MAAM,kFAAkF;AACvG,gBAAQ,WAAW;AACnB;AAAA,MACF;AAEA,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,cAAM,SAAS,iBAAiB,UAAU,MAAM;AAChD,YAAI,OAAO,SAAS;AAClB,iBAAO,OAAO;AAAA,QAChB,OAAO;AACL,iBAAO,EAAE,MAAM,UAAU,OAAO,MAAM;AAAA,QACxC;AAAA,MACF,QAAQ;AACN,eAAO,EAAE,MAAM,UAAU,OAAO,MAAM;AAAA,MACxC;AAAA,IACF;AAEA,UAAM,WAAW,sBAAsB;AACvC,UAAM,QAAQ,IAAI,gBAAgB,EAAE,SAAS,CAAC;AAC9C,UAAM,MAAM,IAAI,KAAK,IAAI;AACzB,YAAQ,OAAO,MAAM,eAAe,GAAG;AAAA,CAAY;AAAA,EACrD,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,kBAAkB,IAAI,UAAU,OAAO,GAAG;AACzE,YAAQ,OAAO,MAAM,UAAU,OAAO;AAAA,CAAI;AAC1C,YAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEH,WACG,QAAQ,WAAW,EACnB,YAAY,8BAA8B,EAC1C,OAAO,iBAAiB,yBAAyB,EACjD,OAAO,OAAO,KAAa,YAAsC;AAChE,MAAI;AACF,UAAM,WAAW,sBAAsB;AACvC,UAAM,QAAQ,IAAI,gBAAgB,EAAE,SAAS,CAAC;AAC9C,UAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAEhC,QAAI,CAAC,MAAM;AACT,cAAQ,OAAO,MAAM,eAAe,GAAG;AAAA,CAAe;AACtD,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,UAAM,SAAS,QAAQ,aAAa,OAAO,OAAO,IAAI;AACtD,YAAQ,OAAO,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAAA,EAC7D,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,kBAAkB,IAAI,UAAU,OAAO,GAAG;AACzE,YAAQ,OAAO,MAAM,UAAU,OAAO;AAAA,CAAI;AAC1C,YAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEH,WACG,QAAQ,cAAc,EACtB,YAAY,4BAA4B,EACxC,OAAO,OAAO,QAAgB;AAC7B,MAAI;AACF,UAAM,WAAW,sBAAsB;AACvC,UAAM,QAAQ,IAAI,gBAAgB,EAAE,SAAS,CAAC;AAC9C,UAAM,UAAU,MAAM,MAAM,OAAO,GAAG;AAEtC,QAAI,SAAS;AACX,cAAQ,OAAO,MAAM,eAAe,GAAG;AAAA,CAAa;AAAA,IACtD,OAAO;AACL,cAAQ,OAAO,MAAM,eAAe,GAAG;AAAA,CAAe;AACtD,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,kBAAkB,IAAI,UAAU,OAAO,GAAG;AACzE,YAAQ,OAAO,MAAM,UAAU,OAAO;AAAA,CAAI;AAC1C,YAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEH,WACG,QAAQ,MAAM,EACd,YAAY,iCAAiC,EAC7C,OAAO,YAAY;AAClB,MAAI;AACF,UAAM,WAAW,sBAAsB;AACvC,UAAM,QAAQ,IAAI,gBAAgB,EAAE,SAAS,CAAC;AAC9C,UAAM,OAAO,MAAM,MAAM,KAAK;AAE9B,eAAW,KAAK,MAAM;AACpB,cAAQ,OAAO,MAAM,IAAI,IAAI;AAAA,IAC/B;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,kBAAkB,IAAI,UAAU,OAAO,GAAG;AACzE,YAAQ,OAAO,MAAM,UAAU,OAAO;AAAA,CAAI;AAC1C,YAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEH,QAAQ,MAAM;","names":["z","providers","ErrorCode","McpError","z","credential","credential","readFile","mkdir","dirname","join","homedir","join","homedir","credential","readFile","dirname","mkdir","credential"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config/schema.ts","../src/constants.ts","../src/config/loader.ts","../src/config/json-schema.ts","../src/config/config-diff.ts","../src/config/config-watcher.ts","../src/logging/index.ts","../src/server/bridge-server.ts","../src/server/tool-registry.ts","../src/server/tool-namespacing.ts","../src/search/tool-search-service.ts","../src/server/session-stats.ts","../src/server/rate-limiter.ts","../src/policy/policy-engine.ts","../src/upstream/base-client.ts","../src/upstream/http-client.ts","../src/credentials/errors.ts","../src/credentials/types.ts","../src/credentials/resolve-templates.ts","../src/upstream/stdio-client.ts","../src/upstream/upstream-manager.ts","../src/credentials/keychain.ts","../src/credentials/credential-store.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport {\n loadConfig,\n ConfigError,\n resolveConfigPath,\n diffConfigs,\n ConfigWatcher,\n} from \"./config/index.js\";\nimport { resolveUpstreams, isStdioServer } from \"./config/schema.js\";\nimport type { ServerBridgeConfig, ServerConfig, HttpServerConfig } from \"./config/schema.js\";\nimport { BridgeServer } from \"./server/index.js\";\nimport { RateLimiter } from \"./server/rate-limiter.js\";\nimport { ToolRegistry } from \"./server/tool-registry.js\";\nimport { ToolSearchService } from \"./search/index.js\";\nimport type { DiscoveryMode } from \"./search/index.js\";\nimport { PolicyEngine } from \"./policy/index.js\";\nimport { UpstreamManager } from \"./upstream/index.js\";\nimport { APP_NAME, APP_VERSION } from \"./constants.js\";\nimport { createLogger } from \"./logging/index.js\";\nimport {\n CredentialStore,\n CredentialSchema,\n CredentialError,\n createKeychainAdapter,\n type Credential,\n} from \"./credentials/index.js\";\n\nfunction buildServerBridgeConfigs(\n upstreams: Record<string, ServerConfig>,\n): Record<string, ServerBridgeConfig> {\n const result: Record<string, ServerBridgeConfig> = {};\n for (const [name, serverConfig] of Object.entries(upstreams)) {\n if (\"_bridge\" in serverConfig && serverConfig._bridge) {\n result[name] = serverConfig._bridge;\n }\n }\n return result;\n}\n\nconst program = new Command();\n\nprogram\n .name(APP_NAME)\n .description(\n \"Aggregates multiple MCP servers behind a single STDIO interface\",\n )\n .version(APP_VERSION)\n .option(\"-c, --config <path>\", \"path to config file\")\n .option(\"--validate\", \"validate config and list upstream servers, then exit\")\n .option(\"--stats\", \"include session_stats in search_tools responses\")\n .addOption(\n new Option(\n \"--discovery-mode <mode>\",\n \"how searched tools are surfaced: search (response only), tools_list (native MCP tools list only), both (default)\",\n ).choices([\"search\", \"tools_list\", \"both\"]).default(\"both\"),\n )\n .action(async (options) => {\n let server: BridgeServer | undefined;\n let upstreamManager: UpstreamManager | undefined;\n let toolSearchService: ToolSearchService | undefined;\n let configWatcher: ConfigWatcher | undefined;\n const rateLimiters = new Map<string, RateLimiter>();\n\n try {\n const configPath = resolveConfigPath({ configPath: options.config });\n let config = await loadConfig({ configPath });\n const upstreams = resolveUpstreams(config);\n\n const logger = createLogger({\n level: config._bridge.logLevel,\n format: config._bridge.logFormat,\n });\n\n // --validate: print config summary and exit (always human-readable CLI output)\n if (options.validate) {\n const entries = Object.entries(upstreams);\n process.stderr.write(`Config OK — ${entries.length} upstream server${entries.length === 1 ? \"\" : \"s\"}\\n`);\n for (const [name, serverConfig] of entries) {\n const transport = isStdioServer(serverConfig)\n ? \"stdio\"\n : (serverConfig as HttpServerConfig).type;\n const category = serverConfig._bridge?.category;\n const suffix = category ? ` [${category}]` : \"\";\n process.stderr.write(` ${name} (${transport})${suffix}\\n`);\n }\n return;\n }\n\n const toolRegistry = new ToolRegistry();\n const credentialStore = new CredentialStore({ keychain: createKeychainAdapter() });\n upstreamManager = new UpstreamManager({ config, toolRegistry, logger, credentialStore });\n\n const serverBridgeConfigs = buildServerBridgeConfigs(upstreams);\n\n const policyEngine = new PolicyEngine(\n config._bridge.toolPolicy,\n serverBridgeConfigs,\n );\n\n const discoveryMode = options.discoveryMode as DiscoveryMode;\n toolSearchService = new ToolSearchService(toolRegistry, policyEngine, discoveryMode);\n\n for (const [name, serverConfig] of Object.entries(upstreams)) {\n if (serverConfig._bridge?.rateLimit) {\n rateLimiters.set(name, new RateLimiter(serverConfig._bridge.rateLimit));\n }\n }\n\n server = new BridgeServer({\n toolRegistry,\n toolSearchService,\n policyEngine,\n getUpstreamClient: (name) => upstreamManager!.getClient(name),\n getRateLimiter: (name) => rateLimiters.get(name),\n showStats: options.stats === true,\n onSearchStats: (stats) => {\n logger.info(\n `tokens saved: ${stats.tokens_saved.toLocaleString()} (baseline: ${stats.baseline_tokens.toLocaleString()}, bridge: ${stats.bridge_tokens.toLocaleString()})`,\n { component: \"stats\" },\n );\n },\n });\n await server.start();\n\n const serverCount = Object.keys(upstreams).length;\n logger.info(`${APP_NAME} running — connecting to ${serverCount} upstream server${serverCount === 1 ? \"\" : \"s\"}`, { component: \"bridge\" });\n\n // Config hot-reload handler\n const onConfigReload = async (newConfig: typeof config) => {\n const diff = diffConfigs(config, newConfig);\n\n // Bridge-level hot-reloadable settings\n if (diff.bridge.logLevel) {\n logger.setLevel(diff.bridge.logLevel);\n logger.info(`log level changed to ${diff.bridge.logLevel}`, { component: \"reload\" });\n }\n\n if (diff.bridge.healthCheckInterval !== undefined) {\n upstreamManager!.restartHealthChecks(diff.bridge.healthCheckInterval);\n logger.info(`health check interval changed to ${diff.bridge.healthCheckInterval}s`, { component: \"reload\" });\n }\n\n if (diff.bridge.requiresRestart.length > 0) {\n logger.warn(\n `config changed for ${diff.bridge.requiresRestart.join(\", \")} — restart required`,\n { component: \"reload\" },\n );\n }\n\n // Always update the policy engine with the full new state\n const newUpstreams = resolveUpstreams(newConfig);\n const newBridgeConfigs = buildServerBridgeConfigs(newUpstreams);\n policyEngine.update(newConfig._bridge.toolPolicy, newBridgeConfigs);\n\n if (diff.bridge.toolPolicy) {\n logger.info(`tool policy changed to ${diff.bridge.toolPolicy}`, { component: \"reload\" });\n }\n\n // Update rate limiters from new config\n for (const [name, serverConfig] of Object.entries(newUpstreams)) {\n const rl = serverConfig._bridge?.rateLimit;\n const existing = rateLimiters.get(name);\n if (rl && existing) {\n existing.reconfigure(rl);\n } else if (rl) {\n rateLimiters.set(name, new RateLimiter(rl));\n } else if (existing) {\n existing.dispose();\n rateLimiters.delete(name);\n }\n }\n // Remove rate limiters for servers no longer in config\n for (const name of rateLimiters.keys()) {\n if (!(name in newUpstreams)) {\n rateLimiters.get(name)!.dispose();\n rateLimiters.delete(name);\n }\n }\n\n // Server-level changes\n const hasServerChanges =\n diff.servers.added.length > 0 ||\n diff.servers.removed.length > 0 ||\n diff.servers.reconnect.length > 0 ||\n diff.servers.updated.length > 0;\n\n if (hasServerChanges) {\n await upstreamManager!.applyConfigDiff(diff, newConfig);\n }\n\n config = newConfig;\n };\n\n // Connect upstreams in the background — tools appear as each server connects.\n // Config watching starts only after initial connections settle to avoid\n // race conditions between connectAll and applyConfigDiff.\n upstreamManager.connectAll().then((result) => {\n const tools = toolRegistry.listRegisteredTools().length;\n if (result.failed.length === 0) {\n logger.info(`${APP_NAME} ready — ${tools} tools from ${result.connected} servers`, { component: \"bridge\" });\n } else {\n logger.warn(`${APP_NAME} ready — ${tools} tools from ${result.connected} servers (${result.failed.length} failed)`, { component: \"bridge\" });\n for (const f of result.failed) {\n logger.error(`${f.name}: ${f.error}`, { component: \"bridge\" });\n }\n }\n upstreamManager?.startHealthChecks();\n }).catch(() => {\n // Individual failures already logged by UpstreamManager.\n }).finally(() => {\n // Start config watching after initial connections settle to avoid\n // race conditions between connectAll and applyConfigDiff.\n configWatcher = new ConfigWatcher({ configPath, logger });\n configWatcher.start(onConfigReload, config);\n });\n } catch (err) {\n if (err instanceof ConfigError) {\n process.stderr.write(`Error: ${err.message}\\n`);\n for (const issue of err.issues) {\n process.stderr.write(` ${issue.path}: ${issue.message}\\n`);\n }\n process.exitCode = 1;\n return;\n } else {\n throw err;\n }\n }\n\n let shuttingDown = false;\n const shutdown = async () => {\n if (shuttingDown) return;\n shuttingDown = true;\n try {\n configWatcher?.stop();\n toolSearchService?.dispose();\n for (const rl of rateLimiters.values()) {\n rl.dispose();\n }\n rateLimiters.clear();\n if (upstreamManager) {\n await upstreamManager.closeAll();\n }\n if (server) {\n await server.close();\n }\n } catch {\n // Don't prevent exit on close error\n }\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n });\n\n// --- Credential helpers ---\n\nfunction readStdin(): Promise<string> {\n const MAX_STDIN_BYTES = 1024 * 1024; // 1 MB\n if (process.stdin.isTTY) {\n return Promise.resolve(\"\");\n }\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let total = 0;\n process.stdin.on(\"data\", (chunk: Buffer) => {\n total += chunk.length;\n if (total > MAX_STDIN_BYTES) {\n process.stdin.destroy();\n reject(new Error(\"stdin input too large (max 1 MB)\"));\n return;\n }\n chunks.push(chunk);\n });\n process.stdin.on(\"end\", () =>\n resolve(Buffer.concat(chunks).toString(\"utf-8\").trim()),\n );\n process.stdin.on(\"error\", reject);\n });\n}\n\nfunction redact(credential: Credential): Credential {\n const mask = (value: string): string => {\n // Tokens under 20 chars are fully masked to avoid leaking most of the value.\n // Longer tokens show first 4 and last 4 characters.\n if (value.length < 20) return \"****\";\n return value.slice(0, 4) + \"****\" + value.slice(-4);\n };\n\n if (credential.type === \"secret\") {\n return { ...credential, value: mask(credential.value) };\n }\n\n const result = { ...credential };\n result.access_token = mask(result.access_token);\n if (\"refresh_token\" in result && result.refresh_token) {\n result.refresh_token = mask(result.refresh_token);\n }\n return result;\n}\n\n// --- Credential subcommand ---\n\nconst credential = program\n .command(\"credential\")\n .description(\"Manage stored credentials\");\n\ncredential\n .command(\"set <key> [value]\")\n .description(\"Store a credential (plain string, --json for typed, or pipe to stdin)\")\n .option(\"--json <json>\", \"typed credential JSON (bearer/oauth2/secret)\")\n .action(async (key: string, value: string | undefined, options: { json?: string }) => {\n try {\n let cred: Credential;\n\n if (options.json) {\n // --json flag: parse as typed credential\n let parsed: unknown;\n try {\n parsed = JSON.parse(options.json);\n } catch {\n process.stderr.write(\"Error: invalid JSON\\n\");\n process.exitCode = 1;\n return;\n }\n const result = CredentialSchema.safeParse(parsed);\n if (!result.success) {\n process.stderr.write(`Error: invalid credential: ${result.error.message}\\n`);\n process.exitCode = 1;\n return;\n }\n cred = result.data;\n } else if (value) {\n // Positional arg: store as simple secret\n cred = { type: \"secret\", value };\n } else {\n // Read from stdin\n const input = await readStdin();\n if (!input) {\n process.stderr.write(\"Error: no credential provided (pass as argument, use --json, or pipe to stdin)\\n\");\n process.exitCode = 1;\n return;\n }\n // Try JSON parse first; if it fails, treat as plain string\n try {\n const parsed = JSON.parse(input);\n const result = CredentialSchema.safeParse(parsed);\n if (result.success) {\n cred = result.data;\n } else {\n cred = { type: \"secret\", value: input };\n }\n } catch {\n cred = { type: \"secret\", value: input };\n }\n }\n\n const keychain = createKeychainAdapter();\n const store = new CredentialStore({ keychain });\n await store.set(key, cred);\n process.stderr.write(`Credential \"${key}\" stored\\n`);\n } catch (err) {\n const message = err instanceof CredentialError ? err.message : String(err);\n process.stderr.write(`Error: ${message}\\n`);\n process.exitCode = 1;\n }\n });\n\ncredential\n .command(\"get <key>\")\n .description(\"Retrieve a stored credential\")\n .option(\"--show-secret\", \"show full secret values\")\n .action(async (key: string, options: { showSecret?: boolean }) => {\n try {\n const keychain = createKeychainAdapter();\n const store = new CredentialStore({ keychain });\n const cred = await store.get(key);\n\n if (!cred) {\n process.stderr.write(`Credential \"${key}\" not found\\n`);\n process.exitCode = 1;\n return;\n }\n\n const output = options.showSecret ? cred : redact(cred);\n process.stdout.write(JSON.stringify(output, null, 2) + \"\\n\");\n } catch (err) {\n const message = err instanceof CredentialError ? err.message : String(err);\n process.stderr.write(`Error: ${message}\\n`);\n process.exitCode = 1;\n }\n });\n\ncredential\n .command(\"delete <key>\")\n .description(\"Delete a stored credential\")\n .action(async (key: string) => {\n try {\n const keychain = createKeychainAdapter();\n const store = new CredentialStore({ keychain });\n const deleted = await store.delete(key);\n\n if (deleted) {\n process.stderr.write(`Credential \"${key}\" deleted\\n`);\n } else {\n process.stderr.write(`Credential \"${key}\" not found\\n`);\n process.exitCode = 1;\n }\n } catch (err) {\n const message = err instanceof CredentialError ? err.message : String(err);\n process.stderr.write(`Error: ${message}\\n`);\n process.exitCode = 1;\n }\n });\n\ncredential\n .command(\"list\")\n .description(\"List all stored credential keys\")\n .action(async () => {\n try {\n const keychain = createKeychainAdapter();\n const store = new CredentialStore({ keychain });\n const keys = await store.list();\n\n for (const k of keys) {\n process.stdout.write(k + \"\\n\");\n }\n } catch (err) {\n const message = err instanceof CredentialError ? err.message : String(err);\n process.stderr.write(`Error: ${message}\\n`);\n process.exitCode = 1;\n }\n });\n\nprogram.parse();\n","import { z } from \"zod\";\nimport { APP_NAME } from \"../constants.js\";\n\n// --- Tool policy ---\n\nexport const ToolPolicySchema = z.enum([\"always\", \"never\", \"prompt\"]);\n\n// --- Per-server auth config ---\n\nexport const ServerOAuthConfigSchema = z.object({\n type: z.literal(\"oauth2\"),\n clientId: z.string(),\n endpoints: z.object({\n authorization: z.string().url(),\n token: z.string().url(),\n }),\n scopes: z.array(z.string()).optional(),\n});\n\nexport const RateLimitConfigSchema = z.object({\n maxCalls: z.number().int().positive(),\n windowSeconds: z.number().int().positive(),\n});\n\nexport const ServerBridgeConfigSchema = z\n .object({\n auth: ServerOAuthConfigSchema.optional(),\n toolPolicy: ToolPolicySchema.optional(),\n tools: z.record(z.string(), ToolPolicySchema).optional(),\n category: z.string().optional(),\n rateLimit: RateLimitConfigSchema.optional(),\n })\n .strict();\n\n// --- Server configs ---\n\nexport const StdioServerConfigSchema = z.object({\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n _bridge: ServerBridgeConfigSchema.optional(),\n});\n\nexport const HttpServerConfigSchema = z.object({\n type: z\n .enum([\"streamable-http\", \"http\", \"streamableHttp\", \"sse\"])\n .default(\"streamable-http\"),\n url: z.string().url(),\n headers: z.record(z.string(), z.string()).optional(),\n _bridge: ServerBridgeConfigSchema.optional(),\n});\n\n// HTTP first: it has a required `type` field that disambiguates\nexport const ServerConfigSchema = z.union([\n HttpServerConfigSchema,\n StdioServerConfigSchema,\n]);\n\n// --- Global bridge config ---\n\nexport const GlobalBridgeConfigSchema = z\n .object({\n port: z.number().int().min(1).max(65535).default(19875),\n logLevel: z\n .enum([\"debug\", \"info\", \"warn\", \"error\"])\n .default(\"info\"),\n logFormat: z.enum([\"text\", \"json\"]).default(\"text\"),\n maxUpstreamConnections: z.number().int().positive().default(1000),\n connectionTimeout: z.number().int().positive().default(30),\n idleTimeout: z.number().int().positive().default(600),\n healthCheckInterval: z.number().int().min(0).default(30),\n toolPolicy: ToolPolicySchema.default(\"always\"),\n })\n .strict();\n\n// --- Top-level config ---\n\nexport const BridgeConfigSchema = z.object({\n mcpServers: z.record(z.string(), ServerConfigSchema).default({}),\n upstreamMcpServers: z.record(z.string(), ServerConfigSchema).optional(),\n upstreamServers: z.record(z.string(), ServerConfigSchema).optional(),\n servers: z.record(z.string(), ServerConfigSchema).optional(),\n context_servers: z.record(z.string(), ServerConfigSchema).optional(),\n _bridge: GlobalBridgeConfigSchema.default(\n GlobalBridgeConfigSchema.parse({}),\n ),\n});\n\n// --- Inferred types ---\n\nexport type ToolPolicy = z.infer<typeof ToolPolicySchema>;\nexport type RateLimitConfig = z.infer<typeof RateLimitConfigSchema>;\nexport type ServerOAuthConfig = z.infer<typeof ServerOAuthConfigSchema>;\nexport type ServerBridgeConfig = z.infer<typeof ServerBridgeConfigSchema>;\nexport type StdioServerConfig = z.infer<typeof StdioServerConfigSchema>;\nexport type HttpServerConfig = z.infer<typeof HttpServerConfigSchema>;\nexport type ServerConfig = z.infer<typeof ServerConfigSchema>;\nexport type GlobalBridgeConfig = z.infer<typeof GlobalBridgeConfigSchema>;\nexport type BridgeConfig = z.infer<typeof BridgeConfigSchema>;\n\n// --- Upstream resolution ---\n\n/**\n * Resolves which servers to use as upstreams.\n *\n * Returns the union of all present config keys. On duplicate names,\n * earlier sources win:\n * `upstreamMcpServers` > `upstreamServers` > `servers` > `context_servers` > `mcpServers`.\n *\n * Self-exclusion: entries from `mcpServers` and `context_servers` whose\n * `command` or `args` contain the app name are filtered out.\n */\nexport function resolveUpstreams(\n config: BridgeConfig,\n): Record<string, ServerConfig> {\n const result: Record<string, ServerConfig> = {};\n\n // mcpServers (lowest priority, with self-exclusion)\n for (const [name, server] of Object.entries(config.mcpServers)) {\n if (isStdioServer(server)) {\n const tokens = [server.command, ...(server.args ?? [])];\n if (tokens.some((t) => t.includes(APP_NAME))) {\n continue;\n }\n }\n result[name] = server;\n }\n\n // context_servers (with self-exclusion, above mcpServers)\n if (config.context_servers) {\n for (const [name, server] of Object.entries(config.context_servers)) {\n if (isStdioServer(server)) {\n const tokens = [server.command, ...(server.args ?? [])];\n if (tokens.some((t) => t.includes(APP_NAME))) {\n continue;\n }\n }\n result[name] = server;\n }\n }\n\n // servers (above context_servers)\n if (config.servers) {\n Object.assign(result, config.servers);\n }\n\n // upstreamServers (above servers)\n if (config.upstreamServers) {\n Object.assign(result, config.upstreamServers);\n }\n\n // upstreamMcpServers (highest priority)\n if (config.upstreamMcpServers) {\n Object.assign(result, config.upstreamMcpServers);\n }\n\n return result;\n}\n\n// --- Type guards ---\n\nexport function isHttpServer(config: ServerConfig): config is HttpServerConfig {\n return \"type\" in config;\n}\n\nexport function isStdioServer(\n config: ServerConfig,\n): config is StdioServerConfig {\n return \"command\" in config;\n}\n","export const APP_NAME = \"crabeye-mcp-bridge\";\nexport const APP_VERSION = \"0.1.0\";\n\nexport const CREDENTIALS_DIR = `.${APP_NAME}`;\nexport const CREDENTIALS_FILENAME = \"credentials.enc\";\n","import { readFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport { BridgeConfigSchema, type BridgeConfig } from \"./schema.js\";\n\nexport interface ConfigIssue {\n path: string;\n message: string;\n}\n\nexport class ConfigError extends Error {\n readonly issues: ConfigIssue[];\n\n constructor(message: string, issues: ConfigIssue[] = []) {\n super(message);\n this.name = \"ConfigError\";\n this.issues = issues;\n }\n}\n\nfunction flattenZodIssue(\n issue: z.ZodIssue,\n parentPath: string[] = [],\n): ConfigIssue[] {\n const fullPath = [...parentPath, ...issue.path.map(String)];\n\n // Union errors: dig into each branch and surface the specifics\n if (issue.code === \"invalid_union\" && \"errors\" in issue) {\n const unionErrors = issue.errors as z.ZodIssue[][];\n return unionErrors.flatMap((branchErrors) =>\n branchErrors.flatMap((e) => flattenZodIssue(e, fullPath)),\n );\n }\n\n return [{ path: fullPath.join(\".\"), message: issue.message }];\n}\n\nfunction formatZodIssues(error: z.ZodError): ConfigIssue[] {\n return error.issues.flatMap((issue) => flattenZodIssue(issue));\n}\n\nexport interface LoadConfigOptions {\n configPath?: string;\n}\n\nexport function resolveConfigPath(options?: LoadConfigOptions): string {\n if (options?.configPath) {\n return options.configPath;\n }\n\n const envPath = process.env.MCP_BRIDGE_CONFIG;\n if (envPath) {\n return envPath;\n }\n\n throw new ConfigError(\n \"No config file specified. Use --config <path> or set MCP_BRIDGE_CONFIG.\",\n );\n}\n\nexport async function loadConfig(\n options?: LoadConfigOptions,\n): Promise<BridgeConfig> {\n const configPath = resolveConfigPath(options);\n\n let raw: string;\n try {\n raw = await readFile(configPath, \"utf-8\");\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n throw new ConfigError(`Config file not found: ${configPath}`);\n }\n throw new ConfigError(\n `Failed to read config file: ${configPath} (${code ?? \"unknown error\"})`,\n );\n }\n\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch {\n throw new ConfigError(`Invalid JSON in config file: ${configPath}`);\n }\n\n const result = BridgeConfigSchema.safeParse(json);\n if (!result.success) {\n throw new ConfigError(\n \"Config validation failed\",\n formatZodIssues(result.error),\n );\n }\n\n return result.data;\n}\n","import { z } from \"zod\";\nimport { BridgeConfigSchema } from \"./schema.js\";\n\nexport function generateJsonSchema(): Record<string, unknown> {\n return z.toJSONSchema(BridgeConfigSchema) as Record<string, unknown>;\n}\n","import type { BridgeConfig, ServerConfig, ToolPolicy } from \"./schema.js\";\nimport { resolveUpstreams, isStdioServer } from \"./schema.js\";\nimport type { LogLevel } from \"../logging/index.js\";\n\nexport interface ConfigDiff {\n servers: {\n added: Array<{ name: string; config: ServerConfig }>;\n removed: string[];\n reconnect: Array<{ name: string; config: ServerConfig }>;\n updated: Array<{ name: string; config: ServerConfig }>;\n };\n bridge: {\n logLevel?: LogLevel;\n healthCheckInterval?: number;\n toolPolicy?: ToolPolicy;\n requiresRestart: string[];\n };\n}\n\nfunction connectionFields(config: ServerConfig): Record<string, unknown> {\n if (isStdioServer(config)) {\n return {\n command: config.command,\n args: config.args,\n env: config.env,\n };\n }\n return {\n type: config.type,\n url: config.url,\n headers: config.headers,\n };\n}\n\n/** Key-order-independent stringify for deep comparison. */\nfunction stableStringify(value: unknown): string {\n if (value === undefined) return \"undefined\";\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) {\n return \"[\" + value.map(stableStringify).join(\",\") + \"]\";\n }\n const keys = Object.keys(value as Record<string, unknown>).sort();\n return (\n \"{\" +\n keys\n .map(\n (k) =>\n JSON.stringify(k) +\n \":\" +\n stableStringify((value as Record<string, unknown>)[k]),\n )\n .join(\",\") +\n \"}\"\n );\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return stableStringify(a) === stableStringify(b);\n}\n\nexport function diffConfigs(oldConfig: BridgeConfig, newConfig: BridgeConfig): ConfigDiff {\n const oldServers = resolveUpstreams(oldConfig);\n const newServers = resolveUpstreams(newConfig);\n\n const oldNames = new Set(Object.keys(oldServers));\n const newNames = new Set(Object.keys(newServers));\n\n const added: ConfigDiff[\"servers\"][\"added\"] = [];\n const removed: string[] = [];\n const reconnect: ConfigDiff[\"servers\"][\"reconnect\"] = [];\n const updated: ConfigDiff[\"servers\"][\"updated\"] = [];\n\n for (const name of newNames) {\n if (!oldNames.has(name)) {\n added.push({ name, config: newServers[name] });\n }\n }\n\n for (const name of oldNames) {\n if (!newNames.has(name)) {\n removed.push(name);\n }\n }\n\n for (const name of newNames) {\n if (!oldNames.has(name)) continue;\n const oldCfg = oldServers[name];\n const newCfg = newServers[name];\n\n if (!deepEqual(connectionFields(oldCfg), connectionFields(newCfg))) {\n reconnect.push({ name, config: newCfg });\n } else if (!deepEqual(oldCfg._bridge, newCfg._bridge)) {\n updated.push({ name, config: newCfg });\n }\n }\n\n // Bridge-level changes\n const ob = oldConfig._bridge;\n const nb = newConfig._bridge;\n const bridge: ConfigDiff[\"bridge\"] = { requiresRestart: [] };\n\n if (ob.logLevel !== nb.logLevel) bridge.logLevel = nb.logLevel;\n if (ob.healthCheckInterval !== nb.healthCheckInterval) bridge.healthCheckInterval = nb.healthCheckInterval;\n if (ob.toolPolicy !== nb.toolPolicy) bridge.toolPolicy = nb.toolPolicy;\n\n const restartFields = [\"port\", \"logFormat\", \"maxUpstreamConnections\", \"connectionTimeout\", \"idleTimeout\"] as const;\n for (const field of restartFields) {\n if (ob[field] !== nb[field]) {\n bridge.requiresRestart.push(field);\n }\n }\n\n return {\n servers: { added, removed, reconnect, updated },\n bridge,\n };\n}\n","import { watch, type FSWatcher } from \"node:fs\";\nimport { dirname, basename } from \"node:path\";\nimport type { Logger } from \"../logging/index.js\";\nimport { createNoopLogger } from \"../logging/index.js\";\nimport { loadConfig } from \"./loader.js\";\nimport type { BridgeConfig } from \"./schema.js\";\n\nexport interface ConfigWatcherOptions {\n configPath: string;\n debounceMs?: number;\n logger?: Logger;\n}\n\nexport class ConfigWatcher {\n private _configPath: string;\n private _debounceMs: number;\n private _logger: Logger;\n private _watcher: FSWatcher | undefined;\n private _timer: ReturnType<typeof setTimeout> | undefined;\n private _listener: ((config: BridgeConfig) => void | Promise<void>) | undefined;\n private _lastJson: string | undefined;\n private _reloading = false;\n private _pendingReload = false;\n\n constructor(options: ConfigWatcherOptions) {\n this._configPath = options.configPath;\n this._debounceMs = options.debounceMs ?? 500;\n this._logger = options.logger ?? createNoopLogger();\n }\n\n start(\n listener: (config: BridgeConfig) => void | Promise<void>,\n initialConfig?: BridgeConfig,\n ): void {\n if (this._watcher) return;\n\n this._listener = listener;\n\n if (initialConfig) {\n this._lastJson = JSON.stringify(initialConfig);\n }\n\n this._logger.debug(\"watching config file\", {\n component: \"config-watcher\",\n path: this._configPath,\n });\n\n // Watch the directory — more reliable across platforms when files are\n // atomically replaced (write-to-temp + rename).\n const dir = dirname(this._configPath);\n const fileName = basename(this._configPath);\n\n this._watcher = watch(dir, (eventType, changedFile) => {\n // changedFile matches our config, or platform didn't provide a filename\n if (changedFile === fileName || (eventType === \"rename\" && !changedFile)) {\n this._scheduleReload();\n }\n });\n }\n\n stop(): void {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n if (this._watcher) {\n this._watcher.close();\n this._watcher = undefined;\n }\n this._listener = undefined;\n this._reloading = false;\n this._pendingReload = false;\n }\n\n private _scheduleReload(): void {\n if (this._timer) clearTimeout(this._timer);\n this._timer = setTimeout(() => {\n this._timer = undefined;\n this._reload();\n }, this._debounceMs);\n }\n\n private _reload(): void {\n if (this._reloading) {\n this._pendingReload = true;\n return;\n }\n this._reloading = true;\n\n loadConfig({ configPath: this._configPath }).then(\n async (config) => {\n const json = JSON.stringify(config);\n if (json === this._lastJson) {\n this._logger.debug(\"config unchanged, skipping reload\", {\n component: \"config-watcher\",\n });\n this._finishReload();\n return;\n }\n this._logger.info(\"config changed, reloading\", {\n component: \"config-watcher\",\n });\n try {\n await this._listener?.(config);\n this._lastJson = json;\n } catch (err) {\n this._logger.error(\"reload listener threw\", {\n component: \"config-watcher\",\n error: err instanceof Error ? err.message : String(err),\n });\n }\n this._finishReload();\n },\n (err) => {\n this._logger.warn(\"failed to reload config\", {\n component: \"config-watcher\",\n error: err instanceof Error ? err.message : String(err),\n });\n this._finishReload();\n },\n );\n }\n\n private _finishReload(): void {\n this._reloading = false;\n if (this._pendingReload) {\n this._pendingReload = false;\n this._reload();\n }\n }\n}\n","export type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nexport interface Logger {\n debug(message: string, context?: Record<string, unknown>): void;\n info(message: string, context?: Record<string, unknown>): void;\n warn(message: string, context?: Record<string, unknown>): void;\n error(message: string, context?: Record<string, unknown>): void;\n child(defaultContext: Record<string, unknown>): Logger;\n setLevel(level: LogLevel): void;\n}\n\nconst LEVEL_VALUE: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface CreateLoggerOptions {\n level: LogLevel;\n format: \"text\" | \"json\";\n}\n\nfunction pad(n: number, width: number): string {\n return String(n).padStart(width, \"0\");\n}\n\nfunction formatTime(): string {\n const d = new Date();\n return `${pad(d.getHours(), 2)}:${pad(d.getMinutes(), 2)}:${pad(d.getSeconds(), 2)}.${pad(d.getMilliseconds(), 3)}`;\n}\n\nfunction formatText(\n level: LogLevel,\n message: string,\n context: Record<string, unknown>,\n): string {\n const tag = level.toUpperCase().padEnd(5);\n const component = context.component as string | undefined;\n const server = context.server as string | undefined;\n let prefix = \"\";\n if (component && server) {\n prefix = `[${component}:${server}] `;\n } else if (component) {\n prefix = `[${component}] `;\n } else if (server) {\n prefix = `[${server}] `;\n }\n\n // Collect extra keys (everything except component/server)\n const extra: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(context)) {\n if (k !== \"component\" && k !== \"server\" && v !== undefined) {\n extra[k] = v;\n }\n }\n const suffix = Object.keys(extra).length > 0\n ? \" \" + Object.entries(extra).map(([k, v]) => `${k}=${typeof v === \"object\" && v !== null ? JSON.stringify(v) : String(v)}`).join(\" \")\n : \"\";\n\n const safeMessage = message.replace(/\\n/g, \"\\\\n\");\n return `${formatTime()} ${tag} ${prefix}${safeMessage}${suffix}\\n`;\n}\n\nfunction formatJson(\n level: LogLevel,\n message: string,\n context: Record<string, unknown>,\n): string {\n return JSON.stringify({\n ...context,\n time: new Date().toISOString(),\n level,\n msg: message,\n }) + \"\\n\";\n}\n\nclass LoggerImpl implements Logger {\n private _shared: { threshold: number };\n private _format: \"text\" | \"json\";\n private _defaultContext: Record<string, unknown>;\n\n constructor(\n options: CreateLoggerOptions,\n defaultContext: Record<string, unknown> = {},\n shared?: { threshold: number },\n ) {\n this._shared = shared ?? { threshold: LEVEL_VALUE[options.level] };\n this._format = options.format;\n this._defaultContext = defaultContext;\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this._log(\"debug\", message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this._log(\"info\", message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this._log(\"warn\", message, context);\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n this._log(\"error\", message, context);\n }\n\n setLevel(level: LogLevel): void {\n this._shared.threshold = LEVEL_VALUE[level];\n }\n\n child(defaultContext: Record<string, unknown>): Logger {\n return new LoggerImpl(\n { level: \"debug\", format: this._format },\n { ...this._defaultContext, ...defaultContext },\n this._shared,\n );\n }\n\n private _log(\n level: LogLevel,\n message: string,\n context?: Record<string, unknown>,\n ): void {\n if (LEVEL_VALUE[level] < this._shared.threshold) return;\n const merged = context\n ? { ...this._defaultContext, ...context }\n : this._defaultContext;\n const line =\n this._format === \"json\"\n ? formatJson(level, message, merged)\n : formatText(level, message, merged);\n process.stderr.write(line);\n }\n}\n\nexport function createLogger(options: CreateLoggerOptions): Logger {\n return new LoggerImpl(options);\n}\n\n/** A logger that discards all output. Useful in tests. */\nexport function createNoopLogger(): Logger {\n const noop = () => {};\n const logger: Logger = {\n debug: noop,\n info: noop,\n warn: noop,\n error: noop,\n child: () => logger,\n setLevel: noop,\n };\n return logger;\n}\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n ListToolsRequestSchema,\n CallToolRequestSchema,\n ErrorCode,\n McpError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { Readable, Writable } from \"node:stream\";\nimport { ToolRegistry } from \"./tool-registry.js\";\nimport { parseNamespacedName } from \"./tool-namespacing.js\";\nimport type { UpstreamClient } from \"../upstream/types.js\";\nimport {\n ToolSearchService,\n SEARCH_TOOL_NAME,\n RUN_TOOL_NAME,\n searchToolDefinition,\n runToolDefinition,\n} from \"../search/index.js\";\nimport type { SearchToolsParams } from \"../search/index.js\";\nimport type { PolicyEngine } from \"../policy/index.js\";\nimport { SessionStats } from \"./session-stats.js\";\nimport type { SessionStatsSnapshot } from \"./session-stats.js\";\nimport type { RateLimiter } from \"./rate-limiter.js\";\nimport { APP_NAME, APP_VERSION } from \"../constants.js\";\n\nexport interface BridgeServerOptions {\n stdin?: Readable;\n stdout?: Writable;\n toolRegistry?: ToolRegistry;\n toolSearchService?: ToolSearchService;\n policyEngine?: PolicyEngine;\n getUpstreamClient?: (name: string) => UpstreamClient | undefined;\n getRateLimiter?: (name: string) => RateLimiter | undefined;\n showStats?: boolean;\n onSearchStats?: (stats: SessionStatsSnapshot) => void;\n}\n\nexport class BridgeServer {\n private server: Server;\n private toolRegistry: ToolRegistry;\n private toolSearchService: ToolSearchService | undefined;\n private policyEngine: PolicyEngine | undefined;\n private sessionStats: SessionStats | undefined;\n private unsubscribe: (() => void) | undefined;\n private options: BridgeServerOptions;\n\n constructor(options?: BridgeServerOptions) {\n this.options = options ?? {};\n this.toolRegistry = options?.toolRegistry ?? new ToolRegistry();\n this.toolSearchService = options?.toolSearchService;\n this.policyEngine = options?.policyEngine;\n\n if (this.toolSearchService) {\n this.sessionStats = new SessionStats(\n this.toolRegistry,\n [searchToolDefinition, runToolDefinition],\n );\n }\n\n const instructions = [\n \"This MCP bridge connects you to many external tools and services.\",\n \"You MUST call search_tools BEFORE any of the following:\",\n \"- The user mentions a service, tool, or MCP server by name\",\n \"- The user says 'use X', 'with X', 'in X', 'on X', 'via X', or 'through X'\",\n \"- The user asks you to perform an action that might be handled by an external service (create, update, query, send, manage, etc.)\",\n \"- The user asks what tools or integrations are available, or what you can do\",\n \"- The user asks 'can you...?' about a capability that could involve an external service\",\n \"- You are about to claim a tool is unavailable or that you cannot perform an action — search first, then answer\",\n \"- You are about to fall back to a web search for something that might be available as a tool\",\n \"\",\n \"Discovery workflow:\",\n '1. Start broad: search by provider or category to get summaries: { \"queries\": [{ \"provider\": \"linear\" }] }',\n '2. Drill in: use a tool filter or expand_tools to get full definitions: { \"queries\": [{ \"provider\": \"linear\", \"expand_tools\": true }] } or { \"queries\": [{ \"tool\": \"create\", \"provider\": \"linear\" }] }',\n \"\",\n \"Results are always grouped by provider: results[].providers[].tools[]\",\n \"After discovering tools, use run_tool to execute them. You can also call auto-enabled tools directly by their namespaced name.\",\n \"When in doubt, search — it is always better to search and find nothing than to miss an available tool.\",\n ].join(\"\\n\");\n\n this.server = new Server(\n { name: APP_NAME, version: APP_VERSION },\n {\n capabilities: { tools: { listChanged: true } },\n instructions,\n },\n );\n\n this.server.setRequestHandler(ListToolsRequestSchema, () => {\n if (this.toolSearchService) {\n return { tools: this.toolSearchService.getVisibleTools() };\n }\n return { tools: this.toolRegistry.listTools() };\n });\n\n this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n // Handle search_tools call\n if (this.toolSearchService && name === SEARCH_TOOL_NAME) {\n const params = (args ?? {}) as unknown as SearchToolsParams;\n\n if (!Array.isArray(params.queries) || params.queries.length === 0) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Error: 'queries' must be a non-empty array of query objects.\",\n },\n ],\n isError: true,\n };\n }\n\n for (let i = 0; i < params.queries.length; i++) {\n const q = params.queries[i];\n if (!q.tool && !q.provider && !q.category) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Error: queries[${i}] must have at least one of 'tool', 'provider', or 'category'.`,\n },\n ],\n isError: true,\n };\n }\n }\n\n const result = this.toolSearchService.search(params);\n let response: object = result;\n if (this.sessionStats) {\n const responseJson = JSON.stringify(result);\n this.sessionStats.recordSearchResponse(responseJson);\n const snapshot = this.sessionStats.getSnapshot();\n if (this.options.showStats) {\n response = { session_stats: snapshot, ...result };\n }\n this.options.onSearchStats?.(snapshot);\n }\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(response) }],\n };\n }\n\n // Handle run_tool call\n if (this.toolSearchService && name === RUN_TOOL_NAME) {\n const toolName = (args as { name?: string })?.name;\n const toolArgs = (args as { arguments?: Record<string, unknown> })?.arguments;\n\n if (!toolName) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Error: 'name' is required — provide the full namespaced tool name (e.g. 'linear__create_issue').\",\n },\n ],\n isError: true,\n };\n }\n\n return this.routeToUpstream(toolName, toolArgs);\n }\n\n // Direct tool call (tool must be in registry)\n const registered = this.toolRegistry.getTool(name);\n if (!registered) {\n throw new McpError(\n ErrorCode.InvalidParams,\n `Unknown tool: ${name}`,\n );\n }\n\n return this.routeToUpstream(name, args);\n });\n\n if (this.toolSearchService) {\n this.unsubscribe = this.toolSearchService.onVisibleToolsChanged(() => {\n this.server.sendToolListChanged().catch(() => {\n // Ignore errors when no client is connected\n });\n });\n } else {\n this.unsubscribe = this.toolRegistry.onChanged(() => {\n this.server.sendToolListChanged().catch(() => {\n // Ignore errors when no client is connected\n });\n });\n }\n }\n\n private async routeToUpstream(\n name: string,\n args?: Record<string, unknown>,\n ): Promise<CallToolResult> {\n const parsed = parseNamespacedName(name);\n if (!parsed) {\n throw new McpError(\n ErrorCode.InvalidParams,\n `Invalid tool name (missing namespace): ${name}`,\n );\n }\n\n if (this.policyEngine) {\n const elicitFn = this.server.elicitInput.bind(this.server);\n await this.policyEngine.enforce(parsed.source, parsed.toolName, args, elicitFn);\n }\n\n const getClient = this.options.getUpstreamClient;\n if (!getClient) {\n throw new McpError(\n ErrorCode.InternalError,\n `No upstream client resolver configured`,\n );\n }\n\n const client = getClient(parsed.source);\n if (!client) {\n throw new McpError(\n ErrorCode.InternalError,\n `Upstream server not found: ${parsed.source}`,\n );\n }\n\n if (client.status !== \"connected\") {\n throw new McpError(\n ErrorCode.InternalError,\n `Upstream server \"${parsed.source}\" is not connected (status: ${client.status})`,\n );\n }\n\n const rateLimiter = this.options.getRateLimiter?.(parsed.source);\n if (rateLimiter) {\n try {\n await rateLimiter.acquire();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new McpError(ErrorCode.InternalError, message);\n }\n }\n\n try {\n return await client.callTool({\n name: parsed.toolName,\n arguments: args,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new McpError(\n ErrorCode.InternalError,\n `Upstream server \"${parsed.source}\" error: ${message}`,\n );\n }\n }\n\n async connect(transport: Transport): Promise<void> {\n await this.server.connect(transport);\n }\n\n async start(): Promise<void> {\n const transport = new StdioServerTransport(\n this.options.stdin,\n this.options.stdout,\n );\n await this.connect(transport);\n }\n\n async close(): Promise<void> {\n this.unsubscribe?.();\n this.unsubscribe = undefined;\n this.sessionStats?.dispose();\n await this.server.close();\n }\n\n getToolRegistry(): ToolRegistry {\n return this.toolRegistry;\n }\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport interface RegisteredTool {\n source: string;\n tool: Tool;\n}\n\nexport type ToolListChangedCallback = () => void;\n\nexport class ToolRegistry {\n private tools = new Map<string, RegisteredTool>();\n private sourceIndex = new Map<string, Set<string>>();\n private sourceCategories = new Map<string, string>();\n private listeners = new Set<ToolListChangedCallback>();\n\n listTools(): Tool[] {\n return Array.from(this.tools.values()).map((r) => r.tool);\n }\n\n listRegisteredTools(): RegisteredTool[] {\n return Array.from(this.tools.values());\n }\n\n listSources(): { name: string; toolCount: number }[] {\n const result: { name: string; toolCount: number }[] = [];\n for (const [name, toolNames] of this.sourceIndex) {\n result.push({ name, toolCount: toolNames.size });\n }\n return result;\n }\n\n getTool(name: string): RegisteredTool | undefined {\n return this.tools.get(name);\n }\n\n setCategoryForSource(source: string, category: string): void {\n this.sourceCategories.set(source, category);\n }\n\n getCategoryForSource(source: string): string | undefined {\n return this.sourceCategories.get(source);\n }\n\n removeCategoryForSource(source: string): void {\n this.sourceCategories.delete(source);\n }\n\n setToolsForSource(source: string, tools: Tool[]): void {\n const oldNames = this.sourceIndex.get(source);\n if (oldNames) {\n for (const name of oldNames) {\n this.tools.delete(name);\n }\n }\n\n const newNames = new Set<string>();\n for (const tool of tools) {\n this.tools.set(tool.name, { source, tool });\n newNames.add(tool.name);\n }\n this.sourceIndex.set(source, newNames);\n\n this.notify();\n }\n\n removeSource(source: string): void {\n const names = this.sourceIndex.get(source);\n if (!names || names.size === 0) {\n this.sourceIndex.delete(source);\n return;\n }\n\n let removed = false;\n for (const name of names) {\n const current = this.tools.get(name);\n if (current && current.source === source) {\n this.tools.delete(name);\n removed = true;\n }\n }\n this.sourceIndex.delete(source);\n this.sourceCategories.delete(source);\n\n if (removed) {\n this.notify();\n }\n }\n\n onChanged(callback: ToolListChangedCallback): () => void {\n this.listeners.add(callback);\n return () => {\n this.listeners.delete(callback);\n };\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n try {\n listener();\n } catch {\n // Listeners must not throw, but don't let one block others\n }\n }\n }\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport const NAMESPACE_SEPARATOR = \"__\";\n\n/**\n * Returns a shallow clone of `tool` with name prefixed as `${source}__${tool.name}`.\n */\nexport function namespaceTool(source: string, tool: Tool): Tool {\n return { ...tool, name: `${source}${NAMESPACE_SEPARATOR}${tool.name}` };\n}\n\n/**\n * Splits a namespaced tool name on the first `__` separator.\n * Returns `undefined` if the name contains no separator.\n */\nexport function parseNamespacedName(\n name: string,\n): { source: string; toolName: string } | undefined {\n const idx = name.indexOf(NAMESPACE_SEPARATOR);\n if (idx === -1) return undefined;\n return {\n source: name.slice(0, idx),\n toolName: name.slice(idx + NAMESPACE_SEPARATOR.length),\n };\n}\n","import MiniSearch from \"minisearch\";\nimport type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ToolRegistry } from \"../server/tool-registry.js\";\nimport { parseNamespacedName } from \"../server/tool-namespacing.js\";\nimport type { PolicyEngine } from \"../policy/index.js\";\n\nexport interface SearchQuery {\n tool?: string;\n provider?: string;\n category?: string;\n expand_tools?: boolean;\n limit?: number;\n offset?: number;\n}\n\nexport interface SearchToolsParams {\n queries: SearchQuery[];\n}\n\nexport interface SearchToolResult {\n tool_name: string;\n source: string;\n description: string;\n input_schema: object;\n disabled?: true;\n}\n\nexport interface ProviderResult {\n name: string;\n category?: string;\n tool_count: number;\n tools: SearchToolResult[];\n}\n\nexport interface QueryResult {\n providers: ProviderResult[];\n total: number;\n count: number;\n remaining: number;\n offset: number;\n limit: number;\n}\n\nexport interface SearchToolsResponse {\n results: QueryResult[];\n}\n\ntype VisibleToolsChangedCallback = () => void;\n\ninterface IndexedTool {\n id: string;\n name: string;\n originalName: string;\n description: string;\n source: string;\n category: string;\n}\n\nexport type DiscoveryMode = \"search\" | \"tools_list\" | \"both\";\n\nconst MAX_LIMIT = 50;\nconst DEFAULT_LIMIT = 10;\nconst SCORE_CUTOFF = 0.3;\n\nconst MAX_REGEX_LEN = 200;\n\nfunction parseRegex(input: string): RegExp | null {\n // Support \"regex:pattern\" prefix (preferred) and legacy /pattern/flags format\n let pattern: string;\n let flags = \"\";\n\n if (input.startsWith(\"regex:\")) {\n pattern = input.slice(6);\n } else {\n const match = /^\\/(.+)\\/([gimsuy]*)$/.exec(input);\n if (!match) return null;\n pattern = match[1];\n flags = match[2];\n }\n\n if (!pattern || pattern.length > MAX_REGEX_LEN) return null;\n\n try {\n // Use 'v' flag (unicode sets) for linear-time guarantee where available,\n // fall back to plain construction on older runtimes.\n try {\n return new RegExp(pattern, flags + \"v\");\n } catch {\n return new RegExp(pattern, flags);\n }\n } catch {\n return null;\n }\n}\n\nfunction setsEqual(a: Set<string>, b: Set<string>): boolean {\n if (a.size !== b.size) return false;\n for (const item of a) {\n if (!b.has(item)) return false;\n }\n return true;\n}\n\nfunction matchesPrefixOrRegex(value: string, pattern: string): boolean {\n const regex = parseRegex(pattern);\n if (regex) return regex.test(value);\n return value.toLowerCase().startsWith(pattern.toLowerCase());\n}\n\nexport const SEARCH_TOOL_NAME = \"search_tools\";\nexport const RUN_TOOL_NAME = \"run_tool\";\n\nexport const searchToolDefinition: Tool = {\n name: SEARCH_TOOL_NAME,\n description: [\n \"Search for available tools across all connected MCP servers. ALWAYS call this BEFORE claiming a tool is unavailable, before web search fallback, or when the user mentions any service/tool/integration.\",\n \"\",\n \"Discovery workflow:\",\n \"1. Search by provider or category to get provider summaries (tool counts, no details)\",\n \"2. If you need the tools, drill in with a tool filter or expand_tools: true to get full tool definitions\",\n \"\",\n \"When to use:\",\n \"- User mentions a service or tool by name — search by provider name first\",\n \"- User wants to perform an action (create, update, query, etc.) — search by tool keyword\",\n \"- User asks what tools or integrations are available — search by provider or category for summaries\",\n \"- User asks 'can you...?' about external capabilities — search before answering\",\n \"- You need a tool you haven't seen yet — many tools are available but not listed until searched\",\n \"\",\n \"Response shape: results[].providers[].tools[]\",\n \"Without a tool filter, only provider summaries are returned (name, category, tool_count). Use a tool query or expand_tools: true to get full tool definitions.\",\n \"Use text queries for fuzzy search or prefix with regex: for precise pattern matching.\",\n \"Each query object can have its own filters and pagination.\",\n ].join(\"\\n\"),\n inputSchema: {\n type: \"object\" as const,\n properties: {\n queries: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n tool: {\n type: \"string\",\n description:\n \"Text search query to match tool names and descriptions. \" +\n \"Prefix with regex: for regex matching (e.g. \\\"regex:.*issue.*\\\"). \" +\n \"Prefer passing several queries covering synonyms and related terms to minimize round-trips.\",\n },\n provider: {\n type: \"string\",\n description:\n \"Filter by upstream server/provider name. \" +\n \"Prefix match by default (e.g. \\\"git\\\" matches \\\"github\\\"). \" +\n \"Use regex: prefix for patterns (e.g. \\\"regex:^(linear|figma)$\\\").\",\n },\n category: {\n type: \"string\",\n description:\n \"Filter by tool category (configured via _bridge.category in server config). \" +\n \"Prefix match by default. Use regex: prefix for patterns.\",\n },\n expand_tools: {\n type: \"boolean\",\n description:\n \"When true, return full tool definitions for all tools from matched providers. \" +\n \"Without this, provider-only queries return summaries (name, tool_count) without tool details. \" +\n \"Ignored when a tool filter is present (tool filter always returns details).\",\n },\n limit: {\n type: \"number\",\n description: `Maximum number of tool results for this query (default ${DEFAULT_LIMIT}, max ${MAX_LIMIT})`,\n },\n offset: {\n type: \"number\",\n description: \"Number of tool results to skip for pagination (default 0)\",\n },\n },\n },\n description:\n \"Array of query objects. Each query is self-contained with its own filters and pagination. \" +\n \"Results are deduplicated across queries — first query wins. \" +\n \"Each query must have at least one of: tool, provider, category.\",\n },\n },\n required: [\"queries\"],\n },\n};\n\nexport const runToolDefinition: Tool = {\n name: RUN_TOOL_NAME,\n description: [\n \"Execute any tool from any connected MCP server by its full namespaced name (provider__tool_name format).\",\n \"Use this after discovering tools via search_tools. The tool does not need to be enabled first.\",\n \"Pass the exact namespaced name from search results and the required arguments.\",\n ].join(\"\\n\"),\n inputSchema: {\n type: \"object\" as const,\n properties: {\n name: {\n type: \"string\",\n description:\n \"The full namespaced tool name to call (e.g. 'linear__create_issue')\",\n },\n arguments: {\n type: \"object\",\n description: \"Arguments to pass to the tool\",\n },\n },\n required: [\"name\"],\n },\n};\n\nexport class ToolSearchService {\n private registry: ToolRegistry;\n private index: MiniSearch<IndexedTool>;\n private indexedTools = new Map<string, IndexedTool>();\n private enabledTools = new Set<string>();\n private listeners = new Set<VisibleToolsChangedCallback>();\n private unsubscribeRegistry: () => void;\n private policyEngine: PolicyEngine | undefined;\n\n private discoveryMode: DiscoveryMode;\n\n constructor(registry: ToolRegistry, policyEngine?: PolicyEngine, discoveryMode: DiscoveryMode = \"both\") {\n this.registry = registry;\n this.policyEngine = policyEngine;\n this.discoveryMode = discoveryMode;\n this.index = this.createIndex();\n this.rebuildIndex();\n this.unsubscribeRegistry = this.registry.onChanged(() => {\n this.rebuildIndex();\n });\n }\n\n private createIndex(): MiniSearch<IndexedTool> {\n return new MiniSearch<IndexedTool>({\n fields: [\"name\", \"originalName\", \"description\", \"source\"],\n storeFields: [\"name\", \"originalName\", \"description\", \"source\", \"category\"],\n searchOptions: {\n boost: { name: 3, originalName: 3, description: 1, source: 0.5 },\n prefix: (term) => term.length >= 3,\n fuzzy: (term) => (term.length >= 5 ? 0.2 : false),\n combineWith: \"AND\",\n },\n tokenize: (text) => text.split(/[\\s_\\-./]+/).filter(Boolean),\n });\n }\n\n private rebuildIndex(): void {\n this.index.removeAll();\n this.indexedTools.clear();\n\n const registered = this.registry.listRegisteredTools();\n for (const { source, tool } of registered) {\n const parsed = parseNamespacedName(tool.name);\n const originalName = parsed?.toolName ?? tool.name;\n const category = this.registry.getCategoryForSource(source) ?? \"\";\n\n const doc: IndexedTool = {\n id: tool.name,\n name: tool.name,\n originalName,\n description: tool.description ?? \"\",\n source,\n category,\n };\n this.indexedTools.set(tool.name, doc);\n this.index.add(doc);\n }\n\n // Prune enabled tools that no longer exist\n let pruned = false;\n for (const name of this.enabledTools) {\n if (!this.indexedTools.has(name)) {\n this.enabledTools.delete(name);\n pruned = true;\n }\n }\n\n if (pruned) {\n this.notifyVisibleToolsChanged();\n }\n }\n\n search(params: SearchToolsParams): SearchToolsResponse {\n const queries = params.queries;\n\n if (!queries || queries.length === 0) {\n return { results: [] };\n }\n\n // Compute total tool count per source (for ProviderResult.tool_count)\n const sourceToolCounts = new Map<string, number>();\n for (const doc of this.indexedTools.values()) {\n sourceToolCounts.set(doc.source, (sourceToolCounts.get(doc.source) ?? 0) + 1);\n }\n\n const seenTools = new Set<string>();\n const allEnabled: string[] = [];\n const results: QueryResult[] = [];\n\n for (const query of queries) {\n const hasToolFilter = query.tool !== undefined && query.tool !== \"\";\n const hasProviderFilter = query.provider !== undefined && query.provider !== \"\";\n const hasCategoryFilter = query.category !== undefined && query.category !== \"\";\n const expandTools = query.expand_tools === true;\n\n // Query with no filters: return empty result for this slot\n if (!hasToolFilter && !hasProviderFilter && !hasCategoryFilter) {\n results.push({\n providers: [],\n total: 0,\n count: 0,\n remaining: 0,\n offset: query.offset ?? 0,\n limit: query.limit ?? DEFAULT_LIMIT,\n });\n continue;\n }\n\n const limit = Math.min(\n Math.max(1, query.limit ?? DEFAULT_LIMIT),\n MAX_LIMIT,\n );\n const offset = Math.max(0, query.offset ?? 0);\n const isSummary = !hasToolFilter && !expandTools;\n\n if (isSummary) {\n // Summary mode: provider summaries only, no tool details\n const matchedSources = new Set<string>();\n for (const doc of this.indexedTools.values()) {\n if (hasProviderFilter && !matchesPrefixOrRegex(doc.source, query.provider!)) continue;\n if (hasCategoryFilter && (!doc.category || !matchesPrefixOrRegex(doc.category, query.category!))) continue;\n matchedSources.add(doc.source);\n }\n\n const providers: ProviderResult[] = [];\n let totalToolCount = 0;\n for (const source of matchedSources) {\n const count = sourceToolCounts.get(source) ?? 0;\n const category = this.registry.getCategoryForSource(source);\n providers.push({\n name: source,\n ...(category ? { category } : {}),\n tool_count: count,\n tools: [],\n });\n totalToolCount += count;\n }\n\n results.push({\n providers,\n total: totalToolCount,\n count: 0,\n remaining: 0,\n offset,\n limit,\n });\n // Do NOT add to seenTools or allEnabled in summary mode\n continue;\n }\n\n // Detail mode: collect candidate tools, then group by provider\n let toolCandidates: Set<string> | null = null;\n let providerCandidates: Set<string> | null = null;\n let categoryCandidates: Set<string> | null = null;\n\n if (hasToolFilter) {\n toolCandidates = new Set<string>();\n const regex = parseRegex(query.tool!);\n if (regex) {\n for (const [name, doc] of this.indexedTools) {\n if (\n regex.test(doc.name) ||\n regex.test(doc.originalName) ||\n regex.test(doc.description) ||\n regex.test(doc.source)\n ) {\n toolCandidates.add(name);\n }\n }\n } else {\n const searchResults = this.index.search(query.tool!);\n if (searchResults.length > 0) {\n const topScore = searchResults[0].score;\n const threshold = topScore * SCORE_CUTOFF;\n for (const r of searchResults) {\n if (r.score >= threshold) {\n toolCandidates.add(r.id as string);\n }\n }\n }\n }\n }\n\n if (hasProviderFilter) {\n providerCandidates = new Set<string>();\n for (const [name, doc] of this.indexedTools) {\n if (matchesPrefixOrRegex(doc.source, query.provider!)) {\n providerCandidates.add(name);\n }\n }\n }\n\n if (hasCategoryFilter) {\n categoryCandidates = new Set<string>();\n for (const [name, doc] of this.indexedTools) {\n if (doc.category && matchesPrefixOrRegex(doc.category, query.category!)) {\n categoryCandidates.add(name);\n }\n }\n }\n\n // Intersect all non-null filter sets (AND logic within a query)\n const filterSets = [toolCandidates, providerCandidates, categoryCandidates].filter(\n (s): s is Set<string> => s !== null,\n );\n\n let candidates: Set<string>;\n if (filterSets.length === 0) {\n candidates = new Set();\n } else if (filterSets.length === 1) {\n candidates = filterSets[0];\n } else {\n // Intersect: start with smallest set for efficiency\n const sorted = filterSets.sort((a, b) => a.size - b.size);\n candidates = new Set<string>();\n for (const name of sorted[0]) {\n if (sorted.every((s) => s.has(name))) {\n candidates.add(name);\n }\n }\n }\n\n // Deduplicate across queries — remove tools already seen\n const deduped: string[] = [];\n for (const name of candidates) {\n if (!seenTools.has(name)) {\n deduped.push(name);\n }\n }\n\n const total = deduped.length;\n const paged = deduped.slice(offset, offset + limit);\n\n // Pre-compute policy for each tool on the page\n const disabledSet = new Set<string>();\n if (this.policyEngine) {\n for (const name of paged) {\n const parsed = parseNamespacedName(name);\n if (parsed && this.policyEngine.resolvePolicy(parsed.source, parsed.toolName) === \"never\") {\n disabledSet.add(name);\n }\n }\n }\n\n // Build tools grouped by provider\n const providerToolsMap = new Map<string, SearchToolResult[]>();\n const providerOrder: string[] = [];\n\n for (const name of paged) {\n const doc = this.indexedTools.get(name);\n if (!doc) continue;\n const registered = this.registry.getTool(name);\n if (!registered) continue;\n\n if (!providerToolsMap.has(doc.source)) {\n providerToolsMap.set(doc.source, []);\n providerOrder.push(doc.source);\n }\n\n if (disabledSet.has(name)) {\n providerToolsMap.get(doc.source)!.push({\n tool_name: name,\n source: doc.source,\n description: \"\",\n input_schema: {},\n disabled: true,\n });\n } else {\n providerToolsMap.get(doc.source)!.push({\n tool_name: name,\n source: doc.source,\n description: doc.description,\n input_schema: registered.tool.inputSchema,\n });\n }\n }\n\n const providers: ProviderResult[] = [];\n for (const source of providerOrder) {\n const category = this.registry.getCategoryForSource(source);\n providers.push({\n name: source,\n ...(category ? { category } : {}),\n tool_count: sourceToolCounts.get(source) ?? 0,\n tools: providerToolsMap.get(source) ?? [],\n });\n }\n\n const toolCount = providers.reduce((sum, p) => sum + p.tools.length, 0);\n const remaining = Math.max(0, total - offset - toolCount);\n\n results.push({\n providers,\n total,\n count: toolCount,\n remaining,\n offset,\n limit,\n });\n\n // Mark tools as seen for deduplication, collect enabled tools\n for (const name of deduped) {\n seenTools.add(name);\n }\n\n // Only enable tools in the current page (skip disabled ones)\n for (const name of paged) {\n if (!disabledSet.has(name) && this.indexedTools.has(name) && this.registry.getTool(name)) {\n allEnabled.push(name);\n }\n }\n }\n\n // In \"search\" mode, don't populate enabledTools (tools only appear in search responses).\n // In \"tools_list\" and \"both\" modes, expose searched tools in the MCP tools list.\n if (this.discoveryMode !== \"search\") {\n const cappedEnabled = allEnabled.slice(0, MAX_LIMIT);\n const newEnabled = new Set(cappedEnabled);\n const changed = !setsEqual(this.enabledTools, newEnabled);\n this.enabledTools = newEnabled;\n\n if (changed) {\n this.notifyVisibleToolsChanged();\n }\n }\n\n // In \"tools_list\" mode, strip input_schema from search results\n // (the assistant gets schemas from the tools list instead).\n if (this.discoveryMode === \"tools_list\") {\n for (const queryResult of results) {\n for (const provider of queryResult.providers) {\n for (const tool of provider.tools) {\n if (!tool.disabled) {\n tool.input_schema = {};\n }\n }\n }\n }\n }\n\n return { results };\n }\n\n getVisibleTools(): Tool[] {\n const sources = this.registry.listSources().map((s) => s.name);\n const searchTool: Tool =\n sources.length > 0\n ? {\n ...searchToolDefinition,\n description:\n searchToolDefinition.description +\n `\\n\\nAvailable integrations: ${sources.join(\", \")}`,\n }\n : searchToolDefinition;\n\n const runTool: Tool = this.enabledTools.size > 0\n ? {\n ...runToolDefinition,\n description: runToolDefinition.description +\n \"\\nYou can also call the discovered tools directly by their namespaced name.\",\n }\n : runToolDefinition;\n\n const tools: Tool[] = [searchTool, runTool];\n for (const name of this.enabledTools) {\n const registered = this.registry.getTool(name);\n if (registered) {\n tools.push(registered.tool);\n }\n }\n return tools;\n }\n\n onVisibleToolsChanged(callback: VisibleToolsChangedCallback): () => void {\n this.listeners.add(callback);\n return () => {\n this.listeners.delete(callback);\n };\n }\n\n dispose(): void {\n this.unsubscribeRegistry();\n this.listeners.clear();\n }\n\n private notifyVisibleToolsChanged(): void {\n for (const listener of this.listeners) {\n try {\n listener();\n } catch {\n // Listeners must not throw, but don't let one block others\n }\n }\n }\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ToolRegistry } from \"./tool-registry.js\";\n\nexport interface SessionStatsSnapshot {\n tokens_saved: number;\n baseline_tokens: number;\n bridge_tokens: number;\n}\n\nfunction estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\nexport class SessionStats {\n private registry: ToolRegistry;\n private metaToolTokens: number = 0;\n private cumulativeSearchTokens: number = 0;\n private unsubscribe: () => void;\n\n constructor(registry: ToolRegistry, metaTools: Tool[]) {\n this.registry = registry;\n this.metaToolTokens = estimateTokens(JSON.stringify(metaTools));\n this.unsubscribe = this.registry.onChanged(() => {\n // Baseline recalculated on every snapshot, nothing to cache\n });\n }\n\n recordSearchResponse(responseJson: string): void {\n this.cumulativeSearchTokens += estimateTokens(responseJson);\n }\n\n getSnapshot(): SessionStatsSnapshot {\n const allTools = this.registry.listTools();\n const baselineTokens = estimateTokens(JSON.stringify(allTools));\n const bridgeTokens = this.metaToolTokens + this.cumulativeSearchTokens;\n return {\n tokens_saved: Math.max(0, baselineTokens - bridgeTokens),\n baseline_tokens: baselineTokens,\n bridge_tokens: bridgeTokens,\n };\n }\n\n dispose(): void {\n this.unsubscribe();\n }\n}\n","import type { RateLimitConfig } from \"../config/schema.js\";\n\nexport type { RateLimitConfig };\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\ninterface Waiter {\n resolve: () => void;\n reject: (err: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\nexport class RateLimiter {\n private maxCalls: number;\n private windowMs: number;\n private timeoutMs: number;\n private timestamps: number[] = [];\n private queue: Waiter[] = [];\n private drainTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(config: RateLimitConfig, timeoutMs = DEFAULT_TIMEOUT_MS) {\n this.maxCalls = config.maxCalls;\n this.windowMs = config.windowSeconds * 1000;\n this.timeoutMs = timeoutMs;\n }\n\n async acquire(): Promise<void> {\n this.prune();\n\n if (this.timestamps.length < this.maxCalls) {\n this.timestamps.push(Date.now());\n return;\n }\n\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n const idx = this.queue.findIndex((w) => w.resolve === resolve);\n if (idx !== -1) this.queue.splice(idx, 1);\n reject(new Error(\"Rate limit timeout: too many calls queued\"));\n }, this.timeoutMs);\n\n this.queue.push({ resolve, reject, timer });\n this.scheduleDrain();\n });\n }\n\n reconfigure(config: RateLimitConfig): void {\n this.maxCalls = config.maxCalls;\n this.windowMs = config.windowSeconds * 1000;\n this.tryDrain();\n }\n\n dispose(): void {\n if (this.drainTimer !== undefined) {\n clearTimeout(this.drainTimer);\n this.drainTimer = undefined;\n }\n for (const waiter of this.queue) {\n clearTimeout(waiter.timer);\n waiter.reject(new Error(\"Rate limiter disposed\"));\n }\n this.queue = [];\n this.timestamps = [];\n }\n\n private prune(): void {\n const cutoff = Date.now() - this.windowMs;\n let i = 0;\n while (i < this.timestamps.length && this.timestamps[i] <= cutoff) i++;\n if (i > 0) this.timestamps.splice(0, i);\n }\n\n private tryDrain(): void {\n this.prune();\n while (this.queue.length > 0 && this.timestamps.length < this.maxCalls) {\n const waiter = this.queue.shift()!;\n clearTimeout(waiter.timer);\n this.timestamps.push(Date.now());\n waiter.resolve();\n }\n this.scheduleDrain();\n }\n\n private scheduleDrain(): void {\n if (this.drainTimer !== undefined) {\n clearTimeout(this.drainTimer);\n this.drainTimer = undefined;\n }\n if (this.queue.length === 0 || this.timestamps.length === 0) return;\n\n const oldestExpiry = this.timestamps[0] + this.windowMs - Date.now();\n const delay = Math.max(1, oldestExpiry);\n this.drainTimer = setTimeout(() => {\n this.drainTimer = undefined;\n this.tryDrain();\n }, delay);\n }\n}\n","import {\n ErrorCode,\n McpError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n ElicitRequestFormParams,\n ElicitResult,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ToolPolicy, ServerBridgeConfig } from \"../config/schema.js\";\n\nexport type ElicitFn = (\n params: ElicitRequestFormParams,\n) => Promise<ElicitResult>;\n\nexport class PolicyEngine {\n private globalPolicy: ToolPolicy;\n private serverConfigs: Record<string, ServerBridgeConfig>;\n\n constructor(\n globalPolicy: ToolPolicy,\n serverConfigs: Record<string, ServerBridgeConfig>,\n ) {\n this.globalPolicy = globalPolicy;\n this.serverConfigs = serverConfigs;\n }\n\n update(\n globalPolicy: ToolPolicy,\n serverConfigs: Record<string, ServerBridgeConfig>,\n ): void {\n this.globalPolicy = globalPolicy;\n this.serverConfigs = serverConfigs;\n }\n\n resolvePolicy(source: string, toolName: string): ToolPolicy {\n const serverConfig = this.serverConfigs[source];\n if (serverConfig) {\n const perTool = serverConfig.tools?.[toolName];\n if (perTool) return perTool;\n\n if (serverConfig.toolPolicy) return serverConfig.toolPolicy;\n }\n\n return this.globalPolicy;\n }\n\n async enforce(\n source: string,\n toolName: string,\n args: Record<string, unknown> | undefined,\n elicitFn: ElicitFn,\n ): Promise<void> {\n const policy = this.resolvePolicy(source, toolName);\n\n if (policy === \"always\") return;\n\n if (policy === \"never\") {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Tool ${source}__${toolName} is disabled by policy`,\n );\n }\n\n // policy === \"prompt\"\n try {\n const result = await elicitFn({\n message: `Allow ${source}__${toolName} to run?\\n\\nArguments:\\n${JSON.stringify(args ?? {}, null, 2)}`,\n requestedSchema: { type: \"object\", properties: {} },\n });\n\n if (result.action !== \"accept\") {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Tool ${source}__${toolName} was declined by user`,\n );\n }\n } catch (err) {\n if (err instanceof McpError) throw err;\n // Client doesn't support elicitation — block the call\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Tool ${source}__${toolName} requires confirmation but the client does not support elicitation`,\n );\n }\n }\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { Tool, CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { APP_NAME, APP_VERSION } from \"../constants.js\";\nimport type { Logger } from \"../logging/index.js\";\nimport { createNoopLogger } from \"../logging/index.js\";\nimport type {\n UpstreamClient,\n ConnectionStatus,\n StatusChangeEvent,\n StatusChangeCallback,\n ToolsChangedCallback,\n} from \"./types.js\";\n\nexport interface BaseUpstreamClientOptions {\n name: string;\n logger?: Logger;\n maxReconnectAttempts?: number;\n reconnectBaseDelay?: number;\n reconnectMaxDelay?: number;\n /** Injectable transport factory for testing. */\n _transportFactory?: () => Transport;\n}\n\nexport abstract class BaseUpstreamClient implements UpstreamClient {\n readonly name: string;\n\n private _status: ConnectionStatus = \"disconnected\";\n private _tools: Tool[] = [];\n private _client: Client | undefined;\n private _closed = false;\n private _epoch = 0;\n private _connectPromise: Promise<void> | undefined;\n private _reconnectAttempt = 0;\n private _reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n private _maxReconnectAttempts: number;\n private _reconnectBaseDelay: number;\n private _reconnectMaxDelay: number;\n private _transportFactory: (() => Transport) | undefined;\n protected _logger: Logger;\n private _statusListeners = new Set<StatusChangeCallback>();\n private _toolsListeners = new Set<ToolsChangedCallback>();\n\n constructor(options: BaseUpstreamClientOptions) {\n this.name = options.name;\n this._maxReconnectAttempts = options.maxReconnectAttempts ?? 5;\n this._reconnectBaseDelay = options.reconnectBaseDelay ?? 1000;\n this._reconnectMaxDelay = options.reconnectMaxDelay ?? 30000;\n this._transportFactory = options._transportFactory;\n this._logger = options.logger ?? createNoopLogger();\n }\n\n get status(): ConnectionStatus {\n return this._status;\n }\n\n get tools(): ReadonlyArray<Tool> {\n return this._tools;\n }\n\n async connect(): Promise<void> {\n if (this._connectPromise) return this._connectPromise;\n this._connectPromise = this._doConnect().finally(() => {\n this._connectPromise = undefined;\n });\n return this._connectPromise;\n }\n\n private async _doConnect(): Promise<void> {\n this._closed = false;\n this._clearReconnectTimer();\n this._epoch++;\n const myEpoch = this._epoch;\n\n // Clean up stale connection before creating a new one\n if (this._client) {\n const old = this._client;\n this._client = undefined;\n await old.close().catch(() => {});\n }\n\n this._setStatus(\"connecting\");\n this._logger.debug(\"connecting\");\n\n try {\n await this._prepareConnect();\n const transport = this._createTransport();\n const client = new Client(\n { name: `${APP_NAME}/${this.name}`, version: APP_VERSION },\n {\n listChanged: {\n tools: {\n autoRefresh: true,\n onChanged: (error, tools) => {\n if (error || !tools || this._epoch !== myEpoch) return;\n this._tools = tools;\n this._notifyToolsChanged();\n },\n },\n },\n },\n );\n\n transport.onclose = () => {\n if (this._closed || this._epoch !== myEpoch) return;\n this._client = undefined;\n this._setStatus(\"disconnected\");\n this._scheduleReconnect();\n };\n\n await client.connect(transport);\n\n const result = await client.listTools();\n this._tools = result.tools;\n this._client = client;\n this._reconnectAttempt = 0;\n this._setStatus(\"connected\");\n this._notifyToolsChanged();\n } catch (err) {\n this._logger.debug(\"connection failed\", {\n error: err instanceof Error ? err.message : String(err),\n });\n this._setStatus(\"disconnected\");\n throw err;\n }\n }\n\n async callTool(params: {\n name: string;\n arguments?: Record<string, unknown>;\n }): Promise<CallToolResult> {\n if (!this._client || this._status !== \"connected\") {\n throw new Error(\n `Cannot call tool \"${params.name}\": client \"${this.name}\" is not connected`,\n );\n }\n return this._client.callTool(params) as Promise<CallToolResult>;\n }\n\n async close(): Promise<void> {\n this._closed = true;\n this._clearReconnectTimer();\n\n if (this._client) {\n const client = this._client;\n this._client = undefined;\n await client.close();\n }\n\n this._tools = [];\n this._setStatus(\"disconnected\");\n }\n\n async ping(timeoutMs = 5000): Promise<void> {\n if (!this._client || this._status !== \"connected\") {\n throw new Error(`Cannot ping: client \"${this.name}\" is not connected`);\n }\n await this._client.ping({ signal: AbortSignal.timeout(timeoutMs) });\n }\n\n async reconnect(): Promise<void> {\n this._reconnectAttempt = 0;\n this._closed = false;\n this._clearReconnectTimer();\n this._epoch++;\n\n if (this._client) {\n const old = this._client;\n this._client = undefined;\n await old.close().catch(() => {});\n }\n\n this._logger.info(\"reconnecting\");\n await this.connect();\n }\n\n onStatusChange(callback: StatusChangeCallback): () => void {\n this._statusListeners.add(callback);\n return () => {\n this._statusListeners.delete(callback);\n };\n }\n\n onToolsChanged(callback: ToolsChangedCallback): () => void {\n this._toolsListeners.add(callback);\n return () => {\n this._toolsListeners.delete(callback);\n };\n }\n\n private _createTransport(): Transport {\n if (this._transportFactory) {\n return this._transportFactory();\n }\n return this._buildTransport();\n }\n\n /** Async hook called before transport creation in _doConnect(). Override for async setup. */\n protected async _prepareConnect(): Promise<void> {}\n\n /** Subclasses create the real transport here. */\n protected abstract _buildTransport(): Transport;\n\n private _setStatus(next: ConnectionStatus, error?: Error): void {\n const previous = this._status;\n if (previous === next) return;\n this._status = next;\n\n const event: StatusChangeEvent = {\n previous,\n current: next,\n ...(error && { error }),\n };\n for (const listener of this._statusListeners) {\n try {\n listener(event);\n } catch {\n // Listeners must not throw\n }\n }\n }\n\n private _notifyToolsChanged(): void {\n for (const listener of this._toolsListeners) {\n try {\n listener(this._tools);\n } catch {\n // Listeners must not throw\n }\n }\n }\n\n private _scheduleReconnect(): void {\n if (this._closed) return;\n if (this._reconnectTimer !== undefined) return;\n if (this._connectPromise) return;\n\n if (this._reconnectAttempt >= this._maxReconnectAttempts) {\n this._logger.warn(\"max reconnect attempts reached\");\n this._setStatus(\"error\", new Error(\"Max reconnect attempts exceeded\"));\n return;\n }\n\n const delay = Math.min(\n this._reconnectBaseDelay * Math.pow(2, this._reconnectAttempt),\n this._reconnectMaxDelay,\n );\n this._reconnectAttempt++;\n this._logger.debug(`reconnecting in ${delay}ms`, { attempt: this._reconnectAttempt });\n\n this._reconnectTimer = setTimeout(() => {\n this._reconnectTimer = undefined;\n this.connect().catch(() => {\n this._scheduleReconnect();\n });\n }, delay);\n }\n\n private _clearReconnectTimer(): void {\n if (this._reconnectTimer !== undefined) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = undefined;\n }\n }\n}\n","import { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { HttpServerConfig } from \"../config/schema.js\";\nimport type { CredentialStore } from \"../credentials/credential-store.js\";\nimport { hasCredentialTemplates, resolveCredentialTemplates } from \"../credentials/resolve-templates.js\";\nimport { BaseUpstreamClient } from \"./base-client.js\";\nimport type { BaseUpstreamClientOptions } from \"./base-client.js\";\n\nexport interface HttpUpstreamClientOptions extends BaseUpstreamClientOptions {\n config: HttpServerConfig;\n credentialStore?: CredentialStore;\n}\n\nexport class HttpUpstreamClient extends BaseUpstreamClient {\n private _config: HttpServerConfig;\n private _credentialStore: CredentialStore | undefined;\n private _resolvedHeaders: Record<string, string> | undefined;\n\n constructor(options: HttpUpstreamClientOptions) {\n super(options);\n this._config = options.config;\n this._credentialStore = options.credentialStore;\n }\n\n protected override async _prepareConnect(): Promise<void> {\n this._resolvedHeaders = undefined;\n if (\n this._credentialStore &&\n this._config.headers &&\n hasCredentialTemplates(this._config.headers as Record<string, string>)\n ) {\n this._resolvedHeaders = await resolveCredentialTemplates(\n this._config.headers as Record<string, string>,\n this._credentialStore,\n );\n }\n }\n\n protected _buildTransport(): Transport {\n const url = new URL(this._config.url);\n const headers = this._resolvedHeaders ?? this._config.headers;\n const requestInit: RequestInit | undefined = headers\n ? { headers: headers as Record<string, string> }\n : undefined;\n\n if (this._config.type !== \"sse\") {\n return new StreamableHTTPClientTransport(url, { requestInit });\n }\n return new SSEClientTransport(url, { requestInit });\n }\n}\n","export class CredentialError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"CredentialError\";\n }\n}\n","import { z } from \"zod\";\n\n// --- Credential schemas ---\n\nexport const BearerCredentialSchema = z.object({\n type: z.literal(\"bearer\"),\n access_token: z.string().min(1),\n});\n\nexport const OAuth2CredentialSchema = z.object({\n type: z.literal(\"oauth2\"),\n access_token: z.string().min(1),\n refresh_token: z.string().min(1).optional(),\n token_endpoint: z.string().url().optional(),\n client_id: z.string().min(1).optional(),\n expires_at: z.number().int().nonnegative().finite().optional(),\n});\n\nexport const SecretCredentialSchema = z.object({\n type: z.literal(\"secret\"),\n value: z.string().min(1),\n});\n\nexport const CredentialSchema = z.union([\n BearerCredentialSchema,\n OAuth2CredentialSchema,\n SecretCredentialSchema,\n]);\n\nexport const CredentialStoreFileSchema = z.object({\n version: z.literal(1),\n credentials: z.record(z.string(), CredentialSchema),\n});\n\n// --- Inferred types ---\n\nexport type BearerCredential = z.infer<typeof BearerCredentialSchema>;\nexport type OAuth2Credential = z.infer<typeof OAuth2CredentialSchema>;\nexport type SecretCredential = z.infer<typeof SecretCredentialSchema>;\nexport type Credential = z.infer<typeof CredentialSchema>;\nexport type CredentialStoreFile = z.infer<typeof CredentialStoreFileSchema>;\n\n// --- Helpers ---\n\n/** Extract the resolved string value from any credential type. */\nexport function resolveCredentialValue(credential: Credential): string {\n if (credential.type === \"secret\") return credential.value;\n return credential.access_token;\n}\n","import type { CredentialStore } from \"./credential-store.js\";\nimport { CredentialError } from \"./errors.js\";\nimport { resolveCredentialValue } from \"./types.js\";\n\nconst TEMPLATE_RE = /\\$\\{credential:([^}]+)\\}/g;\nconst TEMPLATE_TEST_RE = /\\$\\{credential:[^}]+\\}/;\n\n/** Fast check: does any value in the record contain a `${credential:...}` template? */\nexport function hasCredentialTemplates(\n record: Record<string, string> | undefined,\n): boolean {\n if (!record) return false;\n for (const value of Object.values(record)) {\n if (TEMPLATE_TEST_RE.test(value)) return true;\n }\n return false;\n}\n\n/**\n * Replace all `${credential:key}` templates in a string→string record.\n * Supports mixed content (e.g. `\"Bearer ${credential:token}\"`) and\n * multiple templates per value.\n *\n * Uses index-based replacement (processed in reverse) to avoid\n * `String.replace` interpreting `$`-patterns in credential values\n * and to handle duplicate templates correctly.\n */\nexport async function resolveCredentialTemplates(\n record: Record<string, string>,\n store: CredentialStore,\n): Promise<Record<string, string>> {\n const resolved: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(record)) {\n const matches = [...value.matchAll(TEMPLATE_RE)];\n if (matches.length === 0) {\n resolved[key] = value;\n continue;\n }\n\n // Resolve all credentials first (fail-fast on missing keys)\n const replacements: Array<{ start: number; end: number; resolved: string }> = [];\n for (const match of matches) {\n const credKey = match[1];\n const credential = await store.get(credKey);\n if (!credential) {\n throw new CredentialError(\n `Credential \"${credKey}\" not found in credential store`,\n );\n }\n replacements.push({\n start: match.index!,\n end: match.index! + match[0].length,\n resolved: resolveCredentialValue(credential),\n });\n }\n\n // Apply in reverse so earlier indices stay valid\n let result = value;\n for (let i = replacements.length - 1; i >= 0; i--) {\n const { start, end, resolved: val } = replacements[i];\n result = result.slice(0, start) + val + result.slice(end);\n }\n resolved[key] = result;\n }\n\n return resolved;\n}\n","import { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { StdioServerConfig } from \"../config/schema.js\";\nimport type { CredentialStore } from \"../credentials/credential-store.js\";\nimport { hasCredentialTemplates, resolveCredentialTemplates } from \"../credentials/resolve-templates.js\";\nimport { BaseUpstreamClient } from \"./base-client.js\";\nimport type { BaseUpstreamClientOptions } from \"./base-client.js\";\n\nexport interface StdioUpstreamClientOptions extends BaseUpstreamClientOptions {\n config: StdioServerConfig;\n credentialStore?: CredentialStore;\n}\n\nexport class StdioUpstreamClient extends BaseUpstreamClient {\n private _config: StdioServerConfig;\n private _credentialStore: CredentialStore | undefined;\n private _resolvedEnv: Record<string, string> | undefined;\n\n constructor(options: StdioUpstreamClientOptions) {\n super(options);\n this._config = options.config;\n this._credentialStore = options.credentialStore;\n }\n\n protected override async _prepareConnect(): Promise<void> {\n this._resolvedEnv = undefined;\n if (\n this._credentialStore &&\n this._config.env &&\n hasCredentialTemplates(this._config.env as Record<string, string>)\n ) {\n this._resolvedEnv = await resolveCredentialTemplates(\n this._config.env as Record<string, string>,\n this._credentialStore,\n );\n }\n }\n\n protected _buildTransport(): Transport {\n const env = this._resolvedEnv ?? this._config.env;\n const transport = new StdioClientTransport({\n command: this._config.command,\n args: this._config.args,\n env: { ...process.env, ...env } as Record<string, string>,\n stderr: \"pipe\",\n });\n\n // Forward subprocess stderr through the logger\n transport.stderr?.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString().trimEnd();\n if (text) {\n for (const line of text.split(\"\\n\")) {\n this._logger.debug(line, { stream: \"stderr\" });\n }\n }\n });\n\n return transport;\n }\n}\n","import type { BridgeConfig, ServerConfig, HttpServerConfig } from \"../config/schema.js\";\nimport { isStdioServer, resolveUpstreams } from \"../config/schema.js\";\nimport type { ConfigDiff } from \"../config/config-diff.js\";\nimport type { CredentialStore } from \"../credentials/credential-store.js\";\nimport type { Logger } from \"../logging/index.js\";\nimport { createNoopLogger } from \"../logging/index.js\";\nimport type { ToolRegistry } from \"../server/tool-registry.js\";\nimport { namespaceTool } from \"../server/tool-namespacing.js\";\nimport { HttpUpstreamClient } from \"./http-client.js\";\nimport { StdioUpstreamClient } from \"./stdio-client.js\";\nimport type { UpstreamClient, ConnectionStatus, HealthState } from \"./types.js\";\n\nexport interface UpstreamManagerOptions {\n config: BridgeConfig;\n toolRegistry: ToolRegistry;\n logger?: Logger;\n credentialStore?: CredentialStore;\n /** Health check interval in seconds. 0 to disable. Overrides config value. */\n healthCheckInterval?: number;\n /** Injectable client factory for testing. */\n _clientFactory?: (name: string, config: ServerConfig, logger: Logger) => UpstreamClient;\n}\n\nexport interface UpstreamStatus {\n name: string;\n status: ConnectionStatus;\n health: HealthState;\n toolCount: number;\n lastPingAt?: number;\n}\n\ninterface HealthTracking {\n consecutiveFailures: number;\n lastPingAt?: number;\n health: HealthState;\n}\n\nexport interface ConnectAllResult {\n total: number;\n connected: number;\n failed: Array<{ name: string; error: string }>;\n}\n\nexport class UpstreamManager {\n private _config: BridgeConfig;\n private _toolRegistry: ToolRegistry;\n private _logger: Logger;\n private _clientFactory: (name: string, config: ServerConfig, logger: Logger) => UpstreamClient;\n private _clients = new Map<string, UpstreamClient>();\n private _unsubscribers = new Map<string, Array<() => void>>();\n private _healthCheckInterval: number;\n private _healthTimer: ReturnType<typeof setInterval> | undefined;\n private _healthTracking = new Map<string, HealthTracking>();\n private _pingsInFlight = new Set<string>();\n private _pingTimeoutMs = 5000;\n private _unhealthyThreshold = 3;\n\n constructor(options: UpstreamManagerOptions) {\n this._config = options.config;\n this._toolRegistry = options.toolRegistry;\n this._logger = options.logger ?? createNoopLogger();\n this._healthCheckInterval =\n options.healthCheckInterval ?? options.config._bridge.healthCheckInterval;\n const credentialStore = options.credentialStore;\n this._clientFactory =\n options._clientFactory ??\n ((name, config, logger) => {\n if (isStdioServer(config)) {\n return new StdioUpstreamClient({ name, config, logger, credentialStore });\n }\n return new HttpUpstreamClient({ name, config: config as HttpServerConfig, logger, credentialStore });\n });\n }\n\n private _addClient(\n name: string,\n serverConfig: ServerConfig,\n ): Promise<{ name: string; error?: string }> {\n const log = this._logger.child({ component: \"upstream\", server: name });\n const transport = isStdioServer(serverConfig)\n ? \"stdio\"\n : (serverConfig as HttpServerConfig).type;\n log.info(`connecting (${transport})`);\n\n const client = this._clientFactory(name, serverConfig, log);\n this._clients.set(name, client);\n\n const category = serverConfig._bridge?.category;\n if (category) {\n this._toolRegistry.setCategoryForSource(name, category);\n }\n\n const unsubTools = client.onToolsChanged((tools) => {\n const namespaced = tools.map((t) => namespaceTool(name, t));\n this._toolRegistry.setToolsForSource(name, namespaced);\n log.info(\n `${tools.length} tool${tools.length === 1 ? \"\" : \"s\"} discovered: ${namespaced.map((t) => t.name).join(\", \")}`,\n );\n });\n\n const unsubStatus = client.onStatusChange((event) => {\n if (event.current === \"error\") {\n log.error(\n `error: ${event.error?.message ?? \"unknown\"}`,\n );\n this._toolRegistry.removeSource(name);\n } else {\n log.debug(`${event.current}`);\n }\n });\n\n this._unsubscribers.set(name, [unsubTools, unsubStatus]);\n\n return client.connect().then(\n () => ({ name }),\n (err) => {\n const message = err instanceof Error ? err.message : String(err);\n log.error(`failed to connect: ${message}`);\n return { name, error: message };\n },\n );\n }\n\n private async _removeClient(name: string): Promise<void> {\n const unsubs = this._unsubscribers.get(name);\n if (unsubs) {\n for (const unsub of unsubs) unsub();\n this._unsubscribers.delete(name);\n }\n\n const client = this._clients.get(name);\n if (client) {\n await client.close().catch(() => {});\n this._clients.delete(name);\n }\n\n this._toolRegistry.removeSource(name);\n this._healthTracking.delete(name);\n this._pingsInFlight.delete(name);\n }\n\n async connectAll(): Promise<ConnectAllResult> {\n const entries = Object.entries(resolveUpstreams(this._config));\n const connectPromises: Promise<{ name: string; error?: string }>[] = [];\n\n for (const [name, serverConfig] of entries) {\n connectPromises.push(this._addClient(name, serverConfig));\n }\n\n const outcomes = await Promise.all(connectPromises);\n const failed = outcomes.filter((o) => o.error !== undefined) as Array<{ name: string; error: string }>;\n return {\n total: entries.length,\n connected: entries.length - failed.length,\n failed,\n };\n }\n\n async closeAll(): Promise<void> {\n this.stopHealthChecks();\n\n for (const unsubs of this._unsubscribers.values()) {\n for (const unsub of unsubs) unsub();\n }\n this._unsubscribers.clear();\n\n const names = Array.from(this._clients.keys());\n\n const closePromises = Array.from(this._clients.values()).map((client) =>\n client.close().catch(() => {\n // Ignore close errors\n }),\n );\n await Promise.all(closePromises);\n\n for (const name of names) {\n this._toolRegistry.removeSource(name);\n }\n\n this._clients.clear();\n this._healthTracking.clear();\n this._pingsInFlight.clear();\n }\n\n async applyConfigDiff(diff: ConfigDiff, newConfig: BridgeConfig): Promise<void> {\n // 1. Remove deleted servers\n for (const name of diff.servers.removed) {\n this._logger.info(`removing server`, { component: \"reload\", server: name });\n await this._removeClient(name);\n }\n\n // 2. Reconnect servers with changed connection fields\n for (const { name, config } of diff.servers.reconnect) {\n this._logger.info(`reconnecting server`, { component: \"reload\", server: name });\n await this._removeClient(name);\n const result = await this._addClient(name, config);\n if (result.error) {\n this._logger.warn(`server failed to connect after reload`, {\n component: \"reload\", server: name, error: result.error,\n });\n }\n }\n\n // 3. Add new servers\n for (const { name, config } of diff.servers.added) {\n this._logger.info(`adding server`, { component: \"reload\", server: name });\n const result = await this._addClient(name, config);\n if (result.error) {\n this._logger.warn(`server failed to connect after reload`, {\n component: \"reload\", server: name, error: result.error,\n });\n }\n }\n\n // 4. Update metadata-only servers (policy changes handled separately via PolicyEngine.update)\n for (const { name, config } of diff.servers.updated) {\n this._logger.info(`updating metadata`, { component: \"reload\", server: name });\n const category = config._bridge?.category;\n if (category) {\n this._toolRegistry.setCategoryForSource(name, category);\n } else {\n this._toolRegistry.removeCategoryForSource(name);\n }\n }\n\n this._config = newConfig;\n }\n\n restartHealthChecks(interval: number): void {\n this.stopHealthChecks();\n this._healthCheckInterval = interval;\n this.startHealthChecks();\n }\n\n getClient(name: string): UpstreamClient | undefined {\n return this._clients.get(name);\n }\n\n getStatuses(): UpstreamStatus[] {\n return Array.from(this._clients.values()).map((client) => {\n const tracking = this._healthTracking.get(client.name);\n return {\n name: client.name,\n status: client.status,\n health: tracking?.health ?? \"unknown\",\n toolCount: client.tools.length,\n lastPingAt: tracking?.lastPingAt,\n };\n });\n }\n\n startHealthChecks(): void {\n if (this._healthCheckInterval <= 0) return;\n if (this._healthTimer) return;\n\n this._logger.debug(\"starting health checks\", {\n component: \"health\",\n interval: this._healthCheckInterval,\n });\n\n this._healthTimer = setInterval(() => {\n this._runHealthCheck();\n }, this._healthCheckInterval * 1000);\n }\n\n stopHealthChecks(): void {\n if (this._healthTimer) {\n clearInterval(this._healthTimer);\n this._healthTimer = undefined;\n }\n }\n\n private _runHealthCheck(): void {\n for (const [name, client] of this._clients) {\n if (client.status !== \"connected\") continue;\n if (this._pingsInFlight.has(name)) continue;\n\n let tracking = this._healthTracking.get(name);\n if (!tracking) {\n tracking = { consecutiveFailures: 0, health: \"unknown\" };\n this._healthTracking.set(name, tracking);\n }\n\n this._pingsInFlight.add(name);\n\n client.ping(this._pingTimeoutMs).then(\n () => {\n this._pingsInFlight.delete(name);\n const t = this._healthTracking.get(name);\n if (!t) return;\n const wasUnhealthy = t.health === \"unhealthy\";\n t.consecutiveFailures = 0;\n t.lastPingAt = Date.now();\n t.health = \"healthy\";\n if (wasUnhealthy) {\n this._logger.info(\"recovered\", {\n component: \"health\",\n server: name,\n });\n }\n },\n (err) => {\n this._pingsInFlight.delete(name);\n const t = this._healthTracking.get(name);\n if (!t) return;\n t.consecutiveFailures++;\n t.health = \"unhealthy\";\n\n this._logger.warn(\"ping failed\", {\n component: \"health\",\n server: name,\n error: err instanceof Error ? err.message : String(err),\n failures: t.consecutiveFailures,\n });\n\n if (t.consecutiveFailures >= this._unhealthyThreshold) {\n this._logger.error(\n `${t.consecutiveFailures} consecutive ping failures, reconnecting`,\n { component: \"health\", server: name },\n );\n t.consecutiveFailures = 0;\n t.health = \"unknown\";\n client.reconnect().catch((reconnectErr) => {\n this._logger.error(\"reconnect failed\", {\n component: \"health\",\n server: name,\n error:\n reconnectErr instanceof Error\n ? reconnectErr.message\n : String(reconnectErr),\n });\n });\n }\n },\n );\n }\n }\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir, platform } from \"node:os\";\nimport { APP_NAME, CREDENTIALS_DIR } from \"../constants.js\";\nimport { CredentialError } from \"./errors.js\";\n\nconst SERVICE = APP_NAME;\nconst ACCOUNT = \"master-key\";\nconst EXEC_TIMEOUT = 10_000;\n\nexport interface KeychainAdapter {\n /** Returns the key, or undefined if no key has been stored yet. */\n getKey(): Promise<Buffer | undefined>;\n setKey(key: Buffer): Promise<void>;\n deleteKey(): Promise<void>;\n}\n\n// --- Helpers ---\n\nfunction execCommand(\n command: string,\n args: string[],\n): Promise<string> {\n return new Promise((resolve, reject) => {\n execFile(\n command,\n args,\n { timeout: EXEC_TIMEOUT },\n (error, stdout, stderr) => {\n if (error) {\n reject(\n new CredentialError(\n `${command} failed: ${stderr?.trim() || error.message}`,\n { cause: error },\n ),\n );\n return;\n }\n resolve(stdout.trim());\n },\n );\n });\n}\n\nfunction spawnWithStdin(\n command: string,\n args: string[],\n stdin: string,\n): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, { timeout: EXEC_TIMEOUT });\n let stdout = \"\";\n let stderr = \"\";\n let settled = false;\n\n child.stdout.on(\"data\", (data: Buffer) => {\n stdout += data.toString();\n });\n child.stderr.on(\"data\", (data: Buffer) => {\n stderr += data.toString();\n });\n child.on(\"error\", (error) => {\n if (settled) return;\n settled = true;\n reject(\n new CredentialError(`${command} failed: ${error.message}`, {\n cause: error,\n }),\n );\n });\n child.on(\"close\", (code) => {\n if (settled) return;\n settled = true;\n if (code !== 0) {\n reject(\n new CredentialError(\n `${command} exited with code ${code}: ${stderr.trim()}`,\n ),\n );\n return;\n }\n resolve(stdout.trim());\n });\n\n // Suppress EPIPE if child exits before we finish writing.\n // The actual exit code/error is handled by the 'close'/'error' listeners.\n child.stdin.on(\"error\", () => {});\n child.stdin.write(stdin);\n child.stdin.end();\n });\n}\n\nfunction parseHexKey(hex: string, source: string): Buffer {\n const cleaned = hex.trim();\n if (!/^[0-9a-fA-F]{64}$/.test(cleaned)) {\n throw new CredentialError(\n `Invalid master key from ${source}: expected exactly 64 hex characters (32 bytes), got ${cleaned.length}`,\n );\n }\n return Buffer.from(cleaned, \"hex\");\n}\n\n// --- EnvKeychain ---\n\nexport class EnvKeychain implements KeychainAdapter {\n private readonly key: Buffer;\n\n constructor(hex: string) {\n this.key = parseHexKey(hex, \"MCP_BRIDGE_MASTER_KEY\");\n }\n\n async getKey(): Promise<Buffer> {\n return this.key;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async setKey(key: Buffer): Promise<void> {\n throw new CredentialError(\n \"Cannot set master key when using MCP_BRIDGE_MASTER_KEY environment variable\",\n );\n }\n\n async deleteKey(): Promise<void> {\n throw new CredentialError(\n \"Cannot delete master key when using MCP_BRIDGE_MASTER_KEY environment variable\",\n );\n }\n}\n\n// --- MacKeychain ---\n\nexport class MacKeychain implements KeychainAdapter {\n async getKey(): Promise<Buffer | undefined> {\n try {\n const hex = await execCommand(\"security\", [\n \"find-generic-password\",\n \"-s\",\n SERVICE,\n \"-a\",\n ACCOUNT,\n \"-w\",\n ]);\n return parseHexKey(hex, \"macOS keychain\");\n } catch (err) {\n // security exits 44 with \"could not be found\" when item doesn't exist\n if (err instanceof CredentialError && /could not be found/i.test(err.message)) {\n return undefined;\n }\n throw err;\n }\n }\n\n async setKey(key: Buffer): Promise<void> {\n const hex = key.toString(\"hex\");\n await execCommand(\"security\", [\n \"add-generic-password\",\n \"-s\",\n SERVICE,\n \"-a\",\n ACCOUNT,\n \"-w\",\n hex,\n \"-U\",\n ]);\n }\n\n async deleteKey(): Promise<void> {\n await execCommand(\"security\", [\n \"delete-generic-password\",\n \"-s\",\n SERVICE,\n \"-a\",\n ACCOUNT,\n ]);\n }\n}\n\n// --- LinuxKeychain ---\n\nexport class LinuxKeychain implements KeychainAdapter {\n async getKey(): Promise<Buffer | undefined> {\n try {\n const hex = await execCommand(\"secret-tool\", [\n \"lookup\",\n \"service\",\n SERVICE,\n \"account\",\n ACCOUNT,\n ]);\n // secret-tool returns empty stdout when key not found (before exiting 1)\n if (!hex) return undefined;\n return parseHexKey(hex, \"secret-tool\");\n } catch (err) {\n // secret-tool exits 1 with empty stderr when key doesn't exist.\n // execCommand formats this as \"secret-tool failed: Command failed: ...\"\n if (err instanceof CredentialError && /secret-tool failed:.*Command failed/i.test(err.message)) {\n return undefined;\n }\n throw err;\n }\n }\n\n async setKey(key: Buffer): Promise<void> {\n const hex = key.toString(\"hex\");\n await spawnWithStdin(\n \"secret-tool\",\n [\n \"store\",\n \"--label\",\n `${APP_NAME} master key`,\n \"service\",\n SERVICE,\n \"account\",\n ACCOUNT,\n ],\n hex,\n );\n }\n\n async deleteKey(): Promise<void> {\n await execCommand(\"secret-tool\", [\n \"clear\",\n \"service\",\n SERVICE,\n \"account\",\n ACCOUNT,\n ]);\n }\n}\n\n// --- WindowsKeychain ---\n\nexport class WindowsKeychain implements KeychainAdapter {\n private get filePath(): string {\n return join(homedir(), CREDENTIALS_DIR, \"master-key.dpapi\");\n }\n\n private escapeSingleQuote(s: string): string {\n return s.replace(/'/g, \"''\");\n }\n\n private encodedCommand(script: string): string[] {\n // -EncodedCommand accepts a Base64-encoded UTF-16LE string, avoiding\n // any injection via interpolated paths or values.\n const encoded = Buffer.from(script, \"utf16le\").toString(\"base64\");\n return [\"-NoProfile\", \"-NonInteractive\", \"-EncodedCommand\", encoded];\n }\n\n async getKey(): Promise<Buffer | undefined> {\n try {\n const script =\n `$bytes = [IO.File]::ReadAllBytes('${this.escapeSingleQuote(this.filePath)}')\\n` +\n `$decrypted = [Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'CurrentUser')\\n` +\n `[BitConverter]::ToString($decrypted).Replace('-','')`;\n const hex = await execCommand(\"powershell\", this.encodedCommand(script));\n return parseHexKey(hex, \"DPAPI\");\n } catch (err) {\n // FileNotFoundException when the DPAPI file doesn't exist yet\n if (err instanceof CredentialError && /Could not find|does not exist|FileNotFound/i.test(err.message)) {\n return undefined;\n }\n throw err;\n }\n }\n\n async setKey(key: Buffer): Promise<void> {\n const dir = join(homedir(), CREDENTIALS_DIR);\n await mkdir(dir, { recursive: true });\n const hex = key.toString(\"hex\");\n const escapedPath = this.escapeSingleQuote(this.filePath);\n const script =\n `$hex = '${hex}'\\n` +\n `$bytes = [byte[]]::new($hex.Length / 2)\\n` +\n `for ($i = 0; $i -lt $bytes.Length; $i++) { $bytes[$i] = [Convert]::ToByte($hex.Substring($i*2, 2), 16) }\\n` +\n `$encrypted = [Security.Cryptography.ProtectedData]::Protect($bytes, $null, 'CurrentUser')\\n` +\n `[IO.File]::WriteAllBytes('${escapedPath}', $encrypted)`;\n await execCommand(\"powershell\", this.encodedCommand(script));\n }\n\n async deleteKey(): Promise<void> {\n const script = `Remove-Item -LiteralPath '${this.escapeSingleQuote(this.filePath)}' -Force -ErrorAction Stop`;\n await execCommand(\"powershell\", this.encodedCommand(script));\n }\n}\n\n// --- Factory ---\n\nexport interface CreateKeychainOptions {\n _adapter?: KeychainAdapter;\n _platform?: NodeJS.Platform;\n}\n\nexport function createKeychainAdapter(\n options?: CreateKeychainOptions,\n): KeychainAdapter {\n if (options?._adapter) {\n return options._adapter;\n }\n\n const envKey = process.env.MCP_BRIDGE_MASTER_KEY;\n if (envKey) {\n return new EnvKeychain(envKey);\n }\n\n const os = options?._platform ?? platform();\n switch (os) {\n case \"darwin\":\n return new MacKeychain();\n case \"linux\":\n return new LinuxKeychain();\n case \"win32\":\n return new WindowsKeychain();\n default:\n throw new CredentialError(`Unsupported platform for keychain: ${os}`);\n }\n}\n","import { randomBytes, createCipheriv, createDecipheriv } from \"node:crypto\";\nimport { access, readFile, writeFile, rename, mkdir } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { CREDENTIALS_DIR, CREDENTIALS_FILENAME } from \"../constants.js\";\nimport { CredentialStoreFileSchema, type Credential, type CredentialStoreFile } from \"./types.js\";\nimport { CredentialError } from \"./errors.js\";\nimport type { KeychainAdapter } from \"./keychain.js\";\n\nconst ALGORITHM = \"aes-256-gcm\";\nconst IV_LENGTH = 12;\nconst AUTH_TAG_LENGTH = 16;\nconst MAX_KEY_LENGTH = 256;\n\nexport interface CredentialStoreOptions {\n keychain: KeychainAdapter;\n filePath?: string;\n}\n\n// Note: CredentialStore is not concurrency-safe. Concurrent read-modify-write\n// cycles (e.g. two `set()` calls in parallel) may lose writes. This is\n// acceptable for CLI usage; callers requiring concurrency should serialize\n// access externally.\n\nexport class CredentialStore {\n private readonly keychain: KeychainAdapter;\n private readonly filePath: string;\n\n constructor(options: CredentialStoreOptions) {\n this.keychain = options.keychain;\n this.filePath =\n options.filePath ??\n join(homedir(), CREDENTIALS_DIR, CREDENTIALS_FILENAME);\n }\n\n async get(key: string): Promise<Credential | undefined> {\n this._validateKey(key);\n if (!await this._storeFileExists()) return undefined;\n const masterKey = await this._getExistingMasterKey();\n const store = await this._readStore(masterKey);\n return Object.hasOwn(store.credentials, key)\n ? store.credentials[key]\n : undefined;\n }\n\n async set(key: string, credential: Credential): Promise<void> {\n this._validateKey(key);\n const masterKey = await this._getOrCreateMasterKey();\n const store = await this._readStore(masterKey);\n store.credentials[key] = credential;\n await this._writeStore(store, masterKey);\n }\n\n async delete(key: string): Promise<boolean> {\n this._validateKey(key);\n if (!await this._storeFileExists()) return false;\n const masterKey = await this._getExistingMasterKey();\n const store = await this._readStore(masterKey);\n if (!Object.hasOwn(store.credentials, key)) {\n return false;\n }\n delete store.credentials[key];\n await this._writeStore(store, masterKey);\n return true;\n }\n\n async list(): Promise<string[]> {\n if (!await this._storeFileExists()) return [];\n const masterKey = await this._getExistingMasterKey();\n const store = await this._readStore(masterKey);\n return Object.keys(store.credentials);\n }\n\n // --- Internal ---\n\n private _validateKey(key: string): void {\n if (!key) {\n throw new CredentialError(\"Credential key must not be empty\");\n }\n if (key === \"__proto__\") {\n throw new CredentialError(\n `Credential key \"${key}\" is reserved and cannot be used`,\n );\n }\n if (key.length > MAX_KEY_LENGTH) {\n throw new CredentialError(\n `Credential key too long: ${key.length} characters (max ${MAX_KEY_LENGTH})`,\n );\n }\n }\n\n private async _storeFileExists(): Promise<boolean> {\n try {\n await access(this.filePath);\n return true;\n } catch {\n return false;\n }\n }\n\n private async _getOrCreateMasterKey(): Promise<Buffer> {\n const existing = await this.keychain.getKey();\n if (existing) return existing;\n const key = randomBytes(32);\n await this.keychain.setKey(key);\n return key;\n }\n\n private async _getExistingMasterKey(): Promise<Buffer> {\n const existing = await this.keychain.getKey();\n if (!existing) {\n throw new CredentialError(\n \"No master key found in keychain — cannot decrypt credential store. \" +\n \"If the keychain was reset, the credential store must be recreated.\",\n );\n }\n return existing;\n }\n\n private _encrypt(data: Buffer, key: Buffer): Buffer {\n const iv = randomBytes(IV_LENGTH);\n const cipher = createCipheriv(ALGORITHM, key, iv);\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);\n const authTag = cipher.getAuthTag();\n return Buffer.concat([iv, encrypted, authTag]);\n }\n\n private _decrypt(blob: Buffer, key: Buffer): Buffer {\n const minLength = IV_LENGTH + AUTH_TAG_LENGTH;\n if (blob.length < minLength) {\n throw new CredentialError(\n \"Credential store file is corrupted: data too short\",\n );\n }\n\n const iv = blob.subarray(0, IV_LENGTH);\n const authTag = blob.subarray(blob.length - AUTH_TAG_LENGTH);\n const ciphertext = blob.subarray(IV_LENGTH, blob.length - AUTH_TAG_LENGTH);\n\n try {\n const decipher = createDecipheriv(ALGORITHM, key, iv);\n decipher.setAuthTag(authTag);\n return Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n } catch (err) {\n throw new CredentialError(\n \"Failed to decrypt credential store: wrong key or corrupted data\",\n { cause: err },\n );\n }\n }\n\n private async _readStore(masterKey: Buffer): Promise<CredentialStoreFile> {\n let raw: Buffer;\n try {\n raw = await readFile(this.filePath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return { version: 1, credentials: {} };\n }\n throw new CredentialError(\n `Failed to read credential store: ${(err as Error).message}`,\n { cause: err },\n );\n }\n\n const decrypted = this._decrypt(raw, masterKey);\n\n let json: unknown;\n try {\n json = JSON.parse(decrypted.toString(\"utf-8\"));\n } catch (err) {\n throw new CredentialError(\n \"Credential store contains invalid JSON\",\n { cause: err },\n );\n }\n\n const result = CredentialStoreFileSchema.safeParse(json);\n if (!result.success) {\n throw new CredentialError(\n \"Credential store has invalid schema\",\n { cause: result.error },\n );\n }\n\n return result.data;\n }\n\n private async _writeStore(store: CredentialStoreFile, masterKey: Buffer): Promise<void> {\n const data = Buffer.from(JSON.stringify(store), \"utf-8\");\n const encrypted = this._encrypt(data, masterKey);\n\n const dir = dirname(this.filePath);\n await mkdir(dir, { recursive: true });\n\n const tmpPath = `${this.filePath}.tmp.${process.pid}`;\n await writeFile(tmpPath, encrypted, { mode: 0o600 });\n await rename(tmpPath, this.filePath);\n }\n}\n"],"mappings":"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","names":["z","providers","ErrorCode","McpError","z","credential","credential","readFile","mkdir","dirname","join","homedir","join","homedir","credential","readFile","dirname","mkdir","credential"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crabeye-ai/crabeye-mcp-bridge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"mcpName": "io.github.crabeye-ai/crabeye-mcp-bridge",
|
|
4
5
|
"description": "Aggregate multiple MCP servers behind a single STDIO interface. Connect your AI assistant to one bridge instead of configuring each server individually. Supports STDIO and HTTP upstream servers with built-in tool search and discovery.",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/crabeye-ai/crabeye-mcp-bridge.git"
|
|
9
|
+
},
|
|
5
10
|
"type": "module",
|
|
6
11
|
"bin": {
|
|
7
12
|
"crabeye-mcp-bridge": "./bin/crabeye-mcp-bridge"
|