nexus-agents 4.15.5 → 4.15.6

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.
@@ -170,7 +170,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
170
170
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
171
171
 
172
172
  // src/version.ts
173
- var VERSION = true ? "4.15.5" : "dev";
173
+ var VERSION = true ? "4.15.6" : "dev";
174
174
 
175
175
  // src/mcp/task-store.ts
176
176
  import { InMemoryTaskStore } from "@modelcontextprotocol/sdk/experimental/tasks";
@@ -1134,7 +1134,7 @@ async function runDoctorFix(result) {
1134
1134
  writeLine2("\u2500".repeat(40));
1135
1135
  let fixCount = 0;
1136
1136
  if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
1137
- const { initDataDirectories: initDataDirectories2, describeDataDirFix: describeDataDirFix2 } = await import("./setup-data-dir-AER2GI57.js");
1137
+ const { initDataDirectories: initDataDirectories2, describeDataDirFix: describeDataDirFix2 } = await import("./setup-data-dir-VLOT7GSQ.js");
1138
1138
  const outcome = describeDataDirFix2(initDataDirectories2());
1139
1139
  writeLine2(outcome.line);
1140
1140
  if (outcome.counted) fixCount++;
@@ -1237,4 +1237,4 @@ export {
1237
1237
  startStdioServer,
1238
1238
  closeServer
1239
1239
  };
1240
- //# sourceMappingURL=chunk-TL57RB6H.js.map
1240
+ //# sourceMappingURL=chunk-QZAMRR2Q.js.map
@@ -21,7 +21,7 @@ import {
21
21
  import {
22
22
  DEFAULT_TASK_TTL_MS,
23
23
  clampTaskTtl
24
- } from "./chunk-TL57RB6H.js";
24
+ } from "./chunk-QZAMRR2Q.js";
25
25
  import {
26
26
  executeExpert
27
27
  } from "./chunk-BH5PWPKK.js";
@@ -7905,6 +7905,7 @@ var AegeanResultSchema = z21.object({
7905
7905
  totalRounds: z21.number().int().min(0),
7906
7906
  totalDurationMs: z21.number(),
7907
7907
  tokensUsed: z21.number().int().min(0),
7908
+ unmeasuredTokenContributions: z21.number().int().min(0).default(0),
7908
7909
  rounds: z21.array(AegeanRoundSchema).readonly(),
7909
7910
  terminationReason: z21.enum(["consensus", "max_rounds", "timeout", "byzantine_failure", "error"])
7910
7911
  });
@@ -8118,6 +8119,10 @@ function buildAegeanConfig(options) {
8118
8119
  }
8119
8120
  return parsed.data;
8120
8121
  }
8122
+ function tokensFromMetadata(metadata) {
8123
+ if (metadata.tokensMeasured === false) return { tokens: 0, unmeasured: 1 };
8124
+ return { tokens: metadata.tokensUsed, unmeasured: 0 };
8125
+ }
8121
8126
  function buildAegeanResult(opts) {
8122
8127
  return {
8123
8128
  consensusValue: opts.consensusValue,
@@ -8125,6 +8130,7 @@ function buildAegeanResult(opts) {
8125
8130
  totalRounds: opts.rounds.length,
8126
8131
  totalDurationMs: getTimeProvider().now() - opts.startTime,
8127
8132
  tokensUsed: opts.tokensUsed,
8133
+ unmeasuredTokenContributions: opts.unmeasuredTokenContributions,
8128
8134
  rounds: opts.rounds,
8129
8135
  terminationReason: opts.terminationReason
8130
8136
  };
@@ -8148,20 +8154,21 @@ function determineIterationAction(opts) {
8148
8154
  return { type: "early_termination" };
8149
8155
  return { type: "continue" };
8150
8156
  }
8151
- function determinePreRoundAction(cancelled, rounds, startTime, tokensUsed) {
8157
+ function determinePreRoundAction(cancelled, rounds, startTime, tokensUsed, unmeasuredTokenContributions) {
8152
8158
  if (cancelled) {
8153
8159
  return buildAegeanResult({
8154
8160
  rounds,
8155
8161
  consensusValue: null,
8156
8162
  terminationReason: "error",
8157
8163
  startTime,
8158
- tokensUsed
8164
+ tokensUsed,
8165
+ unmeasuredTokenContributions
8159
8166
  });
8160
8167
  }
8161
8168
  return null;
8162
8169
  }
8163
- function createIterationContext(rounds, startTime, totalTokensUsed) {
8164
- return { rounds, startTime, tokensUsed: totalTokensUsed };
8170
+ function createIterationContext(rounds, startTime, totalTokensUsed, unmeasuredTokenContributions) {
8171
+ return { rounds, startTime, tokensUsed: totalTokensUsed, unmeasuredTokenContributions };
8165
8172
  }
8166
8173
  function processIterationAction(opts) {
8167
8174
  const { action, round, sessionId, ctx, emitIterationEvent, onEarlyTermination } = opts;
@@ -8173,7 +8180,8 @@ function processIterationAction(opts) {
8173
8180
  consensusValue: action.value,
8174
8181
  terminationReason: "consensus",
8175
8182
  startTime: ctx.startTime,
8176
- tokensUsed: ctx.tokensUsed
8183
+ tokensUsed: ctx.tokensUsed,
8184
+ unmeasuredTokenContributions: ctx.unmeasuredTokenContributions
8177
8185
  });
8178
8186
  case "early_termination":
8179
8187
  if (onEarlyTermination) onEarlyTermination(round);
@@ -8183,7 +8191,8 @@ function processIterationAction(opts) {
8183
8191
  consensusValue: null,
8184
8192
  terminationReason: "max_rounds",
8185
8193
  startTime: ctx.startTime,
8186
- tokensUsed: ctx.tokensUsed
8194
+ tokensUsed: ctx.tokensUsed,
8195
+ unmeasuredTokenContributions: ctx.unmeasuredTokenContributions
8187
8196
  });
8188
8197
  case "continue":
8189
8198
  emitIterationEvent(round, "in_progress", sessionId);
@@ -8194,12 +8203,13 @@ function processIterationAction(opts) {
8194
8203
  consensusValue: null,
8195
8204
  terminationReason: "error",
8196
8205
  startTime: ctx.startTime,
8197
- tokensUsed: ctx.tokensUsed
8206
+ tokensUsed: ctx.tokensUsed,
8207
+ unmeasuredTokenContributions: ctx.unmeasuredTokenContributions
8198
8208
  });
8199
8209
  }
8200
8210
  }
8201
- function buildLoopResult(rounds, consensusValue, terminationReason, startTime, tokensUsed) {
8202
- return buildAegeanResult({ rounds, consensusValue, terminationReason, startTime, tokensUsed });
8211
+ function buildLoopResult(opts) {
8212
+ return buildAegeanResult(opts);
8203
8213
  }
8204
8214
  function validateAegeanSetup(opts) {
8205
8215
  const minAgents = 3 * opts.byzantineTolerance + 1;
@@ -8231,6 +8241,10 @@ function buildSessionTaskResult(taskId, result, startTime) {
8231
8241
  metadata: {
8232
8242
  durationMs: getTimeProvider().now() - startTime,
8233
8243
  tokensUsed: result.tokensUsed,
8244
+ // The count becomes the disclosure the rest of the tree already reads
8245
+ // (#4734): a total assembled from contributors that reported nothing is
8246
+ // a lower bound, and must not be handed on as a measurement (#4743).
8247
+ tokensMeasured: result.unmeasuredTokenContributions === 0,
8234
8248
  toolsUsed: [],
8235
8249
  model: "aegean-protocol"
8236
8250
  }
@@ -8292,19 +8306,41 @@ var AegeanProtocol = class {
8292
8306
  const startTime = getTimeProvider().now();
8293
8307
  const rounds = [];
8294
8308
  let totalTokensUsed = 0;
8309
+ let unmeasuredTokenContributions = 0;
8295
8310
  for (let round = 0; round < this.config.maxRounds; round++) {
8296
- const preAction = determinePreRoundAction(this.cancelled, rounds, startTime, totalTokensUsed);
8311
+ const preAction = determinePreRoundAction(
8312
+ this.cancelled,
8313
+ rounds,
8314
+ startTime,
8315
+ totalTokensUsed,
8316
+ unmeasuredTokenContributions
8317
+ );
8297
8318
  if (preAction) return ok(preAction);
8298
8319
  const roundResult = await this.executeRound(round, config, agents);
8299
8320
  if (!roundResult.ok) return err(roundResult.error);
8300
- const { roundData, tokensUsed } = roundResult.value;
8321
+ const { roundData, tokensUsed, unmeasured } = roundResult.value;
8301
8322
  rounds.push(roundData);
8302
8323
  totalTokensUsed += tokensUsed;
8303
- const ctx = createIterationContext(rounds, startTime, totalTokensUsed);
8324
+ unmeasuredTokenContributions += unmeasured;
8325
+ const ctx = createIterationContext(
8326
+ rounds,
8327
+ startTime,
8328
+ totalTokensUsed,
8329
+ unmeasuredTokenContributions
8330
+ );
8304
8331
  const iterAction = this.handleIterationAction(round, roundData, config, ctx);
8305
8332
  if (iterAction) return ok(iterAction);
8306
8333
  }
8307
- return ok(buildLoopResult(rounds, null, "max_rounds", startTime, totalTokensUsed));
8334
+ return ok(
8335
+ buildLoopResult({
8336
+ rounds,
8337
+ consensusValue: null,
8338
+ terminationReason: "max_rounds",
8339
+ startTime,
8340
+ tokensUsed: totalTokensUsed,
8341
+ unmeasuredTokenContributions
8342
+ })
8343
+ );
8308
8344
  }
8309
8345
  /** Handles post-round iteration actions. */
8310
8346
  handleIterationAction(round, roundData, config, ctx) {
@@ -8346,16 +8382,36 @@ var AegeanProtocol = class {
8346
8382
  if (leader === void 0) {
8347
8383
  return err(new AgentError(`Leader agent not found: ${leaderId}`));
8348
8384
  }
8349
- this.logger.debug("Starting round", { roundNumber, leaderId });
8350
- emitAegeanRoundStarted(this.eventBus, {
8351
- round: roundNumber,
8352
- maxRounds: this.config.maxRounds,
8385
+ this.announceRoundStart(roundNumber, leaderId, config.sessionId);
8386
+ const gathered = await this.gatherRound(leader, leaderId, config, agents, roundNumber);
8387
+ if (!gathered.ok) return err(gathered.error);
8388
+ const { proposal, votes, tokensUsed, unmeasured } = gathered.value;
8389
+ const quorumStatus = this.evaluateQuorum(
8390
+ votes,
8391
+ config.experts.length,
8392
+ roundNumber,
8393
+ config.sessionId
8394
+ );
8395
+ const roundData = createRoundData({
8396
+ roundNumber,
8353
8397
  leaderId,
8354
- sessionId: config.sessionId
8398
+ proposal,
8399
+ votes,
8400
+ quorumStatus,
8401
+ startTime: roundStart
8355
8402
  });
8403
+ this.logger.debug("Round complete", { roundNumber, ...quorumStatus });
8404
+ return ok({ roundData, tokensUsed, unmeasured });
8405
+ }
8406
+ /** Phases 1 and 2 of a round: the leader's proposal, then the votes on it. */
8407
+ async gatherRound(leader, leaderId, config, agents, roundNumber) {
8356
8408
  const proposalResult = await this.generateProposal(leader, leaderId, config.task, roundNumber);
8357
8409
  if (!proposalResult.ok) return err(proposalResult.error);
8358
- const { proposal, tokensUsed: proposalTokens } = proposalResult.value;
8410
+ const {
8411
+ proposal,
8412
+ tokensUsed: proposalTokens,
8413
+ unmeasured: proposalUnmeasured
8414
+ } = proposalResult.value;
8359
8415
  const votesResult = await this.collectVotes({
8360
8416
  experts: config.experts,
8361
8417
  agents,
@@ -8365,31 +8421,23 @@ var AegeanProtocol = class {
8365
8421
  sessionId: config.sessionId
8366
8422
  });
8367
8423
  if (!votesResult.ok) return err(votesResult.error);
8368
- const { votes, tokensUsed: voteTokens } = votesResult.value;
8369
- const quorumStatus = this.evaluateQuorum(
8370
- votes,
8371
- config.experts.length,
8372
- roundNumber,
8373
- config.sessionId
8374
- );
8375
- const roundData = createRoundData({
8376
- roundNumber,
8377
- leaderId,
8424
+ const { votes, tokensUsed: voteTokens, unmeasured: voteUnmeasured } = votesResult.value;
8425
+ return ok({
8378
8426
  proposal,
8379
8427
  votes,
8380
- quorumStatus,
8381
- startTime: roundStart
8428
+ tokensUsed: proposalTokens + voteTokens,
8429
+ unmeasured: proposalUnmeasured + voteUnmeasured
8382
8430
  });
8383
- this.logger.debug("Round complete", { roundNumber, ...quorumStatus });
8384
- return ok({ roundData, tokensUsed: proposalTokens + voteTokens });
8385
8431
  }
8386
8432
  /** Generates a proposal from the leader. */
8387
8433
  async generateProposal(leader, leaderId, task, round) {
8388
8434
  const result = await leader.execute(createProposalTask(task, round));
8389
8435
  if (!result.ok) return err(result.error);
8436
+ const { tokens, unmeasured } = tokensFromMetadata(result.value.metadata);
8390
8437
  return ok({
8391
8438
  proposal: createProposal(round, leaderId, result.value.output),
8392
- tokensUsed: result.value.metadata.tokensUsed
8439
+ tokensUsed: tokens,
8440
+ unmeasured
8393
8441
  });
8394
8442
  }
8395
8443
  /** Collects votes from all agents. */
@@ -8397,27 +8445,16 @@ var AegeanProtocol = class {
8397
8445
  const { experts, agents, proposal, leaderId, roundNumber, sessionId } = opts;
8398
8446
  const votes = [];
8399
8447
  let totalTokens = 0;
8448
+ let totalUnmeasured = 0;
8400
8449
  const quorumSize = calculateQuorumSize(experts.length, this.config.byzantineTolerance);
8401
8450
  const voterIds = experts.filter((id) => id !== leaderId);
8402
- const votePromises = voterIds.map(async (agentId) => {
8403
- const agent = agents.get(agentId);
8404
- if (agent === void 0) {
8405
- return { agentId, vote: createTimeoutVote(agentId, proposal.proposalId), tokens: 0 };
8406
- }
8407
- const voteResult = await this.getAgentVote(agent, agentId, proposal);
8408
- if (!voteResult.ok) {
8409
- return {
8410
- agentId,
8411
- vote: createTimeoutVote(agentId, proposal.proposalId),
8412
- tokens: 0
8413
- };
8414
- }
8415
- return { agentId, vote: voteResult.value.vote, tokens: voteResult.value.tokensUsed };
8416
- });
8417
- const results = await Promise.all(votePromises);
8418
- for (const { vote, tokens } of results) {
8451
+ const results = await Promise.all(
8452
+ voterIds.map((agentId) => this.voteOrTimeout(agents.get(agentId), agentId, proposal))
8453
+ );
8454
+ for (const { vote, tokens, unmeasured } of results) {
8419
8455
  votes.push(vote);
8420
8456
  totalTokens += tokens;
8457
+ totalUnmeasured += unmeasured;
8421
8458
  emitAegeanVoteCollected(this.eventBus, {
8422
8459
  round: roundNumber,
8423
8460
  voterId: vote.agentId,
@@ -8427,22 +8464,55 @@ var AegeanProtocol = class {
8427
8464
  });
8428
8465
  }
8429
8466
  votes.push(createLeaderVote(leaderId, proposal.proposalId));
8430
- return ok({ votes, tokensUsed: totalTokens });
8467
+ return ok({ votes, tokensUsed: totalTokens, unmeasured: totalUnmeasured });
8468
+ }
8469
+ /** Logs and emits the round-started event (Issue #216). */
8470
+ announceRoundStart(roundNumber, leaderId, sessionId) {
8471
+ this.logger.debug("Starting round", { roundNumber, leaderId });
8472
+ emitAegeanRoundStarted(this.eventBus, {
8473
+ round: roundNumber,
8474
+ maxRounds: this.config.maxRounds,
8475
+ leaderId,
8476
+ sessionId
8477
+ });
8478
+ }
8479
+ /**
8480
+ * One voter's contribution, or a timeout vote when the agent is missing or
8481
+ * errored. A timeout contributes no tokens by a different route than an
8482
+ * unmeasured one — nothing executed — so it is not counted as unmeasured.
8483
+ */
8484
+ async voteOrTimeout(agent, agentId, proposal) {
8485
+ const timedOut = {
8486
+ agentId,
8487
+ vote: createTimeoutVote(agentId, proposal.proposalId),
8488
+ tokens: 0,
8489
+ unmeasured: 0
8490
+ };
8491
+ if (agent === void 0) return timedOut;
8492
+ const voteResult = await this.getAgentVote(agent, agentId, proposal);
8493
+ if (!voteResult.ok) return timedOut;
8494
+ return {
8495
+ agentId,
8496
+ vote: voteResult.value.vote,
8497
+ tokens: voteResult.value.tokensUsed,
8498
+ unmeasured: voteResult.value.unmeasured
8499
+ };
8431
8500
  }
8432
8501
  /** Gets a vote from an agent. */
8433
8502
  async getAgentVote(agent, agentId, proposal) {
8434
8503
  const result = await agent.execute(createVoteTask(proposal, agentId));
8435
8504
  if (!result.ok) {
8436
- return ok({ vote: createTimeoutVote(agentId, proposal.proposalId), tokensUsed: 0 });
8505
+ return ok({
8506
+ vote: createTimeoutVote(agentId, proposal.proposalId),
8507
+ tokensUsed: 0,
8508
+ unmeasured: 0
8509
+ });
8437
8510
  }
8438
- return ok(
8439
- createVoteFromOutput(
8440
- agentId,
8441
- proposal.proposalId,
8442
- result.value.output,
8443
- result.value.metadata.tokensUsed
8444
- )
8445
- );
8511
+ const { tokens, unmeasured } = tokensFromMetadata(result.value.metadata);
8512
+ return ok({
8513
+ ...createVoteFromOutput(agentId, proposal.proposalId, result.value.output, tokens),
8514
+ unmeasured
8515
+ });
8446
8516
  }
8447
8517
  /** Evaluates quorum status from votes. */
8448
8518
  evaluateQuorum(votes, totalAgents, roundNumber, sessionId) {
@@ -55780,4 +55850,4 @@ export {
55780
55850
  shutdownFeedbackSubscriber,
55781
55851
  createEventBusBridge
55782
55852
  };
55783
- //# sourceMappingURL=chunk-VPR6LDBO.js.map
55853
+ //# sourceMappingURL=chunk-XED5OLWO.js.map