nexus-agents 2.84.0 → 2.85.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.
Files changed (110) hide show
  1. package/dist/{child-mcp-config-VSGPMVLL.js → child-mcp-config-FARMFCA3.js} +2 -2
  2. package/dist/{chunk-BX3MUA26.js → chunk-25AQZKMN.js} +2 -2
  3. package/dist/{chunk-ZJGCOJC6.js → chunk-4MYJNFYL.js} +3 -3
  4. package/dist/{chunk-GBGMTN7O.js → chunk-4S5GY2MF.js} +2 -2
  5. package/dist/{chunk-KVYQOOML.js → chunk-4SU4Q37U.js} +4 -4
  6. package/dist/{chunk-3PFESR6I.js → chunk-6KZL5DMU.js} +1783 -1473
  7. package/dist/chunk-6KZL5DMU.js.map +1 -0
  8. package/dist/{chunk-4IXQ6IXI.js → chunk-6QKMUPDP.js} +2 -2
  9. package/dist/{chunk-CJHIKBWI.js → chunk-7J7D3LAL.js} +4 -4
  10. package/dist/{chunk-2PKAWFEU.js → chunk-CIW2BVSN.js} +2 -2
  11. package/dist/{chunk-REH5BB67.js → chunk-EL2KV773.js} +2 -2
  12. package/dist/{chunk-T6B6CKU6.js → chunk-ELVQORLX.js} +3 -3
  13. package/dist/{chunk-UJMIGLZI.js → chunk-FOG7PMGM.js} +2 -2
  14. package/dist/{chunk-I3O5WOGW.js → chunk-FR3P47J2.js} +3 -3
  15. package/dist/{chunk-V7RC2PIY.js → chunk-IF6TXCSE.js} +672 -225
  16. package/dist/chunk-IF6TXCSE.js.map +1 -0
  17. package/dist/{chunk-QIRZSDJK.js → chunk-J5S27RQ4.js} +2 -2
  18. package/dist/{chunk-XK523BNC.js → chunk-LY2KLNXM.js} +2 -2
  19. package/dist/{chunk-MBD5EJBO.js → chunk-NSOB2WRI.js} +3 -3
  20. package/dist/{chunk-VQIWH6X4.js → chunk-OXVOUVKH.js} +7 -7
  21. package/dist/{chunk-V35FWPHD.js → chunk-POTGGTJD.js} +2 -2
  22. package/dist/{chunk-KRRBRT7B.js → chunk-QR4VYHMI.js} +5 -5
  23. package/dist/{chunk-KK2RZVPU.js → chunk-QR5KHIZG.js} +2 -2
  24. package/dist/{chunk-OE7OL2BE.js → chunk-RTAIMK6P.js} +4 -4
  25. package/dist/{chunk-5LFUZ5IC.js → chunk-SOKQOPTM.js} +2 -2
  26. package/dist/{chunk-YVG32OQF.js → chunk-TRX7CAD5.js} +2 -2
  27. package/dist/{chunk-VXHDZULO.js → chunk-XZAWH36N.js} +3 -3
  28. package/dist/{chunk-HLNMWGW3.js → chunk-YLMB5MFQ.js} +2 -2
  29. package/dist/{chunk-HLNMWGW3.js.map → chunk-YLMB5MFQ.js.map} +1 -1
  30. package/dist/{chunk-OROUYVUX.js → chunk-Z5BAZS6F.js} +2 -2
  31. package/dist/{chunk-RZVEVT3M.js → chunk-ZF3MSYLG.js} +7 -7
  32. package/dist/{chunk-D5BKSM6H.js → chunk-ZMERLMEP.js} +2 -2
  33. package/dist/{cli-circuit-breaker-6EQKYNAA.js → cli-circuit-breaker-LF22Z3QL.js} +4 -4
  34. package/dist/cli.d.ts +1 -1
  35. package/dist/cli.js +36 -34
  36. package/dist/cli.js.map +1 -1
  37. package/dist/{composite-router-SA4XHXA3.js → composite-router-TEXZI7WJ.js} +2 -2
  38. package/dist/{consensus-vote-QKUHNHS4.js → consensus-vote-LPYEXUVC.js} +12 -12
  39. package/dist/{consensus-vote-types-CoGbAEjf.d.ts → consensus-vote-types-COAhHVIp.d.ts} +5 -0
  40. package/dist/{context-retriever-XX4TQBIB.js → context-retriever-3TKV4EEC.js} +6 -6
  41. package/dist/{dist-APHOQ26Z.js → dist-75MXB4R3.js} +917 -822
  42. package/dist/dist-75MXB4R3.js.map +1 -0
  43. package/dist/{doctor-deep-NB7IDWJE.js → doctor-deep-OUAKPLJX.js} +3 -3
  44. package/dist/{expert-bridge-4MHM77VW.js → expert-bridge-22UVN5TB.js} +4 -4
  45. package/dist/{factory-FKOPQXRS.js → factory-IGHUOUBS.js} +5 -5
  46. package/dist/{factory-UHH4ZZ64.js → factory-JNXETBS4.js} +5 -5
  47. package/dist/index.d.ts +26 -4
  48. package/dist/index.js +25 -25
  49. package/dist/{init-opencode-AVYAC33Q.js → init-opencode-52TLZ2TO.js} +5 -5
  50. package/dist/{issue-triage-7PYND7PY.js → issue-triage-WUK7L25X.js} +4 -4
  51. package/dist/{registry-command-7SFNZRG5.js → registry-command-ZIAJB2J3.js} +2 -2
  52. package/dist/{repo-security-plan-MTVL5B73.js → repo-security-plan-THHLNGEQ.js} +3 -3
  53. package/dist/{research-helpers-synthesize-6CJ5P4WL.js → research-helpers-synthesize-KNRCAIXK.js} +3 -3
  54. package/dist/{routing-memory-Y577PXFP.js → routing-memory-UY6KTGT2.js} +2 -2
  55. package/dist/{session-memory-6YFGMEMP.js → session-memory-PUJMR6FE.js} +3 -3
  56. package/dist/{setup-command-YBTD6D53.js → setup-command-ZXDAR3GQ.js} +11 -11
  57. package/dist/{setup-config-BQYLUJHY.js → setup-config-EYY5AYZ3.js} +3 -3
  58. package/dist/{setup-custom-api-ZB7LOQC5.js → setup-custom-api-5XRNYFOP.js} +4 -4
  59. package/dist/{tool-memory-GFYQFRQI.js → tool-memory-PNAHRFZM.js} +5 -5
  60. package/dist/{weather-report-CN6WPJI4.js → weather-report-RQMZOL7C.js} +2 -2
  61. package/package.json +4 -4
  62. package/dist/chunk-3PFESR6I.js.map +0 -1
  63. package/dist/chunk-V7RC2PIY.js.map +0 -1
  64. package/dist/dist-APHOQ26Z.js.map +0 -1
  65. /package/dist/{child-mcp-config-VSGPMVLL.js.map → child-mcp-config-FARMFCA3.js.map} +0 -0
  66. /package/dist/{chunk-BX3MUA26.js.map → chunk-25AQZKMN.js.map} +0 -0
  67. /package/dist/{chunk-ZJGCOJC6.js.map → chunk-4MYJNFYL.js.map} +0 -0
  68. /package/dist/{chunk-GBGMTN7O.js.map → chunk-4S5GY2MF.js.map} +0 -0
  69. /package/dist/{chunk-KVYQOOML.js.map → chunk-4SU4Q37U.js.map} +0 -0
  70. /package/dist/{chunk-4IXQ6IXI.js.map → chunk-6QKMUPDP.js.map} +0 -0
  71. /package/dist/{chunk-CJHIKBWI.js.map → chunk-7J7D3LAL.js.map} +0 -0
  72. /package/dist/{chunk-2PKAWFEU.js.map → chunk-CIW2BVSN.js.map} +0 -0
  73. /package/dist/{chunk-REH5BB67.js.map → chunk-EL2KV773.js.map} +0 -0
  74. /package/dist/{chunk-T6B6CKU6.js.map → chunk-ELVQORLX.js.map} +0 -0
  75. /package/dist/{chunk-UJMIGLZI.js.map → chunk-FOG7PMGM.js.map} +0 -0
  76. /package/dist/{chunk-I3O5WOGW.js.map → chunk-FR3P47J2.js.map} +0 -0
  77. /package/dist/{chunk-QIRZSDJK.js.map → chunk-J5S27RQ4.js.map} +0 -0
  78. /package/dist/{chunk-XK523BNC.js.map → chunk-LY2KLNXM.js.map} +0 -0
  79. /package/dist/{chunk-MBD5EJBO.js.map → chunk-NSOB2WRI.js.map} +0 -0
  80. /package/dist/{chunk-VQIWH6X4.js.map → chunk-OXVOUVKH.js.map} +0 -0
  81. /package/dist/{chunk-V35FWPHD.js.map → chunk-POTGGTJD.js.map} +0 -0
  82. /package/dist/{chunk-KRRBRT7B.js.map → chunk-QR4VYHMI.js.map} +0 -0
  83. /package/dist/{chunk-KK2RZVPU.js.map → chunk-QR5KHIZG.js.map} +0 -0
  84. /package/dist/{chunk-OE7OL2BE.js.map → chunk-RTAIMK6P.js.map} +0 -0
  85. /package/dist/{chunk-5LFUZ5IC.js.map → chunk-SOKQOPTM.js.map} +0 -0
  86. /package/dist/{chunk-YVG32OQF.js.map → chunk-TRX7CAD5.js.map} +0 -0
  87. /package/dist/{chunk-VXHDZULO.js.map → chunk-XZAWH36N.js.map} +0 -0
  88. /package/dist/{chunk-OROUYVUX.js.map → chunk-Z5BAZS6F.js.map} +0 -0
  89. /package/dist/{chunk-RZVEVT3M.js.map → chunk-ZF3MSYLG.js.map} +0 -0
  90. /package/dist/{chunk-D5BKSM6H.js.map → chunk-ZMERLMEP.js.map} +0 -0
  91. /package/dist/{cli-circuit-breaker-6EQKYNAA.js.map → cli-circuit-breaker-LF22Z3QL.js.map} +0 -0
  92. /package/dist/{composite-router-SA4XHXA3.js.map → composite-router-TEXZI7WJ.js.map} +0 -0
  93. /package/dist/{consensus-vote-QKUHNHS4.js.map → consensus-vote-LPYEXUVC.js.map} +0 -0
  94. /package/dist/{context-retriever-XX4TQBIB.js.map → context-retriever-3TKV4EEC.js.map} +0 -0
  95. /package/dist/{doctor-deep-NB7IDWJE.js.map → doctor-deep-OUAKPLJX.js.map} +0 -0
  96. /package/dist/{expert-bridge-4MHM77VW.js.map → expert-bridge-22UVN5TB.js.map} +0 -0
  97. /package/dist/{factory-FKOPQXRS.js.map → factory-IGHUOUBS.js.map} +0 -0
  98. /package/dist/{factory-UHH4ZZ64.js.map → factory-JNXETBS4.js.map} +0 -0
  99. /package/dist/{init-opencode-AVYAC33Q.js.map → init-opencode-52TLZ2TO.js.map} +0 -0
  100. /package/dist/{issue-triage-7PYND7PY.js.map → issue-triage-WUK7L25X.js.map} +0 -0
  101. /package/dist/{registry-command-7SFNZRG5.js.map → registry-command-ZIAJB2J3.js.map} +0 -0
  102. /package/dist/{repo-security-plan-MTVL5B73.js.map → repo-security-plan-THHLNGEQ.js.map} +0 -0
  103. /package/dist/{research-helpers-synthesize-6CJ5P4WL.js.map → research-helpers-synthesize-KNRCAIXK.js.map} +0 -0
  104. /package/dist/{routing-memory-Y577PXFP.js.map → routing-memory-UY6KTGT2.js.map} +0 -0
  105. /package/dist/{session-memory-6YFGMEMP.js.map → session-memory-PUJMR6FE.js.map} +0 -0
  106. /package/dist/{setup-command-YBTD6D53.js.map → setup-command-ZXDAR3GQ.js.map} +0 -0
  107. /package/dist/{setup-config-BQYLUJHY.js.map → setup-config-EYY5AYZ3.js.map} +0 -0
  108. /package/dist/{setup-custom-api-ZB7LOQC5.js.map → setup-custom-api-5XRNYFOP.js.map} +0 -0
  109. /package/dist/{tool-memory-GFYQFRQI.js.map → tool-memory-PNAHRFZM.js.map} +0 -0
  110. /package/dist/{weather-report-CN6WPJI4.js.map → weather-report-RQMZOL7C.js.map} +0 -0
@@ -4,21 +4,21 @@ import {
4
4
  createStream,
5
5
  requireApiKey,
6
6
  validateApiKeyPresence
7
- } from "./chunk-4IXQ6IXI.js";
7
+ } from "./chunk-6QKMUPDP.js";
8
8
  import {
9
9
  CUSTOM_API_BASE_URL_ENV,
10
10
  PROVIDER_ENV_KEYS,
11
11
  validateCustomApiBaseUrl
12
- } from "./chunk-V35FWPHD.js";
12
+ } from "./chunk-POTGGTJD.js";
13
13
  import {
14
14
  getToolMemory
15
- } from "./chunk-KVYQOOML.js";
15
+ } from "./chunk-4SU4Q37U.js";
16
16
  import {
17
17
  getDefaultAvailableModelsCache
18
- } from "./chunk-UJMIGLZI.js";
18
+ } from "./chunk-FOG7PMGM.js";
19
19
  import {
20
20
  CUSTOM_API_DEFAULT_MODEL
21
- } from "./chunk-BX3MUA26.js";
21
+ } from "./chunk-25AQZKMN.js";
22
22
  import {
23
23
  createCliAdapter,
24
24
  createCliDetectionCache,
@@ -27,7 +27,7 @@ import {
27
27
  isCliAvailable,
28
28
  sanitizeOutput,
29
29
  withTimeout
30
- } from "./chunk-OE7OL2BE.js";
30
+ } from "./chunk-RTAIMK6P.js";
31
31
  import {
32
32
  AgentError,
33
33
  CACHE_TIMEOUTS,
@@ -70,47 +70,48 @@ import {
70
70
  resolveCliAlias,
71
71
  resolveVoteTimeout,
72
72
  toRateLimitError
73
- } from "./chunk-HLNMWGW3.js";
73
+ } from "./chunk-YLMB5MFQ.js";
74
74
  import {
75
75
  ensureLearningDir,
76
76
  getNexusDataDir,
77
77
  getOutcomesFile,
78
- nexusDataPath
78
+ nexusDataPath,
79
+ nexusDataPathEnsure
79
80
  } from "./chunk-2WCYG75B.js";
80
81
 
81
82
  // src/mcp/tools/consensus-vote.ts
82
- import { z as z10 } from "zod";
83
+ import { z as z12 } from "zod";
83
84
 
84
85
  // src/mcp/mcp-notifier.ts
85
86
  import { AsyncLocalStorage } from "async_hooks";
86
87
  var internalLogger = createLogger({ component: "mcp-notifier" });
87
88
  function createMcpNotifier(server) {
88
- function send(level, logger8, data) {
89
+ function send(level, logger11, data) {
89
90
  try {
90
- server.sendLoggingMessage({ level, logger: logger8, data }).catch((error) => {
91
+ server.sendLoggingMessage({ level, logger: logger11, data }).catch((error) => {
91
92
  internalLogger.debug("Failed to send MCP notification", {
92
93
  level,
93
- logger: logger8,
94
+ logger: logger11,
94
95
  error: getErrorMessage(error)
95
96
  });
96
97
  });
97
98
  } catch (error) {
98
99
  internalLogger.debug("Failed to send MCP notification", {
99
100
  level,
100
- logger: logger8,
101
+ logger: logger11,
101
102
  error: getErrorMessage(error)
102
103
  });
103
104
  }
104
105
  }
105
106
  return {
106
- info: (logger8, data) => {
107
- send("info", logger8, data);
107
+ info: (logger11, data) => {
108
+ send("info", logger11, data);
108
109
  },
109
- debug: (logger8, data) => {
110
- send("debug", logger8, data);
110
+ debug: (logger11, data) => {
111
+ send("debug", logger11, data);
111
112
  },
112
- warn: (logger8, data) => {
113
- send("warning", logger8, data);
113
+ warn: (logger11, data) => {
114
+ send("warning", logger11, data);
114
115
  }
115
116
  };
116
117
  }
@@ -240,7 +241,7 @@ var RateLimiter = class {
240
241
  this.logger.debug("Rate limiter reset", { tokens: this.tokens });
241
242
  }
242
243
  };
243
- function createDefaultRateLimiter(name, logger8) {
244
+ function createDefaultRateLimiter(name, logger11) {
244
245
  const config = {
245
246
  capacity: 100,
246
247
  refillRate: 10,
@@ -249,8 +250,8 @@ function createDefaultRateLimiter(name, logger8) {
249
250
  if (name !== void 0) {
250
251
  config.name = name;
251
252
  }
252
- if (logger8 !== void 0) {
253
- config.logger = logger8;
253
+ if (logger11 !== void 0) {
254
+ config.logger = logger11;
254
255
  }
255
256
  return new RateLimiter(config);
256
257
  }
@@ -890,6 +891,8 @@ var READ_ONLY_TOOLS2 = /* @__PURE__ */ new Set([
890
891
  "query_task_state",
891
892
  // Async-mode result polling (#3042 / epic #2631)
892
893
  "get_job_result",
894
+ // Async-mode job discovery (#3046 / epic #2631 Stage 5)
895
+ "list_jobs",
893
896
  // Codebase intelligence (read-only over local files)
894
897
  "search_codebase",
895
898
  "extract_symbols",
@@ -1237,13 +1240,13 @@ function buildMiddlewareStack(config) {
1237
1240
  return middlewares;
1238
1241
  }
1239
1242
  function createMiddlewareChain(config) {
1240
- const logger8 = config.logger ?? createLogger({ tool: config.toolName });
1243
+ const logger11 = config.logger ?? createLogger({ tool: config.toolName });
1241
1244
  const middlewares = buildMiddlewareStack(config);
1242
1245
  const composed = composeMiddleware(middlewares);
1243
1246
  return (handler) => {
1244
1247
  return async (args) => {
1245
1248
  const requestContext = createRequestContext({ toolName: config.toolName });
1246
- const requestLogger = logger8.child(contextForLogging(requestContext));
1249
+ const requestLogger = logger11.child(contextForLogging(requestContext));
1247
1250
  const ctx = { requestContext, logger: requestLogger };
1248
1251
  return composed(args, ctx, (finalArgs, finalCtx) => handler(finalArgs, finalCtx));
1249
1252
  };
@@ -1430,8 +1433,8 @@ async function runMismatchedCall(ctx) {
1430
1433
  throw err2;
1431
1434
  }
1432
1435
  }
1433
- function toSdkCallbackWithBudgetCheck(handler, toolName, configuredTimeoutMs, logger8) {
1434
- const log = logger8 ?? wrapperLogger;
1436
+ function toSdkCallbackWithBudgetCheck(handler, toolName, configuredTimeoutMs, logger11) {
1437
+ const log = logger11 ?? wrapperLogger;
1435
1438
  return (args, extra) => {
1436
1439
  const progressCtx = extractProgressContext(extra);
1437
1440
  const signal = extra?.signal;
@@ -1555,15 +1558,15 @@ function sanitizeToolInput(args) {
1555
1558
  detectedPatterns: uniquePatterns
1556
1559
  };
1557
1560
  }
1558
- function logSanitizationResult(result, logger8, toolName) {
1561
+ function logSanitizationResult(result, logger11, toolName) {
1559
1562
  if (result.wasModified) {
1560
- logger8.warn("Tool input sanitized \u2014 XML injection tags stripped", {
1563
+ logger11.warn("Tool input sanitized \u2014 XML injection tags stripped", {
1561
1564
  tool: toolName,
1562
1565
  modifiedFields: result.modifiedCount
1563
1566
  });
1564
1567
  }
1565
1568
  if (result.detectedPatterns.length > 0) {
1566
- logger8.warn("Injection patterns detected in tool input", {
1569
+ logger11.warn("Injection patterns detected in tool input", {
1567
1570
  tool: toolName,
1568
1571
  patterns: result.detectedPatterns
1569
1572
  });
@@ -1603,11 +1606,11 @@ var SECRET_PATTERNS = [
1603
1606
  // password= or token= in output
1604
1607
  /(?:password|token|secret|apikey|api_key)\s*[=:]\s*\S{8,}/i
1605
1608
  ];
1606
- function sanitizeOutput2(text, logger8) {
1609
+ function sanitizeOutput2(text, logger11) {
1607
1610
  let sanitized = text;
1608
1611
  for (const pattern of SECRET_PATTERNS) {
1609
1612
  if (pattern.test(sanitized)) {
1610
- logger8.warn("Potential secret detected in tool output, redacting", {
1613
+ logger11.warn("Potential secret detected in tool output, redacting", {
1611
1614
  pattern: pattern.source.slice(0, 30)
1612
1615
  });
1613
1616
  sanitized = sanitized.replace(pattern, "[REDACTED]");
@@ -1615,25 +1618,25 @@ function sanitizeOutput2(text, logger8) {
1615
1618
  }
1616
1619
  return sanitized;
1617
1620
  }
1618
- function sanitizeToolResult(result, logger8) {
1621
+ function sanitizeToolResult(result, logger11) {
1619
1622
  for (const item of result.content) {
1620
- item.text = sanitizeOutput2(item.text, logger8);
1623
+ item.text = sanitizeOutput2(item.text, logger11);
1621
1624
  }
1622
1625
  }
1623
- function checkInputSize(args, logger8, requestId) {
1626
+ function checkInputSize(args, logger11, requestId) {
1624
1627
  if (args === void 0) return null;
1625
1628
  const inputSize = JSON.stringify(args).length;
1626
1629
  if (inputSize > MAX_INPUT_SIZE_BYTES) {
1627
- logger8.warn("Input size exceeds limit", { inputSize, limit: MAX_INPUT_SIZE_BYTES });
1630
+ logger11.warn("Input size exceeds limit", { inputSize, limit: MAX_INPUT_SIZE_BYTES });
1628
1631
  return internalError("Input too large", requestId);
1629
1632
  }
1630
1633
  return null;
1631
1634
  }
1632
- function checkRateLimit(rateLimiter, logger8) {
1635
+ function checkRateLimit(rateLimiter, logger11) {
1633
1636
  const acquired = rateLimiter.tryAcquire();
1634
1637
  if (!acquired) {
1635
1638
  const state = rateLimiter.getState();
1636
- logger8.warn("Rate limit exceeded");
1639
+ logger11.warn("Rate limit exceeded");
1637
1640
  return rateLimitError(state.nextTokenMs);
1638
1641
  }
1639
1642
  return null;
@@ -1654,14 +1657,14 @@ function checkPolicy(opts) {
1654
1657
  opts.logger.debug("Policy check passed", { reason: decision.reason });
1655
1658
  return null;
1656
1659
  }
1657
- async function executeHandler(handler, args, ctx, logger8) {
1660
+ async function executeHandler(handler, args, ctx, logger11) {
1658
1661
  const startTime = getTimeProvider().now();
1659
1662
  const result = handler.length >= 2 ? await handler(args, ctx) : await handler(args);
1660
1663
  const durationMs = getTimeProvider().now() - startTime;
1661
1664
  if (result.isError === true) {
1662
- logger8.warn("Tool execution completed with error", { durationMs });
1665
+ logger11.warn("Tool execution completed with error", { durationMs });
1663
1666
  } else {
1664
- logger8.info("Tool execution completed", { durationMs });
1667
+ logger11.info("Tool execution completed", { durationMs });
1665
1668
  }
1666
1669
  return result;
1667
1670
  }
@@ -1707,12 +1710,12 @@ function emitRateLimitAudit(auditLogger, toolName, ctx) {
1707
1710
  requestId: ctx.requestId
1708
1711
  });
1709
1712
  }
1710
- function checkSecurityTier(config, sanitizeResult, logger8) {
1713
+ function checkSecurityTier(config, sanitizeResult, logger11) {
1711
1714
  const tier = config.securityTier ?? "standard";
1712
1715
  if (tier === "standard" || sanitizeResult.detectedPatterns.length === 0) {
1713
1716
  return null;
1714
1717
  }
1715
- logger8.warn("Input rejected by security tier validation", {
1718
+ logger11.warn("Input rejected by security tier validation", {
1716
1719
  tier,
1717
1720
  patterns: sanitizeResult.detectedPatterns
1718
1721
  });
@@ -1721,16 +1724,16 @@ function checkSecurityTier(config, sanitizeResult, logger8) {
1721
1724
  message: `Input validation failed: detected patterns [${sanitizeResult.detectedPatterns.join(", ")}]. Remove prompt injection patterns and retry.`
1722
1725
  });
1723
1726
  }
1724
- function runPreChecks(config, args, mode, requestContext, logger8) {
1725
- const sizeResult = checkInputSize(args, logger8, requestContext.requestId);
1727
+ function runPreChecks(config, args, mode, requestContext, logger11) {
1728
+ const sizeResult = checkInputSize(args, logger11, requestContext.requestId);
1726
1729
  if (sizeResult) return { error: sizeResult, sanitizedArgs: args };
1727
1730
  const sanitizeResult = sanitizeToolInput(args);
1728
- logSanitizationResult(sanitizeResult, logger8, config.toolName);
1731
+ logSanitizationResult(sanitizeResult, logger11, config.toolName);
1729
1732
  const sanitizedArgs = sanitizeResult.wasModified ? sanitizeResult.sanitized : args;
1730
- const tierError = checkSecurityTier(config, sanitizeResult, logger8);
1733
+ const tierError = checkSecurityTier(config, sanitizeResult, logger11);
1731
1734
  if (tierError !== null) return { error: tierError, sanitizedArgs };
1732
1735
  if (config.rateLimiter) {
1733
- const rlResult = checkRateLimit(config.rateLimiter, logger8);
1736
+ const rlResult = checkRateLimit(config.rateLimiter, logger11);
1734
1737
  if (rlResult) {
1735
1738
  if (config.auditLogger)
1736
1739
  emitRateLimitAudit(config.auditLogger, config.toolName, requestContext);
@@ -1744,7 +1747,7 @@ function runPreChecks(config, args, mode, requestContext, logger8) {
1744
1747
  args: sanitizedArgs,
1745
1748
  mode,
1746
1749
  allowedPaths: config.allowedPaths,
1747
- logger: logger8,
1750
+ logger: logger11,
1748
1751
  requestId: requestContext.requestId
1749
1752
  });
1750
1753
  if (pResult) {
@@ -1756,7 +1759,7 @@ function runPreChecks(config, args, mode, requestContext, logger8) {
1756
1759
  return { error: null, sanitizedArgs };
1757
1760
  }
1758
1761
  function createSecureHandler(handler, config) {
1759
- const logger8 = config.logger ?? createLogger({ tool: config.toolName });
1762
+ const logger11 = config.logger ?? createLogger({ tool: config.toolName });
1760
1763
  const mode = config.executionMode ?? "read-only";
1761
1764
  return async (args) => {
1762
1765
  const ctxOpts = {
@@ -1764,7 +1767,7 @@ function createSecureHandler(handler, config) {
1764
1767
  ...config.callerInfo && { caller: config.callerInfo }
1765
1768
  };
1766
1769
  const requestContext = createRequestContext(ctxOpts);
1767
- const requestLogger = logger8.child(contextForLogging(requestContext));
1770
+ const requestLogger = logger11.child(contextForLogging(requestContext));
1768
1771
  requestLogger.info("Tool invocation started");
1769
1772
  const { error: preCheckError, sanitizedArgs } = runPreChecks(
1770
1773
  config,
@@ -2362,10 +2365,10 @@ var ClaudeAdapter = class extends BaseAdapter {
2362
2365
  return this.modelsCache.value;
2363
2366
  }
2364
2367
  if (this.modelsInFlight !== null) return this.modelsInFlight;
2365
- const inFlight = this.fetchModels();
2366
- this.modelsInFlight = inFlight;
2368
+ const inFlight2 = this.fetchModels();
2369
+ this.modelsInFlight = inFlight2;
2367
2370
  try {
2368
- const value = await inFlight;
2371
+ const value = await inFlight2;
2369
2372
  this.modelsCache = { value, fetchedAt: Date.now() };
2370
2373
  return value;
2371
2374
  } finally {
@@ -2465,13 +2468,13 @@ var SdkAdapter = class extends BaseAdapter {
2465
2468
  customBaseUrl;
2466
2469
  /** Inflight init promise for coalescing concurrent calls (Issue #1438). */
2467
2470
  initPromise;
2468
- constructor(config, logger8) {
2471
+ constructor(config, logger11) {
2469
2472
  const apiKey = resolveApiKey(config.providerId, config.apiKey);
2470
2473
  super({
2471
2474
  providerId: `sdk-${config.providerId}`,
2472
2475
  modelId: config.modelId,
2473
2476
  capabilities: [ModelCapability.COMPLETION, ModelCapability.STREAMING],
2474
- logger: logger8 ?? createLogger({ adapter: `sdk-${config.providerId}` }),
2477
+ logger: logger11 ?? createLogger({ adapter: `sdk-${config.providerId}` }),
2475
2478
  ...apiKey !== void 0 ? { apiKey } : {},
2476
2479
  ...config.timeout !== void 0 ? { timeout: config.timeout } : {},
2477
2480
  ...config.maxRetries !== void 0 ? { maxRetries: config.maxRetries } : {}
@@ -2651,19 +2654,19 @@ var SdkAdapter = class extends BaseAdapter {
2651
2654
 
2652
2655
  // src/adapters/auto-adapter.ts
2653
2656
  var defaultLogger = createLogger({ component: "auto-adapter" });
2654
- function resolveCache(config, logger8) {
2657
+ function resolveCache(config, logger11) {
2655
2658
  if (config.cache !== void 0) {
2656
2659
  return config.cache;
2657
2660
  }
2658
2661
  const enableCache = config.enableCache ?? true;
2659
- return enableCache ? createCliDetectionCache({ logger: logger8 }) : void 0;
2662
+ return enableCache ? createCliDetectionCache({ logger: logger11 }) : void 0;
2660
2663
  }
2661
- async function tryCliAdapter(config, logger8, cache) {
2664
+ async function tryCliAdapter(config, logger11, cache) {
2662
2665
  const preferredCli = config.preferredCli;
2663
2666
  const bridgeConfig = config.defaultCliTimeoutMs !== void 0 ? { defaultTimeoutMs: config.defaultCliTimeoutMs } : void 0;
2664
2667
  if (preferredCli !== void 0 && await isCliAvailable(preferredCli, cache)) {
2665
- logger8.info("Using preferred CLI", { cli: preferredCli });
2666
- const cliAdapter2 = createCliAdapter({ cli: preferredCli, logger: logger8 });
2668
+ logger11.info("Using preferred CLI", { cli: preferredCli });
2669
+ const cliAdapter2 = createCliAdapter({ cli: preferredCli, logger: logger11 });
2667
2670
  await cliAdapter2.initialize();
2668
2671
  return {
2669
2672
  adapter: createCliToModelAdapter(cliAdapter2, bridgeConfig),
@@ -2675,15 +2678,15 @@ async function tryCliAdapter(config, logger8, cache) {
2675
2678
  }
2676
2679
  const availableClis = await getAvailableClis(cache);
2677
2680
  if (availableClis.length === 0) {
2678
- logger8.info("No CLI adapters available");
2681
+ logger11.info("No CLI adapters available");
2679
2682
  return null;
2680
2683
  }
2681
2684
  const selectedCli = availableClis[0];
2682
2685
  if (selectedCli === void 0) {
2683
2686
  return null;
2684
2687
  }
2685
- logger8.info("Auto-selected CLI", { cli: selectedCli, available: availableClis });
2686
- const cliAdapter = createCliAdapter({ cli: selectedCli, logger: logger8 });
2688
+ logger11.info("Auto-selected CLI", { cli: selectedCli, available: availableClis });
2689
+ const cliAdapter = createCliAdapter({ cli: selectedCli, logger: logger11 });
2687
2690
  await cliAdapter.initialize();
2688
2691
  return {
2689
2692
  adapter: createCliToModelAdapter(cliAdapter, bridgeConfig),
@@ -2697,13 +2700,13 @@ function resolveApiKeyFromEnv(configKey, envVar) {
2697
2700
  const key = configKey ?? process.env[envVar];
2698
2701
  return key !== void 0 && key.length > 0 ? key : void 0;
2699
2702
  }
2700
- function tryApiAdapter(config, logger8) {
2703
+ function tryApiAdapter(config, logger11) {
2701
2704
  const claudeModelId = getCliModelName(getDefaultModelForCli("claude"));
2702
2705
  const codexModelId = getCliModelName(getDefaultModelForCli("codex"));
2703
2706
  const geminiModelId = getCliModelName(getDefaultModelForCli("gemini"));
2704
2707
  const anthropicKey = resolveApiKeyFromEnv(config.anthropicApiKey, "ANTHROPIC_API_KEY");
2705
2708
  if (anthropicKey !== void 0) {
2706
- logger8.info("Using Anthropic API adapter", { model: claudeModelId });
2709
+ logger11.info("Using Anthropic API adapter", { model: claudeModelId });
2707
2710
  return {
2708
2711
  adapter: createClaudeAdapter({ modelId: claudeModelId, apiKey: anthropicKey }),
2709
2712
  source: "api",
@@ -2713,7 +2716,7 @@ function tryApiAdapter(config, logger8) {
2713
2716
  }
2714
2717
  const openaiKey = resolveApiKeyFromEnv(config.openaiApiKey, "OPENAI_API_KEY");
2715
2718
  if (openaiKey !== void 0) {
2716
- logger8.info("Using OpenAI API adapter (AI SDK)", { model: codexModelId });
2719
+ logger11.info("Using OpenAI API adapter (AI SDK)", { model: codexModelId });
2717
2720
  return {
2718
2721
  adapter: new SdkAdapter({ providerId: "openai", modelId: codexModelId, apiKey: openaiKey }),
2719
2722
  source: "api",
@@ -2723,7 +2726,7 @@ function tryApiAdapter(config, logger8) {
2723
2726
  }
2724
2727
  const googleKey = resolveApiKeyFromEnv(config.googleApiKey, "GOOGLE_AI_API_KEY");
2725
2728
  if (googleKey !== void 0) {
2726
- logger8.info("Using Google AI API adapter (AI SDK)", { model: geminiModelId });
2729
+ logger11.info("Using Google AI API adapter (AI SDK)", { model: geminiModelId });
2727
2730
  return {
2728
2731
  adapter: new SdkAdapter({
2729
2732
  providerId: "google",
@@ -2735,19 +2738,19 @@ function tryApiAdapter(config, logger8) {
2735
2738
  reason: `Using Google AI API via AI SDK (model: ${geminiModelId})`
2736
2739
  };
2737
2740
  }
2738
- const custom = tryCustomOpenAiAdapter(logger8);
2741
+ const custom = tryCustomOpenAiAdapter(logger11);
2739
2742
  if (custom !== null) return custom;
2740
- logger8.info("No API keys available for any provider");
2743
+ logger11.info("No API keys available for any provider");
2741
2744
  return null;
2742
2745
  }
2743
- function tryCustomOpenAiAdapter(logger8) {
2746
+ function tryCustomOpenAiAdapter(logger11) {
2744
2747
  const customKey = resolveApiKeyFromEnv(void 0, "NEXUS_CUSTOM_API_KEY");
2745
2748
  const customBaseUrl = process.env["NEXUS_CUSTOM_API_BASE_URL"];
2746
2749
  if (customKey === void 0 || customBaseUrl === void 0 || customBaseUrl === "") {
2747
2750
  return null;
2748
2751
  }
2749
2752
  const customModelId = process.env["NEXUS_CUSTOM_MODEL"] ?? CUSTOM_API_DEFAULT_MODEL;
2750
- logger8.info("Using custom-openai SDK adapter", {
2753
+ logger11.info("Using custom-openai SDK adapter", {
2751
2754
  model: customModelId,
2752
2755
  baseUrl: customBaseUrl
2753
2756
  });
@@ -2763,52 +2766,52 @@ function tryCustomOpenAiAdapter(logger8) {
2763
2766
  reason: `Using custom OpenAI-compatible gateway at ${customBaseUrl} (model: ${customModelId})`
2764
2767
  };
2765
2768
  }
2766
- async function selectCliFirst(config, logger8, cache) {
2767
- const cliResult = await tryCliAdapter(config, logger8, cache);
2769
+ async function selectCliFirst(config, logger11, cache) {
2770
+ const cliResult = await tryCliAdapter(config, logger11, cache);
2768
2771
  if (cliResult !== null) return cliResult;
2769
- const apiResult = tryApiAdapter(config, logger8);
2772
+ const apiResult = tryApiAdapter(config, logger11);
2770
2773
  if (apiResult !== null) return apiResult;
2771
2774
  throw new Error(
2772
2775
  "No adapters available. Install a CLI (claude/gemini/codex) or set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_API_KEY."
2773
2776
  );
2774
2777
  }
2775
- async function selectApiFirst(config, logger8, cache) {
2776
- const apiResult = tryApiAdapter(config, logger8);
2778
+ async function selectApiFirst(config, logger11, cache) {
2779
+ const apiResult = tryApiAdapter(config, logger11);
2777
2780
  if (apiResult !== null) return apiResult;
2778
- const cliResult = await tryCliAdapter(config, logger8, cache);
2781
+ const cliResult = await tryCliAdapter(config, logger11, cache);
2779
2782
  if (cliResult !== null) return cliResult;
2780
2783
  throw new Error(
2781
2784
  "No adapters available. Set ANTHROPIC_API_KEY/OPENAI_API_KEY/GOOGLE_AI_API_KEY or install a CLI (claude/gemini/codex)."
2782
2785
  );
2783
2786
  }
2784
- async function selectCliOnly(config, logger8, cache) {
2785
- const cliResult = await tryCliAdapter(config, logger8, cache);
2787
+ async function selectCliOnly(config, logger11, cache) {
2788
+ const cliResult = await tryCliAdapter(config, logger11, cache);
2786
2789
  if (cliResult !== null) return cliResult;
2787
2790
  throw new Error(
2788
2791
  "No CLI adapters available. Install and authenticate claude, gemini, or codex CLI."
2789
2792
  );
2790
2793
  }
2791
- function selectApiOnly(config, logger8) {
2792
- const apiResult = tryApiAdapter(config, logger8);
2794
+ function selectApiOnly(config, logger11) {
2795
+ const apiResult = tryApiAdapter(config, logger11);
2793
2796
  if (apiResult !== null) return apiResult;
2794
2797
  throw new Error(
2795
2798
  "No API key available. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_API_KEY."
2796
2799
  );
2797
2800
  }
2798
2801
  async function createAutoAdapter(config = {}) {
2799
- const logger8 = config.logger ?? defaultLogger;
2802
+ const logger11 = config.logger ?? defaultLogger;
2800
2803
  const priority = config.priority ?? "cli-first";
2801
- const cache = resolveCache(config, logger8);
2802
- logger8.info("Auto-selecting adapter", { priority, cacheEnabled: cache !== void 0 });
2804
+ const cache = resolveCache(config, logger11);
2805
+ logger11.info("Auto-selecting adapter", { priority, cacheEnabled: cache !== void 0 });
2803
2806
  switch (priority) {
2804
2807
  case "cli-first":
2805
- return selectCliFirst(config, logger8, cache);
2808
+ return selectCliFirst(config, logger11, cache);
2806
2809
  case "api-first":
2807
- return selectApiFirst(config, logger8, cache);
2810
+ return selectApiFirst(config, logger11, cache);
2808
2811
  case "cli-only":
2809
- return selectCliOnly(config, logger8, cache);
2812
+ return selectCliOnly(config, logger11, cache);
2810
2813
  case "api-only":
2811
- return selectApiOnly(config, logger8);
2814
+ return selectApiOnly(config, logger11);
2812
2815
  default: {
2813
2816
  const exhaustive = priority;
2814
2817
  throw new Error(`Unknown priority: ${String(exhaustive)}`);
@@ -4404,21 +4407,21 @@ async function executeSingleVoteAttempt(role, proposal, adapter, timeoutMs) {
4404
4407
  }
4405
4408
  }
4406
4409
  async function executeWithRetries(opts) {
4407
- const { role, proposal, adapter, logger: logger8, timeoutMs, maxRetries } = opts;
4410
+ const { role, proposal, adapter, logger: logger11, timeoutMs, maxRetries } = opts;
4408
4411
  let lastError = "";
4409
4412
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
4410
4413
  if (attempt > 0) {
4411
4414
  const isRateLimit = isRateLimitError(lastError);
4412
4415
  const baseDelay = isRateLimit ? RATE_LIMIT_RETRY_DELAY_MS : INITIAL_RETRY_DELAY_MS;
4413
4416
  const delayMs = baseDelay * Math.pow(2, attempt - 1);
4414
- logger8.debug("Retrying vote execution", { role, attempt, delayMs, isRateLimit });
4417
+ logger11.debug("Retrying vote execution", { role, attempt, delayMs, isRateLimit });
4415
4418
  await delay(delayMs);
4416
4419
  }
4417
4420
  const attemptStart = Date.now();
4418
4421
  const result = await executeSingleVoteAttempt(role, proposal, adapter, timeoutMs);
4419
4422
  const attemptMs = Date.now() - attemptStart;
4420
4423
  if (result.ok) {
4421
- logger8.info("Vote attempt timing", {
4424
+ logger11.info("Vote attempt timing", {
4422
4425
  role,
4423
4426
  attempt: attempt + 1,
4424
4427
  attemptMs,
@@ -4428,14 +4431,14 @@ async function executeWithRetries(opts) {
4428
4431
  }
4429
4432
  lastError = result.error;
4430
4433
  const rateLimited = isRateLimitError(lastError);
4431
- logger8.info("Vote attempt timing", {
4434
+ logger11.info("Vote attempt timing", {
4432
4435
  role,
4433
4436
  attempt: attempt + 1,
4434
4437
  attemptMs,
4435
4438
  succeeded: false,
4436
4439
  rateLimited
4437
4440
  });
4438
- logger8.warn("Vote attempt failed", {
4441
+ logger11.warn("Vote attempt failed", {
4439
4442
  role,
4440
4443
  attempt: attempt + 1,
4441
4444
  maxRetries: maxRetries + 1,
@@ -4465,7 +4468,7 @@ async function launchVotesWithOverallDeadline(input) {
4465
4468
  proposal,
4466
4469
  roleAdapters,
4467
4470
  fallbackAdapter,
4468
- logger: logger8,
4471
+ logger: logger11,
4469
4472
  voteOptions,
4470
4473
  interDelay,
4471
4474
  overallDeadlineMs,
@@ -4477,12 +4480,12 @@ async function launchVotesWithOverallDeadline(input) {
4477
4480
  const adapter = roleAdapters.get(role) ?? fallbackAdapter;
4478
4481
  const elapsed = Date.now() - startedAt;
4479
4482
  const remaining = Math.max(1, overallDeadlineMs - elapsed);
4480
- return raceWithDeadline(voteFn(role, proposal, adapter, logger8, voteOptions), role, remaining);
4483
+ return raceWithDeadline(voteFn(role, proposal, adapter, logger11, voteOptions), role, remaining);
4481
4484
  });
4482
4485
  const results = await Promise.all(wrapped);
4483
4486
  const expired = results.filter((r) => r.source === "error" && r.error === DEADLINE_MESSAGE);
4484
4487
  if (expired.length > 0) {
4485
- logger8.warn("Consensus overall deadline reached; returning partial results", {
4488
+ logger11.warn("Consensus overall deadline reached; returning partial results", {
4486
4489
  totalRoles: roles.length,
4487
4490
  expiredRoles: expired.map((r) => r.role),
4488
4491
  overallDeadlineMs
@@ -4499,32 +4502,32 @@ function computeOverallConsensusDeadlineMs(timeoutMs, maxRetries, roleCount, int
4499
4502
  }
4500
4503
  var DEFAULT_INTER_AGENT_DELAY_MS = 2e3;
4501
4504
  var defaultLogger2 = createLogger({ component: "voter-agents" });
4502
- async function executeAgentVote(role, proposal, adapter, logger8, options) {
4505
+ async function executeAgentVote(role, proposal, adapter, logger11, options) {
4503
4506
  const start = getTimeProvider().now();
4504
4507
  const timeoutMs = options?.timeoutMs ?? resolveVoteTimeout();
4505
4508
  const maxRetries = options?.maxRetries ?? VOTE_TIMEOUTS.maxRetries;
4506
4509
  const allowSimulation = options?.allowSimulation ?? false;
4507
- logger8.info("Executing vote", { role, model: adapter.modelId, provider: adapter.providerId });
4510
+ logger11.info("Executing vote", { role, model: adapter.modelId, provider: adapter.providerId });
4508
4511
  const result = await executeWithRetries({
4509
4512
  role,
4510
4513
  proposal,
4511
4514
  adapter,
4512
- logger: logger8,
4515
+ logger: logger11,
4513
4516
  timeoutMs,
4514
4517
  maxRetries
4515
4518
  });
4516
4519
  const processingTimeMs = getTimeProvider().now() - start;
4517
4520
  if (result.ok) {
4518
- logger8.info("Vote completed", { role, model: adapter.modelId, decision: result.vote.decision });
4521
+ logger11.info("Vote completed", { role, model: adapter.modelId, decision: result.vote.decision });
4519
4522
  return { role, vote: result.vote, processingTimeMs, source: "llm", cli: adapter.providerId };
4520
4523
  }
4521
- logger8.error("Vote execution failed after all retries", void 0, {
4524
+ logger11.error("Vote execution failed after all retries", void 0, {
4522
4525
  role,
4523
4526
  model: adapter.modelId,
4524
4527
  errorMessage: result.error
4525
4528
  });
4526
4529
  if (allowSimulation) {
4527
- logger8.warn("Falling back to simulation (allowSimulation=true)", { role });
4530
+ logger11.warn("Falling back to simulation (allowSimulation=true)", { role });
4528
4531
  return createSimulationVoteResult(role, proposal, processingTimeMs, result.error);
4529
4532
  }
4530
4533
  return createErrorVoteResult(role, result.error, processingTimeMs);
@@ -4535,22 +4538,22 @@ var NoAdapterError = class extends Error {
4535
4538
  this.name = "NoAdapterError";
4536
4539
  }
4537
4540
  };
4538
- function resolveAdapter(options, logger8) {
4541
+ function resolveAdapter(options, logger11) {
4539
4542
  try {
4540
4543
  if (options.adapter !== void 0) return { adapter: options.adapter };
4541
- const registry = getGlobalRegistry({ logger: logger8 });
4544
+ const registry = getGlobalRegistry({ logger: logger11 });
4542
4545
  return { adapter: registry.getDefault() };
4543
4546
  } catch (error) {
4544
4547
  return { error: getErrorMessage(error) };
4545
4548
  }
4546
4549
  }
4547
- function warnIfCodexConcurrencyExceeded(roleAdapters, logger8) {
4550
+ function warnIfCodexConcurrencyExceeded(roleAdapters, logger11) {
4548
4551
  const codexBound = [...roleAdapters.values()].filter(
4549
4552
  (a) => a.name === "codex"
4550
4553
  ).length;
4551
4554
  const warning = checkCodexConcurrency(codexBound);
4552
4555
  if (warning !== null) {
4553
- logger8.warn("Codex concurrency limit may be exceeded", { detail: warning });
4556
+ logger11.warn("Codex concurrency limit may be exceeded", { detail: warning });
4554
4557
  }
4555
4558
  }
4556
4559
  function assignUniformAdapter(roles, adapter) {
@@ -4558,29 +4561,29 @@ function assignUniformAdapter(roles, adapter) {
4558
4561
  for (const role of roles) adapters.set(role, adapter);
4559
4562
  return adapters;
4560
4563
  }
4561
- function createCliAdapterMap(clis, logger8) {
4562
- const registry = getGlobalRegistry({ logger: logger8 });
4564
+ function createCliAdapterMap(clis, logger11) {
4565
+ const registry = getGlobalRegistry({ logger: logger11 });
4563
4566
  const result = /* @__PURE__ */ new Map();
4564
4567
  for (const cli of clis) {
4565
4568
  result.set(cli, registry.getAdapterForCli(cli));
4566
4569
  }
4567
4570
  return result;
4568
4571
  }
4569
- async function resolveDiverseAdapters(roles, logger8, fallbackAdapter) {
4572
+ async function resolveDiverseAdapters(roles, logger11, fallbackAdapter) {
4570
4573
  let availableClis;
4571
4574
  try {
4572
4575
  availableClis = await getAvailableClis();
4573
4576
  } catch (e) {
4574
- logger8.warn("Failed to resolve available CLIs; falling back to single adapter", {
4577
+ logger11.warn("Failed to resolve available CLIs; falling back to single adapter", {
4575
4578
  error: String(e)
4576
4579
  });
4577
4580
  availableClis = [];
4578
4581
  }
4579
4582
  if (availableClis.length <= 1) {
4580
- logger8.info("Using single adapter for all roles", { cliCount: availableClis.length });
4583
+ logger11.info("Using single adapter for all roles", { cliCount: availableClis.length });
4581
4584
  return assignUniformAdapter(roles, fallbackAdapter);
4582
4585
  }
4583
- const cliAdapters = createCliAdapterMap(availableClis, logger8);
4586
+ const cliAdapters = createCliAdapterMap(availableClis, logger11);
4584
4587
  if (cliAdapters.size <= 1) return assignUniformAdapter(roles, fallbackAdapter);
4585
4588
  const cliList = [...cliAdapters.entries()];
4586
4589
  const adapters = /* @__PURE__ */ new Map();
@@ -4592,7 +4595,7 @@ async function resolveDiverseAdapters(roles, logger8, fallbackAdapter) {
4592
4595
  adapters.set(role, entry[1]);
4593
4596
  assignments[role] = entry[0];
4594
4597
  }
4595
- logger8.info("Diverse adapters assigned", {
4598
+ logger11.info("Diverse adapters assigned", {
4596
4599
  cliCount: cliAdapters.size,
4597
4600
  clis: [...cliAdapters.keys()],
4598
4601
  roleAssignments: assignments
@@ -4600,7 +4603,7 @@ async function resolveDiverseAdapters(roles, logger8, fallbackAdapter) {
4600
4603
  return adapters;
4601
4604
  }
4602
4605
  async function launchStaggeredVotes(input) {
4603
- const { roles, proposal, roleAdapters, fallbackAdapter, logger: logger8, voteOptions, interDelay } = input;
4606
+ const { roles, proposal, roleAdapters, fallbackAdapter, logger: logger11, voteOptions, interDelay } = input;
4604
4607
  const computedDeadlineMs = computeOverallConsensusDeadlineMs(
4605
4608
  voteOptions.timeoutMs,
4606
4609
  voteOptions.maxRetries,
@@ -4609,7 +4612,7 @@ async function launchStaggeredVotes(input) {
4609
4612
  );
4610
4613
  const overallDeadlineMs = getMcpSafeDeadlineMs(computedDeadlineMs, "consensus_vote");
4611
4614
  if (overallDeadlineMs < computedDeadlineMs) {
4612
- logger8.debug("Consensus deadline clamped to MCP wrapper timeout", {
4615
+ logger11.debug("Consensus deadline clamped to MCP wrapper timeout", {
4613
4616
  computedDeadlineMs,
4614
4617
  overallDeadlineMs
4615
4618
  });
@@ -4619,7 +4622,7 @@ async function launchStaggeredVotes(input) {
4619
4622
  proposal,
4620
4623
  roleAdapters,
4621
4624
  fallbackAdapter,
4622
- logger: logger8,
4625
+ logger: logger11,
4623
4626
  voteOptions,
4624
4627
  interDelay,
4625
4628
  overallDeadlineMs,
@@ -4627,27 +4630,27 @@ async function launchStaggeredVotes(input) {
4627
4630
  });
4628
4631
  }
4629
4632
  async function collectRealVotes(options) {
4630
- const logger8 = options.logger ?? defaultLogger2;
4633
+ const logger11 = options.logger ?? defaultLogger2;
4631
4634
  const { roles, proposal, simulate, allowSimulation } = options;
4632
4635
  const timeoutMs = options.timeoutMs ?? resolveVoteTimeout();
4633
4636
  const maxRetries = options.maxRetries ?? VOTE_TIMEOUTS.maxRetries;
4634
4637
  if (simulate === true) {
4635
- logger8.info("Using simulation mode (explicitly requested)");
4638
+ logger11.info("Using simulation mode (explicitly requested)");
4636
4639
  return createSimulatedVotes(roles, proposal);
4637
4640
  }
4638
- const adapterResult = resolveAdapter(options, logger8);
4641
+ const adapterResult = resolveAdapter(options, logger11);
4639
4642
  if ("error" in adapterResult) {
4640
- logger8.error("No adapter available for voting", void 0, { error: adapterResult.error });
4643
+ logger11.error("No adapter available for voting", void 0, { error: adapterResult.error });
4641
4644
  if (allowSimulation === true) {
4642
- logger8.warn("Falling back to simulation (allowSimulation=true)");
4645
+ logger11.warn("Falling back to simulation (allowSimulation=true)");
4643
4646
  return createSimulatedVotes(roles, proposal, "No adapter available");
4644
4647
  }
4645
4648
  throw new NoAdapterError(
4646
4649
  `No adapter available for voting: ${adapterResult.error}. Install a CLI (claude/gemini/codex) or set ANTHROPIC_API_KEY.`
4647
4650
  );
4648
4651
  }
4649
- const roleAdapters = options.adapter !== void 0 ? assignUniformAdapter(roles, adapterResult.adapter) : await resolveDiverseAdapters(roles, logger8, adapterResult.adapter);
4650
- warnIfCodexConcurrencyExceeded(roleAdapters, logger8);
4652
+ const roleAdapters = options.adapter !== void 0 ? assignUniformAdapter(roles, adapterResult.adapter) : await resolveDiverseAdapters(roles, logger11, adapterResult.adapter);
4653
+ warnIfCodexConcurrencyExceeded(roleAdapters, logger11);
4651
4654
  const voteOptions = { timeoutMs, maxRetries, allowSimulation: allowSimulation ?? false };
4652
4655
  const interDelay = options.interAgentDelayMs ?? DEFAULT_INTER_AGENT_DELAY_MS;
4653
4656
  return launchStaggeredVotes({
@@ -4655,7 +4658,7 @@ async function collectRealVotes(options) {
4655
4658
  proposal,
4656
4659
  roleAdapters,
4657
4660
  fallbackAdapter: adapterResult.adapter,
4658
- logger: logger8,
4661
+ logger: logger11,
4659
4662
  voteOptions,
4660
4663
  interDelay
4661
4664
  });
@@ -5644,11 +5647,11 @@ var ConsensusEngine = class {
5644
5647
  logger;
5645
5648
  metrics;
5646
5649
  voterExpansionCallback;
5647
- constructor(config, logger8) {
5650
+ constructor(config, logger11) {
5648
5651
  this.config = { ...DEFAULT_CONSENSUS_CONFIG, ...config };
5649
5652
  this.cacheConfig = { ...DEFAULT_PROPOSAL_CACHE_CONFIG, ...config?.proposalCache };
5650
5653
  this.quorumConfig = { ...DEFAULT_INCREMENTAL_QUORUM_CONFIG, ...config?.incrementalQuorum };
5651
- this.logger = logger8 ?? createLogger({ component: "ConsensusEngine" });
5654
+ this.logger = logger11 ?? createLogger({ component: "ConsensusEngine" });
5652
5655
  this.strategyFactory = new VotingStrategyFactory();
5653
5656
  this.metrics = this.createInitialMetrics();
5654
5657
  }
@@ -6090,8 +6093,8 @@ var ConsensusEngine = class {
6090
6093
  this.logger.debug("Proposal cache cleared");
6091
6094
  }
6092
6095
  };
6093
- function createConsensusEngine(config, logger8) {
6094
- return new ConsensusEngine(config, logger8);
6096
+ function createConsensusEngine(config, logger11) {
6097
+ return new ConsensusEngine(config, logger11);
6095
6098
  }
6096
6099
 
6097
6100
  // src/consensus/quorum-validator.ts
@@ -6099,8 +6102,8 @@ var DEFAULT_MIN_TRUST = 0.3;
6099
6102
  var DEFAULT_MIN_WEIGHT = 0.1;
6100
6103
  var QuorumValidator = class {
6101
6104
  logger;
6102
- constructor(logger8) {
6103
- this.logger = logger8 ?? createLogger({ component: "QuorumValidator" });
6105
+ constructor(logger11) {
6106
+ this.logger = logger11 ?? createLogger({ component: "QuorumValidator" });
6104
6107
  }
6105
6108
  validateQuorum(input) {
6106
6109
  const { votes, config } = input;
@@ -6327,8 +6330,8 @@ var QuorumValidator = class {
6327
6330
  };
6328
6331
  }
6329
6332
  };
6330
- function createQuorumValidator(logger8) {
6331
- return new QuorumValidator(logger8);
6333
+ function createQuorumValidator(logger11) {
6334
+ return new QuorumValidator(logger11);
6332
6335
  }
6333
6336
 
6334
6337
  // src/consensus/voting-protocol-helpers.ts
@@ -7908,6 +7911,35 @@ var ConsensusVoteInputSchema = z9.object({
7908
7911
  quickMode: z9.boolean().optional().default(false).describe("Use 3 agents instead of 5 for faster execution"),
7909
7912
  simulateVotes: z9.boolean().optional().default(false).describe(
7910
7913
  "TESTS ONLY \u2014 when true, voters return random decisions. Output must not be used for real decisions. (#2319)"
7914
+ ),
7915
+ /**
7916
+ * Async-mode dispatch (#3045, Stage 4 of epic #2631). Default `sync` —
7917
+ * backward-compat invariant. `async` returns `{ status: 'pending', jobId }`
7918
+ * immediately; caller polls `get_job_result(jobId)`. Per-tool cap via
7919
+ * `NEXUS_JOB_MAX_CONCURRENT_CONSENSUS_VOTE` (default 2 — voting is
7920
+ * 7-fan-out so concurrent jobs multiply adapter load fast).
7921
+ *
7922
+ * Cancellation semantics (#3041 vote deferred this to Stage 4): when
7923
+ * a polling client calls `cancel_job` mid-vote, the dispatcher aborts
7924
+ * in-flight voters via the AbortSignal plumbing from #3038. The
7925
+ * resulting job result is `{ status: 'cancelled', partialVotes: [...] }`
7926
+ * with whatever voters completed before the abort signal — preserves
7927
+ * audit visibility into who voted before the cancel landed.
7928
+ *
7929
+ * Kept optional (no `.default()`) so the inferred type doesn't force
7930
+ * `mode: 'sync'` on every existing call site / test fixture.
7931
+ */
7932
+ mode: z9.enum(["sync", "async"]).optional().describe(
7933
+ 'Dispatch mode (default: sync). Use "async" for higher-order strategies with 7 voters.'
7934
+ ),
7935
+ /**
7936
+ * Idempotency key for async-mode replay-safety (#3042 Stage 1c / epic
7937
+ * #2631). When set: identical (key, inputs) returns the existing job;
7938
+ * same key with different inputs fails closed with
7939
+ * `idempotency_key_collision`. Sync mode ignores this.
7940
+ */
7941
+ idempotencyKey: z9.string().min(1).max(256).optional().describe(
7942
+ "Replay-safe key for async-mode dispatch (#3042 Stage 1c). Same (key, inputs) returns existing jobId."
7911
7943
  )
7912
7944
  });
7913
7945
  function toAgentVoteSummary(result) {
@@ -8014,10 +8046,10 @@ import { appendFileSync as appendFileSync3, readFileSync as readFileSync2, write
8014
8046
  var PersistentOutcomeStore = class extends OutcomeStore {
8015
8047
  filePath;
8016
8048
  logger;
8017
- constructor(config, logger8) {
8049
+ constructor(config, logger11) {
8018
8050
  super(config);
8019
8051
  this.filePath = config?.filePath ?? getOutcomesFile();
8020
- this.logger = logger8 ?? createLogger({ component: "PersistentOutcomeStore" });
8052
+ this.logger = logger11 ?? createLogger({ component: "PersistentOutcomeStore" });
8021
8053
  const dataDir = config?.dataDir;
8022
8054
  ensureLearningDir(dataDir);
8023
8055
  this.hydrate();
@@ -8211,11 +8243,11 @@ var WARNED = /* @__PURE__ */ new Set();
8211
8243
  function isTestRunner() {
8212
8244
  return process.env.VITEST === "true" || process.env.NODE_ENV === "test";
8213
8245
  }
8214
- function warnIfSimulatedOutsideTests(toolName, logger8) {
8246
+ function warnIfSimulatedOutsideTests(toolName, logger11) {
8215
8247
  if (isTestRunner()) return;
8216
8248
  if (WARNED.has(toolName)) return;
8217
8249
  WARNED.add(toolName);
8218
- logger8.warn(
8250
+ logger11.warn(
8219
8251
  `[${toolName}] simulateVotes=true: output is RANDOM and reserved for tests/demos. Do not treat the result as a real decision.`
8220
8252
  );
8221
8253
  }
@@ -8466,6 +8498,13 @@ var TOOL_ANNOTATIONS = {
8466
8498
  idempotentHint: true,
8467
8499
  openWorldHint: false
8468
8500
  },
8501
+ /** Lists async-mode job summaries from the sidecar dir (#3046 / #2631 Stage 5). */
8502
+ list_jobs: {
8503
+ readOnlyHint: true,
8504
+ destructiveHint: false,
8505
+ idempotentHint: true,
8506
+ openWorldHint: false
8507
+ },
8469
8508
  /** Verifies hash chain of audit log files. */
8470
8509
  verify_audit_chain: {
8471
8510
  readOnlyHint: true,
@@ -8539,7 +8578,321 @@ function getToolAnnotations(name) {
8539
8578
  return a;
8540
8579
  }
8541
8580
 
8581
+ // src/mcp/jobs/job-result-store.ts
8582
+ import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync, writeFileSync as writeFileSync3 } from "fs";
8583
+ import { z as z10 } from "zod";
8584
+ var logger8 = createLogger({ component: "job-result-store" });
8585
+ var JobStatusSchema = z10.enum(["pending", "complete", "failed", "cancelled"]);
8586
+ var JobResultSchema = z10.object({
8587
+ /** Format version. Currently `1` — bump if the shape changes. */
8588
+ v: z10.literal(1),
8589
+ jobId: z10.string().min(1),
8590
+ /** Tool that was invoked (e.g. `orchestrate`). */
8591
+ toolName: z10.string().min(1),
8592
+ status: JobStatusSchema,
8593
+ createdAt: z10.iso.datetime(),
8594
+ /** Set when the job leaves `pending` — either via `complete` or `failed` or `cancelled`. */
8595
+ completedAt: z10.iso.datetime().optional(),
8596
+ /**
8597
+ * Structured payload the synchronous mode would have returned. Present
8598
+ * only when `status === 'complete'`. Shape is tool-specific — readers
8599
+ * cast to the tool's known output type after status check.
8600
+ */
8601
+ result: z10.unknown().optional(),
8602
+ /**
8603
+ * Failure message when `status === 'failed'`. Cannot be paired with
8604
+ * `result` — the discriminator is `status`.
8605
+ */
8606
+ error: z10.string().optional()
8607
+ });
8608
+ function jobResultPath(jobId) {
8609
+ return nexusDataPathEnsure("jobs", `result-${jobId}.json`);
8610
+ }
8611
+ function writeJobPending(jobId, toolName) {
8612
+ const path = jobResultPath(jobId);
8613
+ if (existsSync4(path)) {
8614
+ logger8.debug("Job result file already exists \u2014 leaving in place", { jobId });
8615
+ return;
8616
+ }
8617
+ const record = {
8618
+ v: 1,
8619
+ jobId,
8620
+ toolName,
8621
+ status: "pending",
8622
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
8623
+ };
8624
+ writeFileSync3(path, JSON.stringify(record, null, 2));
8625
+ logger8.debug("Wrote pending job record", { jobId, toolName });
8626
+ }
8627
+ function writeJobComplete(jobId, toolName, result) {
8628
+ const record = {
8629
+ v: 1,
8630
+ jobId,
8631
+ toolName,
8632
+ status: "complete",
8633
+ createdAt: readJobResult(jobId)?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
8634
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
8635
+ result
8636
+ };
8637
+ writeFileSync3(jobResultPath(jobId), JSON.stringify(record, null, 2));
8638
+ logger8.debug("Wrote complete job record", { jobId, toolName });
8639
+ }
8640
+ function writeJobFailed(jobId, toolName, error) {
8641
+ const record = {
8642
+ v: 1,
8643
+ jobId,
8644
+ toolName,
8645
+ status: "failed",
8646
+ createdAt: readJobResult(jobId)?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
8647
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
8648
+ error
8649
+ };
8650
+ writeFileSync3(jobResultPath(jobId), JSON.stringify(record, null, 2));
8651
+ logger8.debug("Wrote failed job record", { jobId, toolName, error });
8652
+ }
8653
+ function readJobResult(jobId) {
8654
+ const path = nexusDataPath("jobs", `result-${jobId}.json`);
8655
+ if (!existsSync4(path)) return null;
8656
+ try {
8657
+ const raw = JSON.parse(readFileSync3(path, "utf-8"));
8658
+ const parsed = JobResultSchema.safeParse(raw);
8659
+ if (!parsed.success) {
8660
+ logger8.warn("Job result file failed schema check", { jobId, path });
8661
+ return null;
8662
+ }
8663
+ return parsed.data;
8664
+ } catch (err2) {
8665
+ logger8.warn("Job result file unreadable", {
8666
+ jobId,
8667
+ path,
8668
+ error: err2 instanceof Error ? err2.message : String(err2)
8669
+ });
8670
+ return null;
8671
+ }
8672
+ }
8673
+ function listJobs() {
8674
+ const dir = nexusDataPath("jobs");
8675
+ if (!existsSync4(dir)) return [];
8676
+ let entries;
8677
+ try {
8678
+ entries = readdirSync(dir);
8679
+ } catch (err2) {
8680
+ logger8.warn("jobs directory unreadable", {
8681
+ dir,
8682
+ error: err2 instanceof Error ? err2.message : String(err2)
8683
+ });
8684
+ return [];
8685
+ }
8686
+ const summaries = [];
8687
+ for (const entry of entries) {
8688
+ const match = /^result-(.+)\.json$/.exec(entry);
8689
+ if (match === null) continue;
8690
+ const jobId = match[1];
8691
+ if (jobId === void 0) continue;
8692
+ const record = readJobResult(jobId);
8693
+ if (record === null) continue;
8694
+ const summary = {
8695
+ jobId: record.jobId,
8696
+ toolName: record.toolName,
8697
+ status: record.status,
8698
+ createdAt: record.createdAt,
8699
+ hasError: record.error !== void 0,
8700
+ ...record.completedAt !== void 0 ? { completedAt: record.completedAt } : {}
8701
+ };
8702
+ summaries.push(summary);
8703
+ }
8704
+ return summaries.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
8705
+ }
8706
+
8707
+ // src/mcp/jobs/job-idempotency.ts
8708
+ import { createHash, randomUUID as randomUUID3 } from "crypto";
8709
+ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
8710
+ import { z as z11 } from "zod";
8711
+ var logger9 = createLogger({ component: "job-idempotency" });
8712
+ var IdempotencyIndexEntrySchema = z11.object({
8713
+ v: z11.literal(1),
8714
+ /** MCP tool name (e.g. `orchestrate`, `run_workflow`, `consensus_vote`). */
8715
+ tool: z11.string().min(1),
8716
+ /** Caller-supplied idempotency key. */
8717
+ key: z11.string().min(1),
8718
+ /** sha256 of the canonical input JSON. */
8719
+ inputsHash: z11.string().length(64),
8720
+ /** Existing jobId for this (tool, key, inputs) tuple. */
8721
+ jobId: z11.string().min(1),
8722
+ /** ISO timestamp of first dispatch. */
8723
+ createdAt: z11.iso.datetime()
8724
+ });
8725
+ function sha256Hex(input) {
8726
+ return createHash("sha256").update(input).digest("hex");
8727
+ }
8728
+ function canonicalJsonStringify(value) {
8729
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
8730
+ if (Array.isArray(value)) return `[${value.map(canonicalJsonStringify).join(",")}]`;
8731
+ const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
8732
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJsonStringify(v)}`).join(",")}}`;
8733
+ }
8734
+ function computeInputsHash(inputs) {
8735
+ return sha256Hex(canonicalJsonStringify(inputs));
8736
+ }
8737
+ function indexFilePath(tool, key) {
8738
+ const filename = `key-${sha256Hex(`${tool}:${key}`)}.json`;
8739
+ return nexusDataPathEnsure("jobs", filename);
8740
+ }
8741
+ function indexFilePathReadOnly(tool, key) {
8742
+ const filename = `key-${sha256Hex(`${tool}:${key}`)}.json`;
8743
+ return nexusDataPath("jobs", filename);
8744
+ }
8745
+ function resolveIdempotency(tool, idempotencyKey, inputs, randomFallback = randomUUID3) {
8746
+ if (idempotencyKey === void 0 || idempotencyKey === "") {
8747
+ return { kind: "fresh", jobId: randomFallback() };
8748
+ }
8749
+ const incomingInputsHash = computeInputsHash(inputs);
8750
+ const path = indexFilePathReadOnly(tool, idempotencyKey);
8751
+ if (existsSync5(path)) {
8752
+ const entry = readIndexEntry(path);
8753
+ if (entry !== null) {
8754
+ if (entry.inputsHash === incomingInputsHash) {
8755
+ return { kind: "replay", jobId: entry.jobId, entry };
8756
+ }
8757
+ return {
8758
+ kind: "collision",
8759
+ existingInputsHash: entry.inputsHash,
8760
+ incomingInputsHash,
8761
+ existingJobId: entry.jobId
8762
+ };
8763
+ }
8764
+ logger9.warn("Idempotency index file unreadable; treating as fresh dispatch", { tool, path });
8765
+ }
8766
+ const jobId = `job-${tool}-${sha256Hex(`${tool}:${idempotencyKey}:${incomingInputsHash}`).slice(0, 16)}`;
8767
+ return { kind: "fresh", jobId };
8768
+ }
8769
+ function registerIdempotentJob(params) {
8770
+ const path = indexFilePath(params.tool, params.idempotencyKey);
8771
+ if (existsSync5(path)) {
8772
+ logger9.debug("Idempotency index entry already present; skipping write", {
8773
+ tool: params.tool,
8774
+ jobId: params.jobId
8775
+ });
8776
+ return;
8777
+ }
8778
+ const entry = {
8779
+ v: 1,
8780
+ tool: params.tool,
8781
+ key: params.idempotencyKey,
8782
+ inputsHash: computeInputsHash(params.inputs),
8783
+ jobId: params.jobId,
8784
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
8785
+ };
8786
+ writeFileSync4(path, JSON.stringify(entry, null, 2));
8787
+ logger9.debug("Wrote idempotency index entry", { tool: params.tool, jobId: params.jobId });
8788
+ }
8789
+ function shortCircuitOrFreshJobId(params) {
8790
+ const r = resolveIdempotency(
8791
+ params.tool,
8792
+ params.idempotencyKey,
8793
+ params.inputs,
8794
+ params.freshJobId
8795
+ );
8796
+ if (r.kind === "collision") {
8797
+ return { kind: "shortCircuit", value: params.collisionEnvelope(r.existingJobId) };
8798
+ }
8799
+ if (r.kind === "replay") {
8800
+ return { kind: "shortCircuit", value: params.replayEnvelope(r.jobId) };
8801
+ }
8802
+ return { kind: "continue", jobId: r.jobId };
8803
+ }
8804
+ function readIndexEntry(path) {
8805
+ try {
8806
+ const raw = JSON.parse(readFileSync4(path, "utf-8"));
8807
+ const parsed = IdempotencyIndexEntrySchema.safeParse(raw);
8808
+ if (!parsed.success) {
8809
+ logger9.warn("Idempotency index file failed schema check", { path });
8810
+ return null;
8811
+ }
8812
+ return parsed.data;
8813
+ } catch (err2) {
8814
+ logger9.warn("Idempotency index file read failed", {
8815
+ path,
8816
+ error: err2 instanceof Error ? err2.message : String(err2)
8817
+ });
8818
+ return null;
8819
+ }
8820
+ }
8821
+
8822
+ // src/mcp/jobs/job-concurrency.ts
8823
+ var logger10 = createLogger({ component: "job-concurrency" });
8824
+ var DEFAULT_JOB_CAPS = {
8825
+ orchestrate: 3,
8826
+ run_workflow: 3,
8827
+ consensus_vote: 2,
8828
+ execute_expert: 4
8829
+ };
8830
+ var DEFAULT_GLOBAL_JOB_CAP = 10;
8831
+ var inFlight = /* @__PURE__ */ new Map();
8832
+ function getJobCap(toolName) {
8833
+ const envKey = `NEXUS_JOB_MAX_CONCURRENT_${toolName.toUpperCase()}`;
8834
+ const envValue = process.env[envKey];
8835
+ if (envValue !== void 0 && envValue !== "") {
8836
+ const parsed = Number(envValue);
8837
+ if (Number.isInteger(parsed) && parsed >= 0) {
8838
+ return parsed;
8839
+ }
8840
+ logger10.warn("Invalid env override for job cap \u2014 ignoring", {
8841
+ tool: toolName,
8842
+ envKey,
8843
+ envValue
8844
+ });
8845
+ }
8846
+ return DEFAULT_JOB_CAPS[toolName] ?? DEFAULT_GLOBAL_JOB_CAP;
8847
+ }
8848
+ function getGlobalJobCap() {
8849
+ const envValue = process.env["NEXUS_JOB_MAX_CONCURRENT_TOTAL"];
8850
+ if (envValue !== void 0 && envValue !== "") {
8851
+ const parsed = Number(envValue);
8852
+ if (Number.isInteger(parsed) && parsed >= 0) {
8853
+ return parsed;
8854
+ }
8855
+ logger10.warn("Invalid env override for global job cap \u2014 ignoring", {
8856
+ envKey: "NEXUS_JOB_MAX_CONCURRENT_TOTAL",
8857
+ envValue
8858
+ });
8859
+ }
8860
+ return DEFAULT_GLOBAL_JOB_CAP;
8861
+ }
8862
+ function getTotalInFlight() {
8863
+ let total = 0;
8864
+ for (const count of inFlight.values()) total += count;
8865
+ return total;
8866
+ }
8867
+ function tryAcquire(toolName) {
8868
+ const cap = getJobCap(toolName);
8869
+ if (cap === 0) return false;
8870
+ const current = inFlight.get(toolName) ?? 0;
8871
+ if (current >= cap) return false;
8872
+ const globalCap = getGlobalJobCap();
8873
+ if (globalCap === 0) return false;
8874
+ if (getTotalInFlight() >= globalCap) return false;
8875
+ inFlight.set(toolName, current + 1);
8876
+ return true;
8877
+ }
8878
+ function release(toolName) {
8879
+ const current = inFlight.get(toolName) ?? 0;
8880
+ if (current === 0) {
8881
+ logger10.warn("release() called with no in-flight count \u2014 caller bug", { tool: toolName });
8882
+ return;
8883
+ }
8884
+ inFlight.set(toolName, current - 1);
8885
+ }
8886
+ function suggestRetryAfterMs(toolName) {
8887
+ const cap = getJobCap(toolName);
8888
+ if (cap === 0) return 0;
8889
+ const current = inFlight.get(toolName) ?? 0;
8890
+ const base = 3e4 * (current / Math.max(1, cap));
8891
+ return Math.min(6e4, Math.max(5e3, base));
8892
+ }
8893
+
8542
8894
  // src/mcp/tools/consensus-vote.ts
8895
+ import { randomUUID as randomUUID4 } from "crypto";
8543
8896
  var persistentCorrelationTracker;
8544
8897
  function getOrCreateCorrelationTracker() {
8545
8898
  persistentCorrelationTracker ??= createPersistentCorrelationTracker();
@@ -8648,22 +9001,22 @@ async function processVotesThroughEngine(engineVotes, proposal, algorithm) {
8648
9001
  });
8649
9002
  return resultRes.value;
8650
9003
  }
8651
- function runHigherOrderVoting(strategy, voteMap, logger8) {
9004
+ function runHigherOrderVoting(strategy, voteMap, logger11) {
8652
9005
  if (strategy !== "higher_order") return void 0;
8653
9006
  const hovStrategy = new HigherOrderVotingStrategy();
8654
9007
  const tracker = getOrCreateCorrelationTracker();
8655
9008
  const result = hovStrategy.aggregate(voteMap, tracker);
8656
- logger8.info("Higher-Order Voting complete", {
9009
+ logger11.info("Higher-Order Voting complete", {
8657
9010
  method: result.method,
8658
9011
  decision: result.decision,
8659
9012
  posteriorApproval: result.posteriorApproval.toFixed(3)
8660
9013
  });
8661
9014
  return result;
8662
9015
  }
8663
- function recordVotesToTracker(votes, voteMap, outcome, logger8) {
9016
+ function recordVotesToTracker(votes, voteMap, outcome, logger11) {
8664
9017
  const allVotesReal = votes.every((v) => v.source === "llm");
8665
9018
  if (!allVotesReal) {
8666
- logger8.warn("Skipping correlation recording due to non-LLM votes", {
9019
+ logger11.warn("Skipping correlation recording due to non-LLM votes", {
8667
9020
  count: votes.filter((v) => v.source !== "llm").length
8668
9021
  });
8669
9022
  return;
@@ -8671,16 +9024,16 @@ function recordVotesToTracker(votes, voteMap, outcome, logger8) {
8671
9024
  const tracker = getOrCreateCorrelationTracker();
8672
9025
  const id = `consensus-${String(getTimeProvider().now())}-${getRandomProvider().random().toString(36).slice(2, 9)}`;
8673
9026
  tracker.recordProposalVotes(id, voteMap, outcome);
8674
- logger8.debug("Recorded votes to tracker", { proposalId: id, outcome });
9027
+ logger11.debug("Recorded votes to tracker", { proposalId: id, outcome });
8675
9028
  try {
8676
9029
  const persisted = createPersistedProposal(id, voteMap, outcome);
8677
9030
  const saveResult = saveCorrelationData([persisted]);
8678
9031
  if (!saveResult.ok) {
8679
- logger8.warn("Failed to persist correlation data", { error: saveResult.error.message });
9032
+ logger11.warn("Failed to persist correlation data", { error: saveResult.error.message });
8680
9033
  }
8681
9034
  } catch (error) {
8682
9035
  const message = getErrorMessage(error);
8683
- logger8.warn("Error persisting correlation data", { error: message });
9036
+ logger11.warn("Error persisting correlation data", { error: message });
8684
9037
  }
8685
9038
  }
8686
9039
  async function processVotesWithCascade(engineVotes, opts) {
@@ -8705,7 +9058,7 @@ async function processVotesWithCascade(engineVotes, opts) {
8705
9058
  var CONTRARIAN_ESCALATION_THRESHOLD = 0.8;
8706
9059
  async function runContrarianCheck(proposal, log) {
8707
9060
  try {
8708
- const { executeExpert } = await import("./expert-bridge-4MHM77VW.js");
9061
+ const { executeExpert } = await import("./expert-bridge-22UVN5TB.js");
8709
9062
  const prompt = [
8710
9063
  "You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.",
8711
9064
  "Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.",
@@ -8755,23 +9108,23 @@ function buildPolicyShortCircuitResult(args) {
8755
9108
  strategy: args.strategy
8756
9109
  };
8757
9110
  }
8758
- async function maybeEscalateContrarian(input, outcome, logger8, opts) {
9111
+ async function maybeEscalateContrarian(input, outcome, logger11, opts) {
8759
9112
  if (!input.quickMode || outcome !== "approved" || input.simulateVotes) return void 0;
8760
- const escalation = await runContrarianCheck(input.proposal, logger8);
9113
+ const escalation = await runContrarianCheck(input.proposal, logger11);
8761
9114
  if (!escalation.shouldEscalate) return void 0;
8762
- logger8.warn("Contrarian escalation: re-running with full vote", {
9115
+ logger11.warn("Contrarian escalation: re-running with full vote", {
8763
9116
  reason: escalation.reason,
8764
9117
  confidence: escalation.confidence
8765
9118
  });
8766
- return executeVoting({ ...input, quickMode: false }, logger8, opts);
9119
+ return executeVoting({ ...input, quickMode: false }, logger11, opts);
8767
9120
  }
8768
- async function executeVoting(input, logger8, opts) {
9121
+ async function executeVoting(input, logger11, opts) {
8769
9122
  const strategy = resolveStrategy(input);
8770
9123
  const algorithm = strategyToAlgorithm(strategy);
8771
9124
  const roles = getVoterRoles(input.quickMode);
8772
9125
  const startTime = getTimeProvider().now();
8773
9126
  const errorPolicy = input.errorPolicy ?? getDefaultErrorPolicy(strategy);
8774
- logger8.info("Starting consensus vote", {
9127
+ logger11.info("Starting consensus vote", {
8775
9128
  strategy,
8776
9129
  algorithm,
8777
9130
  roleCount: roles.length,
@@ -8793,7 +9146,7 @@ async function executeVoting(input, logger8, opts) {
8793
9146
  errorPolicy,
8794
9147
  reason: policyDecision.reason ?? "error policy short-circuit",
8795
9148
  startTime,
8796
- logger: logger8
9149
+ logger: logger11
8797
9150
  });
8798
9151
  }
8799
9152
  const { engineResult, voteMap, higherOrderResult, outcome, cascaded } = await processVotesWithCascade(policyDecision.engineVotes, {
@@ -8801,10 +9154,10 @@ async function executeVoting(input, logger8, opts) {
8801
9154
  proposal: input.proposal,
8802
9155
  algorithm,
8803
9156
  strategy,
8804
- log: logger8
9157
+ log: logger11
8805
9158
  });
8806
- recordVotesToTracker(votes, voteMap, outcome, logger8);
8807
- const escalated = await maybeEscalateContrarian(input, outcome, logger8, opts);
9159
+ recordVotesToTracker(votes, voteMap, outcome, logger11);
9160
+ const escalated = await maybeEscalateContrarian(input, outcome, logger11, opts);
8808
9161
  if (escalated !== void 0) return escalated;
8809
9162
  return finalizeVotingResult({
8810
9163
  input,
@@ -8816,7 +9169,7 @@ async function executeVoting(input, logger8, opts) {
8816
9169
  outcome,
8817
9170
  cascaded,
8818
9171
  startTime,
8819
- logger: logger8
9172
+ logger: logger11
8820
9173
  });
8821
9174
  }
8822
9175
  function finalizeVotingResult(args) {
@@ -8840,15 +9193,15 @@ function finalizeVotingResult(args) {
8840
9193
  return result;
8841
9194
  }
8842
9195
  async function handleConsensusVote(deps, args) {
8843
- const logger8 = deps.logger ?? createLogger({ tool: "consensus_vote" });
8844
- if (args.simulateVotes) warnIfSimulatedOutsideTests("consensus_vote", logger8);
9196
+ const logger11 = deps.logger ?? createLogger({ tool: "consensus_vote" });
9197
+ if (args.simulateVotes) warnIfSimulatedOutsideTests("consensus_vote", logger11);
8845
9198
  try {
8846
- const result = await executeVoting(args, logger8);
9199
+ const result = await executeVoting(args, logger11);
8847
9200
  const strategy = args.strategy ?? "simple_majority";
8848
9201
  const errorVotes = result.votes.filter((v) => v.source === "error");
8849
9202
  if (errorVotes.length === result.votes.length && result.votes.length > 0) {
8850
9203
  const failures = errorVotes.map((v) => `${v.role}: ${v.error ?? "unknown error"}`).join("; ");
8851
- logger8.warn("All voters failed", { failureCount: errorVotes.length, failures });
9204
+ logger11.warn("All voters failed", { failureCount: errorVotes.length, failures });
8852
9205
  recordVoteError(args.proposal, `All ${String(errorVotes.length)} voters failed: ${failures}`);
8853
9206
  return {
8854
9207
  ok: false,
@@ -8866,11 +9219,109 @@ async function handleConsensusVote(deps, args) {
8866
9219
  } catch (error) {
8867
9220
  const message = getErrorMessage(error);
8868
9221
  const cause = error instanceof Error ? error : new Error(message);
8869
- logger8.error("Consensus vote failed", cause);
9222
+ logger11.error("Consensus vote failed", cause);
8870
9223
  recordVoteError(args.proposal, message);
8871
9224
  return { ok: false, error: `Voting failed: ${message}` };
8872
9225
  }
8873
9226
  }
9227
+ function buildConsensusVoteReplayEnvelope(jobId) {
9228
+ return toolSuccess(
9229
+ JSON.stringify({
9230
+ status: "replay",
9231
+ jobId,
9232
+ pollTool: "get_job_result",
9233
+ note: "Idempotency key matched a prior dispatch \u2014 poll get_job_result for current status."
9234
+ })
9235
+ );
9236
+ }
9237
+ function buildConsensusVoteCollisionEnvelope(existingJobId) {
9238
+ return toolStructuredError({
9239
+ errorCategory: "validation",
9240
+ message: `Idempotency key already used with different inputs. Existing jobId: ${existingJobId}. Use a fresh key or omit it.`
9241
+ });
9242
+ }
9243
+ function dispatchAsyncConsensusVote(deps, args) {
9244
+ const idempotency = shortCircuitOrFreshJobId({
9245
+ tool: "consensus_vote",
9246
+ idempotencyKey: args.idempotencyKey,
9247
+ inputs: args,
9248
+ freshJobId: () => `job-vote-${randomUUID4()}`,
9249
+ replayEnvelope: buildConsensusVoteReplayEnvelope,
9250
+ collisionEnvelope: buildConsensusVoteCollisionEnvelope
9251
+ });
9252
+ if (idempotency.kind === "shortCircuit") return idempotency.value;
9253
+ if (!tryAcquire("consensus_vote")) {
9254
+ return toolSuccess(
9255
+ JSON.stringify({
9256
+ status: "busy",
9257
+ retryAfterMs: suggestRetryAfterMs("consensus_vote"),
9258
+ note: 'Async-mode concurrency cap reached for consensus_vote. Retry later or use mode: "sync".'
9259
+ })
9260
+ );
9261
+ }
9262
+ const jobId = idempotency.jobId;
9263
+ recordConsensusVotePending(jobId, args);
9264
+ void runConsensusVoteInBackground(jobId, deps, args);
9265
+ return toolSuccess(
9266
+ JSON.stringify({
9267
+ status: "pending",
9268
+ jobId,
9269
+ pollTool: "get_job_result",
9270
+ note: 'Poll via get_job_result({ jobId }) until status !== "pending".'
9271
+ })
9272
+ );
9273
+ }
9274
+ function recordConsensusVotePending(jobId, args) {
9275
+ writeJobPending(jobId, "consensus_vote");
9276
+ if (args.idempotencyKey !== void 0 && args.idempotencyKey !== "") {
9277
+ registerIdempotentJob({
9278
+ tool: "consensus_vote",
9279
+ idempotencyKey: args.idempotencyKey,
9280
+ inputs: args,
9281
+ jobId
9282
+ });
9283
+ }
9284
+ }
9285
+ async function runConsensusVoteInBackground(jobId, deps, args) {
9286
+ try {
9287
+ const result = await handleConsensusVote(deps, args);
9288
+ writeJobComplete(jobId, "consensus_vote", result);
9289
+ } catch (err2) {
9290
+ const errObj = err2 instanceof Error ? err2 : new Error(String(err2));
9291
+ deps.logger?.error("Async consensus_vote dispatch failed", errObj, { jobId });
9292
+ writeJobFailed(jobId, "consensus_vote", errObj.message);
9293
+ } finally {
9294
+ release("consensus_vote");
9295
+ }
9296
+ }
9297
+ async function runSyncConsensusVote(deps, notifier, args) {
9298
+ const result = await withProgressHeartbeat(
9299
+ "consensus_vote",
9300
+ notifier,
9301
+ () => handleConsensusVote(deps, args)
9302
+ );
9303
+ if (!result.ok) {
9304
+ return toolStructuredError({ errorCategory: "internal", message: result.error });
9305
+ }
9306
+ for (const vote of result.value.votes) {
9307
+ notifier.debug("consensus_vote", {
9308
+ event: "vote_collected",
9309
+ role: vote.role,
9310
+ decision: vote.decision
9311
+ });
9312
+ }
9313
+ notifier.info("consensus_vote", {
9314
+ event: "vote_complete",
9315
+ decision: result.value.decision,
9316
+ approvalPercentage: result.value.approvalPercentage,
9317
+ voteCount: result.value.votes.length
9318
+ });
9319
+ const data = result.value;
9320
+ return {
9321
+ ...toolSuccess(JSON.stringify(result.value, null, 2)),
9322
+ structuredContent: data
9323
+ };
9324
+ }
8874
9325
  function createConsensusVoteHandler(deps) {
8875
9326
  const notifier = deps.notifier ?? NOOP_NOTIFIER;
8876
9327
  return async (args, ctx) => {
@@ -8884,63 +9335,48 @@ function createConsensusVoteHandler(deps) {
8884
9335
  const strategy = validationResult.data.strategy ?? "simple_majority";
8885
9336
  ctx.logger.debug("Starting consensus vote", {
8886
9337
  strategy,
8887
- quickMode: validationResult.data.quickMode
9338
+ quickMode: validationResult.data.quickMode,
9339
+ ...validationResult.data.mode !== void 0 ? { mode: validationResult.data.mode } : {}
8888
9340
  });
8889
9341
  notifier.info("consensus_vote", {
8890
9342
  event: "vote_start",
8891
9343
  proposalLength: validationResult.data.proposal.length,
8892
9344
  strategy
8893
9345
  });
8894
- const result = await withProgressHeartbeat(
8895
- "consensus_vote",
8896
- notifier,
8897
- () => handleConsensusVote(deps, validationResult.data)
8898
- );
8899
- if (!result.ok) {
8900
- return toolStructuredError({ errorCategory: "internal", message: result.error });
8901
- }
8902
- for (const vote of result.value.votes) {
8903
- notifier.debug("consensus_vote", {
8904
- event: "vote_collected",
8905
- role: vote.role,
8906
- decision: vote.decision
9346
+ if (validationResult.data.mode === "async") {
9347
+ const asyncResult = dispatchAsyncConsensusVote(deps, validationResult.data);
9348
+ notifier.info("consensus_vote", {
9349
+ event: "vote_dispatched_async",
9350
+ proposalLength: validationResult.data.proposal.length,
9351
+ strategy
8907
9352
  });
9353
+ return asyncResult;
8908
9354
  }
8909
- notifier.info("consensus_vote", {
8910
- event: "vote_complete",
8911
- decision: result.value.decision,
8912
- approvalPercentage: result.value.approvalPercentage,
8913
- voteCount: result.value.votes.length
8914
- });
8915
- const data = result.value;
8916
- return {
8917
- ...toolSuccess(JSON.stringify(result.value, null, 2)),
8918
- structuredContent: data
8919
- };
9355
+ return runSyncConsensusVote(deps, notifier, validationResult.data);
8920
9356
  };
8921
9357
  }
8922
9358
  var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
8923
- proposal: z10.string(),
9359
+ proposal: z12.string(),
8924
9360
  strategy: VotingStrategySchema,
8925
- decision: z10.enum(["approved", "rejected", "no_quorum"]),
8926
- approvalPercentage: z10.number(),
8927
- voteCounts: z10.object({
8928
- approve: z10.number(),
8929
- reject: z10.number(),
8930
- abstain: z10.number(),
8931
- error: z10.number()
9361
+ decision: z12.enum(["approved", "rejected", "no_quorum"]),
9362
+ approvalPercentage: z12.number(),
9363
+ voteCounts: z12.object({
9364
+ approve: z12.number(),
9365
+ reject: z12.number(),
9366
+ abstain: z12.number(),
9367
+ error: z12.number()
8932
9368
  }),
8933
- votes: z10.array(
8934
- z10.object({
8935
- role: z10.string().max(100),
8936
- decision: z10.enum(["approve", "reject", "abstain"]),
8937
- confidence: z10.number(),
8938
- reasoning: z10.string().max(4e3),
8939
- simulated: z10.boolean(),
8940
- error: z10.boolean(),
8941
- modelUsed: z10.string().max(100).optional(),
8942
- rejectionCategories: z10.array(
8943
- z10.enum([
9369
+ votes: z12.array(
9370
+ z12.object({
9371
+ role: z12.string().max(100),
9372
+ decision: z12.enum(["approve", "reject", "abstain"]),
9373
+ confidence: z12.number(),
9374
+ reasoning: z12.string().max(4e3),
9375
+ simulated: z12.boolean(),
9376
+ error: z12.boolean(),
9377
+ modelUsed: z12.string().max(100).optional(),
9378
+ rejectionCategories: z12.array(
9379
+ z12.enum([
8944
9380
  "YAGNI",
8945
9381
  "DRY_VIOLATION",
8946
9382
  "OVER_ENGINEERING",
@@ -8953,42 +9389,42 @@ var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
8953
9389
  })
8954
9390
  ),
8955
9391
  threshold: VoteThresholdSchema.optional(),
8956
- durationMs: z10.number(),
8957
- simulateVotes: z10.boolean(),
8958
- higherOrderMetadata: z10.object({
8959
- posteriorApproval: z10.number(),
8960
- posteriorRejection: z10.number(),
8961
- effectiveVoteCount: z10.number(),
8962
- method: z10.enum(["ow", "isp", "simple"]),
8963
- usedCorrelationData: z10.boolean(),
8964
- improvementOverBaseline: z10.number(),
8965
- downweightedAgents: z10.array(z10.string().max(100)).max(10),
8966
- reasoning: z10.string().max(2e3)
9392
+ durationMs: z12.number(),
9393
+ simulateVotes: z12.boolean(),
9394
+ higherOrderMetadata: z12.object({
9395
+ posteriorApproval: z12.number(),
9396
+ posteriorRejection: z12.number(),
9397
+ effectiveVoteCount: z12.number(),
9398
+ method: z12.enum(["ow", "isp", "simple"]),
9399
+ usedCorrelationData: z12.boolean(),
9400
+ improvementOverBaseline: z12.number(),
9401
+ downweightedAgents: z12.array(z12.string().max(100)).max(10),
9402
+ reasoning: z12.string().max(2e3)
8967
9403
  }).optional()
8968
9404
  };
8969
9405
  function registerConsensusVoteTool(server, deps) {
8970
- const logger8 = deps.logger ?? createLogger({ tool: "consensus_vote" });
9406
+ const logger11 = deps.logger ?? createLogger({ tool: "consensus_vote" });
8971
9407
  const notifier = deps.notifier ?? createMcpNotifier(server);
8972
9408
  const depsWithNotifier = { ...deps, notifier };
8973
9409
  const toolSchema = {
8974
- proposal: z10.string().min(1).max(MAX_PROPOSAL_LENGTH).describe("Proposal text to vote on"),
8975
- threshold: z10.enum(["majority", "supermajority", "unanimous"]).optional().describe("Voting threshold (legacy). Use strategy instead."),
9410
+ proposal: z12.string().min(1).max(MAX_PROPOSAL_LENGTH).describe("Proposal text to vote on"),
9411
+ threshold: z12.enum(["majority", "supermajority", "unanimous"]).optional().describe("Voting threshold (legacy). Use strategy instead."),
8976
9412
  strategy: VotingStrategySchema.optional().describe(
8977
9413
  "Voting strategy: simple_majority (default), supermajority, unanimous, proof_of_learning, or higher_order"
8978
9414
  ),
8979
- quickMode: z10.boolean().optional().default(false).describe("Use 3 agents instead of 7"),
8980
- simulateVotes: z10.boolean().optional().default(false).describe("TESTS ONLY \u2014 random output, must not be used for real decisions (#2319)")
9415
+ quickMode: z12.boolean().optional().default(false).describe("Use 3 agents instead of 7"),
9416
+ simulateVotes: z12.boolean().optional().default(false).describe("TESTS ONLY \u2014 random output, must not be used for real decisions (#2319)")
8981
9417
  };
8982
9418
  const description = "Execute multi-model consensus voting on a proposal. Uses 7 specialized agent roles (architect, security, devex, ai_ml, pm, catfish, scope_steward) to vote on proposals with configurable strategies. Supports higher_order strategy for Bayesian-optimal aggregation with correlation awareness (Issue #514).";
8983
9419
  const secureHandler = createSecureHandler(createConsensusVoteHandler(depsWithNotifier), {
8984
9420
  toolName: "consensus_vote",
8985
9421
  rateLimiter: deps.rateLimiter,
8986
- logger: logger8
9422
+ logger: logger11
8987
9423
  });
8988
9424
  const timeoutMs = getToolTimeout("consensus_vote", deps.security);
8989
9425
  const wrappedHandler = wrapToolWithTimeout("consensus_vote", secureHandler, {
8990
9426
  timeoutMs,
8991
- logger: logger8
9427
+ logger: logger11
8992
9428
  });
8993
9429
  server.registerTool(
8994
9430
  "consensus_vote",
@@ -8998,9 +9434,9 @@ function registerConsensusVoteTool(server, deps) {
8998
9434
  outputSchema: CONSENSUS_VOTE_OUTPUT_SCHEMA,
8999
9435
  annotations: getToolAnnotations("consensus_vote")
9000
9436
  },
9001
- toSdkCallbackWithBudgetCheck(wrappedHandler, "consensus_vote", timeoutMs, logger8)
9437
+ toSdkCallbackWithBudgetCheck(wrappedHandler, "consensus_vote", timeoutMs, logger11)
9002
9438
  );
9003
- logger8.info("Registered consensus_vote tool with secure handler and timeout protection");
9439
+ logger11.info("Registered consensus_vote tool with secure handler and timeout protection");
9004
9440
  }
9005
9441
 
9006
9442
  export {
@@ -9053,6 +9489,17 @@ export {
9053
9489
  toSdkCallbackWithBudgetCheck,
9054
9490
  getToolAnnotations,
9055
9491
  PersistentOutcomeStore,
9492
+ JobStatusSchema,
9493
+ writeJobPending,
9494
+ writeJobComplete,
9495
+ writeJobFailed,
9496
+ readJobResult,
9497
+ listJobs,
9498
+ registerIdempotentJob,
9499
+ shortCircuitOrFreshJobId,
9500
+ tryAcquire,
9501
+ release,
9502
+ suggestRetryAfterMs,
9056
9503
  DEFAULT_VOTE_TIMEOUT_MS,
9057
9504
  isRateLimitError,
9058
9505
  VOTER_ROLES,
@@ -9122,4 +9569,4 @@ export {
9122
9569
  CONSENSUS_VOTE_OUTPUT_SCHEMA,
9123
9570
  registerConsensusVoteTool
9124
9571
  };
9125
- //# sourceMappingURL=chunk-V7RC2PIY.js.map
9572
+ //# sourceMappingURL=chunk-IF6TXCSE.js.map