@sw4rm/js-sdk 0.3.0 → 0.4.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/esm/index.js CHANGED
@@ -1908,15 +1908,15 @@ var require_fetch = __commonJS({
1908
1908
  var require_path = __commonJS({
1909
1909
  "node_modules/@protobufjs/path/index.js"(exports2) {
1910
1910
  "use strict";
1911
- var path3 = exports2;
1911
+ var path4 = exports2;
1912
1912
  var isAbsolute = (
1913
1913
  /**
1914
1914
  * Tests if the specified path is absolute.
1915
1915
  * @param {string} path Path to test
1916
1916
  * @returns {boolean} `true` if path is absolute
1917
1917
  */
1918
- path3.isAbsolute = function isAbsolute2(path4) {
1919
- return /^(?:\/|\w+:)/.test(path4);
1918
+ path4.isAbsolute = function isAbsolute2(path5) {
1919
+ return /^(?:\/|\w+:)/.test(path5);
1920
1920
  }
1921
1921
  );
1922
1922
  var normalize = (
@@ -1925,9 +1925,9 @@ var require_path = __commonJS({
1925
1925
  * @param {string} path Path to normalize
1926
1926
  * @returns {string} Normalized path
1927
1927
  */
1928
- path3.normalize = function normalize2(path4) {
1929
- path4 = path4.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
1930
- var parts = path4.split("/"), absolute = isAbsolute(path4), prefix = "";
1928
+ path4.normalize = function normalize2(path5) {
1929
+ path5 = path5.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
1930
+ var parts = path5.split("/"), absolute = isAbsolute(path5), prefix = "";
1931
1931
  if (absolute)
1932
1932
  prefix = parts.shift() + "/";
1933
1933
  for (var i = 0; i < parts.length; ) {
@@ -1946,7 +1946,7 @@ var require_path = __commonJS({
1946
1946
  return prefix + parts.join("/");
1947
1947
  }
1948
1948
  );
1949
- path3.resolve = function resolve(originPath, includePath, alreadyNormalized) {
1949
+ path4.resolve = function resolve(originPath, includePath, alreadyNormalized) {
1950
1950
  if (!alreadyNormalized)
1951
1951
  includePath = normalize(includePath);
1952
1952
  if (isAbsolute(includePath))
@@ -2097,16 +2097,16 @@ var require_namespace = __commonJS({
2097
2097
  object.onRemove(this);
2098
2098
  return clearCache(this);
2099
2099
  };
2100
- Namespace.prototype.define = function define2(path3, json) {
2101
- if (util.isString(path3))
2102
- path3 = path3.split(".");
2103
- else if (!Array.isArray(path3))
2100
+ Namespace.prototype.define = function define2(path4, json) {
2101
+ if (util.isString(path4))
2102
+ path4 = path4.split(".");
2103
+ else if (!Array.isArray(path4))
2104
2104
  throw TypeError("illegal path");
2105
- if (path3 && path3.length && path3[0] === "")
2105
+ if (path4 && path4.length && path4[0] === "")
2106
2106
  throw Error("path must be relative");
2107
2107
  var ptr = this;
2108
- while (path3.length > 0) {
2109
- var part = path3.shift();
2108
+ while (path4.length > 0) {
2109
+ var part = path4.shift();
2110
2110
  if (ptr.nested && ptr.nested[part]) {
2111
2111
  ptr = ptr.nested[part];
2112
2112
  if (!(ptr instanceof Namespace))
@@ -2143,26 +2143,26 @@ var require_namespace = __commonJS({
2143
2143
  });
2144
2144
  return this;
2145
2145
  };
2146
- Namespace.prototype.lookup = function lookup(path3, filterTypes, parentAlreadyChecked) {
2146
+ Namespace.prototype.lookup = function lookup(path4, filterTypes, parentAlreadyChecked) {
2147
2147
  if (typeof filterTypes === "boolean") {
2148
2148
  parentAlreadyChecked = filterTypes;
2149
2149
  filterTypes = void 0;
2150
2150
  } else if (filterTypes && !Array.isArray(filterTypes))
2151
2151
  filterTypes = [filterTypes];
2152
- if (util.isString(path3) && path3.length) {
2153
- if (path3 === ".")
2152
+ if (util.isString(path4) && path4.length) {
2153
+ if (path4 === ".")
2154
2154
  return this.root;
2155
- path3 = path3.split(".");
2156
- } else if (!path3.length)
2155
+ path4 = path4.split(".");
2156
+ } else if (!path4.length)
2157
2157
  return this;
2158
- var flatPath = path3.join(".");
2159
- if (path3[0] === "")
2160
- return this.root.lookup(path3.slice(1), filterTypes);
2158
+ var flatPath = path4.join(".");
2159
+ if (path4[0] === "")
2160
+ return this.root.lookup(path4.slice(1), filterTypes);
2161
2161
  var found = this.root._fullyQualifiedObjects && this.root._fullyQualifiedObjects["." + flatPath];
2162
2162
  if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
2163
2163
  return found;
2164
2164
  }
2165
- found = this._lookupImpl(path3, flatPath);
2165
+ found = this._lookupImpl(path4, flatPath);
2166
2166
  if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
2167
2167
  return found;
2168
2168
  }
@@ -2170,7 +2170,7 @@ var require_namespace = __commonJS({
2170
2170
  return null;
2171
2171
  var current = this;
2172
2172
  while (current.parent) {
2173
- found = current.parent._lookupImpl(path3, flatPath);
2173
+ found = current.parent._lookupImpl(path4, flatPath);
2174
2174
  if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
2175
2175
  return found;
2176
2176
  }
@@ -2178,49 +2178,49 @@ var require_namespace = __commonJS({
2178
2178
  }
2179
2179
  return null;
2180
2180
  };
2181
- Namespace.prototype._lookupImpl = function lookup(path3, flatPath) {
2181
+ Namespace.prototype._lookupImpl = function lookup(path4, flatPath) {
2182
2182
  if (Object.prototype.hasOwnProperty.call(this._lookupCache, flatPath)) {
2183
2183
  return this._lookupCache[flatPath];
2184
2184
  }
2185
- var found = this.get(path3[0]);
2185
+ var found = this.get(path4[0]);
2186
2186
  var exact = null;
2187
2187
  if (found) {
2188
- if (path3.length === 1) {
2188
+ if (path4.length === 1) {
2189
2189
  exact = found;
2190
2190
  } else if (found instanceof Namespace) {
2191
- path3 = path3.slice(1);
2192
- exact = found._lookupImpl(path3, path3.join("."));
2191
+ path4 = path4.slice(1);
2192
+ exact = found._lookupImpl(path4, path4.join("."));
2193
2193
  }
2194
2194
  } else {
2195
2195
  for (var i = 0; i < this.nestedArray.length; ++i)
2196
- if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path3, flatPath)))
2196
+ if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path4, flatPath)))
2197
2197
  exact = found;
2198
2198
  }
2199
2199
  this._lookupCache[flatPath] = exact;
2200
2200
  return exact;
2201
2201
  };
2202
- Namespace.prototype.lookupType = function lookupType(path3) {
2203
- var found = this.lookup(path3, [Type]);
2202
+ Namespace.prototype.lookupType = function lookupType(path4) {
2203
+ var found = this.lookup(path4, [Type]);
2204
2204
  if (!found)
2205
- throw Error("no such type: " + path3);
2205
+ throw Error("no such type: " + path4);
2206
2206
  return found;
2207
2207
  };
2208
- Namespace.prototype.lookupEnum = function lookupEnum(path3) {
2209
- var found = this.lookup(path3, [Enum]);
2208
+ Namespace.prototype.lookupEnum = function lookupEnum(path4) {
2209
+ var found = this.lookup(path4, [Enum]);
2210
2210
  if (!found)
2211
- throw Error("no such Enum '" + path3 + "' in " + this);
2211
+ throw Error("no such Enum '" + path4 + "' in " + this);
2212
2212
  return found;
2213
2213
  };
2214
- Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(path3) {
2215
- var found = this.lookup(path3, [Type, Enum]);
2214
+ Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(path4) {
2215
+ var found = this.lookup(path4, [Type, Enum]);
2216
2216
  if (!found)
2217
- throw Error("no such Type or Enum '" + path3 + "' in " + this);
2217
+ throw Error("no such Type or Enum '" + path4 + "' in " + this);
2218
2218
  return found;
2219
2219
  };
2220
- Namespace.prototype.lookupService = function lookupService(path3) {
2221
- var found = this.lookup(path3, [Service]);
2220
+ Namespace.prototype.lookupService = function lookupService(path4) {
2221
+ var found = this.lookup(path4, [Service]);
2222
2222
  if (!found)
2223
- throw Error("no such Service '" + path3 + "' in " + this);
2223
+ throw Error("no such Service '" + path4 + "' in " + this);
2224
2224
  return found;
2225
2225
  };
2226
2226
  Namespace._configure = function(Type_, Service_, Enum_) {
@@ -3621,14 +3621,14 @@ var require_util = __commonJS({
3621
3621
  Object.defineProperty(object, "$type", { value: enm, enumerable: false });
3622
3622
  return enm;
3623
3623
  };
3624
- util.setProperty = function setProperty(dst, path3, value, ifNotSet) {
3625
- function setProp(dst2, path4, value2) {
3626
- var part = path4.shift();
3624
+ util.setProperty = function setProperty(dst, path4, value, ifNotSet) {
3625
+ function setProp(dst2, path5, value2) {
3626
+ var part = path5.shift();
3627
3627
  if (part === "__proto__" || part === "prototype") {
3628
3628
  return dst2;
3629
3629
  }
3630
- if (path4.length > 0) {
3631
- dst2[part] = setProp(dst2[part] || {}, path4, value2);
3630
+ if (path5.length > 0) {
3631
+ dst2[part] = setProp(dst2[part] || {}, path5, value2);
3632
3632
  } else {
3633
3633
  var prevValue = dst2[part];
3634
3634
  if (prevValue && ifNotSet)
@@ -3641,10 +3641,10 @@ var require_util = __commonJS({
3641
3641
  }
3642
3642
  if (typeof dst !== "object")
3643
3643
  throw TypeError("dst must be an object");
3644
- if (!path3)
3644
+ if (!path4)
3645
3645
  throw TypeError("path must be specified");
3646
- path3 = path3.split(".");
3647
- return setProp(dst, path3, value);
3646
+ path4 = path4.split(".");
3647
+ return setProp(dst, path4, value);
3648
3648
  };
3649
3649
  Object.defineProperty(util, "decorateRoot", {
3650
3650
  get: function() {
@@ -4191,12 +4191,12 @@ var require_object = __commonJS({
4191
4191
  */
4192
4192
  fullName: {
4193
4193
  get: function() {
4194
- var path3 = [this.name], ptr = this.parent;
4194
+ var path4 = [this.name], ptr = this.parent;
4195
4195
  while (ptr) {
4196
- path3.unshift(ptr.name);
4196
+ path4.unshift(ptr.name);
4197
4197
  ptr = ptr.parent;
4198
4198
  }
4199
- return path3.join(".");
4199
+ return path4.join(".");
4200
4200
  }
4201
4201
  }
4202
4202
  });
@@ -8179,16 +8179,16 @@ var require_util2 = __commonJS({
8179
8179
  Object.defineProperty(exports2, "__esModule", { value: true });
8180
8180
  exports2.addCommonProtos = exports2.loadProtosWithOptionsSync = exports2.loadProtosWithOptions = void 0;
8181
8181
  var fs = __require("fs");
8182
- var path3 = __require("path");
8182
+ var path4 = __require("path");
8183
8183
  var Protobuf = require_protobufjs();
8184
8184
  function addIncludePathResolver(root, includePaths) {
8185
8185
  const originalResolvePath = root.resolvePath;
8186
8186
  root.resolvePath = (origin, target) => {
8187
- if (path3.isAbsolute(target)) {
8187
+ if (path4.isAbsolute(target)) {
8188
8188
  return target;
8189
8189
  }
8190
8190
  for (const directory of includePaths) {
8191
- const fullPath = path3.join(directory, target);
8191
+ const fullPath = path4.join(directory, target);
8192
8192
  try {
8193
8193
  fs.accessSync(fullPath, fs.constants.R_OK);
8194
8194
  return fullPath;
@@ -9605,7 +9605,7 @@ var InterceptorChain = class {
9605
9605
  };
9606
9606
  function timingInterceptor() {
9607
9607
  return {
9608
- onRequest(ctx) {
9608
+ onRequest(_ctx) {
9609
9609
  },
9610
9610
  onResponse(ctx, status) {
9611
9611
  if (typeof console !== "undefined" && console.debug) {
@@ -10274,6 +10274,961 @@ var RegistryClient = class extends BaseClient {
10274
10274
  }
10275
10275
  };
10276
10276
 
10277
+ // src/clients/negotiationRoom.ts
10278
+ var ArtifactType = /* @__PURE__ */ ((ArtifactType2) => {
10279
+ ArtifactType2[ArtifactType2["ARTIFACT_TYPE_UNSPECIFIED"] = 0] = "ARTIFACT_TYPE_UNSPECIFIED";
10280
+ ArtifactType2[ArtifactType2["REQUIREMENTS"] = 1] = "REQUIREMENTS";
10281
+ ArtifactType2[ArtifactType2["PLAN"] = 2] = "PLAN";
10282
+ ArtifactType2[ArtifactType2["CODE"] = 3] = "CODE";
10283
+ ArtifactType2[ArtifactType2["DEPLOYMENT"] = 4] = "DEPLOYMENT";
10284
+ return ArtifactType2;
10285
+ })(ArtifactType || {});
10286
+ var DecisionOutcome = /* @__PURE__ */ ((DecisionOutcome2) => {
10287
+ DecisionOutcome2[DecisionOutcome2["DECISION_OUTCOME_UNSPECIFIED"] = 0] = "DECISION_OUTCOME_UNSPECIFIED";
10288
+ DecisionOutcome2[DecisionOutcome2["APPROVED"] = 1] = "APPROVED";
10289
+ DecisionOutcome2[DecisionOutcome2["REVISION_REQUESTED"] = 2] = "REVISION_REQUESTED";
10290
+ DecisionOutcome2[DecisionOutcome2["ESCALATED_TO_HITL"] = 3] = "ESCALATED_TO_HITL";
10291
+ return DecisionOutcome2;
10292
+ })(DecisionOutcome || {});
10293
+ var NegotiationTimeoutError = class extends Error {
10294
+ constructor(message) {
10295
+ super(message);
10296
+ this.name = "NegotiationTimeoutError";
10297
+ }
10298
+ };
10299
+ var NegotiationValidationError = class extends Error {
10300
+ constructor(message) {
10301
+ super(message);
10302
+ this.name = "NegotiationValidationError";
10303
+ }
10304
+ };
10305
+ function validateVote(vote) {
10306
+ if (vote.score < 0 || vote.score > 10) {
10307
+ throw new NegotiationValidationError(
10308
+ `score must be in range [0, 10], got ${vote.score}`
10309
+ );
10310
+ }
10311
+ if (vote.confidence < 0 || vote.confidence > 1) {
10312
+ throw new NegotiationValidationError(
10313
+ `confidence must be in range [0, 1], got ${vote.confidence}`
10314
+ );
10315
+ }
10316
+ }
10317
+ var NegotiationRoomClient = class {
10318
+ proposals = /* @__PURE__ */ new Map();
10319
+ votes = /* @__PURE__ */ new Map();
10320
+ decisions = /* @__PURE__ */ new Map();
10321
+ /**
10322
+ * Submit an artifact proposal for multi-agent review.
10323
+ *
10324
+ * Stores the proposal and initializes empty vote tracking for the artifact.
10325
+ * This method is typically called by producer agents.
10326
+ *
10327
+ * @param proposal - The negotiation proposal containing artifact details
10328
+ * @returns The artifact_id of the submitted proposal
10329
+ * @throws NegotiationValidationError if a proposal with the same artifact_id already exists
10330
+ *
10331
+ * @example
10332
+ * ```typescript
10333
+ * const client = new NegotiationRoomClient();
10334
+ * const proposal: NegotiationProposal = {
10335
+ * artifactType: ArtifactType.CODE,
10336
+ * artifactId: "code-123",
10337
+ * producerId: "agent-producer",
10338
+ * artifact: new TextEncoder().encode("def hello(): pass"),
10339
+ * artifactContentType: "text/x-python",
10340
+ * requestedCritics: ["critic-1", "critic-2"],
10341
+ * negotiationRoomId: "room-1"
10342
+ * };
10343
+ * const artifactId = await client.submitProposal(proposal);
10344
+ * console.log(artifactId); // "code-123"
10345
+ * ```
10346
+ */
10347
+ async submitProposal(proposal) {
10348
+ const artifactId = proposal.artifactId;
10349
+ if (this.proposals.has(artifactId)) {
10350
+ throw new NegotiationValidationError(
10351
+ `Proposal with artifact_id '${artifactId}' already exists`
10352
+ );
10353
+ }
10354
+ const proposalWithTimestamp = {
10355
+ ...proposal,
10356
+ createdAt: proposal.createdAt || (/* @__PURE__ */ new Date()).toISOString()
10357
+ };
10358
+ this.proposals.set(artifactId, proposalWithTimestamp);
10359
+ this.votes.set(artifactId, []);
10360
+ return artifactId;
10361
+ }
10362
+ /**
10363
+ * Submit a critic's vote for an artifact.
10364
+ *
10365
+ * Adds the vote to the collection for the specified artifact.
10366
+ * This method is typically called by critic agents after evaluating
10367
+ * an artifact.
10368
+ *
10369
+ * @param vote - The negotiation vote containing the critic's evaluation
10370
+ * @throws NegotiationValidationError if no proposal exists for the vote's artifact_id
10371
+ * @throws NegotiationValidationError if the critic has already voted for this artifact
10372
+ * @throws NegotiationValidationError if score or confidence are out of range
10373
+ *
10374
+ * @example
10375
+ * ```typescript
10376
+ * const vote: NegotiationVote = {
10377
+ * artifactId: "code-123",
10378
+ * criticId: "critic-1",
10379
+ * score: 8.5,
10380
+ * confidence: 0.9,
10381
+ * passed: true,
10382
+ * strengths: ["Good structure"],
10383
+ * weaknesses: ["Needs tests"],
10384
+ * recommendations: ["Add unit tests"],
10385
+ * negotiationRoomId: "room-1"
10386
+ * };
10387
+ * await client.submitVote(vote);
10388
+ * ```
10389
+ */
10390
+ async submitVote(vote) {
10391
+ const artifactId = vote.artifactId;
10392
+ if (!this.proposals.has(artifactId)) {
10393
+ throw new NegotiationValidationError(
10394
+ `No proposal found for artifact_id '${artifactId}'`
10395
+ );
10396
+ }
10397
+ validateVote(vote);
10398
+ const existingVotes = this.votes.get(artifactId) || [];
10399
+ for (const existingVote of existingVotes) {
10400
+ if (existingVote.criticId === vote.criticId) {
10401
+ throw new NegotiationValidationError(
10402
+ `Critic '${vote.criticId}' has already voted for artifact '${artifactId}'`
10403
+ );
10404
+ }
10405
+ }
10406
+ const voteWithTimestamp = {
10407
+ ...vote,
10408
+ votedAt: vote.votedAt || (/* @__PURE__ */ new Date()).toISOString()
10409
+ };
10410
+ existingVotes.push(voteWithTimestamp);
10411
+ this.votes.set(artifactId, existingVotes);
10412
+ }
10413
+ /**
10414
+ * Retrieve all votes for a specific artifact.
10415
+ *
10416
+ * Returns all critic votes that have been submitted for the artifact.
10417
+ * This method is typically called by coordinator agents to aggregate
10418
+ * votes and make decisions.
10419
+ *
10420
+ * @param artifactId - The identifier of the artifact
10421
+ * @returns List of all votes for the artifact (empty array if no votes yet)
10422
+ * @throws NegotiationValidationError if no proposal exists for the artifact_id
10423
+ *
10424
+ * @example
10425
+ * ```typescript
10426
+ * const votes = await client.getVotes("code-123");
10427
+ * console.log(votes.length); // 1
10428
+ * ```
10429
+ */
10430
+ async getVotes(artifactId) {
10431
+ if (!this.proposals.has(artifactId)) {
10432
+ throw new NegotiationValidationError(
10433
+ `No proposal found for artifact_id '${artifactId}'`
10434
+ );
10435
+ }
10436
+ return this.votes.get(artifactId) || [];
10437
+ }
10438
+ /**
10439
+ * Retrieve the decision for a specific artifact if available.
10440
+ *
10441
+ * Returns the final decision if one has been made, or null if the
10442
+ * artifact is still under review.
10443
+ *
10444
+ * @param artifactId - The identifier of the artifact
10445
+ * @returns The negotiation decision if available, null otherwise
10446
+ * @throws NegotiationValidationError if no proposal exists for the artifact_id
10447
+ *
10448
+ * @example
10449
+ * ```typescript
10450
+ * const decision = await client.getDecision("code-123");
10451
+ * if (decision === null) {
10452
+ * console.log("Decision pending");
10453
+ * }
10454
+ * ```
10455
+ */
10456
+ async getDecision(artifactId) {
10457
+ if (!this.proposals.has(artifactId)) {
10458
+ throw new NegotiationValidationError(
10459
+ `No proposal found for artifact_id '${artifactId}'`
10460
+ );
10461
+ }
10462
+ return this.decisions.get(artifactId) || null;
10463
+ }
10464
+ /**
10465
+ * Store a decision for an artifact.
10466
+ *
10467
+ * This is an internal method used by coordinators to record the
10468
+ * final decision after evaluating votes. Once a decision is stored,
10469
+ * it becomes available via getDecision() and waitForDecision().
10470
+ *
10471
+ * @param decision - The negotiation decision to store
10472
+ * @throws NegotiationValidationError if no proposal exists for the decision's artifact_id
10473
+ * @throws NegotiationValidationError if a decision already exists for this artifact
10474
+ *
10475
+ * @example
10476
+ * ```typescript
10477
+ * const votes = await client.getVotes("code-123");
10478
+ * const aggregated = aggregateVotes(votes);
10479
+ * const decision: NegotiationDecision = {
10480
+ * artifactId: "code-123",
10481
+ * outcome: DecisionOutcome.APPROVED,
10482
+ * votes: votes,
10483
+ * aggregatedScore: aggregated,
10484
+ * policyVersion: "1.0",
10485
+ * reason: "Met all criteria",
10486
+ * negotiationRoomId: "room-1"
10487
+ * };
10488
+ * await client.storeDecision(decision);
10489
+ * ```
10490
+ */
10491
+ async storeDecision(decision) {
10492
+ const artifactId = decision.artifactId;
10493
+ if (!this.proposals.has(artifactId)) {
10494
+ throw new NegotiationValidationError(
10495
+ `No proposal found for artifact_id '${artifactId}'`
10496
+ );
10497
+ }
10498
+ if (this.decisions.has(artifactId)) {
10499
+ throw new NegotiationValidationError(
10500
+ `Decision already exists for artifact_id '${artifactId}'`
10501
+ );
10502
+ }
10503
+ const decisionWithTimestamp = {
10504
+ ...decision,
10505
+ decidedAt: decision.decidedAt || (/* @__PURE__ */ new Date()).toISOString()
10506
+ };
10507
+ this.decisions.set(artifactId, decisionWithTimestamp);
10508
+ }
10509
+ /**
10510
+ * Wait for a decision to be made on an artifact.
10511
+ *
10512
+ * Polls for a decision until one is available or the timeout is reached.
10513
+ * This method is useful for producer agents waiting for the outcome
10514
+ * of their artifact review.
10515
+ *
10516
+ * @param artifactId - The identifier of the artifact
10517
+ * @param timeoutMs - Maximum time to wait in milliseconds (default: 30000)
10518
+ * @param pollIntervalMs - Time between polling attempts in milliseconds (default: 100)
10519
+ * @returns The negotiation decision once available
10520
+ * @throws NegotiationValidationError if no proposal exists for the artifact_id
10521
+ * @throws NegotiationTimeoutError if no decision is made within the timeout period
10522
+ *
10523
+ * @example
10524
+ * ```typescript
10525
+ * // In a separate thread/process, a coordinator makes a decision
10526
+ * const decision = await client.waitForDecision("code-123", 10000);
10527
+ * console.log(decision.outcome); // DecisionOutcome.APPROVED
10528
+ * ```
10529
+ */
10530
+ async waitForDecision(artifactId, timeoutMs = 3e4, pollIntervalMs = 100) {
10531
+ if (!this.proposals.has(artifactId)) {
10532
+ throw new NegotiationValidationError(
10533
+ `No proposal found for artifact_id '${artifactId}'`
10534
+ );
10535
+ }
10536
+ const startTime = Date.now();
10537
+ while (Date.now() - startTime < timeoutMs) {
10538
+ const decision = await this.getDecision(artifactId);
10539
+ if (decision !== null) {
10540
+ return decision;
10541
+ }
10542
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
10543
+ }
10544
+ throw new NegotiationTimeoutError(
10545
+ `No decision made for artifact '${artifactId}' within ${timeoutMs} milliseconds`
10546
+ );
10547
+ }
10548
+ /**
10549
+ * Retrieve the original proposal for an artifact.
10550
+ *
10551
+ * Useful for critics that need to review the original artifact
10552
+ * before submitting a vote.
10553
+ *
10554
+ * @param artifactId - The identifier of the artifact
10555
+ * @returns The negotiation proposal if it exists, null otherwise
10556
+ *
10557
+ * @example
10558
+ * ```typescript
10559
+ * const proposal = await client.getProposal("code-123");
10560
+ * console.log(proposal?.artifactType); // ArtifactType.CODE
10561
+ * ```
10562
+ */
10563
+ async getProposal(artifactId) {
10564
+ return this.proposals.get(artifactId) || null;
10565
+ }
10566
+ /**
10567
+ * List all proposals, optionally filtered by negotiation room.
10568
+ *
10569
+ * @param negotiationRoomId - If provided, only return proposals for this room
10570
+ * @returns List of proposals matching the filter criteria
10571
+ *
10572
+ * @example
10573
+ * ```typescript
10574
+ * const proposals = await client.listProposals("room-1");
10575
+ * console.log(proposals.length); // 1
10576
+ * ```
10577
+ */
10578
+ async listProposals(negotiationRoomId) {
10579
+ const allProposals = Array.from(this.proposals.values());
10580
+ if (negotiationRoomId === void 0) {
10581
+ return allProposals;
10582
+ }
10583
+ return allProposals.filter(
10584
+ (p) => p.negotiationRoomId === negotiationRoomId
10585
+ );
10586
+ }
10587
+ };
10588
+ function aggregateVotes(votes) {
10589
+ if (votes.length === 0) {
10590
+ throw new NegotiationValidationError(
10591
+ "Cannot aggregate empty list of votes"
10592
+ );
10593
+ }
10594
+ const scores = votes.map((v) => v.score);
10595
+ const confidences = votes.map((v) => v.confidence);
10596
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
10597
+ const minScore = Math.min(...scores);
10598
+ const maxScore = Math.max(...scores);
10599
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
10600
+ const stdDev = Math.sqrt(variance);
10601
+ const totalConfidence = confidences.reduce((a, b) => a + b, 0);
10602
+ let weightedMean;
10603
+ if (totalConfidence > 0) {
10604
+ weightedMean = scores.reduce((sum, s, i) => sum + s * confidences[i], 0) / totalConfidence;
10605
+ } else {
10606
+ weightedMean = mean;
10607
+ }
10608
+ return {
10609
+ mean,
10610
+ minScore,
10611
+ maxScore,
10612
+ stdDev,
10613
+ weightedMean,
10614
+ voteCount: votes.length
10615
+ };
10616
+ }
10617
+
10618
+ // src/clients/handoff.ts
10619
+ var HandoffStatus = /* @__PURE__ */ ((HandoffStatus2) => {
10620
+ HandoffStatus2[HandoffStatus2["HANDOFF_STATUS_UNSPECIFIED"] = 0] = "HANDOFF_STATUS_UNSPECIFIED";
10621
+ HandoffStatus2[HandoffStatus2["PENDING"] = 1] = "PENDING";
10622
+ HandoffStatus2[HandoffStatus2["ACCEPTED"] = 2] = "ACCEPTED";
10623
+ HandoffStatus2[HandoffStatus2["REJECTED"] = 3] = "REJECTED";
10624
+ HandoffStatus2[HandoffStatus2["COMPLETED"] = 4] = "COMPLETED";
10625
+ HandoffStatus2[HandoffStatus2["EXPIRED"] = 5] = "EXPIRED";
10626
+ return HandoffStatus2;
10627
+ })(HandoffStatus || {});
10628
+ var HandoffValidationError = class extends Error {
10629
+ constructor(message) {
10630
+ super(message);
10631
+ this.name = "HandoffValidationError";
10632
+ }
10633
+ };
10634
+ var HandoffTimeoutError = class extends Error {
10635
+ constructor(message) {
10636
+ super(message);
10637
+ this.name = "HandoffTimeoutError";
10638
+ }
10639
+ };
10640
+ var HandoffClient = class {
10641
+ requests = /* @__PURE__ */ new Map();
10642
+ responses = /* @__PURE__ */ new Map();
10643
+ pendingByAgent = /* @__PURE__ */ new Map();
10644
+ /**
10645
+ * Request a handoff to another agent.
10646
+ *
10647
+ * Initiates a handoff request that the target agent can accept or reject.
10648
+ * The request is stored and made available to the target agent via
10649
+ * getPendingHandoffs().
10650
+ *
10651
+ * @param request - The handoff request containing context and requirements
10652
+ * @returns The response once the handoff is accepted, rejected, or times out
10653
+ * @throws HandoffValidationError if a request with the same ID already exists
10654
+ *
10655
+ * @example
10656
+ * ```typescript
10657
+ * const client = new HandoffClient();
10658
+ * const request: HandoffRequest = {
10659
+ * requestId: "handoff-123",
10660
+ * fromAgent: "agent-a",
10661
+ * toAgent: "agent-b",
10662
+ * reason: "Capability mismatch",
10663
+ * contextSnapshot: new TextEncoder().encode('{"state": "in_progress"}'),
10664
+ * capabilitiesRequired: ["code_review"],
10665
+ * priority: 5
10666
+ * };
10667
+ * const response = await client.requestHandoff(request);
10668
+ * ```
10669
+ */
10670
+ async requestHandoff(request) {
10671
+ if (this.requests.has(request.requestId)) {
10672
+ throw new HandoffValidationError(
10673
+ `Handoff request with ID '${request.requestId}' already exists`
10674
+ );
10675
+ }
10676
+ const requestWithTimestamp = {
10677
+ ...request,
10678
+ createdAt: request.createdAt || (/* @__PURE__ */ new Date()).toISOString()
10679
+ };
10680
+ this.requests.set(request.requestId, requestWithTimestamp);
10681
+ if (request.toAgent) {
10682
+ if (!this.pendingByAgent.has(request.toAgent)) {
10683
+ this.pendingByAgent.set(request.toAgent, /* @__PURE__ */ new Set());
10684
+ }
10685
+ this.pendingByAgent.get(request.toAgent).add(request.requestId);
10686
+ }
10687
+ const timeoutMs = request.timeoutMs || 3e4;
10688
+ const startTime = Date.now();
10689
+ const pollIntervalMs = 100;
10690
+ while (Date.now() - startTime < timeoutMs) {
10691
+ const response = this.responses.get(request.requestId);
10692
+ if (response) {
10693
+ return response;
10694
+ }
10695
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
10696
+ }
10697
+ const timeoutResponse = {
10698
+ requestId: request.requestId,
10699
+ accepted: false,
10700
+ rejectionReason: `Handoff request timed out after ${timeoutMs}ms`
10701
+ };
10702
+ this.responses.set(request.requestId, timeoutResponse);
10703
+ if (request.toAgent && this.pendingByAgent.has(request.toAgent)) {
10704
+ this.pendingByAgent.get(request.toAgent).delete(request.requestId);
10705
+ }
10706
+ return timeoutResponse;
10707
+ }
10708
+ /**
10709
+ * Accept a pending handoff request.
10710
+ *
10711
+ * Called by the target agent to accept a handoff. After acceptance,
10712
+ * the agent should process the context snapshot and continue the work.
10713
+ *
10714
+ * @param handoffId - The ID of the handoff request to accept
10715
+ * @throws HandoffValidationError if no request exists with the given ID
10716
+ * @throws HandoffValidationError if the request has already been responded to
10717
+ *
10718
+ * @example
10719
+ * ```typescript
10720
+ * // Get pending handoffs for this agent
10721
+ * const pending = await client.getPendingHandoffs("agent-b");
10722
+ * if (pending.length > 0) {
10723
+ * await client.acceptHandoff(pending[0].requestId);
10724
+ * }
10725
+ * ```
10726
+ */
10727
+ async acceptHandoff(handoffId) {
10728
+ const request = this.requests.get(handoffId);
10729
+ if (!request) {
10730
+ throw new HandoffValidationError(
10731
+ `No handoff request found with ID '${handoffId}'`
10732
+ );
10733
+ }
10734
+ if (this.responses.has(handoffId)) {
10735
+ throw new HandoffValidationError(
10736
+ `Handoff request '${handoffId}' has already been responded to`
10737
+ );
10738
+ }
10739
+ const response = {
10740
+ requestId: handoffId,
10741
+ accepted: true,
10742
+ acceptingAgent: request.toAgent
10743
+ };
10744
+ this.responses.set(handoffId, response);
10745
+ if (request.toAgent && this.pendingByAgent.has(request.toAgent)) {
10746
+ this.pendingByAgent.get(request.toAgent).delete(handoffId);
10747
+ }
10748
+ }
10749
+ /**
10750
+ * Reject a pending handoff request.
10751
+ *
10752
+ * Called by the target agent to reject a handoff. A reason should be
10753
+ * provided to help the originating agent determine next steps.
10754
+ *
10755
+ * @param handoffId - The ID of the handoff request to reject
10756
+ * @param reason - Human-readable reason for the rejection
10757
+ * @throws HandoffValidationError if no request exists with the given ID
10758
+ * @throws HandoffValidationError if the request has already been responded to
10759
+ *
10760
+ * @example
10761
+ * ```typescript
10762
+ * await client.rejectHandoff("handoff-123", "Agent at capacity");
10763
+ * ```
10764
+ */
10765
+ async rejectHandoff(handoffId, reason) {
10766
+ const request = this.requests.get(handoffId);
10767
+ if (!request) {
10768
+ throw new HandoffValidationError(
10769
+ `No handoff request found with ID '${handoffId}'`
10770
+ );
10771
+ }
10772
+ if (this.responses.has(handoffId)) {
10773
+ throw new HandoffValidationError(
10774
+ `Handoff request '${handoffId}' has already been responded to`
10775
+ );
10776
+ }
10777
+ const response = {
10778
+ requestId: handoffId,
10779
+ accepted: false,
10780
+ rejectionReason: reason
10781
+ };
10782
+ this.responses.set(handoffId, response);
10783
+ if (request.toAgent && this.pendingByAgent.has(request.toAgent)) {
10784
+ this.pendingByAgent.get(request.toAgent).delete(handoffId);
10785
+ }
10786
+ }
10787
+ /**
10788
+ * Get all pending handoff requests for an agent.
10789
+ *
10790
+ * Returns handoff requests that have been addressed to the specified
10791
+ * agent and have not yet been accepted or rejected.
10792
+ *
10793
+ * @param agentId - The ID of the agent to get pending handoffs for
10794
+ * @returns List of pending handoff requests for the agent
10795
+ *
10796
+ * @example
10797
+ * ```typescript
10798
+ * const pending = await client.getPendingHandoffs("agent-b");
10799
+ * console.log(`${pending.length} pending handoffs`);
10800
+ * for (const request of pending) {
10801
+ * console.log(`From ${request.fromAgent}: ${request.reason}`);
10802
+ * }
10803
+ * ```
10804
+ */
10805
+ async getPendingHandoffs(agentId) {
10806
+ const pendingIds = this.pendingByAgent.get(agentId);
10807
+ if (!pendingIds) {
10808
+ return [];
10809
+ }
10810
+ const pending = [];
10811
+ for (const requestId of pendingIds) {
10812
+ const request = this.requests.get(requestId);
10813
+ if (request && !this.responses.has(requestId)) {
10814
+ pending.push(request);
10815
+ }
10816
+ }
10817
+ return pending;
10818
+ }
10819
+ /**
10820
+ * Get the response for a handoff request.
10821
+ *
10822
+ * Returns the response if the handoff has been accepted, rejected, or
10823
+ * timed out. Returns null if the handoff is still pending.
10824
+ *
10825
+ * @param handoffId - The ID of the handoff request
10826
+ * @returns The handoff response if available, null otherwise
10827
+ */
10828
+ async getHandoffResponse(handoffId) {
10829
+ return this.responses.get(handoffId) || null;
10830
+ }
10831
+ /**
10832
+ * Get the original handoff request.
10833
+ *
10834
+ * @param handoffId - The ID of the handoff request
10835
+ * @returns The handoff request if it exists, null otherwise
10836
+ */
10837
+ async getHandoffRequest(handoffId) {
10838
+ return this.requests.get(handoffId) || null;
10839
+ }
10840
+ };
10841
+
10842
+ // src/clients/workflow.ts
10843
+ var NodeStatus = /* @__PURE__ */ ((NodeStatus2) => {
10844
+ NodeStatus2[NodeStatus2["NODE_STATUS_UNSPECIFIED"] = 0] = "NODE_STATUS_UNSPECIFIED";
10845
+ NodeStatus2[NodeStatus2["PENDING"] = 1] = "PENDING";
10846
+ NodeStatus2[NodeStatus2["READY"] = 2] = "READY";
10847
+ NodeStatus2[NodeStatus2["RUNNING"] = 3] = "RUNNING";
10848
+ NodeStatus2[NodeStatus2["COMPLETED"] = 4] = "COMPLETED";
10849
+ NodeStatus2[NodeStatus2["FAILED"] = 5] = "FAILED";
10850
+ NodeStatus2[NodeStatus2["SKIPPED"] = 6] = "SKIPPED";
10851
+ return NodeStatus2;
10852
+ })(NodeStatus || {});
10853
+ var TriggerType = /* @__PURE__ */ ((TriggerType2) => {
10854
+ TriggerType2[TriggerType2["TRIGGER_TYPE_UNSPECIFIED"] = 0] = "TRIGGER_TYPE_UNSPECIFIED";
10855
+ TriggerType2[TriggerType2["EVENT"] = 1] = "EVENT";
10856
+ TriggerType2[TriggerType2["SCHEDULE"] = 2] = "SCHEDULE";
10857
+ TriggerType2[TriggerType2["MANUAL"] = 3] = "MANUAL";
10858
+ TriggerType2[TriggerType2["DEPENDENCY"] = 4] = "DEPENDENCY";
10859
+ return TriggerType2;
10860
+ })(TriggerType || {});
10861
+ var WorkflowStatus = /* @__PURE__ */ ((WorkflowStatus2) => {
10862
+ WorkflowStatus2[WorkflowStatus2["WORKFLOW_STATUS_UNSPECIFIED"] = 0] = "WORKFLOW_STATUS_UNSPECIFIED";
10863
+ WorkflowStatus2[WorkflowStatus2["CREATED"] = 1] = "CREATED";
10864
+ WorkflowStatus2[WorkflowStatus2["RUNNING"] = 2] = "RUNNING";
10865
+ WorkflowStatus2[WorkflowStatus2["COMPLETED"] = 3] = "COMPLETED";
10866
+ WorkflowStatus2[WorkflowStatus2["FAILED"] = 4] = "FAILED";
10867
+ WorkflowStatus2[WorkflowStatus2["CANCELLED"] = 5] = "CANCELLED";
10868
+ WorkflowStatus2[WorkflowStatus2["PAUSED"] = 6] = "PAUSED";
10869
+ return WorkflowStatus2;
10870
+ })(WorkflowStatus || {});
10871
+ var WorkflowValidationError = class extends Error {
10872
+ constructor(message) {
10873
+ super(message);
10874
+ this.name = "WorkflowValidationError";
10875
+ }
10876
+ };
10877
+ var WorkflowCycleError = class extends Error {
10878
+ constructor(message) {
10879
+ super(message);
10880
+ this.name = "WorkflowCycleError";
10881
+ }
10882
+ };
10883
+ function validateWorkflowDefinition(definition) {
10884
+ const nodeIds = new Set(Object.keys(definition.nodes));
10885
+ for (const [nodeId, node] of Object.entries(definition.nodes)) {
10886
+ for (const dep of node.dependencies) {
10887
+ if (!nodeIds.has(dep)) {
10888
+ throw new WorkflowValidationError(
10889
+ `Node '${nodeId}' has dependency '${dep}' which does not exist`
10890
+ );
10891
+ }
10892
+ if (dep === nodeId) {
10893
+ throw new WorkflowCycleError(
10894
+ `Node '${nodeId}' has a self-dependency`
10895
+ );
10896
+ }
10897
+ }
10898
+ }
10899
+ const visited = /* @__PURE__ */ new Set();
10900
+ const recursionStack = /* @__PURE__ */ new Set();
10901
+ function hasCycle(nodeId) {
10902
+ if (recursionStack.has(nodeId)) {
10903
+ return true;
10904
+ }
10905
+ if (visited.has(nodeId)) {
10906
+ return false;
10907
+ }
10908
+ visited.add(nodeId);
10909
+ recursionStack.add(nodeId);
10910
+ const node = definition.nodes[nodeId];
10911
+ for (const dep of node.dependencies) {
10912
+ if (hasCycle(dep)) {
10913
+ return true;
10914
+ }
10915
+ }
10916
+ recursionStack.delete(nodeId);
10917
+ return false;
10918
+ }
10919
+ for (const nodeId of nodeIds) {
10920
+ if (hasCycle(nodeId)) {
10921
+ throw new WorkflowCycleError(
10922
+ `Workflow contains a cycle involving node '${nodeId}'`
10923
+ );
10924
+ }
10925
+ }
10926
+ }
10927
+ function generateInstanceId() {
10928
+ return `wf-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
10929
+ }
10930
+ var WorkflowClient = class {
10931
+ definitions = /* @__PURE__ */ new Map();
10932
+ instances = /* @__PURE__ */ new Map();
10933
+ instancesByWorkflow = /* @__PURE__ */ new Map();
10934
+ /**
10935
+ * Create a new workflow from a definition.
10936
+ *
10937
+ * Validates the workflow definition and stores it for later execution.
10938
+ *
10939
+ * @param definition - The workflow definition to create
10940
+ * @returns The workflow_id of the created workflow
10941
+ * @throws WorkflowValidationError if the definition is invalid
10942
+ * @throws WorkflowCycleError if the workflow contains a cycle
10943
+ *
10944
+ * @example
10945
+ * ```typescript
10946
+ * const client = new WorkflowClient();
10947
+ * const definition: WorkflowDefinition = {
10948
+ * workflowId: "review-workflow",
10949
+ * nodes: {
10950
+ * "produce": {
10951
+ * nodeId: "produce",
10952
+ * agentId: "producer-agent",
10953
+ * dependencies: [],
10954
+ * triggerType: TriggerType.MANUAL,
10955
+ * inputMapping: {},
10956
+ * outputMapping: { "artifact": "produced_artifact" },
10957
+ * metadata: {}
10958
+ * },
10959
+ * "review": {
10960
+ * nodeId: "review",
10961
+ * agentId: "critic-agent",
10962
+ * dependencies: ["produce"],
10963
+ * triggerType: TriggerType.DEPENDENCY,
10964
+ * inputMapping: { "artifact": "produced_artifact" },
10965
+ * outputMapping: { "result": "review_result" },
10966
+ * metadata: {}
10967
+ * }
10968
+ * },
10969
+ * metadata: {}
10970
+ * };
10971
+ * const workflowId = await client.createWorkflow(definition);
10972
+ * ```
10973
+ */
10974
+ async createWorkflow(definition) {
10975
+ validateWorkflowDefinition(definition);
10976
+ if (this.definitions.has(definition.workflowId)) {
10977
+ throw new WorkflowValidationError(
10978
+ `Workflow with ID '${definition.workflowId}' already exists`
10979
+ );
10980
+ }
10981
+ const definitionWithTimestamp = {
10982
+ ...definition,
10983
+ createdAt: definition.createdAt || (/* @__PURE__ */ new Date()).toISOString()
10984
+ };
10985
+ this.definitions.set(definition.workflowId, definitionWithTimestamp);
10986
+ this.instancesByWorkflow.set(definition.workflowId, /* @__PURE__ */ new Set());
10987
+ return definition.workflowId;
10988
+ }
10989
+ /**
10990
+ * Start a new instance of a workflow.
10991
+ *
10992
+ * Creates a new workflow instance and initializes all nodes to their
10993
+ * starting states based on dependencies.
10994
+ *
10995
+ * @param workflowId - The ID of the workflow to start
10996
+ * @param initialData - Optional initial workflow data (JSON string)
10997
+ * @param metadata - Optional runtime metadata
10998
+ * @returns The created workflow instance
10999
+ * @throws WorkflowValidationError if the workflow does not exist
11000
+ *
11001
+ * @example
11002
+ * ```typescript
11003
+ * const instance = await client.startWorkflow("review-workflow");
11004
+ * console.log(instance.status); // WorkflowStatus.RUNNING
11005
+ * ```
11006
+ */
11007
+ async startWorkflow(workflowId, initialData, metadata) {
11008
+ const definition = this.definitions.get(workflowId);
11009
+ if (!definition) {
11010
+ throw new WorkflowValidationError(
11011
+ `Workflow with ID '${workflowId}' does not exist`
11012
+ );
11013
+ }
11014
+ const instanceId = generateInstanceId();
11015
+ const now = (/* @__PURE__ */ new Date()).toISOString();
11016
+ const nodeStates = {};
11017
+ for (const [nodeId, node] of Object.entries(definition.nodes)) {
11018
+ const status = node.dependencies.length === 0 ? 2 /* READY */ : 1 /* PENDING */;
11019
+ nodeStates[nodeId] = {
11020
+ nodeId,
11021
+ status
11022
+ };
11023
+ }
11024
+ const instance = {
11025
+ instanceId,
11026
+ workflowId,
11027
+ status: 2 /* RUNNING */,
11028
+ nodeStates,
11029
+ workflowData: initialData || "{}",
11030
+ startedAt: now,
11031
+ metadata: metadata || {}
11032
+ };
11033
+ this.instances.set(instanceId, instance);
11034
+ this.instancesByWorkflow.get(workflowId).add(instanceId);
11035
+ return instance;
11036
+ }
11037
+ /**
11038
+ * Get the current status of a workflow instance.
11039
+ *
11040
+ * @param instanceId - The ID of the workflow instance
11041
+ * @returns The workflow instance with current state
11042
+ * @throws WorkflowValidationError if the instance does not exist
11043
+ *
11044
+ * @example
11045
+ * ```typescript
11046
+ * const instance = await client.getWorkflowStatus("wf-123-abc");
11047
+ * console.log(instance.status);
11048
+ * for (const [nodeId, state] of Object.entries(instance.nodeStates)) {
11049
+ * console.log(`${nodeId}: ${NodeStatus[state.status]}`);
11050
+ * }
11051
+ * ```
11052
+ */
11053
+ async getWorkflowStatus(instanceId) {
11054
+ const instance = this.instances.get(instanceId);
11055
+ if (!instance) {
11056
+ throw new WorkflowValidationError(
11057
+ `Workflow instance with ID '${instanceId}' does not exist`
11058
+ );
11059
+ }
11060
+ return instance;
11061
+ }
11062
+ /**
11063
+ * Cancel a running workflow instance.
11064
+ *
11065
+ * Marks the workflow as cancelled and stops any pending nodes.
11066
+ *
11067
+ * @param instanceId - The ID of the workflow instance to cancel
11068
+ * @throws WorkflowValidationError if the instance does not exist
11069
+ * @throws WorkflowValidationError if the workflow is not in a cancellable state
11070
+ *
11071
+ * @example
11072
+ * ```typescript
11073
+ * await client.cancelWorkflow("wf-123-abc");
11074
+ * const instance = await client.getWorkflowStatus("wf-123-abc");
11075
+ * console.log(instance.status); // WorkflowStatus.CANCELLED
11076
+ * ```
11077
+ */
11078
+ async cancelWorkflow(instanceId) {
11079
+ const instance = this.instances.get(instanceId);
11080
+ if (!instance) {
11081
+ throw new WorkflowValidationError(
11082
+ `Workflow instance with ID '${instanceId}' does not exist`
11083
+ );
11084
+ }
11085
+ if (instance.status === 3 /* COMPLETED */ || instance.status === 4 /* FAILED */ || instance.status === 5 /* CANCELLED */) {
11086
+ throw new WorkflowValidationError(
11087
+ `Workflow instance '${instanceId}' is already in terminal state '${WorkflowStatus[instance.status]}'`
11088
+ );
11089
+ }
11090
+ instance.status = 5 /* CANCELLED */;
11091
+ instance.completedAt = (/* @__PURE__ */ new Date()).toISOString();
11092
+ for (const nodeState of Object.values(instance.nodeStates)) {
11093
+ if (nodeState.status === 1 /* PENDING */ || nodeState.status === 2 /* READY */) {
11094
+ nodeState.status = 6 /* SKIPPED */;
11095
+ }
11096
+ }
11097
+ this.instances.set(instanceId, instance);
11098
+ }
11099
+ /**
11100
+ * Get the workflow definition.
11101
+ *
11102
+ * @param workflowId - The ID of the workflow
11103
+ * @returns The workflow definition if it exists, null otherwise
11104
+ */
11105
+ async getWorkflowDefinition(workflowId) {
11106
+ return this.definitions.get(workflowId) || null;
11107
+ }
11108
+ /**
11109
+ * List all instances of a workflow.
11110
+ *
11111
+ * @param workflowId - The ID of the workflow
11112
+ * @returns List of all instances for the workflow
11113
+ */
11114
+ async listWorkflowInstances(workflowId) {
11115
+ const instanceIds = this.instancesByWorkflow.get(workflowId);
11116
+ if (!instanceIds) {
11117
+ return [];
11118
+ }
11119
+ const instances = [];
11120
+ for (const instanceId of instanceIds) {
11121
+ const instance = this.instances.get(instanceId);
11122
+ if (instance) {
11123
+ instances.push(instance);
11124
+ }
11125
+ }
11126
+ return instances;
11127
+ }
11128
+ /**
11129
+ * Update the state of a node in a workflow instance.
11130
+ *
11131
+ * This is an internal method used by node executors to report progress.
11132
+ *
11133
+ * @param instanceId - The ID of the workflow instance
11134
+ * @param nodeId - The ID of the node to update
11135
+ * @param status - The new status of the node
11136
+ * @param output - Optional output data from the node
11137
+ * @param error - Optional error message if the node failed
11138
+ * @throws WorkflowValidationError if the instance or node does not exist
11139
+ */
11140
+ async updateNodeState(instanceId, nodeId, status, output, error) {
11141
+ const instance = this.instances.get(instanceId);
11142
+ if (!instance) {
11143
+ throw new WorkflowValidationError(
11144
+ `Workflow instance with ID '${instanceId}' does not exist`
11145
+ );
11146
+ }
11147
+ const nodeState = instance.nodeStates[nodeId];
11148
+ if (!nodeState) {
11149
+ throw new WorkflowValidationError(
11150
+ `Node '${nodeId}' does not exist in workflow instance '${instanceId}'`
11151
+ );
11152
+ }
11153
+ const now = (/* @__PURE__ */ new Date()).toISOString();
11154
+ nodeState.status = status;
11155
+ if (status === 3 /* RUNNING */ && !nodeState.startedAt) {
11156
+ nodeState.startedAt = now;
11157
+ }
11158
+ if (status === 4 /* COMPLETED */ || status === 5 /* FAILED */ || status === 6 /* SKIPPED */) {
11159
+ nodeState.completedAt = now;
11160
+ }
11161
+ if (output !== void 0) {
11162
+ nodeState.output = output;
11163
+ }
11164
+ if (error !== void 0) {
11165
+ nodeState.error = error;
11166
+ }
11167
+ if (status === 4 /* COMPLETED */) {
11168
+ const definition = this.definitions.get(instance.workflowId);
11169
+ if (definition) {
11170
+ this.updateDependentNodes(instance, definition, nodeId);
11171
+ }
11172
+ }
11173
+ this.checkWorkflowCompletion(instance);
11174
+ this.instances.set(instanceId, instance);
11175
+ }
11176
+ /**
11177
+ * Update the status of nodes that depend on a completed node.
11178
+ */
11179
+ updateDependentNodes(instance, definition, completedNodeId) {
11180
+ for (const [nodeId, node] of Object.entries(definition.nodes)) {
11181
+ if (node.dependencies.includes(completedNodeId)) {
11182
+ const nodeState = instance.nodeStates[nodeId];
11183
+ if (nodeState.status === 1 /* PENDING */) {
11184
+ const allDepsComplete = node.dependencies.every((dep) => {
11185
+ const depState = instance.nodeStates[dep];
11186
+ return depState && depState.status === 4 /* COMPLETED */;
11187
+ });
11188
+ if (allDepsComplete) {
11189
+ nodeState.status = 2 /* READY */;
11190
+ }
11191
+ }
11192
+ }
11193
+ }
11194
+ }
11195
+ /**
11196
+ * Check if a workflow instance is complete and update its status.
11197
+ */
11198
+ checkWorkflowCompletion(instance) {
11199
+ const nodeStatuses = Object.values(instance.nodeStates).map((s) => s.status);
11200
+ if (nodeStatuses.some((s) => s === 5 /* FAILED */)) {
11201
+ instance.status = 4 /* FAILED */;
11202
+ instance.completedAt = (/* @__PURE__ */ new Date()).toISOString();
11203
+ return;
11204
+ }
11205
+ const allComplete = nodeStatuses.every(
11206
+ (s) => s === 4 /* COMPLETED */ || s === 6 /* SKIPPED */
11207
+ );
11208
+ if (allComplete) {
11209
+ instance.status = 3 /* COMPLETED */;
11210
+ instance.completedAt = (/* @__PURE__ */ new Date()).toISOString();
11211
+ }
11212
+ }
11213
+ /**
11214
+ * Update the shared workflow data.
11215
+ *
11216
+ * @param instanceId - The ID of the workflow instance
11217
+ * @param workflowData - The new workflow data (JSON string)
11218
+ * @throws WorkflowValidationError if the instance does not exist
11219
+ */
11220
+ async updateWorkflowData(instanceId, workflowData) {
11221
+ const instance = this.instances.get(instanceId);
11222
+ if (!instance) {
11223
+ throw new WorkflowValidationError(
11224
+ `Workflow instance with ID '${instanceId}' does not exist`
11225
+ );
11226
+ }
11227
+ instance.workflowData = workflowData;
11228
+ this.instances.set(instanceId, instance);
11229
+ }
11230
+ };
11231
+
10277
11232
  // src/internal/envelope.ts
10278
11233
  import crypto2 from "node:crypto";
10279
11234
  function nowTimestamp(date = /* @__PURE__ */ new Date()) {
@@ -10516,11 +11471,15 @@ async function sendMessageWithAck(router, inboundStream, envelope, ackLifecycle,
10516
11471
  }
10517
11472
  }
10518
11473
  };
10519
- return new Promise(async (resolve, reject) => {
10520
- let timeout;
11474
+ await router.sendMessage(envelope);
11475
+ return new Promise((resolve, reject) => {
11476
+ const timeout = setTimeout(() => {
11477
+ ackLifecycle.mark(envelope.message_id, 6 /* TIMED_OUT */, "received_timeout");
11478
+ cleanup();
11479
+ reject(new Error("ACK RECEIVED timeout exceeded"));
11480
+ }, receivedTimeoutMs);
10521
11481
  const cleanup = () => {
10522
- if (timeout)
10523
- clearTimeout(timeout);
11482
+ clearTimeout(timeout);
10524
11483
  inboundStream.removeListener("data", onData);
10525
11484
  inboundStream.removeListener("error", onErr);
10526
11485
  };
@@ -10530,27 +11489,13 @@ async function sendMessageWithAck(router, inboundStream, envelope, ackLifecycle,
10530
11489
  };
10531
11490
  inboundStream.on("data", onData);
10532
11491
  inboundStream.on("error", onErr);
10533
- try {
10534
- await router.sendMessage(envelope);
10535
- } catch (e) {
10536
- cleanup();
10537
- return reject(e);
10538
- }
10539
- timeout = setTimeout(() => {
10540
- ackLifecycle.mark(envelope.message_id, 6 /* TIMED_OUT */, "received_timeout");
10541
- cleanup();
10542
- reject(new Error("ACK RECEIVED timeout exceeded"));
10543
- }, receivedTimeoutMs);
10544
11492
  const checkInterval = setInterval(() => {
10545
11493
  const state = ackLifecycle.get(envelope.message_id);
10546
11494
  if (!state)
10547
11495
  return;
10548
11496
  if (state.stage === 1 /* RECEIVED */ || state.stage === 2 /* READ */ || state.stage === 3 /* FULFILLED */) {
10549
11497
  clearInterval(checkInterval);
10550
- if (timeout)
10551
- clearTimeout(timeout);
10552
- inboundStream.removeListener("data", onData);
10553
- inboundStream.removeListener("error", onErr);
11498
+ cleanup();
10554
11499
  resolve();
10555
11500
  }
10556
11501
  }, 25);
@@ -10697,6 +11642,1187 @@ var JSONFilePersistence = class {
10697
11642
  }
10698
11643
  };
10699
11644
 
11645
+ // src/runtime/voting.ts
11646
+ var SimpleAverageAggregator = class {
11647
+ /**
11648
+ * Aggregate votes using simple arithmetic mean.
11649
+ *
11650
+ * @param votes - List of critic votes to aggregate
11651
+ * @returns AggregatedScore with simple mean in both mean and weightedMean fields
11652
+ * @throws NegotiationValidationError if votes list is empty
11653
+ */
11654
+ aggregate(votes) {
11655
+ if (votes.length === 0) {
11656
+ throw new NegotiationValidationError(
11657
+ "Cannot aggregate empty list of votes"
11658
+ );
11659
+ }
11660
+ const scores = votes.map((v) => v.score);
11661
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
11662
+ const minScore = Math.min(...scores);
11663
+ const maxScore = Math.max(...scores);
11664
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
11665
+ const stdDev = Math.sqrt(variance);
11666
+ return {
11667
+ mean,
11668
+ minScore,
11669
+ maxScore,
11670
+ stdDev,
11671
+ weightedMean: mean,
11672
+ voteCount: votes.length
11673
+ };
11674
+ }
11675
+ };
11676
+ var ConfidenceWeightedAggregator = class {
11677
+ /**
11678
+ * Aggregate votes using confidence weighting.
11679
+ *
11680
+ * @param votes - List of critic votes to aggregate
11681
+ * @returns AggregatedScore with confidence-weighted mean
11682
+ * @throws NegotiationValidationError if votes list is empty
11683
+ */
11684
+ aggregate(votes) {
11685
+ if (votes.length === 0) {
11686
+ throw new NegotiationValidationError(
11687
+ "Cannot aggregate empty list of votes"
11688
+ );
11689
+ }
11690
+ const scores = votes.map((v) => v.score);
11691
+ const confidences = votes.map((v) => v.confidence);
11692
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
11693
+ const minScore = Math.min(...scores);
11694
+ const maxScore = Math.max(...scores);
11695
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
11696
+ const stdDev = Math.sqrt(variance);
11697
+ const totalConfidence = confidences.reduce((a, b) => a + b, 0);
11698
+ let weightedMean;
11699
+ if (totalConfidence > 0) {
11700
+ weightedMean = scores.reduce((sum, s, i) => sum + s * confidences[i], 0) / totalConfidence;
11701
+ } else {
11702
+ weightedMean = mean;
11703
+ }
11704
+ return {
11705
+ mean,
11706
+ minScore,
11707
+ maxScore,
11708
+ stdDev,
11709
+ weightedMean,
11710
+ voteCount: votes.length
11711
+ };
11712
+ }
11713
+ };
11714
+ var MajorityVoteAggregator = class {
11715
+ /**
11716
+ * Aggregate votes using majority voting.
11717
+ *
11718
+ * @param votes - List of critic votes to aggregate
11719
+ * @returns AggregatedScore with score based on majority outcome
11720
+ * @throws NegotiationValidationError if votes list is empty
11721
+ */
11722
+ aggregate(votes) {
11723
+ if (votes.length === 0) {
11724
+ throw new NegotiationValidationError(
11725
+ "Cannot aggregate empty list of votes"
11726
+ );
11727
+ }
11728
+ const scores = votes.map((v) => v.score);
11729
+ const passedCount = votes.filter((v) => v.passed).length;
11730
+ const failedCount = votes.length - passedCount;
11731
+ let majorityScore;
11732
+ if (passedCount === votes.length) {
11733
+ majorityScore = 10;
11734
+ } else if (failedCount === votes.length) {
11735
+ majorityScore = 0;
11736
+ } else if (passedCount > failedCount) {
11737
+ majorityScore = 7.5;
11738
+ } else if (failedCount > passedCount) {
11739
+ majorityScore = 2.5;
11740
+ } else {
11741
+ majorityScore = 5;
11742
+ }
11743
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
11744
+ const minScore = Math.min(...scores);
11745
+ const maxScore = Math.max(...scores);
11746
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
11747
+ const stdDev = Math.sqrt(variance);
11748
+ return {
11749
+ mean,
11750
+ minScore,
11751
+ maxScore,
11752
+ stdDev,
11753
+ weightedMean: majorityScore,
11754
+ voteCount: votes.length
11755
+ };
11756
+ }
11757
+ };
11758
+ var BordaCountAggregator = class {
11759
+ /**
11760
+ * Aggregate votes using Borda count.
11761
+ *
11762
+ * @param votes - List of critic votes to aggregate
11763
+ * @returns AggregatedScore with Borda count normalized score
11764
+ * @throws NegotiationValidationError if votes list is empty
11765
+ */
11766
+ aggregate(votes) {
11767
+ if (votes.length === 0) {
11768
+ throw new NegotiationValidationError(
11769
+ "Cannot aggregate empty list of votes"
11770
+ );
11771
+ }
11772
+ const scores = votes.map((v) => v.score);
11773
+ const n = votes.length;
11774
+ const mean = scores.reduce((a, b) => a + b, 0) / n;
11775
+ const minScore = Math.min(...scores);
11776
+ const maxScore = Math.max(...scores);
11777
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / n;
11778
+ const stdDev = Math.sqrt(variance);
11779
+ const indexedScores = scores.map((score, idx) => ({ score, idx }));
11780
+ indexedScores.sort((a, b) => b.score - a.score);
11781
+ let totalPoints = 0;
11782
+ for (let rank = 0; rank < indexedScores.length; rank++) {
11783
+ const points = n - rank;
11784
+ totalPoints += points;
11785
+ }
11786
+ const avgPoints = totalPoints / n;
11787
+ const bordaScore = avgPoints / n * 10;
11788
+ return {
11789
+ mean,
11790
+ minScore,
11791
+ maxScore,
11792
+ stdDev,
11793
+ weightedMean: bordaScore,
11794
+ voteCount: n
11795
+ };
11796
+ }
11797
+ };
11798
+ var VotingAnalyzer = class {
11799
+ strategy;
11800
+ /**
11801
+ * Initialize analyzer with a strategy.
11802
+ *
11803
+ * @param strategy - The aggregation strategy to use
11804
+ */
11805
+ constructor(strategy) {
11806
+ this.strategy = strategy;
11807
+ }
11808
+ /**
11809
+ * Aggregate votes using the configured strategy.
11810
+ *
11811
+ * @param votes - List of critic votes to aggregate
11812
+ * @returns AggregatedScore with aggregation results
11813
+ * @throws NegotiationValidationError if votes list is empty
11814
+ */
11815
+ aggregate(votes) {
11816
+ return this.strategy.aggregate(votes);
11817
+ }
11818
+ /**
11819
+ * Compute Shannon entropy of vote distribution.
11820
+ *
11821
+ * Entropy measures the uncertainty or disorder in the vote distribution.
11822
+ * Higher entropy indicates more disagreement/uncertainty, lower entropy
11823
+ * indicates more consensus.
11824
+ *
11825
+ * The score range [0, 10] is divided into bins, and entropy is computed
11826
+ * over the probability distribution of votes across bins.
11827
+ *
11828
+ * @param votes - List of critic votes
11829
+ * @returns Entropy value in bits (0 = perfect consensus, higher = more uncertainty)
11830
+ * @throws NegotiationValidationError if votes list is empty
11831
+ */
11832
+ computeEntropy(votes) {
11833
+ if (votes.length === 0) {
11834
+ throw new NegotiationValidationError(
11835
+ "Cannot compute entropy of empty vote list"
11836
+ );
11837
+ }
11838
+ const numBins = 5;
11839
+ const binWidth = 10 / numBins;
11840
+ const binCounts = new Array(numBins).fill(0);
11841
+ for (const vote of votes) {
11842
+ const binIdx = Math.min(Math.floor(vote.score / binWidth), numBins - 1);
11843
+ binCounts[binIdx]++;
11844
+ }
11845
+ const total = votes.length;
11846
+ let entropy = 0;
11847
+ for (const count of binCounts) {
11848
+ if (count > 0) {
11849
+ const probability = count / total;
11850
+ entropy -= probability * Math.log2(probability);
11851
+ }
11852
+ }
11853
+ return entropy;
11854
+ }
11855
+ /**
11856
+ * Detect if votes show strong consensus.
11857
+ *
11858
+ * Consensus is detected when:
11859
+ * 1. Standard deviation of scores is low (< 2.0)
11860
+ * 2. A large proportion of critics agree on pass/fail (>= threshold)
11861
+ *
11862
+ * @param votes - List of critic votes
11863
+ * @param threshold - Minimum proportion of agreement required (default 0.8 = 80%)
11864
+ * @returns True if consensus is detected, false otherwise
11865
+ * @throws NegotiationValidationError if votes list is empty or threshold not in [0, 1]
11866
+ */
11867
+ detectConsensus(votes, threshold = 0.8) {
11868
+ if (votes.length === 0) {
11869
+ throw new NegotiationValidationError(
11870
+ "Cannot detect consensus in empty vote list"
11871
+ );
11872
+ }
11873
+ if (threshold < 0 || threshold > 1) {
11874
+ throw new NegotiationValidationError(
11875
+ `Threshold must be in [0, 1], got ${threshold}`
11876
+ );
11877
+ }
11878
+ const scores = votes.map((v) => v.score);
11879
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
11880
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
11881
+ const stdDev = Math.sqrt(variance);
11882
+ if (stdDev >= 2) {
11883
+ return false;
11884
+ }
11885
+ const passedCount = votes.filter((v) => v.passed).length;
11886
+ const failedCount = votes.length - passedCount;
11887
+ const agreementRatio = Math.max(passedCount, failedCount) / votes.length;
11888
+ return agreementRatio >= threshold;
11889
+ }
11890
+ /**
11891
+ * Detect if votes show polarization (bimodal distribution).
11892
+ *
11893
+ * Polarization is detected when votes cluster into two distinct groups,
11894
+ * typically at opposite ends of the score spectrum. This is identified by:
11895
+ * 1. High standard deviation (>= 3.0)
11896
+ * 2. Low density in the middle range (4-6)
11897
+ * 3. High density in the extremes (0-3 or 7-10)
11898
+ *
11899
+ * @param votes - List of critic votes
11900
+ * @returns True if polarization is detected, false otherwise
11901
+ * @throws NegotiationValidationError if votes list is empty
11902
+ */
11903
+ detectPolarization(votes) {
11904
+ if (votes.length === 0) {
11905
+ throw new NegotiationValidationError(
11906
+ "Cannot detect polarization in empty vote list"
11907
+ );
11908
+ }
11909
+ if (votes.length < 3) {
11910
+ return false;
11911
+ }
11912
+ const scores = votes.map((v) => v.score);
11913
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
11914
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
11915
+ const stdDev = Math.sqrt(variance);
11916
+ if (stdDev < 3) {
11917
+ return false;
11918
+ }
11919
+ const lowCount = scores.filter((s) => s <= 3).length;
11920
+ const middleCount = scores.filter((s) => s > 3 && s < 7).length;
11921
+ const highCount = scores.filter((s) => s >= 7).length;
11922
+ const hasLowCluster = lowCount >= votes.length * 0.3;
11923
+ const hasHighCluster = highCount >= votes.length * 0.3;
11924
+ const middleSparse = middleCount <= votes.length * 0.2;
11925
+ return hasLowCluster && hasHighCluster && middleSparse;
11926
+ }
11927
+ /**
11928
+ * Compute variance of confidence levels across votes.
11929
+ *
11930
+ * High variance in confidence suggests critics have different levels of
11931
+ * certainty about their evaluations, which may indicate the artifact is
11932
+ * harder to assess or has ambiguous quality.
11933
+ *
11934
+ * @param votes - List of critic votes
11935
+ * @returns Variance of confidence values
11936
+ * @throws NegotiationValidationError if votes list is empty
11937
+ */
11938
+ computeConfidenceVariance(votes) {
11939
+ if (votes.length === 0) {
11940
+ throw new NegotiationValidationError(
11941
+ "Cannot compute confidence variance of empty vote list"
11942
+ );
11943
+ }
11944
+ const confidences = votes.map((v) => v.confidence);
11945
+ const meanConfidence = confidences.reduce((a, b) => a + b, 0) / confidences.length;
11946
+ const variance = confidences.reduce(
11947
+ (sum, c) => sum + Math.pow(c - meanConfidence, 2),
11948
+ 0
11949
+ ) / confidences.length;
11950
+ return variance;
11951
+ }
11952
+ /**
11953
+ * Get comprehensive summary of vote characteristics.
11954
+ *
11955
+ * Combines multiple analytical methods to provide a complete picture
11956
+ * of the vote distribution and critic agreement.
11957
+ *
11958
+ * @param votes - List of critic votes
11959
+ * @returns Object with summary statistics
11960
+ * @throws NegotiationValidationError if votes list is empty
11961
+ */
11962
+ getVoteSummary(votes) {
11963
+ if (votes.length === 0) {
11964
+ throw new NegotiationValidationError("Cannot summarize empty vote list");
11965
+ }
11966
+ const passedCount = votes.filter((v) => v.passed).length;
11967
+ return {
11968
+ entropy: this.computeEntropy(votes),
11969
+ consensus: this.detectConsensus(votes),
11970
+ polarization: this.detectPolarization(votes),
11971
+ confidenceVariance: this.computeConfidenceVariance(votes),
11972
+ passRate: passedCount / votes.length
11973
+ };
11974
+ }
11975
+ };
11976
+
11977
+ // src/runtime/policyStore.ts
11978
+ import fsp2 from "node:fs/promises";
11979
+ import path3 from "node:path";
11980
+ var HitlMode = /* @__PURE__ */ ((HitlMode2) => {
11981
+ HitlMode2["NONE"] = "None";
11982
+ HitlMode2["PAUSE_BETWEEN_ROUNDS"] = "PauseBetweenRounds";
11983
+ HitlMode2["PAUSE_ON_FINAL_ACCEPT"] = "PauseOnFinalAccept";
11984
+ return HitlMode2;
11985
+ })(HitlMode || {});
11986
+ var DEFAULT_EXECUTION_POLICY = {
11987
+ timeoutMs: 6e4,
11988
+ maxRetries: 3,
11989
+ backoff: "exponential",
11990
+ worktreeRequired: false,
11991
+ networkPolicy: "restricted",
11992
+ privilegeLevel: "standard",
11993
+ budgetCpuMs: 3e4,
11994
+ budgetWallMs: 6e4
11995
+ };
11996
+ var DEFAULT_ESCALATION_POLICY = {
11997
+ autoEscalateOnDeadlock: true,
11998
+ deadlockRounds: 3,
11999
+ escalationReasons: ["debate_deadlock", "security_flag", "timeout"],
12000
+ defaultAction: "escalate"
12001
+ };
12002
+ var PolicyStoreError = class extends Error {
12003
+ constructor(message) {
12004
+ super(message);
12005
+ this.name = "PolicyStoreError";
12006
+ }
12007
+ };
12008
+ var DEFAULT_NEGOTIATION_POLICY = {
12009
+ maxRounds: 10,
12010
+ scoreThreshold: 0.7,
12011
+ diffTolerance: 0.3,
12012
+ roundTimeoutMs: 3e4,
12013
+ tokenBudgetPerRound: 4096,
12014
+ totalTokenBudget: 0,
12015
+ // unlimited
12016
+ oscillationLimit: 3,
12017
+ hitl: "None" /* NONE */,
12018
+ scoring: {
12019
+ requireSchemaValid: true,
12020
+ requireExamplesPass: false,
12021
+ llmWeight: 0.5
12022
+ }
12023
+ };
12024
+ function generatePolicyId() {
12025
+ return `policy-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
12026
+ }
12027
+ function generatePolicyVersion() {
12028
+ const timestampMs = Date.now();
12029
+ const uniqueId = Math.random().toString(36).substring(2, 11);
12030
+ return `${timestampMs}_${uniqueId}`;
12031
+ }
12032
+ var InMemoryPolicyStore = class {
12033
+ // Maps policy_id -> list of EffectivePolicy (chronological order)
12034
+ policies = /* @__PURE__ */ new Map();
12035
+ profiles = /* @__PURE__ */ new Map();
12036
+ constructor() {
12037
+ this.initializeDefaultProfiles();
12038
+ }
12039
+ /**
12040
+ * Initialize default policy profiles.
12041
+ */
12042
+ initializeDefaultProfiles() {
12043
+ const lowProfile = {
12044
+ name: "LOW",
12045
+ negotiation: {
12046
+ maxRounds: 5,
12047
+ scoreThreshold: 0.6,
12048
+ diffTolerance: 0.4,
12049
+ roundTimeoutMs: 6e4,
12050
+ tokenBudgetPerRound: 2048,
12051
+ totalTokenBudget: 0,
12052
+ oscillationLimit: 5,
12053
+ hitl: "None" /* NONE */,
12054
+ scoring: {
12055
+ requireSchemaValid: false,
12056
+ requireExamplesPass: false,
12057
+ llmWeight: 0.3
12058
+ }
12059
+ },
12060
+ execution: {
12061
+ ...DEFAULT_EXECUTION_POLICY,
12062
+ timeoutMs: 12e4,
12063
+ // More lenient for low priority
12064
+ maxRetries: 5
12065
+ },
12066
+ escalation: {
12067
+ ...DEFAULT_ESCALATION_POLICY,
12068
+ deadlockRounds: 5
12069
+ // More tolerant
12070
+ }
12071
+ };
12072
+ const mediumProfile = {
12073
+ name: "MEDIUM",
12074
+ negotiation: { ...DEFAULT_NEGOTIATION_POLICY },
12075
+ execution: { ...DEFAULT_EXECUTION_POLICY },
12076
+ escalation: { ...DEFAULT_ESCALATION_POLICY }
12077
+ };
12078
+ const highProfile = {
12079
+ name: "HIGH",
12080
+ negotiation: {
12081
+ maxRounds: 15,
12082
+ scoreThreshold: 0.85,
12083
+ diffTolerance: 0.2,
12084
+ roundTimeoutMs: 2e4,
12085
+ tokenBudgetPerRound: 8192,
12086
+ totalTokenBudget: 1e5,
12087
+ oscillationLimit: 2,
12088
+ hitl: "PauseOnFinalAccept" /* PAUSE_ON_FINAL_ACCEPT */,
12089
+ scoring: {
12090
+ requireSchemaValid: true,
12091
+ requireExamplesPass: true,
12092
+ llmWeight: 0.7
12093
+ }
12094
+ },
12095
+ execution: {
12096
+ ...DEFAULT_EXECUTION_POLICY,
12097
+ timeoutMs: 3e4,
12098
+ // Stricter timeout
12099
+ maxRetries: 2,
12100
+ networkPolicy: "none"
12101
+ // More restrictive
12102
+ },
12103
+ escalation: {
12104
+ ...DEFAULT_ESCALATION_POLICY,
12105
+ deadlockRounds: 2,
12106
+ // Quick escalation
12107
+ autoEscalateOnDeadlock: true
12108
+ }
12109
+ };
12110
+ this.profiles.set("LOW", lowProfile);
12111
+ this.profiles.set("MEDIUM", mediumProfile);
12112
+ this.profiles.set("HIGH", highProfile);
12113
+ }
12114
+ /**
12115
+ * Get the latest version of a policy by its ID.
12116
+ *
12117
+ * @param policyId - The unique identifier of the policy
12118
+ * @returns The most recent effective policy if found, null otherwise
12119
+ */
12120
+ async getPolicy(policyId) {
12121
+ const versions = this.policies.get(policyId);
12122
+ if (!versions || versions.length === 0) {
12123
+ return null;
12124
+ }
12125
+ return versions[versions.length - 1];
12126
+ }
12127
+ /**
12128
+ * Save a policy snapshot to the version history.
12129
+ *
12130
+ * If the policy does not have an ID, one will be generated.
12131
+ * If the policy does not have a version, one will be generated.
12132
+ *
12133
+ * @param policy - The effective policy to save
12134
+ * @returns The policy ID
12135
+ */
12136
+ async savePolicy(policy) {
12137
+ const policyId = policy.policyId || generatePolicyId();
12138
+ const version2 = policy.version || generatePolicyVersion();
12139
+ const policyWithMeta = {
12140
+ ...policy,
12141
+ policyId,
12142
+ version: version2,
12143
+ createdAt: policy.createdAt || (/* @__PURE__ */ new Date()).toISOString()
12144
+ };
12145
+ const versions = this.policies.get(policyId) || [];
12146
+ versions.push(policyWithMeta);
12147
+ this.policies.set(policyId, versions);
12148
+ return policyId;
12149
+ }
12150
+ /**
12151
+ * List all policy IDs, optionally filtered by prefix.
12152
+ *
12153
+ * @param prefix - Optional prefix to filter policy IDs
12154
+ * @returns List of matching policy IDs
12155
+ */
12156
+ async listPolicies(prefix) {
12157
+ const allIds = Array.from(this.policies.keys());
12158
+ if (prefix === void 0) {
12159
+ return allIds;
12160
+ }
12161
+ return allIds.filter((id) => id.startsWith(prefix));
12162
+ }
12163
+ /**
12164
+ * Delete a policy by its ID (removes all versions).
12165
+ *
12166
+ * @param policyId - The unique identifier of the policy
12167
+ * @returns True if the policy was deleted, false if not found
12168
+ */
12169
+ async deletePolicy(policyId) {
12170
+ return this.policies.delete(policyId);
12171
+ }
12172
+ /**
12173
+ * Retrieve the complete version history for a policy.
12174
+ *
12175
+ * Returns policies in chronological order (oldest to newest).
12176
+ *
12177
+ * @param policyId - The unique identifier of the policy
12178
+ * @returns List of all versions of the policy
12179
+ */
12180
+ async getHistory(policyId) {
12181
+ const versions = this.policies.get(policyId);
12182
+ if (!versions) {
12183
+ return [];
12184
+ }
12185
+ return [...versions];
12186
+ }
12187
+ /**
12188
+ * Get a policy profile by name.
12189
+ *
12190
+ * @param name - The profile name
12191
+ * @returns The policy profile if found, null otherwise
12192
+ */
12193
+ async getProfile(name) {
12194
+ return this.profiles.get(name) || null;
12195
+ }
12196
+ /**
12197
+ * Save a policy profile.
12198
+ *
12199
+ * @param profile - The policy profile to save
12200
+ * @returns The profile name
12201
+ */
12202
+ async saveProfile(profile) {
12203
+ this.profiles.set(profile.name, profile);
12204
+ return profile.name;
12205
+ }
12206
+ /**
12207
+ * List all profile names.
12208
+ *
12209
+ * @returns List of profile names
12210
+ */
12211
+ async listProfiles() {
12212
+ return Array.from(this.profiles.keys());
12213
+ }
12214
+ /**
12215
+ * Create an effective policy from a profile and agent preferences.
12216
+ *
12217
+ * Clamps agent preferences to the profile's guardrails.
12218
+ *
12219
+ * @param profileName - The profile to use as base
12220
+ * @param agentPrefs - Optional agent preferences to apply
12221
+ * @param negotiationId - Optional negotiation ID
12222
+ * @returns The effective policy
12223
+ * @throws PolicyStoreError if the profile does not exist
12224
+ */
12225
+ async createEffectivePolicy(profileName, agentPrefs, negotiationId) {
12226
+ const profile = await this.getProfile(profileName);
12227
+ if (!profile) {
12228
+ throw new PolicyStoreError(`Profile '${profileName}' does not exist`);
12229
+ }
12230
+ const baseNegotiation = { ...profile.negotiation };
12231
+ const baseExecution = { ...profile.execution };
12232
+ const baseEscalation = { ...profile.escalation };
12233
+ const applied = {};
12234
+ if (agentPrefs) {
12235
+ for (const [agentId, prefs] of Object.entries(agentPrefs)) {
12236
+ const clamped = {};
12237
+ if (prefs.maxRounds !== void 0) {
12238
+ clamped.maxRounds = Math.min(prefs.maxRounds, baseNegotiation.maxRounds);
12239
+ }
12240
+ if (prefs.scoreThreshold !== void 0) {
12241
+ clamped.scoreThreshold = Math.max(
12242
+ prefs.scoreThreshold,
12243
+ baseNegotiation.scoreThreshold
12244
+ );
12245
+ }
12246
+ if (prefs.diffTolerance !== void 0) {
12247
+ clamped.diffTolerance = Math.min(
12248
+ prefs.diffTolerance,
12249
+ baseNegotiation.diffTolerance
12250
+ );
12251
+ }
12252
+ if (prefs.roundTimeoutMs !== void 0) {
12253
+ clamped.roundTimeoutMs = Math.min(
12254
+ prefs.roundTimeoutMs,
12255
+ baseNegotiation.roundTimeoutMs
12256
+ );
12257
+ }
12258
+ if (prefs.tokenBudgetPerRound !== void 0) {
12259
+ clamped.tokenBudgetPerRound = Math.min(
12260
+ prefs.tokenBudgetPerRound,
12261
+ baseNegotiation.tokenBudgetPerRound
12262
+ );
12263
+ }
12264
+ if (prefs.totalTokenBudget !== void 0 && baseNegotiation.totalTokenBudget > 0) {
12265
+ clamped.totalTokenBudget = Math.min(
12266
+ prefs.totalTokenBudget,
12267
+ baseNegotiation.totalTokenBudget
12268
+ );
12269
+ }
12270
+ if (prefs.oscillationLimit !== void 0) {
12271
+ clamped.oscillationLimit = Math.min(
12272
+ prefs.oscillationLimit,
12273
+ baseNegotiation.oscillationLimit
12274
+ );
12275
+ }
12276
+ applied[agentId] = clamped;
12277
+ }
12278
+ }
12279
+ const effectivePolicy = {
12280
+ policyId: generatePolicyId(),
12281
+ version: generatePolicyVersion(),
12282
+ negotiation: baseNegotiation,
12283
+ execution: baseExecution,
12284
+ escalation: baseEscalation,
12285
+ negotiationId,
12286
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
12287
+ };
12288
+ if (Object.keys(applied).length > 0) {
12289
+ effectivePolicy.applied = applied;
12290
+ }
12291
+ await this.savePolicy(effectivePolicy);
12292
+ return effectivePolicy;
12293
+ }
12294
+ };
12295
+ var JsonFilePolicyStore = class {
12296
+ directory;
12297
+ profiles = /* @__PURE__ */ new Map();
12298
+ /**
12299
+ * Create a new JSON file policy store.
12300
+ *
12301
+ * @param directory - Directory to store policy files
12302
+ */
12303
+ constructor(directory) {
12304
+ this.directory = directory;
12305
+ this.initializeDefaultProfiles();
12306
+ }
12307
+ /**
12308
+ * Initialize the store, creating the directory if needed.
12309
+ */
12310
+ async initialize() {
12311
+ await fsp2.mkdir(this.directory, { recursive: true });
12312
+ }
12313
+ /**
12314
+ * Initialize default policy profiles.
12315
+ */
12316
+ initializeDefaultProfiles() {
12317
+ const lowProfile = {
12318
+ name: "LOW",
12319
+ negotiation: {
12320
+ maxRounds: 5,
12321
+ scoreThreshold: 0.6,
12322
+ diffTolerance: 0.4,
12323
+ roundTimeoutMs: 6e4,
12324
+ tokenBudgetPerRound: 2048,
12325
+ totalTokenBudget: 0,
12326
+ oscillationLimit: 5,
12327
+ hitl: "None" /* NONE */,
12328
+ scoring: {
12329
+ requireSchemaValid: false,
12330
+ requireExamplesPass: false,
12331
+ llmWeight: 0.3
12332
+ }
12333
+ },
12334
+ execution: {
12335
+ ...DEFAULT_EXECUTION_POLICY,
12336
+ timeoutMs: 12e4,
12337
+ maxRetries: 5
12338
+ },
12339
+ escalation: {
12340
+ ...DEFAULT_ESCALATION_POLICY,
12341
+ deadlockRounds: 5
12342
+ }
12343
+ };
12344
+ const mediumProfile = {
12345
+ name: "MEDIUM",
12346
+ negotiation: { ...DEFAULT_NEGOTIATION_POLICY },
12347
+ execution: { ...DEFAULT_EXECUTION_POLICY },
12348
+ escalation: { ...DEFAULT_ESCALATION_POLICY }
12349
+ };
12350
+ const highProfile = {
12351
+ name: "HIGH",
12352
+ negotiation: {
12353
+ maxRounds: 15,
12354
+ scoreThreshold: 0.85,
12355
+ diffTolerance: 0.2,
12356
+ roundTimeoutMs: 2e4,
12357
+ tokenBudgetPerRound: 8192,
12358
+ totalTokenBudget: 1e5,
12359
+ oscillationLimit: 2,
12360
+ hitl: "PauseOnFinalAccept" /* PAUSE_ON_FINAL_ACCEPT */,
12361
+ scoring: {
12362
+ requireSchemaValid: true,
12363
+ requireExamplesPass: true,
12364
+ llmWeight: 0.7
12365
+ }
12366
+ },
12367
+ execution: {
12368
+ ...DEFAULT_EXECUTION_POLICY,
12369
+ timeoutMs: 3e4,
12370
+ maxRetries: 2,
12371
+ networkPolicy: "none"
12372
+ },
12373
+ escalation: {
12374
+ ...DEFAULT_ESCALATION_POLICY,
12375
+ deadlockRounds: 2,
12376
+ autoEscalateOnDeadlock: true
12377
+ }
12378
+ };
12379
+ this.profiles.set("LOW", lowProfile);
12380
+ this.profiles.set("MEDIUM", mediumProfile);
12381
+ this.profiles.set("HIGH", highProfile);
12382
+ }
12383
+ /**
12384
+ * Sanitize a policy ID for use as a filename.
12385
+ */
12386
+ sanitizeId(policyId) {
12387
+ return policyId.replace(/[/\\]/g, "_");
12388
+ }
12389
+ /**
12390
+ * Get the file path for a policy.
12391
+ */
12392
+ getFilePath(policyId) {
12393
+ return path3.join(this.directory, `${this.sanitizeId(policyId)}.json`);
12394
+ }
12395
+ /**
12396
+ * Load versions from a file.
12397
+ */
12398
+ async loadFromFile(policyId) {
12399
+ const filePath = this.getFilePath(policyId);
12400
+ try {
12401
+ const data = await fsp2.readFile(filePath, "utf-8");
12402
+ const parsed = JSON.parse(data);
12403
+ if (Array.isArray(parsed)) {
12404
+ return parsed;
12405
+ }
12406
+ return [parsed];
12407
+ } catch {
12408
+ return [];
12409
+ }
12410
+ }
12411
+ /**
12412
+ * Save versions to a file atomically.
12413
+ */
12414
+ async saveToFile(policyId, versions) {
12415
+ await this.initialize();
12416
+ const filePath = this.getFilePath(policyId);
12417
+ const tempPath = `${filePath}.tmp.${Date.now()}`;
12418
+ const data = JSON.stringify(versions, null, 2);
12419
+ await fsp2.writeFile(tempPath, data, "utf-8");
12420
+ await fsp2.rename(tempPath, filePath);
12421
+ }
12422
+ async getPolicy(policyId) {
12423
+ const versions = await this.loadFromFile(policyId);
12424
+ if (versions.length === 0) {
12425
+ return null;
12426
+ }
12427
+ return versions[versions.length - 1];
12428
+ }
12429
+ async savePolicy(policy) {
12430
+ const policyId = policy.policyId || generatePolicyId();
12431
+ const version2 = policy.version || generatePolicyVersion();
12432
+ const policyWithMeta = {
12433
+ ...policy,
12434
+ policyId,
12435
+ version: version2,
12436
+ createdAt: policy.createdAt || (/* @__PURE__ */ new Date()).toISOString()
12437
+ };
12438
+ const versions = await this.loadFromFile(policyId);
12439
+ versions.push(policyWithMeta);
12440
+ await this.saveToFile(policyId, versions);
12441
+ return policyId;
12442
+ }
12443
+ async listPolicies(prefix) {
12444
+ try {
12445
+ await this.initialize();
12446
+ const files = await fsp2.readdir(this.directory);
12447
+ const policyIds = files.filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -5));
12448
+ if (prefix === void 0) {
12449
+ return policyIds;
12450
+ }
12451
+ return policyIds.filter((id) => id.startsWith(prefix));
12452
+ } catch {
12453
+ return [];
12454
+ }
12455
+ }
12456
+ async deletePolicy(policyId) {
12457
+ const filePath = this.getFilePath(policyId);
12458
+ try {
12459
+ await fsp2.unlink(filePath);
12460
+ return true;
12461
+ } catch {
12462
+ return false;
12463
+ }
12464
+ }
12465
+ async getHistory(policyId) {
12466
+ return this.loadFromFile(policyId);
12467
+ }
12468
+ async getProfile(name) {
12469
+ return this.profiles.get(name) || null;
12470
+ }
12471
+ async saveProfile(profile) {
12472
+ this.profiles.set(profile.name, profile);
12473
+ return profile.name;
12474
+ }
12475
+ async listProfiles() {
12476
+ return Array.from(this.profiles.keys());
12477
+ }
12478
+ /**
12479
+ * Create an effective policy from a profile and agent preferences.
12480
+ */
12481
+ async createEffectivePolicy(profileName, agentPrefs, negotiationId) {
12482
+ const profile = await this.getProfile(profileName);
12483
+ if (!profile) {
12484
+ throw new PolicyStoreError(`Profile '${profileName}' does not exist`);
12485
+ }
12486
+ const baseNegotiation = { ...profile.negotiation };
12487
+ const baseExecution = { ...profile.execution };
12488
+ const baseEscalation = { ...profile.escalation };
12489
+ const applied = {};
12490
+ if (agentPrefs) {
12491
+ for (const [agentId, prefs] of Object.entries(agentPrefs)) {
12492
+ const clamped = {};
12493
+ if (prefs.maxRounds !== void 0) {
12494
+ clamped.maxRounds = Math.min(prefs.maxRounds, baseNegotiation.maxRounds);
12495
+ }
12496
+ if (prefs.scoreThreshold !== void 0) {
12497
+ clamped.scoreThreshold = Math.max(prefs.scoreThreshold, baseNegotiation.scoreThreshold);
12498
+ }
12499
+ if (prefs.diffTolerance !== void 0) {
12500
+ clamped.diffTolerance = Math.min(prefs.diffTolerance, baseNegotiation.diffTolerance);
12501
+ }
12502
+ if (prefs.roundTimeoutMs !== void 0) {
12503
+ clamped.roundTimeoutMs = Math.min(prefs.roundTimeoutMs, baseNegotiation.roundTimeoutMs);
12504
+ }
12505
+ if (prefs.tokenBudgetPerRound !== void 0) {
12506
+ clamped.tokenBudgetPerRound = Math.min(prefs.tokenBudgetPerRound, baseNegotiation.tokenBudgetPerRound);
12507
+ }
12508
+ if (prefs.totalTokenBudget !== void 0 && baseNegotiation.totalTokenBudget > 0) {
12509
+ clamped.totalTokenBudget = Math.min(prefs.totalTokenBudget, baseNegotiation.totalTokenBudget);
12510
+ }
12511
+ if (prefs.oscillationLimit !== void 0) {
12512
+ clamped.oscillationLimit = Math.min(prefs.oscillationLimit, baseNegotiation.oscillationLimit);
12513
+ }
12514
+ applied[agentId] = clamped;
12515
+ }
12516
+ }
12517
+ const effectivePolicy = {
12518
+ policyId: generatePolicyId(),
12519
+ version: generatePolicyVersion(),
12520
+ negotiation: baseNegotiation,
12521
+ execution: baseExecution,
12522
+ escalation: baseEscalation,
12523
+ negotiationId,
12524
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
12525
+ };
12526
+ if (Object.keys(applied).length > 0) {
12527
+ effectivePolicy.applied = applied;
12528
+ }
12529
+ await this.savePolicy(effectivePolicy);
12530
+ return effectivePolicy;
12531
+ }
12532
+ };
12533
+
12534
+ // src/runtime/agentState.ts
12535
+ var AgentState = /* @__PURE__ */ ((AgentState2) => {
12536
+ AgentState2[AgentState2["AGENT_STATE_UNSPECIFIED"] = 0] = "AGENT_STATE_UNSPECIFIED";
12537
+ AgentState2[AgentState2["INITIALIZING"] = 1] = "INITIALIZING";
12538
+ AgentState2[AgentState2["RUNNABLE"] = 2] = "RUNNABLE";
12539
+ AgentState2[AgentState2["SCHEDULED"] = 3] = "SCHEDULED";
12540
+ AgentState2[AgentState2["RUNNING"] = 4] = "RUNNING";
12541
+ AgentState2[AgentState2["WAITING"] = 5] = "WAITING";
12542
+ AgentState2[AgentState2["WAITING_RESOURCES"] = 6] = "WAITING_RESOURCES";
12543
+ AgentState2[AgentState2["SUSPENDED"] = 7] = "SUSPENDED";
12544
+ AgentState2[AgentState2["RESUMED"] = 8] = "RESUMED";
12545
+ AgentState2[AgentState2["COMPLETED"] = 9] = "COMPLETED";
12546
+ AgentState2[AgentState2["FAILED"] = 10] = "FAILED";
12547
+ AgentState2[AgentState2["SHUTTING_DOWN"] = 11] = "SHUTTING_DOWN";
12548
+ AgentState2[AgentState2["RECOVERING"] = 12] = "RECOVERING";
12549
+ return AgentState2;
12550
+ })(AgentState || {});
12551
+ var StateTransitionError = class extends Error {
12552
+ fromState;
12553
+ toState;
12554
+ constructor(fromState, toState) {
12555
+ const fromName = AgentState[fromState];
12556
+ const toName = AgentState[toState];
12557
+ super(`Invalid state transition from ${fromName} to ${toName}`);
12558
+ this.name = "StateTransitionError";
12559
+ this.fromState = fromState;
12560
+ this.toState = toState;
12561
+ }
12562
+ };
12563
+ var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
12564
+ // INITIALIZING -> RUNNABLE
12565
+ [1 /* INITIALIZING */, /* @__PURE__ */ new Set([2 /* RUNNABLE */])],
12566
+ // RUNNABLE -> SCHEDULED
12567
+ [2 /* RUNNABLE */, /* @__PURE__ */ new Set([3 /* SCHEDULED */])],
12568
+ // SCHEDULED -> RUNNING
12569
+ [3 /* SCHEDULED */, /* @__PURE__ */ new Set([4 /* RUNNING */])],
12570
+ // RUNNING -> WAITING, WAITING_RESOURCES, SUSPENDED, COMPLETED, FAILED, SHUTTING_DOWN
12571
+ [
12572
+ 4 /* RUNNING */,
12573
+ /* @__PURE__ */ new Set([
12574
+ 5 /* WAITING */,
12575
+ 6 /* WAITING_RESOURCES */,
12576
+ 7 /* SUSPENDED */,
12577
+ 9 /* COMPLETED */,
12578
+ 10 /* FAILED */,
12579
+ 11 /* SHUTTING_DOWN */
12580
+ ])
12581
+ ],
12582
+ // WAITING -> RUNNING
12583
+ [5 /* WAITING */, /* @__PURE__ */ new Set([4 /* RUNNING */])],
12584
+ // WAITING_RESOURCES -> RUNNING, FAILED (resource timeout)
12585
+ [
12586
+ 6 /* WAITING_RESOURCES */,
12587
+ /* @__PURE__ */ new Set([4 /* RUNNING */, 10 /* FAILED */])
12588
+ ],
12589
+ // SUSPENDED -> RESUMED
12590
+ [7 /* SUSPENDED */, /* @__PURE__ */ new Set([8 /* RESUMED */])],
12591
+ // RESUMED -> RUNNING
12592
+ [8 /* RESUMED */, /* @__PURE__ */ new Set([4 /* RUNNING */])],
12593
+ // COMPLETED -> RUNNABLE
12594
+ [9 /* COMPLETED */, /* @__PURE__ */ new Set([2 /* RUNNABLE */])],
12595
+ // FAILED -> RECOVERING
12596
+ [10 /* FAILED */, /* @__PURE__ */ new Set([12 /* RECOVERING */])],
12597
+ // SHUTTING_DOWN -> FAILED (agent_shutdown_timeout)
12598
+ [11 /* SHUTTING_DOWN */, /* @__PURE__ */ new Set([10 /* FAILED */])],
12599
+ // RECOVERING -> RUNNABLE, SHUTTING_DOWN (recovery abort)
12600
+ [
12601
+ 12 /* RECOVERING */,
12602
+ /* @__PURE__ */ new Set([2 /* RUNNABLE */, 11 /* SHUTTING_DOWN */])
12603
+ ]
12604
+ ]);
12605
+ function isValidTransition(fromState, toState) {
12606
+ const validTargets = VALID_TRANSITIONS.get(fromState);
12607
+ if (!validTargets) {
12608
+ return false;
12609
+ }
12610
+ return validTargets.has(toState);
12611
+ }
12612
+ function getValidTransitions(fromState) {
12613
+ const validTargets = VALID_TRANSITIONS.get(fromState);
12614
+ if (!validTargets) {
12615
+ return [];
12616
+ }
12617
+ return Array.from(validTargets);
12618
+ }
12619
+ var AgentStateMachine = class {
12620
+ state = 0 /* AGENT_STATE_UNSPECIFIED */;
12621
+ hooks;
12622
+ stateHistory = [];
12623
+ /**
12624
+ * Create a new agent state machine.
12625
+ *
12626
+ * @param hooks - Optional lifecycle hooks
12627
+ */
12628
+ constructor(hooks) {
12629
+ this.hooks = hooks || {};
12630
+ }
12631
+ /**
12632
+ * Get the current state.
12633
+ *
12634
+ * @returns The current agent state
12635
+ */
12636
+ getState() {
12637
+ return this.state;
12638
+ }
12639
+ /**
12640
+ * Get the state history.
12641
+ *
12642
+ * @returns Array of state transitions with timestamps
12643
+ */
12644
+ getStateHistory() {
12645
+ return [...this.stateHistory];
12646
+ }
12647
+ /**
12648
+ * Initialize the agent (transition to INITIALIZING).
12649
+ *
12650
+ * @throws StateTransitionError if already initialized
12651
+ */
12652
+ async initialize() {
12653
+ if (this.state !== 0 /* AGENT_STATE_UNSPECIFIED */) {
12654
+ throw new StateTransitionError(this.state, 1 /* INITIALIZING */);
12655
+ }
12656
+ await this.transitionTo(1 /* INITIALIZING */);
12657
+ }
12658
+ /**
12659
+ * Transition to a new state.
12660
+ *
12661
+ * @param toState - The target state
12662
+ * @param context - Optional context for the transition
12663
+ * @throws StateTransitionError if the transition is invalid
12664
+ */
12665
+ async transitionTo(toState, context) {
12666
+ if (this.state === 0 /* AGENT_STATE_UNSPECIFIED */ && toState === 1 /* INITIALIZING */) {
12667
+ await this.doTransition(toState, context);
12668
+ return;
12669
+ }
12670
+ if (!isValidTransition(this.state, toState)) {
12671
+ throw new StateTransitionError(this.state, toState);
12672
+ }
12673
+ await this.doTransition(toState, context);
12674
+ }
12675
+ /**
12676
+ * Perform the state transition and call hooks.
12677
+ */
12678
+ async doTransition(toState, context) {
12679
+ const fromState = this.state;
12680
+ this.state = toState;
12681
+ this.stateHistory.push({
12682
+ state: toState,
12683
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12684
+ context
12685
+ });
12686
+ if (this.hooks.onStateChange) {
12687
+ await this.hooks.onStateChange(fromState, toState, context);
12688
+ }
12689
+ await this.callSpecificHooks(fromState, toState, context);
12690
+ }
12691
+ /**
12692
+ * Call specific lifecycle hooks based on the transition.
12693
+ */
12694
+ async callSpecificHooks(fromState, toState, context) {
12695
+ switch (toState) {
12696
+ case 3 /* SCHEDULED */:
12697
+ if (this.hooks.onScheduled) {
12698
+ const taskId = context?.taskId || "unknown";
12699
+ await this.hooks.onScheduled(taskId, context);
12700
+ }
12701
+ break;
12702
+ case 7 /* SUSPENDED */:
12703
+ if (fromState === 4 /* RUNNING */ && this.hooks.onPreempt) {
12704
+ const reason = context?.reason || "preemption";
12705
+ await this.hooks.onPreempt(reason, context);
12706
+ }
12707
+ break;
12708
+ case 4 /* RUNNING */:
12709
+ if (fromState === 8 /* RESUMED */ && this.hooks.onResume) {
12710
+ await this.hooks.onResume(context);
12711
+ }
12712
+ break;
12713
+ case 5 /* WAITING */:
12714
+ if (this.hooks.onWait) {
12715
+ const reason = context?.reason || "waiting";
12716
+ await this.hooks.onWait(reason, context);
12717
+ }
12718
+ break;
12719
+ case 6 /* WAITING_RESOURCES */:
12720
+ if (this.hooks.onWaitResources) {
12721
+ const resources = context?.resources || [];
12722
+ await this.hooks.onWaitResources(resources, context);
12723
+ }
12724
+ break;
12725
+ case 9 /* COMPLETED */:
12726
+ if (this.hooks.onComplete) {
12727
+ await this.hooks.onComplete(context?.result, context);
12728
+ }
12729
+ break;
12730
+ case 10 /* FAILED */:
12731
+ if (this.hooks.onFail) {
12732
+ const error = context?.error || new Error("Unknown failure");
12733
+ await this.hooks.onFail(error, context);
12734
+ }
12735
+ break;
12736
+ case 11 /* SHUTTING_DOWN */:
12737
+ if (this.hooks.onShutdown) {
12738
+ const gracePeriodMs = context?.gracePeriodMs || 3e4;
12739
+ await this.hooks.onShutdown(gracePeriodMs, context);
12740
+ }
12741
+ break;
12742
+ case 12 /* RECOVERING */:
12743
+ if (this.hooks.onRecover) {
12744
+ await this.hooks.onRecover(context);
12745
+ }
12746
+ break;
12747
+ }
12748
+ }
12749
+ /**
12750
+ * Check if the agent can transition to a given state.
12751
+ *
12752
+ * @param toState - The target state
12753
+ * @returns True if the transition is valid
12754
+ */
12755
+ canTransitionTo(toState) {
12756
+ if (this.state === 0 /* AGENT_STATE_UNSPECIFIED */ && toState === 1 /* INITIALIZING */) {
12757
+ return true;
12758
+ }
12759
+ return isValidTransition(this.state, toState);
12760
+ }
12761
+ /**
12762
+ * Get all states the agent can currently transition to.
12763
+ *
12764
+ * @returns Array of valid target states
12765
+ */
12766
+ getAvailableTransitions() {
12767
+ if (this.state === 0 /* AGENT_STATE_UNSPECIFIED */) {
12768
+ return [1 /* INITIALIZING */];
12769
+ }
12770
+ return getValidTransitions(this.state);
12771
+ }
12772
+ /**
12773
+ * Check if the agent is in a terminal state.
12774
+ *
12775
+ * Terminal states are states where the agent cannot make further
12776
+ * progress without external intervention.
12777
+ *
12778
+ * @returns True if in a terminal state
12779
+ */
12780
+ isTerminal() {
12781
+ return getValidTransitions(this.state).length === 0;
12782
+ }
12783
+ /**
12784
+ * Check if the agent is in an active state (executing work).
12785
+ *
12786
+ * @returns True if the agent is actively working
12787
+ */
12788
+ isActive() {
12789
+ return this.state === 4 /* RUNNING */ || this.state === 3 /* SCHEDULED */ || this.state === 8 /* RESUMED */;
12790
+ }
12791
+ /**
12792
+ * Check if the agent is in a waiting state.
12793
+ *
12794
+ * @returns True if the agent is waiting
12795
+ */
12796
+ isWaiting() {
12797
+ return this.state === 5 /* WAITING */ || this.state === 6 /* WAITING_RESOURCES */;
12798
+ }
12799
+ /**
12800
+ * Check if the agent is in a suspended or shutdown state.
12801
+ *
12802
+ * @returns True if the agent is suspended or shutting down
12803
+ */
12804
+ isSuspendedOrShuttingDown() {
12805
+ return this.state === 7 /* SUSPENDED */ || this.state === 11 /* SHUTTING_DOWN */;
12806
+ }
12807
+ /**
12808
+ * Update lifecycle hooks.
12809
+ *
12810
+ * @param hooks - New hooks to merge with existing hooks
12811
+ */
12812
+ setHooks(hooks) {
12813
+ this.hooks = { ...this.hooks, ...hooks };
12814
+ }
12815
+ /**
12816
+ * Reset the state machine to uninitialized state.
12817
+ *
12818
+ * This is primarily for testing purposes.
12819
+ */
12820
+ reset() {
12821
+ this.state = 0 /* AGENT_STATE_UNSPECIFIED */;
12822
+ this.stateHistory = [];
12823
+ }
12824
+ };
12825
+
10700
12826
  // src/internal/idempotency.ts
10701
12827
  import crypto3 from "node:crypto";
10702
12828
  function computeIdempotencyToken(input) {
@@ -10909,7 +13035,7 @@ var Resolver = class {
10909
13035
  try {
10910
13036
  const v = await this.backend.get(scope, key);
10911
13037
  return [v, scope.isGlobal ? "global" /* GLOBAL */ : "scoped" /* SCOPED */];
10912
- } catch (e) {
13038
+ } catch {
10913
13039
  }
10914
13040
  if (!scope.isGlobal) {
10915
13041
  const v = await this.backend.get(new Scope(null), key);
@@ -10934,8 +13060,8 @@ function defaultPath() {
10934
13060
  }
10935
13061
  var FileBackend = class {
10936
13062
  path;
10937
- constructor(path3) {
10938
- this.path = path3 ?? defaultPath();
13063
+ constructor(path4) {
13064
+ this.path = path4 ?? defaultPath();
10939
13065
  mkdirSync(dirname(this.path), { recursive: true });
10940
13066
  try {
10941
13067
  chmodSync(dirname(this.path), 448);
@@ -11066,31 +13192,53 @@ async function selectBackend(mode) {
11066
13192
  }
11067
13193
 
11068
13194
  // src/index.ts
11069
- var version = "0.3.0";
13195
+ var version = "0.4.0";
11070
13196
  export {
11071
13197
  ACKLifecycleManager,
11072
13198
  AckStage,
11073
13199
  ActivityBuffer,
11074
13200
  ActivityBufferSync,
11075
13201
  ActivityClient,
13202
+ AgentState,
13203
+ AgentStateMachine,
13204
+ ArtifactType,
11076
13205
  BaseClient,
13206
+ BordaCountAggregator,
11077
13207
  CT_AGENT_REPORT_V1,
11078
13208
  CT_SCHEDULER_COMMAND_V1,
13209
+ ConfidenceWeightedAggregator,
11079
13210
  ConnectorClient,
13211
+ DEFAULT_ESCALATION_POLICY,
13212
+ DEFAULT_EXECUTION_POLICY,
13213
+ DEFAULT_NEGOTIATION_POLICY,
13214
+ DecisionOutcome,
11080
13215
  DefaultWorktreePolicy,
11081
13216
  ErrorCode,
11082
13217
  ErrorCodeMapper,
11083
13218
  FileBackend,
11084
13219
  HITLClient,
13220
+ HandoffClient,
13221
+ HandoffStatus,
13222
+ HandoffTimeoutError,
13223
+ HandoffValidationError,
13224
+ HitlMode,
13225
+ InMemoryPolicyStore,
11085
13226
  InterceptorChain,
11086
13227
  JSONFilePersistence,
13228
+ JsonFilePolicyStore,
11087
13229
  KeyringBackend,
11088
13230
  LoggingClient,
13231
+ MajorityVoteAggregator,
11089
13232
  MaxEntriesStrategy,
11090
13233
  MessageProcessor,
11091
13234
  MessageType,
11092
13235
  NegotiationClient,
13236
+ NegotiationRoomClient,
13237
+ NegotiationTimeoutError,
13238
+ NegotiationValidationError,
13239
+ NodeStatus,
11093
13240
  PersistentWorktreeState,
13241
+ PolicyStoreError,
11094
13242
  ReasoningClient,
11095
13243
  RegistryClient,
11096
13244
  Resolver,
@@ -11108,9 +13256,18 @@ export {
11108
13256
  SecretValidationError,
11109
13257
  SecretValue,
11110
13258
  Secrets,
13259
+ SimpleAverageAggregator,
13260
+ StateTransitionError,
11111
13261
  Sw4rmError,
11112
13262
  ToolClient,
13263
+ TriggerType,
13264
+ VotingAnalyzer,
13265
+ WorkflowClient,
13266
+ WorkflowCycleError,
13267
+ WorkflowStatus,
13268
+ WorkflowValidationError,
11113
13269
  WorktreeClient,
13270
+ aggregateVotes,
11114
13271
  buildAckEnvelope,
11115
13272
  buildEnvelope,
11116
13273
  computeIdempotencyToken,
@@ -11119,6 +13276,8 @@ export {
11119
13276
  decodeBase64,
11120
13277
  durationToMs,
11121
13278
  encodeSchedulerCommandV1,
13279
+ getValidTransitions,
13280
+ isValidTransition,
11122
13281
  loggingInterceptor,
11123
13282
  mapGrpcStatusToErrorCode,
11124
13283
  msToDuration,