nexus-agents 2.104.0 → 2.105.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.
@@ -7003,7 +7003,7 @@ async function processVotesWithCascade(engineVotes, opts) {
7003
7003
  var CONTRARIAN_ESCALATION_THRESHOLD = 0.8;
7004
7004
  async function runContrarianCheck(proposal, log) {
7005
7005
  try {
7006
- const { executeExpert } = await import("./expert-bridge-7R4AU4DE.js");
7006
+ const { executeExpert } = await import("./expert-bridge-MQURDKJI.js");
7007
7007
  const prompt = [
7008
7008
  "You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.",
7009
7009
  "Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.",
@@ -7496,4 +7496,4 @@ export {
7496
7496
  CONSENSUS_VOTE_OUTPUT_SCHEMA,
7497
7497
  registerConsensusVoteTool
7498
7498
  };
7499
- //# sourceMappingURL=chunk-2MM5MC45.js.map
7499
+ //# sourceMappingURL=chunk-MKSP4M55.js.map
@@ -40,7 +40,7 @@ import {
40
40
  } from "./chunk-CH7QIDHQ.js";
41
41
 
42
42
  // src/version.ts
43
- var VERSION = true ? "2.104.0" : "dev";
43
+ var VERSION = true ? "2.105.0" : "dev";
44
44
 
45
45
  // src/config/schemas-core.ts
46
46
  import { z } from "zod";
@@ -2096,7 +2096,7 @@ async function runDoctorFix(result) {
2096
2096
  writeLine2("\u2500".repeat(40));
2097
2097
  let fixCount = 0;
2098
2098
  if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
2099
- const { runSetup } = await import("./setup-command-AS65DYIU.js");
2099
+ const { runSetup } = await import("./setup-command-KTMIAEU6.js");
2100
2100
  const setupResult = runSetup({
2101
2101
  skipMcp: true,
2102
2102
  skipRules: true,
@@ -2208,4 +2208,4 @@ export {
2208
2208
  startStdioServer,
2209
2209
  closeServer
2210
2210
  };
2211
- //# sourceMappingURL=chunk-5YMSKNUG.js.map
2211
+ //# sourceMappingURL=chunk-OESO6AQL.js.map
package/dist/cli.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  import {
25
25
  setupCommandAsync,
26
26
  verifyCommand
27
- } from "./chunk-4KTPDSFZ.js";
27
+ } from "./chunk-75BXDWVG.js";
28
28
  import "./chunk-FVJ2LM2G.js";
29
29
  import {
30
30
  AuthHandler,
@@ -166,7 +166,7 @@ import {
166
166
  validateCommand,
167
167
  validateWorkflow,
168
168
  wrapInMarkdownFence
169
- } from "./chunk-LM3BH55G.js";
169
+ } from "./chunk-FTFFYAY6.js";
170
170
  import "./chunk-3ACDP4E6.js";
171
171
  import {
172
172
  resolveToken
@@ -179,7 +179,7 @@ import "./chunk-7RE2S46N.js";
179
179
  import "./chunk-P5XUYJBO.js";
180
180
  import {
181
181
  shutdownExpertBridge
182
- } from "./chunk-47FQ3BU7.js";
182
+ } from "./chunk-BMM6OX2K.js";
183
183
  import {
184
184
  DEFAULT_VOTE_TIMEOUT_MS,
185
185
  ErrorPolicySchema,
@@ -189,7 +189,7 @@ import {
189
189
  executeVoting,
190
190
  registerConsensusVoteTool,
191
191
  warnIfSimulatedOutsideTests
192
- } from "./chunk-2MM5MC45.js";
192
+ } from "./chunk-MKSP4M55.js";
193
193
  import "./chunk-ABNHZEKO.js";
194
194
  import "./chunk-BLMWODJG.js";
195
195
  import {
@@ -251,7 +251,7 @@ import {
251
251
  loadConfig,
252
252
  runDoctor,
253
253
  validateNexusEnv
254
- } from "./chunk-5YMSKNUG.js";
254
+ } from "./chunk-OESO6AQL.js";
255
255
  import {
256
256
  DEFAULTS
257
257
  } from "./chunk-I7UDM43R.js";
@@ -6,7 +6,7 @@ import {
6
6
  executeVoting,
7
7
  registerConsensusVoteTool,
8
8
  resetCorrelationTracker
9
- } from "./chunk-2MM5MC45.js";
9
+ } from "./chunk-MKSP4M55.js";
10
10
  import "./chunk-ABNHZEKO.js";
11
11
  import "./chunk-BLMWODJG.js";
12
12
  import "./chunk-XWOLOXKN.js";
@@ -31,4 +31,4 @@ export {
31
31
  registerConsensusVoteTool,
32
32
  resetCorrelationTracker
33
33
  };
34
- //# sourceMappingURL=consensus-vote-7HEHHH5S.js.map
34
+ //# sourceMappingURL=consensus-vote-VUNGPXXS.js.map
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  executeExpert,
3
3
  shutdownExpertBridge,
4
+ tokenSplitFromUsage,
4
5
  totalTokensFromUsage
5
- } from "./chunk-47FQ3BU7.js";
6
+ } from "./chunk-BMM6OX2K.js";
6
7
  import "./chunk-RZ4A2RRN.js";
7
8
  import "./chunk-WDVUKSIQ.js";
8
9
  import "./chunk-CH7QIDHQ.js";
@@ -10,6 +11,7 @@ import "./chunk-PR4QN5HX.js";
10
11
  export {
11
12
  executeExpert,
12
13
  shutdownExpertBridge,
14
+ tokenSplitFromUsage,
13
15
  totalTokensFromUsage
14
16
  };
15
- //# sourceMappingURL=expert-bridge-7R4AU4DE.js.map
17
+ //# sourceMappingURL=expert-bridge-MQURDKJI.js.map
package/dist/index.d.ts CHANGED
@@ -32436,6 +32436,21 @@ interface ExpertBridgeResult {
32436
32436
  * #3387, routing-experience metrics) must tolerate `undefined`.
32437
32437
  */
32438
32438
  readonly tokensUsed?: number;
32439
+ /**
32440
+ * Concrete model id the underlying adapter reported (`CliResponse.model`),
32441
+ * when present (#3387). Distinct from {@link cli} (the slot): one CLI can run
32442
+ * several models. Undefined when the adapter didn't report a model or the
32443
+ * bridge failed before dispatch. Required to emit a `model.called` event.
32444
+ */
32445
+ readonly model?: string;
32446
+ /**
32447
+ * Input/output token split from the adapter's `CliResponse.usage` (#3387),
32448
+ * when reported. Best-effort like {@link tokensUsed}; both undefined together
32449
+ * when no usage was available. `tokensIn + tokensOut` reconciles with
32450
+ * `tokensUsed` (single source of truth — both derive from the same record).
32451
+ */
32452
+ readonly tokensIn?: number;
32453
+ readonly tokensOut?: number;
32439
32454
  }
32440
32455
  declare function executeExpert(expertType: BuiltInExpertType, prompt: string): Promise<ExpertBridgeResult>;
32441
32456
 
package/dist/index.js CHANGED
@@ -517,7 +517,7 @@ import {
517
517
  validateWorkflow,
518
518
  validateWorkflowDependencies,
519
519
  withLogging
520
- } from "./chunk-LM3BH55G.js";
520
+ } from "./chunk-FTFFYAY6.js";
521
521
  import "./chunk-3ACDP4E6.js";
522
522
  import {
523
523
  getTokenEnvVars,
@@ -537,7 +537,7 @@ import {
537
537
  } from "./chunk-P5XUYJBO.js";
538
538
  import {
539
539
  executeExpert
540
- } from "./chunk-47FQ3BU7.js";
540
+ } from "./chunk-BMM6OX2K.js";
541
541
  import {
542
542
  AgentFindingSchema,
543
543
  AgentPerformanceSchema,
@@ -613,7 +613,7 @@ import {
613
613
  resetGlobalRegistry,
614
614
  withModelNotFoundFallback,
615
615
  wrapResilientWithFallback
616
- } from "./chunk-2MM5MC45.js";
616
+ } from "./chunk-MKSP4M55.js";
617
617
  import {
618
618
  AdapterModelError,
619
619
  BaseAdapter,
@@ -759,7 +759,7 @@ import {
759
759
  getKnownNexusVarNames,
760
760
  startStdioServer,
761
761
  validateNexusEnv
762
- } from "./chunk-5YMSKNUG.js";
762
+ } from "./chunk-OESO6AQL.js";
763
763
  import {
764
764
  DEFAULTS
765
765
  } from "./chunk-I7UDM43R.js";
@@ -6085,7 +6085,7 @@ function buildVotingInput(plan, config) {
6085
6085
  }
6086
6086
  async function executeSingleVote(plan, config, log) {
6087
6087
  try {
6088
- const { executeVoting } = await import("./consensus-vote-7HEHHH5S.js");
6088
+ const { executeVoting } = await import("./consensus-vote-VUNGPXXS.js");
6089
6089
  const input = buildVotingInput(plan, config);
6090
6090
  const result = await executeVoting(input, log);
6091
6091
  return parseVotingResult(result);
@@ -8,9 +8,9 @@ import {
8
8
  runWizard,
9
9
  setupCommand,
10
10
  setupCommandAsync
11
- } from "./chunk-4KTPDSFZ.js";
11
+ } from "./chunk-75BXDWVG.js";
12
12
  import "./chunk-FVJ2LM2G.js";
13
- import "./chunk-5YMSKNUG.js";
13
+ import "./chunk-OESO6AQL.js";
14
14
  import "./chunk-I7UDM43R.js";
15
15
  import "./chunk-NUBSJGQZ.js";
16
16
  import "./chunk-6T3EPABN.js";
@@ -33,4 +33,4 @@ export {
33
33
  setupCommand,
34
34
  setupCommandAsync
35
35
  };
36
- //# sourceMappingURL=setup-command-AS65DYIU.js.map
36
+ //# sourceMappingURL=setup-command-KTMIAEU6.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexus-agents",
3
- "version": "2.104.0",
3
+ "version": "2.105.0",
4
4
  "description": "Governance substrate for AI coding agents — adversarial PR review, drift-detected rules, immutable audit, and closed-loop outcome routing for Claude, Codex, Gemini, and OpenCode",
5
5
  "mcpName": "io.github.nexus-substrate/nexus-agents",
6
6
  "license": "MIT",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/pipeline/expert-bridge.ts"],"sourcesContent":["/**\n * Expert Bridge — Programmatic access to the execute_expert pipeline (#1693)\n *\n * Provides a clean wrapper for calling experts with the full pipeline:\n * timeout, fallback cascade, degradation detection, heartbeat, outcome recording.\n *\n * DRY: reuses createBuiltInExpert + CompositeRouter instead of reimplementing.\n *\n * @module pipeline/expert-bridge\n */\n\nimport { createLogger, getTimeProvider } from '../core/index.js';\nimport type { BuiltInExpertType } from '../agents/experts/expert-config.js';\nimport { isRateLimitText } from '../adapters/rate-limit-detector.js';\nimport { resolveCliSlot } from '../config/model-availability.js';\nimport type { CliNameLiteral } from '../config/model-capabilities-types.js';\n\n/**\n * Resolves a CLI slot from the model string a (CLI or API) adapter returned.\n * Known models resolve to their exact slot; **unknown** models — new releases\n * or API/openrouter models not in the curated registry — fall back to the\n * vendor-derived slot (#3317 / #3293) so the outcome is recorded against a real\n * slot instead of being dropped with an undefined cli (the api-mode gap).\n * Returns undefined only when no model is present (the bridge failed before\n * dispatch — no execution to attribute).\n */\nfunction resolveCliFromModelString(model: string | undefined): CliNameLiteral | undefined {\n return resolveCliSlot(model);\n}\n\nconst logger = createLogger({ component: 'expert-bridge' });\n\n/** Base delay for rate limit retry backoff (ms). Scales linearly: 3s, 6s, 9s. */\nconst RATE_LIMIT_BASE_DELAY_MS = 3000;\n\n/** Result of an expert execution. */\nexport interface ExpertBridgeResult {\n readonly success: boolean;\n readonly text: string;\n readonly expertType: BuiltInExpertType;\n readonly durationMs: number;\n readonly error?: string;\n /**\n * CLI that actually executed the task, resolved from the underlying\n * `CliResponse.model` via `getCliForModelId`. Undefined when the bridge\n * failed before dispatch (no adapters / circuit-open / rate-limit cap).\n * Callers writing to OutcomeStore should use this rather than hardcoding\n * a cli — see #2823 (#1154 regression).\n */\n readonly cli?: CliNameLiteral;\n /**\n * Total tokens (input + output) the underlying CLI/adapter reported for this\n * call, when available (#3396). Best-effort: `CliResponse.usage` is optional\n * — CLI-subprocess paths whose `extractUsage` returns null leave this\n * undefined. Consumers (budget enforcement #3395, model.called attribution\n * #3387, routing-experience metrics) must tolerate `undefined`.\n */\n readonly tokensUsed?: number;\n}\n\n/**\n * Execute an expert task with the full nexus-agents expert pipeline.\n *\n * Creates a built-in expert, executes via CompositeRouter (for intelligent\n * CLI routing), and records outcomes. Falls back gracefully on failure.\n *\n * @param expertType - Built-in expert type (code, architecture, security, qa, etc.)\n * @param prompt - Task prompt for the expert\n * @returns Expert result with text output\n */\n/** Minimal router interface for the bridge. */\ninterface RouterLike {\n executeTask(task: { content: string; options?: Record<string, unknown> | undefined }): Promise<{\n ok: boolean;\n value: { text: string; cli?: CliNameLiteral; tokensUsed?: number };\n error: { message: string };\n }>;\n}\n\n// Cached router — lazily initialized, reused across calls within a session\nlet cachedRouter: RouterLike | null = null;\n\n// Cached MCP config — generated once, reused across expert calls (#1708)\nlet cachedMcpConfigPath: string | null = null;\n// Cached cleanup for the cached config's tempdir (closes #2946). Previously\n// the cleanup returned by `generateMcpConfig` was thrown away, so\n// `/tmp/nexus-mcp-XXXXXX/` accumulated one entry per MCP server lifetime.\n// Stored here + invoked by `shutdownExpertBridge()` from the server's\n// graceful-shutdown path.\nlet cachedMcpConfigCleanup: (() => Promise<void>) | null = null;\n// Coalesces concurrent init under voter fan-out (closes #2969). consensus_vote\n// fans out N=7 callers on cold start; without this each one ran the full init\n// including a mkdtemp() that the loser N-1 instances never cleaned up.\nlet mcpConfigInitPromise: Promise<string | null> | null = null;\n\n/** Get or create cached MCP config path for expert CLI sessions (#1708). */\nasync function getMcpConfigPath(): Promise<string | null> {\n if (cachedMcpConfigPath !== null) return cachedMcpConfigPath;\n mcpConfigInitPromise ??= (async (): Promise<string | null> => {\n try {\n const { generateMcpConfig } = await import('../cli-adapters/child-mcp-config.js');\n const config = await generateMcpConfig();\n cachedMcpConfigPath = config.configPath;\n cachedMcpConfigCleanup = config.cleanup;\n return cachedMcpConfigPath;\n } catch {\n mcpConfigInitPromise = null; // allow retry on next call\n return null; // MCP config not available — experts run without tools\n }\n })();\n return mcpConfigInitPromise;\n}\n\n/**\n * Removes the cached MCP-config tempdir (closes #2946). Invoke from the\n * server's graceful-shutdown path so stale nexus-mcp-* tempdirs (under\n * the OS tmpdir, see child-mcp-config.ts) don't accumulate across daemon\n * restarts. Idempotent; safe to call multiple times. Never throws —\n * cleanup failures are logged and swallowed.\n */\nexport async function shutdownExpertBridge(): Promise<void> {\n const cleanup = cachedMcpConfigCleanup;\n if (cleanup === null) return;\n cachedMcpConfigCleanup = null;\n cachedMcpConfigPath = null;\n mcpConfigInitPromise = null;\n try {\n await cleanup();\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.debug('Expert-bridge MCP-config cleanup failed', { error: msg });\n }\n}\n\n/** Cached circuit breaker for health monitoring (#1766). */\nlet cachedCircuitBreaker: {\n getHealthStatus(): {\n systemHealthy: boolean;\n healthyCount: number;\n clis: ReadonlyArray<{ name: string; healthy: boolean }>;\n };\n} | null = null;\n\n/**\n * Adapt a CompositeRouter to the narrower RouterLike interface used by this\n * bridge. Previously did `as unknown as RouterLike` which hid any structural\n * mismatch between CompositeRouter's `Result<CliResponse, CliError>` and\n * RouterLike's flat `{ ok, value: { text }, error: { message } }` shape.\n * If CliResponse renames `.text` → `.output` (or similar), this adapter\n * breaks at compile time instead of silently returning wrong data (#1921).\n */\n/**\n * Total tokens from a best-effort `CliResponse.usage` record (#3396). Prefers\n * the reported `totalTokens`; falls back to input+output; returns undefined\n * when no usage was reported (so callers can distinguish \"0 tokens\" — which\n * never happens for a real call — from \"unknown\").\n */\nexport function totalTokensFromUsage(\n usage: { totalTokens?: number; inputTokens?: number; outputTokens?: number } | undefined\n): number | undefined {\n if (usage === undefined) return undefined;\n if (typeof usage.totalTokens === 'number') return usage.totalTokens;\n const total = (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0);\n return total > 0 ? total : undefined;\n}\n\nfunction adaptCompositeRouter(\n compositeRouter: import('../cli-adapters/composite-router.js').ICompositeRouter\n): RouterLike {\n return {\n async executeTask(task): Promise<{\n ok: boolean;\n value: { text: string; cli?: CliNameLiteral };\n error: { message: string };\n }> {\n const cliTask: import('../cli-adapters/types.js').CliTask = {\n content: task.content,\n ...(task.options !== undefined ? { options: task.options } : {}),\n };\n const result = await compositeRouter.executeTask(cliTask);\n if (result.ok) {\n // #2823: surface which CLI actually executed so callers writing to\n // OutcomeStore don't have to hardcode 'claude' (the bug #1154 fixed\n // and that regressed into the pipeline/ tree). Derive via the\n // canonical model→cli mapping in the registry — if the underlying\n // adapter didn't set `model` or the model isn't in the registry,\n // cli stays undefined and downstream code can skip the record\n // rather than lie.\n const cli = resolveCliFromModelString(result.value.model);\n // #3396: surface token usage (best-effort) so budget enforcement,\n // attribution, and routing-experience metrics get real numbers instead\n // of zeros. `usage` is optional and `totalTokens` may be absent — fall\n // back to input+output, and leave undefined when no usage was reported.\n const tokensUsed = totalTokensFromUsage(result.value.usage);\n return {\n ok: true,\n value: {\n text: result.value.text,\n ...(cli !== undefined && { cli }),\n ...(tokensUsed !== undefined && { tokensUsed }),\n },\n error: { message: '' },\n };\n }\n return { ok: false, value: { text: '' }, error: { message: result.error.message } };\n },\n };\n}\n\n// Coalesces concurrent router init the same way mcpConfigInitPromise does\n// (closes #2969). N=7 voter fan-out previously ran createAllAdapters() N times\n// — N sets of CLI probe subprocesses, all but one discarded.\nlet routerInitPromise: Promise<RouterLike | null> | null = null;\n\n/** Get or create a cached CompositeRouter with circuit breaker monitoring. */\nasync function getRouter(): Promise<RouterLike | null> {\n if (cachedRouter !== null) return cachedRouter;\n routerInitPromise ??= (async (): Promise<RouterLike | null> => {\n const { createAllAdapters } = await import('../cli-adapters/factory.js');\n const { createCompositeRouter } = await import('../cli-adapters/composite-router.js');\n const adapters = createAllAdapters();\n if (adapters.size === 0) {\n routerInitPromise = null; // allow retry once adapters become available\n return null;\n }\n cachedRouter = adaptCompositeRouter(createCompositeRouter(adapters));\n\n // Initialize circuit breaker monitoring (#1766)\n try {\n const { createCliCircuitBreakerIntegration } =\n await import('../cli-adapters/cli-circuit-breaker.js');\n cachedCircuitBreaker = createCliCircuitBreakerIntegration([...adapters.values()]);\n } catch (error: unknown) {\n // Circuit breaker not available — continue without it. Log so we can\n // notice if initialization silently stops working (#1913 Class B).\n const msg = error instanceof Error ? error.message : String(error);\n logger.debug('Circuit breaker init failed; continuing without it', { error: msg });\n }\n\n return cachedRouter;\n })();\n return routerInitPromise;\n}\n\n/** Check CLI health before dispatch (#1766). */\nfunction checkCircuitHealth(): { healthy: boolean; message: string } {\n if (cachedCircuitBreaker === null) return { healthy: true, message: '' };\n const status = cachedCircuitBreaker.getHealthStatus();\n if (!status.systemHealthy) {\n return {\n healthy: false,\n message: `All CLI circuits open (${String(status.healthyCount)}/${String(status.clis.length)} healthy)`,\n };\n }\n return { healthy: true, message: '' };\n}\n\n/** Dispatch task to router with rate limit retry (#1802). */\nasync function dispatchWithRateLimitRetry(\n router: RouterLike,\n task: { content: string; options?: Record<string, unknown> | undefined },\n expertType: BuiltInExpertType,\n start: number\n): Promise<ExpertBridgeResult> {\n const maxAttempts = 3;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const result = await router.executeTask(task);\n const durationMs = getTimeProvider().now() - start;\n\n if (result.ok) {\n logger.info('Expert executed successfully', {\n expertType,\n durationMs,\n cli: result.value.cli,\n });\n return {\n success: true,\n text: result.value.text,\n expertType,\n durationMs,\n ...(result.value.cli !== undefined && { cli: result.value.cli }),\n ...(result.value.tokensUsed !== undefined && { tokensUsed: result.value.tokensUsed }),\n };\n }\n\n const isRateLimit = isRateLimitText(result.error.message);\n if (isRateLimit && attempt < maxAttempts - 1) {\n const backoffMs = RATE_LIMIT_BASE_DELAY_MS * (attempt + 1);\n logger.warn('Expert rate limited, retrying', { expertType, attempt: attempt + 1, backoffMs });\n await new Promise((resolve) => setTimeout(resolve, backoffMs));\n continue;\n }\n\n logger.warn('Expert execution failed', { expertType, error: result.error.message });\n return { success: false, text: '', expertType, durationMs, error: result.error.message };\n }\n\n return {\n success: false,\n text: '',\n expertType,\n durationMs: getTimeProvider().now() - start,\n error: 'Max retry attempts exceeded',\n };\n}\n\nexport async function executeExpert(\n expertType: BuiltInExpertType,\n prompt: string\n): Promise<ExpertBridgeResult> {\n const start = getTimeProvider().now();\n try {\n const { BUILT_IN_EXPERTS } = await import('../agents/experts/expert-config.js');\n const config = BUILT_IN_EXPERTS[expertType];\n const fullPrompt = `${config.systemPrompt}\\n\\n${prompt}`;\n\n const router = await getRouter();\n if (router === null) {\n return {\n success: false,\n text: `[No adapters] ${prompt}`,\n expertType,\n durationMs: getTimeProvider().now() - start,\n error: 'No CLI adapters available',\n };\n }\n\n // Check circuit breaker health before dispatch (#1766)\n const health = checkCircuitHealth();\n if (!health.healthy) {\n logger.warn('Circuit breaker: all CLIs unavailable', { expertType, reason: health.message });\n return {\n success: false,\n text: '',\n expertType,\n durationMs: getTimeProvider().now() - start,\n error: health.message,\n };\n }\n\n // Pass MCP config so CLI experts can call nexus-agents tools (#1708)\n const mcpConfigPath = await getMcpConfigPath();\n const task: { content: string; options?: Record<string, unknown> | undefined } = {\n content: fullPrompt,\n };\n if (mcpConfigPath !== null) task.options = { mcpConfigPath };\n\n return await dispatchWithRateLimitRetry(router, task, expertType, start);\n } catch (error) {\n const durationMs = getTimeProvider().now() - start;\n const msg = error instanceof Error ? error.message : String(error);\n logger.warn('Expert bridge error', { expertType, error: msg });\n return { success: false, text: '', expertType, durationMs, error: msg };\n }\n}\n"],"mappings":"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","names":[]}