nexus-agents 2.83.1 → 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 (124) hide show
  1. package/dist/{child-mcp-config-3ZW2UPKZ.js → child-mcp-config-FARMFCA3.js} +3 -3
  2. package/dist/{chunk-DWOSFYI2.js → chunk-25AQZKMN.js} +2 -2
  3. package/dist/{chunk-I2HMWH4R.js → chunk-2WCYG75B.js} +13 -2
  4. package/dist/chunk-2WCYG75B.js.map +1 -0
  5. package/dist/{chunk-A6WC5I7V.js → chunk-4MYJNFYL.js} +4 -4
  6. package/dist/{chunk-W6MLS2UL.js → chunk-4S5GY2MF.js} +2 -2
  7. package/dist/{chunk-7V367KT4.js → chunk-4SU4Q37U.js} +7 -23
  8. package/dist/chunk-4SU4Q37U.js.map +1 -0
  9. package/dist/{chunk-J4ZBKE4B.js → chunk-6KZL5DMU.js} +910 -308
  10. package/dist/chunk-6KZL5DMU.js.map +1 -0
  11. package/dist/{chunk-JA6ON2RP.js → chunk-6QKMUPDP.js} +2 -2
  12. package/dist/{chunk-MATFDJRW.js → chunk-7J7D3LAL.js} +4 -4
  13. package/dist/{chunk-LM2S2QWO.js → chunk-CIW2BVSN.js} +3 -2
  14. package/dist/{chunk-LM2S2QWO.js.map → chunk-CIW2BVSN.js.map} +1 -1
  15. package/dist/{chunk-ZLGU7T6J.js → chunk-EL2KV773.js} +78 -63
  16. package/dist/chunk-EL2KV773.js.map +1 -0
  17. package/dist/{chunk-IM2B3FK2.js → chunk-ELVQORLX.js} +4 -4
  18. package/dist/chunk-ELVQORLX.js.map +1 -0
  19. package/dist/{chunk-VXIHHHLQ.js → chunk-FOG7PMGM.js} +2 -2
  20. package/dist/{chunk-HGPIHDC4.js → chunk-FR3P47J2.js} +4 -4
  21. package/dist/{chunk-ODKIRXN7.js → chunk-IF6TXCSE.js} +683 -227
  22. package/dist/chunk-IF6TXCSE.js.map +1 -0
  23. package/dist/{chunk-TKGVRHEI.js → chunk-J5S27RQ4.js} +2 -2
  24. package/dist/{chunk-UFUR6RBP.js → chunk-LY2KLNXM.js} +2 -2
  25. package/dist/{chunk-5QJPM5CB.js → chunk-NSOB2WRI.js} +3 -3
  26. package/dist/{chunk-4XSCU4B3.js → chunk-OXVOUVKH.js} +8 -8
  27. package/dist/{chunk-6XRNFLPI.js → chunk-POTGGTJD.js} +2 -2
  28. package/dist/{chunk-ZA6AZ7LK.js → chunk-QR4VYHMI.js} +6 -6
  29. package/dist/{chunk-FHY7I736.js → chunk-QR5KHIZG.js} +2 -2
  30. package/dist/{chunk-ELRNVADA.js → chunk-RTAIMK6P.js} +155 -47
  31. package/dist/chunk-RTAIMK6P.js.map +1 -0
  32. package/dist/{chunk-O3XJLOEX.js → chunk-SOKQOPTM.js} +2 -2
  33. package/dist/chunk-TRX7CAD5.js +27 -0
  34. package/dist/chunk-TRX7CAD5.js.map +1 -0
  35. package/dist/{chunk-BICIQYET.js → chunk-XZAWH36N.js} +3 -3
  36. package/dist/{chunk-6UI4NKT4.js → chunk-YLMB5MFQ.js} +27 -4
  37. package/dist/{chunk-6UI4NKT4.js.map → chunk-YLMB5MFQ.js.map} +1 -1
  38. package/dist/{chunk-BUXXAN6V.js → chunk-Z5BAZS6F.js} +2 -2
  39. package/dist/{chunk-SZZS57X7.js → chunk-ZF3MSYLG.js} +7 -7
  40. package/dist/{chunk-XODXYOFN.js → chunk-ZMERLMEP.js} +2 -2
  41. package/dist/{cli-circuit-breaker-LC4NZUGD.js → cli-circuit-breaker-LF22Z3QL.js} +5 -5
  42. package/dist/cli.d.ts +1 -1
  43. package/dist/cli.js +39 -34
  44. package/dist/cli.js.map +1 -1
  45. package/dist/{composite-router-GXQ25DO4.js → composite-router-TEXZI7WJ.js} +3 -3
  46. package/dist/{consensus-vote-MTLP6E72.js → consensus-vote-LPYEXUVC.js} +13 -12
  47. package/dist/{consensus-vote-types-CoGbAEjf.d.ts → consensus-vote-types-COAhHVIp.d.ts} +5 -0
  48. package/dist/{context-retriever-GQRC2MVM.js → context-retriever-3TKV4EEC.js} +7 -6
  49. package/dist/{dist-APHOQ26Z.js → dist-75MXB4R3.js} +917 -822
  50. package/dist/dist-75MXB4R3.js.map +1 -0
  51. package/dist/{doctor-deep-T3UUJX2E.js → doctor-deep-OUAKPLJX.js} +4 -4
  52. package/dist/expert-bridge-22UVN5TB.js +13 -0
  53. package/dist/{factory-OKNCTJO6.js → factory-IGHUOUBS.js} +6 -5
  54. package/dist/factory-JNXETBS4.js +14 -0
  55. package/dist/index.d.ts +137 -10
  56. package/dist/index.js +59 -26
  57. package/dist/index.js.map +1 -1
  58. package/dist/{init-opencode-KDTBKLXS.js → init-opencode-52TLZ2TO.js} +6 -6
  59. package/dist/issue-triage-WUK7L25X.js +15 -0
  60. package/dist/{learning-persistence-NX2KHL5T.js → learning-persistence-5ALG6XRC.js} +2 -2
  61. package/dist/{registry-command-D56ROMFJ.js → registry-command-ZIAJB2J3.js} +3 -3
  62. package/dist/{repo-security-plan-N3CDMW6L.js → repo-security-plan-THHLNGEQ.js} +4 -4
  63. package/dist/{research-helpers-synthesize-36QBOKII.js → research-helpers-synthesize-KNRCAIXK.js} +4 -4
  64. package/dist/{routing-memory-6IEPJ3EP.js → routing-memory-UY6KTGT2.js} +3 -3
  65. package/dist/{session-memory-X6SCDFER.js → session-memory-PUJMR6FE.js} +4 -4
  66. package/dist/{setup-command-5AEO5A4Z.js → setup-command-ZXDAR3GQ.js} +12 -11
  67. package/dist/setup-config-EYY5AYZ3.js +10 -0
  68. package/dist/{setup-custom-api-RBOJT3SS.js → setup-custom-api-5XRNYFOP.js} +5 -5
  69. package/dist/{tool-memory-EEHITQRJ.js → tool-memory-PNAHRFZM.js} +6 -5
  70. package/dist/{weather-report-6BC3JK5H.js → weather-report-RQMZOL7C.js} +3 -3
  71. package/package.json +4 -4
  72. package/dist/chunk-7V367KT4.js.map +0 -1
  73. package/dist/chunk-ELRNVADA.js.map +0 -1
  74. package/dist/chunk-I2HMWH4R.js.map +0 -1
  75. package/dist/chunk-IM2B3FK2.js.map +0 -1
  76. package/dist/chunk-J4ZBKE4B.js.map +0 -1
  77. package/dist/chunk-ODKIRXN7.js.map +0 -1
  78. package/dist/chunk-ZLGU7T6J.js.map +0 -1
  79. package/dist/dist-APHOQ26Z.js.map +0 -1
  80. package/dist/expert-bridge-7LPGCPPR.js +0 -13
  81. package/dist/factory-3XB5CAAA.js +0 -14
  82. package/dist/issue-triage-MURMDN2G.js +0 -15
  83. package/dist/setup-config-RPSVIQJO.js +0 -10
  84. /package/dist/{child-mcp-config-3ZW2UPKZ.js.map → child-mcp-config-FARMFCA3.js.map} +0 -0
  85. /package/dist/{chunk-DWOSFYI2.js.map → chunk-25AQZKMN.js.map} +0 -0
  86. /package/dist/{chunk-A6WC5I7V.js.map → chunk-4MYJNFYL.js.map} +0 -0
  87. /package/dist/{chunk-W6MLS2UL.js.map → chunk-4S5GY2MF.js.map} +0 -0
  88. /package/dist/{chunk-JA6ON2RP.js.map → chunk-6QKMUPDP.js.map} +0 -0
  89. /package/dist/{chunk-MATFDJRW.js.map → chunk-7J7D3LAL.js.map} +0 -0
  90. /package/dist/{chunk-VXIHHHLQ.js.map → chunk-FOG7PMGM.js.map} +0 -0
  91. /package/dist/{chunk-HGPIHDC4.js.map → chunk-FR3P47J2.js.map} +0 -0
  92. /package/dist/{chunk-TKGVRHEI.js.map → chunk-J5S27RQ4.js.map} +0 -0
  93. /package/dist/{chunk-UFUR6RBP.js.map → chunk-LY2KLNXM.js.map} +0 -0
  94. /package/dist/{chunk-5QJPM5CB.js.map → chunk-NSOB2WRI.js.map} +0 -0
  95. /package/dist/{chunk-4XSCU4B3.js.map → chunk-OXVOUVKH.js.map} +0 -0
  96. /package/dist/{chunk-6XRNFLPI.js.map → chunk-POTGGTJD.js.map} +0 -0
  97. /package/dist/{chunk-ZA6AZ7LK.js.map → chunk-QR4VYHMI.js.map} +0 -0
  98. /package/dist/{chunk-FHY7I736.js.map → chunk-QR5KHIZG.js.map} +0 -0
  99. /package/dist/{chunk-O3XJLOEX.js.map → chunk-SOKQOPTM.js.map} +0 -0
  100. /package/dist/{chunk-BICIQYET.js.map → chunk-XZAWH36N.js.map} +0 -0
  101. /package/dist/{chunk-BUXXAN6V.js.map → chunk-Z5BAZS6F.js.map} +0 -0
  102. /package/dist/{chunk-SZZS57X7.js.map → chunk-ZF3MSYLG.js.map} +0 -0
  103. /package/dist/{chunk-XODXYOFN.js.map → chunk-ZMERLMEP.js.map} +0 -0
  104. /package/dist/{cli-circuit-breaker-LC4NZUGD.js.map → cli-circuit-breaker-LF22Z3QL.js.map} +0 -0
  105. /package/dist/{composite-router-GXQ25DO4.js.map → composite-router-TEXZI7WJ.js.map} +0 -0
  106. /package/dist/{consensus-vote-MTLP6E72.js.map → consensus-vote-LPYEXUVC.js.map} +0 -0
  107. /package/dist/{context-retriever-GQRC2MVM.js.map → context-retriever-3TKV4EEC.js.map} +0 -0
  108. /package/dist/{doctor-deep-T3UUJX2E.js.map → doctor-deep-OUAKPLJX.js.map} +0 -0
  109. /package/dist/{expert-bridge-7LPGCPPR.js.map → expert-bridge-22UVN5TB.js.map} +0 -0
  110. /package/dist/{factory-3XB5CAAA.js.map → factory-IGHUOUBS.js.map} +0 -0
  111. /package/dist/{factory-OKNCTJO6.js.map → factory-JNXETBS4.js.map} +0 -0
  112. /package/dist/{init-opencode-KDTBKLXS.js.map → init-opencode-52TLZ2TO.js.map} +0 -0
  113. /package/dist/{issue-triage-MURMDN2G.js.map → issue-triage-WUK7L25X.js.map} +0 -0
  114. /package/dist/{learning-persistence-NX2KHL5T.js.map → learning-persistence-5ALG6XRC.js.map} +0 -0
  115. /package/dist/{registry-command-D56ROMFJ.js.map → registry-command-ZIAJB2J3.js.map} +0 -0
  116. /package/dist/{repo-security-plan-N3CDMW6L.js.map → repo-security-plan-THHLNGEQ.js.map} +0 -0
  117. /package/dist/{research-helpers-synthesize-36QBOKII.js.map → research-helpers-synthesize-KNRCAIXK.js.map} +0 -0
  118. /package/dist/{routing-memory-6IEPJ3EP.js.map → routing-memory-UY6KTGT2.js.map} +0 -0
  119. /package/dist/{session-memory-X6SCDFER.js.map → session-memory-PUJMR6FE.js.map} +0 -0
  120. /package/dist/{setup-command-5AEO5A4Z.js.map → setup-command-ZXDAR3GQ.js.map} +0 -0
  121. /package/dist/{setup-config-RPSVIQJO.js.map → setup-config-EYY5AYZ3.js.map} +0 -0
  122. /package/dist/{setup-custom-api-RBOJT3SS.js.map → setup-custom-api-5XRNYFOP.js.map} +0 -0
  123. /package/dist/{tool-memory-EEHITQRJ.js.map → tool-memory-PNAHRFZM.js.map} +0 -0
  124. /package/dist/{weather-report-6BC3JK5H.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-JA6ON2RP.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-6XRNFLPI.js";
12
+ } from "./chunk-POTGGTJD.js";
13
13
  import {
14
14
  getToolMemory
15
- } from "./chunk-7V367KT4.js";
15
+ } from "./chunk-4SU4Q37U.js";
16
16
  import {
17
17
  getDefaultAvailableModelsCache
18
- } from "./chunk-VXIHHHLQ.js";
18
+ } from "./chunk-FOG7PMGM.js";
19
19
  import {
20
20
  CUSTOM_API_DEFAULT_MODEL
21
- } from "./chunk-DWOSFYI2.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-ELRNVADA.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-6UI4NKT4.js";
73
+ } from "./chunk-YLMB5MFQ.js";
74
74
  import {
75
75
  ensureLearningDir,
76
76
  getNexusDataDir,
77
77
  getOutcomesFile,
78
- nexusDataPath
79
- } from "./chunk-I2HMWH4R.js";
78
+ nexusDataPath,
79
+ nexusDataPathEnsure
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
  }
@@ -888,6 +889,10 @@ var READ_ONLY_TOOLS2 = /* @__PURE__ */ new Set([
888
889
  "weather_report",
889
890
  "query_trace",
890
891
  "query_task_state",
892
+ // Async-mode result polling (#3042 / epic #2631)
893
+ "get_job_result",
894
+ // Async-mode job discovery (#3046 / epic #2631 Stage 5)
895
+ "list_jobs",
891
896
  // Codebase intelligence (read-only over local files)
892
897
  "search_codebase",
893
898
  "extract_symbols",
@@ -1235,13 +1240,13 @@ function buildMiddlewareStack(config) {
1235
1240
  return middlewares;
1236
1241
  }
1237
1242
  function createMiddlewareChain(config) {
1238
- const logger8 = config.logger ?? createLogger({ tool: config.toolName });
1243
+ const logger11 = config.logger ?? createLogger({ tool: config.toolName });
1239
1244
  const middlewares = buildMiddlewareStack(config);
1240
1245
  const composed = composeMiddleware(middlewares);
1241
1246
  return (handler) => {
1242
1247
  return async (args) => {
1243
1248
  const requestContext = createRequestContext({ toolName: config.toolName });
1244
- const requestLogger = logger8.child(contextForLogging(requestContext));
1249
+ const requestLogger = logger11.child(contextForLogging(requestContext));
1245
1250
  const ctx = { requestContext, logger: requestLogger };
1246
1251
  return composed(args, ctx, (finalArgs, finalCtx) => handler(finalArgs, finalCtx));
1247
1252
  };
@@ -1428,8 +1433,8 @@ async function runMismatchedCall(ctx) {
1428
1433
  throw err2;
1429
1434
  }
1430
1435
  }
1431
- function toSdkCallbackWithBudgetCheck(handler, toolName, configuredTimeoutMs, logger8) {
1432
- const log = logger8 ?? wrapperLogger;
1436
+ function toSdkCallbackWithBudgetCheck(handler, toolName, configuredTimeoutMs, logger11) {
1437
+ const log = logger11 ?? wrapperLogger;
1433
1438
  return (args, extra) => {
1434
1439
  const progressCtx = extractProgressContext(extra);
1435
1440
  const signal = extra?.signal;
@@ -1553,15 +1558,15 @@ function sanitizeToolInput(args) {
1553
1558
  detectedPatterns: uniquePatterns
1554
1559
  };
1555
1560
  }
1556
- function logSanitizationResult(result, logger8, toolName) {
1561
+ function logSanitizationResult(result, logger11, toolName) {
1557
1562
  if (result.wasModified) {
1558
- logger8.warn("Tool input sanitized \u2014 XML injection tags stripped", {
1563
+ logger11.warn("Tool input sanitized \u2014 XML injection tags stripped", {
1559
1564
  tool: toolName,
1560
1565
  modifiedFields: result.modifiedCount
1561
1566
  });
1562
1567
  }
1563
1568
  if (result.detectedPatterns.length > 0) {
1564
- logger8.warn("Injection patterns detected in tool input", {
1569
+ logger11.warn("Injection patterns detected in tool input", {
1565
1570
  tool: toolName,
1566
1571
  patterns: result.detectedPatterns
1567
1572
  });
@@ -1601,11 +1606,11 @@ var SECRET_PATTERNS = [
1601
1606
  // password= or token= in output
1602
1607
  /(?:password|token|secret|apikey|api_key)\s*[=:]\s*\S{8,}/i
1603
1608
  ];
1604
- function sanitizeOutput2(text, logger8) {
1609
+ function sanitizeOutput2(text, logger11) {
1605
1610
  let sanitized = text;
1606
1611
  for (const pattern of SECRET_PATTERNS) {
1607
1612
  if (pattern.test(sanitized)) {
1608
- logger8.warn("Potential secret detected in tool output, redacting", {
1613
+ logger11.warn("Potential secret detected in tool output, redacting", {
1609
1614
  pattern: pattern.source.slice(0, 30)
1610
1615
  });
1611
1616
  sanitized = sanitized.replace(pattern, "[REDACTED]");
@@ -1613,25 +1618,25 @@ function sanitizeOutput2(text, logger8) {
1613
1618
  }
1614
1619
  return sanitized;
1615
1620
  }
1616
- function sanitizeToolResult(result, logger8) {
1621
+ function sanitizeToolResult(result, logger11) {
1617
1622
  for (const item of result.content) {
1618
- item.text = sanitizeOutput2(item.text, logger8);
1623
+ item.text = sanitizeOutput2(item.text, logger11);
1619
1624
  }
1620
1625
  }
1621
- function checkInputSize(args, logger8, requestId) {
1626
+ function checkInputSize(args, logger11, requestId) {
1622
1627
  if (args === void 0) return null;
1623
1628
  const inputSize = JSON.stringify(args).length;
1624
1629
  if (inputSize > MAX_INPUT_SIZE_BYTES) {
1625
- 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 });
1626
1631
  return internalError("Input too large", requestId);
1627
1632
  }
1628
1633
  return null;
1629
1634
  }
1630
- function checkRateLimit(rateLimiter, logger8) {
1635
+ function checkRateLimit(rateLimiter, logger11) {
1631
1636
  const acquired = rateLimiter.tryAcquire();
1632
1637
  if (!acquired) {
1633
1638
  const state = rateLimiter.getState();
1634
- logger8.warn("Rate limit exceeded");
1639
+ logger11.warn("Rate limit exceeded");
1635
1640
  return rateLimitError(state.nextTokenMs);
1636
1641
  }
1637
1642
  return null;
@@ -1652,14 +1657,14 @@ function checkPolicy(opts) {
1652
1657
  opts.logger.debug("Policy check passed", { reason: decision.reason });
1653
1658
  return null;
1654
1659
  }
1655
- async function executeHandler(handler, args, ctx, logger8) {
1660
+ async function executeHandler(handler, args, ctx, logger11) {
1656
1661
  const startTime = getTimeProvider().now();
1657
1662
  const result = handler.length >= 2 ? await handler(args, ctx) : await handler(args);
1658
1663
  const durationMs = getTimeProvider().now() - startTime;
1659
1664
  if (result.isError === true) {
1660
- logger8.warn("Tool execution completed with error", { durationMs });
1665
+ logger11.warn("Tool execution completed with error", { durationMs });
1661
1666
  } else {
1662
- logger8.info("Tool execution completed", { durationMs });
1667
+ logger11.info("Tool execution completed", { durationMs });
1663
1668
  }
1664
1669
  return result;
1665
1670
  }
@@ -1705,12 +1710,12 @@ function emitRateLimitAudit(auditLogger, toolName, ctx) {
1705
1710
  requestId: ctx.requestId
1706
1711
  });
1707
1712
  }
1708
- function checkSecurityTier(config, sanitizeResult, logger8) {
1713
+ function checkSecurityTier(config, sanitizeResult, logger11) {
1709
1714
  const tier = config.securityTier ?? "standard";
1710
1715
  if (tier === "standard" || sanitizeResult.detectedPatterns.length === 0) {
1711
1716
  return null;
1712
1717
  }
1713
- logger8.warn("Input rejected by security tier validation", {
1718
+ logger11.warn("Input rejected by security tier validation", {
1714
1719
  tier,
1715
1720
  patterns: sanitizeResult.detectedPatterns
1716
1721
  });
@@ -1719,16 +1724,16 @@ function checkSecurityTier(config, sanitizeResult, logger8) {
1719
1724
  message: `Input validation failed: detected patterns [${sanitizeResult.detectedPatterns.join(", ")}]. Remove prompt injection patterns and retry.`
1720
1725
  });
1721
1726
  }
1722
- function runPreChecks(config, args, mode, requestContext, logger8) {
1723
- const sizeResult = checkInputSize(args, logger8, requestContext.requestId);
1727
+ function runPreChecks(config, args, mode, requestContext, logger11) {
1728
+ const sizeResult = checkInputSize(args, logger11, requestContext.requestId);
1724
1729
  if (sizeResult) return { error: sizeResult, sanitizedArgs: args };
1725
1730
  const sanitizeResult = sanitizeToolInput(args);
1726
- logSanitizationResult(sanitizeResult, logger8, config.toolName);
1731
+ logSanitizationResult(sanitizeResult, logger11, config.toolName);
1727
1732
  const sanitizedArgs = sanitizeResult.wasModified ? sanitizeResult.sanitized : args;
1728
- const tierError = checkSecurityTier(config, sanitizeResult, logger8);
1733
+ const tierError = checkSecurityTier(config, sanitizeResult, logger11);
1729
1734
  if (tierError !== null) return { error: tierError, sanitizedArgs };
1730
1735
  if (config.rateLimiter) {
1731
- const rlResult = checkRateLimit(config.rateLimiter, logger8);
1736
+ const rlResult = checkRateLimit(config.rateLimiter, logger11);
1732
1737
  if (rlResult) {
1733
1738
  if (config.auditLogger)
1734
1739
  emitRateLimitAudit(config.auditLogger, config.toolName, requestContext);
@@ -1742,7 +1747,7 @@ function runPreChecks(config, args, mode, requestContext, logger8) {
1742
1747
  args: sanitizedArgs,
1743
1748
  mode,
1744
1749
  allowedPaths: config.allowedPaths,
1745
- logger: logger8,
1750
+ logger: logger11,
1746
1751
  requestId: requestContext.requestId
1747
1752
  });
1748
1753
  if (pResult) {
@@ -1754,7 +1759,7 @@ function runPreChecks(config, args, mode, requestContext, logger8) {
1754
1759
  return { error: null, sanitizedArgs };
1755
1760
  }
1756
1761
  function createSecureHandler(handler, config) {
1757
- const logger8 = config.logger ?? createLogger({ tool: config.toolName });
1762
+ const logger11 = config.logger ?? createLogger({ tool: config.toolName });
1758
1763
  const mode = config.executionMode ?? "read-only";
1759
1764
  return async (args) => {
1760
1765
  const ctxOpts = {
@@ -1762,7 +1767,7 @@ function createSecureHandler(handler, config) {
1762
1767
  ...config.callerInfo && { caller: config.callerInfo }
1763
1768
  };
1764
1769
  const requestContext = createRequestContext(ctxOpts);
1765
- const requestLogger = logger8.child(contextForLogging(requestContext));
1770
+ const requestLogger = logger11.child(contextForLogging(requestContext));
1766
1771
  requestLogger.info("Tool invocation started");
1767
1772
  const { error: preCheckError, sanitizedArgs } = runPreChecks(
1768
1773
  config,
@@ -2225,7 +2230,7 @@ var ClaudeAdapter = class extends BaseAdapter {
2225
2230
  */
2226
2231
  async executeCompletion(request) {
2227
2232
  const params = this.buildRequestParams(request);
2228
- const response = await this.client.messages.create(params);
2233
+ const response = request.signal !== void 0 ? await this.client.messages.create(params, { signal: request.signal }) : await this.client.messages.create(params);
2229
2234
  return this.mapResponse(response);
2230
2235
  }
2231
2236
  /**
@@ -2360,10 +2365,10 @@ var ClaudeAdapter = class extends BaseAdapter {
2360
2365
  return this.modelsCache.value;
2361
2366
  }
2362
2367
  if (this.modelsInFlight !== null) return this.modelsInFlight;
2363
- const inFlight = this.fetchModels();
2364
- this.modelsInFlight = inFlight;
2368
+ const inFlight2 = this.fetchModels();
2369
+ this.modelsInFlight = inFlight2;
2365
2370
  try {
2366
- const value = await inFlight;
2371
+ const value = await inFlight2;
2367
2372
  this.modelsCache = { value, fetchedAt: Date.now() };
2368
2373
  return value;
2369
2374
  } finally {
@@ -2463,13 +2468,13 @@ var SdkAdapter = class extends BaseAdapter {
2463
2468
  customBaseUrl;
2464
2469
  /** Inflight init promise for coalescing concurrent calls (Issue #1438). */
2465
2470
  initPromise;
2466
- constructor(config, logger8) {
2471
+ constructor(config, logger11) {
2467
2472
  const apiKey = resolveApiKey(config.providerId, config.apiKey);
2468
2473
  super({
2469
2474
  providerId: `sdk-${config.providerId}`,
2470
2475
  modelId: config.modelId,
2471
2476
  capabilities: [ModelCapability.COMPLETION, ModelCapability.STREAMING],
2472
- logger: logger8 ?? createLogger({ adapter: `sdk-${config.providerId}` }),
2477
+ logger: logger11 ?? createLogger({ adapter: `sdk-${config.providerId}` }),
2473
2478
  ...apiKey !== void 0 ? { apiKey } : {},
2474
2479
  ...config.timeout !== void 0 ? { timeout: config.timeout } : {},
2475
2480
  ...config.maxRetries !== void 0 ? { maxRetries: config.maxRetries } : {}
@@ -2649,19 +2654,19 @@ var SdkAdapter = class extends BaseAdapter {
2649
2654
 
2650
2655
  // src/adapters/auto-adapter.ts
2651
2656
  var defaultLogger = createLogger({ component: "auto-adapter" });
2652
- function resolveCache(config, logger8) {
2657
+ function resolveCache(config, logger11) {
2653
2658
  if (config.cache !== void 0) {
2654
2659
  return config.cache;
2655
2660
  }
2656
2661
  const enableCache = config.enableCache ?? true;
2657
- return enableCache ? createCliDetectionCache({ logger: logger8 }) : void 0;
2662
+ return enableCache ? createCliDetectionCache({ logger: logger11 }) : void 0;
2658
2663
  }
2659
- async function tryCliAdapter(config, logger8, cache) {
2664
+ async function tryCliAdapter(config, logger11, cache) {
2660
2665
  const preferredCli = config.preferredCli;
2661
2666
  const bridgeConfig = config.defaultCliTimeoutMs !== void 0 ? { defaultTimeoutMs: config.defaultCliTimeoutMs } : void 0;
2662
2667
  if (preferredCli !== void 0 && await isCliAvailable(preferredCli, cache)) {
2663
- logger8.info("Using preferred CLI", { cli: preferredCli });
2664
- const cliAdapter2 = createCliAdapter({ cli: preferredCli, logger: logger8 });
2668
+ logger11.info("Using preferred CLI", { cli: preferredCli });
2669
+ const cliAdapter2 = createCliAdapter({ cli: preferredCli, logger: logger11 });
2665
2670
  await cliAdapter2.initialize();
2666
2671
  return {
2667
2672
  adapter: createCliToModelAdapter(cliAdapter2, bridgeConfig),
@@ -2673,15 +2678,15 @@ async function tryCliAdapter(config, logger8, cache) {
2673
2678
  }
2674
2679
  const availableClis = await getAvailableClis(cache);
2675
2680
  if (availableClis.length === 0) {
2676
- logger8.info("No CLI adapters available");
2681
+ logger11.info("No CLI adapters available");
2677
2682
  return null;
2678
2683
  }
2679
2684
  const selectedCli = availableClis[0];
2680
2685
  if (selectedCli === void 0) {
2681
2686
  return null;
2682
2687
  }
2683
- logger8.info("Auto-selected CLI", { cli: selectedCli, available: availableClis });
2684
- 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 });
2685
2690
  await cliAdapter.initialize();
2686
2691
  return {
2687
2692
  adapter: createCliToModelAdapter(cliAdapter, bridgeConfig),
@@ -2695,13 +2700,13 @@ function resolveApiKeyFromEnv(configKey, envVar) {
2695
2700
  const key = configKey ?? process.env[envVar];
2696
2701
  return key !== void 0 && key.length > 0 ? key : void 0;
2697
2702
  }
2698
- function tryApiAdapter(config, logger8) {
2703
+ function tryApiAdapter(config, logger11) {
2699
2704
  const claudeModelId = getCliModelName(getDefaultModelForCli("claude"));
2700
2705
  const codexModelId = getCliModelName(getDefaultModelForCli("codex"));
2701
2706
  const geminiModelId = getCliModelName(getDefaultModelForCli("gemini"));
2702
2707
  const anthropicKey = resolveApiKeyFromEnv(config.anthropicApiKey, "ANTHROPIC_API_KEY");
2703
2708
  if (anthropicKey !== void 0) {
2704
- logger8.info("Using Anthropic API adapter", { model: claudeModelId });
2709
+ logger11.info("Using Anthropic API adapter", { model: claudeModelId });
2705
2710
  return {
2706
2711
  adapter: createClaudeAdapter({ modelId: claudeModelId, apiKey: anthropicKey }),
2707
2712
  source: "api",
@@ -2711,7 +2716,7 @@ function tryApiAdapter(config, logger8) {
2711
2716
  }
2712
2717
  const openaiKey = resolveApiKeyFromEnv(config.openaiApiKey, "OPENAI_API_KEY");
2713
2718
  if (openaiKey !== void 0) {
2714
- logger8.info("Using OpenAI API adapter (AI SDK)", { model: codexModelId });
2719
+ logger11.info("Using OpenAI API adapter (AI SDK)", { model: codexModelId });
2715
2720
  return {
2716
2721
  adapter: new SdkAdapter({ providerId: "openai", modelId: codexModelId, apiKey: openaiKey }),
2717
2722
  source: "api",
@@ -2721,7 +2726,7 @@ function tryApiAdapter(config, logger8) {
2721
2726
  }
2722
2727
  const googleKey = resolveApiKeyFromEnv(config.googleApiKey, "GOOGLE_AI_API_KEY");
2723
2728
  if (googleKey !== void 0) {
2724
- logger8.info("Using Google AI API adapter (AI SDK)", { model: geminiModelId });
2729
+ logger11.info("Using Google AI API adapter (AI SDK)", { model: geminiModelId });
2725
2730
  return {
2726
2731
  adapter: new SdkAdapter({
2727
2732
  providerId: "google",
@@ -2733,19 +2738,19 @@ function tryApiAdapter(config, logger8) {
2733
2738
  reason: `Using Google AI API via AI SDK (model: ${geminiModelId})`
2734
2739
  };
2735
2740
  }
2736
- const custom = tryCustomOpenAiAdapter(logger8);
2741
+ const custom = tryCustomOpenAiAdapter(logger11);
2737
2742
  if (custom !== null) return custom;
2738
- logger8.info("No API keys available for any provider");
2743
+ logger11.info("No API keys available for any provider");
2739
2744
  return null;
2740
2745
  }
2741
- function tryCustomOpenAiAdapter(logger8) {
2746
+ function tryCustomOpenAiAdapter(logger11) {
2742
2747
  const customKey = resolveApiKeyFromEnv(void 0, "NEXUS_CUSTOM_API_KEY");
2743
2748
  const customBaseUrl = process.env["NEXUS_CUSTOM_API_BASE_URL"];
2744
2749
  if (customKey === void 0 || customBaseUrl === void 0 || customBaseUrl === "") {
2745
2750
  return null;
2746
2751
  }
2747
2752
  const customModelId = process.env["NEXUS_CUSTOM_MODEL"] ?? CUSTOM_API_DEFAULT_MODEL;
2748
- logger8.info("Using custom-openai SDK adapter", {
2753
+ logger11.info("Using custom-openai SDK adapter", {
2749
2754
  model: customModelId,
2750
2755
  baseUrl: customBaseUrl
2751
2756
  });
@@ -2761,52 +2766,52 @@ function tryCustomOpenAiAdapter(logger8) {
2761
2766
  reason: `Using custom OpenAI-compatible gateway at ${customBaseUrl} (model: ${customModelId})`
2762
2767
  };
2763
2768
  }
2764
- async function selectCliFirst(config, logger8, cache) {
2765
- const cliResult = await tryCliAdapter(config, logger8, cache);
2769
+ async function selectCliFirst(config, logger11, cache) {
2770
+ const cliResult = await tryCliAdapter(config, logger11, cache);
2766
2771
  if (cliResult !== null) return cliResult;
2767
- const apiResult = tryApiAdapter(config, logger8);
2772
+ const apiResult = tryApiAdapter(config, logger11);
2768
2773
  if (apiResult !== null) return apiResult;
2769
2774
  throw new Error(
2770
2775
  "No adapters available. Install a CLI (claude/gemini/codex) or set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_API_KEY."
2771
2776
  );
2772
2777
  }
2773
- async function selectApiFirst(config, logger8, cache) {
2774
- const apiResult = tryApiAdapter(config, logger8);
2778
+ async function selectApiFirst(config, logger11, cache) {
2779
+ const apiResult = tryApiAdapter(config, logger11);
2775
2780
  if (apiResult !== null) return apiResult;
2776
- const cliResult = await tryCliAdapter(config, logger8, cache);
2781
+ const cliResult = await tryCliAdapter(config, logger11, cache);
2777
2782
  if (cliResult !== null) return cliResult;
2778
2783
  throw new Error(
2779
2784
  "No adapters available. Set ANTHROPIC_API_KEY/OPENAI_API_KEY/GOOGLE_AI_API_KEY or install a CLI (claude/gemini/codex)."
2780
2785
  );
2781
2786
  }
2782
- async function selectCliOnly(config, logger8, cache) {
2783
- const cliResult = await tryCliAdapter(config, logger8, cache);
2787
+ async function selectCliOnly(config, logger11, cache) {
2788
+ const cliResult = await tryCliAdapter(config, logger11, cache);
2784
2789
  if (cliResult !== null) return cliResult;
2785
2790
  throw new Error(
2786
2791
  "No CLI adapters available. Install and authenticate claude, gemini, or codex CLI."
2787
2792
  );
2788
2793
  }
2789
- function selectApiOnly(config, logger8) {
2790
- const apiResult = tryApiAdapter(config, logger8);
2794
+ function selectApiOnly(config, logger11) {
2795
+ const apiResult = tryApiAdapter(config, logger11);
2791
2796
  if (apiResult !== null) return apiResult;
2792
2797
  throw new Error(
2793
2798
  "No API key available. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_API_KEY."
2794
2799
  );
2795
2800
  }
2796
2801
  async function createAutoAdapter(config = {}) {
2797
- const logger8 = config.logger ?? defaultLogger;
2802
+ const logger11 = config.logger ?? defaultLogger;
2798
2803
  const priority = config.priority ?? "cli-first";
2799
- const cache = resolveCache(config, logger8);
2800
- 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 });
2801
2806
  switch (priority) {
2802
2807
  case "cli-first":
2803
- return selectCliFirst(config, logger8, cache);
2808
+ return selectCliFirst(config, logger11, cache);
2804
2809
  case "api-first":
2805
- return selectApiFirst(config, logger8, cache);
2810
+ return selectApiFirst(config, logger11, cache);
2806
2811
  case "cli-only":
2807
- return selectCliOnly(config, logger8, cache);
2812
+ return selectCliOnly(config, logger11, cache);
2808
2813
  case "api-only":
2809
- return selectApiOnly(config, logger8);
2814
+ return selectApiOnly(config, logger11);
2810
2815
  default: {
2811
2816
  const exhaustive = priority;
2812
2817
  throw new Error(`Unknown priority: ${String(exhaustive)}`);
@@ -4402,21 +4407,21 @@ async function executeSingleVoteAttempt(role, proposal, adapter, timeoutMs) {
4402
4407
  }
4403
4408
  }
4404
4409
  async function executeWithRetries(opts) {
4405
- const { role, proposal, adapter, logger: logger8, timeoutMs, maxRetries } = opts;
4410
+ const { role, proposal, adapter, logger: logger11, timeoutMs, maxRetries } = opts;
4406
4411
  let lastError = "";
4407
4412
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
4408
4413
  if (attempt > 0) {
4409
4414
  const isRateLimit = isRateLimitError(lastError);
4410
4415
  const baseDelay = isRateLimit ? RATE_LIMIT_RETRY_DELAY_MS : INITIAL_RETRY_DELAY_MS;
4411
4416
  const delayMs = baseDelay * Math.pow(2, attempt - 1);
4412
- logger8.debug("Retrying vote execution", { role, attempt, delayMs, isRateLimit });
4417
+ logger11.debug("Retrying vote execution", { role, attempt, delayMs, isRateLimit });
4413
4418
  await delay(delayMs);
4414
4419
  }
4415
4420
  const attemptStart = Date.now();
4416
4421
  const result = await executeSingleVoteAttempt(role, proposal, adapter, timeoutMs);
4417
4422
  const attemptMs = Date.now() - attemptStart;
4418
4423
  if (result.ok) {
4419
- logger8.info("Vote attempt timing", {
4424
+ logger11.info("Vote attempt timing", {
4420
4425
  role,
4421
4426
  attempt: attempt + 1,
4422
4427
  attemptMs,
@@ -4426,14 +4431,14 @@ async function executeWithRetries(opts) {
4426
4431
  }
4427
4432
  lastError = result.error;
4428
4433
  const rateLimited = isRateLimitError(lastError);
4429
- logger8.info("Vote attempt timing", {
4434
+ logger11.info("Vote attempt timing", {
4430
4435
  role,
4431
4436
  attempt: attempt + 1,
4432
4437
  attemptMs,
4433
4438
  succeeded: false,
4434
4439
  rateLimited
4435
4440
  });
4436
- logger8.warn("Vote attempt failed", {
4441
+ logger11.warn("Vote attempt failed", {
4437
4442
  role,
4438
4443
  attempt: attempt + 1,
4439
4444
  maxRetries: maxRetries + 1,
@@ -4463,7 +4468,7 @@ async function launchVotesWithOverallDeadline(input) {
4463
4468
  proposal,
4464
4469
  roleAdapters,
4465
4470
  fallbackAdapter,
4466
- logger: logger8,
4471
+ logger: logger11,
4467
4472
  voteOptions,
4468
4473
  interDelay,
4469
4474
  overallDeadlineMs,
@@ -4475,12 +4480,12 @@ async function launchVotesWithOverallDeadline(input) {
4475
4480
  const adapter = roleAdapters.get(role) ?? fallbackAdapter;
4476
4481
  const elapsed = Date.now() - startedAt;
4477
4482
  const remaining = Math.max(1, overallDeadlineMs - elapsed);
4478
- return raceWithDeadline(voteFn(role, proposal, adapter, logger8, voteOptions), role, remaining);
4483
+ return raceWithDeadline(voteFn(role, proposal, adapter, logger11, voteOptions), role, remaining);
4479
4484
  });
4480
4485
  const results = await Promise.all(wrapped);
4481
4486
  const expired = results.filter((r) => r.source === "error" && r.error === DEADLINE_MESSAGE);
4482
4487
  if (expired.length > 0) {
4483
- logger8.warn("Consensus overall deadline reached; returning partial results", {
4488
+ logger11.warn("Consensus overall deadline reached; returning partial results", {
4484
4489
  totalRoles: roles.length,
4485
4490
  expiredRoles: expired.map((r) => r.role),
4486
4491
  overallDeadlineMs
@@ -4497,32 +4502,32 @@ function computeOverallConsensusDeadlineMs(timeoutMs, maxRetries, roleCount, int
4497
4502
  }
4498
4503
  var DEFAULT_INTER_AGENT_DELAY_MS = 2e3;
4499
4504
  var defaultLogger2 = createLogger({ component: "voter-agents" });
4500
- async function executeAgentVote(role, proposal, adapter, logger8, options) {
4505
+ async function executeAgentVote(role, proposal, adapter, logger11, options) {
4501
4506
  const start = getTimeProvider().now();
4502
4507
  const timeoutMs = options?.timeoutMs ?? resolveVoteTimeout();
4503
4508
  const maxRetries = options?.maxRetries ?? VOTE_TIMEOUTS.maxRetries;
4504
4509
  const allowSimulation = options?.allowSimulation ?? false;
4505
- logger8.info("Executing vote", { role, model: adapter.modelId, provider: adapter.providerId });
4510
+ logger11.info("Executing vote", { role, model: adapter.modelId, provider: adapter.providerId });
4506
4511
  const result = await executeWithRetries({
4507
4512
  role,
4508
4513
  proposal,
4509
4514
  adapter,
4510
- logger: logger8,
4515
+ logger: logger11,
4511
4516
  timeoutMs,
4512
4517
  maxRetries
4513
4518
  });
4514
4519
  const processingTimeMs = getTimeProvider().now() - start;
4515
4520
  if (result.ok) {
4516
- 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 });
4517
4522
  return { role, vote: result.vote, processingTimeMs, source: "llm", cli: adapter.providerId };
4518
4523
  }
4519
- logger8.error("Vote execution failed after all retries", void 0, {
4524
+ logger11.error("Vote execution failed after all retries", void 0, {
4520
4525
  role,
4521
4526
  model: adapter.modelId,
4522
4527
  errorMessage: result.error
4523
4528
  });
4524
4529
  if (allowSimulation) {
4525
- logger8.warn("Falling back to simulation (allowSimulation=true)", { role });
4530
+ logger11.warn("Falling back to simulation (allowSimulation=true)", { role });
4526
4531
  return createSimulationVoteResult(role, proposal, processingTimeMs, result.error);
4527
4532
  }
4528
4533
  return createErrorVoteResult(role, result.error, processingTimeMs);
@@ -4533,22 +4538,22 @@ var NoAdapterError = class extends Error {
4533
4538
  this.name = "NoAdapterError";
4534
4539
  }
4535
4540
  };
4536
- function resolveAdapter(options, logger8) {
4541
+ function resolveAdapter(options, logger11) {
4537
4542
  try {
4538
4543
  if (options.adapter !== void 0) return { adapter: options.adapter };
4539
- const registry = getGlobalRegistry({ logger: logger8 });
4544
+ const registry = getGlobalRegistry({ logger: logger11 });
4540
4545
  return { adapter: registry.getDefault() };
4541
4546
  } catch (error) {
4542
4547
  return { error: getErrorMessage(error) };
4543
4548
  }
4544
4549
  }
4545
- function warnIfCodexConcurrencyExceeded(roleAdapters, logger8) {
4550
+ function warnIfCodexConcurrencyExceeded(roleAdapters, logger11) {
4546
4551
  const codexBound = [...roleAdapters.values()].filter(
4547
4552
  (a) => a.name === "codex"
4548
4553
  ).length;
4549
4554
  const warning = checkCodexConcurrency(codexBound);
4550
4555
  if (warning !== null) {
4551
- logger8.warn("Codex concurrency limit may be exceeded", { detail: warning });
4556
+ logger11.warn("Codex concurrency limit may be exceeded", { detail: warning });
4552
4557
  }
4553
4558
  }
4554
4559
  function assignUniformAdapter(roles, adapter) {
@@ -4556,29 +4561,29 @@ function assignUniformAdapter(roles, adapter) {
4556
4561
  for (const role of roles) adapters.set(role, adapter);
4557
4562
  return adapters;
4558
4563
  }
4559
- function createCliAdapterMap(clis, logger8) {
4560
- const registry = getGlobalRegistry({ logger: logger8 });
4564
+ function createCliAdapterMap(clis, logger11) {
4565
+ const registry = getGlobalRegistry({ logger: logger11 });
4561
4566
  const result = /* @__PURE__ */ new Map();
4562
4567
  for (const cli of clis) {
4563
4568
  result.set(cli, registry.getAdapterForCli(cli));
4564
4569
  }
4565
4570
  return result;
4566
4571
  }
4567
- async function resolveDiverseAdapters(roles, logger8, fallbackAdapter) {
4572
+ async function resolveDiverseAdapters(roles, logger11, fallbackAdapter) {
4568
4573
  let availableClis;
4569
4574
  try {
4570
4575
  availableClis = await getAvailableClis();
4571
4576
  } catch (e) {
4572
- 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", {
4573
4578
  error: String(e)
4574
4579
  });
4575
4580
  availableClis = [];
4576
4581
  }
4577
4582
  if (availableClis.length <= 1) {
4578
- logger8.info("Using single adapter for all roles", { cliCount: availableClis.length });
4583
+ logger11.info("Using single adapter for all roles", { cliCount: availableClis.length });
4579
4584
  return assignUniformAdapter(roles, fallbackAdapter);
4580
4585
  }
4581
- const cliAdapters = createCliAdapterMap(availableClis, logger8);
4586
+ const cliAdapters = createCliAdapterMap(availableClis, logger11);
4582
4587
  if (cliAdapters.size <= 1) return assignUniformAdapter(roles, fallbackAdapter);
4583
4588
  const cliList = [...cliAdapters.entries()];
4584
4589
  const adapters = /* @__PURE__ */ new Map();
@@ -4590,7 +4595,7 @@ async function resolveDiverseAdapters(roles, logger8, fallbackAdapter) {
4590
4595
  adapters.set(role, entry[1]);
4591
4596
  assignments[role] = entry[0];
4592
4597
  }
4593
- logger8.info("Diverse adapters assigned", {
4598
+ logger11.info("Diverse adapters assigned", {
4594
4599
  cliCount: cliAdapters.size,
4595
4600
  clis: [...cliAdapters.keys()],
4596
4601
  roleAssignments: assignments
@@ -4598,7 +4603,7 @@ async function resolveDiverseAdapters(roles, logger8, fallbackAdapter) {
4598
4603
  return adapters;
4599
4604
  }
4600
4605
  async function launchStaggeredVotes(input) {
4601
- const { roles, proposal, roleAdapters, fallbackAdapter, logger: logger8, voteOptions, interDelay } = input;
4606
+ const { roles, proposal, roleAdapters, fallbackAdapter, logger: logger11, voteOptions, interDelay } = input;
4602
4607
  const computedDeadlineMs = computeOverallConsensusDeadlineMs(
4603
4608
  voteOptions.timeoutMs,
4604
4609
  voteOptions.maxRetries,
@@ -4607,7 +4612,7 @@ async function launchStaggeredVotes(input) {
4607
4612
  );
4608
4613
  const overallDeadlineMs = getMcpSafeDeadlineMs(computedDeadlineMs, "consensus_vote");
4609
4614
  if (overallDeadlineMs < computedDeadlineMs) {
4610
- logger8.debug("Consensus deadline clamped to MCP wrapper timeout", {
4615
+ logger11.debug("Consensus deadline clamped to MCP wrapper timeout", {
4611
4616
  computedDeadlineMs,
4612
4617
  overallDeadlineMs
4613
4618
  });
@@ -4617,7 +4622,7 @@ async function launchStaggeredVotes(input) {
4617
4622
  proposal,
4618
4623
  roleAdapters,
4619
4624
  fallbackAdapter,
4620
- logger: logger8,
4625
+ logger: logger11,
4621
4626
  voteOptions,
4622
4627
  interDelay,
4623
4628
  overallDeadlineMs,
@@ -4625,27 +4630,27 @@ async function launchStaggeredVotes(input) {
4625
4630
  });
4626
4631
  }
4627
4632
  async function collectRealVotes(options) {
4628
- const logger8 = options.logger ?? defaultLogger2;
4633
+ const logger11 = options.logger ?? defaultLogger2;
4629
4634
  const { roles, proposal, simulate, allowSimulation } = options;
4630
4635
  const timeoutMs = options.timeoutMs ?? resolveVoteTimeout();
4631
4636
  const maxRetries = options.maxRetries ?? VOTE_TIMEOUTS.maxRetries;
4632
4637
  if (simulate === true) {
4633
- logger8.info("Using simulation mode (explicitly requested)");
4638
+ logger11.info("Using simulation mode (explicitly requested)");
4634
4639
  return createSimulatedVotes(roles, proposal);
4635
4640
  }
4636
- const adapterResult = resolveAdapter(options, logger8);
4641
+ const adapterResult = resolveAdapter(options, logger11);
4637
4642
  if ("error" in adapterResult) {
4638
- 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 });
4639
4644
  if (allowSimulation === true) {
4640
- logger8.warn("Falling back to simulation (allowSimulation=true)");
4645
+ logger11.warn("Falling back to simulation (allowSimulation=true)");
4641
4646
  return createSimulatedVotes(roles, proposal, "No adapter available");
4642
4647
  }
4643
4648
  throw new NoAdapterError(
4644
4649
  `No adapter available for voting: ${adapterResult.error}. Install a CLI (claude/gemini/codex) or set ANTHROPIC_API_KEY.`
4645
4650
  );
4646
4651
  }
4647
- const roleAdapters = options.adapter !== void 0 ? assignUniformAdapter(roles, adapterResult.adapter) : await resolveDiverseAdapters(roles, logger8, adapterResult.adapter);
4648
- warnIfCodexConcurrencyExceeded(roleAdapters, logger8);
4652
+ const roleAdapters = options.adapter !== void 0 ? assignUniformAdapter(roles, adapterResult.adapter) : await resolveDiverseAdapters(roles, logger11, adapterResult.adapter);
4653
+ warnIfCodexConcurrencyExceeded(roleAdapters, logger11);
4649
4654
  const voteOptions = { timeoutMs, maxRetries, allowSimulation: allowSimulation ?? false };
4650
4655
  const interDelay = options.interAgentDelayMs ?? DEFAULT_INTER_AGENT_DELAY_MS;
4651
4656
  return launchStaggeredVotes({
@@ -4653,7 +4658,7 @@ async function collectRealVotes(options) {
4653
4658
  proposal,
4654
4659
  roleAdapters,
4655
4660
  fallbackAdapter: adapterResult.adapter,
4656
- logger: logger8,
4661
+ logger: logger11,
4657
4662
  voteOptions,
4658
4663
  interDelay
4659
4664
  });
@@ -5642,11 +5647,11 @@ var ConsensusEngine = class {
5642
5647
  logger;
5643
5648
  metrics;
5644
5649
  voterExpansionCallback;
5645
- constructor(config, logger8) {
5650
+ constructor(config, logger11) {
5646
5651
  this.config = { ...DEFAULT_CONSENSUS_CONFIG, ...config };
5647
5652
  this.cacheConfig = { ...DEFAULT_PROPOSAL_CACHE_CONFIG, ...config?.proposalCache };
5648
5653
  this.quorumConfig = { ...DEFAULT_INCREMENTAL_QUORUM_CONFIG, ...config?.incrementalQuorum };
5649
- this.logger = logger8 ?? createLogger({ component: "ConsensusEngine" });
5654
+ this.logger = logger11 ?? createLogger({ component: "ConsensusEngine" });
5650
5655
  this.strategyFactory = new VotingStrategyFactory();
5651
5656
  this.metrics = this.createInitialMetrics();
5652
5657
  }
@@ -6088,8 +6093,8 @@ var ConsensusEngine = class {
6088
6093
  this.logger.debug("Proposal cache cleared");
6089
6094
  }
6090
6095
  };
6091
- function createConsensusEngine(config, logger8) {
6092
- return new ConsensusEngine(config, logger8);
6096
+ function createConsensusEngine(config, logger11) {
6097
+ return new ConsensusEngine(config, logger11);
6093
6098
  }
6094
6099
 
6095
6100
  // src/consensus/quorum-validator.ts
@@ -6097,8 +6102,8 @@ var DEFAULT_MIN_TRUST = 0.3;
6097
6102
  var DEFAULT_MIN_WEIGHT = 0.1;
6098
6103
  var QuorumValidator = class {
6099
6104
  logger;
6100
- constructor(logger8) {
6101
- this.logger = logger8 ?? createLogger({ component: "QuorumValidator" });
6105
+ constructor(logger11) {
6106
+ this.logger = logger11 ?? createLogger({ component: "QuorumValidator" });
6102
6107
  }
6103
6108
  validateQuorum(input) {
6104
6109
  const { votes, config } = input;
@@ -6325,8 +6330,8 @@ var QuorumValidator = class {
6325
6330
  };
6326
6331
  }
6327
6332
  };
6328
- function createQuorumValidator(logger8) {
6329
- return new QuorumValidator(logger8);
6333
+ function createQuorumValidator(logger11) {
6334
+ return new QuorumValidator(logger11);
6330
6335
  }
6331
6336
 
6332
6337
  // src/consensus/voting-protocol-helpers.ts
@@ -7906,6 +7911,35 @@ var ConsensusVoteInputSchema = z9.object({
7906
7911
  quickMode: z9.boolean().optional().default(false).describe("Use 3 agents instead of 5 for faster execution"),
7907
7912
  simulateVotes: z9.boolean().optional().default(false).describe(
7908
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."
7909
7943
  )
7910
7944
  });
7911
7945
  function toAgentVoteSummary(result) {
@@ -8012,10 +8046,10 @@ import { appendFileSync as appendFileSync3, readFileSync as readFileSync2, write
8012
8046
  var PersistentOutcomeStore = class extends OutcomeStore {
8013
8047
  filePath;
8014
8048
  logger;
8015
- constructor(config, logger8) {
8049
+ constructor(config, logger11) {
8016
8050
  super(config);
8017
8051
  this.filePath = config?.filePath ?? getOutcomesFile();
8018
- this.logger = logger8 ?? createLogger({ component: "PersistentOutcomeStore" });
8052
+ this.logger = logger11 ?? createLogger({ component: "PersistentOutcomeStore" });
8019
8053
  const dataDir = config?.dataDir;
8020
8054
  ensureLearningDir(dataDir);
8021
8055
  this.hydrate();
@@ -8209,11 +8243,11 @@ var WARNED = /* @__PURE__ */ new Set();
8209
8243
  function isTestRunner() {
8210
8244
  return process.env.VITEST === "true" || process.env.NODE_ENV === "test";
8211
8245
  }
8212
- function warnIfSimulatedOutsideTests(toolName, logger8) {
8246
+ function warnIfSimulatedOutsideTests(toolName, logger11) {
8213
8247
  if (isTestRunner()) return;
8214
8248
  if (WARNED.has(toolName)) return;
8215
8249
  WARNED.add(toolName);
8216
- logger8.warn(
8250
+ logger11.warn(
8217
8251
  `[${toolName}] simulateVotes=true: output is RANDOM and reserved for tests/demos. Do not treat the result as a real decision.`
8218
8252
  );
8219
8253
  }
@@ -8457,6 +8491,20 @@ var TOOL_ANNOTATIONS = {
8457
8491
  idempotentHint: true,
8458
8492
  openWorldHint: false
8459
8493
  },
8494
+ /** Reads job-result sidecar file for an async-mode dispatch (#3042 / #2631). */
8495
+ get_job_result: {
8496
+ readOnlyHint: true,
8497
+ destructiveHint: false,
8498
+ idempotentHint: true,
8499
+ openWorldHint: false
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
+ },
8460
8508
  /** Verifies hash chain of audit log files. */
8461
8509
  verify_audit_chain: {
8462
8510
  readOnlyHint: true,
@@ -8530,7 +8578,321 @@ function getToolAnnotations(name) {
8530
8578
  return a;
8531
8579
  }
8532
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
+
8533
8894
  // src/mcp/tools/consensus-vote.ts
8895
+ import { randomUUID as randomUUID4 } from "crypto";
8534
8896
  var persistentCorrelationTracker;
8535
8897
  function getOrCreateCorrelationTracker() {
8536
8898
  persistentCorrelationTracker ??= createPersistentCorrelationTracker();
@@ -8639,22 +9001,22 @@ async function processVotesThroughEngine(engineVotes, proposal, algorithm) {
8639
9001
  });
8640
9002
  return resultRes.value;
8641
9003
  }
8642
- function runHigherOrderVoting(strategy, voteMap, logger8) {
9004
+ function runHigherOrderVoting(strategy, voteMap, logger11) {
8643
9005
  if (strategy !== "higher_order") return void 0;
8644
9006
  const hovStrategy = new HigherOrderVotingStrategy();
8645
9007
  const tracker = getOrCreateCorrelationTracker();
8646
9008
  const result = hovStrategy.aggregate(voteMap, tracker);
8647
- logger8.info("Higher-Order Voting complete", {
9009
+ logger11.info("Higher-Order Voting complete", {
8648
9010
  method: result.method,
8649
9011
  decision: result.decision,
8650
9012
  posteriorApproval: result.posteriorApproval.toFixed(3)
8651
9013
  });
8652
9014
  return result;
8653
9015
  }
8654
- function recordVotesToTracker(votes, voteMap, outcome, logger8) {
9016
+ function recordVotesToTracker(votes, voteMap, outcome, logger11) {
8655
9017
  const allVotesReal = votes.every((v) => v.source === "llm");
8656
9018
  if (!allVotesReal) {
8657
- logger8.warn("Skipping correlation recording due to non-LLM votes", {
9019
+ logger11.warn("Skipping correlation recording due to non-LLM votes", {
8658
9020
  count: votes.filter((v) => v.source !== "llm").length
8659
9021
  });
8660
9022
  return;
@@ -8662,16 +9024,16 @@ function recordVotesToTracker(votes, voteMap, outcome, logger8) {
8662
9024
  const tracker = getOrCreateCorrelationTracker();
8663
9025
  const id = `consensus-${String(getTimeProvider().now())}-${getRandomProvider().random().toString(36).slice(2, 9)}`;
8664
9026
  tracker.recordProposalVotes(id, voteMap, outcome);
8665
- logger8.debug("Recorded votes to tracker", { proposalId: id, outcome });
9027
+ logger11.debug("Recorded votes to tracker", { proposalId: id, outcome });
8666
9028
  try {
8667
9029
  const persisted = createPersistedProposal(id, voteMap, outcome);
8668
9030
  const saveResult = saveCorrelationData([persisted]);
8669
9031
  if (!saveResult.ok) {
8670
- logger8.warn("Failed to persist correlation data", { error: saveResult.error.message });
9032
+ logger11.warn("Failed to persist correlation data", { error: saveResult.error.message });
8671
9033
  }
8672
9034
  } catch (error) {
8673
9035
  const message = getErrorMessage(error);
8674
- logger8.warn("Error persisting correlation data", { error: message });
9036
+ logger11.warn("Error persisting correlation data", { error: message });
8675
9037
  }
8676
9038
  }
8677
9039
  async function processVotesWithCascade(engineVotes, opts) {
@@ -8696,7 +9058,7 @@ async function processVotesWithCascade(engineVotes, opts) {
8696
9058
  var CONTRARIAN_ESCALATION_THRESHOLD = 0.8;
8697
9059
  async function runContrarianCheck(proposal, log) {
8698
9060
  try {
8699
- const { executeExpert } = await import("./expert-bridge-7LPGCPPR.js");
9061
+ const { executeExpert } = await import("./expert-bridge-22UVN5TB.js");
8700
9062
  const prompt = [
8701
9063
  "You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.",
8702
9064
  "Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.",
@@ -8746,23 +9108,23 @@ function buildPolicyShortCircuitResult(args) {
8746
9108
  strategy: args.strategy
8747
9109
  };
8748
9110
  }
8749
- async function maybeEscalateContrarian(input, outcome, logger8, opts) {
9111
+ async function maybeEscalateContrarian(input, outcome, logger11, opts) {
8750
9112
  if (!input.quickMode || outcome !== "approved" || input.simulateVotes) return void 0;
8751
- const escalation = await runContrarianCheck(input.proposal, logger8);
9113
+ const escalation = await runContrarianCheck(input.proposal, logger11);
8752
9114
  if (!escalation.shouldEscalate) return void 0;
8753
- logger8.warn("Contrarian escalation: re-running with full vote", {
9115
+ logger11.warn("Contrarian escalation: re-running with full vote", {
8754
9116
  reason: escalation.reason,
8755
9117
  confidence: escalation.confidence
8756
9118
  });
8757
- return executeVoting({ ...input, quickMode: false }, logger8, opts);
9119
+ return executeVoting({ ...input, quickMode: false }, logger11, opts);
8758
9120
  }
8759
- async function executeVoting(input, logger8, opts) {
9121
+ async function executeVoting(input, logger11, opts) {
8760
9122
  const strategy = resolveStrategy(input);
8761
9123
  const algorithm = strategyToAlgorithm(strategy);
8762
9124
  const roles = getVoterRoles(input.quickMode);
8763
9125
  const startTime = getTimeProvider().now();
8764
9126
  const errorPolicy = input.errorPolicy ?? getDefaultErrorPolicy(strategy);
8765
- logger8.info("Starting consensus vote", {
9127
+ logger11.info("Starting consensus vote", {
8766
9128
  strategy,
8767
9129
  algorithm,
8768
9130
  roleCount: roles.length,
@@ -8784,7 +9146,7 @@ async function executeVoting(input, logger8, opts) {
8784
9146
  errorPolicy,
8785
9147
  reason: policyDecision.reason ?? "error policy short-circuit",
8786
9148
  startTime,
8787
- logger: logger8
9149
+ logger: logger11
8788
9150
  });
8789
9151
  }
8790
9152
  const { engineResult, voteMap, higherOrderResult, outcome, cascaded } = await processVotesWithCascade(policyDecision.engineVotes, {
@@ -8792,10 +9154,10 @@ async function executeVoting(input, logger8, opts) {
8792
9154
  proposal: input.proposal,
8793
9155
  algorithm,
8794
9156
  strategy,
8795
- log: logger8
9157
+ log: logger11
8796
9158
  });
8797
- recordVotesToTracker(votes, voteMap, outcome, logger8);
8798
- const escalated = await maybeEscalateContrarian(input, outcome, logger8, opts);
9159
+ recordVotesToTracker(votes, voteMap, outcome, logger11);
9160
+ const escalated = await maybeEscalateContrarian(input, outcome, logger11, opts);
8799
9161
  if (escalated !== void 0) return escalated;
8800
9162
  return finalizeVotingResult({
8801
9163
  input,
@@ -8807,7 +9169,7 @@ async function executeVoting(input, logger8, opts) {
8807
9169
  outcome,
8808
9170
  cascaded,
8809
9171
  startTime,
8810
- logger: logger8
9172
+ logger: logger11
8811
9173
  });
8812
9174
  }
8813
9175
  function finalizeVotingResult(args) {
@@ -8831,15 +9193,15 @@ function finalizeVotingResult(args) {
8831
9193
  return result;
8832
9194
  }
8833
9195
  async function handleConsensusVote(deps, args) {
8834
- const logger8 = deps.logger ?? createLogger({ tool: "consensus_vote" });
8835
- if (args.simulateVotes) warnIfSimulatedOutsideTests("consensus_vote", logger8);
9196
+ const logger11 = deps.logger ?? createLogger({ tool: "consensus_vote" });
9197
+ if (args.simulateVotes) warnIfSimulatedOutsideTests("consensus_vote", logger11);
8836
9198
  try {
8837
- const result = await executeVoting(args, logger8);
9199
+ const result = await executeVoting(args, logger11);
8838
9200
  const strategy = args.strategy ?? "simple_majority";
8839
9201
  const errorVotes = result.votes.filter((v) => v.source === "error");
8840
9202
  if (errorVotes.length === result.votes.length && result.votes.length > 0) {
8841
9203
  const failures = errorVotes.map((v) => `${v.role}: ${v.error ?? "unknown error"}`).join("; ");
8842
- logger8.warn("All voters failed", { failureCount: errorVotes.length, failures });
9204
+ logger11.warn("All voters failed", { failureCount: errorVotes.length, failures });
8843
9205
  recordVoteError(args.proposal, `All ${String(errorVotes.length)} voters failed: ${failures}`);
8844
9206
  return {
8845
9207
  ok: false,
@@ -8857,11 +9219,109 @@ async function handleConsensusVote(deps, args) {
8857
9219
  } catch (error) {
8858
9220
  const message = getErrorMessage(error);
8859
9221
  const cause = error instanceof Error ? error : new Error(message);
8860
- logger8.error("Consensus vote failed", cause);
9222
+ logger11.error("Consensus vote failed", cause);
8861
9223
  recordVoteError(args.proposal, message);
8862
9224
  return { ok: false, error: `Voting failed: ${message}` };
8863
9225
  }
8864
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
+ }
8865
9325
  function createConsensusVoteHandler(deps) {
8866
9326
  const notifier = deps.notifier ?? NOOP_NOTIFIER;
8867
9327
  return async (args, ctx) => {
@@ -8875,63 +9335,48 @@ function createConsensusVoteHandler(deps) {
8875
9335
  const strategy = validationResult.data.strategy ?? "simple_majority";
8876
9336
  ctx.logger.debug("Starting consensus vote", {
8877
9337
  strategy,
8878
- quickMode: validationResult.data.quickMode
9338
+ quickMode: validationResult.data.quickMode,
9339
+ ...validationResult.data.mode !== void 0 ? { mode: validationResult.data.mode } : {}
8879
9340
  });
8880
9341
  notifier.info("consensus_vote", {
8881
9342
  event: "vote_start",
8882
9343
  proposalLength: validationResult.data.proposal.length,
8883
9344
  strategy
8884
9345
  });
8885
- const result = await withProgressHeartbeat(
8886
- "consensus_vote",
8887
- notifier,
8888
- () => handleConsensusVote(deps, validationResult.data)
8889
- );
8890
- if (!result.ok) {
8891
- return toolStructuredError({ errorCategory: "internal", message: result.error });
8892
- }
8893
- for (const vote of result.value.votes) {
8894
- notifier.debug("consensus_vote", {
8895
- event: "vote_collected",
8896
- role: vote.role,
8897
- 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
8898
9352
  });
9353
+ return asyncResult;
8899
9354
  }
8900
- notifier.info("consensus_vote", {
8901
- event: "vote_complete",
8902
- decision: result.value.decision,
8903
- approvalPercentage: result.value.approvalPercentage,
8904
- voteCount: result.value.votes.length
8905
- });
8906
- const data = result.value;
8907
- return {
8908
- ...toolSuccess(JSON.stringify(result.value, null, 2)),
8909
- structuredContent: data
8910
- };
9355
+ return runSyncConsensusVote(deps, notifier, validationResult.data);
8911
9356
  };
8912
9357
  }
8913
9358
  var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
8914
- proposal: z10.string(),
9359
+ proposal: z12.string(),
8915
9360
  strategy: VotingStrategySchema,
8916
- decision: z10.enum(["approved", "rejected", "no_quorum"]),
8917
- approvalPercentage: z10.number(),
8918
- voteCounts: z10.object({
8919
- approve: z10.number(),
8920
- reject: z10.number(),
8921
- abstain: z10.number(),
8922
- 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()
8923
9368
  }),
8924
- votes: z10.array(
8925
- z10.object({
8926
- role: z10.string().max(100),
8927
- decision: z10.enum(["approve", "reject", "abstain"]),
8928
- confidence: z10.number(),
8929
- reasoning: z10.string().max(4e3),
8930
- simulated: z10.boolean(),
8931
- error: z10.boolean(),
8932
- modelUsed: z10.string().max(100).optional(),
8933
- rejectionCategories: z10.array(
8934
- 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([
8935
9380
  "YAGNI",
8936
9381
  "DRY_VIOLATION",
8937
9382
  "OVER_ENGINEERING",
@@ -8944,42 +9389,42 @@ var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
8944
9389
  })
8945
9390
  ),
8946
9391
  threshold: VoteThresholdSchema.optional(),
8947
- durationMs: z10.number(),
8948
- simulateVotes: z10.boolean(),
8949
- higherOrderMetadata: z10.object({
8950
- posteriorApproval: z10.number(),
8951
- posteriorRejection: z10.number(),
8952
- effectiveVoteCount: z10.number(),
8953
- method: z10.enum(["ow", "isp", "simple"]),
8954
- usedCorrelationData: z10.boolean(),
8955
- improvementOverBaseline: z10.number(),
8956
- downweightedAgents: z10.array(z10.string().max(100)).max(10),
8957
- 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)
8958
9403
  }).optional()
8959
9404
  };
8960
9405
  function registerConsensusVoteTool(server, deps) {
8961
- const logger8 = deps.logger ?? createLogger({ tool: "consensus_vote" });
9406
+ const logger11 = deps.logger ?? createLogger({ tool: "consensus_vote" });
8962
9407
  const notifier = deps.notifier ?? createMcpNotifier(server);
8963
9408
  const depsWithNotifier = { ...deps, notifier };
8964
9409
  const toolSchema = {
8965
- proposal: z10.string().min(1).max(MAX_PROPOSAL_LENGTH).describe("Proposal text to vote on"),
8966
- 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."),
8967
9412
  strategy: VotingStrategySchema.optional().describe(
8968
9413
  "Voting strategy: simple_majority (default), supermajority, unanimous, proof_of_learning, or higher_order"
8969
9414
  ),
8970
- quickMode: z10.boolean().optional().default(false).describe("Use 3 agents instead of 7"),
8971
- 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)")
8972
9417
  };
8973
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).";
8974
9419
  const secureHandler = createSecureHandler(createConsensusVoteHandler(depsWithNotifier), {
8975
9420
  toolName: "consensus_vote",
8976
9421
  rateLimiter: deps.rateLimiter,
8977
- logger: logger8
9422
+ logger: logger11
8978
9423
  });
8979
9424
  const timeoutMs = getToolTimeout("consensus_vote", deps.security);
8980
9425
  const wrappedHandler = wrapToolWithTimeout("consensus_vote", secureHandler, {
8981
9426
  timeoutMs,
8982
- logger: logger8
9427
+ logger: logger11
8983
9428
  });
8984
9429
  server.registerTool(
8985
9430
  "consensus_vote",
@@ -8989,9 +9434,9 @@ function registerConsensusVoteTool(server, deps) {
8989
9434
  outputSchema: CONSENSUS_VOTE_OUTPUT_SCHEMA,
8990
9435
  annotations: getToolAnnotations("consensus_vote")
8991
9436
  },
8992
- toSdkCallbackWithBudgetCheck(wrappedHandler, "consensus_vote", timeoutMs, logger8)
9437
+ toSdkCallbackWithBudgetCheck(wrappedHandler, "consensus_vote", timeoutMs, logger11)
8993
9438
  );
8994
- 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");
8995
9440
  }
8996
9441
 
8997
9442
  export {
@@ -9044,6 +9489,17 @@ export {
9044
9489
  toSdkCallbackWithBudgetCheck,
9045
9490
  getToolAnnotations,
9046
9491
  PersistentOutcomeStore,
9492
+ JobStatusSchema,
9493
+ writeJobPending,
9494
+ writeJobComplete,
9495
+ writeJobFailed,
9496
+ readJobResult,
9497
+ listJobs,
9498
+ registerIdempotentJob,
9499
+ shortCircuitOrFreshJobId,
9500
+ tryAcquire,
9501
+ release,
9502
+ suggestRetryAfterMs,
9047
9503
  DEFAULT_VOTE_TIMEOUT_MS,
9048
9504
  isRateLimitError,
9049
9505
  VOTER_ROLES,
@@ -9113,4 +9569,4 @@ export {
9113
9569
  CONSENSUS_VOTE_OUTPUT_SCHEMA,
9114
9570
  registerConsensusVoteTool
9115
9571
  };
9116
- //# sourceMappingURL=chunk-ODKIRXN7.js.map
9572
+ //# sourceMappingURL=chunk-IF6TXCSE.js.map