nexus-agents 2.151.1 → 2.152.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -520,7 +520,7 @@ import {
520
520
  validateWorkflow,
521
521
  validateWorkflowDependencies,
522
522
  withLogging
523
- } from "./chunk-IR7FP4SS.js";
523
+ } from "./chunk-4RJB246Z.js";
524
524
  import {
525
525
  OPENAI_MODELS,
526
526
  OPENAI_MODEL_ALIASES,
@@ -560,7 +560,7 @@ import {
560
560
  getKnownNexusVarNames,
561
561
  startStdioServer,
562
562
  validateNexusEnv
563
- } from "./chunk-SJFARLAQ.js";
563
+ } from "./chunk-GKZ3GPB3.js";
564
564
  import {
565
565
  CliCircuitBreakerIntegration,
566
566
  createCliCircuitBreakerIntegration
@@ -616,7 +616,7 @@ import {
616
616
  generateProposalId,
617
617
  parseAgentPairKey,
618
618
  registerConsensusVoteTool
619
- } from "./chunk-UIL37D2V.js";
619
+ } from "./chunk-447YUGJD.js";
620
620
  import "./chunk-XSA7VZCU.js";
621
621
  import "./chunk-7ZMOF54O.js";
622
622
  import {
@@ -5891,20 +5891,44 @@ var logger10 = createLogger({ component: "quality-pipeline" });
5891
5891
  // src/pipeline/iterative-consensus.ts
5892
5892
  var defaultLogger = createLogger({ component: "iterative-consensus" });
5893
5893
  var DEFAULT_MAX_ITERATIONS = 3;
5894
+ var DEFAULT_MAX_NO_QUORUM_RETRIES = 2;
5894
5895
  var DEFAULT_MAX_PROPOSAL_LENGTH = 4e3;
5895
5896
  var DEFAULT_STRATEGY = "higher_order";
5896
5897
  var DEFAULT_PREFIX = "pipeline";
5898
+ async function voteWithQuorumRecovery(state) {
5899
+ let vote = await executeSingleVote(state.plan, state.config, state.log);
5900
+ for (let attempt = 1; vote.kind === "no_quorum" && attempt <= state.maxNoQuorumRetries; attempt++) {
5901
+ state.log.warn("Vote reached no_quorum \u2014 re-running the missing voice (bounded)", {
5902
+ attempt,
5903
+ maxNoQuorumRetries: state.maxNoQuorumRetries,
5904
+ reason: vote.reason
5905
+ });
5906
+ emitPipelineStageEvent(state.prefix, "vote", "started");
5907
+ vote = await executeSingleVote(state.plan, state.config, state.log);
5908
+ }
5909
+ return vote;
5910
+ }
5897
5911
  async function runOneIteration(state, iteration) {
5898
5912
  state.log.info("Consensus iteration", { iteration });
5899
5913
  emitPipelineStageEvent(state.prefix, "vote", "started");
5900
- state.lastVote = await executeSingleVote(state.plan, state.config, state.log);
5914
+ state.lastVote = await voteWithQuorumRecovery(state);
5901
5915
  const iterMs = getTimeProvider().now() - state.globalStart;
5902
- const status = isVoteAccepted(state.lastVote) ? "completed" : "failed";
5903
- emitPipelineStageEvent(state.prefix, "vote", status, { durationMs: iterMs });
5904
- if (isVoteAccepted(state.lastVote)) {
5905
- return { vote: state.lastVote, iterations: iteration, durationMs: iterMs };
5916
+ const accepted = isVoteAccepted(state.lastVote);
5917
+ emitPipelineStageEvent(state.prefix, "vote", accepted ? "completed" : "failed", {
5918
+ durationMs: iterMs
5919
+ });
5920
+ if (accepted) {
5921
+ return { result: { vote: state.lastVote, iterations: iteration, durationMs: iterMs } };
5922
+ }
5923
+ if (state.lastVote.kind === "no_quorum") {
5924
+ const terminalVote = {
5925
+ kind: "no_quorum",
5926
+ reason: `vote could not reach quorum after ${String(state.maxNoQuorumRetries)} re-run(s): ${state.lastVote.reason}`,
5927
+ approvalPercentage: state.lastVote.approvalPercentage
5928
+ };
5929
+ return { terminal: { vote: terminalVote, iterations: iteration, durationMs: iterMs } };
5906
5930
  }
5907
- return void 0;
5931
+ return {};
5908
5932
  }
5909
5933
  async function runIterativeConsensus(initialPlan, revisePlan, config) {
5910
5934
  const maxIter = config?.maxIterations ?? DEFAULT_MAX_ITERATIONS;
@@ -5914,11 +5938,16 @@ async function runIterativeConsensus(initialPlan, revisePlan, config) {
5914
5938
  config,
5915
5939
  log: config?.logger ?? defaultLogger,
5916
5940
  prefix: config?.pipelinePrefix ?? DEFAULT_PREFIX,
5917
- globalStart: getTimeProvider().now()
5941
+ globalStart: getTimeProvider().now(),
5942
+ maxNoQuorumRetries: config?.maxNoQuorumRetries ?? DEFAULT_MAX_NO_QUORUM_RETRIES
5918
5943
  };
5944
+ return runConsensusLoop(state, maxIter, revisePlan);
5945
+ }
5946
+ async function runConsensusLoop(state, maxIter, revisePlan) {
5919
5947
  for (let i = 0; i < maxIter; i++) {
5920
- const accepted = await runOneIteration(state, i + 1);
5921
- if (accepted !== void 0) return accepted;
5948
+ const outcome = await runOneIteration(state, i + 1);
5949
+ const done = outcome.result ?? outcome.terminal;
5950
+ if (done !== void 0) return done;
5922
5951
  await maybeRevise(state, i, maxIter, revisePlan);
5923
5952
  }
5924
5953
  return buildExhaustedResult(state, maxIter);
@@ -5955,7 +5984,7 @@ function buildVotingInput(plan, config) {
5955
5984
  }
5956
5985
  async function executeSingleVote(plan, config, log) {
5957
5986
  try {
5958
- const { executeVoting } = await import("./consensus-vote-72AX6HNF.js");
5987
+ const { executeVoting } = await import("./consensus-vote-VPHFIIMN.js");
5959
5988
  const input = buildVotingInput(plan, config);
5960
5989
  const result = await executeVoting(input, log);
5961
5990
  return parseVotingResult(result);
@@ -5970,12 +5999,19 @@ async function executeSingleVote(plan, config, log) {
5970
5999
  }
5971
6000
  }
5972
6001
  function parseVotingResult(result) {
5973
- const approved = result.result.outcome === "approved";
5974
6002
  const total = Math.max(1, result.result.voteCounts.approve + result.result.voteCounts.reject);
5975
6003
  const pct = result.result.voteCounts.approve / total * 100;
5976
- if (approved) {
6004
+ const decision = result.decision ?? (result.result.outcome === "approved" ? "approved" : "rejected");
6005
+ if (decision === "approved") {
5977
6006
  return { kind: "approved", approvalPercentage: pct };
5978
6007
  }
6008
+ if (decision === "no_quorum") {
6009
+ return {
6010
+ kind: "no_quorum",
6011
+ reason: "vote could not reach quorum (a voice was missing)",
6012
+ approvalPercentage: pct
6013
+ };
6014
+ }
5979
6015
  const feedback = result.votes.filter((v) => v.vote.decision !== "approve").map((v) => v.vote.reasoning).join("\n");
5980
6016
  return { kind: "rejected", feedback, approvalPercentage: pct };
5981
6017
  }