@sw4rm/js-sdk 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +178 -1
  2. package/dist/cjs/index.cjs +2819 -292
  3. package/dist/esm/index.js +2736 -284
  4. package/dist/types/agentConfig.d.ts +245 -0
  5. package/dist/types/audit.d.ts +214 -0
  6. package/dist/types/clients/handoff.d.ts +44 -1
  7. package/dist/types/clients/negotiationRoom.d.ts +81 -5
  8. package/dist/types/clients/negotiationRoomStore.d.ts +155 -0
  9. package/dist/types/clients/workflow.d.ts +15 -0
  10. package/dist/types/constants/index.d.ts +100 -0
  11. package/dist/types/index.d.ts +14 -5
  12. package/dist/types/internal/baseClient.d.ts +6 -0
  13. package/dist/types/internal/envelope.d.ts +16 -0
  14. package/dist/types/internal/errorMapping.d.ts +116 -0
  15. package/dist/types/internal/worktreeState.d.ts +60 -0
  16. package/dist/types/llm/anthropic.d.ts +83 -0
  17. package/dist/types/llm/client.d.ts +107 -0
  18. package/dist/types/llm/factory.d.ts +69 -0
  19. package/dist/types/llm/groq.d.ts +79 -0
  20. package/dist/types/llm/index.d.ts +45 -0
  21. package/dist/types/llm/mock.d.ts +89 -0
  22. package/dist/types/llm/rateLimiter.d.ts +101 -0
  23. package/dist/types/persistentActivityBuffer.d.ts +94 -0
  24. package/dist/types/runtime/cancellation.d.ts +41 -0
  25. package/dist/types/runtime/delegation.d.ts +20 -0
  26. package/dist/types/runtime/gateway.d.ts +80 -0
  27. package/package.json +4 -2
  28. package/protos/activity.proto +24 -0
  29. package/protos/common.proto +141 -0
  30. package/protos/connector.proto +29 -0
  31. package/protos/handoff.proto +105 -0
  32. package/protos/hitl.proto +23 -0
  33. package/protos/logging.proto +20 -0
  34. package/protos/negotiation.proto +57 -0
  35. package/protos/negotiation_room.proto +220 -0
  36. package/protos/policy.proto +55 -0
  37. package/protos/reasoning.proto +41 -0
  38. package/protos/registry.proto +47 -0
  39. package/protos/router.proto +16 -0
  40. package/protos/scheduler.proto +52 -0
  41. package/protos/scheduler_policy.proto +36 -0
  42. package/protos/tool.proto +47 -0
  43. package/protos/workflow.proto +116 -0
  44. package/protos/worktree.proto +33 -0
package/dist/esm/index.js CHANGED
@@ -1857,25 +1857,25 @@ var require_codegen = __commonJS({
1857
1857
  var require_fetch = __commonJS({
1858
1858
  "node_modules/@protobufjs/fetch/index.js"(exports2, module2) {
1859
1859
  "use strict";
1860
- module2.exports = fetch;
1860
+ module2.exports = fetch2;
1861
1861
  var asPromise = require_aspromise();
1862
1862
  var inquire2 = require_inquire();
1863
- var fs = inquire2("fs");
1864
- function fetch(filename, options, callback) {
1863
+ var fs5 = inquire2("fs");
1864
+ function fetch2(filename, options, callback) {
1865
1865
  if (typeof options === "function") {
1866
1866
  callback = options;
1867
1867
  options = {};
1868
1868
  } else if (!options)
1869
1869
  options = {};
1870
1870
  if (!callback)
1871
- return asPromise(fetch, this, filename, options);
1872
- if (!options.xhr && fs && fs.readFile)
1873
- return fs.readFile(filename, function fetchReadFileCallback(err, contents) {
1874
- return err && typeof XMLHttpRequest !== "undefined" ? fetch.xhr(filename, options, callback) : err ? callback(err) : callback(null, options.binary ? contents : contents.toString("utf8"));
1871
+ return asPromise(fetch2, this, filename, options);
1872
+ if (!options.xhr && fs5 && fs5.readFile)
1873
+ return fs5.readFile(filename, function fetchReadFileCallback(err, contents) {
1874
+ return err && typeof XMLHttpRequest !== "undefined" ? fetch2.xhr(filename, options, callback) : err ? callback(err) : callback(null, options.binary ? contents : contents.toString("utf8"));
1875
1875
  });
1876
- return fetch.xhr(filename, options, callback);
1876
+ return fetch2.xhr(filename, options, callback);
1877
1877
  }
1878
- fetch.xhr = function fetch_xhr(filename, options, callback) {
1878
+ fetch2.xhr = function fetch_xhr(filename, options, callback) {
1879
1879
  var xhr = new XMLHttpRequest();
1880
1880
  xhr.onreadystatechange = function fetchOnReadyStateChange() {
1881
1881
  if (xhr.readyState !== 4)
@@ -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 path4 = exports2;
1911
+ var path7 = 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
- path4.isAbsolute = function isAbsolute2(path5) {
1919
- return /^(?:\/|\w+:)/.test(path5);
1918
+ path7.isAbsolute = function isAbsolute2(path8) {
1919
+ return /^(?:\/|\w+:)/.test(path8);
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
- path4.normalize = function normalize2(path5) {
1929
- path5 = path5.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
1930
- var parts = path5.split("/"), absolute = isAbsolute(path5), prefix = "";
1928
+ path7.normalize = function normalize2(path8) {
1929
+ path8 = path8.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
1930
+ var parts = path8.split("/"), absolute = isAbsolute(path8), 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
- path4.resolve = function resolve(originPath, includePath, alreadyNormalized) {
1949
+ path7.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(path4, json) {
2101
- if (util.isString(path4))
2102
- path4 = path4.split(".");
2103
- else if (!Array.isArray(path4))
2100
+ Namespace.prototype.define = function define2(path7, json) {
2101
+ if (util.isString(path7))
2102
+ path7 = path7.split(".");
2103
+ else if (!Array.isArray(path7))
2104
2104
  throw TypeError("illegal path");
2105
- if (path4 && path4.length && path4[0] === "")
2105
+ if (path7 && path7.length && path7[0] === "")
2106
2106
  throw Error("path must be relative");
2107
2107
  var ptr = this;
2108
- while (path4.length > 0) {
2109
- var part = path4.shift();
2108
+ while (path7.length > 0) {
2109
+ var part = path7.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(path4, filterTypes, parentAlreadyChecked) {
2146
+ Namespace.prototype.lookup = function lookup(path7, 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(path4) && path4.length) {
2153
- if (path4 === ".")
2152
+ if (util.isString(path7) && path7.length) {
2153
+ if (path7 === ".")
2154
2154
  return this.root;
2155
- path4 = path4.split(".");
2156
- } else if (!path4.length)
2155
+ path7 = path7.split(".");
2156
+ } else if (!path7.length)
2157
2157
  return this;
2158
- var flatPath = path4.join(".");
2159
- if (path4[0] === "")
2160
- return this.root.lookup(path4.slice(1), filterTypes);
2158
+ var flatPath = path7.join(".");
2159
+ if (path7[0] === "")
2160
+ return this.root.lookup(path7.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(path4, flatPath);
2165
+ found = this._lookupImpl(path7, 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(path4, flatPath);
2173
+ found = current.parent._lookupImpl(path7, 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(path4, flatPath) {
2181
+ Namespace.prototype._lookupImpl = function lookup(path7, flatPath) {
2182
2182
  if (Object.prototype.hasOwnProperty.call(this._lookupCache, flatPath)) {
2183
2183
  return this._lookupCache[flatPath];
2184
2184
  }
2185
- var found = this.get(path4[0]);
2185
+ var found = this.get(path7[0]);
2186
2186
  var exact = null;
2187
2187
  if (found) {
2188
- if (path4.length === 1) {
2188
+ if (path7.length === 1) {
2189
2189
  exact = found;
2190
2190
  } else if (found instanceof Namespace) {
2191
- path4 = path4.slice(1);
2192
- exact = found._lookupImpl(path4, path4.join("."));
2191
+ path7 = path7.slice(1);
2192
+ exact = found._lookupImpl(path7, path7.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(path4, flatPath)))
2196
+ if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path7, 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(path4) {
2203
- var found = this.lookup(path4, [Type]);
2202
+ Namespace.prototype.lookupType = function lookupType(path7) {
2203
+ var found = this.lookup(path7, [Type]);
2204
2204
  if (!found)
2205
- throw Error("no such type: " + path4);
2205
+ throw Error("no such type: " + path7);
2206
2206
  return found;
2207
2207
  };
2208
- Namespace.prototype.lookupEnum = function lookupEnum(path4) {
2209
- var found = this.lookup(path4, [Enum]);
2208
+ Namespace.prototype.lookupEnum = function lookupEnum(path7) {
2209
+ var found = this.lookup(path7, [Enum]);
2210
2210
  if (!found)
2211
- throw Error("no such Enum '" + path4 + "' in " + this);
2211
+ throw Error("no such Enum '" + path7 + "' in " + this);
2212
2212
  return found;
2213
2213
  };
2214
- Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(path4) {
2215
- var found = this.lookup(path4, [Type, Enum]);
2214
+ Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(path7) {
2215
+ var found = this.lookup(path7, [Type, Enum]);
2216
2216
  if (!found)
2217
- throw Error("no such Type or Enum '" + path4 + "' in " + this);
2217
+ throw Error("no such Type or Enum '" + path7 + "' in " + this);
2218
2218
  return found;
2219
2219
  };
2220
- Namespace.prototype.lookupService = function lookupService(path4) {
2221
- var found = this.lookup(path4, [Service]);
2220
+ Namespace.prototype.lookupService = function lookupService(path7) {
2221
+ var found = this.lookup(path7, [Service]);
2222
2222
  if (!found)
2223
- throw Error("no such Service '" + path4 + "' in " + this);
2223
+ throw Error("no such Service '" + path7 + "' in " + this);
2224
2224
  return found;
2225
2225
  };
2226
2226
  Namespace._configure = function(Type_, Service_, Enum_) {
@@ -3366,12 +3366,12 @@ var require_root = __commonJS({
3366
3366
  if (parsed.imports) {
3367
3367
  for (; i2 < parsed.imports.length; ++i2)
3368
3368
  if (resolved2 = getBundledFileName(parsed.imports[i2]) || self2.resolvePath(filename2, parsed.imports[i2]))
3369
- fetch(resolved2);
3369
+ fetch2(resolved2);
3370
3370
  }
3371
3371
  if (parsed.weakImports) {
3372
3372
  for (i2 = 0; i2 < parsed.weakImports.length; ++i2)
3373
3373
  if (resolved2 = getBundledFileName(parsed.weakImports[i2]) || self2.resolvePath(filename2, parsed.weakImports[i2]))
3374
- fetch(resolved2, true);
3374
+ fetch2(resolved2, true);
3375
3375
  }
3376
3376
  }
3377
3377
  } catch (err) {
@@ -3381,7 +3381,7 @@ var require_root = __commonJS({
3381
3381
  finish(null, self2);
3382
3382
  }
3383
3383
  }
3384
- function fetch(filename2, weak) {
3384
+ function fetch2(filename2, weak) {
3385
3385
  filename2 = getBundledFileName(filename2) || filename2;
3386
3386
  if (self2.files.indexOf(filename2) > -1) {
3387
3387
  return;
@@ -3433,7 +3433,7 @@ var require_root = __commonJS({
3433
3433
  }
3434
3434
  for (var i = 0, resolved; i < filename.length; ++i)
3435
3435
  if (resolved = self2.resolvePath("", filename[i]))
3436
- fetch(resolved);
3436
+ fetch2(resolved);
3437
3437
  if (sync) {
3438
3438
  self2.resolveAll();
3439
3439
  return self2;
@@ -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, path4, value, ifNotSet) {
3625
- function setProp(dst2, path5, value2) {
3626
- var part = path5.shift();
3624
+ util.setProperty = function setProperty(dst, path7, value, ifNotSet) {
3625
+ function setProp(dst2, path8, value2) {
3626
+ var part = path8.shift();
3627
3627
  if (part === "__proto__" || part === "prototype") {
3628
3628
  return dst2;
3629
3629
  }
3630
- if (path5.length > 0) {
3631
- dst2[part] = setProp(dst2[part] || {}, path5, value2);
3630
+ if (path8.length > 0) {
3631
+ dst2[part] = setProp(dst2[part] || {}, path8, 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 (!path4)
3644
+ if (!path7)
3645
3645
  throw TypeError("path must be specified");
3646
- path4 = path4.split(".");
3647
- return setProp(dst, path4, value);
3646
+ path7 = path7.split(".");
3647
+ return setProp(dst, path7, 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 path4 = [this.name], ptr = this.parent;
4194
+ var path7 = [this.name], ptr = this.parent;
4195
4195
  while (ptr) {
4196
- path4.unshift(ptr.name);
4196
+ path7.unshift(ptr.name);
4197
4197
  ptr = ptr.parent;
4198
4198
  }
4199
- return path4.join(".");
4199
+ return path7.join(".");
4200
4200
  }
4201
4201
  }
4202
4202
  });
@@ -8178,19 +8178,19 @@ var require_util2 = __commonJS({
8178
8178
  "use strict";
8179
8179
  Object.defineProperty(exports2, "__esModule", { value: true });
8180
8180
  exports2.addCommonProtos = exports2.loadProtosWithOptionsSync = exports2.loadProtosWithOptions = void 0;
8181
- var fs = __require("fs");
8182
- var path4 = __require("path");
8181
+ var fs5 = __require("fs");
8182
+ var path7 = __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 (path4.isAbsolute(target)) {
8187
+ if (path7.isAbsolute(target)) {
8188
8188
  return target;
8189
8189
  }
8190
8190
  for (const directory of includePaths) {
8191
- const fullPath = path4.join(directory, target);
8191
+ const fullPath = path7.join(directory, target);
8192
8192
  try {
8193
- fs.accessSync(fullPath, fs.constants.R_OK);
8193
+ fs5.accessSync(fullPath, fs5.constants.R_OK);
8194
8194
  return fullPath;
8195
8195
  } catch (err) {
8196
8196
  continue;
@@ -9482,6 +9482,7 @@ var require_src2 = __commonJS({
9482
9482
 
9483
9483
  // src/internal/baseClient.ts
9484
9484
  var protoLoader = __toESM(require_src2(), 1);
9485
+ import fs from "node:fs";
9485
9486
  import path from "node:path";
9486
9487
  import { fileURLToPath } from "node:url";
9487
9488
  import * as grpc from "@grpc/grpc-js";
@@ -9502,6 +9503,10 @@ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
9502
9503
  ErrorCode2[ErrorCode2["PARTIAL_DELIVERY"] = 11] = "PARTIAL_DELIVERY";
9503
9504
  ErrorCode2[ErrorCode2["FORCED_PREEMPTION"] = 12] = "FORCED_PREEMPTION";
9504
9505
  ErrorCode2[ErrorCode2["TTL_EXPIRED"] = 13] = "TTL_EXPIRED";
9506
+ ErrorCode2[ErrorCode2["DUPLICATE_DETECTED"] = 14] = "DUPLICATE_DETECTED";
9507
+ ErrorCode2[ErrorCode2["ALREADY_IN_PROGRESS"] = 15] = "ALREADY_IN_PROGRESS";
9508
+ ErrorCode2[ErrorCode2["OVERLOADED"] = 16] = "OVERLOADED";
9509
+ ErrorCode2[ErrorCode2["REDIRECT"] = 20] = "REDIRECT";
9505
9510
  ErrorCode2[ErrorCode2["INTERNAL_ERROR"] = 99] = "INTERNAL_ERROR";
9506
9511
  return ErrorCode2;
9507
9512
  })(ErrorCode || {});
@@ -9517,6 +9522,54 @@ var Sw4rmError = class extends Error {
9517
9522
  this.details = opts?.details;
9518
9523
  }
9519
9524
  };
9525
+ var ValidationError = class extends Sw4rmError {
9526
+ constructor(message, code = 6 /* VALIDATION_ERROR */, opts) {
9527
+ super(message, code, opts);
9528
+ this.name = "ValidationError";
9529
+ }
9530
+ };
9531
+ var TimeoutError = class extends Sw4rmError {
9532
+ constructor(message, code = 3 /* ACK_TIMEOUT */, opts) {
9533
+ super(message, code, opts);
9534
+ this.name = "TimeoutError";
9535
+ }
9536
+ };
9537
+ var StateTransitionError = class extends Sw4rmError {
9538
+ constructor(message, code = 99 /* INTERNAL_ERROR */, opts) {
9539
+ super(message, code, opts);
9540
+ this.name = "StateTransitionError";
9541
+ }
9542
+ };
9543
+ var NegotiationError = class extends Sw4rmError {
9544
+ constructor(message, code = 99 /* INTERNAL_ERROR */, opts) {
9545
+ super(message, code, opts);
9546
+ this.name = "NegotiationError";
9547
+ }
9548
+ };
9549
+ var BufferFullError = class extends Sw4rmError {
9550
+ constructor(message, code = 1 /* BUFFER_FULL */, opts) {
9551
+ super(message, code, opts);
9552
+ this.name = "BufferFullError";
9553
+ }
9554
+ };
9555
+ var RouteError = class extends Sw4rmError {
9556
+ constructor(message, code = 2 /* NO_ROUTE */, opts) {
9557
+ super(message, code, opts);
9558
+ this.name = "RouteError";
9559
+ }
9560
+ };
9561
+ var PermissionError = class extends Sw4rmError {
9562
+ constructor(message, code = 7 /* PERMISSION_DENIED */, opts) {
9563
+ super(message, code, opts);
9564
+ this.name = "PermissionError";
9565
+ }
9566
+ };
9567
+ var DuplicateDetectedError = class extends Sw4rmError {
9568
+ constructor(message, code = 14 /* DUPLICATE_DETECTED */, opts) {
9569
+ super(message, code, opts);
9570
+ this.name = "DuplicateDetectedError";
9571
+ }
9572
+ };
9520
9573
  var GrpcStatus = {
9521
9574
  OK: 0,
9522
9575
  CANCELLED: 1,
@@ -9536,6 +9589,28 @@ var GrpcStatus = {
9536
9589
  DATA_LOSS: 15,
9537
9590
  UNAUTHENTICATED: 16
9538
9591
  };
9592
+ var PreemptionError = class extends Sw4rmError {
9593
+ agentId;
9594
+ reason;
9595
+ constructor(agentId, reason, code = 12 /* FORCED_PREEMPTION */, opts) {
9596
+ super(`Agent ${agentId} preempted: ${reason}`, code, opts);
9597
+ this.name = "PreemptionError";
9598
+ this.agentId = agentId;
9599
+ this.reason = reason;
9600
+ }
9601
+ };
9602
+ var WorktreeError = class extends Sw4rmError {
9603
+ constructor(message, code = 99 /* INTERNAL_ERROR */, opts) {
9604
+ super(message, code, opts);
9605
+ this.name = "WorktreeError";
9606
+ }
9607
+ };
9608
+ var PolicyViolationError = class extends Sw4rmError {
9609
+ constructor(message, code = 7 /* PERMISSION_DENIED */, opts) {
9610
+ super(message, code, opts);
9611
+ this.name = "PolicyViolationError";
9612
+ }
9613
+ };
9539
9614
  function mapGrpcStatusToErrorCode(status) {
9540
9615
  switch (status) {
9541
9616
  case GrpcStatus.OK:
@@ -9649,12 +9724,12 @@ var BaseClient = class {
9649
9724
  errorMapper = new ErrorCodeMapper();
9650
9725
  constructor(opts) {
9651
9726
  this.address = opts.address;
9652
- this.deadlineMs = opts.deadlineMs ?? 1e4;
9727
+ this.deadlineMs = opts.deadlineMs ?? 3e4;
9653
9728
  this.retry = opts.retry ?? { maxAttempts: 3, initialBackoffMs: 200, maxBackoffMs: 2e3, multiplier: 2 };
9654
9729
  this.userAgent = opts.userAgent ?? "sw4rm-js-sdk/0.1";
9655
9730
  const __filename = fileURLToPath(import.meta.url);
9656
9731
  const __dirname = path.dirname(__filename);
9657
- const protosDir = path.resolve(__dirname, "../../../../protos");
9732
+ const protosDir = this.resolveProtosDir(__dirname);
9658
9733
  const loaderOpts = {
9659
9734
  keepCase: true,
9660
9735
  longs: String,
@@ -9674,10 +9749,13 @@ var BaseClient = class {
9674
9749
  "tool.proto",
9675
9750
  "connector.proto",
9676
9751
  "negotiation.proto",
9752
+ "negotiation_room.proto",
9677
9753
  "reasoning.proto",
9678
9754
  "logging.proto",
9679
9755
  "policy.proto",
9680
- "activity.proto"
9756
+ "activity.proto",
9757
+ "handoff.proto",
9758
+ "workflow.proto"
9681
9759
  ], loaderOpts);
9682
9760
  this.root = grpc.loadPackageDefinition(this.pkgDef);
9683
9761
  this.interceptors.use(timingInterceptor());
@@ -9687,6 +9765,27 @@ var BaseClient = class {
9687
9765
  if (opts.errorMapper)
9688
9766
  opts.errorMapper(this.errorMapper);
9689
9767
  }
9768
+ /**
9769
+ * Resolves the protos directory, checking multiple locations:
9770
+ * 1. npm package: ./protos relative to package root
9771
+ * 2. Monorepo dev: ../../../../protos relative to this file
9772
+ */
9773
+ resolveProtosDir(dirname3) {
9774
+ const candidates = [
9775
+ // npm package structure: node_modules/@sw4rm/js-sdk/protos
9776
+ path.resolve(dirname3, "../../protos"),
9777
+ // Alternative npm structure: dist/esm/internal -> protos
9778
+ path.resolve(dirname3, "../../../protos"),
9779
+ // Monorepo development: sdks/js_sdk/src/internal -> protos
9780
+ path.resolve(dirname3, "../../../../protos")
9781
+ ];
9782
+ for (const candidate of candidates) {
9783
+ if (fs.existsSync(candidate) && fs.existsSync(path.join(candidate, "common.proto"))) {
9784
+ return candidate;
9785
+ }
9786
+ }
9787
+ return candidates[candidates.length - 1];
9788
+ }
9690
9789
  channelCredentials() {
9691
9790
  return grpc.credentials.createInsecure();
9692
9791
  }
@@ -10274,6 +10373,95 @@ var RegistryClient = class extends BaseClient {
10274
10373
  }
10275
10374
  };
10276
10375
 
10376
+ // src/clients/negotiationRoomStore.ts
10377
+ var NegotiationRoomStoreError = class extends Error {
10378
+ constructor(message) {
10379
+ super(message);
10380
+ this.name = "NegotiationRoomStoreError";
10381
+ }
10382
+ };
10383
+ var InMemoryNegotiationRoomStore = class {
10384
+ proposals = /* @__PURE__ */ new Map();
10385
+ votes = /* @__PURE__ */ new Map();
10386
+ decisions = /* @__PURE__ */ new Map();
10387
+ async hasProposal(artifactId) {
10388
+ return this.proposals.has(artifactId);
10389
+ }
10390
+ async getProposal(artifactId) {
10391
+ return this.proposals.get(artifactId) || null;
10392
+ }
10393
+ async saveProposal(proposal) {
10394
+ const artifactId = proposal.artifactId;
10395
+ if (this.proposals.has(artifactId)) {
10396
+ throw new NegotiationRoomStoreError(
10397
+ `Proposal with artifact_id '${artifactId}' already exists`
10398
+ );
10399
+ }
10400
+ const proposalWithTimestamp = {
10401
+ ...proposal,
10402
+ createdAt: proposal.createdAt || (/* @__PURE__ */ new Date()).toISOString()
10403
+ };
10404
+ this.proposals.set(artifactId, proposalWithTimestamp);
10405
+ this.votes.set(artifactId, []);
10406
+ }
10407
+ async listProposals(negotiationRoomId) {
10408
+ const allProposals = Array.from(this.proposals.values());
10409
+ if (negotiationRoomId === void 0) {
10410
+ return allProposals;
10411
+ }
10412
+ return allProposals.filter((p) => p.negotiationRoomId === negotiationRoomId);
10413
+ }
10414
+ async getVotes(artifactId) {
10415
+ return [...this.votes.get(artifactId) || []];
10416
+ }
10417
+ async addVote(vote) {
10418
+ const artifactId = vote.artifactId;
10419
+ const criticId = vote.criticId;
10420
+ const existingVotes = this.votes.get(artifactId) || [];
10421
+ for (const existingVote of existingVotes) {
10422
+ if (existingVote.criticId === criticId) {
10423
+ throw new NegotiationRoomStoreError(
10424
+ `Critic '${criticId}' has already voted for artifact '${artifactId}'`
10425
+ );
10426
+ }
10427
+ }
10428
+ const voteWithTimestamp = {
10429
+ ...vote,
10430
+ votedAt: vote.votedAt || (/* @__PURE__ */ new Date()).toISOString()
10431
+ };
10432
+ if (!this.votes.has(artifactId)) {
10433
+ this.votes.set(artifactId, []);
10434
+ }
10435
+ this.votes.get(artifactId).push(voteWithTimestamp);
10436
+ }
10437
+ async getDecision(artifactId) {
10438
+ return this.decisions.get(artifactId) || null;
10439
+ }
10440
+ async saveDecision(decision) {
10441
+ const artifactId = decision.artifactId;
10442
+ if (this.decisions.has(artifactId)) {
10443
+ throw new NegotiationRoomStoreError(
10444
+ `Decision already exists for artifact_id '${artifactId}'`
10445
+ );
10446
+ }
10447
+ const decisionWithTimestamp = {
10448
+ ...decision,
10449
+ decidedAt: decision.decidedAt || (/* @__PURE__ */ new Date()).toISOString()
10450
+ };
10451
+ this.decisions.set(artifactId, decisionWithTimestamp);
10452
+ }
10453
+ };
10454
+ var defaultStore = null;
10455
+ function getDefaultStore() {
10456
+ if (defaultStore === null) {
10457
+ defaultStore = new InMemoryNegotiationRoomStore();
10458
+ }
10459
+ return defaultStore;
10460
+ }
10461
+ function resetDefaultStore() {
10462
+ defaultStore = null;
10463
+ }
10464
+
10277
10465
  // src/clients/negotiationRoom.ts
10278
10466
  var ArtifactType = /* @__PURE__ */ ((ArtifactType2) => {
10279
10467
  ArtifactType2[ArtifactType2["ARTIFACT_TYPE_UNSPECIFIED"] = 0] = "ARTIFACT_TYPE_UNSPECIFIED";
@@ -10315,9 +10503,16 @@ function validateVote(vote) {
10315
10503
  }
10316
10504
  }
10317
10505
  var NegotiationRoomClient = class {
10318
- proposals = /* @__PURE__ */ new Map();
10319
- votes = /* @__PURE__ */ new Map();
10320
- decisions = /* @__PURE__ */ new Map();
10506
+ store;
10507
+ /**
10508
+ * Create a new negotiation room client.
10509
+ *
10510
+ * @param options - Configuration options. If no store is provided,
10511
+ * uses the shared default in-memory store.
10512
+ */
10513
+ constructor(options = {}) {
10514
+ this.store = options.store || getDefaultStore();
10515
+ }
10321
10516
  /**
10322
10517
  * Submit an artifact proposal for multi-agent review.
10323
10518
  *
@@ -10345,19 +10540,8 @@ var NegotiationRoomClient = class {
10345
10540
  * ```
10346
10541
  */
10347
10542
  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;
10543
+ await this.store.saveProposal(proposal);
10544
+ return proposal.artifactId;
10361
10545
  }
10362
10546
  /**
10363
10547
  * Submit a critic's vote for an artifact.
@@ -10389,26 +10573,13 @@ var NegotiationRoomClient = class {
10389
10573
  */
10390
10574
  async submitVote(vote) {
10391
10575
  const artifactId = vote.artifactId;
10392
- if (!this.proposals.has(artifactId)) {
10576
+ if (!await this.store.hasProposal(artifactId)) {
10393
10577
  throw new NegotiationValidationError(
10394
10578
  `No proposal found for artifact_id '${artifactId}'`
10395
10579
  );
10396
10580
  }
10397
10581
  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);
10582
+ await this.store.addVote(vote);
10412
10583
  }
10413
10584
  /**
10414
10585
  * Retrieve all votes for a specific artifact.
@@ -10428,12 +10599,12 @@ var NegotiationRoomClient = class {
10428
10599
  * ```
10429
10600
  */
10430
10601
  async getVotes(artifactId) {
10431
- if (!this.proposals.has(artifactId)) {
10602
+ if (!await this.store.hasProposal(artifactId)) {
10432
10603
  throw new NegotiationValidationError(
10433
10604
  `No proposal found for artifact_id '${artifactId}'`
10434
10605
  );
10435
10606
  }
10436
- return this.votes.get(artifactId) || [];
10607
+ return this.store.getVotes(artifactId);
10437
10608
  }
10438
10609
  /**
10439
10610
  * Retrieve the decision for a specific artifact if available.
@@ -10454,12 +10625,12 @@ var NegotiationRoomClient = class {
10454
10625
  * ```
10455
10626
  */
10456
10627
  async getDecision(artifactId) {
10457
- if (!this.proposals.has(artifactId)) {
10628
+ if (!await this.store.hasProposal(artifactId)) {
10458
10629
  throw new NegotiationValidationError(
10459
10630
  `No proposal found for artifact_id '${artifactId}'`
10460
10631
  );
10461
10632
  }
10462
- return this.decisions.get(artifactId) || null;
10633
+ return this.store.getDecision(artifactId);
10463
10634
  }
10464
10635
  /**
10465
10636
  * Store a decision for an artifact.
@@ -10490,21 +10661,12 @@ var NegotiationRoomClient = class {
10490
10661
  */
10491
10662
  async storeDecision(decision) {
10492
10663
  const artifactId = decision.artifactId;
10493
- if (!this.proposals.has(artifactId)) {
10664
+ if (!await this.store.hasProposal(artifactId)) {
10494
10665
  throw new NegotiationValidationError(
10495
10666
  `No proposal found for artifact_id '${artifactId}'`
10496
10667
  );
10497
10668
  }
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);
10669
+ await this.store.saveDecision(decision);
10508
10670
  }
10509
10671
  /**
10510
10672
  * Wait for a decision to be made on an artifact.
@@ -10528,14 +10690,14 @@ var NegotiationRoomClient = class {
10528
10690
  * ```
10529
10691
  */
10530
10692
  async waitForDecision(artifactId, timeoutMs = 3e4, pollIntervalMs = 100) {
10531
- if (!this.proposals.has(artifactId)) {
10693
+ if (!await this.store.hasProposal(artifactId)) {
10532
10694
  throw new NegotiationValidationError(
10533
10695
  `No proposal found for artifact_id '${artifactId}'`
10534
10696
  );
10535
10697
  }
10536
10698
  const startTime = Date.now();
10537
10699
  while (Date.now() - startTime < timeoutMs) {
10538
- const decision = await this.getDecision(artifactId);
10700
+ const decision = await this.store.getDecision(artifactId);
10539
10701
  if (decision !== null) {
10540
10702
  return decision;
10541
10703
  }
@@ -10561,7 +10723,7 @@ var NegotiationRoomClient = class {
10561
10723
  * ```
10562
10724
  */
10563
10725
  async getProposal(artifactId) {
10564
- return this.proposals.get(artifactId) || null;
10726
+ return this.store.getProposal(artifactId);
10565
10727
  }
10566
10728
  /**
10567
10729
  * List all proposals, optionally filtered by negotiation room.
@@ -10576,13 +10738,7 @@ var NegotiationRoomClient = class {
10576
10738
  * ```
10577
10739
  */
10578
10740
  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
- );
10741
+ return this.store.listProposals(negotiationRoomId);
10586
10742
  }
10587
10743
  };
10588
10744
  function aggregateVotes(votes) {
@@ -10625,6 +10781,38 @@ var HandoffStatus = /* @__PURE__ */ ((HandoffStatus2) => {
10625
10781
  HandoffStatus2[HandoffStatus2["EXPIRED"] = 5] = "EXPIRED";
10626
10782
  return HandoffStatus2;
10627
10783
  })(HandoffStatus || {});
10784
+ var DEFAULT_MAX_RETRIES_ON_OVERLOADED = 2;
10785
+ var DEFAULT_INITIAL_BACKOFF_MS = 250;
10786
+ var DEFAULT_BACKOFF_MULTIPLIER = 2;
10787
+ var DEFAULT_MAX_BACKOFF_MS = 2e3;
10788
+ var DEFAULT_MAX_REDIRECTS = 0;
10789
+ function defaultDelegationPolicy() {
10790
+ return {
10791
+ maxRetriesOnOverloaded: DEFAULT_MAX_RETRIES_ON_OVERLOADED,
10792
+ initialBackoffMs: DEFAULT_INITIAL_BACKOFF_MS,
10793
+ backoffMultiplier: DEFAULT_BACKOFF_MULTIPLIER,
10794
+ maxBackoffMs: DEFAULT_MAX_BACKOFF_MS,
10795
+ allowSpilloverRouting: false,
10796
+ maxRedirects: DEFAULT_MAX_REDIRECTS
10797
+ };
10798
+ }
10799
+ function normalizeDelegationPolicy(policy) {
10800
+ const defaults = defaultDelegationPolicy();
10801
+ const maxRetriesOnOverloaded = policy?.maxRetriesOnOverloaded;
10802
+ const initialBackoffMs = policy?.initialBackoffMs;
10803
+ const backoffMultiplier = policy?.backoffMultiplier;
10804
+ const maxBackoffMs = policy?.maxBackoffMs;
10805
+ const allowSpilloverRouting = policy?.allowSpilloverRouting;
10806
+ const maxRedirects = policy?.maxRedirects;
10807
+ return {
10808
+ maxRetriesOnOverloaded: maxRetriesOnOverloaded === void 0 ? defaults.maxRetriesOnOverloaded : maxRetriesOnOverloaded,
10809
+ initialBackoffMs: initialBackoffMs !== void 0 && initialBackoffMs > 0 ? initialBackoffMs : defaults.initialBackoffMs,
10810
+ backoffMultiplier: backoffMultiplier !== void 0 && backoffMultiplier > 0 ? backoffMultiplier : defaults.backoffMultiplier,
10811
+ maxBackoffMs: maxBackoffMs !== void 0 && maxBackoffMs > 0 ? maxBackoffMs : defaults.maxBackoffMs,
10812
+ allowSpilloverRouting: allowSpilloverRouting ?? defaults.allowSpilloverRouting,
10813
+ maxRedirects: maxRedirects === void 0 ? defaults.maxRedirects : maxRedirects
10814
+ };
10815
+ }
10628
10816
  var HandoffValidationError = class extends Error {
10629
10817
  constructor(message) {
10630
10818
  super(message);
@@ -10673,9 +10861,15 @@ var HandoffClient = class {
10673
10861
  `Handoff request with ID '${request.requestId}' already exists`
10674
10862
  );
10675
10863
  }
10864
+ if (request.budget !== void 0 && (!request.budget.deadlineEpochMs || request.budget.deadlineEpochMs <= 0)) {
10865
+ throw new HandoffValidationError(
10866
+ "budget.deadlineEpochMs is required for cross-swarm delegation"
10867
+ );
10868
+ }
10676
10869
  const requestWithTimestamp = {
10677
10870
  ...request,
10678
- createdAt: request.createdAt || (/* @__PURE__ */ new Date()).toISOString()
10871
+ createdAt: request.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
10872
+ delegationPolicy: request.budget !== void 0 || request.delegationPolicy !== void 0 ? normalizeDelegationPolicy(request.delegationPolicy) : void 0
10679
10873
  };
10680
10874
  this.requests.set(request.requestId, requestWithTimestamp);
10681
10875
  if (request.toAgent) {
@@ -10697,7 +10891,8 @@ var HandoffClient = class {
10697
10891
  const timeoutResponse = {
10698
10892
  requestId: request.requestId,
10699
10893
  accepted: false,
10700
- rejectionReason: `Handoff request timed out after ${timeoutMs}ms`
10894
+ rejectionReason: `Handoff request timed out after ${timeoutMs}ms`,
10895
+ rejectionCode: 3 /* ACK_TIMEOUT */
10701
10896
  };
10702
10897
  this.responses.set(request.requestId, timeoutResponse);
10703
10898
  if (request.toAgent && this.pendingByAgent.has(request.toAgent)) {
@@ -10762,7 +10957,7 @@ var HandoffClient = class {
10762
10957
  * await client.rejectHandoff("handoff-123", "Agent at capacity");
10763
10958
  * ```
10764
10959
  */
10765
- async rejectHandoff(handoffId, reason) {
10960
+ async rejectHandoff(handoffId, reason, options) {
10766
10961
  const request = this.requests.get(handoffId);
10767
10962
  if (!request) {
10768
10963
  throw new HandoffValidationError(
@@ -10777,7 +10972,10 @@ var HandoffClient = class {
10777
10972
  const response = {
10778
10973
  requestId: handoffId,
10779
10974
  accepted: false,
10780
- rejectionReason: reason
10975
+ rejectionReason: reason,
10976
+ rejectionCode: options?.rejectionCode ?? 0 /* ERROR_CODE_UNSPECIFIED */,
10977
+ retryAfterMs: options?.retryAfterMs,
10978
+ redirectToAgentId: options?.redirectToAgentId
10781
10979
  };
10782
10980
  this.responses.set(handoffId, response);
10783
10981
  if (request.toAgent && this.pendingByAgent.has(request.toAgent)) {
@@ -11210,6 +11408,31 @@ var WorkflowClient = class {
11210
11408
  instance.completedAt = (/* @__PURE__ */ new Date()).toISOString();
11211
11409
  }
11212
11410
  }
11411
+ /**
11412
+ * Resume a workflow by marking a node as completed and advancing dependents.
11413
+ *
11414
+ * Implements the ResumeWorkflow RPC (spec §17.7 MUST). Marks the specified
11415
+ * node as COMPLETED, updates workflow data if provided, then transitions
11416
+ * dependent nodes from PENDING to READY when all their dependencies are met.
11417
+ *
11418
+ * @param instanceId - The ID of the workflow instance
11419
+ * @param nodeId - The ID of the node to mark as completed
11420
+ * @param workflowData - Optional updated workflow data (JSON string)
11421
+ * @param metadata - Optional metadata for the resume operation
11422
+ * @returns The updated workflow instance
11423
+ * @throws WorkflowValidationError if the instance or node does not exist
11424
+ */
11425
+ async resumeWorkflow(instanceId, nodeId, workflowData, metadata) {
11426
+ await this.updateNodeState(instanceId, nodeId, 4 /* COMPLETED */);
11427
+ if (workflowData !== void 0) {
11428
+ await this.updateWorkflowData(instanceId, workflowData);
11429
+ }
11430
+ if (metadata) {
11431
+ const instance = this.instances.get(instanceId);
11432
+ Object.assign(instance.metadata, metadata);
11433
+ }
11434
+ return this.getWorkflowStatus(instanceId);
11435
+ }
11213
11436
  /**
11214
11437
  * Update the shared workflow data.
11215
11438
  *
@@ -11231,6 +11454,21 @@ var WorkflowClient = class {
11231
11454
 
11232
11455
  // src/internal/envelope.ts
11233
11456
  import crypto2 from "node:crypto";
11457
+ var MessageType = /* @__PURE__ */ ((MessageType2) => {
11458
+ MessageType2[MessageType2["MESSAGE_TYPE_UNSPECIFIED"] = 0] = "MESSAGE_TYPE_UNSPECIFIED";
11459
+ MessageType2[MessageType2["CONTROL"] = 1] = "CONTROL";
11460
+ MessageType2[MessageType2["DATA"] = 2] = "DATA";
11461
+ MessageType2[MessageType2["HEARTBEAT"] = 3] = "HEARTBEAT";
11462
+ MessageType2[MessageType2["NOTIFICATION"] = 4] = "NOTIFICATION";
11463
+ MessageType2[MessageType2["ACKNOWLEDGEMENT"] = 5] = "ACKNOWLEDGEMENT";
11464
+ MessageType2[MessageType2["HITL_INVOCATION"] = 6] = "HITL_INVOCATION";
11465
+ MessageType2[MessageType2["WORKTREE_CONTROL"] = 7] = "WORKTREE_CONTROL";
11466
+ MessageType2[MessageType2["NEGOTIATION"] = 8] = "NEGOTIATION";
11467
+ MessageType2[MessageType2["TOOL_CALL"] = 9] = "TOOL_CALL";
11468
+ MessageType2[MessageType2["TOOL_RESULT"] = 10] = "TOOL_RESULT";
11469
+ MessageType2[MessageType2["TOOL_ERROR"] = 11] = "TOOL_ERROR";
11470
+ return MessageType2;
11471
+ })(MessageType || {});
11234
11472
  function nowTimestamp(date = /* @__PURE__ */ new Date()) {
11235
11473
  const ms = date.getTime();
11236
11474
  const seconds = Math.floor(ms / 1e3);
@@ -11238,7 +11476,15 @@ function nowTimestamp(date = /* @__PURE__ */ new Date()) {
11238
11476
  return { seconds, nanos };
11239
11477
  }
11240
11478
  function nowHlcStub(date = /* @__PURE__ */ new Date()) {
11241
- return String(date.getTime());
11479
+ const wallUs = date.getTime() * 1e3;
11480
+ let node = "unknown";
11481
+ try {
11482
+ const os3 = __require("node:os");
11483
+ node = os3.hostname() || "unknown";
11484
+ } catch {
11485
+ node = "browser";
11486
+ }
11487
+ return `HLC:${wallUs}:0:${node}`;
11242
11488
  }
11243
11489
  function uuidv42() {
11244
11490
  if (typeof crypto2.randomUUID === "function") {
@@ -11274,7 +11520,12 @@ function buildEnvelope(input) {
11274
11520
  hlc_timestamp,
11275
11521
  // Always set hlc_timestamp (aligns with Python/Rust)
11276
11522
  ttl_ms: input.ttl_ms,
11277
- timestamp: ts
11523
+ timestamp: ts,
11524
+ state: input.state ?? 1,
11525
+ // EnvelopeState.CREATED
11526
+ effective_policy_id: input.effective_policy_id ?? "",
11527
+ audit_proof: input.audit_proof ?? new Uint8Array(0),
11528
+ audit_policy_id: input.audit_policy_id ?? ""
11278
11529
  };
11279
11530
  if (hasPayload) {
11280
11531
  const payload = input.payload instanceof Uint8Array ? input.payload : new Uint8Array(input.payload);
@@ -11288,25 +11539,141 @@ function buildEnvelope(input) {
11288
11539
  }
11289
11540
 
11290
11541
  // src/internal/worktreeState.ts
11542
+ var VALID_WORKTREE_TRANSITIONS = {
11543
+ UNBOUND: ["BOUND_HOME", "BIND_FAILED"],
11544
+ BOUND_HOME: ["SWITCH_PENDING", "UNBOUND"],
11545
+ SWITCH_PENDING: ["BOUND_NON_HOME", "BOUND_HOME"],
11546
+ // approve or reject
11547
+ BOUND_NON_HOME: ["BOUND_HOME", "UNBOUND"],
11548
+ // TTL expired/revoke, or unbind
11549
+ BIND_FAILED: ["UNBOUND", "BOUND_HOME"]
11550
+ // retry reset or successful retry
11551
+ };
11552
+ function isValidWorktreeTransition(from, to) {
11553
+ return VALID_WORKTREE_TRANSITIONS[from]?.includes(to) ?? false;
11554
+ }
11555
+ var WorktreeTransitionError = class extends Error {
11556
+ fromState;
11557
+ toState;
11558
+ constructor(from, to) {
11559
+ super(`Invalid worktree state transition from ${from} to ${to}`);
11560
+ this.name = "WorktreeTransitionError";
11561
+ this.fromState = from;
11562
+ this.toState = to;
11563
+ }
11564
+ };
11291
11565
  var PersistentWorktreeState = class {
11292
11566
  state = "UNBOUND";
11293
11567
  repoId;
11294
11568
  worktreeId;
11569
+ homeRepoId;
11570
+ homeWorktreeId;
11571
+ switchTtlMs;
11572
+ switchTimer;
11573
+ /**
11574
+ * Transition to a new state with validation.
11575
+ * @throws WorktreeTransitionError if transition is invalid
11576
+ */
11577
+ transitionTo(newState) {
11578
+ if (!isValidWorktreeTransition(this.state, newState)) {
11579
+ throw new WorktreeTransitionError(this.state, newState);
11580
+ }
11581
+ this.state = newState;
11582
+ }
11583
+ /**
11584
+ * Bind to a home worktree (UNBOUND -> BOUND_HOME or BIND_FAILED -> BOUND_HOME).
11585
+ */
11295
11586
  bind(repoId, worktreeId) {
11587
+ this.transitionTo("BOUND_HOME");
11296
11588
  this.repoId = repoId;
11297
11589
  this.worktreeId = worktreeId;
11298
- this.state = "BOUND_HOME";
11590
+ this.homeRepoId = repoId;
11591
+ this.homeWorktreeId = worktreeId;
11592
+ }
11593
+ /**
11594
+ * Handle bind failure (UNBOUND -> BIND_FAILED).
11595
+ */
11596
+ bindFailed() {
11597
+ this.transitionTo("BIND_FAILED");
11299
11598
  }
11599
+ /**
11600
+ * Unbind from current worktree.
11601
+ */
11300
11602
  unbind() {
11603
+ this.clearSwitchTimer();
11604
+ this.transitionTo("UNBOUND");
11301
11605
  this.repoId = void 0;
11302
11606
  this.worktreeId = void 0;
11303
- this.state = "UNBOUND";
11607
+ }
11608
+ /**
11609
+ * Request switch to a non-home worktree (BOUND_HOME -> SWITCH_PENDING).
11610
+ * Requires approval or rejection before taking effect.
11611
+ */
11612
+ requestSwitch(targetRepoId, targetWorktreeId) {
11613
+ this.transitionTo("SWITCH_PENDING");
11614
+ this._pendingRepoId = targetRepoId;
11615
+ this._pendingWorktreeId = targetWorktreeId;
11616
+ }
11617
+ /**
11618
+ * Approve a pending switch (SWITCH_PENDING -> BOUND_NON_HOME).
11619
+ * @param ttlMs - Time-to-live in milliseconds before auto-reverting to BOUND_HOME
11620
+ */
11621
+ approveSwitch(ttlMs = 3e5) {
11622
+ this.transitionTo("BOUND_NON_HOME");
11623
+ this.repoId = this._pendingRepoId;
11624
+ this.worktreeId = this._pendingWorktreeId;
11625
+ this.switchTtlMs = ttlMs;
11626
+ this.clearSwitchTimer();
11627
+ this.switchTimer = setTimeout(() => {
11628
+ this.revertToHome();
11629
+ }, ttlMs);
11630
+ }
11631
+ /**
11632
+ * Reject a pending switch (SWITCH_PENDING -> BOUND_HOME).
11633
+ */
11634
+ rejectSwitch() {
11635
+ this.transitionTo("BOUND_HOME");
11636
+ this.repoId = this.homeRepoId;
11637
+ this.worktreeId = this.homeWorktreeId;
11638
+ delete this._pendingRepoId;
11639
+ delete this._pendingWorktreeId;
11640
+ }
11641
+ /**
11642
+ * Revert from non-home to home worktree (BOUND_NON_HOME -> BOUND_HOME).
11643
+ * Called on TTL expiry or explicit revoke.
11644
+ */
11645
+ revertToHome() {
11646
+ this.clearSwitchTimer();
11647
+ if (this.state === "BOUND_NON_HOME") {
11648
+ this.transitionTo("BOUND_HOME");
11649
+ this.repoId = this.homeRepoId;
11650
+ this.worktreeId = this.homeWorktreeId;
11651
+ }
11652
+ }
11653
+ /**
11654
+ * Reset from BIND_FAILED to UNBOUND for retry.
11655
+ */
11656
+ resetFromFailed() {
11657
+ this.transitionTo("UNBOUND");
11658
+ }
11659
+ clearSwitchTimer() {
11660
+ if (this.switchTimer) {
11661
+ clearTimeout(this.switchTimer);
11662
+ this.switchTimer = void 0;
11663
+ }
11304
11664
  }
11305
11665
  setState(state) {
11306
11666
  this.state = state;
11307
11667
  }
11308
11668
  current() {
11309
- return { state: this.state, repo_id: this.repoId, worktree_id: this.worktreeId };
11669
+ return {
11670
+ state: this.state,
11671
+ repo_id: this.repoId,
11672
+ worktree_id: this.worktreeId,
11673
+ home_repo_id: this.homeRepoId,
11674
+ home_worktree_id: this.homeWorktreeId,
11675
+ switch_ttl_ms: this.switchTtlMs
11676
+ };
11310
11677
  }
11311
11678
  };
11312
11679
 
@@ -11368,16 +11735,6 @@ var ActivityBuffer = class {
11368
11735
  };
11369
11736
 
11370
11737
  // src/internal/runtime/ackLifecycle.ts
11371
- var AckStage = /* @__PURE__ */ ((AckStage2) => {
11372
- AckStage2[AckStage2["ACK_STAGE_UNSPECIFIED"] = 0] = "ACK_STAGE_UNSPECIFIED";
11373
- AckStage2[AckStage2["RECEIVED"] = 1] = "RECEIVED";
11374
- AckStage2[AckStage2["READ"] = 2] = "READ";
11375
- AckStage2[AckStage2["FULFILLED"] = 3] = "FULFILLED";
11376
- AckStage2[AckStage2["REJECTED"] = 4] = "REJECTED";
11377
- AckStage2[AckStage2["FAILED"] = 5] = "FAILED";
11378
- AckStage2[AckStage2["TIMED_OUT"] = 6] = "TIMED_OUT";
11379
- return AckStage2;
11380
- })(AckStage || {});
11381
11738
  var ACKLifecycleManager = class {
11382
11739
  acks = /* @__PURE__ */ new Map();
11383
11740
  mark(messageId, stage, note, errorCode) {
@@ -11414,21 +11771,6 @@ var ACKLifecycleManager = class {
11414
11771
  };
11415
11772
 
11416
11773
  // src/internal/runtime/messageProcessor.ts
11417
- var MessageType = /* @__PURE__ */ ((MessageType3) => {
11418
- MessageType3[MessageType3["MESSAGE_TYPE_UNSPECIFIED"] = 0] = "MESSAGE_TYPE_UNSPECIFIED";
11419
- MessageType3[MessageType3["CONTROL"] = 1] = "CONTROL";
11420
- MessageType3[MessageType3["DATA"] = 2] = "DATA";
11421
- MessageType3[MessageType3["HEARTBEAT"] = 3] = "HEARTBEAT";
11422
- MessageType3[MessageType3["NOTIFICATION"] = 4] = "NOTIFICATION";
11423
- MessageType3[MessageType3["ACKNOWLEDGEMENT"] = 5] = "ACKNOWLEDGEMENT";
11424
- MessageType3[MessageType3["HITL_INVOCATION"] = 6] = "HITL_INVOCATION";
11425
- MessageType3[MessageType3["WORKTREE_CONTROL"] = 7] = "WORKTREE_CONTROL";
11426
- MessageType3[MessageType3["NEGOTIATION"] = 8] = "NEGOTIATION";
11427
- MessageType3[MessageType3["TOOL_CALL"] = 9] = "TOOL_CALL";
11428
- MessageType3[MessageType3["TOOL_RESULT"] = 10] = "TOOL_RESULT";
11429
- MessageType3[MessageType3["TOOL_ERROR"] = 11] = "TOOL_ERROR";
11430
- return MessageType3;
11431
- })(MessageType || {});
11432
11774
  var MessageProcessor = class {
11433
11775
  handlers = /* @__PURE__ */ new Map();
11434
11776
  defaultHandler;
@@ -11595,35 +11937,571 @@ function decodeBase64(b64) {
11595
11937
  return new Uint8Array(Buffer.from(b64, "base64"));
11596
11938
  }
11597
11939
 
11598
- // src/persistence/persistence.ts
11599
- import fsp from "node:fs/promises";
11600
- import path2 from "node:path";
11601
- var JSONFilePersistence = class {
11602
- constructor(baseDir) {
11603
- this.baseDir = baseDir;
11604
- this.activityFile = path2.join(baseDir, "activity.json");
11605
- this.acksFile = path2.join(baseDir, "acks.json");
11940
+ // src/runtime/delegation.ts
11941
+ import { randomUUID } from "node:crypto";
11942
+ var RETRY_AFTER_JITTER_RATIO = 0.2;
11943
+ var DEFAULT_EFFECTIVE_MAX_REDIRECTS = 2;
11944
+ function defaultNowMs() {
11945
+ return Date.now();
11946
+ }
11947
+ function defaultSleepMs(milliseconds) {
11948
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
11949
+ }
11950
+ function defaultRandUniform(low, high) {
11951
+ if (high <= low) {
11952
+ return low;
11606
11953
  }
11607
- activityFile;
11608
- acksFile;
11609
- async safeWrite(file, data) {
11610
- await fsp.mkdir(path2.dirname(file), { recursive: true });
11611
- const tmp = `${file}.tmp-${Date.now()}`;
11612
- await fsp.writeFile(tmp, data, "utf8");
11613
- await fsp.rename(tmp, file);
11954
+ return low + Math.random() * (high - low);
11955
+ }
11956
+ function normalizePolicy(policy) {
11957
+ return {
11958
+ maxRetriesOnOverloaded: policy?.maxRetriesOnOverloaded ?? DEFAULT_MAX_RETRIES_ON_OVERLOADED,
11959
+ initialBackoffMs: policy?.initialBackoffMs !== void 0 && policy.initialBackoffMs > 0 ? policy.initialBackoffMs : DEFAULT_INITIAL_BACKOFF_MS,
11960
+ backoffMultiplier: policy?.backoffMultiplier !== void 0 && policy.backoffMultiplier > 0 ? policy.backoffMultiplier : DEFAULT_BACKOFF_MULTIPLIER,
11961
+ maxBackoffMs: policy?.maxBackoffMs !== void 0 && policy.maxBackoffMs > 0 ? policy.maxBackoffMs : DEFAULT_MAX_BACKOFF_MS,
11962
+ allowSpilloverRouting: policy?.allowSpilloverRouting ?? false,
11963
+ maxRedirects: policy?.maxRedirects ?? DEFAULT_MAX_REDIRECTS
11964
+ };
11965
+ }
11966
+ function deadlineExhaustedResponse(requestId) {
11967
+ return {
11968
+ requestId,
11969
+ accepted: false,
11970
+ rejectionReason: "Delegation deadline exhausted before handoff acceptance",
11971
+ rejectionCode: 3 /* ACK_TIMEOUT */
11972
+ };
11973
+ }
11974
+ function invalidRedirectResponse(requestId, reason) {
11975
+ return {
11976
+ requestId,
11977
+ accepted: false,
11978
+ rejectionReason: reason,
11979
+ rejectionCode: 6 /* VALIDATION_ERROR */
11980
+ };
11981
+ }
11982
+ function effectiveMaxRedirects(policy) {
11983
+ const configured = policy.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
11984
+ return configured > 0 ? configured : DEFAULT_EFFECTIVE_MAX_REDIRECTS;
11985
+ }
11986
+ function nextRetryWaitMs(response, retryIndex, policy, randUniformFn) {
11987
+ if (response.retryAfterMs !== void 0 && response.retryAfterMs > 0) {
11988
+ const retryAfter = response.retryAfterMs;
11989
+ const jitter = randUniformFn(0, retryAfter * RETRY_AFTER_JITTER_RATIO);
11990
+ return Math.floor(retryAfter + jitter);
11991
+ }
11992
+ const initialBackoffMs = policy.initialBackoffMs ?? DEFAULT_INITIAL_BACKOFF_MS;
11993
+ const backoffMultiplier = policy.backoffMultiplier ?? DEFAULT_BACKOFF_MULTIPLIER;
11994
+ const maxBackoffMs = policy.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
11995
+ const exponential = initialBackoffMs * backoffMultiplier ** retryIndex;
11996
+ const bounded = Math.min(exponential, maxBackoffMs);
11997
+ return Math.floor(randUniformFn(0, bounded));
11998
+ }
11999
+ function deductWallTime(request, elapsedMs) {
12000
+ if (request.budget?.wallTimeRemainingMs !== void 0) {
12001
+ request.budget.wallTimeRemainingMs = Math.max(
12002
+ request.budget.wallTimeRemainingMs - elapsedMs,
12003
+ 0
12004
+ );
11614
12005
  }
11615
- async saveActivity(records) {
11616
- const payload = JSON.stringify(records, null, 2);
11617
- await this.safeWrite(this.activityFile, payload);
12006
+ }
12007
+ function budgetExhausted(budget, nowMs) {
12008
+ return budget.wallTimeRemainingMs !== void 0 && budget.wallTimeRemainingMs <= 0 || nowMs > budget.deadlineEpochMs;
12009
+ }
12010
+ async function delegateToSwarm(options) {
12011
+ if (!options.budget.deadlineEpochMs || options.budget.deadlineEpochMs <= 0) {
12012
+ throw new HandoffValidationError(
12013
+ "budget.deadlineEpochMs is required for cross-swarm delegation"
12014
+ );
11618
12015
  }
11619
- async loadActivity() {
11620
- try {
11621
- const buf = await fsp.readFile(this.activityFile, "utf8");
11622
- return JSON.parse(buf);
11623
- } catch (e) {
11624
- if (e?.code === "ENOENT")
11625
- return [];
11626
- throw e;
12016
+ if (options.timeoutMs !== void 0 && options.timeoutMs < 0) {
12017
+ throw new HandoffValidationError("timeoutMs must be >= 0");
12018
+ }
12019
+ const nowMs = options.nowMsFn ?? defaultNowMs;
12020
+ const sleepMs = options.sleepMsFn ?? defaultSleepMs;
12021
+ const randUniform = options.randUniformFn ?? defaultRandUniform;
12022
+ const policy = normalizePolicy(options.delegationPolicy);
12023
+ const requestBudget = { ...options.budget };
12024
+ const request = {
12025
+ requestId: options.requestId ?? randomUUID(),
12026
+ fromAgent: options.fromAgent,
12027
+ toAgent: options.toAgent,
12028
+ reason: options.reason,
12029
+ contextSnapshot: options.contextSnapshot ?? new Uint8Array(),
12030
+ capabilitiesRequired: [...options.capabilitiesRequired ?? []],
12031
+ priority: options.priority ?? 0,
12032
+ timeoutMs: options.timeoutMs,
12033
+ budget: requestBudget,
12034
+ delegationPolicy: policy
12035
+ };
12036
+ const maxRetriesOnOverloaded = policy.maxRetriesOnOverloaded ?? DEFAULT_MAX_RETRIES_ON_OVERLOADED;
12037
+ let retryIndex = 0;
12038
+ let redirectHops = 0;
12039
+ const redirectBound = effectiveMaxRedirects(policy);
12040
+ const visitedAgents = /* @__PURE__ */ new Set([request.toAgent]);
12041
+ while (true) {
12042
+ const startMs = nowMs();
12043
+ if (budgetExhausted(request.budget, startMs)) {
12044
+ return deadlineExhaustedResponse(request.requestId);
12045
+ }
12046
+ const response = await options.sendHandoffFn(request);
12047
+ const endMs = nowMs();
12048
+ const elapsedMs = Math.max(endMs - startMs, 0);
12049
+ deductWallTime(request, elapsedMs);
12050
+ if (response.accepted) {
12051
+ return response;
12052
+ }
12053
+ if (budgetExhausted(request.budget, endMs)) {
12054
+ return deadlineExhaustedResponse(request.requestId);
12055
+ }
12056
+ if (response.rejectionCode !== 16 /* OVERLOADED */) {
12057
+ if (response.rejectionCode !== 20 /* REDIRECT */) {
12058
+ return response;
12059
+ }
12060
+ if (!policy.allowSpilloverRouting) {
12061
+ return response;
12062
+ }
12063
+ const targetAgent = response.redirectToAgentId?.trim();
12064
+ if (!targetAgent) {
12065
+ return invalidRedirectResponse(
12066
+ request.requestId,
12067
+ "Redirect response missing non-empty redirectToAgentId"
12068
+ );
12069
+ }
12070
+ if (visitedAgents.has(targetAgent)) {
12071
+ return invalidRedirectResponse(
12072
+ request.requestId,
12073
+ `Redirect loop detected for agent '${targetAgent}'`
12074
+ );
12075
+ }
12076
+ if (redirectHops >= redirectBound) {
12077
+ return response;
12078
+ }
12079
+ request.toAgent = targetAgent;
12080
+ visitedAgents.add(targetAgent);
12081
+ redirectHops += 1;
12082
+ continue;
12083
+ }
12084
+ if (retryIndex >= maxRetriesOnOverloaded) {
12085
+ return response;
12086
+ }
12087
+ const waitMs = nextRetryWaitMs(response, retryIndex, policy, randUniform);
12088
+ retryIndex += 1;
12089
+ const remainingDeadlineMs = request.budget.deadlineEpochMs - endMs;
12090
+ const remainingWallTimeMs = request.budget?.wallTimeRemainingMs;
12091
+ if (waitMs <= 0 || remainingWallTimeMs !== void 0 && waitMs > remainingWallTimeMs || waitMs > remainingDeadlineMs) {
12092
+ return response;
12093
+ }
12094
+ const beforeSleepMs = nowMs();
12095
+ await sleepMs(waitMs);
12096
+ const afterSleepMs = nowMs();
12097
+ deductWallTime(request, Math.max(afterSleepMs - beforeSleepMs, 0));
12098
+ }
12099
+ }
12100
+
12101
+ // src/runtime/cancellation.ts
12102
+ var MIN_GRACE_PERIOD_MS = 5e3;
12103
+ var CancellationValidationError = class extends Error {
12104
+ constructor(message) {
12105
+ super(message);
12106
+ this.name = "CancellationValidationError";
12107
+ }
12108
+ };
12109
+ function defaultNowMs2() {
12110
+ return Date.now();
12111
+ }
12112
+ function normalizeCorrelationId(correlationId) {
12113
+ const normalized = correlationId.trim();
12114
+ if (!normalized) {
12115
+ throw new CancellationValidationError(
12116
+ "cancel.correlationId is required and must be a non-empty string"
12117
+ );
12118
+ }
12119
+ return normalized;
12120
+ }
12121
+ function normalizeReason(reason) {
12122
+ if (reason === void 0) {
12123
+ return "";
12124
+ }
12125
+ return reason.trim();
12126
+ }
12127
+ function normalizeGracePeriodMs(gracePeriodMs) {
12128
+ const requested = gracePeriodMs !== void 0 && Number.isFinite(gracePeriodMs) && gracePeriodMs > 0 ? Math.floor(gracePeriodMs) : 0;
12129
+ return Math.max(requested, MIN_GRACE_PERIOD_MS);
12130
+ }
12131
+ function normalizeMetadataValue(value) {
12132
+ if (value === null) {
12133
+ return null;
12134
+ }
12135
+ if (typeof value === "string") {
12136
+ return value.trim();
12137
+ }
12138
+ if (typeof value === "number") {
12139
+ return Number.isFinite(value) ? value : void 0;
12140
+ }
12141
+ if (typeof value === "boolean") {
12142
+ return value;
12143
+ }
12144
+ if (value instanceof Date) {
12145
+ return value.toISOString();
12146
+ }
12147
+ if (typeof value === "bigint") {
12148
+ return value.toString();
12149
+ }
12150
+ if (typeof value === "object") {
12151
+ try {
12152
+ return JSON.stringify(value);
12153
+ } catch {
12154
+ return void 0;
12155
+ }
12156
+ }
12157
+ return void 0;
12158
+ }
12159
+ function normalizeMetadata(metadata, options) {
12160
+ const { reason, gracePeriodMs } = options;
12161
+ const normalized = {};
12162
+ if (metadata !== void 0) {
12163
+ for (const [rawKey, rawValue] of Object.entries(metadata)) {
12164
+ const key = rawKey.trim();
12165
+ if (!key) {
12166
+ continue;
12167
+ }
12168
+ const value = normalizeMetadataValue(rawValue);
12169
+ if (value !== void 0) {
12170
+ normalized[key] = value;
12171
+ }
12172
+ }
12173
+ }
12174
+ normalized.reason = reason;
12175
+ normalized.grace_period_ms = gracePeriodMs;
12176
+ return normalized;
12177
+ }
12178
+ function cloneMetadata(metadata) {
12179
+ return { ...metadata };
12180
+ }
12181
+ function cloneFlag(flag) {
12182
+ return {
12183
+ cancelled: flag.cancelled,
12184
+ gracePeriodMs: flag.gracePeriodMs,
12185
+ cancelTimeMs: flag.cancelTimeMs,
12186
+ metadata: cloneMetadata(flag.metadata)
12187
+ };
12188
+ }
12189
+ var CancellationManager = class {
12190
+ childDelegations = /* @__PURE__ */ new Map();
12191
+ cancellationFlags = /* @__PURE__ */ new Map();
12192
+ nowMs;
12193
+ constructor(options = {}) {
12194
+ this.nowMs = options.nowMsFn ?? defaultNowMs2;
12195
+ }
12196
+ registerChildDelegation(parentCorrelationId, childCorrelationId) {
12197
+ const parent = normalizeCorrelationId(parentCorrelationId);
12198
+ const child = normalizeCorrelationId(childCorrelationId);
12199
+ if (!this.childDelegations.has(parent)) {
12200
+ this.childDelegations.set(parent, /* @__PURE__ */ new Set());
12201
+ }
12202
+ this.childDelegations.get(parent).add(child);
12203
+ }
12204
+ handleCancelDelegation(cancel) {
12205
+ const correlationId = normalizeCorrelationId(cancel.correlationId);
12206
+ const gracePeriodMs = normalizeGracePeriodMs(cancel.gracePeriodMs);
12207
+ const reason = normalizeReason(cancel.reason);
12208
+ const cancelTimeMs = this.nowMs();
12209
+ const metadata = normalizeMetadata(cancel.metadata, {
12210
+ reason,
12211
+ gracePeriodMs
12212
+ });
12213
+ const flag = {
12214
+ cancelled: true,
12215
+ gracePeriodMs,
12216
+ cancelTimeMs,
12217
+ metadata
12218
+ };
12219
+ this.cancellationFlags.set(correlationId, cloneFlag(flag));
12220
+ for (const childCorrelationId of this.childDelegations.get(correlationId) ?? []) {
12221
+ this.cancellationFlags.set(childCorrelationId, cloneFlag(flag));
12222
+ }
12223
+ return {
12224
+ acknowledged: true,
12225
+ correlationId,
12226
+ gracePeriodMs,
12227
+ message: "Cancellation recorded",
12228
+ metadata: cloneMetadata(metadata)
12229
+ };
12230
+ }
12231
+ isCancelled(correlationId) {
12232
+ const normalized = correlationId.trim();
12233
+ if (!normalized) {
12234
+ return false;
12235
+ }
12236
+ const entry = this.cancellationFlags.get(normalized);
12237
+ return Boolean(entry?.cancelled);
12238
+ }
12239
+ isGraceExpired(correlationId, nowMs) {
12240
+ const normalized = correlationId.trim();
12241
+ if (!normalized) {
12242
+ return false;
12243
+ }
12244
+ const entry = this.cancellationFlags.get(normalized);
12245
+ if (entry === void 0 || !entry.cancelled) {
12246
+ return false;
12247
+ }
12248
+ const currentMs = nowMs ?? this.nowMs();
12249
+ return currentMs - entry.cancelTimeMs >= entry.gracePeriodMs;
12250
+ }
12251
+ forcedPreemptionErrorCode(correlationId, nowMs) {
12252
+ if (this.isGraceExpired(correlationId, nowMs)) {
12253
+ return 12 /* FORCED_PREEMPTION */;
12254
+ }
12255
+ return 0 /* ERROR_CODE_UNSPECIFIED */;
12256
+ }
12257
+ collectForcedPreemptions(correlationIds, nowMs) {
12258
+ const currentMs = nowMs ?? this.nowMs();
12259
+ const forced = /* @__PURE__ */ new Set();
12260
+ for (const correlationId of correlationIds) {
12261
+ if (this.isGraceExpired(correlationId, currentMs)) {
12262
+ forced.add(correlationId);
12263
+ }
12264
+ }
12265
+ return forced;
12266
+ }
12267
+ };
12268
+
12269
+ // src/runtime/gateway.ts
12270
+ var REGISTRATION_TYPE_STANDARD_AGENT = 1;
12271
+ var REGISTRATION_TYPE_SWARM_GATEWAY = 2;
12272
+ var AGENT_STATE_INITIALIZING = 1;
12273
+ var AGENT_STATE_RUNNING = 4;
12274
+ var AGENT_STATE_FAILED = 10;
12275
+ var AGENT_STATE_SHUTTING_DOWN = 11;
12276
+ var DEFAULT_PEER_LIVENESS_THRESHOLD_MS = 3e4;
12277
+ var NON_SERVING_AGENT_STATES = /* @__PURE__ */ new Set([
12278
+ AGENT_STATE_INITIALIZING,
12279
+ AGENT_STATE_FAILED,
12280
+ AGENT_STATE_SHUTTING_DOWN
12281
+ ]);
12282
+ var GatewayValidationError = class extends Error {
12283
+ constructor(message) {
12284
+ super(message);
12285
+ this.name = "GatewayValidationError";
12286
+ }
12287
+ };
12288
+ function defaultNowMs3() {
12289
+ return Date.now();
12290
+ }
12291
+ function sameCapabilities(peerCapabilities, localCapabilities) {
12292
+ const peerSet = new Set(peerCapabilities);
12293
+ if (peerSet.size !== localCapabilities.size) {
12294
+ return false;
12295
+ }
12296
+ for (const localCapability of localCapabilities) {
12297
+ if (!peerSet.has(localCapability)) {
12298
+ return false;
12299
+ }
12300
+ }
12301
+ return true;
12302
+ }
12303
+ var PeerSelector = class {
12304
+ localAgentId;
12305
+ localCapabilities;
12306
+ nowMs;
12307
+ peerHealthFn;
12308
+ livenessThresholdMs;
12309
+ peers = [];
12310
+ runtime = /* @__PURE__ */ new Map();
12311
+ rrCursor = 0;
12312
+ constructor(options) {
12313
+ const threshold = options.livenessThresholdMs ?? DEFAULT_PEER_LIVENESS_THRESHOLD_MS;
12314
+ if (threshold < 0) {
12315
+ throw new GatewayValidationError("livenessThresholdMs must be >= 0");
12316
+ }
12317
+ this.localAgentId = options.localAgentId;
12318
+ this.localCapabilities = new Set(options.localCapabilities ?? []);
12319
+ this.nowMs = options.nowMsFn ?? defaultNowMs3;
12320
+ this.peerHealthFn = options.peerHealthFn ?? (() => true);
12321
+ this.livenessThresholdMs = threshold;
12322
+ }
12323
+ setPeers(peers) {
12324
+ this.peers = [...peers];
12325
+ const activeIds = new Set(this.peers.map((peer) => peer.agentId));
12326
+ for (const agentId of [...this.runtime.keys()]) {
12327
+ if (!activeIds.has(agentId)) {
12328
+ this.runtime.delete(agentId);
12329
+ }
12330
+ }
12331
+ const nowMs = this.nowMs();
12332
+ for (const peer of this.peers) {
12333
+ if (!this.runtime.has(peer.agentId)) {
12334
+ this.runtime.set(peer.agentId, {
12335
+ state: AGENT_STATE_RUNNING,
12336
+ lastHeartbeatMs: nowMs,
12337
+ cooldownUntilMs: 0
12338
+ });
12339
+ }
12340
+ }
12341
+ }
12342
+ updatePeerRuntimeState(agentId, options = {}) {
12343
+ const runtime = this.ensureRuntime(agentId);
12344
+ if (options.state !== void 0) {
12345
+ runtime.state = options.state;
12346
+ }
12347
+ if (options.lastHeartbeatMs !== void 0) {
12348
+ runtime.lastHeartbeatMs = Math.max(Math.floor(options.lastHeartbeatMs), 0);
12349
+ }
12350
+ if (options.cooldownUntilMs !== void 0) {
12351
+ runtime.cooldownUntilMs = Math.max(Math.floor(options.cooldownUntilMs), 0);
12352
+ }
12353
+ this.runtime.set(agentId, runtime);
12354
+ }
12355
+ touchPeerHeartbeat(agentId, options = {}) {
12356
+ this.updatePeerRuntimeState(agentId, {
12357
+ state: options.state,
12358
+ lastHeartbeatMs: options.nowMs ?? this.nowMs()
12359
+ });
12360
+ }
12361
+ recordPeerOverloaded(agentId, options = {}) {
12362
+ const runtime = this.ensureRuntime(agentId);
12363
+ const nowMs = this.nowMs();
12364
+ const retryAfterMs = Math.max(Math.floor(options.retryAfterMs ?? 0), 0);
12365
+ const localCooldownMs = Math.max(Math.floor(options.localCooldownMs ?? 0), 0);
12366
+ const cooldownMs = Math.max(retryAfterMs, localCooldownMs);
12367
+ runtime.cooldownUntilMs = Math.max(runtime.cooldownUntilMs, nowMs + cooldownMs);
12368
+ this.runtime.set(agentId, runtime);
12369
+ }
12370
+ isEligible(peer) {
12371
+ if (peer.registrationType !== REGISTRATION_TYPE_SWARM_GATEWAY) {
12372
+ return false;
12373
+ }
12374
+ if (peer.agentId === this.localAgentId) {
12375
+ return false;
12376
+ }
12377
+ return sameCapabilities(peer.capabilities, this.localCapabilities);
12378
+ }
12379
+ selectPeer() {
12380
+ const healthy = this.peers.filter((peer) => this.isHealthy(peer));
12381
+ if (healthy.length === 0) {
12382
+ return "";
12383
+ }
12384
+ const idx = this.rrCursor % healthy.length;
12385
+ this.rrCursor += 1;
12386
+ return healthy[idx].agentId;
12387
+ }
12388
+ ensureRuntime(agentId) {
12389
+ const existing = this.runtime.get(agentId);
12390
+ if (existing !== void 0) {
12391
+ return existing;
12392
+ }
12393
+ return {
12394
+ state: AGENT_STATE_RUNNING,
12395
+ lastHeartbeatMs: this.nowMs(),
12396
+ cooldownUntilMs: 0
12397
+ };
12398
+ }
12399
+ isHealthy(peer) {
12400
+ if (!this.isEligible(peer)) {
12401
+ return false;
12402
+ }
12403
+ if (!this.peerHealthFn(peer)) {
12404
+ return false;
12405
+ }
12406
+ const runtime = this.runtime.get(peer.agentId);
12407
+ if (runtime === void 0) {
12408
+ return false;
12409
+ }
12410
+ const nowMs = this.nowMs();
12411
+ if (runtime.cooldownUntilMs > nowMs) {
12412
+ return false;
12413
+ }
12414
+ if (nowMs - runtime.lastHeartbeatMs > this.livenessThresholdMs) {
12415
+ return false;
12416
+ }
12417
+ if (NON_SERVING_AGENT_STATES.has(runtime.state)) {
12418
+ return false;
12419
+ }
12420
+ return true;
12421
+ }
12422
+ };
12423
+ var GatewayRedirectEmitter = class {
12424
+ retryAfterMs;
12425
+ peerSelector;
12426
+ constructor(options) {
12427
+ if ((options.retryAfterMs ?? 0) < 0) {
12428
+ throw new GatewayValidationError("retryAfterMs must be >= 0");
12429
+ }
12430
+ this.retryAfterMs = options.retryAfterMs ?? 1e3;
12431
+ this.peerSelector = new PeerSelector({
12432
+ localAgentId: options.agentId,
12433
+ localCapabilities: options.capabilities ?? [],
12434
+ nowMsFn: options.nowMsFn,
12435
+ peerHealthFn: options.peerHealthFn,
12436
+ livenessThresholdMs: options.peerLivenessThresholdMs
12437
+ });
12438
+ this.peerSelector.setPeers(options.peerDescriptors ?? []);
12439
+ }
12440
+ setPeerDescriptors(peers) {
12441
+ this.peerSelector.setPeers(peers);
12442
+ }
12443
+ updatePeerRuntimeState(agentId, options = {}) {
12444
+ this.peerSelector.updatePeerRuntimeState(agentId, options);
12445
+ }
12446
+ touchPeerHeartbeat(agentId, options = {}) {
12447
+ this.peerSelector.touchPeerHeartbeat(agentId, options);
12448
+ }
12449
+ recordPeerOverloaded(agentId, options = {}) {
12450
+ this.peerSelector.recordPeerOverloaded(agentId, options);
12451
+ }
12452
+ emitOverloadedResponse(request) {
12453
+ if (request.delegationPolicy?.allowSpilloverRouting) {
12454
+ const redirectToAgentId = this.peerSelector.selectPeer();
12455
+ if (redirectToAgentId) {
12456
+ return {
12457
+ requestId: request.requestId,
12458
+ accepted: false,
12459
+ rejectionReason: "Gateway at capacity; redirect to peer gateway",
12460
+ rejectionCode: 20 /* REDIRECT */,
12461
+ retryAfterMs: 0,
12462
+ redirectToAgentId
12463
+ };
12464
+ }
12465
+ }
12466
+ return {
12467
+ requestId: request.requestId,
12468
+ accepted: false,
12469
+ rejectionReason: "Gateway at capacity",
12470
+ rejectionCode: 16 /* OVERLOADED */,
12471
+ retryAfterMs: this.retryAfterMs
12472
+ };
12473
+ }
12474
+ };
12475
+
12476
+ // src/persistence/persistence.ts
12477
+ import fsp from "node:fs/promises";
12478
+ import path2 from "node:path";
12479
+ var JSONFilePersistence = class {
12480
+ constructor(baseDir) {
12481
+ this.baseDir = baseDir;
12482
+ this.activityFile = path2.join(baseDir, "activity.json");
12483
+ this.acksFile = path2.join(baseDir, "acks.json");
12484
+ }
12485
+ activityFile;
12486
+ acksFile;
12487
+ async safeWrite(file, data) {
12488
+ await fsp.mkdir(path2.dirname(file), { recursive: true });
12489
+ const tmp = `${file}.tmp-${Date.now()}`;
12490
+ await fsp.writeFile(tmp, data, "utf8");
12491
+ await fsp.rename(tmp, file);
12492
+ }
12493
+ async saveActivity(records) {
12494
+ const payload = JSON.stringify(records, null, 2);
12495
+ await this.safeWrite(this.activityFile, payload);
12496
+ }
12497
+ async loadActivity() {
12498
+ try {
12499
+ const buf = await fsp.readFile(this.activityFile, "utf8");
12500
+ return JSON.parse(buf);
12501
+ } catch (e) {
12502
+ if (e?.code === "ENOENT")
12503
+ return [];
12504
+ throw e;
11627
12505
  }
11628
12506
  }
11629
12507
  async saveAcks(states) {
@@ -12548,7 +13426,7 @@ var AgentState = /* @__PURE__ */ ((AgentState2) => {
12548
13426
  AgentState2[AgentState2["RECOVERING"] = 12] = "RECOVERING";
12549
13427
  return AgentState2;
12550
13428
  })(AgentState || {});
12551
- var StateTransitionError = class extends Error {
13429
+ var StateTransitionError2 = class extends Error {
12552
13430
  fromState;
12553
13431
  toState;
12554
13432
  constructor(fromState, toState) {
@@ -12561,8 +13439,8 @@ var StateTransitionError = class extends Error {
12561
13439
  }
12562
13440
  };
12563
13441
  var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
12564
- // INITIALIZING -> RUNNABLE
12565
- [1 /* INITIALIZING */, /* @__PURE__ */ new Set([2 /* RUNNABLE */])],
13442
+ // INITIALIZING -> RUNNABLE, FAILED (init timeout per spec s8.2)
13443
+ [1 /* INITIALIZING */, /* @__PURE__ */ new Set([2 /* RUNNABLE */, 10 /* FAILED */])],
12566
13444
  // RUNNABLE -> SCHEDULED
12567
13445
  [2 /* RUNNABLE */, /* @__PURE__ */ new Set([3 /* SCHEDULED */])],
12568
13446
  // SCHEDULED -> RUNNING
@@ -12586,8 +13464,8 @@ var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
12586
13464
  6 /* WAITING_RESOURCES */,
12587
13465
  /* @__PURE__ */ new Set([4 /* RUNNING */, 10 /* FAILED */])
12588
13466
  ],
12589
- // SUSPENDED -> RESUMED
12590
- [7 /* SUSPENDED */, /* @__PURE__ */ new Set([8 /* RESUMED */])],
13467
+ // SUSPENDED -> RESUMED, FAILED (suspension timeout per spec s8.3)
13468
+ [7 /* SUSPENDED */, /* @__PURE__ */ new Set([8 /* RESUMED */, 10 /* FAILED */])],
12591
13469
  // RESUMED -> RUNNING
12592
13470
  [8 /* RESUMED */, /* @__PURE__ */ new Set([4 /* RUNNING */])],
12593
13471
  // COMPLETED -> RUNNABLE
@@ -12596,10 +13474,10 @@ var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
12596
13474
  [10 /* FAILED */, /* @__PURE__ */ new Set([12 /* RECOVERING */])],
12597
13475
  // SHUTTING_DOWN -> FAILED (agent_shutdown_timeout)
12598
13476
  [11 /* SHUTTING_DOWN */, /* @__PURE__ */ new Set([10 /* FAILED */])],
12599
- // RECOVERING -> RUNNABLE, SHUTTING_DOWN (recovery abort)
13477
+ // RECOVERING -> RUNNABLE, SHUTTING_DOWN (recovery abort), FAILED (recovery timeout per spec s8.3)
12600
13478
  [
12601
13479
  12 /* RECOVERING */,
12602
- /* @__PURE__ */ new Set([2 /* RUNNABLE */, 11 /* SHUTTING_DOWN */])
13480
+ /* @__PURE__ */ new Set([2 /* RUNNABLE */, 11 /* SHUTTING_DOWN */, 10 /* FAILED */])
12603
13481
  ]
12604
13482
  ]);
12605
13483
  function isValidTransition(fromState, toState) {
@@ -12651,7 +13529,7 @@ var AgentStateMachine = class {
12651
13529
  */
12652
13530
  async initialize() {
12653
13531
  if (this.state !== 0 /* AGENT_STATE_UNSPECIFIED */) {
12654
- throw new StateTransitionError(this.state, 1 /* INITIALIZING */);
13532
+ throw new StateTransitionError2(this.state, 1 /* INITIALIZING */);
12655
13533
  }
12656
13534
  await this.transitionTo(1 /* INITIALIZING */);
12657
13535
  }
@@ -12668,7 +13546,7 @@ var AgentStateMachine = class {
12668
13546
  return;
12669
13547
  }
12670
13548
  if (!isValidTransition(this.state, toState)) {
12671
- throw new StateTransitionError(this.state, toState);
13549
+ throw new StateTransitionError2(this.state, toState);
12672
13550
  }
12673
13551
  await this.doTransition(toState, context);
12674
13552
  }
@@ -12832,7 +13710,8 @@ function computeIdempotencyToken(input) {
12832
13710
  h.update(input.operation);
12833
13711
  h.update("\n");
12834
13712
  h.update(Buffer.from(input.canonical_bytes));
12835
- return `v1:${h.digest("hex")}`;
13713
+ const hash16 = h.digest("hex").slice(0, 16);
13714
+ return `${input.producer_id}:${input.operation}:${hash16}`;
12836
13715
  }
12837
13716
 
12838
13717
  // src/runtime/persistenceAdapter.ts
@@ -12949,89 +13828,752 @@ function normalizeReportPaths(report) {
12949
13828
  return report;
12950
13829
  }
12951
13830
 
12952
- // src/secrets/types.ts
12953
- var SecretSource = /* @__PURE__ */ ((SecretSource2) => {
12954
- SecretSource2["CLI"] = "cli";
12955
- SecretSource2["ENV"] = "env";
12956
- SecretSource2["SCOPED"] = "scoped";
12957
- SecretSource2["GLOBAL"] = "global";
12958
- return SecretSource2;
12959
- })(SecretSource || {});
12960
- var Scope = class {
12961
- constructor(name = null) {
12962
- this.name = name;
12963
- }
12964
- get isGlobal() {
12965
- return this.name === null;
13831
+ // src/constants/index.ts
13832
+ var CommunicationClass = /* @__PURE__ */ ((CommunicationClass2) => {
13833
+ CommunicationClass2[CommunicationClass2["COMM_CLASS_UNSPECIFIED"] = 0] = "COMM_CLASS_UNSPECIFIED";
13834
+ CommunicationClass2[CommunicationClass2["PRIVILEGED"] = 1] = "PRIVILEGED";
13835
+ CommunicationClass2[CommunicationClass2["STANDARD"] = 2] = "STANDARD";
13836
+ CommunicationClass2[CommunicationClass2["BULK"] = 3] = "BULK";
13837
+ return CommunicationClass2;
13838
+ })(CommunicationClass || {});
13839
+ var DebateIntensity = /* @__PURE__ */ ((DebateIntensity2) => {
13840
+ DebateIntensity2[DebateIntensity2["DEBATE_INTENSITY_UNSPECIFIED"] = 0] = "DEBATE_INTENSITY_UNSPECIFIED";
13841
+ DebateIntensity2[DebateIntensity2["LOWEST"] = 1] = "LOWEST";
13842
+ DebateIntensity2[DebateIntensity2["LOW"] = 2] = "LOW";
13843
+ DebateIntensity2[DebateIntensity2["MEDIUM"] = 3] = "MEDIUM";
13844
+ DebateIntensity2[DebateIntensity2["HIGH"] = 4] = "HIGH";
13845
+ DebateIntensity2[DebateIntensity2["HIGHEST"] = 5] = "HIGHEST";
13846
+ return DebateIntensity2;
13847
+ })(DebateIntensity || {});
13848
+ var HitlReasonType = /* @__PURE__ */ ((HitlReasonType2) => {
13849
+ HitlReasonType2[HitlReasonType2["HITL_REASON_UNSPECIFIED"] = 0] = "HITL_REASON_UNSPECIFIED";
13850
+ HitlReasonType2[HitlReasonType2["CONFLICT"] = 1] = "CONFLICT";
13851
+ HitlReasonType2[HitlReasonType2["SECURITY_APPROVAL"] = 2] = "SECURITY_APPROVAL";
13852
+ HitlReasonType2[HitlReasonType2["TASK_ESCALATION"] = 3] = "TASK_ESCALATION";
13853
+ HitlReasonType2[HitlReasonType2["MANUAL_OVERRIDE"] = 4] = "MANUAL_OVERRIDE";
13854
+ HitlReasonType2[HitlReasonType2["WORKTREE_OVERRIDE"] = 5] = "WORKTREE_OVERRIDE";
13855
+ HitlReasonType2[HitlReasonType2["DEBATE_DEADLOCK"] = 6] = "DEBATE_DEADLOCK";
13856
+ HitlReasonType2[HitlReasonType2["TOOL_PRIVILEGE_ESCALATION"] = 7] = "TOOL_PRIVILEGE_ESCALATION";
13857
+ HitlReasonType2[HitlReasonType2["CONNECTOR_APPROVAL"] = 8] = "CONNECTOR_APPROVAL";
13858
+ return HitlReasonType2;
13859
+ })(HitlReasonType || {});
13860
+ var AckStage2 = /* @__PURE__ */ ((AckStage3) => {
13861
+ AckStage3[AckStage3["ACK_STAGE_UNSPECIFIED"] = 0] = "ACK_STAGE_UNSPECIFIED";
13862
+ AckStage3[AckStage3["RECEIVED"] = 1] = "RECEIVED";
13863
+ AckStage3[AckStage3["READ"] = 2] = "READ";
13864
+ AckStage3[AckStage3["FULFILLED"] = 3] = "FULFILLED";
13865
+ AckStage3[AckStage3["REJECTED"] = 4] = "REJECTED";
13866
+ AckStage3[AckStage3["FAILED"] = 5] = "FAILED";
13867
+ AckStage3[AckStage3["TIMED_OUT"] = 6] = "TIMED_OUT";
13868
+ return AckStage3;
13869
+ })(AckStage2 || {});
13870
+ var EnvelopeState = /* @__PURE__ */ ((EnvelopeState3) => {
13871
+ EnvelopeState3[EnvelopeState3["ENVELOPE_STATE_UNSPECIFIED"] = 0] = "ENVELOPE_STATE_UNSPECIFIED";
13872
+ EnvelopeState3[EnvelopeState3["SENT"] = 1] = "SENT";
13873
+ EnvelopeState3[EnvelopeState3["RECEIVED"] = 2] = "RECEIVED";
13874
+ EnvelopeState3[EnvelopeState3["READ"] = 3] = "READ";
13875
+ EnvelopeState3[EnvelopeState3["FULFILLED"] = 4] = "FULFILLED";
13876
+ EnvelopeState3[EnvelopeState3["REJECTED"] = 5] = "REJECTED";
13877
+ EnvelopeState3[EnvelopeState3["FAILED"] = 6] = "FAILED";
13878
+ EnvelopeState3[EnvelopeState3["TIMED_OUT"] = 7] = "TIMED_OUT";
13879
+ return EnvelopeState3;
13880
+ })(EnvelopeState || {});
13881
+ var WorktreeStateEnum = /* @__PURE__ */ ((WorktreeStateEnum2) => {
13882
+ WorktreeStateEnum2[WorktreeStateEnum2["WORKTREE_STATE_UNSPECIFIED"] = 0] = "WORKTREE_STATE_UNSPECIFIED";
13883
+ WorktreeStateEnum2[WorktreeStateEnum2["UNBOUND"] = 1] = "UNBOUND";
13884
+ WorktreeStateEnum2[WorktreeStateEnum2["BOUND_HOME"] = 2] = "BOUND_HOME";
13885
+ WorktreeStateEnum2[WorktreeStateEnum2["SWITCH_PENDING"] = 3] = "SWITCH_PENDING";
13886
+ WorktreeStateEnum2[WorktreeStateEnum2["BOUND_NON_HOME"] = 4] = "BOUND_NON_HOME";
13887
+ WorktreeStateEnum2[WorktreeStateEnum2["BIND_FAILED"] = 5] = "BIND_FAILED";
13888
+ return WorktreeStateEnum2;
13889
+ })(WorktreeStateEnum || {});
13890
+ var DEFAULT_ACK_TIMEOUT_MS = 1e4;
13891
+ var DEDUP_WINDOW_S = 3600;
13892
+ function isTerminalEnvelopeState(state) {
13893
+ return state === 4 /* FULFILLED */ || state === 5 /* REJECTED */ || state === 6 /* FAILED */ || state === 7 /* TIMED_OUT */;
13894
+ }
13895
+ function updateEnvelopeState(envelope, newState) {
13896
+ envelope.state = newState;
13897
+ return envelope;
13898
+ }
13899
+
13900
+ // src/audit.ts
13901
+ import crypto4 from "node:crypto";
13902
+ function uuidv43() {
13903
+ if (typeof crypto4.randomUUID === "function") {
13904
+ return crypto4.randomUUID();
12966
13905
  }
12967
- label() {
12968
- return this.name ?? "global";
13906
+ const buf = crypto4.randomBytes(16);
13907
+ buf[6] = buf[6] & 15 | 64;
13908
+ buf[8] = buf[8] & 63 | 128;
13909
+ const hex = [...buf].map((b) => b.toString(16).padStart(2, "0"));
13910
+ return hex.slice(0, 4).join("") + "-" + hex.slice(4, 6).join("") + "-" + hex.slice(6, 8).join("") + "-" + hex.slice(8, 10).join("") + "-" + hex.slice(10, 16).join("");
13911
+ }
13912
+ function computeEnvelopeHash(envelope) {
13913
+ const envelopeCopy = { ...envelope };
13914
+ const payload = envelopeCopy.payload;
13915
+ const audit_proof = envelopeCopy.audit_proof;
13916
+ delete envelopeCopy.payload;
13917
+ delete envelopeCopy.audit_proof;
13918
+ const envelopeJson = JSON.stringify(envelopeCopy, Object.keys(envelopeCopy).sort());
13919
+ const hasher = crypto4.createHash("sha256");
13920
+ hasher.update(envelopeJson, "utf-8");
13921
+ if (payload) {
13922
+ if (payload instanceof Uint8Array) {
13923
+ hasher.update(payload);
13924
+ } else if (typeof payload === "string") {
13925
+ hasher.update(payload, "utf-8");
13926
+ }
13927
+ }
13928
+ if (audit_proof) {
13929
+ if (audit_proof instanceof Uint8Array) {
13930
+ hasher.update(audit_proof);
13931
+ } else if (typeof audit_proof === "string") {
13932
+ hasher.update(audit_proof, "utf-8");
13933
+ }
13934
+ }
13935
+ return hasher.digest("hex");
13936
+ }
13937
+ function createSimpleProof(envelope, actor_id) {
13938
+ const envelopeHash = computeEnvelopeHash(envelope);
13939
+ const timestamp = nowHlcStub();
13940
+ const proofInput = `${envelopeHash}:${actor_id}:${timestamp}`;
13941
+ const proofHash = crypto4.createHash("sha256").update(proofInput, "utf-8").digest();
13942
+ return {
13943
+ proof_id: uuidv43(),
13944
+ proof_type: "simple_hash",
13945
+ proof_data: new Uint8Array(proofHash),
13946
+ created_at: timestamp,
13947
+ verified: false
13948
+ };
13949
+ }
13950
+ function verifyAuditProof(envelope, proof) {
13951
+ if (proof.proof_type === "noop") {
13952
+ return true;
12969
13953
  }
12970
- };
12971
- var SecretKey = class {
12972
- constructor(key) {
12973
- this.key = key;
12974
- if (!key || key.split(".").some((p) => p.trim() === "")) {
12975
- throw new Error("secret key must be dotted identifiers without empty segments");
13954
+ if (proof.proof_type === "simple_hash") {
13955
+ if (proof.proof_data.length === 0) {
13956
+ return false;
12976
13957
  }
12977
- }
12978
- };
12979
- var SecretValue = class _SecretValue {
12980
- constructor(value) {
12981
- this.value = value;
12982
- if (value.length > _SecretValue.MAX_LEN) {
12983
- throw new Error("secret value exceeds maximum allowed length (8KB)");
13958
+ const envelopeHash = computeEnvelopeHash(envelope);
13959
+ if (proof.proof_data.length !== 32) {
13960
+ return false;
12984
13961
  }
13962
+ return true;
12985
13963
  }
12986
- static MAX_LEN = 8 * 1024;
12987
- };
12988
-
12989
- // src/secrets/errors.ts
12990
- var SecretError = class extends Error {
12991
- };
12992
- var SecretNotFound = class extends SecretError {
12993
- constructor(scope, key) {
12994
- super(`secret not found: scope=${scope} key=${key}`);
12995
- this.scope = scope;
12996
- this.key = key;
12997
- }
12998
- };
12999
- var SecretBackendError = class extends SecretError {
13000
- };
13001
- var SecretPermissionError = class extends SecretError {
13002
- };
13003
- var SecretValidationError = class extends SecretError {
13004
- };
13005
-
13006
- // src/secrets/backend.ts
13007
- var Secrets = class {
13008
- constructor(backend) {
13009
- this.backend = backend;
13964
+ return false;
13965
+ }
13966
+ var NoOpAuditor = class {
13967
+ /**
13968
+ * Create a minimal no-op proof.
13969
+ *
13970
+ * @param envelope - The envelope (ignored)
13971
+ * @param action - The action (ignored)
13972
+ * @returns A minimal no-op proof
13973
+ */
13974
+ createProof(envelope, action) {
13975
+ return {
13976
+ proof_id: uuidv43(),
13977
+ proof_type: "noop",
13978
+ proof_data: new Uint8Array(0),
13979
+ created_at: nowHlcStub(),
13980
+ verified: true
13981
+ };
13010
13982
  }
13011
- set(scope, key, value) {
13012
- return this.backend.set(scope, key, value);
13983
+ /**
13984
+ * Always returns true for no-op proofs.
13985
+ *
13986
+ * @param proof - The proof (ignored)
13987
+ * @returns Always true
13988
+ */
13989
+ verifyProof(proof) {
13990
+ return true;
13013
13991
  }
13014
- get(scope, key) {
13015
- return this.backend.get(scope, key);
13992
+ /**
13993
+ * Create a minimal audit record without storing it.
13994
+ *
13995
+ * @param envelope - The envelope being audited
13996
+ * @param action - The action being performed
13997
+ * @param proof - Optional proof to attach
13998
+ * @returns A minimal audit record
13999
+ */
14000
+ record(envelope, action, proof) {
14001
+ return {
14002
+ record_id: uuidv43(),
14003
+ envelope_id: envelope.message_id ?? "unknown",
14004
+ action,
14005
+ actor_id: envelope.producer_id ?? "unknown",
14006
+ timestamp: nowHlcStub(),
14007
+ proof
14008
+ };
13016
14009
  }
13017
- list(scope) {
13018
- return this.backend.list(scope);
14010
+ /**
14011
+ * Always returns empty array.
14012
+ *
14013
+ * @param envelope_id - The envelope ID (ignored)
14014
+ * @returns Empty array
14015
+ */
14016
+ query(envelope_id) {
14017
+ return [];
13019
14018
  }
13020
14019
  };
13021
-
13022
- // src/secrets/resolver.ts
13023
- var Resolver = class {
13024
- constructor(backend, env = process.env) {
13025
- this.backend = backend;
13026
- this.env = env;
14020
+ var InMemoryAuditor = class {
14021
+ _records;
14022
+ /**
14023
+ * Initialize with empty record storage.
14024
+ */
14025
+ constructor() {
14026
+ this._records = /* @__PURE__ */ new Map();
13027
14027
  }
13028
- async resolve(key, scope, opts) {
13029
- const explicit = opts?.explicit ?? null;
13030
- const envVar = opts?.envVar ?? null;
13031
- if (explicit !== null)
13032
- return [explicit, "cli" /* CLI */];
13033
- if (envVar && this.env[envVar] && this.env[envVar] !== "")
13034
- return [this.env[envVar], "env" /* ENV */];
14028
+ /**
14029
+ * Create a simple hash-based proof.
14030
+ *
14031
+ * @param envelope - The envelope to create proof for
14032
+ * @param action - The action being performed
14033
+ * @returns A simple hash-based proof
14034
+ */
14035
+ createProof(envelope, action) {
14036
+ return createSimpleProof(envelope, envelope.producer_id ?? "unknown");
14037
+ }
14038
+ /**
14039
+ * Verify a proof using the verification module.
14040
+ *
14041
+ * @param proof - The proof to verify
14042
+ * @returns True if proof is valid, false otherwise
14043
+ */
14044
+ verifyProof(proof) {
14045
+ if (proof.proof_type === "noop") {
14046
+ return true;
14047
+ }
14048
+ if (proof.proof_type === "simple_hash") {
14049
+ return proof.proof_data.length > 0;
14050
+ }
14051
+ return false;
14052
+ }
14053
+ /**
14054
+ * Create and store an audit record.
14055
+ *
14056
+ * @param envelope - The envelope being audited
14057
+ * @param action - The action being performed
14058
+ * @param proof - Optional proof to attach
14059
+ * @returns The created audit record
14060
+ */
14061
+ record(envelope, action, proof) {
14062
+ const record = {
14063
+ record_id: uuidv43(),
14064
+ envelope_id: envelope.message_id ?? "unknown",
14065
+ action,
14066
+ actor_id: envelope.producer_id ?? "unknown",
14067
+ timestamp: nowHlcStub(),
14068
+ proof
14069
+ };
14070
+ const envelope_id = record.envelope_id;
14071
+ if (!this._records.has(envelope_id)) {
14072
+ this._records.set(envelope_id, []);
14073
+ }
14074
+ this._records.get(envelope_id).push(record);
14075
+ return record;
14076
+ }
14077
+ /**
14078
+ * Query all audit records for a specific envelope.
14079
+ *
14080
+ * @param envelope_id - The message_id of the envelope to query
14081
+ * @returns List of audit records for this envelope
14082
+ */
14083
+ query(envelope_id) {
14084
+ return this._records.get(envelope_id) ?? [];
14085
+ }
14086
+ /**
14087
+ * Get all audit records (useful for testing).
14088
+ *
14089
+ * @returns All audit records across all envelopes
14090
+ */
14091
+ getAllRecords() {
14092
+ const allRecords = [];
14093
+ for (const records of this._records.values()) {
14094
+ allRecords.push(...records);
14095
+ }
14096
+ return allRecords;
14097
+ }
14098
+ /**
14099
+ * Clear all stored records (useful for testing).
14100
+ */
14101
+ clear() {
14102
+ this._records.clear();
14103
+ }
14104
+ };
14105
+
14106
+ // src/agentConfig.ts
14107
+ import * as fs2 from "fs";
14108
+ import * as path4 from "path";
14109
+ function defaultEndpoints() {
14110
+ return {
14111
+ router: process.env.SW4RM_ROUTER_ADDR || "http://localhost:50051",
14112
+ registry: process.env.SW4RM_REGISTRY_ADDR || "http://localhost:50052",
14113
+ scheduler: process.env.SW4RM_SCHEDULER_ADDR || "http://localhost:50053",
14114
+ hitl: process.env.SW4RM_HITL_ADDR || "http://localhost:50054",
14115
+ worktree: process.env.SW4RM_WORKTREE_ADDR || "http://localhost:50055",
14116
+ tool: process.env.SW4RM_TOOL_ADDR || "http://localhost:50056",
14117
+ connector: process.env.SW4RM_CONNECTOR_ADDR || "http://localhost:50057",
14118
+ negotiation: process.env.SW4RM_NEGOTIATION_ADDR || "http://localhost:50058",
14119
+ reasoning: process.env.SW4RM_REASONING_ADDR || "http://localhost:50059",
14120
+ logging: process.env.SW4RM_LOGGING_ADDR || "http://localhost:50060"
14121
+ };
14122
+ }
14123
+ function defaultRetryPolicy() {
14124
+ return {
14125
+ maxAttempts: 3,
14126
+ initialBackoffMs: 200,
14127
+ maxBackoffMs: 2e3,
14128
+ multiplier: 2
14129
+ };
14130
+ }
14131
+ function defaultAgentConfig(agentId = "agent-1", name = "Agent") {
14132
+ return {
14133
+ agentId,
14134
+ name,
14135
+ description: void 0,
14136
+ version: "0.1.0",
14137
+ capabilities: [],
14138
+ endpoints: defaultEndpoints(),
14139
+ timeoutMs: 3e4,
14140
+ streamKeepaliveMs: 6e4,
14141
+ retry: defaultRetryPolicy(),
14142
+ metadata: {},
14143
+ communicationClass: 2,
14144
+ // STANDARD
14145
+ modalitiesSupported: ["application/json"],
14146
+ reasoningConnectors: [],
14147
+ publicKey: void 0
14148
+ };
14149
+ }
14150
+ function loadConfigFromEnv() {
14151
+ const config = defaultAgentConfig();
14152
+ if (process.env.AGENT_ID) {
14153
+ config.agentId = process.env.AGENT_ID;
14154
+ }
14155
+ if (process.env.AGENT_NAME) {
14156
+ config.name = process.env.AGENT_NAME;
14157
+ }
14158
+ if (process.env.AGENT_DESCRIPTION) {
14159
+ config.description = process.env.AGENT_DESCRIPTION;
14160
+ }
14161
+ if (process.env.AGENT_VERSION) {
14162
+ config.version = process.env.AGENT_VERSION;
14163
+ }
14164
+ if (process.env.AGENT_CAPABILITIES) {
14165
+ config.capabilities = process.env.AGENT_CAPABILITIES.split(",").map((s) => s.trim());
14166
+ }
14167
+ if (process.env.SW4RM_TIMEOUT_MS) {
14168
+ const timeout = parseInt(process.env.SW4RM_TIMEOUT_MS, 10);
14169
+ if (!isNaN(timeout)) {
14170
+ config.timeoutMs = timeout;
14171
+ }
14172
+ }
14173
+ if (process.env.SW4RM_STREAM_KEEPALIVE_MS) {
14174
+ const keepalive = parseInt(process.env.SW4RM_STREAM_KEEPALIVE_MS, 10);
14175
+ if (!isNaN(keepalive)) {
14176
+ config.streamKeepaliveMs = keepalive;
14177
+ }
14178
+ }
14179
+ if (process.env.SW4RM_RETRY_MAX_ATTEMPTS) {
14180
+ const attempts = parseInt(process.env.SW4RM_RETRY_MAX_ATTEMPTS, 10);
14181
+ if (!isNaN(attempts)) {
14182
+ config.retry.maxAttempts = attempts;
14183
+ }
14184
+ }
14185
+ if (process.env.SW4RM_COMMUNICATION_CLASS) {
14186
+ const cls = parseInt(process.env.SW4RM_COMMUNICATION_CLASS, 10);
14187
+ if (!isNaN(cls)) {
14188
+ config.communicationClass = cls;
14189
+ }
14190
+ }
14191
+ config.endpoints = defaultEndpoints();
14192
+ return config;
14193
+ }
14194
+ function defaultSW4RMConfig() {
14195
+ return {
14196
+ routerAddr: process.env.SW4RM_ROUTER_ADDR || "http://localhost:50051",
14197
+ registryAddr: process.env.SW4RM_REGISTRY_ADDR || "http://localhost:50052",
14198
+ defaultTimeoutMs: parseInt(process.env.SW4RM_DEFAULT_TIMEOUT_MS || "30000", 10),
14199
+ maxRetries: parseInt(process.env.SW4RM_MAX_RETRIES || "3", 10),
14200
+ enableMetrics: parseBool(process.env.SW4RM_ENABLE_METRICS, true),
14201
+ enableTracing: parseBool(process.env.SW4RM_ENABLE_TRACING, true),
14202
+ logLevel: process.env.SW4RM_LOG_LEVEL || "INFO",
14203
+ featureFlags: {}
14204
+ };
14205
+ }
14206
+ function parseBool(value, defaultValue) {
14207
+ if (value === void 0) {
14208
+ return defaultValue;
14209
+ }
14210
+ return ["true", "1", "yes", "on"].includes(value.toLowerCase());
14211
+ }
14212
+ function loadConfig(configPath) {
14213
+ let config = defaultSW4RMConfig();
14214
+ if (configPath) {
14215
+ if (!fs2.existsSync(configPath)) {
14216
+ throw new Error(`Configuration file not found: ${configPath}`);
14217
+ }
14218
+ const ext = path4.extname(configPath).toLowerCase();
14219
+ if (ext !== ".json") {
14220
+ throw new Error(
14221
+ `Unsupported configuration file format: ${ext}. Supported formats: .json`
14222
+ );
14223
+ }
14224
+ const fileContent = fs2.readFileSync(configPath, "utf8");
14225
+ const fileConfig = JSON.parse(fileContent);
14226
+ config = { ...config, ...fileConfig };
14227
+ }
14228
+ const envConfig = loadFromEnv();
14229
+ config = { ...config, ...envConfig };
14230
+ return config;
14231
+ }
14232
+ function loadFromEnv() {
14233
+ const envConfig = {};
14234
+ if (process.env.SW4RM_ROUTER_ADDR) {
14235
+ envConfig.routerAddr = process.env.SW4RM_ROUTER_ADDR;
14236
+ }
14237
+ if (process.env.SW4RM_REGISTRY_ADDR) {
14238
+ envConfig.registryAddr = process.env.SW4RM_REGISTRY_ADDR;
14239
+ }
14240
+ if (process.env.SW4RM_DEFAULT_TIMEOUT_MS) {
14241
+ const timeout = parseInt(process.env.SW4RM_DEFAULT_TIMEOUT_MS, 10);
14242
+ if (!isNaN(timeout)) {
14243
+ envConfig.defaultTimeoutMs = timeout;
14244
+ }
14245
+ }
14246
+ if (process.env.SW4RM_MAX_RETRIES) {
14247
+ const retries = parseInt(process.env.SW4RM_MAX_RETRIES, 10);
14248
+ if (!isNaN(retries)) {
14249
+ envConfig.maxRetries = retries;
14250
+ }
14251
+ }
14252
+ if (process.env.SW4RM_ENABLE_METRICS !== void 0) {
14253
+ envConfig.enableMetrics = parseBool(process.env.SW4RM_ENABLE_METRICS, true);
14254
+ }
14255
+ if (process.env.SW4RM_ENABLE_TRACING !== void 0) {
14256
+ envConfig.enableTracing = parseBool(process.env.SW4RM_ENABLE_TRACING, true);
14257
+ }
14258
+ if (process.env.SW4RM_LOG_LEVEL) {
14259
+ envConfig.logLevel = process.env.SW4RM_LOG_LEVEL.toUpperCase();
14260
+ }
14261
+ return envConfig;
14262
+ }
14263
+ var _globalConfig = null;
14264
+ function getConfig() {
14265
+ if (_globalConfig === null) {
14266
+ _globalConfig = loadConfig();
14267
+ }
14268
+ return _globalConfig;
14269
+ }
14270
+ function setConfig(config) {
14271
+ _globalConfig = config;
14272
+ }
14273
+ function resetConfig() {
14274
+ _globalConfig = null;
14275
+ }
14276
+
14277
+ // src/persistentActivityBuffer.ts
14278
+ import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdirSync } from "node:fs";
14279
+ import { dirname } from "node:path";
14280
+ var JSONFilePersistence2 = class {
14281
+ constructor(filePath = "sw4rm_activity.json") {
14282
+ this.filePath = filePath;
14283
+ }
14284
+ load() {
14285
+ if (!existsSync2(this.filePath)) {
14286
+ return { records: {}, order: [] };
14287
+ }
14288
+ const raw = readFileSync2(this.filePath, "utf-8");
14289
+ const data = JSON.parse(raw);
14290
+ return {
14291
+ records: data.records ?? {},
14292
+ order: data.order ?? []
14293
+ };
14294
+ }
14295
+ save(records, order) {
14296
+ const dir = dirname(this.filePath);
14297
+ if (dir && !existsSync2(dir)) {
14298
+ mkdirSync(dir, { recursive: true });
14299
+ }
14300
+ writeFileSync(this.filePath, JSON.stringify({ records, order, version: "1.0" }, null, 2));
14301
+ }
14302
+ clear() {
14303
+ if (existsSync2(this.filePath)) {
14304
+ writeFileSync(this.filePath, JSON.stringify({ records: {}, order: [], version: "1.0" }));
14305
+ }
14306
+ }
14307
+ };
14308
+ var PersistentActivityBuffer = class {
14309
+ byId = /* @__PURE__ */ new Map();
14310
+ byIdempotencyToken = /* @__PURE__ */ new Map();
14311
+ // token -> message_id
14312
+ order = [];
14313
+ maxItems;
14314
+ persistence;
14315
+ dedupWindowS;
14316
+ dirty = false;
14317
+ constructor(opts) {
14318
+ this.maxItems = opts?.maxItems ?? 1e4;
14319
+ this.persistence = opts?.persistence ?? new JSONFilePersistence2();
14320
+ this.dedupWindowS = opts?.dedupWindowS ?? 3600;
14321
+ this.loadFromPersistence();
14322
+ }
14323
+ loadFromPersistence() {
14324
+ try {
14325
+ const { records, order } = this.persistence.load();
14326
+ this.byId = new Map(Object.entries(records));
14327
+ this.order = order;
14328
+ for (const [mid, rec] of this.byId) {
14329
+ const token = rec.envelope?.idempotency_token;
14330
+ if (token) {
14331
+ this.byIdempotencyToken.set(token, mid);
14332
+ }
14333
+ }
14334
+ } catch {
14335
+ this.byId = /* @__PURE__ */ new Map();
14336
+ this.byIdempotencyToken = /* @__PURE__ */ new Map();
14337
+ this.order = [];
14338
+ }
14339
+ }
14340
+ saveToPersistence() {
14341
+ if (!this.dirty)
14342
+ return;
14343
+ try {
14344
+ const records = {};
14345
+ for (const [k, v] of this.byId) {
14346
+ records[k] = v;
14347
+ }
14348
+ this.persistence.save(records, this.order);
14349
+ this.dirty = false;
14350
+ } catch {
14351
+ }
14352
+ }
14353
+ checkCapacity() {
14354
+ if (this.byId.size >= this.maxItems) {
14355
+ throw new BufferFullError(
14356
+ `Activity buffer is full (max ${this.maxItems} items). Reject per spec.`,
14357
+ 1 /* BUFFER_FULL */
14358
+ );
14359
+ }
14360
+ }
14361
+ cleanupExpiredDedupEntries() {
14362
+ const nowMs = Date.now();
14363
+ const windowMs = this.dedupWindowS * 1e3;
14364
+ const expired = [];
14365
+ for (const [token, mid] of this.byIdempotencyToken) {
14366
+ const rec = this.byId.get(mid);
14367
+ if (rec && nowMs - rec.ts_ms > windowMs) {
14368
+ expired.push(token);
14369
+ }
14370
+ }
14371
+ for (const token of expired) {
14372
+ this.byIdempotencyToken.delete(token);
14373
+ }
14374
+ }
14375
+ /**
14376
+ * Record an incoming envelope. Throws BufferFullError if buffer is at capacity.
14377
+ */
14378
+ recordIncoming(envelope) {
14379
+ this.checkCapacity();
14380
+ const mid = String(envelope.message_id ?? "");
14381
+ const rec = {
14382
+ message_id: mid,
14383
+ direction: "in",
14384
+ envelope,
14385
+ ts_ms: Date.now(),
14386
+ ack_stage: 0 /* ACK_STAGE_UNSPECIFIED */,
14387
+ error_code: 0 /* ERROR_CODE_UNSPECIFIED */,
14388
+ ack_note: ""
14389
+ };
14390
+ this.byId.set(mid, rec);
14391
+ this.order.push(mid);
14392
+ const token = envelope.idempotency_token;
14393
+ if (token) {
14394
+ this.byIdempotencyToken.set(token, mid);
14395
+ }
14396
+ this.cleanupExpiredDedupEntries();
14397
+ this.dirty = true;
14398
+ return rec;
14399
+ }
14400
+ /**
14401
+ * Record an outgoing envelope. Throws BufferFullError if buffer is at capacity.
14402
+ */
14403
+ recordOutgoing(envelope) {
14404
+ this.checkCapacity();
14405
+ const mid = String(envelope.message_id ?? "");
14406
+ const rec = {
14407
+ message_id: mid,
14408
+ direction: "out",
14409
+ envelope,
14410
+ ts_ms: Date.now(),
14411
+ ack_stage: 0 /* ACK_STAGE_UNSPECIFIED */,
14412
+ error_code: 0 /* ERROR_CODE_UNSPECIFIED */,
14413
+ ack_note: ""
14414
+ };
14415
+ this.byId.set(mid, rec);
14416
+ this.order.push(mid);
14417
+ const token = envelope.idempotency_token;
14418
+ if (token) {
14419
+ this.byIdempotencyToken.set(token, mid);
14420
+ }
14421
+ this.cleanupExpiredDedupEntries();
14422
+ this.dirty = true;
14423
+ return rec;
14424
+ }
14425
+ /**
14426
+ * Process an ACK for a previously recorded message.
14427
+ */
14428
+ ack(ackMsg) {
14429
+ const target = String(ackMsg.ack_for_message_id);
14430
+ const rec = this.byId.get(target);
14431
+ if (rec) {
14432
+ rec.ack_stage = ackMsg.ack_stage ?? 0 /* ACK_STAGE_UNSPECIFIED */;
14433
+ rec.error_code = ackMsg.error_code ?? 0 /* ERROR_CODE_UNSPECIFIED */;
14434
+ rec.ack_note = ackMsg.note ?? "";
14435
+ this.dirty = true;
14436
+ }
14437
+ return rec;
14438
+ }
14439
+ /** Get record by message ID. */
14440
+ get(messageId) {
14441
+ return this.byId.get(messageId);
14442
+ }
14443
+ /** Get record by idempotency token (for deduplication). */
14444
+ getByIdempotencyToken(token) {
14445
+ this.cleanupExpiredDedupEntries();
14446
+ const mid = this.byIdempotencyToken.get(token);
14447
+ if (mid)
14448
+ return this.byId.get(mid);
14449
+ return void 0;
14450
+ }
14451
+ /** Get all un-ACKed records. */
14452
+ unacked() {
14453
+ return [...this.byId.values()].filter(
14454
+ (r) => r.ack_stage === 0 /* ACK_STAGE_UNSPECIFIED */ || r.ack_stage === 1 /* RECEIVED */ || r.ack_stage === 2 /* READ */
14455
+ );
14456
+ }
14457
+ /** Get N most recent records. */
14458
+ recent(n = 50) {
14459
+ const ids = this.order.slice(-n);
14460
+ return ids.map((id) => this.byId.get(id)).filter(Boolean);
14461
+ }
14462
+ /** Update envelope state for a message. */
14463
+ updateState(messageId, newState) {
14464
+ const rec = this.byId.get(messageId);
14465
+ if (rec) {
14466
+ rec.envelope.state = newState;
14467
+ this.dirty = true;
14468
+ }
14469
+ return rec;
14470
+ }
14471
+ /** Return unacked outgoing messages for reconciliation. */
14472
+ reconcile() {
14473
+ return this.unacked().filter((r) => r.direction === "out");
14474
+ }
14475
+ /** Force save to persistence. */
14476
+ flush() {
14477
+ this.dirty = true;
14478
+ this.saveToPersistence();
14479
+ }
14480
+ /** Clear all records. */
14481
+ clear() {
14482
+ this.byId.clear();
14483
+ this.byIdempotencyToken.clear();
14484
+ this.order = [];
14485
+ this.persistence.clear();
14486
+ this.dirty = false;
14487
+ }
14488
+ /** Get the count of records. */
14489
+ get size() {
14490
+ return this.byId.size;
14491
+ }
14492
+ };
14493
+
14494
+ // src/secrets/types.ts
14495
+ var SecretSource = /* @__PURE__ */ ((SecretSource2) => {
14496
+ SecretSource2["CLI"] = "cli";
14497
+ SecretSource2["ENV"] = "env";
14498
+ SecretSource2["SCOPED"] = "scoped";
14499
+ SecretSource2["GLOBAL"] = "global";
14500
+ return SecretSource2;
14501
+ })(SecretSource || {});
14502
+ var Scope = class {
14503
+ constructor(name = null) {
14504
+ this.name = name;
14505
+ }
14506
+ get isGlobal() {
14507
+ return this.name === null;
14508
+ }
14509
+ label() {
14510
+ return this.name ?? "global";
14511
+ }
14512
+ };
14513
+ var SecretKey = class {
14514
+ constructor(key) {
14515
+ this.key = key;
14516
+ if (!key || key.split(".").some((p) => p.trim() === "")) {
14517
+ throw new Error("secret key must be dotted identifiers without empty segments");
14518
+ }
14519
+ }
14520
+ };
14521
+ var SecretValue = class _SecretValue {
14522
+ constructor(value) {
14523
+ this.value = value;
14524
+ if (value.length > _SecretValue.MAX_LEN) {
14525
+ throw new Error("secret value exceeds maximum allowed length (8KB)");
14526
+ }
14527
+ }
14528
+ static MAX_LEN = 8 * 1024;
14529
+ };
14530
+
14531
+ // src/secrets/errors.ts
14532
+ var SecretError = class extends Error {
14533
+ };
14534
+ var SecretNotFound = class extends SecretError {
14535
+ constructor(scope, key) {
14536
+ super(`secret not found: scope=${scope} key=${key}`);
14537
+ this.scope = scope;
14538
+ this.key = key;
14539
+ }
14540
+ };
14541
+ var SecretBackendError = class extends SecretError {
14542
+ };
14543
+ var SecretPermissionError = class extends SecretError {
14544
+ };
14545
+ var SecretValidationError = class extends SecretError {
14546
+ };
14547
+
14548
+ // src/secrets/backend.ts
14549
+ var Secrets = class {
14550
+ constructor(backend) {
14551
+ this.backend = backend;
14552
+ }
14553
+ set(scope, key, value) {
14554
+ return this.backend.set(scope, key, value);
14555
+ }
14556
+ get(scope, key) {
14557
+ return this.backend.get(scope, key);
14558
+ }
14559
+ list(scope) {
14560
+ return this.backend.list(scope);
14561
+ }
14562
+ };
14563
+
14564
+ // src/secrets/resolver.ts
14565
+ var Resolver = class {
14566
+ constructor(backend, env = process.env) {
14567
+ this.backend = backend;
14568
+ this.env = env;
14569
+ }
14570
+ async resolve(key, scope, opts) {
14571
+ const explicit = opts?.explicit ?? null;
14572
+ const envVar = opts?.envVar ?? null;
14573
+ if (explicit !== null)
14574
+ return [explicit, "cli" /* CLI */];
14575
+ if (envVar && this.env[envVar] && this.env[envVar] !== "")
14576
+ return [this.env[envVar], "env" /* ENV */];
13035
14577
  try {
13036
14578
  const v = await this.backend.get(scope, key);
13037
14579
  return [v, scope.isGlobal ? "global" /* GLOBAL */ : "scoped" /* SCOPED */];
@@ -13046,8 +14588,8 @@ var Resolver = class {
13046
14588
  };
13047
14589
 
13048
14590
  // src/secrets/backends/file.ts
13049
- import { mkdirSync, readFileSync, renameSync, writeFileSync, existsSync, chmodSync } from "node:fs";
13050
- import { join, dirname } from "node:path";
14591
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync, writeFileSync as writeFileSync2, existsSync as existsSync3, chmodSync } from "node:fs";
14592
+ import { join, dirname as dirname2 } from "node:path";
13051
14593
  function defaultPath() {
13052
14594
  const isWin = process.platform === "win32";
13053
14595
  if (isWin) {
@@ -13060,14 +14602,14 @@ function defaultPath() {
13060
14602
  }
13061
14603
  var FileBackend = class {
13062
14604
  path;
13063
- constructor(path4) {
13064
- this.path = path4 ?? defaultPath();
13065
- mkdirSync(dirname(this.path), { recursive: true });
14605
+ constructor(path7) {
14606
+ this.path = path7 ?? defaultPath();
14607
+ mkdirSync2(dirname2(this.path), { recursive: true });
13066
14608
  try {
13067
- chmodSync(dirname(this.path), 448);
14609
+ chmodSync(dirname2(this.path), 448);
13068
14610
  } catch {
13069
14611
  }
13070
- if (!existsSync(this.path)) {
14612
+ if (!existsSync3(this.path)) {
13071
14613
  this.safeWrite({});
13072
14614
  this.enforceFilePerms();
13073
14615
  } else {
@@ -13084,9 +14626,9 @@ var FileBackend = class {
13084
14626
  }
13085
14627
  }
13086
14628
  safeWrite(obj) {
13087
- const tmp = join(dirname(this.path), `.secrets.${Date.now()}.${Math.random().toString(16).slice(2)}`);
14629
+ const tmp = join(dirname2(this.path), `.secrets.${Date.now()}.${Math.random().toString(16).slice(2)}`);
13088
14630
  try {
13089
- writeFileSync(tmp, JSON.stringify(obj, null, 2), { encoding: "utf8", mode: 384 });
14631
+ writeFileSync2(tmp, JSON.stringify(obj, null, 2), { encoding: "utf8", mode: 384 });
13090
14632
  renameSync(tmp, this.path);
13091
14633
  this.enforceFilePerms();
13092
14634
  } catch (e) {
@@ -13095,7 +14637,7 @@ var FileBackend = class {
13095
14637
  }
13096
14638
  load() {
13097
14639
  try {
13098
- const s = readFileSync(this.path, { encoding: "utf8" });
14640
+ const s = readFileSync3(this.path, { encoding: "utf8" });
13099
14641
  return JSON.parse(s);
13100
14642
  } catch (e) {
13101
14643
  if (e.code === "ENOENT")
@@ -13191,57 +14733,939 @@ async function selectBackend(mode) {
13191
14733
  }
13192
14734
  }
13193
14735
 
14736
+ // src/llm/client.ts
14737
+ var LlmError = class extends Error {
14738
+ constructor(message) {
14739
+ super(message);
14740
+ this.name = "LlmError";
14741
+ Object.setPrototypeOf(this, new.target.prototype);
14742
+ }
14743
+ };
14744
+ var LlmAuthenticationError = class extends LlmError {
14745
+ constructor(message) {
14746
+ super(message);
14747
+ this.name = "LlmAuthenticationError";
14748
+ }
14749
+ };
14750
+ var LlmRateLimitError = class extends LlmError {
14751
+ constructor(message) {
14752
+ super(message);
14753
+ this.name = "LlmRateLimitError";
14754
+ }
14755
+ };
14756
+ var LlmTimeoutError = class extends LlmError {
14757
+ constructor(message) {
14758
+ super(message);
14759
+ this.name = "LlmTimeoutError";
14760
+ }
14761
+ };
14762
+ var LlmContextLengthError = class extends LlmError {
14763
+ constructor(message) {
14764
+ super(message);
14765
+ this.name = "LlmContextLengthError";
14766
+ }
14767
+ };
14768
+
14769
+ // src/llm/rateLimiter.ts
14770
+ function envBool(name, defaultVal) {
14771
+ const raw = (process.env[name] ?? defaultVal).toLowerCase();
14772
+ return !["0", "false", "no"].includes(raw);
14773
+ }
14774
+ function buildRateLimiterConfig(overrides) {
14775
+ return {
14776
+ tokensPerMinute: overrides?.tokensPerMinute ?? parseInt(process.env["LLM_RATE_LIMIT_TOKENS_PER_MIN"] ?? "250000", 10),
14777
+ burstAllowance: overrides?.burstAllowance ?? 1,
14778
+ minTokensPerRequest: overrides?.minTokensPerRequest ?? 100,
14779
+ maxWaitSeconds: overrides?.maxWaitSeconds ?? 120,
14780
+ enabled: overrides?.enabled ?? envBool("LLM_RATE_LIMIT_ENABLED", "1"),
14781
+ adaptiveEnabled: overrides?.adaptiveEnabled ?? envBool("LLM_RATE_LIMIT_ADAPTIVE", "1"),
14782
+ reductionFactor: overrides?.reductionFactor ?? parseFloat(process.env["LLM_RATE_LIMIT_REDUCTION_FACTOR"] ?? "0.7"),
14783
+ recoveryFactor: overrides?.recoveryFactor ?? parseFloat(process.env["LLM_RATE_LIMIT_RECOVERY_FACTOR"] ?? "1.1"),
14784
+ cooldownSeconds: overrides?.cooldownSeconds ?? parseFloat(process.env["LLM_RATE_LIMIT_COOLDOWN_SECONDS"] ?? "30"),
14785
+ successesForRecovery: overrides?.successesForRecovery ?? parseInt(
14786
+ process.env["LLM_RATE_LIMIT_RECOVERY_SUCCESS_THRESHOLD"] ?? "20",
14787
+ 10
14788
+ )
14789
+ };
14790
+ }
14791
+ var TokenBucket = class {
14792
+ config;
14793
+ baseTpm;
14794
+ currentTpm;
14795
+ minTpm;
14796
+ tokens;
14797
+ lastRefill;
14798
+ lastRateLimitTime = null;
14799
+ successesSinceLimit = 0;
14800
+ constructor(config) {
14801
+ this.config = buildRateLimiterConfig(config);
14802
+ this.baseTpm = this.config.tokensPerMinute;
14803
+ this.currentTpm = this.config.tokensPerMinute;
14804
+ this.minTpm = Math.max(1e3, this.baseTpm * 0.25);
14805
+ this.tokens = this.currentTpm;
14806
+ this.lastRefill = performance.now();
14807
+ }
14808
+ // -- Internal helpers ----------------------------------------------------
14809
+ refill() {
14810
+ const now = performance.now();
14811
+ const elapsedSeconds = (now - this.lastRefill) / 1e3;
14812
+ const refill = elapsedSeconds * (this.currentTpm / 60);
14813
+ this.tokens = Math.min(
14814
+ this.tokens + refill,
14815
+ this.currentTpm * this.config.burstAllowance
14816
+ );
14817
+ this.lastRefill = now;
14818
+ this.maybeRecover(now);
14819
+ }
14820
+ maybeRecover(now) {
14821
+ if (!this.config.adaptiveEnabled)
14822
+ return;
14823
+ if (this.currentTpm >= this.baseTpm)
14824
+ return;
14825
+ if (this.lastRateLimitTime === null)
14826
+ return;
14827
+ if ((now - this.lastRateLimitTime) / 1e3 < this.config.cooldownSeconds)
14828
+ return;
14829
+ if (this.successesSinceLimit < this.config.successesForRecovery)
14830
+ return;
14831
+ const newLimit = Math.min(
14832
+ this.baseTpm,
14833
+ this.currentTpm * this.config.recoveryFactor
14834
+ );
14835
+ if (newLimit > this.currentTpm) {
14836
+ this.currentTpm = newLimit;
14837
+ this.successesSinceLimit = 0;
14838
+ }
14839
+ }
14840
+ // -- Public API ----------------------------------------------------------
14841
+ /**
14842
+ * Acquire tokens, waiting if necessary.
14843
+ *
14844
+ * @param estimatedTokens - Estimated token count for the request.
14845
+ * @returns Time spent waiting in milliseconds (0 if immediate).
14846
+ * @throws Error if waiting exceeds {@link RateLimiterConfig.maxWaitSeconds}.
14847
+ */
14848
+ async acquire(estimatedTokens) {
14849
+ if (!this.config.enabled)
14850
+ return 0;
14851
+ estimatedTokens = Math.max(estimatedTokens, this.config.minTokensPerRequest);
14852
+ const waitStart = performance.now();
14853
+ for (; ; ) {
14854
+ this.refill();
14855
+ if (this.tokens >= estimatedTokens) {
14856
+ this.tokens -= estimatedTokens;
14857
+ return performance.now() - waitStart;
14858
+ }
14859
+ const elapsed = (performance.now() - waitStart) / 1e3;
14860
+ if (elapsed >= this.config.maxWaitSeconds) {
14861
+ throw new Error(
14862
+ `Rate limiter: waited ${elapsed.toFixed(1)}s for ${estimatedTokens} tokens`
14863
+ );
14864
+ }
14865
+ await new Promise((resolve) => setTimeout(resolve, 250));
14866
+ }
14867
+ }
14868
+ /**
14869
+ * Record a 429 event -- adaptively reduce budget.
14870
+ *
14871
+ * Call this when the upstream API returns HTTP 429 or an equivalent
14872
+ * rate-limit error.
14873
+ */
14874
+ recordRateLimit() {
14875
+ if (!(this.config.enabled && this.config.adaptiveEnabled))
14876
+ return;
14877
+ this.lastRateLimitTime = performance.now();
14878
+ this.successesSinceLimit = 0;
14879
+ const newLimit = Math.max(
14880
+ this.minTpm,
14881
+ this.currentTpm * this.config.reductionFactor
14882
+ );
14883
+ if (newLimit < this.currentTpm) {
14884
+ this.currentTpm = newLimit;
14885
+ this.tokens = Math.min(this.tokens, this.currentTpm);
14886
+ }
14887
+ }
14888
+ /**
14889
+ * Record a successful request for adaptive recovery.
14890
+ *
14891
+ * Call this after each successful API response.
14892
+ */
14893
+ recordSuccess() {
14894
+ if (!(this.config.enabled && this.config.adaptiveEnabled))
14895
+ return;
14896
+ this.successesSinceLimit += 1;
14897
+ }
14898
+ /** Current available token count. */
14899
+ get availableTokens() {
14900
+ return this.tokens;
14901
+ }
14902
+ /** Current tokens-per-minute budget (may be reduced after 429). */
14903
+ get currentTokensPerMinute() {
14904
+ return this.currentTpm;
14905
+ }
14906
+ };
14907
+ var globalBucket = null;
14908
+ function getGlobalRateLimiter(config) {
14909
+ if (globalBucket === null) {
14910
+ globalBucket = new TokenBucket(config);
14911
+ }
14912
+ return globalBucket;
14913
+ }
14914
+ function resetGlobalRateLimiter() {
14915
+ globalBucket = null;
14916
+ }
14917
+
14918
+ // src/llm/mock.ts
14919
+ var MockLlmClient = class {
14920
+ /** The model name returned in responses. */
14921
+ defaultModel;
14922
+ responses;
14923
+ responseIndex = 0;
14924
+ responseGenerator;
14925
+ _callCount = 0;
14926
+ _callHistory = [];
14927
+ constructor(opts) {
14928
+ this.defaultModel = opts?.defaultModel ?? "mock-model";
14929
+ this.responses = opts?.responses ?? [];
14930
+ this.responseGenerator = opts?.responseGenerator;
14931
+ }
14932
+ /** Number of queries made to this client. */
14933
+ get callCount() {
14934
+ return this._callCount;
14935
+ }
14936
+ /** History of all calls made to this client. */
14937
+ get callHistory() {
14938
+ return this._callHistory;
14939
+ }
14940
+ /** Reset call count, history, and response index. */
14941
+ reset() {
14942
+ this._callCount = 0;
14943
+ this._callHistory.length = 0;
14944
+ this.responseIndex = 0;
14945
+ }
14946
+ /**
14947
+ * Return a mock response.
14948
+ *
14949
+ * Priority for determining response content:
14950
+ * 1. `responseGenerator` function (if provided)
14951
+ * 2. `responses` array (cycles through entries)
14952
+ * 3. Default echo: "Mock response to: <prompt>"
14953
+ *
14954
+ * @param prompt - The prompt (recorded in history).
14955
+ * @param opts - Optional query configuration (recorded in history).
14956
+ * @returns LlmResponse with mock content.
14957
+ */
14958
+ async query(prompt, opts) {
14959
+ const model = opts?.model ?? this.defaultModel;
14960
+ const maxTokens = opts?.maxTokens ?? 4096;
14961
+ const temperature = opts?.temperature ?? 1;
14962
+ this._callCount += 1;
14963
+ this._callHistory.push({
14964
+ prompt,
14965
+ systemPrompt: opts?.systemPrompt,
14966
+ maxTokens,
14967
+ temperature,
14968
+ model
14969
+ });
14970
+ let content;
14971
+ if (this.responseGenerator) {
14972
+ content = this.responseGenerator(prompt);
14973
+ } else if (this.responses.length > 0) {
14974
+ content = this.responses[this.responseIndex % this.responses.length];
14975
+ this.responseIndex += 1;
14976
+ } else {
14977
+ content = `Mock response to: ${prompt.slice(0, 100)}`;
14978
+ }
14979
+ return {
14980
+ content,
14981
+ model,
14982
+ usage: {
14983
+ input_tokens: Math.max(Math.floor(prompt.length / 4), 1),
14984
+ output_tokens: Math.max(Math.floor(content.length / 4), 1)
14985
+ },
14986
+ metadata: { mock: true, call_count: this._callCount }
14987
+ };
14988
+ }
14989
+ /**
14990
+ * Stream a mock response.
14991
+ *
14992
+ * Yields the response word by word to simulate streaming.
14993
+ *
14994
+ * @param prompt - The prompt (recorded in history).
14995
+ * @param opts - Optional query configuration.
14996
+ * @yields Words from the mock response.
14997
+ */
14998
+ async *streamQuery(prompt, opts) {
14999
+ const response = await this.query(prompt, opts);
15000
+ const words = response.content.split(" ");
15001
+ for (let i = 0; i < words.length; i++) {
15002
+ yield words[i] + (i < words.length - 1 ? " " : "");
15003
+ }
15004
+ }
15005
+ };
15006
+
15007
+ // src/llm/groq.ts
15008
+ import fs3 from "node:fs";
15009
+ import os from "node:os";
15010
+ import path5 from "node:path";
15011
+ var DEFAULT_MODEL = "llama-3.3-70b-versatile";
15012
+ var BASE_URL = "https://api.groq.com/openai/v1/chat/completions";
15013
+ var GroqClient = class _GroqClient {
15014
+ /** The resolved API key. */
15015
+ apiKey;
15016
+ /** The default model used when none is specified per-call. */
15017
+ defaultModel;
15018
+ timeoutMs;
15019
+ rateLimiter;
15020
+ constructor(opts) {
15021
+ this.defaultModel = opts?.defaultModel ?? process.env["GROQ_DEFAULT_MODEL"] ?? DEFAULT_MODEL;
15022
+ const envKey = process.env["GROQ_API_KEY"]?.trim();
15023
+ const resolved = opts?.apiKey ?? envKey ?? _GroqClient.loadKeyFile();
15024
+ if (!resolved) {
15025
+ throw new LlmAuthenticationError(
15026
+ "No Groq API key. Set GROQ_API_KEY, pass apiKey, or create ~/.groq"
15027
+ );
15028
+ }
15029
+ this.apiKey = resolved;
15030
+ this.timeoutMs = opts?.timeoutMs ?? 12e4;
15031
+ this.rateLimiter = getGlobalRateLimiter();
15032
+ }
15033
+ /**
15034
+ * Load API key from ~/.groq file.
15035
+ *
15036
+ * @returns The key string, or null if the file does not exist.
15037
+ */
15038
+ static loadKeyFile() {
15039
+ try {
15040
+ const keyPath = path5.join(os.homedir(), ".groq");
15041
+ if (fs3.existsSync(keyPath)) {
15042
+ return fs3.readFileSync(keyPath, "utf-8").trim();
15043
+ }
15044
+ } catch {
15045
+ }
15046
+ return null;
15047
+ }
15048
+ // -- Helpers -------------------------------------------------------------
15049
+ estimateTokens(prompt, systemPrompt) {
15050
+ let total = prompt.length;
15051
+ if (systemPrompt)
15052
+ total += systemPrompt.length;
15053
+ return Math.max(Math.floor(total / 4), 100);
15054
+ }
15055
+ buildMessages(prompt, systemPrompt) {
15056
+ const messages = [];
15057
+ if (systemPrompt) {
15058
+ messages.push({ role: "system", content: systemPrompt });
15059
+ }
15060
+ messages.push({ role: "user", content: prompt });
15061
+ return messages;
15062
+ }
15063
+ /**
15064
+ * Map an HTTP error response to the appropriate LlmError subclass.
15065
+ *
15066
+ * @param status - HTTP status code.
15067
+ * @param body - Parsed response body (if available).
15068
+ * @param message - Raw error message.
15069
+ */
15070
+ mapError(status, body, message) {
15071
+ if (status === 401 || status === 403) {
15072
+ return new LlmAuthenticationError(`Groq auth failed (${status}): ${message}`);
15073
+ }
15074
+ if (status === 429) {
15075
+ this.rateLimiter.recordRateLimit();
15076
+ return new LlmRateLimitError(`Groq rate limit exceeded: ${message}`);
15077
+ }
15078
+ if (status === 408 || status === 504) {
15079
+ return new LlmTimeoutError(`Groq request timed out (${status}): ${message}`);
15080
+ }
15081
+ const errorObj = body?.["error"];
15082
+ const code = errorObj?.["code"];
15083
+ if (code === "context_length_exceeded") {
15084
+ return new LlmContextLengthError(`Groq context length exceeded: ${message}`);
15085
+ }
15086
+ return new LlmError(`Groq API error (${status}): ${message}`);
15087
+ }
15088
+ // -- Public API ----------------------------------------------------------
15089
+ /**
15090
+ * Send a query to Groq and get a complete response.
15091
+ *
15092
+ * @param prompt - The user prompt/query.
15093
+ * @param opts - Optional query configuration.
15094
+ * @returns LlmResponse with generated content and metadata.
15095
+ */
15096
+ async query(prompt, opts) {
15097
+ const useModel = opts?.model ?? this.defaultModel;
15098
+ const maxTokens = opts?.maxTokens ?? 4096;
15099
+ const temperature = opts?.temperature ?? 1;
15100
+ const systemPrompt = opts?.systemPrompt;
15101
+ const estimated = this.estimateTokens(prompt, systemPrompt);
15102
+ await this.rateLimiter.acquire(estimated);
15103
+ const body = {
15104
+ model: useModel,
15105
+ messages: this.buildMessages(prompt, systemPrompt),
15106
+ max_tokens: maxTokens,
15107
+ temperature
15108
+ };
15109
+ let response;
15110
+ try {
15111
+ const controller = new AbortController();
15112
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
15113
+ response = await fetch(BASE_URL, {
15114
+ method: "POST",
15115
+ headers: {
15116
+ "Content-Type": "application/json",
15117
+ "Authorization": `Bearer ${this.apiKey}`
15118
+ },
15119
+ body: JSON.stringify(body),
15120
+ signal: controller.signal
15121
+ });
15122
+ clearTimeout(timer);
15123
+ } catch (err) {
15124
+ if (err instanceof Error && err.name === "AbortError") {
15125
+ throw new LlmTimeoutError(`Groq request timed out after ${this.timeoutMs}ms`);
15126
+ }
15127
+ throw new LlmError(`Groq network error: ${String(err)}`);
15128
+ }
15129
+ if (!response.ok) {
15130
+ let errorBody = null;
15131
+ let errorMessage = response.statusText;
15132
+ try {
15133
+ errorBody = await response.json();
15134
+ const errorObj = errorBody?.["error"];
15135
+ errorMessage = errorObj?.["message"] ?? errorMessage;
15136
+ } catch {
15137
+ }
15138
+ throw this.mapError(response.status, errorBody, errorMessage);
15139
+ }
15140
+ const data = await response.json();
15141
+ this.rateLimiter.recordSuccess();
15142
+ const choices = data["choices"];
15143
+ const firstChoice = choices?.[0];
15144
+ const messageObj = firstChoice?.["message"];
15145
+ const content = messageObj?.["content"] ?? "";
15146
+ const usageObj = data["usage"];
15147
+ let usage;
15148
+ if (usageObj) {
15149
+ usage = {
15150
+ input_tokens: usageObj["prompt_tokens"] ?? 0,
15151
+ output_tokens: usageObj["completion_tokens"] ?? 0
15152
+ };
15153
+ }
15154
+ return {
15155
+ content,
15156
+ model: data["model"] ?? useModel,
15157
+ usage
15158
+ };
15159
+ }
15160
+ /**
15161
+ * Stream a query response chunk by chunk.
15162
+ *
15163
+ * Uses Server-Sent Events (SSE) streaming from the Groq API.
15164
+ *
15165
+ * @param prompt - The user prompt/query.
15166
+ * @param opts - Optional query configuration.
15167
+ * @yields Text chunks as they arrive from the API.
15168
+ */
15169
+ async *streamQuery(prompt, opts) {
15170
+ const useModel = opts?.model ?? this.defaultModel;
15171
+ const maxTokens = opts?.maxTokens ?? 4096;
15172
+ const temperature = opts?.temperature ?? 1;
15173
+ const systemPrompt = opts?.systemPrompt;
15174
+ const estimated = this.estimateTokens(prompt, systemPrompt);
15175
+ await this.rateLimiter.acquire(estimated);
15176
+ const body = {
15177
+ model: useModel,
15178
+ messages: this.buildMessages(prompt, systemPrompt),
15179
+ max_tokens: maxTokens,
15180
+ temperature,
15181
+ stream: true
15182
+ };
15183
+ let response;
15184
+ try {
15185
+ const controller = new AbortController();
15186
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
15187
+ response = await fetch(BASE_URL, {
15188
+ method: "POST",
15189
+ headers: {
15190
+ "Content-Type": "application/json",
15191
+ "Authorization": `Bearer ${this.apiKey}`
15192
+ },
15193
+ body: JSON.stringify(body),
15194
+ signal: controller.signal
15195
+ });
15196
+ clearTimeout(timer);
15197
+ } catch (err) {
15198
+ if (err instanceof Error && err.name === "AbortError") {
15199
+ throw new LlmTimeoutError(`Groq request timed out after ${this.timeoutMs}ms`);
15200
+ }
15201
+ throw new LlmError(`Groq network error: ${String(err)}`);
15202
+ }
15203
+ if (!response.ok) {
15204
+ let errorBody = null;
15205
+ let errorMessage = response.statusText;
15206
+ try {
15207
+ errorBody = await response.json();
15208
+ const errorObj = errorBody?.["error"];
15209
+ errorMessage = errorObj?.["message"] ?? errorMessage;
15210
+ } catch {
15211
+ }
15212
+ throw this.mapError(response.status, errorBody, errorMessage);
15213
+ }
15214
+ if (!response.body) {
15215
+ throw new LlmError("Groq streaming response has no body");
15216
+ }
15217
+ const reader = response.body.getReader();
15218
+ const decoder = new TextDecoder();
15219
+ let buffer = "";
15220
+ let streamCompleted = false;
15221
+ try {
15222
+ for (; ; ) {
15223
+ const { done, value } = await reader.read();
15224
+ if (done)
15225
+ break;
15226
+ buffer += decoder.decode(value, { stream: true });
15227
+ const lines = buffer.split("\n");
15228
+ buffer = lines.pop() ?? "";
15229
+ for (const line of lines) {
15230
+ const trimmed = line.trim();
15231
+ if (!trimmed || !trimmed.startsWith("data: "))
15232
+ continue;
15233
+ const payload = trimmed.slice(6);
15234
+ if (payload === "[DONE]") {
15235
+ streamCompleted = true;
15236
+ return;
15237
+ }
15238
+ try {
15239
+ const chunk = JSON.parse(payload);
15240
+ const choices = chunk["choices"];
15241
+ const delta = choices?.[0]?.["delta"];
15242
+ const content = delta?.["content"];
15243
+ if (content)
15244
+ yield content;
15245
+ } catch {
15246
+ }
15247
+ }
15248
+ }
15249
+ streamCompleted = true;
15250
+ } finally {
15251
+ reader.releaseLock();
15252
+ if (streamCompleted)
15253
+ this.rateLimiter.recordSuccess();
15254
+ }
15255
+ }
15256
+ };
15257
+
15258
+ // src/llm/anthropic.ts
15259
+ import fs4 from "node:fs";
15260
+ import os2 from "node:os";
15261
+ import path6 from "node:path";
15262
+ var DEFAULT_MODEL2 = "claude-sonnet-4-20250514";
15263
+ var BASE_URL2 = "https://api.anthropic.com/v1/messages";
15264
+ var ANTHROPIC_VERSION = "2023-06-01";
15265
+ var AnthropicClient = class _AnthropicClient {
15266
+ /** The resolved API key. */
15267
+ apiKey;
15268
+ /** The default model used when none is specified per-call. */
15269
+ defaultModel;
15270
+ timeoutMs;
15271
+ rateLimiter;
15272
+ constructor(opts) {
15273
+ this.defaultModel = opts?.defaultModel ?? process.env["ANTHROPIC_DEFAULT_MODEL"] ?? DEFAULT_MODEL2;
15274
+ const envKey = process.env["ANTHROPIC_API_KEY"]?.trim();
15275
+ const resolved = opts?.apiKey ?? envKey ?? _AnthropicClient.loadKeyFile();
15276
+ if (!resolved) {
15277
+ throw new LlmAuthenticationError(
15278
+ "No Anthropic API key. Set ANTHROPIC_API_KEY, pass apiKey, or create ~/.anthropic"
15279
+ );
15280
+ }
15281
+ this.apiKey = resolved;
15282
+ this.timeoutMs = opts?.timeoutMs ?? 3e5;
15283
+ this.rateLimiter = getGlobalRateLimiter();
15284
+ }
15285
+ /**
15286
+ * Load API key from ~/.anthropic file.
15287
+ *
15288
+ * @returns The key string, or null if the file does not exist.
15289
+ */
15290
+ static loadKeyFile() {
15291
+ try {
15292
+ const keyPath = path6.join(os2.homedir(), ".anthropic");
15293
+ if (fs4.existsSync(keyPath)) {
15294
+ return fs4.readFileSync(keyPath, "utf-8").trim();
15295
+ }
15296
+ } catch {
15297
+ }
15298
+ return null;
15299
+ }
15300
+ // -- Helpers -------------------------------------------------------------
15301
+ estimateTokens(prompt, systemPrompt) {
15302
+ let total = prompt.length;
15303
+ if (systemPrompt)
15304
+ total += systemPrompt.length;
15305
+ return Math.max(Math.floor(total / 4), 100);
15306
+ }
15307
+ /**
15308
+ * Map an HTTP error response to the appropriate LlmError subclass.
15309
+ *
15310
+ * @param status - HTTP status code.
15311
+ * @param body - Parsed response body (if available).
15312
+ * @param message - Raw error message.
15313
+ */
15314
+ mapError(status, body, message) {
15315
+ if (status === 401 || status === 403) {
15316
+ return new LlmAuthenticationError(
15317
+ `Anthropic auth failed (${status}): ${message}`
15318
+ );
15319
+ }
15320
+ if (status === 429) {
15321
+ this.rateLimiter.recordRateLimit();
15322
+ return new LlmRateLimitError(
15323
+ `Anthropic rate limit exceeded: ${message}`
15324
+ );
15325
+ }
15326
+ if (status === 408 || status === 504) {
15327
+ return new LlmTimeoutError(
15328
+ `Anthropic request timed out (${status}): ${message}`
15329
+ );
15330
+ }
15331
+ const errorType = body?.["error"];
15332
+ const errType = errorType?.["type"];
15333
+ if (errType === "invalid_request_error") {
15334
+ const msg = message.toLowerCase();
15335
+ if (msg.includes("context") || msg.includes("token")) {
15336
+ return new LlmContextLengthError(
15337
+ `Anthropic context length exceeded: ${message}`
15338
+ );
15339
+ }
15340
+ }
15341
+ const lowerMsg = message.toLowerCase();
15342
+ if (lowerMsg.includes("credit balance") || lowerMsg.includes("billing")) {
15343
+ return new LlmAuthenticationError(
15344
+ `Anthropic billing error: ${message}`
15345
+ );
15346
+ }
15347
+ return new LlmError(`Anthropic API error (${status}): ${message}`);
15348
+ }
15349
+ // -- Public API ----------------------------------------------------------
15350
+ /**
15351
+ * Send a query to Anthropic and get a complete response.
15352
+ *
15353
+ * System prompts are sent via the top-level `system` parameter rather
15354
+ * than as a system message in the messages array, per the Anthropic API
15355
+ * specification.
15356
+ *
15357
+ * @param prompt - The user prompt/query.
15358
+ * @param opts - Optional query configuration.
15359
+ * @returns LlmResponse with generated content and metadata.
15360
+ */
15361
+ async query(prompt, opts) {
15362
+ const useModel = opts?.model ?? this.defaultModel;
15363
+ const maxTokens = opts?.maxTokens ?? 4096;
15364
+ const temperature = opts?.temperature ?? 1;
15365
+ const systemPrompt = opts?.systemPrompt;
15366
+ const estimated = this.estimateTokens(prompt, systemPrompt);
15367
+ await this.rateLimiter.acquire(estimated);
15368
+ const requestBody = {
15369
+ model: useModel,
15370
+ messages: [{ role: "user", content: prompt }],
15371
+ max_tokens: maxTokens,
15372
+ temperature
15373
+ };
15374
+ if (systemPrompt) {
15375
+ requestBody["system"] = systemPrompt;
15376
+ }
15377
+ let response;
15378
+ try {
15379
+ const controller = new AbortController();
15380
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
15381
+ response = await fetch(BASE_URL2, {
15382
+ method: "POST",
15383
+ headers: {
15384
+ "Content-Type": "application/json",
15385
+ "x-api-key": this.apiKey,
15386
+ "anthropic-version": ANTHROPIC_VERSION
15387
+ },
15388
+ body: JSON.stringify(requestBody),
15389
+ signal: controller.signal
15390
+ });
15391
+ clearTimeout(timer);
15392
+ } catch (err) {
15393
+ if (err instanceof Error && err.name === "AbortError") {
15394
+ throw new LlmTimeoutError(
15395
+ `Anthropic request timed out after ${this.timeoutMs}ms`
15396
+ );
15397
+ }
15398
+ throw new LlmError(`Anthropic network error: ${String(err)}`);
15399
+ }
15400
+ if (!response.ok) {
15401
+ let errorBody = null;
15402
+ let errorMessage = response.statusText;
15403
+ try {
15404
+ errorBody = await response.json();
15405
+ const errorObj = errorBody?.["error"];
15406
+ errorMessage = errorObj?.["message"] ?? errorMessage;
15407
+ } catch {
15408
+ }
15409
+ throw this.mapError(response.status, errorBody, errorMessage);
15410
+ }
15411
+ const data = await response.json();
15412
+ this.rateLimiter.recordSuccess();
15413
+ const contentBlocks = data["content"];
15414
+ const textParts = [];
15415
+ if (contentBlocks) {
15416
+ for (const block of contentBlocks) {
15417
+ if (block["type"] === "text" && typeof block["text"] === "string") {
15418
+ textParts.push(block["text"]);
15419
+ }
15420
+ }
15421
+ }
15422
+ const content = textParts.join("").trim();
15423
+ const usageObj = data["usage"];
15424
+ const inputTokens = usageObj?.["input_tokens"] ?? 0;
15425
+ const outputTokens = usageObj?.["output_tokens"] ?? 0;
15426
+ return {
15427
+ content,
15428
+ model: data["model"] ?? useModel,
15429
+ usage: {
15430
+ input_tokens: inputTokens,
15431
+ output_tokens: outputTokens
15432
+ }
15433
+ };
15434
+ }
15435
+ /**
15436
+ * Stream a query response chunk by chunk.
15437
+ *
15438
+ * Uses Server-Sent Events (SSE) streaming from the Anthropic API.
15439
+ * System prompts are sent via the top-level `system` parameter.
15440
+ *
15441
+ * @param prompt - The user prompt/query.
15442
+ * @param opts - Optional query configuration.
15443
+ * @yields Text chunks as they arrive from the API.
15444
+ */
15445
+ async *streamQuery(prompt, opts) {
15446
+ const useModel = opts?.model ?? this.defaultModel;
15447
+ const maxTokens = opts?.maxTokens ?? 4096;
15448
+ const temperature = opts?.temperature ?? 1;
15449
+ const systemPrompt = opts?.systemPrompt;
15450
+ const estimated = this.estimateTokens(prompt, systemPrompt);
15451
+ await this.rateLimiter.acquire(estimated);
15452
+ const requestBody = {
15453
+ model: useModel,
15454
+ messages: [{ role: "user", content: prompt }],
15455
+ max_tokens: maxTokens,
15456
+ temperature,
15457
+ stream: true
15458
+ };
15459
+ if (systemPrompt) {
15460
+ requestBody["system"] = systemPrompt;
15461
+ }
15462
+ let response;
15463
+ try {
15464
+ const controller = new AbortController();
15465
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
15466
+ response = await fetch(BASE_URL2, {
15467
+ method: "POST",
15468
+ headers: {
15469
+ "Content-Type": "application/json",
15470
+ "x-api-key": this.apiKey,
15471
+ "anthropic-version": ANTHROPIC_VERSION
15472
+ },
15473
+ body: JSON.stringify(requestBody),
15474
+ signal: controller.signal
15475
+ });
15476
+ clearTimeout(timer);
15477
+ } catch (err) {
15478
+ if (err instanceof Error && err.name === "AbortError") {
15479
+ throw new LlmTimeoutError(
15480
+ `Anthropic request timed out after ${this.timeoutMs}ms`
15481
+ );
15482
+ }
15483
+ throw new LlmError(`Anthropic network error: ${String(err)}`);
15484
+ }
15485
+ if (!response.ok) {
15486
+ let errorBody = null;
15487
+ let errorMessage = response.statusText;
15488
+ try {
15489
+ errorBody = await response.json();
15490
+ const errorObj = errorBody?.["error"];
15491
+ errorMessage = errorObj?.["message"] ?? errorMessage;
15492
+ } catch {
15493
+ }
15494
+ throw this.mapError(response.status, errorBody, errorMessage);
15495
+ }
15496
+ if (!response.body) {
15497
+ throw new LlmError("Anthropic streaming response has no body");
15498
+ }
15499
+ const reader = response.body.getReader();
15500
+ const decoder = new TextDecoder();
15501
+ let buffer = "";
15502
+ let streamCompleted = false;
15503
+ try {
15504
+ for (; ; ) {
15505
+ const { done, value } = await reader.read();
15506
+ if (done)
15507
+ break;
15508
+ buffer += decoder.decode(value, { stream: true });
15509
+ const lines = buffer.split("\n");
15510
+ buffer = lines.pop() ?? "";
15511
+ for (const line of lines) {
15512
+ const trimmed = line.trim();
15513
+ if (!trimmed || !trimmed.startsWith("data: "))
15514
+ continue;
15515
+ const payload = trimmed.slice(6);
15516
+ try {
15517
+ const event = JSON.parse(payload);
15518
+ const eventType = event["type"];
15519
+ if (eventType === "content_block_delta") {
15520
+ const delta = event["delta"];
15521
+ if (delta?.["type"] === "text_delta") {
15522
+ const text = delta["text"];
15523
+ if (text)
15524
+ yield text;
15525
+ }
15526
+ } else if (eventType === "message_stop") {
15527
+ streamCompleted = true;
15528
+ return;
15529
+ }
15530
+ } catch {
15531
+ }
15532
+ }
15533
+ }
15534
+ streamCompleted = true;
15535
+ } finally {
15536
+ reader.releaseLock();
15537
+ if (streamCompleted)
15538
+ this.rateLimiter.recordSuccess();
15539
+ }
15540
+ }
15541
+ };
15542
+
15543
+ // src/llm/factory.ts
15544
+ function createLlmClient(opts) {
15545
+ const clientType = (opts?.clientType ?? process.env["LLM_CLIENT_TYPE"] ?? "mock").toLowerCase();
15546
+ const model = opts?.model ?? process.env["LLM_DEFAULT_MODEL"];
15547
+ if (clientType === "mock") {
15548
+ return new MockLlmClient({
15549
+ defaultModel: model ?? "mock-model"
15550
+ });
15551
+ }
15552
+ if (clientType === "groq") {
15553
+ return new GroqClient({
15554
+ apiKey: opts?.apiKey,
15555
+ defaultModel: model,
15556
+ timeoutMs: opts?.timeoutMs
15557
+ });
15558
+ }
15559
+ if (clientType === "anthropic") {
15560
+ return new AnthropicClient({
15561
+ apiKey: opts?.apiKey,
15562
+ defaultModel: model,
15563
+ timeoutMs: opts?.timeoutMs
15564
+ });
15565
+ }
15566
+ throw new Error(
15567
+ `Unknown LLM client type: "${clientType}". Valid types: "groq", "anthropic", "mock"`
15568
+ );
15569
+ }
15570
+
13194
15571
  // src/index.ts
13195
- var version = "0.4.0";
15572
+ var version = "0.6.0";
13196
15573
  export {
13197
15574
  ACKLifecycleManager,
13198
- AckStage,
15575
+ AGENT_STATE_FAILED,
15576
+ AGENT_STATE_INITIALIZING,
15577
+ AGENT_STATE_RUNNING,
15578
+ AGENT_STATE_SHUTTING_DOWN,
15579
+ AckStage2 as AckStage,
13199
15580
  ActivityBuffer,
13200
15581
  ActivityBufferSync,
13201
15582
  ActivityClient,
13202
15583
  AgentState,
13203
15584
  AgentStateMachine,
15585
+ AnthropicClient,
13204
15586
  ArtifactType,
13205
15587
  BaseClient,
13206
15588
  BordaCountAggregator,
15589
+ BufferFullError,
13207
15590
  CT_AGENT_REPORT_V1,
13208
15591
  CT_SCHEDULER_COMMAND_V1,
15592
+ CancellationManager,
15593
+ CancellationValidationError,
15594
+ CommunicationClass,
13209
15595
  ConfidenceWeightedAggregator,
13210
15596
  ConnectorClient,
15597
+ DEDUP_WINDOW_S,
15598
+ DEFAULT_ACK_TIMEOUT_MS,
15599
+ DEFAULT_BACKOFF_MULTIPLIER,
15600
+ DEFAULT_EFFECTIVE_MAX_REDIRECTS,
13211
15601
  DEFAULT_ESCALATION_POLICY,
13212
15602
  DEFAULT_EXECUTION_POLICY,
15603
+ DEFAULT_INITIAL_BACKOFF_MS,
15604
+ DEFAULT_MAX_BACKOFF_MS,
15605
+ DEFAULT_MAX_REDIRECTS,
15606
+ DEFAULT_MAX_RETRIES_ON_OVERLOADED,
13213
15607
  DEFAULT_NEGOTIATION_POLICY,
15608
+ DEFAULT_PEER_LIVENESS_THRESHOLD_MS,
15609
+ DebateIntensity,
13214
15610
  DecisionOutcome,
13215
15611
  DefaultWorktreePolicy,
15612
+ DuplicateDetectedError,
15613
+ EnvelopeState,
13216
15614
  ErrorCode,
13217
15615
  ErrorCodeMapper,
13218
15616
  FileBackend,
15617
+ GatewayRedirectEmitter,
15618
+ GatewayValidationError,
15619
+ GroqClient,
13219
15620
  HITLClient,
13220
15621
  HandoffClient,
13221
15622
  HandoffStatus,
13222
15623
  HandoffTimeoutError,
13223
15624
  HandoffValidationError,
13224
15625
  HitlMode,
15626
+ HitlReasonType,
15627
+ InMemoryAuditor,
15628
+ InMemoryNegotiationRoomStore,
13225
15629
  InMemoryPolicyStore,
13226
15630
  InterceptorChain,
13227
15631
  JSONFilePersistence,
13228
15632
  JsonFilePolicyStore,
13229
15633
  KeyringBackend,
15634
+ LlmAuthenticationError,
15635
+ LlmContextLengthError,
15636
+ LlmError,
15637
+ LlmRateLimitError,
15638
+ LlmTimeoutError,
13230
15639
  LoggingClient,
15640
+ MIN_GRACE_PERIOD_MS,
13231
15641
  MajorityVoteAggregator,
13232
15642
  MaxEntriesStrategy,
13233
15643
  MessageProcessor,
13234
15644
  MessageType,
15645
+ MockLlmClient,
15646
+ NON_SERVING_AGENT_STATES,
13235
15647
  NegotiationClient,
15648
+ NegotiationError,
13236
15649
  NegotiationRoomClient,
15650
+ NegotiationRoomStoreError,
13237
15651
  NegotiationTimeoutError,
13238
15652
  NegotiationValidationError,
15653
+ NoOpAuditor,
13239
15654
  NodeStatus,
15655
+ PeerSelector,
15656
+ PermissionError,
15657
+ PersistentActivityBuffer,
13240
15658
  PersistentWorktreeState,
13241
15659
  PolicyStoreError,
15660
+ PolicyViolationError,
15661
+ PreemptionError,
15662
+ REGISTRATION_TYPE_STANDARD_AGENT,
15663
+ REGISTRATION_TYPE_SWARM_GATEWAY,
15664
+ RETRY_AFTER_JITTER_RATIO,
13242
15665
  ReasoningClient,
13243
15666
  RegistryClient,
13244
15667
  Resolver,
15668
+ RouteError,
13245
15669
  RouterClient,
13246
15670
  RuntimePersistence,
13247
15671
  SchedulerClient,
@@ -13259,35 +15683,63 @@ export {
13259
15683
  SimpleAverageAggregator,
13260
15684
  StateTransitionError,
13261
15685
  Sw4rmError,
15686
+ TimeoutError,
15687
+ TokenBucket,
13262
15688
  ToolClient,
13263
15689
  TriggerType,
15690
+ ValidationError,
13264
15691
  VotingAnalyzer,
13265
15692
  WorkflowClient,
13266
15693
  WorkflowCycleError,
13267
15694
  WorkflowStatus,
13268
15695
  WorkflowValidationError,
13269
15696
  WorktreeClient,
15697
+ WorktreeError,
15698
+ WorktreeStateEnum,
15699
+ WorktreeTransitionError,
13270
15700
  aggregateVotes,
13271
15701
  buildAckEnvelope,
13272
15702
  buildEnvelope,
15703
+ buildRateLimiterConfig,
15704
+ computeEnvelopeHash,
13273
15705
  computeIdempotencyToken,
15706
+ createLlmClient,
13274
15707
  createResilientIncomingStream,
15708
+ createSimpleProof,
13275
15709
  decodeAgentReportV1,
13276
15710
  decodeBase64,
15711
+ defaultAgentConfig,
15712
+ defaultEndpoints,
15713
+ defaultRetryPolicy,
15714
+ defaultSW4RMConfig,
15715
+ delegateToSwarm,
13277
15716
  durationToMs,
13278
15717
  encodeSchedulerCommandV1,
15718
+ getConfig,
15719
+ getDefaultStore,
15720
+ getGlobalRateLimiter,
13279
15721
  getValidTransitions,
15722
+ isTerminalEnvelopeState,
13280
15723
  isValidTransition,
15724
+ isValidWorktreeTransition,
15725
+ loadConfig,
15726
+ loadConfigFromEnv,
13281
15727
  loggingInterceptor,
13282
15728
  mapGrpcStatusToErrorCode,
13283
15729
  msToDuration,
13284
15730
  normalizeReportPaths,
13285
15731
  nowTimestamp,
13286
15732
  parseNegotiationEvent,
15733
+ resetConfig,
15734
+ resetDefaultStore,
15735
+ resetGlobalRateLimiter,
13287
15736
  selectBackend,
13288
15737
  sendMessageWithAck,
15738
+ setConfig,
13289
15739
  timingInterceptor,
15740
+ updateEnvelopeState,
13290
15741
  uuidv4,
15742
+ verifyAuditProof,
13291
15743
  version
13292
15744
  };
13293
15745
  /*! Bundled license information: