@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
@@ -1856,25 +1856,25 @@ var require_codegen = __commonJS({
1856
1856
  var require_fetch = __commonJS({
1857
1857
  "node_modules/@protobufjs/fetch/index.js"(exports2, module2) {
1858
1858
  "use strict";
1859
- module2.exports = fetch;
1859
+ module2.exports = fetch2;
1860
1860
  var asPromise = require_aspromise();
1861
1861
  var inquire2 = require_inquire();
1862
- var fs = inquire2("fs");
1863
- function fetch(filename, options, callback) {
1862
+ var fs5 = inquire2("fs");
1863
+ function fetch2(filename, options, callback) {
1864
1864
  if (typeof options === "function") {
1865
1865
  callback = options;
1866
1866
  options = {};
1867
1867
  } else if (!options)
1868
1868
  options = {};
1869
1869
  if (!callback)
1870
- return asPromise(fetch, this, filename, options);
1871
- if (!options.xhr && fs && fs.readFile)
1872
- return fs.readFile(filename, function fetchReadFileCallback(err, contents) {
1873
- return err && typeof XMLHttpRequest !== "undefined" ? fetch.xhr(filename, options, callback) : err ? callback(err) : callback(null, options.binary ? contents : contents.toString("utf8"));
1870
+ return asPromise(fetch2, this, filename, options);
1871
+ if (!options.xhr && fs5 && fs5.readFile)
1872
+ return fs5.readFile(filename, function fetchReadFileCallback(err, contents) {
1873
+ return err && typeof XMLHttpRequest !== "undefined" ? fetch2.xhr(filename, options, callback) : err ? callback(err) : callback(null, options.binary ? contents : contents.toString("utf8"));
1874
1874
  });
1875
- return fetch.xhr(filename, options, callback);
1875
+ return fetch2.xhr(filename, options, callback);
1876
1876
  }
1877
- fetch.xhr = function fetch_xhr(filename, options, callback) {
1877
+ fetch2.xhr = function fetch_xhr(filename, options, callback) {
1878
1878
  var xhr = new XMLHttpRequest();
1879
1879
  xhr.onreadystatechange = function fetchOnReadyStateChange() {
1880
1880
  if (xhr.readyState !== 4)
@@ -1907,15 +1907,15 @@ var require_fetch = __commonJS({
1907
1907
  var require_path = __commonJS({
1908
1908
  "node_modules/@protobufjs/path/index.js"(exports2) {
1909
1909
  "use strict";
1910
- var path4 = exports2;
1910
+ var path7 = exports2;
1911
1911
  var isAbsolute = (
1912
1912
  /**
1913
1913
  * Tests if the specified path is absolute.
1914
1914
  * @param {string} path Path to test
1915
1915
  * @returns {boolean} `true` if path is absolute
1916
1916
  */
1917
- path4.isAbsolute = function isAbsolute2(path5) {
1918
- return /^(?:\/|\w+:)/.test(path5);
1917
+ path7.isAbsolute = function isAbsolute2(path8) {
1918
+ return /^(?:\/|\w+:)/.test(path8);
1919
1919
  }
1920
1920
  );
1921
1921
  var normalize = (
@@ -1924,9 +1924,9 @@ var require_path = __commonJS({
1924
1924
  * @param {string} path Path to normalize
1925
1925
  * @returns {string} Normalized path
1926
1926
  */
1927
- path4.normalize = function normalize2(path5) {
1928
- path5 = path5.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
1929
- var parts = path5.split("/"), absolute = isAbsolute(path5), prefix = "";
1927
+ path7.normalize = function normalize2(path8) {
1928
+ path8 = path8.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
1929
+ var parts = path8.split("/"), absolute = isAbsolute(path8), prefix = "";
1930
1930
  if (absolute)
1931
1931
  prefix = parts.shift() + "/";
1932
1932
  for (var i = 0; i < parts.length; ) {
@@ -1945,7 +1945,7 @@ var require_path = __commonJS({
1945
1945
  return prefix + parts.join("/");
1946
1946
  }
1947
1947
  );
1948
- path4.resolve = function resolve(originPath, includePath, alreadyNormalized) {
1948
+ path7.resolve = function resolve(originPath, includePath, alreadyNormalized) {
1949
1949
  if (!alreadyNormalized)
1950
1950
  includePath = normalize(includePath);
1951
1951
  if (isAbsolute(includePath))
@@ -2096,16 +2096,16 @@ var require_namespace = __commonJS({
2096
2096
  object.onRemove(this);
2097
2097
  return clearCache(this);
2098
2098
  };
2099
- Namespace.prototype.define = function define2(path4, json) {
2100
- if (util.isString(path4))
2101
- path4 = path4.split(".");
2102
- else if (!Array.isArray(path4))
2099
+ Namespace.prototype.define = function define2(path7, json) {
2100
+ if (util.isString(path7))
2101
+ path7 = path7.split(".");
2102
+ else if (!Array.isArray(path7))
2103
2103
  throw TypeError("illegal path");
2104
- if (path4 && path4.length && path4[0] === "")
2104
+ if (path7 && path7.length && path7[0] === "")
2105
2105
  throw Error("path must be relative");
2106
2106
  var ptr = this;
2107
- while (path4.length > 0) {
2108
- var part = path4.shift();
2107
+ while (path7.length > 0) {
2108
+ var part = path7.shift();
2109
2109
  if (ptr.nested && ptr.nested[part]) {
2110
2110
  ptr = ptr.nested[part];
2111
2111
  if (!(ptr instanceof Namespace))
@@ -2142,26 +2142,26 @@ var require_namespace = __commonJS({
2142
2142
  });
2143
2143
  return this;
2144
2144
  };
2145
- Namespace.prototype.lookup = function lookup(path4, filterTypes, parentAlreadyChecked) {
2145
+ Namespace.prototype.lookup = function lookup(path7, filterTypes, parentAlreadyChecked) {
2146
2146
  if (typeof filterTypes === "boolean") {
2147
2147
  parentAlreadyChecked = filterTypes;
2148
2148
  filterTypes = void 0;
2149
2149
  } else if (filterTypes && !Array.isArray(filterTypes))
2150
2150
  filterTypes = [filterTypes];
2151
- if (util.isString(path4) && path4.length) {
2152
- if (path4 === ".")
2151
+ if (util.isString(path7) && path7.length) {
2152
+ if (path7 === ".")
2153
2153
  return this.root;
2154
- path4 = path4.split(".");
2155
- } else if (!path4.length)
2154
+ path7 = path7.split(".");
2155
+ } else if (!path7.length)
2156
2156
  return this;
2157
- var flatPath = path4.join(".");
2158
- if (path4[0] === "")
2159
- return this.root.lookup(path4.slice(1), filterTypes);
2157
+ var flatPath = path7.join(".");
2158
+ if (path7[0] === "")
2159
+ return this.root.lookup(path7.slice(1), filterTypes);
2160
2160
  var found = this.root._fullyQualifiedObjects && this.root._fullyQualifiedObjects["." + flatPath];
2161
2161
  if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
2162
2162
  return found;
2163
2163
  }
2164
- found = this._lookupImpl(path4, flatPath);
2164
+ found = this._lookupImpl(path7, flatPath);
2165
2165
  if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
2166
2166
  return found;
2167
2167
  }
@@ -2169,7 +2169,7 @@ var require_namespace = __commonJS({
2169
2169
  return null;
2170
2170
  var current = this;
2171
2171
  while (current.parent) {
2172
- found = current.parent._lookupImpl(path4, flatPath);
2172
+ found = current.parent._lookupImpl(path7, flatPath);
2173
2173
  if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
2174
2174
  return found;
2175
2175
  }
@@ -2177,49 +2177,49 @@ var require_namespace = __commonJS({
2177
2177
  }
2178
2178
  return null;
2179
2179
  };
2180
- Namespace.prototype._lookupImpl = function lookup(path4, flatPath) {
2180
+ Namespace.prototype._lookupImpl = function lookup(path7, flatPath) {
2181
2181
  if (Object.prototype.hasOwnProperty.call(this._lookupCache, flatPath)) {
2182
2182
  return this._lookupCache[flatPath];
2183
2183
  }
2184
- var found = this.get(path4[0]);
2184
+ var found = this.get(path7[0]);
2185
2185
  var exact = null;
2186
2186
  if (found) {
2187
- if (path4.length === 1) {
2187
+ if (path7.length === 1) {
2188
2188
  exact = found;
2189
2189
  } else if (found instanceof Namespace) {
2190
- path4 = path4.slice(1);
2191
- exact = found._lookupImpl(path4, path4.join("."));
2190
+ path7 = path7.slice(1);
2191
+ exact = found._lookupImpl(path7, path7.join("."));
2192
2192
  }
2193
2193
  } else {
2194
2194
  for (var i = 0; i < this.nestedArray.length; ++i)
2195
- if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path4, flatPath)))
2195
+ if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path7, flatPath)))
2196
2196
  exact = found;
2197
2197
  }
2198
2198
  this._lookupCache[flatPath] = exact;
2199
2199
  return exact;
2200
2200
  };
2201
- Namespace.prototype.lookupType = function lookupType(path4) {
2202
- var found = this.lookup(path4, [Type]);
2201
+ Namespace.prototype.lookupType = function lookupType(path7) {
2202
+ var found = this.lookup(path7, [Type]);
2203
2203
  if (!found)
2204
- throw Error("no such type: " + path4);
2204
+ throw Error("no such type: " + path7);
2205
2205
  return found;
2206
2206
  };
2207
- Namespace.prototype.lookupEnum = function lookupEnum(path4) {
2208
- var found = this.lookup(path4, [Enum]);
2207
+ Namespace.prototype.lookupEnum = function lookupEnum(path7) {
2208
+ var found = this.lookup(path7, [Enum]);
2209
2209
  if (!found)
2210
- throw Error("no such Enum '" + path4 + "' in " + this);
2210
+ throw Error("no such Enum '" + path7 + "' in " + this);
2211
2211
  return found;
2212
2212
  };
2213
- Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(path4) {
2214
- var found = this.lookup(path4, [Type, Enum]);
2213
+ Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(path7) {
2214
+ var found = this.lookup(path7, [Type, Enum]);
2215
2215
  if (!found)
2216
- throw Error("no such Type or Enum '" + path4 + "' in " + this);
2216
+ throw Error("no such Type or Enum '" + path7 + "' in " + this);
2217
2217
  return found;
2218
2218
  };
2219
- Namespace.prototype.lookupService = function lookupService(path4) {
2220
- var found = this.lookup(path4, [Service]);
2219
+ Namespace.prototype.lookupService = function lookupService(path7) {
2220
+ var found = this.lookup(path7, [Service]);
2221
2221
  if (!found)
2222
- throw Error("no such Service '" + path4 + "' in " + this);
2222
+ throw Error("no such Service '" + path7 + "' in " + this);
2223
2223
  return found;
2224
2224
  };
2225
2225
  Namespace._configure = function(Type_, Service_, Enum_) {
@@ -3365,12 +3365,12 @@ var require_root = __commonJS({
3365
3365
  if (parsed.imports) {
3366
3366
  for (; i2 < parsed.imports.length; ++i2)
3367
3367
  if (resolved2 = getBundledFileName(parsed.imports[i2]) || self2.resolvePath(filename2, parsed.imports[i2]))
3368
- fetch(resolved2);
3368
+ fetch2(resolved2);
3369
3369
  }
3370
3370
  if (parsed.weakImports) {
3371
3371
  for (i2 = 0; i2 < parsed.weakImports.length; ++i2)
3372
3372
  if (resolved2 = getBundledFileName(parsed.weakImports[i2]) || self2.resolvePath(filename2, parsed.weakImports[i2]))
3373
- fetch(resolved2, true);
3373
+ fetch2(resolved2, true);
3374
3374
  }
3375
3375
  }
3376
3376
  } catch (err) {
@@ -3380,7 +3380,7 @@ var require_root = __commonJS({
3380
3380
  finish(null, self2);
3381
3381
  }
3382
3382
  }
3383
- function fetch(filename2, weak) {
3383
+ function fetch2(filename2, weak) {
3384
3384
  filename2 = getBundledFileName(filename2) || filename2;
3385
3385
  if (self2.files.indexOf(filename2) > -1) {
3386
3386
  return;
@@ -3432,7 +3432,7 @@ var require_root = __commonJS({
3432
3432
  }
3433
3433
  for (var i = 0, resolved; i < filename.length; ++i)
3434
3434
  if (resolved = self2.resolvePath("", filename[i]))
3435
- fetch(resolved);
3435
+ fetch2(resolved);
3436
3436
  if (sync) {
3437
3437
  self2.resolveAll();
3438
3438
  return self2;
@@ -3620,14 +3620,14 @@ var require_util = __commonJS({
3620
3620
  Object.defineProperty(object, "$type", { value: enm, enumerable: false });
3621
3621
  return enm;
3622
3622
  };
3623
- util.setProperty = function setProperty(dst, path4, value, ifNotSet) {
3624
- function setProp(dst2, path5, value2) {
3625
- var part = path5.shift();
3623
+ util.setProperty = function setProperty(dst, path7, value, ifNotSet) {
3624
+ function setProp(dst2, path8, value2) {
3625
+ var part = path8.shift();
3626
3626
  if (part === "__proto__" || part === "prototype") {
3627
3627
  return dst2;
3628
3628
  }
3629
- if (path5.length > 0) {
3630
- dst2[part] = setProp(dst2[part] || {}, path5, value2);
3629
+ if (path8.length > 0) {
3630
+ dst2[part] = setProp(dst2[part] || {}, path8, value2);
3631
3631
  } else {
3632
3632
  var prevValue = dst2[part];
3633
3633
  if (prevValue && ifNotSet)
@@ -3640,10 +3640,10 @@ var require_util = __commonJS({
3640
3640
  }
3641
3641
  if (typeof dst !== "object")
3642
3642
  throw TypeError("dst must be an object");
3643
- if (!path4)
3643
+ if (!path7)
3644
3644
  throw TypeError("path must be specified");
3645
- path4 = path4.split(".");
3646
- return setProp(dst, path4, value);
3645
+ path7 = path7.split(".");
3646
+ return setProp(dst, path7, value);
3647
3647
  };
3648
3648
  Object.defineProperty(util, "decorateRoot", {
3649
3649
  get: function() {
@@ -4190,12 +4190,12 @@ var require_object = __commonJS({
4190
4190
  */
4191
4191
  fullName: {
4192
4192
  get: function() {
4193
- var path4 = [this.name], ptr = this.parent;
4193
+ var path7 = [this.name], ptr = this.parent;
4194
4194
  while (ptr) {
4195
- path4.unshift(ptr.name);
4195
+ path7.unshift(ptr.name);
4196
4196
  ptr = ptr.parent;
4197
4197
  }
4198
- return path4.join(".");
4198
+ return path7.join(".");
4199
4199
  }
4200
4200
  }
4201
4201
  });
@@ -8177,19 +8177,19 @@ var require_util2 = __commonJS({
8177
8177
  "use strict";
8178
8178
  Object.defineProperty(exports2, "__esModule", { value: true });
8179
8179
  exports2.addCommonProtos = exports2.loadProtosWithOptionsSync = exports2.loadProtosWithOptions = void 0;
8180
- var fs = require("fs");
8181
- var path4 = require("path");
8180
+ var fs5 = require("fs");
8181
+ var path7 = require("path");
8182
8182
  var Protobuf = require_protobufjs();
8183
8183
  function addIncludePathResolver(root, includePaths) {
8184
8184
  const originalResolvePath = root.resolvePath;
8185
8185
  root.resolvePath = (origin, target) => {
8186
- if (path4.isAbsolute(target)) {
8186
+ if (path7.isAbsolute(target)) {
8187
8187
  return target;
8188
8188
  }
8189
8189
  for (const directory of includePaths) {
8190
- const fullPath = path4.join(directory, target);
8190
+ const fullPath = path7.join(directory, target);
8191
8191
  try {
8192
- fs.accessSync(fullPath, fs.constants.R_OK);
8192
+ fs5.accessSync(fullPath, fs5.constants.R_OK);
8193
8193
  return fullPath;
8194
8194
  } catch (err) {
8195
8195
  continue;
@@ -9483,53 +9483,100 @@ var require_src2 = __commonJS({
9483
9483
  var src_exports = {};
9484
9484
  __export(src_exports, {
9485
9485
  ACKLifecycleManager: () => ACKLifecycleManager,
9486
- AckStage: () => AckStage,
9486
+ AGENT_STATE_FAILED: () => AGENT_STATE_FAILED,
9487
+ AGENT_STATE_INITIALIZING: () => AGENT_STATE_INITIALIZING,
9488
+ AGENT_STATE_RUNNING: () => AGENT_STATE_RUNNING,
9489
+ AGENT_STATE_SHUTTING_DOWN: () => AGENT_STATE_SHUTTING_DOWN,
9490
+ AckStage: () => AckStage2,
9487
9491
  ActivityBuffer: () => ActivityBuffer,
9488
9492
  ActivityBufferSync: () => ActivityBufferSync,
9489
9493
  ActivityClient: () => ActivityClient,
9490
9494
  AgentState: () => AgentState,
9491
9495
  AgentStateMachine: () => AgentStateMachine,
9496
+ AnthropicClient: () => AnthropicClient,
9492
9497
  ArtifactType: () => ArtifactType,
9493
9498
  BaseClient: () => BaseClient,
9494
9499
  BordaCountAggregator: () => BordaCountAggregator,
9500
+ BufferFullError: () => BufferFullError,
9495
9501
  CT_AGENT_REPORT_V1: () => CT_AGENT_REPORT_V1,
9496
9502
  CT_SCHEDULER_COMMAND_V1: () => CT_SCHEDULER_COMMAND_V1,
9503
+ CancellationManager: () => CancellationManager,
9504
+ CancellationValidationError: () => CancellationValidationError,
9505
+ CommunicationClass: () => CommunicationClass,
9497
9506
  ConfidenceWeightedAggregator: () => ConfidenceWeightedAggregator,
9498
9507
  ConnectorClient: () => ConnectorClient,
9508
+ DEDUP_WINDOW_S: () => DEDUP_WINDOW_S,
9509
+ DEFAULT_ACK_TIMEOUT_MS: () => DEFAULT_ACK_TIMEOUT_MS,
9510
+ DEFAULT_BACKOFF_MULTIPLIER: () => DEFAULT_BACKOFF_MULTIPLIER,
9511
+ DEFAULT_EFFECTIVE_MAX_REDIRECTS: () => DEFAULT_EFFECTIVE_MAX_REDIRECTS,
9499
9512
  DEFAULT_ESCALATION_POLICY: () => DEFAULT_ESCALATION_POLICY,
9500
9513
  DEFAULT_EXECUTION_POLICY: () => DEFAULT_EXECUTION_POLICY,
9514
+ DEFAULT_INITIAL_BACKOFF_MS: () => DEFAULT_INITIAL_BACKOFF_MS,
9515
+ DEFAULT_MAX_BACKOFF_MS: () => DEFAULT_MAX_BACKOFF_MS,
9516
+ DEFAULT_MAX_REDIRECTS: () => DEFAULT_MAX_REDIRECTS,
9517
+ DEFAULT_MAX_RETRIES_ON_OVERLOADED: () => DEFAULT_MAX_RETRIES_ON_OVERLOADED,
9501
9518
  DEFAULT_NEGOTIATION_POLICY: () => DEFAULT_NEGOTIATION_POLICY,
9519
+ DEFAULT_PEER_LIVENESS_THRESHOLD_MS: () => DEFAULT_PEER_LIVENESS_THRESHOLD_MS,
9520
+ DebateIntensity: () => DebateIntensity,
9502
9521
  DecisionOutcome: () => DecisionOutcome,
9503
9522
  DefaultWorktreePolicy: () => DefaultWorktreePolicy,
9523
+ DuplicateDetectedError: () => DuplicateDetectedError,
9524
+ EnvelopeState: () => EnvelopeState,
9504
9525
  ErrorCode: () => ErrorCode,
9505
9526
  ErrorCodeMapper: () => ErrorCodeMapper,
9506
9527
  FileBackend: () => FileBackend,
9528
+ GatewayRedirectEmitter: () => GatewayRedirectEmitter,
9529
+ GatewayValidationError: () => GatewayValidationError,
9530
+ GroqClient: () => GroqClient,
9507
9531
  HITLClient: () => HITLClient,
9508
9532
  HandoffClient: () => HandoffClient,
9509
9533
  HandoffStatus: () => HandoffStatus,
9510
9534
  HandoffTimeoutError: () => HandoffTimeoutError,
9511
9535
  HandoffValidationError: () => HandoffValidationError,
9512
9536
  HitlMode: () => HitlMode,
9537
+ HitlReasonType: () => HitlReasonType,
9538
+ InMemoryAuditor: () => InMemoryAuditor,
9539
+ InMemoryNegotiationRoomStore: () => InMemoryNegotiationRoomStore,
9513
9540
  InMemoryPolicyStore: () => InMemoryPolicyStore,
9514
9541
  InterceptorChain: () => InterceptorChain,
9515
9542
  JSONFilePersistence: () => JSONFilePersistence,
9516
9543
  JsonFilePolicyStore: () => JsonFilePolicyStore,
9517
9544
  KeyringBackend: () => KeyringBackend,
9545
+ LlmAuthenticationError: () => LlmAuthenticationError,
9546
+ LlmContextLengthError: () => LlmContextLengthError,
9547
+ LlmError: () => LlmError,
9548
+ LlmRateLimitError: () => LlmRateLimitError,
9549
+ LlmTimeoutError: () => LlmTimeoutError,
9518
9550
  LoggingClient: () => LoggingClient,
9551
+ MIN_GRACE_PERIOD_MS: () => MIN_GRACE_PERIOD_MS,
9519
9552
  MajorityVoteAggregator: () => MajorityVoteAggregator,
9520
9553
  MaxEntriesStrategy: () => MaxEntriesStrategy,
9521
9554
  MessageProcessor: () => MessageProcessor,
9522
9555
  MessageType: () => MessageType,
9556
+ MockLlmClient: () => MockLlmClient,
9557
+ NON_SERVING_AGENT_STATES: () => NON_SERVING_AGENT_STATES,
9523
9558
  NegotiationClient: () => NegotiationClient,
9559
+ NegotiationError: () => NegotiationError,
9524
9560
  NegotiationRoomClient: () => NegotiationRoomClient,
9561
+ NegotiationRoomStoreError: () => NegotiationRoomStoreError,
9525
9562
  NegotiationTimeoutError: () => NegotiationTimeoutError,
9526
9563
  NegotiationValidationError: () => NegotiationValidationError,
9564
+ NoOpAuditor: () => NoOpAuditor,
9527
9565
  NodeStatus: () => NodeStatus,
9566
+ PeerSelector: () => PeerSelector,
9567
+ PermissionError: () => PermissionError,
9568
+ PersistentActivityBuffer: () => PersistentActivityBuffer,
9528
9569
  PersistentWorktreeState: () => PersistentWorktreeState,
9529
9570
  PolicyStoreError: () => PolicyStoreError,
9571
+ PolicyViolationError: () => PolicyViolationError,
9572
+ PreemptionError: () => PreemptionError,
9573
+ REGISTRATION_TYPE_STANDARD_AGENT: () => REGISTRATION_TYPE_STANDARD_AGENT,
9574
+ REGISTRATION_TYPE_SWARM_GATEWAY: () => REGISTRATION_TYPE_SWARM_GATEWAY,
9575
+ RETRY_AFTER_JITTER_RATIO: () => RETRY_AFTER_JITTER_RATIO,
9530
9576
  ReasoningClient: () => ReasoningClient,
9531
9577
  RegistryClient: () => RegistryClient,
9532
9578
  Resolver: () => Resolver,
9579
+ RouteError: () => RouteError,
9533
9580
  RouterClient: () => RouterClient,
9534
9581
  RuntimePersistence: () => RuntimePersistence,
9535
9582
  SchedulerClient: () => SchedulerClient,
@@ -9547,40 +9594,69 @@ __export(src_exports, {
9547
9594
  SimpleAverageAggregator: () => SimpleAverageAggregator,
9548
9595
  StateTransitionError: () => StateTransitionError,
9549
9596
  Sw4rmError: () => Sw4rmError,
9597
+ TimeoutError: () => TimeoutError,
9598
+ TokenBucket: () => TokenBucket,
9550
9599
  ToolClient: () => ToolClient,
9551
9600
  TriggerType: () => TriggerType,
9601
+ ValidationError: () => ValidationError,
9552
9602
  VotingAnalyzer: () => VotingAnalyzer,
9553
9603
  WorkflowClient: () => WorkflowClient,
9554
9604
  WorkflowCycleError: () => WorkflowCycleError,
9555
9605
  WorkflowStatus: () => WorkflowStatus,
9556
9606
  WorkflowValidationError: () => WorkflowValidationError,
9557
9607
  WorktreeClient: () => WorktreeClient,
9608
+ WorktreeError: () => WorktreeError,
9609
+ WorktreeStateEnum: () => WorktreeStateEnum,
9610
+ WorktreeTransitionError: () => WorktreeTransitionError,
9558
9611
  aggregateVotes: () => aggregateVotes,
9559
9612
  buildAckEnvelope: () => buildAckEnvelope,
9560
9613
  buildEnvelope: () => buildEnvelope,
9614
+ buildRateLimiterConfig: () => buildRateLimiterConfig,
9615
+ computeEnvelopeHash: () => computeEnvelopeHash,
9561
9616
  computeIdempotencyToken: () => computeIdempotencyToken,
9617
+ createLlmClient: () => createLlmClient,
9562
9618
  createResilientIncomingStream: () => createResilientIncomingStream,
9619
+ createSimpleProof: () => createSimpleProof,
9563
9620
  decodeAgentReportV1: () => decodeAgentReportV1,
9564
9621
  decodeBase64: () => decodeBase64,
9622
+ defaultAgentConfig: () => defaultAgentConfig,
9623
+ defaultEndpoints: () => defaultEndpoints,
9624
+ defaultRetryPolicy: () => defaultRetryPolicy,
9625
+ defaultSW4RMConfig: () => defaultSW4RMConfig,
9626
+ delegateToSwarm: () => delegateToSwarm,
9565
9627
  durationToMs: () => durationToMs,
9566
9628
  encodeSchedulerCommandV1: () => encodeSchedulerCommandV1,
9629
+ getConfig: () => getConfig,
9630
+ getDefaultStore: () => getDefaultStore,
9631
+ getGlobalRateLimiter: () => getGlobalRateLimiter,
9567
9632
  getValidTransitions: () => getValidTransitions,
9633
+ isTerminalEnvelopeState: () => isTerminalEnvelopeState,
9568
9634
  isValidTransition: () => isValidTransition,
9635
+ isValidWorktreeTransition: () => isValidWorktreeTransition,
9636
+ loadConfig: () => loadConfig,
9637
+ loadConfigFromEnv: () => loadConfigFromEnv,
9569
9638
  loggingInterceptor: () => loggingInterceptor,
9570
9639
  mapGrpcStatusToErrorCode: () => mapGrpcStatusToErrorCode,
9571
9640
  msToDuration: () => msToDuration,
9572
9641
  normalizeReportPaths: () => normalizeReportPaths,
9573
9642
  nowTimestamp: () => nowTimestamp,
9574
9643
  parseNegotiationEvent: () => parseNegotiationEvent,
9644
+ resetConfig: () => resetConfig,
9645
+ resetDefaultStore: () => resetDefaultStore,
9646
+ resetGlobalRateLimiter: () => resetGlobalRateLimiter,
9575
9647
  selectBackend: () => selectBackend,
9576
9648
  sendMessageWithAck: () => sendMessageWithAck,
9649
+ setConfig: () => setConfig,
9577
9650
  timingInterceptor: () => timingInterceptor,
9651
+ updateEnvelopeState: () => updateEnvelopeState,
9578
9652
  uuidv4: () => uuidv4,
9653
+ verifyAuditProof: () => verifyAuditProof,
9579
9654
  version: () => version
9580
9655
  });
9581
9656
  module.exports = __toCommonJS(src_exports);
9582
9657
 
9583
9658
  // src/internal/baseClient.ts
9659
+ var import_node_fs = __toESM(require("node:fs"), 1);
9584
9660
  var import_node_path = __toESM(require("node:path"), 1);
9585
9661
  var import_node_url = require("node:url");
9586
9662
  var grpc = __toESM(require("@grpc/grpc-js"), 1);
@@ -9602,6 +9678,10 @@ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
9602
9678
  ErrorCode2[ErrorCode2["PARTIAL_DELIVERY"] = 11] = "PARTIAL_DELIVERY";
9603
9679
  ErrorCode2[ErrorCode2["FORCED_PREEMPTION"] = 12] = "FORCED_PREEMPTION";
9604
9680
  ErrorCode2[ErrorCode2["TTL_EXPIRED"] = 13] = "TTL_EXPIRED";
9681
+ ErrorCode2[ErrorCode2["DUPLICATE_DETECTED"] = 14] = "DUPLICATE_DETECTED";
9682
+ ErrorCode2[ErrorCode2["ALREADY_IN_PROGRESS"] = 15] = "ALREADY_IN_PROGRESS";
9683
+ ErrorCode2[ErrorCode2["OVERLOADED"] = 16] = "OVERLOADED";
9684
+ ErrorCode2[ErrorCode2["REDIRECT"] = 20] = "REDIRECT";
9605
9685
  ErrorCode2[ErrorCode2["INTERNAL_ERROR"] = 99] = "INTERNAL_ERROR";
9606
9686
  return ErrorCode2;
9607
9687
  })(ErrorCode || {});
@@ -9617,6 +9697,54 @@ var Sw4rmError = class extends Error {
9617
9697
  this.details = opts?.details;
9618
9698
  }
9619
9699
  };
9700
+ var ValidationError = class extends Sw4rmError {
9701
+ constructor(message, code = 6 /* VALIDATION_ERROR */, opts) {
9702
+ super(message, code, opts);
9703
+ this.name = "ValidationError";
9704
+ }
9705
+ };
9706
+ var TimeoutError = class extends Sw4rmError {
9707
+ constructor(message, code = 3 /* ACK_TIMEOUT */, opts) {
9708
+ super(message, code, opts);
9709
+ this.name = "TimeoutError";
9710
+ }
9711
+ };
9712
+ var StateTransitionError = class extends Sw4rmError {
9713
+ constructor(message, code = 99 /* INTERNAL_ERROR */, opts) {
9714
+ super(message, code, opts);
9715
+ this.name = "StateTransitionError";
9716
+ }
9717
+ };
9718
+ var NegotiationError = class extends Sw4rmError {
9719
+ constructor(message, code = 99 /* INTERNAL_ERROR */, opts) {
9720
+ super(message, code, opts);
9721
+ this.name = "NegotiationError";
9722
+ }
9723
+ };
9724
+ var BufferFullError = class extends Sw4rmError {
9725
+ constructor(message, code = 1 /* BUFFER_FULL */, opts) {
9726
+ super(message, code, opts);
9727
+ this.name = "BufferFullError";
9728
+ }
9729
+ };
9730
+ var RouteError = class extends Sw4rmError {
9731
+ constructor(message, code = 2 /* NO_ROUTE */, opts) {
9732
+ super(message, code, opts);
9733
+ this.name = "RouteError";
9734
+ }
9735
+ };
9736
+ var PermissionError = class extends Sw4rmError {
9737
+ constructor(message, code = 7 /* PERMISSION_DENIED */, opts) {
9738
+ super(message, code, opts);
9739
+ this.name = "PermissionError";
9740
+ }
9741
+ };
9742
+ var DuplicateDetectedError = class extends Sw4rmError {
9743
+ constructor(message, code = 14 /* DUPLICATE_DETECTED */, opts) {
9744
+ super(message, code, opts);
9745
+ this.name = "DuplicateDetectedError";
9746
+ }
9747
+ };
9620
9748
  var GrpcStatus = {
9621
9749
  OK: 0,
9622
9750
  CANCELLED: 1,
@@ -9636,6 +9764,28 @@ var GrpcStatus = {
9636
9764
  DATA_LOSS: 15,
9637
9765
  UNAUTHENTICATED: 16
9638
9766
  };
9767
+ var PreemptionError = class extends Sw4rmError {
9768
+ agentId;
9769
+ reason;
9770
+ constructor(agentId, reason, code = 12 /* FORCED_PREEMPTION */, opts) {
9771
+ super(`Agent ${agentId} preempted: ${reason}`, code, opts);
9772
+ this.name = "PreemptionError";
9773
+ this.agentId = agentId;
9774
+ this.reason = reason;
9775
+ }
9776
+ };
9777
+ var WorktreeError = class extends Sw4rmError {
9778
+ constructor(message, code = 99 /* INTERNAL_ERROR */, opts) {
9779
+ super(message, code, opts);
9780
+ this.name = "WorktreeError";
9781
+ }
9782
+ };
9783
+ var PolicyViolationError = class extends Sw4rmError {
9784
+ constructor(message, code = 7 /* PERMISSION_DENIED */, opts) {
9785
+ super(message, code, opts);
9786
+ this.name = "PolicyViolationError";
9787
+ }
9788
+ };
9639
9789
  function mapGrpcStatusToErrorCode(status) {
9640
9790
  switch (status) {
9641
9791
  case GrpcStatus.OK:
@@ -9750,12 +9900,12 @@ var BaseClient = class {
9750
9900
  errorMapper = new ErrorCodeMapper();
9751
9901
  constructor(opts) {
9752
9902
  this.address = opts.address;
9753
- this.deadlineMs = opts.deadlineMs ?? 1e4;
9903
+ this.deadlineMs = opts.deadlineMs ?? 3e4;
9754
9904
  this.retry = opts.retry ?? { maxAttempts: 3, initialBackoffMs: 200, maxBackoffMs: 2e3, multiplier: 2 };
9755
9905
  this.userAgent = opts.userAgent ?? "sw4rm-js-sdk/0.1";
9756
9906
  const __filename = (0, import_node_url.fileURLToPath)(import_meta.url);
9757
9907
  const __dirname = import_node_path.default.dirname(__filename);
9758
- const protosDir = import_node_path.default.resolve(__dirname, "../../../../protos");
9908
+ const protosDir = this.resolveProtosDir(__dirname);
9759
9909
  const loaderOpts = {
9760
9910
  keepCase: true,
9761
9911
  longs: String,
@@ -9775,10 +9925,13 @@ var BaseClient = class {
9775
9925
  "tool.proto",
9776
9926
  "connector.proto",
9777
9927
  "negotiation.proto",
9928
+ "negotiation_room.proto",
9778
9929
  "reasoning.proto",
9779
9930
  "logging.proto",
9780
9931
  "policy.proto",
9781
- "activity.proto"
9932
+ "activity.proto",
9933
+ "handoff.proto",
9934
+ "workflow.proto"
9782
9935
  ], loaderOpts);
9783
9936
  this.root = grpc.loadPackageDefinition(this.pkgDef);
9784
9937
  this.interceptors.use(timingInterceptor());
@@ -9788,6 +9941,27 @@ var BaseClient = class {
9788
9941
  if (opts.errorMapper)
9789
9942
  opts.errorMapper(this.errorMapper);
9790
9943
  }
9944
+ /**
9945
+ * Resolves the protos directory, checking multiple locations:
9946
+ * 1. npm package: ./protos relative to package root
9947
+ * 2. Monorepo dev: ../../../../protos relative to this file
9948
+ */
9949
+ resolveProtosDir(dirname3) {
9950
+ const candidates = [
9951
+ // npm package structure: node_modules/@sw4rm/js-sdk/protos
9952
+ import_node_path.default.resolve(dirname3, "../../protos"),
9953
+ // Alternative npm structure: dist/esm/internal -> protos
9954
+ import_node_path.default.resolve(dirname3, "../../../protos"),
9955
+ // Monorepo development: sdks/js_sdk/src/internal -> protos
9956
+ import_node_path.default.resolve(dirname3, "../../../../protos")
9957
+ ];
9958
+ for (const candidate of candidates) {
9959
+ if (import_node_fs.default.existsSync(candidate) && import_node_fs.default.existsSync(import_node_path.default.join(candidate, "common.proto"))) {
9960
+ return candidate;
9961
+ }
9962
+ }
9963
+ return candidates[candidates.length - 1];
9964
+ }
9791
9965
  channelCredentials() {
9792
9966
  return grpc.credentials.createInsecure();
9793
9967
  }
@@ -10375,6 +10549,95 @@ var RegistryClient = class extends BaseClient {
10375
10549
  }
10376
10550
  };
10377
10551
 
10552
+ // src/clients/negotiationRoomStore.ts
10553
+ var NegotiationRoomStoreError = class extends Error {
10554
+ constructor(message) {
10555
+ super(message);
10556
+ this.name = "NegotiationRoomStoreError";
10557
+ }
10558
+ };
10559
+ var InMemoryNegotiationRoomStore = class {
10560
+ proposals = /* @__PURE__ */ new Map();
10561
+ votes = /* @__PURE__ */ new Map();
10562
+ decisions = /* @__PURE__ */ new Map();
10563
+ async hasProposal(artifactId) {
10564
+ return this.proposals.has(artifactId);
10565
+ }
10566
+ async getProposal(artifactId) {
10567
+ return this.proposals.get(artifactId) || null;
10568
+ }
10569
+ async saveProposal(proposal) {
10570
+ const artifactId = proposal.artifactId;
10571
+ if (this.proposals.has(artifactId)) {
10572
+ throw new NegotiationRoomStoreError(
10573
+ `Proposal with artifact_id '${artifactId}' already exists`
10574
+ );
10575
+ }
10576
+ const proposalWithTimestamp = {
10577
+ ...proposal,
10578
+ createdAt: proposal.createdAt || (/* @__PURE__ */ new Date()).toISOString()
10579
+ };
10580
+ this.proposals.set(artifactId, proposalWithTimestamp);
10581
+ this.votes.set(artifactId, []);
10582
+ }
10583
+ async listProposals(negotiationRoomId) {
10584
+ const allProposals = Array.from(this.proposals.values());
10585
+ if (negotiationRoomId === void 0) {
10586
+ return allProposals;
10587
+ }
10588
+ return allProposals.filter((p) => p.negotiationRoomId === negotiationRoomId);
10589
+ }
10590
+ async getVotes(artifactId) {
10591
+ return [...this.votes.get(artifactId) || []];
10592
+ }
10593
+ async addVote(vote) {
10594
+ const artifactId = vote.artifactId;
10595
+ const criticId = vote.criticId;
10596
+ const existingVotes = this.votes.get(artifactId) || [];
10597
+ for (const existingVote of existingVotes) {
10598
+ if (existingVote.criticId === criticId) {
10599
+ throw new NegotiationRoomStoreError(
10600
+ `Critic '${criticId}' has already voted for artifact '${artifactId}'`
10601
+ );
10602
+ }
10603
+ }
10604
+ const voteWithTimestamp = {
10605
+ ...vote,
10606
+ votedAt: vote.votedAt || (/* @__PURE__ */ new Date()).toISOString()
10607
+ };
10608
+ if (!this.votes.has(artifactId)) {
10609
+ this.votes.set(artifactId, []);
10610
+ }
10611
+ this.votes.get(artifactId).push(voteWithTimestamp);
10612
+ }
10613
+ async getDecision(artifactId) {
10614
+ return this.decisions.get(artifactId) || null;
10615
+ }
10616
+ async saveDecision(decision) {
10617
+ const artifactId = decision.artifactId;
10618
+ if (this.decisions.has(artifactId)) {
10619
+ throw new NegotiationRoomStoreError(
10620
+ `Decision already exists for artifact_id '${artifactId}'`
10621
+ );
10622
+ }
10623
+ const decisionWithTimestamp = {
10624
+ ...decision,
10625
+ decidedAt: decision.decidedAt || (/* @__PURE__ */ new Date()).toISOString()
10626
+ };
10627
+ this.decisions.set(artifactId, decisionWithTimestamp);
10628
+ }
10629
+ };
10630
+ var defaultStore = null;
10631
+ function getDefaultStore() {
10632
+ if (defaultStore === null) {
10633
+ defaultStore = new InMemoryNegotiationRoomStore();
10634
+ }
10635
+ return defaultStore;
10636
+ }
10637
+ function resetDefaultStore() {
10638
+ defaultStore = null;
10639
+ }
10640
+
10378
10641
  // src/clients/negotiationRoom.ts
10379
10642
  var ArtifactType = /* @__PURE__ */ ((ArtifactType2) => {
10380
10643
  ArtifactType2[ArtifactType2["ARTIFACT_TYPE_UNSPECIFIED"] = 0] = "ARTIFACT_TYPE_UNSPECIFIED";
@@ -10416,9 +10679,16 @@ function validateVote(vote) {
10416
10679
  }
10417
10680
  }
10418
10681
  var NegotiationRoomClient = class {
10419
- proposals = /* @__PURE__ */ new Map();
10420
- votes = /* @__PURE__ */ new Map();
10421
- decisions = /* @__PURE__ */ new Map();
10682
+ store;
10683
+ /**
10684
+ * Create a new negotiation room client.
10685
+ *
10686
+ * @param options - Configuration options. If no store is provided,
10687
+ * uses the shared default in-memory store.
10688
+ */
10689
+ constructor(options = {}) {
10690
+ this.store = options.store || getDefaultStore();
10691
+ }
10422
10692
  /**
10423
10693
  * Submit an artifact proposal for multi-agent review.
10424
10694
  *
@@ -10446,19 +10716,8 @@ var NegotiationRoomClient = class {
10446
10716
  * ```
10447
10717
  */
10448
10718
  async submitProposal(proposal) {
10449
- const artifactId = proposal.artifactId;
10450
- if (this.proposals.has(artifactId)) {
10451
- throw new NegotiationValidationError(
10452
- `Proposal with artifact_id '${artifactId}' already exists`
10453
- );
10454
- }
10455
- const proposalWithTimestamp = {
10456
- ...proposal,
10457
- createdAt: proposal.createdAt || (/* @__PURE__ */ new Date()).toISOString()
10458
- };
10459
- this.proposals.set(artifactId, proposalWithTimestamp);
10460
- this.votes.set(artifactId, []);
10461
- return artifactId;
10719
+ await this.store.saveProposal(proposal);
10720
+ return proposal.artifactId;
10462
10721
  }
10463
10722
  /**
10464
10723
  * Submit a critic's vote for an artifact.
@@ -10490,26 +10749,13 @@ var NegotiationRoomClient = class {
10490
10749
  */
10491
10750
  async submitVote(vote) {
10492
10751
  const artifactId = vote.artifactId;
10493
- if (!this.proposals.has(artifactId)) {
10752
+ if (!await this.store.hasProposal(artifactId)) {
10494
10753
  throw new NegotiationValidationError(
10495
10754
  `No proposal found for artifact_id '${artifactId}'`
10496
10755
  );
10497
10756
  }
10498
10757
  validateVote(vote);
10499
- const existingVotes = this.votes.get(artifactId) || [];
10500
- for (const existingVote of existingVotes) {
10501
- if (existingVote.criticId === vote.criticId) {
10502
- throw new NegotiationValidationError(
10503
- `Critic '${vote.criticId}' has already voted for artifact '${artifactId}'`
10504
- );
10505
- }
10506
- }
10507
- const voteWithTimestamp = {
10508
- ...vote,
10509
- votedAt: vote.votedAt || (/* @__PURE__ */ new Date()).toISOString()
10510
- };
10511
- existingVotes.push(voteWithTimestamp);
10512
- this.votes.set(artifactId, existingVotes);
10758
+ await this.store.addVote(vote);
10513
10759
  }
10514
10760
  /**
10515
10761
  * Retrieve all votes for a specific artifact.
@@ -10529,12 +10775,12 @@ var NegotiationRoomClient = class {
10529
10775
  * ```
10530
10776
  */
10531
10777
  async getVotes(artifactId) {
10532
- if (!this.proposals.has(artifactId)) {
10778
+ if (!await this.store.hasProposal(artifactId)) {
10533
10779
  throw new NegotiationValidationError(
10534
10780
  `No proposal found for artifact_id '${artifactId}'`
10535
10781
  );
10536
10782
  }
10537
- return this.votes.get(artifactId) || [];
10783
+ return this.store.getVotes(artifactId);
10538
10784
  }
10539
10785
  /**
10540
10786
  * Retrieve the decision for a specific artifact if available.
@@ -10555,12 +10801,12 @@ var NegotiationRoomClient = class {
10555
10801
  * ```
10556
10802
  */
10557
10803
  async getDecision(artifactId) {
10558
- if (!this.proposals.has(artifactId)) {
10804
+ if (!await this.store.hasProposal(artifactId)) {
10559
10805
  throw new NegotiationValidationError(
10560
10806
  `No proposal found for artifact_id '${artifactId}'`
10561
10807
  );
10562
10808
  }
10563
- return this.decisions.get(artifactId) || null;
10809
+ return this.store.getDecision(artifactId);
10564
10810
  }
10565
10811
  /**
10566
10812
  * Store a decision for an artifact.
@@ -10591,21 +10837,12 @@ var NegotiationRoomClient = class {
10591
10837
  */
10592
10838
  async storeDecision(decision) {
10593
10839
  const artifactId = decision.artifactId;
10594
- if (!this.proposals.has(artifactId)) {
10840
+ if (!await this.store.hasProposal(artifactId)) {
10595
10841
  throw new NegotiationValidationError(
10596
10842
  `No proposal found for artifact_id '${artifactId}'`
10597
10843
  );
10598
10844
  }
10599
- if (this.decisions.has(artifactId)) {
10600
- throw new NegotiationValidationError(
10601
- `Decision already exists for artifact_id '${artifactId}'`
10602
- );
10603
- }
10604
- const decisionWithTimestamp = {
10605
- ...decision,
10606
- decidedAt: decision.decidedAt || (/* @__PURE__ */ new Date()).toISOString()
10607
- };
10608
- this.decisions.set(artifactId, decisionWithTimestamp);
10845
+ await this.store.saveDecision(decision);
10609
10846
  }
10610
10847
  /**
10611
10848
  * Wait for a decision to be made on an artifact.
@@ -10629,14 +10866,14 @@ var NegotiationRoomClient = class {
10629
10866
  * ```
10630
10867
  */
10631
10868
  async waitForDecision(artifactId, timeoutMs = 3e4, pollIntervalMs = 100) {
10632
- if (!this.proposals.has(artifactId)) {
10869
+ if (!await this.store.hasProposal(artifactId)) {
10633
10870
  throw new NegotiationValidationError(
10634
10871
  `No proposal found for artifact_id '${artifactId}'`
10635
10872
  );
10636
10873
  }
10637
10874
  const startTime = Date.now();
10638
10875
  while (Date.now() - startTime < timeoutMs) {
10639
- const decision = await this.getDecision(artifactId);
10876
+ const decision = await this.store.getDecision(artifactId);
10640
10877
  if (decision !== null) {
10641
10878
  return decision;
10642
10879
  }
@@ -10662,7 +10899,7 @@ var NegotiationRoomClient = class {
10662
10899
  * ```
10663
10900
  */
10664
10901
  async getProposal(artifactId) {
10665
- return this.proposals.get(artifactId) || null;
10902
+ return this.store.getProposal(artifactId);
10666
10903
  }
10667
10904
  /**
10668
10905
  * List all proposals, optionally filtered by negotiation room.
@@ -10677,13 +10914,7 @@ var NegotiationRoomClient = class {
10677
10914
  * ```
10678
10915
  */
10679
10916
  async listProposals(negotiationRoomId) {
10680
- const allProposals = Array.from(this.proposals.values());
10681
- if (negotiationRoomId === void 0) {
10682
- return allProposals;
10683
- }
10684
- return allProposals.filter(
10685
- (p) => p.negotiationRoomId === negotiationRoomId
10686
- );
10917
+ return this.store.listProposals(negotiationRoomId);
10687
10918
  }
10688
10919
  };
10689
10920
  function aggregateVotes(votes) {
@@ -10726,6 +10957,38 @@ var HandoffStatus = /* @__PURE__ */ ((HandoffStatus2) => {
10726
10957
  HandoffStatus2[HandoffStatus2["EXPIRED"] = 5] = "EXPIRED";
10727
10958
  return HandoffStatus2;
10728
10959
  })(HandoffStatus || {});
10960
+ var DEFAULT_MAX_RETRIES_ON_OVERLOADED = 2;
10961
+ var DEFAULT_INITIAL_BACKOFF_MS = 250;
10962
+ var DEFAULT_BACKOFF_MULTIPLIER = 2;
10963
+ var DEFAULT_MAX_BACKOFF_MS = 2e3;
10964
+ var DEFAULT_MAX_REDIRECTS = 0;
10965
+ function defaultDelegationPolicy() {
10966
+ return {
10967
+ maxRetriesOnOverloaded: DEFAULT_MAX_RETRIES_ON_OVERLOADED,
10968
+ initialBackoffMs: DEFAULT_INITIAL_BACKOFF_MS,
10969
+ backoffMultiplier: DEFAULT_BACKOFF_MULTIPLIER,
10970
+ maxBackoffMs: DEFAULT_MAX_BACKOFF_MS,
10971
+ allowSpilloverRouting: false,
10972
+ maxRedirects: DEFAULT_MAX_REDIRECTS
10973
+ };
10974
+ }
10975
+ function normalizeDelegationPolicy(policy) {
10976
+ const defaults = defaultDelegationPolicy();
10977
+ const maxRetriesOnOverloaded = policy?.maxRetriesOnOverloaded;
10978
+ const initialBackoffMs = policy?.initialBackoffMs;
10979
+ const backoffMultiplier = policy?.backoffMultiplier;
10980
+ const maxBackoffMs = policy?.maxBackoffMs;
10981
+ const allowSpilloverRouting = policy?.allowSpilloverRouting;
10982
+ const maxRedirects = policy?.maxRedirects;
10983
+ return {
10984
+ maxRetriesOnOverloaded: maxRetriesOnOverloaded === void 0 ? defaults.maxRetriesOnOverloaded : maxRetriesOnOverloaded,
10985
+ initialBackoffMs: initialBackoffMs !== void 0 && initialBackoffMs > 0 ? initialBackoffMs : defaults.initialBackoffMs,
10986
+ backoffMultiplier: backoffMultiplier !== void 0 && backoffMultiplier > 0 ? backoffMultiplier : defaults.backoffMultiplier,
10987
+ maxBackoffMs: maxBackoffMs !== void 0 && maxBackoffMs > 0 ? maxBackoffMs : defaults.maxBackoffMs,
10988
+ allowSpilloverRouting: allowSpilloverRouting ?? defaults.allowSpilloverRouting,
10989
+ maxRedirects: maxRedirects === void 0 ? defaults.maxRedirects : maxRedirects
10990
+ };
10991
+ }
10729
10992
  var HandoffValidationError = class extends Error {
10730
10993
  constructor(message) {
10731
10994
  super(message);
@@ -10774,9 +11037,15 @@ var HandoffClient = class {
10774
11037
  `Handoff request with ID '${request.requestId}' already exists`
10775
11038
  );
10776
11039
  }
11040
+ if (request.budget !== void 0 && (!request.budget.deadlineEpochMs || request.budget.deadlineEpochMs <= 0)) {
11041
+ throw new HandoffValidationError(
11042
+ "budget.deadlineEpochMs is required for cross-swarm delegation"
11043
+ );
11044
+ }
10777
11045
  const requestWithTimestamp = {
10778
11046
  ...request,
10779
- createdAt: request.createdAt || (/* @__PURE__ */ new Date()).toISOString()
11047
+ createdAt: request.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
11048
+ delegationPolicy: request.budget !== void 0 || request.delegationPolicy !== void 0 ? normalizeDelegationPolicy(request.delegationPolicy) : void 0
10780
11049
  };
10781
11050
  this.requests.set(request.requestId, requestWithTimestamp);
10782
11051
  if (request.toAgent) {
@@ -10798,7 +11067,8 @@ var HandoffClient = class {
10798
11067
  const timeoutResponse = {
10799
11068
  requestId: request.requestId,
10800
11069
  accepted: false,
10801
- rejectionReason: `Handoff request timed out after ${timeoutMs}ms`
11070
+ rejectionReason: `Handoff request timed out after ${timeoutMs}ms`,
11071
+ rejectionCode: 3 /* ACK_TIMEOUT */
10802
11072
  };
10803
11073
  this.responses.set(request.requestId, timeoutResponse);
10804
11074
  if (request.toAgent && this.pendingByAgent.has(request.toAgent)) {
@@ -10863,7 +11133,7 @@ var HandoffClient = class {
10863
11133
  * await client.rejectHandoff("handoff-123", "Agent at capacity");
10864
11134
  * ```
10865
11135
  */
10866
- async rejectHandoff(handoffId, reason) {
11136
+ async rejectHandoff(handoffId, reason, options) {
10867
11137
  const request = this.requests.get(handoffId);
10868
11138
  if (!request) {
10869
11139
  throw new HandoffValidationError(
@@ -10878,7 +11148,10 @@ var HandoffClient = class {
10878
11148
  const response = {
10879
11149
  requestId: handoffId,
10880
11150
  accepted: false,
10881
- rejectionReason: reason
11151
+ rejectionReason: reason,
11152
+ rejectionCode: options?.rejectionCode ?? 0 /* ERROR_CODE_UNSPECIFIED */,
11153
+ retryAfterMs: options?.retryAfterMs,
11154
+ redirectToAgentId: options?.redirectToAgentId
10882
11155
  };
10883
11156
  this.responses.set(handoffId, response);
10884
11157
  if (request.toAgent && this.pendingByAgent.has(request.toAgent)) {
@@ -11311,6 +11584,31 @@ var WorkflowClient = class {
11311
11584
  instance.completedAt = (/* @__PURE__ */ new Date()).toISOString();
11312
11585
  }
11313
11586
  }
11587
+ /**
11588
+ * Resume a workflow by marking a node as completed and advancing dependents.
11589
+ *
11590
+ * Implements the ResumeWorkflow RPC (spec §17.7 MUST). Marks the specified
11591
+ * node as COMPLETED, updates workflow data if provided, then transitions
11592
+ * dependent nodes from PENDING to READY when all their dependencies are met.
11593
+ *
11594
+ * @param instanceId - The ID of the workflow instance
11595
+ * @param nodeId - The ID of the node to mark as completed
11596
+ * @param workflowData - Optional updated workflow data (JSON string)
11597
+ * @param metadata - Optional metadata for the resume operation
11598
+ * @returns The updated workflow instance
11599
+ * @throws WorkflowValidationError if the instance or node does not exist
11600
+ */
11601
+ async resumeWorkflow(instanceId, nodeId, workflowData, metadata) {
11602
+ await this.updateNodeState(instanceId, nodeId, 4 /* COMPLETED */);
11603
+ if (workflowData !== void 0) {
11604
+ await this.updateWorkflowData(instanceId, workflowData);
11605
+ }
11606
+ if (metadata) {
11607
+ const instance = this.instances.get(instanceId);
11608
+ Object.assign(instance.metadata, metadata);
11609
+ }
11610
+ return this.getWorkflowStatus(instanceId);
11611
+ }
11314
11612
  /**
11315
11613
  * Update the shared workflow data.
11316
11614
  *
@@ -11332,6 +11630,21 @@ var WorkflowClient = class {
11332
11630
 
11333
11631
  // src/internal/envelope.ts
11334
11632
  var import_node_crypto2 = __toESM(require("node:crypto"), 1);
11633
+ var MessageType = /* @__PURE__ */ ((MessageType2) => {
11634
+ MessageType2[MessageType2["MESSAGE_TYPE_UNSPECIFIED"] = 0] = "MESSAGE_TYPE_UNSPECIFIED";
11635
+ MessageType2[MessageType2["CONTROL"] = 1] = "CONTROL";
11636
+ MessageType2[MessageType2["DATA"] = 2] = "DATA";
11637
+ MessageType2[MessageType2["HEARTBEAT"] = 3] = "HEARTBEAT";
11638
+ MessageType2[MessageType2["NOTIFICATION"] = 4] = "NOTIFICATION";
11639
+ MessageType2[MessageType2["ACKNOWLEDGEMENT"] = 5] = "ACKNOWLEDGEMENT";
11640
+ MessageType2[MessageType2["HITL_INVOCATION"] = 6] = "HITL_INVOCATION";
11641
+ MessageType2[MessageType2["WORKTREE_CONTROL"] = 7] = "WORKTREE_CONTROL";
11642
+ MessageType2[MessageType2["NEGOTIATION"] = 8] = "NEGOTIATION";
11643
+ MessageType2[MessageType2["TOOL_CALL"] = 9] = "TOOL_CALL";
11644
+ MessageType2[MessageType2["TOOL_RESULT"] = 10] = "TOOL_RESULT";
11645
+ MessageType2[MessageType2["TOOL_ERROR"] = 11] = "TOOL_ERROR";
11646
+ return MessageType2;
11647
+ })(MessageType || {});
11335
11648
  function nowTimestamp(date = /* @__PURE__ */ new Date()) {
11336
11649
  const ms = date.getTime();
11337
11650
  const seconds = Math.floor(ms / 1e3);
@@ -11339,7 +11652,15 @@ function nowTimestamp(date = /* @__PURE__ */ new Date()) {
11339
11652
  return { seconds, nanos };
11340
11653
  }
11341
11654
  function nowHlcStub(date = /* @__PURE__ */ new Date()) {
11342
- return String(date.getTime());
11655
+ const wallUs = date.getTime() * 1e3;
11656
+ let node = "unknown";
11657
+ try {
11658
+ const os3 = require("node:os");
11659
+ node = os3.hostname() || "unknown";
11660
+ } catch {
11661
+ node = "browser";
11662
+ }
11663
+ return `HLC:${wallUs}:0:${node}`;
11343
11664
  }
11344
11665
  function uuidv42() {
11345
11666
  if (typeof import_node_crypto2.default.randomUUID === "function") {
@@ -11375,7 +11696,12 @@ function buildEnvelope(input) {
11375
11696
  hlc_timestamp,
11376
11697
  // Always set hlc_timestamp (aligns with Python/Rust)
11377
11698
  ttl_ms: input.ttl_ms,
11378
- timestamp: ts
11699
+ timestamp: ts,
11700
+ state: input.state ?? 1,
11701
+ // EnvelopeState.CREATED
11702
+ effective_policy_id: input.effective_policy_id ?? "",
11703
+ audit_proof: input.audit_proof ?? new Uint8Array(0),
11704
+ audit_policy_id: input.audit_policy_id ?? ""
11379
11705
  };
11380
11706
  if (hasPayload) {
11381
11707
  const payload = input.payload instanceof Uint8Array ? input.payload : new Uint8Array(input.payload);
@@ -11389,25 +11715,141 @@ function buildEnvelope(input) {
11389
11715
  }
11390
11716
 
11391
11717
  // src/internal/worktreeState.ts
11718
+ var VALID_WORKTREE_TRANSITIONS = {
11719
+ UNBOUND: ["BOUND_HOME", "BIND_FAILED"],
11720
+ BOUND_HOME: ["SWITCH_PENDING", "UNBOUND"],
11721
+ SWITCH_PENDING: ["BOUND_NON_HOME", "BOUND_HOME"],
11722
+ // approve or reject
11723
+ BOUND_NON_HOME: ["BOUND_HOME", "UNBOUND"],
11724
+ // TTL expired/revoke, or unbind
11725
+ BIND_FAILED: ["UNBOUND", "BOUND_HOME"]
11726
+ // retry reset or successful retry
11727
+ };
11728
+ function isValidWorktreeTransition(from, to) {
11729
+ return VALID_WORKTREE_TRANSITIONS[from]?.includes(to) ?? false;
11730
+ }
11731
+ var WorktreeTransitionError = class extends Error {
11732
+ fromState;
11733
+ toState;
11734
+ constructor(from, to) {
11735
+ super(`Invalid worktree state transition from ${from} to ${to}`);
11736
+ this.name = "WorktreeTransitionError";
11737
+ this.fromState = from;
11738
+ this.toState = to;
11739
+ }
11740
+ };
11392
11741
  var PersistentWorktreeState = class {
11393
11742
  state = "UNBOUND";
11394
11743
  repoId;
11395
11744
  worktreeId;
11745
+ homeRepoId;
11746
+ homeWorktreeId;
11747
+ switchTtlMs;
11748
+ switchTimer;
11749
+ /**
11750
+ * Transition to a new state with validation.
11751
+ * @throws WorktreeTransitionError if transition is invalid
11752
+ */
11753
+ transitionTo(newState) {
11754
+ if (!isValidWorktreeTransition(this.state, newState)) {
11755
+ throw new WorktreeTransitionError(this.state, newState);
11756
+ }
11757
+ this.state = newState;
11758
+ }
11759
+ /**
11760
+ * Bind to a home worktree (UNBOUND -> BOUND_HOME or BIND_FAILED -> BOUND_HOME).
11761
+ */
11396
11762
  bind(repoId, worktreeId) {
11763
+ this.transitionTo("BOUND_HOME");
11397
11764
  this.repoId = repoId;
11398
11765
  this.worktreeId = worktreeId;
11399
- this.state = "BOUND_HOME";
11766
+ this.homeRepoId = repoId;
11767
+ this.homeWorktreeId = worktreeId;
11768
+ }
11769
+ /**
11770
+ * Handle bind failure (UNBOUND -> BIND_FAILED).
11771
+ */
11772
+ bindFailed() {
11773
+ this.transitionTo("BIND_FAILED");
11400
11774
  }
11775
+ /**
11776
+ * Unbind from current worktree.
11777
+ */
11401
11778
  unbind() {
11779
+ this.clearSwitchTimer();
11780
+ this.transitionTo("UNBOUND");
11402
11781
  this.repoId = void 0;
11403
11782
  this.worktreeId = void 0;
11404
- this.state = "UNBOUND";
11783
+ }
11784
+ /**
11785
+ * Request switch to a non-home worktree (BOUND_HOME -> SWITCH_PENDING).
11786
+ * Requires approval or rejection before taking effect.
11787
+ */
11788
+ requestSwitch(targetRepoId, targetWorktreeId) {
11789
+ this.transitionTo("SWITCH_PENDING");
11790
+ this._pendingRepoId = targetRepoId;
11791
+ this._pendingWorktreeId = targetWorktreeId;
11792
+ }
11793
+ /**
11794
+ * Approve a pending switch (SWITCH_PENDING -> BOUND_NON_HOME).
11795
+ * @param ttlMs - Time-to-live in milliseconds before auto-reverting to BOUND_HOME
11796
+ */
11797
+ approveSwitch(ttlMs = 3e5) {
11798
+ this.transitionTo("BOUND_NON_HOME");
11799
+ this.repoId = this._pendingRepoId;
11800
+ this.worktreeId = this._pendingWorktreeId;
11801
+ this.switchTtlMs = ttlMs;
11802
+ this.clearSwitchTimer();
11803
+ this.switchTimer = setTimeout(() => {
11804
+ this.revertToHome();
11805
+ }, ttlMs);
11806
+ }
11807
+ /**
11808
+ * Reject a pending switch (SWITCH_PENDING -> BOUND_HOME).
11809
+ */
11810
+ rejectSwitch() {
11811
+ this.transitionTo("BOUND_HOME");
11812
+ this.repoId = this.homeRepoId;
11813
+ this.worktreeId = this.homeWorktreeId;
11814
+ delete this._pendingRepoId;
11815
+ delete this._pendingWorktreeId;
11816
+ }
11817
+ /**
11818
+ * Revert from non-home to home worktree (BOUND_NON_HOME -> BOUND_HOME).
11819
+ * Called on TTL expiry or explicit revoke.
11820
+ */
11821
+ revertToHome() {
11822
+ this.clearSwitchTimer();
11823
+ if (this.state === "BOUND_NON_HOME") {
11824
+ this.transitionTo("BOUND_HOME");
11825
+ this.repoId = this.homeRepoId;
11826
+ this.worktreeId = this.homeWorktreeId;
11827
+ }
11828
+ }
11829
+ /**
11830
+ * Reset from BIND_FAILED to UNBOUND for retry.
11831
+ */
11832
+ resetFromFailed() {
11833
+ this.transitionTo("UNBOUND");
11834
+ }
11835
+ clearSwitchTimer() {
11836
+ if (this.switchTimer) {
11837
+ clearTimeout(this.switchTimer);
11838
+ this.switchTimer = void 0;
11839
+ }
11405
11840
  }
11406
11841
  setState(state) {
11407
11842
  this.state = state;
11408
11843
  }
11409
11844
  current() {
11410
- return { state: this.state, repo_id: this.repoId, worktree_id: this.worktreeId };
11845
+ return {
11846
+ state: this.state,
11847
+ repo_id: this.repoId,
11848
+ worktree_id: this.worktreeId,
11849
+ home_repo_id: this.homeRepoId,
11850
+ home_worktree_id: this.homeWorktreeId,
11851
+ switch_ttl_ms: this.switchTtlMs
11852
+ };
11411
11853
  }
11412
11854
  };
11413
11855
 
@@ -11469,16 +11911,6 @@ var ActivityBuffer = class {
11469
11911
  };
11470
11912
 
11471
11913
  // src/internal/runtime/ackLifecycle.ts
11472
- var AckStage = /* @__PURE__ */ ((AckStage2) => {
11473
- AckStage2[AckStage2["ACK_STAGE_UNSPECIFIED"] = 0] = "ACK_STAGE_UNSPECIFIED";
11474
- AckStage2[AckStage2["RECEIVED"] = 1] = "RECEIVED";
11475
- AckStage2[AckStage2["READ"] = 2] = "READ";
11476
- AckStage2[AckStage2["FULFILLED"] = 3] = "FULFILLED";
11477
- AckStage2[AckStage2["REJECTED"] = 4] = "REJECTED";
11478
- AckStage2[AckStage2["FAILED"] = 5] = "FAILED";
11479
- AckStage2[AckStage2["TIMED_OUT"] = 6] = "TIMED_OUT";
11480
- return AckStage2;
11481
- })(AckStage || {});
11482
11914
  var ACKLifecycleManager = class {
11483
11915
  acks = /* @__PURE__ */ new Map();
11484
11916
  mark(messageId, stage, note, errorCode) {
@@ -11515,21 +11947,6 @@ var ACKLifecycleManager = class {
11515
11947
  };
11516
11948
 
11517
11949
  // src/internal/runtime/messageProcessor.ts
11518
- var MessageType = /* @__PURE__ */ ((MessageType3) => {
11519
- MessageType3[MessageType3["MESSAGE_TYPE_UNSPECIFIED"] = 0] = "MESSAGE_TYPE_UNSPECIFIED";
11520
- MessageType3[MessageType3["CONTROL"] = 1] = "CONTROL";
11521
- MessageType3[MessageType3["DATA"] = 2] = "DATA";
11522
- MessageType3[MessageType3["HEARTBEAT"] = 3] = "HEARTBEAT";
11523
- MessageType3[MessageType3["NOTIFICATION"] = 4] = "NOTIFICATION";
11524
- MessageType3[MessageType3["ACKNOWLEDGEMENT"] = 5] = "ACKNOWLEDGEMENT";
11525
- MessageType3[MessageType3["HITL_INVOCATION"] = 6] = "HITL_INVOCATION";
11526
- MessageType3[MessageType3["WORKTREE_CONTROL"] = 7] = "WORKTREE_CONTROL";
11527
- MessageType3[MessageType3["NEGOTIATION"] = 8] = "NEGOTIATION";
11528
- MessageType3[MessageType3["TOOL_CALL"] = 9] = "TOOL_CALL";
11529
- MessageType3[MessageType3["TOOL_RESULT"] = 10] = "TOOL_RESULT";
11530
- MessageType3[MessageType3["TOOL_ERROR"] = 11] = "TOOL_ERROR";
11531
- return MessageType3;
11532
- })(MessageType || {});
11533
11950
  var MessageProcessor = class {
11534
11951
  handlers = /* @__PURE__ */ new Map();
11535
11952
  defaultHandler;
@@ -11696,35 +12113,571 @@ function decodeBase64(b64) {
11696
12113
  return new Uint8Array(Buffer.from(b64, "base64"));
11697
12114
  }
11698
12115
 
11699
- // src/persistence/persistence.ts
11700
- var import_promises = __toESM(require("node:fs/promises"), 1);
11701
- var import_node_path2 = __toESM(require("node:path"), 1);
11702
- var JSONFilePersistence = class {
11703
- constructor(baseDir) {
11704
- this.baseDir = baseDir;
11705
- this.activityFile = import_node_path2.default.join(baseDir, "activity.json");
11706
- this.acksFile = import_node_path2.default.join(baseDir, "acks.json");
12116
+ // src/runtime/delegation.ts
12117
+ var import_node_crypto3 = require("node:crypto");
12118
+ var RETRY_AFTER_JITTER_RATIO = 0.2;
12119
+ var DEFAULT_EFFECTIVE_MAX_REDIRECTS = 2;
12120
+ function defaultNowMs() {
12121
+ return Date.now();
12122
+ }
12123
+ function defaultSleepMs(milliseconds) {
12124
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
12125
+ }
12126
+ function defaultRandUniform(low, high) {
12127
+ if (high <= low) {
12128
+ return low;
11707
12129
  }
11708
- activityFile;
11709
- acksFile;
11710
- async safeWrite(file, data) {
11711
- await import_promises.default.mkdir(import_node_path2.default.dirname(file), { recursive: true });
11712
- const tmp = `${file}.tmp-${Date.now()}`;
11713
- await import_promises.default.writeFile(tmp, data, "utf8");
11714
- await import_promises.default.rename(tmp, file);
12130
+ return low + Math.random() * (high - low);
12131
+ }
12132
+ function normalizePolicy(policy) {
12133
+ return {
12134
+ maxRetriesOnOverloaded: policy?.maxRetriesOnOverloaded ?? DEFAULT_MAX_RETRIES_ON_OVERLOADED,
12135
+ initialBackoffMs: policy?.initialBackoffMs !== void 0 && policy.initialBackoffMs > 0 ? policy.initialBackoffMs : DEFAULT_INITIAL_BACKOFF_MS,
12136
+ backoffMultiplier: policy?.backoffMultiplier !== void 0 && policy.backoffMultiplier > 0 ? policy.backoffMultiplier : DEFAULT_BACKOFF_MULTIPLIER,
12137
+ maxBackoffMs: policy?.maxBackoffMs !== void 0 && policy.maxBackoffMs > 0 ? policy.maxBackoffMs : DEFAULT_MAX_BACKOFF_MS,
12138
+ allowSpilloverRouting: policy?.allowSpilloverRouting ?? false,
12139
+ maxRedirects: policy?.maxRedirects ?? DEFAULT_MAX_REDIRECTS
12140
+ };
12141
+ }
12142
+ function deadlineExhaustedResponse(requestId) {
12143
+ return {
12144
+ requestId,
12145
+ accepted: false,
12146
+ rejectionReason: "Delegation deadline exhausted before handoff acceptance",
12147
+ rejectionCode: 3 /* ACK_TIMEOUT */
12148
+ };
12149
+ }
12150
+ function invalidRedirectResponse(requestId, reason) {
12151
+ return {
12152
+ requestId,
12153
+ accepted: false,
12154
+ rejectionReason: reason,
12155
+ rejectionCode: 6 /* VALIDATION_ERROR */
12156
+ };
12157
+ }
12158
+ function effectiveMaxRedirects(policy) {
12159
+ const configured = policy.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
12160
+ return configured > 0 ? configured : DEFAULT_EFFECTIVE_MAX_REDIRECTS;
12161
+ }
12162
+ function nextRetryWaitMs(response, retryIndex, policy, randUniformFn) {
12163
+ if (response.retryAfterMs !== void 0 && response.retryAfterMs > 0) {
12164
+ const retryAfter = response.retryAfterMs;
12165
+ const jitter = randUniformFn(0, retryAfter * RETRY_AFTER_JITTER_RATIO);
12166
+ return Math.floor(retryAfter + jitter);
12167
+ }
12168
+ const initialBackoffMs = policy.initialBackoffMs ?? DEFAULT_INITIAL_BACKOFF_MS;
12169
+ const backoffMultiplier = policy.backoffMultiplier ?? DEFAULT_BACKOFF_MULTIPLIER;
12170
+ const maxBackoffMs = policy.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
12171
+ const exponential = initialBackoffMs * backoffMultiplier ** retryIndex;
12172
+ const bounded = Math.min(exponential, maxBackoffMs);
12173
+ return Math.floor(randUniformFn(0, bounded));
12174
+ }
12175
+ function deductWallTime(request, elapsedMs) {
12176
+ if (request.budget?.wallTimeRemainingMs !== void 0) {
12177
+ request.budget.wallTimeRemainingMs = Math.max(
12178
+ request.budget.wallTimeRemainingMs - elapsedMs,
12179
+ 0
12180
+ );
11715
12181
  }
11716
- async saveActivity(records) {
11717
- const payload = JSON.stringify(records, null, 2);
11718
- await this.safeWrite(this.activityFile, payload);
12182
+ }
12183
+ function budgetExhausted(budget, nowMs) {
12184
+ return budget.wallTimeRemainingMs !== void 0 && budget.wallTimeRemainingMs <= 0 || nowMs > budget.deadlineEpochMs;
12185
+ }
12186
+ async function delegateToSwarm(options) {
12187
+ if (!options.budget.deadlineEpochMs || options.budget.deadlineEpochMs <= 0) {
12188
+ throw new HandoffValidationError(
12189
+ "budget.deadlineEpochMs is required for cross-swarm delegation"
12190
+ );
11719
12191
  }
11720
- async loadActivity() {
11721
- try {
11722
- const buf = await import_promises.default.readFile(this.activityFile, "utf8");
11723
- return JSON.parse(buf);
11724
- } catch (e) {
11725
- if (e?.code === "ENOENT")
11726
- return [];
11727
- throw e;
12192
+ if (options.timeoutMs !== void 0 && options.timeoutMs < 0) {
12193
+ throw new HandoffValidationError("timeoutMs must be >= 0");
12194
+ }
12195
+ const nowMs = options.nowMsFn ?? defaultNowMs;
12196
+ const sleepMs = options.sleepMsFn ?? defaultSleepMs;
12197
+ const randUniform = options.randUniformFn ?? defaultRandUniform;
12198
+ const policy = normalizePolicy(options.delegationPolicy);
12199
+ const requestBudget = { ...options.budget };
12200
+ const request = {
12201
+ requestId: options.requestId ?? (0, import_node_crypto3.randomUUID)(),
12202
+ fromAgent: options.fromAgent,
12203
+ toAgent: options.toAgent,
12204
+ reason: options.reason,
12205
+ contextSnapshot: options.contextSnapshot ?? new Uint8Array(),
12206
+ capabilitiesRequired: [...options.capabilitiesRequired ?? []],
12207
+ priority: options.priority ?? 0,
12208
+ timeoutMs: options.timeoutMs,
12209
+ budget: requestBudget,
12210
+ delegationPolicy: policy
12211
+ };
12212
+ const maxRetriesOnOverloaded = policy.maxRetriesOnOverloaded ?? DEFAULT_MAX_RETRIES_ON_OVERLOADED;
12213
+ let retryIndex = 0;
12214
+ let redirectHops = 0;
12215
+ const redirectBound = effectiveMaxRedirects(policy);
12216
+ const visitedAgents = /* @__PURE__ */ new Set([request.toAgent]);
12217
+ while (true) {
12218
+ const startMs = nowMs();
12219
+ if (budgetExhausted(request.budget, startMs)) {
12220
+ return deadlineExhaustedResponse(request.requestId);
12221
+ }
12222
+ const response = await options.sendHandoffFn(request);
12223
+ const endMs = nowMs();
12224
+ const elapsedMs = Math.max(endMs - startMs, 0);
12225
+ deductWallTime(request, elapsedMs);
12226
+ if (response.accepted) {
12227
+ return response;
12228
+ }
12229
+ if (budgetExhausted(request.budget, endMs)) {
12230
+ return deadlineExhaustedResponse(request.requestId);
12231
+ }
12232
+ if (response.rejectionCode !== 16 /* OVERLOADED */) {
12233
+ if (response.rejectionCode !== 20 /* REDIRECT */) {
12234
+ return response;
12235
+ }
12236
+ if (!policy.allowSpilloverRouting) {
12237
+ return response;
12238
+ }
12239
+ const targetAgent = response.redirectToAgentId?.trim();
12240
+ if (!targetAgent) {
12241
+ return invalidRedirectResponse(
12242
+ request.requestId,
12243
+ "Redirect response missing non-empty redirectToAgentId"
12244
+ );
12245
+ }
12246
+ if (visitedAgents.has(targetAgent)) {
12247
+ return invalidRedirectResponse(
12248
+ request.requestId,
12249
+ `Redirect loop detected for agent '${targetAgent}'`
12250
+ );
12251
+ }
12252
+ if (redirectHops >= redirectBound) {
12253
+ return response;
12254
+ }
12255
+ request.toAgent = targetAgent;
12256
+ visitedAgents.add(targetAgent);
12257
+ redirectHops += 1;
12258
+ continue;
12259
+ }
12260
+ if (retryIndex >= maxRetriesOnOverloaded) {
12261
+ return response;
12262
+ }
12263
+ const waitMs = nextRetryWaitMs(response, retryIndex, policy, randUniform);
12264
+ retryIndex += 1;
12265
+ const remainingDeadlineMs = request.budget.deadlineEpochMs - endMs;
12266
+ const remainingWallTimeMs = request.budget?.wallTimeRemainingMs;
12267
+ if (waitMs <= 0 || remainingWallTimeMs !== void 0 && waitMs > remainingWallTimeMs || waitMs > remainingDeadlineMs) {
12268
+ return response;
12269
+ }
12270
+ const beforeSleepMs = nowMs();
12271
+ await sleepMs(waitMs);
12272
+ const afterSleepMs = nowMs();
12273
+ deductWallTime(request, Math.max(afterSleepMs - beforeSleepMs, 0));
12274
+ }
12275
+ }
12276
+
12277
+ // src/runtime/cancellation.ts
12278
+ var MIN_GRACE_PERIOD_MS = 5e3;
12279
+ var CancellationValidationError = class extends Error {
12280
+ constructor(message) {
12281
+ super(message);
12282
+ this.name = "CancellationValidationError";
12283
+ }
12284
+ };
12285
+ function defaultNowMs2() {
12286
+ return Date.now();
12287
+ }
12288
+ function normalizeCorrelationId(correlationId) {
12289
+ const normalized = correlationId.trim();
12290
+ if (!normalized) {
12291
+ throw new CancellationValidationError(
12292
+ "cancel.correlationId is required and must be a non-empty string"
12293
+ );
12294
+ }
12295
+ return normalized;
12296
+ }
12297
+ function normalizeReason(reason) {
12298
+ if (reason === void 0) {
12299
+ return "";
12300
+ }
12301
+ return reason.trim();
12302
+ }
12303
+ function normalizeGracePeriodMs(gracePeriodMs) {
12304
+ const requested = gracePeriodMs !== void 0 && Number.isFinite(gracePeriodMs) && gracePeriodMs > 0 ? Math.floor(gracePeriodMs) : 0;
12305
+ return Math.max(requested, MIN_GRACE_PERIOD_MS);
12306
+ }
12307
+ function normalizeMetadataValue(value) {
12308
+ if (value === null) {
12309
+ return null;
12310
+ }
12311
+ if (typeof value === "string") {
12312
+ return value.trim();
12313
+ }
12314
+ if (typeof value === "number") {
12315
+ return Number.isFinite(value) ? value : void 0;
12316
+ }
12317
+ if (typeof value === "boolean") {
12318
+ return value;
12319
+ }
12320
+ if (value instanceof Date) {
12321
+ return value.toISOString();
12322
+ }
12323
+ if (typeof value === "bigint") {
12324
+ return value.toString();
12325
+ }
12326
+ if (typeof value === "object") {
12327
+ try {
12328
+ return JSON.stringify(value);
12329
+ } catch {
12330
+ return void 0;
12331
+ }
12332
+ }
12333
+ return void 0;
12334
+ }
12335
+ function normalizeMetadata(metadata, options) {
12336
+ const { reason, gracePeriodMs } = options;
12337
+ const normalized = {};
12338
+ if (metadata !== void 0) {
12339
+ for (const [rawKey, rawValue] of Object.entries(metadata)) {
12340
+ const key = rawKey.trim();
12341
+ if (!key) {
12342
+ continue;
12343
+ }
12344
+ const value = normalizeMetadataValue(rawValue);
12345
+ if (value !== void 0) {
12346
+ normalized[key] = value;
12347
+ }
12348
+ }
12349
+ }
12350
+ normalized.reason = reason;
12351
+ normalized.grace_period_ms = gracePeriodMs;
12352
+ return normalized;
12353
+ }
12354
+ function cloneMetadata(metadata) {
12355
+ return { ...metadata };
12356
+ }
12357
+ function cloneFlag(flag) {
12358
+ return {
12359
+ cancelled: flag.cancelled,
12360
+ gracePeriodMs: flag.gracePeriodMs,
12361
+ cancelTimeMs: flag.cancelTimeMs,
12362
+ metadata: cloneMetadata(flag.metadata)
12363
+ };
12364
+ }
12365
+ var CancellationManager = class {
12366
+ childDelegations = /* @__PURE__ */ new Map();
12367
+ cancellationFlags = /* @__PURE__ */ new Map();
12368
+ nowMs;
12369
+ constructor(options = {}) {
12370
+ this.nowMs = options.nowMsFn ?? defaultNowMs2;
12371
+ }
12372
+ registerChildDelegation(parentCorrelationId, childCorrelationId) {
12373
+ const parent = normalizeCorrelationId(parentCorrelationId);
12374
+ const child = normalizeCorrelationId(childCorrelationId);
12375
+ if (!this.childDelegations.has(parent)) {
12376
+ this.childDelegations.set(parent, /* @__PURE__ */ new Set());
12377
+ }
12378
+ this.childDelegations.get(parent).add(child);
12379
+ }
12380
+ handleCancelDelegation(cancel) {
12381
+ const correlationId = normalizeCorrelationId(cancel.correlationId);
12382
+ const gracePeriodMs = normalizeGracePeriodMs(cancel.gracePeriodMs);
12383
+ const reason = normalizeReason(cancel.reason);
12384
+ const cancelTimeMs = this.nowMs();
12385
+ const metadata = normalizeMetadata(cancel.metadata, {
12386
+ reason,
12387
+ gracePeriodMs
12388
+ });
12389
+ const flag = {
12390
+ cancelled: true,
12391
+ gracePeriodMs,
12392
+ cancelTimeMs,
12393
+ metadata
12394
+ };
12395
+ this.cancellationFlags.set(correlationId, cloneFlag(flag));
12396
+ for (const childCorrelationId of this.childDelegations.get(correlationId) ?? []) {
12397
+ this.cancellationFlags.set(childCorrelationId, cloneFlag(flag));
12398
+ }
12399
+ return {
12400
+ acknowledged: true,
12401
+ correlationId,
12402
+ gracePeriodMs,
12403
+ message: "Cancellation recorded",
12404
+ metadata: cloneMetadata(metadata)
12405
+ };
12406
+ }
12407
+ isCancelled(correlationId) {
12408
+ const normalized = correlationId.trim();
12409
+ if (!normalized) {
12410
+ return false;
12411
+ }
12412
+ const entry = this.cancellationFlags.get(normalized);
12413
+ return Boolean(entry?.cancelled);
12414
+ }
12415
+ isGraceExpired(correlationId, nowMs) {
12416
+ const normalized = correlationId.trim();
12417
+ if (!normalized) {
12418
+ return false;
12419
+ }
12420
+ const entry = this.cancellationFlags.get(normalized);
12421
+ if (entry === void 0 || !entry.cancelled) {
12422
+ return false;
12423
+ }
12424
+ const currentMs = nowMs ?? this.nowMs();
12425
+ return currentMs - entry.cancelTimeMs >= entry.gracePeriodMs;
12426
+ }
12427
+ forcedPreemptionErrorCode(correlationId, nowMs) {
12428
+ if (this.isGraceExpired(correlationId, nowMs)) {
12429
+ return 12 /* FORCED_PREEMPTION */;
12430
+ }
12431
+ return 0 /* ERROR_CODE_UNSPECIFIED */;
12432
+ }
12433
+ collectForcedPreemptions(correlationIds, nowMs) {
12434
+ const currentMs = nowMs ?? this.nowMs();
12435
+ const forced = /* @__PURE__ */ new Set();
12436
+ for (const correlationId of correlationIds) {
12437
+ if (this.isGraceExpired(correlationId, currentMs)) {
12438
+ forced.add(correlationId);
12439
+ }
12440
+ }
12441
+ return forced;
12442
+ }
12443
+ };
12444
+
12445
+ // src/runtime/gateway.ts
12446
+ var REGISTRATION_TYPE_STANDARD_AGENT = 1;
12447
+ var REGISTRATION_TYPE_SWARM_GATEWAY = 2;
12448
+ var AGENT_STATE_INITIALIZING = 1;
12449
+ var AGENT_STATE_RUNNING = 4;
12450
+ var AGENT_STATE_FAILED = 10;
12451
+ var AGENT_STATE_SHUTTING_DOWN = 11;
12452
+ var DEFAULT_PEER_LIVENESS_THRESHOLD_MS = 3e4;
12453
+ var NON_SERVING_AGENT_STATES = /* @__PURE__ */ new Set([
12454
+ AGENT_STATE_INITIALIZING,
12455
+ AGENT_STATE_FAILED,
12456
+ AGENT_STATE_SHUTTING_DOWN
12457
+ ]);
12458
+ var GatewayValidationError = class extends Error {
12459
+ constructor(message) {
12460
+ super(message);
12461
+ this.name = "GatewayValidationError";
12462
+ }
12463
+ };
12464
+ function defaultNowMs3() {
12465
+ return Date.now();
12466
+ }
12467
+ function sameCapabilities(peerCapabilities, localCapabilities) {
12468
+ const peerSet = new Set(peerCapabilities);
12469
+ if (peerSet.size !== localCapabilities.size) {
12470
+ return false;
12471
+ }
12472
+ for (const localCapability of localCapabilities) {
12473
+ if (!peerSet.has(localCapability)) {
12474
+ return false;
12475
+ }
12476
+ }
12477
+ return true;
12478
+ }
12479
+ var PeerSelector = class {
12480
+ localAgentId;
12481
+ localCapabilities;
12482
+ nowMs;
12483
+ peerHealthFn;
12484
+ livenessThresholdMs;
12485
+ peers = [];
12486
+ runtime = /* @__PURE__ */ new Map();
12487
+ rrCursor = 0;
12488
+ constructor(options) {
12489
+ const threshold = options.livenessThresholdMs ?? DEFAULT_PEER_LIVENESS_THRESHOLD_MS;
12490
+ if (threshold < 0) {
12491
+ throw new GatewayValidationError("livenessThresholdMs must be >= 0");
12492
+ }
12493
+ this.localAgentId = options.localAgentId;
12494
+ this.localCapabilities = new Set(options.localCapabilities ?? []);
12495
+ this.nowMs = options.nowMsFn ?? defaultNowMs3;
12496
+ this.peerHealthFn = options.peerHealthFn ?? (() => true);
12497
+ this.livenessThresholdMs = threshold;
12498
+ }
12499
+ setPeers(peers) {
12500
+ this.peers = [...peers];
12501
+ const activeIds = new Set(this.peers.map((peer) => peer.agentId));
12502
+ for (const agentId of [...this.runtime.keys()]) {
12503
+ if (!activeIds.has(agentId)) {
12504
+ this.runtime.delete(agentId);
12505
+ }
12506
+ }
12507
+ const nowMs = this.nowMs();
12508
+ for (const peer of this.peers) {
12509
+ if (!this.runtime.has(peer.agentId)) {
12510
+ this.runtime.set(peer.agentId, {
12511
+ state: AGENT_STATE_RUNNING,
12512
+ lastHeartbeatMs: nowMs,
12513
+ cooldownUntilMs: 0
12514
+ });
12515
+ }
12516
+ }
12517
+ }
12518
+ updatePeerRuntimeState(agentId, options = {}) {
12519
+ const runtime = this.ensureRuntime(agentId);
12520
+ if (options.state !== void 0) {
12521
+ runtime.state = options.state;
12522
+ }
12523
+ if (options.lastHeartbeatMs !== void 0) {
12524
+ runtime.lastHeartbeatMs = Math.max(Math.floor(options.lastHeartbeatMs), 0);
12525
+ }
12526
+ if (options.cooldownUntilMs !== void 0) {
12527
+ runtime.cooldownUntilMs = Math.max(Math.floor(options.cooldownUntilMs), 0);
12528
+ }
12529
+ this.runtime.set(agentId, runtime);
12530
+ }
12531
+ touchPeerHeartbeat(agentId, options = {}) {
12532
+ this.updatePeerRuntimeState(agentId, {
12533
+ state: options.state,
12534
+ lastHeartbeatMs: options.nowMs ?? this.nowMs()
12535
+ });
12536
+ }
12537
+ recordPeerOverloaded(agentId, options = {}) {
12538
+ const runtime = this.ensureRuntime(agentId);
12539
+ const nowMs = this.nowMs();
12540
+ const retryAfterMs = Math.max(Math.floor(options.retryAfterMs ?? 0), 0);
12541
+ const localCooldownMs = Math.max(Math.floor(options.localCooldownMs ?? 0), 0);
12542
+ const cooldownMs = Math.max(retryAfterMs, localCooldownMs);
12543
+ runtime.cooldownUntilMs = Math.max(runtime.cooldownUntilMs, nowMs + cooldownMs);
12544
+ this.runtime.set(agentId, runtime);
12545
+ }
12546
+ isEligible(peer) {
12547
+ if (peer.registrationType !== REGISTRATION_TYPE_SWARM_GATEWAY) {
12548
+ return false;
12549
+ }
12550
+ if (peer.agentId === this.localAgentId) {
12551
+ return false;
12552
+ }
12553
+ return sameCapabilities(peer.capabilities, this.localCapabilities);
12554
+ }
12555
+ selectPeer() {
12556
+ const healthy = this.peers.filter((peer) => this.isHealthy(peer));
12557
+ if (healthy.length === 0) {
12558
+ return "";
12559
+ }
12560
+ const idx = this.rrCursor % healthy.length;
12561
+ this.rrCursor += 1;
12562
+ return healthy[idx].agentId;
12563
+ }
12564
+ ensureRuntime(agentId) {
12565
+ const existing = this.runtime.get(agentId);
12566
+ if (existing !== void 0) {
12567
+ return existing;
12568
+ }
12569
+ return {
12570
+ state: AGENT_STATE_RUNNING,
12571
+ lastHeartbeatMs: this.nowMs(),
12572
+ cooldownUntilMs: 0
12573
+ };
12574
+ }
12575
+ isHealthy(peer) {
12576
+ if (!this.isEligible(peer)) {
12577
+ return false;
12578
+ }
12579
+ if (!this.peerHealthFn(peer)) {
12580
+ return false;
12581
+ }
12582
+ const runtime = this.runtime.get(peer.agentId);
12583
+ if (runtime === void 0) {
12584
+ return false;
12585
+ }
12586
+ const nowMs = this.nowMs();
12587
+ if (runtime.cooldownUntilMs > nowMs) {
12588
+ return false;
12589
+ }
12590
+ if (nowMs - runtime.lastHeartbeatMs > this.livenessThresholdMs) {
12591
+ return false;
12592
+ }
12593
+ if (NON_SERVING_AGENT_STATES.has(runtime.state)) {
12594
+ return false;
12595
+ }
12596
+ return true;
12597
+ }
12598
+ };
12599
+ var GatewayRedirectEmitter = class {
12600
+ retryAfterMs;
12601
+ peerSelector;
12602
+ constructor(options) {
12603
+ if ((options.retryAfterMs ?? 0) < 0) {
12604
+ throw new GatewayValidationError("retryAfterMs must be >= 0");
12605
+ }
12606
+ this.retryAfterMs = options.retryAfterMs ?? 1e3;
12607
+ this.peerSelector = new PeerSelector({
12608
+ localAgentId: options.agentId,
12609
+ localCapabilities: options.capabilities ?? [],
12610
+ nowMsFn: options.nowMsFn,
12611
+ peerHealthFn: options.peerHealthFn,
12612
+ livenessThresholdMs: options.peerLivenessThresholdMs
12613
+ });
12614
+ this.peerSelector.setPeers(options.peerDescriptors ?? []);
12615
+ }
12616
+ setPeerDescriptors(peers) {
12617
+ this.peerSelector.setPeers(peers);
12618
+ }
12619
+ updatePeerRuntimeState(agentId, options = {}) {
12620
+ this.peerSelector.updatePeerRuntimeState(agentId, options);
12621
+ }
12622
+ touchPeerHeartbeat(agentId, options = {}) {
12623
+ this.peerSelector.touchPeerHeartbeat(agentId, options);
12624
+ }
12625
+ recordPeerOverloaded(agentId, options = {}) {
12626
+ this.peerSelector.recordPeerOverloaded(agentId, options);
12627
+ }
12628
+ emitOverloadedResponse(request) {
12629
+ if (request.delegationPolicy?.allowSpilloverRouting) {
12630
+ const redirectToAgentId = this.peerSelector.selectPeer();
12631
+ if (redirectToAgentId) {
12632
+ return {
12633
+ requestId: request.requestId,
12634
+ accepted: false,
12635
+ rejectionReason: "Gateway at capacity; redirect to peer gateway",
12636
+ rejectionCode: 20 /* REDIRECT */,
12637
+ retryAfterMs: 0,
12638
+ redirectToAgentId
12639
+ };
12640
+ }
12641
+ }
12642
+ return {
12643
+ requestId: request.requestId,
12644
+ accepted: false,
12645
+ rejectionReason: "Gateway at capacity",
12646
+ rejectionCode: 16 /* OVERLOADED */,
12647
+ retryAfterMs: this.retryAfterMs
12648
+ };
12649
+ }
12650
+ };
12651
+
12652
+ // src/persistence/persistence.ts
12653
+ var import_promises = __toESM(require("node:fs/promises"), 1);
12654
+ var import_node_path2 = __toESM(require("node:path"), 1);
12655
+ var JSONFilePersistence = class {
12656
+ constructor(baseDir) {
12657
+ this.baseDir = baseDir;
12658
+ this.activityFile = import_node_path2.default.join(baseDir, "activity.json");
12659
+ this.acksFile = import_node_path2.default.join(baseDir, "acks.json");
12660
+ }
12661
+ activityFile;
12662
+ acksFile;
12663
+ async safeWrite(file, data) {
12664
+ await import_promises.default.mkdir(import_node_path2.default.dirname(file), { recursive: true });
12665
+ const tmp = `${file}.tmp-${Date.now()}`;
12666
+ await import_promises.default.writeFile(tmp, data, "utf8");
12667
+ await import_promises.default.rename(tmp, file);
12668
+ }
12669
+ async saveActivity(records) {
12670
+ const payload = JSON.stringify(records, null, 2);
12671
+ await this.safeWrite(this.activityFile, payload);
12672
+ }
12673
+ async loadActivity() {
12674
+ try {
12675
+ const buf = await import_promises.default.readFile(this.activityFile, "utf8");
12676
+ return JSON.parse(buf);
12677
+ } catch (e) {
12678
+ if (e?.code === "ENOENT")
12679
+ return [];
12680
+ throw e;
11728
12681
  }
11729
12682
  }
11730
12683
  async saveAcks(states) {
@@ -12649,7 +13602,7 @@ var AgentState = /* @__PURE__ */ ((AgentState2) => {
12649
13602
  AgentState2[AgentState2["RECOVERING"] = 12] = "RECOVERING";
12650
13603
  return AgentState2;
12651
13604
  })(AgentState || {});
12652
- var StateTransitionError = class extends Error {
13605
+ var StateTransitionError2 = class extends Error {
12653
13606
  fromState;
12654
13607
  toState;
12655
13608
  constructor(fromState, toState) {
@@ -12662,8 +13615,8 @@ var StateTransitionError = class extends Error {
12662
13615
  }
12663
13616
  };
12664
13617
  var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
12665
- // INITIALIZING -> RUNNABLE
12666
- [1 /* INITIALIZING */, /* @__PURE__ */ new Set([2 /* RUNNABLE */])],
13618
+ // INITIALIZING -> RUNNABLE, FAILED (init timeout per spec s8.2)
13619
+ [1 /* INITIALIZING */, /* @__PURE__ */ new Set([2 /* RUNNABLE */, 10 /* FAILED */])],
12667
13620
  // RUNNABLE -> SCHEDULED
12668
13621
  [2 /* RUNNABLE */, /* @__PURE__ */ new Set([3 /* SCHEDULED */])],
12669
13622
  // SCHEDULED -> RUNNING
@@ -12687,8 +13640,8 @@ var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
12687
13640
  6 /* WAITING_RESOURCES */,
12688
13641
  /* @__PURE__ */ new Set([4 /* RUNNING */, 10 /* FAILED */])
12689
13642
  ],
12690
- // SUSPENDED -> RESUMED
12691
- [7 /* SUSPENDED */, /* @__PURE__ */ new Set([8 /* RESUMED */])],
13643
+ // SUSPENDED -> RESUMED, FAILED (suspension timeout per spec s8.3)
13644
+ [7 /* SUSPENDED */, /* @__PURE__ */ new Set([8 /* RESUMED */, 10 /* FAILED */])],
12692
13645
  // RESUMED -> RUNNING
12693
13646
  [8 /* RESUMED */, /* @__PURE__ */ new Set([4 /* RUNNING */])],
12694
13647
  // COMPLETED -> RUNNABLE
@@ -12697,10 +13650,10 @@ var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
12697
13650
  [10 /* FAILED */, /* @__PURE__ */ new Set([12 /* RECOVERING */])],
12698
13651
  // SHUTTING_DOWN -> FAILED (agent_shutdown_timeout)
12699
13652
  [11 /* SHUTTING_DOWN */, /* @__PURE__ */ new Set([10 /* FAILED */])],
12700
- // RECOVERING -> RUNNABLE, SHUTTING_DOWN (recovery abort)
13653
+ // RECOVERING -> RUNNABLE, SHUTTING_DOWN (recovery abort), FAILED (recovery timeout per spec s8.3)
12701
13654
  [
12702
13655
  12 /* RECOVERING */,
12703
- /* @__PURE__ */ new Set([2 /* RUNNABLE */, 11 /* SHUTTING_DOWN */])
13656
+ /* @__PURE__ */ new Set([2 /* RUNNABLE */, 11 /* SHUTTING_DOWN */, 10 /* FAILED */])
12704
13657
  ]
12705
13658
  ]);
12706
13659
  function isValidTransition(fromState, toState) {
@@ -12752,7 +13705,7 @@ var AgentStateMachine = class {
12752
13705
  */
12753
13706
  async initialize() {
12754
13707
  if (this.state !== 0 /* AGENT_STATE_UNSPECIFIED */) {
12755
- throw new StateTransitionError(this.state, 1 /* INITIALIZING */);
13708
+ throw new StateTransitionError2(this.state, 1 /* INITIALIZING */);
12756
13709
  }
12757
13710
  await this.transitionTo(1 /* INITIALIZING */);
12758
13711
  }
@@ -12769,7 +13722,7 @@ var AgentStateMachine = class {
12769
13722
  return;
12770
13723
  }
12771
13724
  if (!isValidTransition(this.state, toState)) {
12772
- throw new StateTransitionError(this.state, toState);
13725
+ throw new StateTransitionError2(this.state, toState);
12773
13726
  }
12774
13727
  await this.doTransition(toState, context);
12775
13728
  }
@@ -12925,15 +13878,16 @@ var AgentStateMachine = class {
12925
13878
  };
12926
13879
 
12927
13880
  // src/internal/idempotency.ts
12928
- var import_node_crypto3 = __toESM(require("node:crypto"), 1);
13881
+ var import_node_crypto4 = __toESM(require("node:crypto"), 1);
12929
13882
  function computeIdempotencyToken(input) {
12930
- const h = import_node_crypto3.default.createHash("sha256");
13883
+ const h = import_node_crypto4.default.createHash("sha256");
12931
13884
  h.update(input.producer_id);
12932
13885
  h.update("\n");
12933
13886
  h.update(input.operation);
12934
13887
  h.update("\n");
12935
13888
  h.update(Buffer.from(input.canonical_bytes));
12936
- return `v1:${h.digest("hex")}`;
13889
+ const hash16 = h.digest("hex").slice(0, 16);
13890
+ return `${input.producer_id}:${input.operation}:${hash16}`;
12937
13891
  }
12938
13892
 
12939
13893
  // src/runtime/persistenceAdapter.ts
@@ -13050,89 +14004,752 @@ function normalizeReportPaths(report) {
13050
14004
  return report;
13051
14005
  }
13052
14006
 
13053
- // src/secrets/types.ts
13054
- var SecretSource = /* @__PURE__ */ ((SecretSource2) => {
13055
- SecretSource2["CLI"] = "cli";
13056
- SecretSource2["ENV"] = "env";
13057
- SecretSource2["SCOPED"] = "scoped";
13058
- SecretSource2["GLOBAL"] = "global";
13059
- return SecretSource2;
13060
- })(SecretSource || {});
13061
- var Scope = class {
13062
- constructor(name = null) {
13063
- this.name = name;
13064
- }
13065
- get isGlobal() {
13066
- return this.name === null;
14007
+ // src/constants/index.ts
14008
+ var CommunicationClass = /* @__PURE__ */ ((CommunicationClass2) => {
14009
+ CommunicationClass2[CommunicationClass2["COMM_CLASS_UNSPECIFIED"] = 0] = "COMM_CLASS_UNSPECIFIED";
14010
+ CommunicationClass2[CommunicationClass2["PRIVILEGED"] = 1] = "PRIVILEGED";
14011
+ CommunicationClass2[CommunicationClass2["STANDARD"] = 2] = "STANDARD";
14012
+ CommunicationClass2[CommunicationClass2["BULK"] = 3] = "BULK";
14013
+ return CommunicationClass2;
14014
+ })(CommunicationClass || {});
14015
+ var DebateIntensity = /* @__PURE__ */ ((DebateIntensity2) => {
14016
+ DebateIntensity2[DebateIntensity2["DEBATE_INTENSITY_UNSPECIFIED"] = 0] = "DEBATE_INTENSITY_UNSPECIFIED";
14017
+ DebateIntensity2[DebateIntensity2["LOWEST"] = 1] = "LOWEST";
14018
+ DebateIntensity2[DebateIntensity2["LOW"] = 2] = "LOW";
14019
+ DebateIntensity2[DebateIntensity2["MEDIUM"] = 3] = "MEDIUM";
14020
+ DebateIntensity2[DebateIntensity2["HIGH"] = 4] = "HIGH";
14021
+ DebateIntensity2[DebateIntensity2["HIGHEST"] = 5] = "HIGHEST";
14022
+ return DebateIntensity2;
14023
+ })(DebateIntensity || {});
14024
+ var HitlReasonType = /* @__PURE__ */ ((HitlReasonType2) => {
14025
+ HitlReasonType2[HitlReasonType2["HITL_REASON_UNSPECIFIED"] = 0] = "HITL_REASON_UNSPECIFIED";
14026
+ HitlReasonType2[HitlReasonType2["CONFLICT"] = 1] = "CONFLICT";
14027
+ HitlReasonType2[HitlReasonType2["SECURITY_APPROVAL"] = 2] = "SECURITY_APPROVAL";
14028
+ HitlReasonType2[HitlReasonType2["TASK_ESCALATION"] = 3] = "TASK_ESCALATION";
14029
+ HitlReasonType2[HitlReasonType2["MANUAL_OVERRIDE"] = 4] = "MANUAL_OVERRIDE";
14030
+ HitlReasonType2[HitlReasonType2["WORKTREE_OVERRIDE"] = 5] = "WORKTREE_OVERRIDE";
14031
+ HitlReasonType2[HitlReasonType2["DEBATE_DEADLOCK"] = 6] = "DEBATE_DEADLOCK";
14032
+ HitlReasonType2[HitlReasonType2["TOOL_PRIVILEGE_ESCALATION"] = 7] = "TOOL_PRIVILEGE_ESCALATION";
14033
+ HitlReasonType2[HitlReasonType2["CONNECTOR_APPROVAL"] = 8] = "CONNECTOR_APPROVAL";
14034
+ return HitlReasonType2;
14035
+ })(HitlReasonType || {});
14036
+ var AckStage2 = /* @__PURE__ */ ((AckStage3) => {
14037
+ AckStage3[AckStage3["ACK_STAGE_UNSPECIFIED"] = 0] = "ACK_STAGE_UNSPECIFIED";
14038
+ AckStage3[AckStage3["RECEIVED"] = 1] = "RECEIVED";
14039
+ AckStage3[AckStage3["READ"] = 2] = "READ";
14040
+ AckStage3[AckStage3["FULFILLED"] = 3] = "FULFILLED";
14041
+ AckStage3[AckStage3["REJECTED"] = 4] = "REJECTED";
14042
+ AckStage3[AckStage3["FAILED"] = 5] = "FAILED";
14043
+ AckStage3[AckStage3["TIMED_OUT"] = 6] = "TIMED_OUT";
14044
+ return AckStage3;
14045
+ })(AckStage2 || {});
14046
+ var EnvelopeState = /* @__PURE__ */ ((EnvelopeState3) => {
14047
+ EnvelopeState3[EnvelopeState3["ENVELOPE_STATE_UNSPECIFIED"] = 0] = "ENVELOPE_STATE_UNSPECIFIED";
14048
+ EnvelopeState3[EnvelopeState3["SENT"] = 1] = "SENT";
14049
+ EnvelopeState3[EnvelopeState3["RECEIVED"] = 2] = "RECEIVED";
14050
+ EnvelopeState3[EnvelopeState3["READ"] = 3] = "READ";
14051
+ EnvelopeState3[EnvelopeState3["FULFILLED"] = 4] = "FULFILLED";
14052
+ EnvelopeState3[EnvelopeState3["REJECTED"] = 5] = "REJECTED";
14053
+ EnvelopeState3[EnvelopeState3["FAILED"] = 6] = "FAILED";
14054
+ EnvelopeState3[EnvelopeState3["TIMED_OUT"] = 7] = "TIMED_OUT";
14055
+ return EnvelopeState3;
14056
+ })(EnvelopeState || {});
14057
+ var WorktreeStateEnum = /* @__PURE__ */ ((WorktreeStateEnum2) => {
14058
+ WorktreeStateEnum2[WorktreeStateEnum2["WORKTREE_STATE_UNSPECIFIED"] = 0] = "WORKTREE_STATE_UNSPECIFIED";
14059
+ WorktreeStateEnum2[WorktreeStateEnum2["UNBOUND"] = 1] = "UNBOUND";
14060
+ WorktreeStateEnum2[WorktreeStateEnum2["BOUND_HOME"] = 2] = "BOUND_HOME";
14061
+ WorktreeStateEnum2[WorktreeStateEnum2["SWITCH_PENDING"] = 3] = "SWITCH_PENDING";
14062
+ WorktreeStateEnum2[WorktreeStateEnum2["BOUND_NON_HOME"] = 4] = "BOUND_NON_HOME";
14063
+ WorktreeStateEnum2[WorktreeStateEnum2["BIND_FAILED"] = 5] = "BIND_FAILED";
14064
+ return WorktreeStateEnum2;
14065
+ })(WorktreeStateEnum || {});
14066
+ var DEFAULT_ACK_TIMEOUT_MS = 1e4;
14067
+ var DEDUP_WINDOW_S = 3600;
14068
+ function isTerminalEnvelopeState(state) {
14069
+ return state === 4 /* FULFILLED */ || state === 5 /* REJECTED */ || state === 6 /* FAILED */ || state === 7 /* TIMED_OUT */;
14070
+ }
14071
+ function updateEnvelopeState(envelope, newState) {
14072
+ envelope.state = newState;
14073
+ return envelope;
14074
+ }
14075
+
14076
+ // src/audit.ts
14077
+ var import_node_crypto5 = __toESM(require("node:crypto"), 1);
14078
+ function uuidv43() {
14079
+ if (typeof import_node_crypto5.default.randomUUID === "function") {
14080
+ return import_node_crypto5.default.randomUUID();
13067
14081
  }
13068
- label() {
13069
- return this.name ?? "global";
14082
+ const buf = import_node_crypto5.default.randomBytes(16);
14083
+ buf[6] = buf[6] & 15 | 64;
14084
+ buf[8] = buf[8] & 63 | 128;
14085
+ const hex = [...buf].map((b) => b.toString(16).padStart(2, "0"));
14086
+ 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("");
14087
+ }
14088
+ function computeEnvelopeHash(envelope) {
14089
+ const envelopeCopy = { ...envelope };
14090
+ const payload = envelopeCopy.payload;
14091
+ const audit_proof = envelopeCopy.audit_proof;
14092
+ delete envelopeCopy.payload;
14093
+ delete envelopeCopy.audit_proof;
14094
+ const envelopeJson = JSON.stringify(envelopeCopy, Object.keys(envelopeCopy).sort());
14095
+ const hasher = import_node_crypto5.default.createHash("sha256");
14096
+ hasher.update(envelopeJson, "utf-8");
14097
+ if (payload) {
14098
+ if (payload instanceof Uint8Array) {
14099
+ hasher.update(payload);
14100
+ } else if (typeof payload === "string") {
14101
+ hasher.update(payload, "utf-8");
14102
+ }
14103
+ }
14104
+ if (audit_proof) {
14105
+ if (audit_proof instanceof Uint8Array) {
14106
+ hasher.update(audit_proof);
14107
+ } else if (typeof audit_proof === "string") {
14108
+ hasher.update(audit_proof, "utf-8");
14109
+ }
14110
+ }
14111
+ return hasher.digest("hex");
14112
+ }
14113
+ function createSimpleProof(envelope, actor_id) {
14114
+ const envelopeHash = computeEnvelopeHash(envelope);
14115
+ const timestamp = nowHlcStub();
14116
+ const proofInput = `${envelopeHash}:${actor_id}:${timestamp}`;
14117
+ const proofHash = import_node_crypto5.default.createHash("sha256").update(proofInput, "utf-8").digest();
14118
+ return {
14119
+ proof_id: uuidv43(),
14120
+ proof_type: "simple_hash",
14121
+ proof_data: new Uint8Array(proofHash),
14122
+ created_at: timestamp,
14123
+ verified: false
14124
+ };
14125
+ }
14126
+ function verifyAuditProof(envelope, proof) {
14127
+ if (proof.proof_type === "noop") {
14128
+ return true;
13070
14129
  }
13071
- };
13072
- var SecretKey = class {
13073
- constructor(key) {
13074
- this.key = key;
13075
- if (!key || key.split(".").some((p) => p.trim() === "")) {
13076
- throw new Error("secret key must be dotted identifiers without empty segments");
14130
+ if (proof.proof_type === "simple_hash") {
14131
+ if (proof.proof_data.length === 0) {
14132
+ return false;
13077
14133
  }
13078
- }
13079
- };
13080
- var SecretValue = class _SecretValue {
13081
- constructor(value) {
13082
- this.value = value;
13083
- if (value.length > _SecretValue.MAX_LEN) {
13084
- throw new Error("secret value exceeds maximum allowed length (8KB)");
14134
+ const envelopeHash = computeEnvelopeHash(envelope);
14135
+ if (proof.proof_data.length !== 32) {
14136
+ return false;
13085
14137
  }
14138
+ return true;
13086
14139
  }
13087
- static MAX_LEN = 8 * 1024;
13088
- };
13089
-
13090
- // src/secrets/errors.ts
13091
- var SecretError = class extends Error {
13092
- };
13093
- var SecretNotFound = class extends SecretError {
13094
- constructor(scope, key) {
13095
- super(`secret not found: scope=${scope} key=${key}`);
13096
- this.scope = scope;
13097
- this.key = key;
13098
- }
13099
- };
13100
- var SecretBackendError = class extends SecretError {
13101
- };
13102
- var SecretPermissionError = class extends SecretError {
13103
- };
13104
- var SecretValidationError = class extends SecretError {
13105
- };
13106
-
13107
- // src/secrets/backend.ts
13108
- var Secrets = class {
13109
- constructor(backend) {
13110
- this.backend = backend;
14140
+ return false;
14141
+ }
14142
+ var NoOpAuditor = class {
14143
+ /**
14144
+ * Create a minimal no-op proof.
14145
+ *
14146
+ * @param envelope - The envelope (ignored)
14147
+ * @param action - The action (ignored)
14148
+ * @returns A minimal no-op proof
14149
+ */
14150
+ createProof(envelope, action) {
14151
+ return {
14152
+ proof_id: uuidv43(),
14153
+ proof_type: "noop",
14154
+ proof_data: new Uint8Array(0),
14155
+ created_at: nowHlcStub(),
14156
+ verified: true
14157
+ };
13111
14158
  }
13112
- set(scope, key, value) {
13113
- return this.backend.set(scope, key, value);
14159
+ /**
14160
+ * Always returns true for no-op proofs.
14161
+ *
14162
+ * @param proof - The proof (ignored)
14163
+ * @returns Always true
14164
+ */
14165
+ verifyProof(proof) {
14166
+ return true;
13114
14167
  }
13115
- get(scope, key) {
13116
- return this.backend.get(scope, key);
14168
+ /**
14169
+ * Create a minimal audit record without storing it.
14170
+ *
14171
+ * @param envelope - The envelope being audited
14172
+ * @param action - The action being performed
14173
+ * @param proof - Optional proof to attach
14174
+ * @returns A minimal audit record
14175
+ */
14176
+ record(envelope, action, proof) {
14177
+ return {
14178
+ record_id: uuidv43(),
14179
+ envelope_id: envelope.message_id ?? "unknown",
14180
+ action,
14181
+ actor_id: envelope.producer_id ?? "unknown",
14182
+ timestamp: nowHlcStub(),
14183
+ proof
14184
+ };
13117
14185
  }
13118
- list(scope) {
13119
- return this.backend.list(scope);
14186
+ /**
14187
+ * Always returns empty array.
14188
+ *
14189
+ * @param envelope_id - The envelope ID (ignored)
14190
+ * @returns Empty array
14191
+ */
14192
+ query(envelope_id) {
14193
+ return [];
13120
14194
  }
13121
14195
  };
13122
-
13123
- // src/secrets/resolver.ts
13124
- var Resolver = class {
13125
- constructor(backend, env = process.env) {
13126
- this.backend = backend;
13127
- this.env = env;
14196
+ var InMemoryAuditor = class {
14197
+ _records;
14198
+ /**
14199
+ * Initialize with empty record storage.
14200
+ */
14201
+ constructor() {
14202
+ this._records = /* @__PURE__ */ new Map();
13128
14203
  }
13129
- async resolve(key, scope, opts) {
13130
- const explicit = opts?.explicit ?? null;
13131
- const envVar = opts?.envVar ?? null;
13132
- if (explicit !== null)
13133
- return [explicit, "cli" /* CLI */];
13134
- if (envVar && this.env[envVar] && this.env[envVar] !== "")
13135
- return [this.env[envVar], "env" /* ENV */];
14204
+ /**
14205
+ * Create a simple hash-based proof.
14206
+ *
14207
+ * @param envelope - The envelope to create proof for
14208
+ * @param action - The action being performed
14209
+ * @returns A simple hash-based proof
14210
+ */
14211
+ createProof(envelope, action) {
14212
+ return createSimpleProof(envelope, envelope.producer_id ?? "unknown");
14213
+ }
14214
+ /**
14215
+ * Verify a proof using the verification module.
14216
+ *
14217
+ * @param proof - The proof to verify
14218
+ * @returns True if proof is valid, false otherwise
14219
+ */
14220
+ verifyProof(proof) {
14221
+ if (proof.proof_type === "noop") {
14222
+ return true;
14223
+ }
14224
+ if (proof.proof_type === "simple_hash") {
14225
+ return proof.proof_data.length > 0;
14226
+ }
14227
+ return false;
14228
+ }
14229
+ /**
14230
+ * Create and store an audit record.
14231
+ *
14232
+ * @param envelope - The envelope being audited
14233
+ * @param action - The action being performed
14234
+ * @param proof - Optional proof to attach
14235
+ * @returns The created audit record
14236
+ */
14237
+ record(envelope, action, proof) {
14238
+ const record = {
14239
+ record_id: uuidv43(),
14240
+ envelope_id: envelope.message_id ?? "unknown",
14241
+ action,
14242
+ actor_id: envelope.producer_id ?? "unknown",
14243
+ timestamp: nowHlcStub(),
14244
+ proof
14245
+ };
14246
+ const envelope_id = record.envelope_id;
14247
+ if (!this._records.has(envelope_id)) {
14248
+ this._records.set(envelope_id, []);
14249
+ }
14250
+ this._records.get(envelope_id).push(record);
14251
+ return record;
14252
+ }
14253
+ /**
14254
+ * Query all audit records for a specific envelope.
14255
+ *
14256
+ * @param envelope_id - The message_id of the envelope to query
14257
+ * @returns List of audit records for this envelope
14258
+ */
14259
+ query(envelope_id) {
14260
+ return this._records.get(envelope_id) ?? [];
14261
+ }
14262
+ /**
14263
+ * Get all audit records (useful for testing).
14264
+ *
14265
+ * @returns All audit records across all envelopes
14266
+ */
14267
+ getAllRecords() {
14268
+ const allRecords = [];
14269
+ for (const records of this._records.values()) {
14270
+ allRecords.push(...records);
14271
+ }
14272
+ return allRecords;
14273
+ }
14274
+ /**
14275
+ * Clear all stored records (useful for testing).
14276
+ */
14277
+ clear() {
14278
+ this._records.clear();
14279
+ }
14280
+ };
14281
+
14282
+ // src/agentConfig.ts
14283
+ var fs2 = __toESM(require("fs"), 1);
14284
+ var path4 = __toESM(require("path"), 1);
14285
+ function defaultEndpoints() {
14286
+ return {
14287
+ router: process.env.SW4RM_ROUTER_ADDR || "http://localhost:50051",
14288
+ registry: process.env.SW4RM_REGISTRY_ADDR || "http://localhost:50052",
14289
+ scheduler: process.env.SW4RM_SCHEDULER_ADDR || "http://localhost:50053",
14290
+ hitl: process.env.SW4RM_HITL_ADDR || "http://localhost:50054",
14291
+ worktree: process.env.SW4RM_WORKTREE_ADDR || "http://localhost:50055",
14292
+ tool: process.env.SW4RM_TOOL_ADDR || "http://localhost:50056",
14293
+ connector: process.env.SW4RM_CONNECTOR_ADDR || "http://localhost:50057",
14294
+ negotiation: process.env.SW4RM_NEGOTIATION_ADDR || "http://localhost:50058",
14295
+ reasoning: process.env.SW4RM_REASONING_ADDR || "http://localhost:50059",
14296
+ logging: process.env.SW4RM_LOGGING_ADDR || "http://localhost:50060"
14297
+ };
14298
+ }
14299
+ function defaultRetryPolicy() {
14300
+ return {
14301
+ maxAttempts: 3,
14302
+ initialBackoffMs: 200,
14303
+ maxBackoffMs: 2e3,
14304
+ multiplier: 2
14305
+ };
14306
+ }
14307
+ function defaultAgentConfig(agentId = "agent-1", name = "Agent") {
14308
+ return {
14309
+ agentId,
14310
+ name,
14311
+ description: void 0,
14312
+ version: "0.1.0",
14313
+ capabilities: [],
14314
+ endpoints: defaultEndpoints(),
14315
+ timeoutMs: 3e4,
14316
+ streamKeepaliveMs: 6e4,
14317
+ retry: defaultRetryPolicy(),
14318
+ metadata: {},
14319
+ communicationClass: 2,
14320
+ // STANDARD
14321
+ modalitiesSupported: ["application/json"],
14322
+ reasoningConnectors: [],
14323
+ publicKey: void 0
14324
+ };
14325
+ }
14326
+ function loadConfigFromEnv() {
14327
+ const config = defaultAgentConfig();
14328
+ if (process.env.AGENT_ID) {
14329
+ config.agentId = process.env.AGENT_ID;
14330
+ }
14331
+ if (process.env.AGENT_NAME) {
14332
+ config.name = process.env.AGENT_NAME;
14333
+ }
14334
+ if (process.env.AGENT_DESCRIPTION) {
14335
+ config.description = process.env.AGENT_DESCRIPTION;
14336
+ }
14337
+ if (process.env.AGENT_VERSION) {
14338
+ config.version = process.env.AGENT_VERSION;
14339
+ }
14340
+ if (process.env.AGENT_CAPABILITIES) {
14341
+ config.capabilities = process.env.AGENT_CAPABILITIES.split(",").map((s) => s.trim());
14342
+ }
14343
+ if (process.env.SW4RM_TIMEOUT_MS) {
14344
+ const timeout = parseInt(process.env.SW4RM_TIMEOUT_MS, 10);
14345
+ if (!isNaN(timeout)) {
14346
+ config.timeoutMs = timeout;
14347
+ }
14348
+ }
14349
+ if (process.env.SW4RM_STREAM_KEEPALIVE_MS) {
14350
+ const keepalive = parseInt(process.env.SW4RM_STREAM_KEEPALIVE_MS, 10);
14351
+ if (!isNaN(keepalive)) {
14352
+ config.streamKeepaliveMs = keepalive;
14353
+ }
14354
+ }
14355
+ if (process.env.SW4RM_RETRY_MAX_ATTEMPTS) {
14356
+ const attempts = parseInt(process.env.SW4RM_RETRY_MAX_ATTEMPTS, 10);
14357
+ if (!isNaN(attempts)) {
14358
+ config.retry.maxAttempts = attempts;
14359
+ }
14360
+ }
14361
+ if (process.env.SW4RM_COMMUNICATION_CLASS) {
14362
+ const cls = parseInt(process.env.SW4RM_COMMUNICATION_CLASS, 10);
14363
+ if (!isNaN(cls)) {
14364
+ config.communicationClass = cls;
14365
+ }
14366
+ }
14367
+ config.endpoints = defaultEndpoints();
14368
+ return config;
14369
+ }
14370
+ function defaultSW4RMConfig() {
14371
+ return {
14372
+ routerAddr: process.env.SW4RM_ROUTER_ADDR || "http://localhost:50051",
14373
+ registryAddr: process.env.SW4RM_REGISTRY_ADDR || "http://localhost:50052",
14374
+ defaultTimeoutMs: parseInt(process.env.SW4RM_DEFAULT_TIMEOUT_MS || "30000", 10),
14375
+ maxRetries: parseInt(process.env.SW4RM_MAX_RETRIES || "3", 10),
14376
+ enableMetrics: parseBool(process.env.SW4RM_ENABLE_METRICS, true),
14377
+ enableTracing: parseBool(process.env.SW4RM_ENABLE_TRACING, true),
14378
+ logLevel: process.env.SW4RM_LOG_LEVEL || "INFO",
14379
+ featureFlags: {}
14380
+ };
14381
+ }
14382
+ function parseBool(value, defaultValue) {
14383
+ if (value === void 0) {
14384
+ return defaultValue;
14385
+ }
14386
+ return ["true", "1", "yes", "on"].includes(value.toLowerCase());
14387
+ }
14388
+ function loadConfig(configPath) {
14389
+ let config = defaultSW4RMConfig();
14390
+ if (configPath) {
14391
+ if (!fs2.existsSync(configPath)) {
14392
+ throw new Error(`Configuration file not found: ${configPath}`);
14393
+ }
14394
+ const ext = path4.extname(configPath).toLowerCase();
14395
+ if (ext !== ".json") {
14396
+ throw new Error(
14397
+ `Unsupported configuration file format: ${ext}. Supported formats: .json`
14398
+ );
14399
+ }
14400
+ const fileContent = fs2.readFileSync(configPath, "utf8");
14401
+ const fileConfig = JSON.parse(fileContent);
14402
+ config = { ...config, ...fileConfig };
14403
+ }
14404
+ const envConfig = loadFromEnv();
14405
+ config = { ...config, ...envConfig };
14406
+ return config;
14407
+ }
14408
+ function loadFromEnv() {
14409
+ const envConfig = {};
14410
+ if (process.env.SW4RM_ROUTER_ADDR) {
14411
+ envConfig.routerAddr = process.env.SW4RM_ROUTER_ADDR;
14412
+ }
14413
+ if (process.env.SW4RM_REGISTRY_ADDR) {
14414
+ envConfig.registryAddr = process.env.SW4RM_REGISTRY_ADDR;
14415
+ }
14416
+ if (process.env.SW4RM_DEFAULT_TIMEOUT_MS) {
14417
+ const timeout = parseInt(process.env.SW4RM_DEFAULT_TIMEOUT_MS, 10);
14418
+ if (!isNaN(timeout)) {
14419
+ envConfig.defaultTimeoutMs = timeout;
14420
+ }
14421
+ }
14422
+ if (process.env.SW4RM_MAX_RETRIES) {
14423
+ const retries = parseInt(process.env.SW4RM_MAX_RETRIES, 10);
14424
+ if (!isNaN(retries)) {
14425
+ envConfig.maxRetries = retries;
14426
+ }
14427
+ }
14428
+ if (process.env.SW4RM_ENABLE_METRICS !== void 0) {
14429
+ envConfig.enableMetrics = parseBool(process.env.SW4RM_ENABLE_METRICS, true);
14430
+ }
14431
+ if (process.env.SW4RM_ENABLE_TRACING !== void 0) {
14432
+ envConfig.enableTracing = parseBool(process.env.SW4RM_ENABLE_TRACING, true);
14433
+ }
14434
+ if (process.env.SW4RM_LOG_LEVEL) {
14435
+ envConfig.logLevel = process.env.SW4RM_LOG_LEVEL.toUpperCase();
14436
+ }
14437
+ return envConfig;
14438
+ }
14439
+ var _globalConfig = null;
14440
+ function getConfig() {
14441
+ if (_globalConfig === null) {
14442
+ _globalConfig = loadConfig();
14443
+ }
14444
+ return _globalConfig;
14445
+ }
14446
+ function setConfig(config) {
14447
+ _globalConfig = config;
14448
+ }
14449
+ function resetConfig() {
14450
+ _globalConfig = null;
14451
+ }
14452
+
14453
+ // src/persistentActivityBuffer.ts
14454
+ var import_node_fs2 = require("node:fs");
14455
+ var import_node_path4 = require("node:path");
14456
+ var JSONFilePersistence2 = class {
14457
+ constructor(filePath = "sw4rm_activity.json") {
14458
+ this.filePath = filePath;
14459
+ }
14460
+ load() {
14461
+ if (!(0, import_node_fs2.existsSync)(this.filePath)) {
14462
+ return { records: {}, order: [] };
14463
+ }
14464
+ const raw = (0, import_node_fs2.readFileSync)(this.filePath, "utf-8");
14465
+ const data = JSON.parse(raw);
14466
+ return {
14467
+ records: data.records ?? {},
14468
+ order: data.order ?? []
14469
+ };
14470
+ }
14471
+ save(records, order) {
14472
+ const dir = (0, import_node_path4.dirname)(this.filePath);
14473
+ if (dir && !(0, import_node_fs2.existsSync)(dir)) {
14474
+ (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
14475
+ }
14476
+ (0, import_node_fs2.writeFileSync)(this.filePath, JSON.stringify({ records, order, version: "1.0" }, null, 2));
14477
+ }
14478
+ clear() {
14479
+ if ((0, import_node_fs2.existsSync)(this.filePath)) {
14480
+ (0, import_node_fs2.writeFileSync)(this.filePath, JSON.stringify({ records: {}, order: [], version: "1.0" }));
14481
+ }
14482
+ }
14483
+ };
14484
+ var PersistentActivityBuffer = class {
14485
+ byId = /* @__PURE__ */ new Map();
14486
+ byIdempotencyToken = /* @__PURE__ */ new Map();
14487
+ // token -> message_id
14488
+ order = [];
14489
+ maxItems;
14490
+ persistence;
14491
+ dedupWindowS;
14492
+ dirty = false;
14493
+ constructor(opts) {
14494
+ this.maxItems = opts?.maxItems ?? 1e4;
14495
+ this.persistence = opts?.persistence ?? new JSONFilePersistence2();
14496
+ this.dedupWindowS = opts?.dedupWindowS ?? 3600;
14497
+ this.loadFromPersistence();
14498
+ }
14499
+ loadFromPersistence() {
14500
+ try {
14501
+ const { records, order } = this.persistence.load();
14502
+ this.byId = new Map(Object.entries(records));
14503
+ this.order = order;
14504
+ for (const [mid, rec] of this.byId) {
14505
+ const token = rec.envelope?.idempotency_token;
14506
+ if (token) {
14507
+ this.byIdempotencyToken.set(token, mid);
14508
+ }
14509
+ }
14510
+ } catch {
14511
+ this.byId = /* @__PURE__ */ new Map();
14512
+ this.byIdempotencyToken = /* @__PURE__ */ new Map();
14513
+ this.order = [];
14514
+ }
14515
+ }
14516
+ saveToPersistence() {
14517
+ if (!this.dirty)
14518
+ return;
14519
+ try {
14520
+ const records = {};
14521
+ for (const [k, v] of this.byId) {
14522
+ records[k] = v;
14523
+ }
14524
+ this.persistence.save(records, this.order);
14525
+ this.dirty = false;
14526
+ } catch {
14527
+ }
14528
+ }
14529
+ checkCapacity() {
14530
+ if (this.byId.size >= this.maxItems) {
14531
+ throw new BufferFullError(
14532
+ `Activity buffer is full (max ${this.maxItems} items). Reject per spec.`,
14533
+ 1 /* BUFFER_FULL */
14534
+ );
14535
+ }
14536
+ }
14537
+ cleanupExpiredDedupEntries() {
14538
+ const nowMs = Date.now();
14539
+ const windowMs = this.dedupWindowS * 1e3;
14540
+ const expired = [];
14541
+ for (const [token, mid] of this.byIdempotencyToken) {
14542
+ const rec = this.byId.get(mid);
14543
+ if (rec && nowMs - rec.ts_ms > windowMs) {
14544
+ expired.push(token);
14545
+ }
14546
+ }
14547
+ for (const token of expired) {
14548
+ this.byIdempotencyToken.delete(token);
14549
+ }
14550
+ }
14551
+ /**
14552
+ * Record an incoming envelope. Throws BufferFullError if buffer is at capacity.
14553
+ */
14554
+ recordIncoming(envelope) {
14555
+ this.checkCapacity();
14556
+ const mid = String(envelope.message_id ?? "");
14557
+ const rec = {
14558
+ message_id: mid,
14559
+ direction: "in",
14560
+ envelope,
14561
+ ts_ms: Date.now(),
14562
+ ack_stage: 0 /* ACK_STAGE_UNSPECIFIED */,
14563
+ error_code: 0 /* ERROR_CODE_UNSPECIFIED */,
14564
+ ack_note: ""
14565
+ };
14566
+ this.byId.set(mid, rec);
14567
+ this.order.push(mid);
14568
+ const token = envelope.idempotency_token;
14569
+ if (token) {
14570
+ this.byIdempotencyToken.set(token, mid);
14571
+ }
14572
+ this.cleanupExpiredDedupEntries();
14573
+ this.dirty = true;
14574
+ return rec;
14575
+ }
14576
+ /**
14577
+ * Record an outgoing envelope. Throws BufferFullError if buffer is at capacity.
14578
+ */
14579
+ recordOutgoing(envelope) {
14580
+ this.checkCapacity();
14581
+ const mid = String(envelope.message_id ?? "");
14582
+ const rec = {
14583
+ message_id: mid,
14584
+ direction: "out",
14585
+ envelope,
14586
+ ts_ms: Date.now(),
14587
+ ack_stage: 0 /* ACK_STAGE_UNSPECIFIED */,
14588
+ error_code: 0 /* ERROR_CODE_UNSPECIFIED */,
14589
+ ack_note: ""
14590
+ };
14591
+ this.byId.set(mid, rec);
14592
+ this.order.push(mid);
14593
+ const token = envelope.idempotency_token;
14594
+ if (token) {
14595
+ this.byIdempotencyToken.set(token, mid);
14596
+ }
14597
+ this.cleanupExpiredDedupEntries();
14598
+ this.dirty = true;
14599
+ return rec;
14600
+ }
14601
+ /**
14602
+ * Process an ACK for a previously recorded message.
14603
+ */
14604
+ ack(ackMsg) {
14605
+ const target = String(ackMsg.ack_for_message_id);
14606
+ const rec = this.byId.get(target);
14607
+ if (rec) {
14608
+ rec.ack_stage = ackMsg.ack_stage ?? 0 /* ACK_STAGE_UNSPECIFIED */;
14609
+ rec.error_code = ackMsg.error_code ?? 0 /* ERROR_CODE_UNSPECIFIED */;
14610
+ rec.ack_note = ackMsg.note ?? "";
14611
+ this.dirty = true;
14612
+ }
14613
+ return rec;
14614
+ }
14615
+ /** Get record by message ID. */
14616
+ get(messageId) {
14617
+ return this.byId.get(messageId);
14618
+ }
14619
+ /** Get record by idempotency token (for deduplication). */
14620
+ getByIdempotencyToken(token) {
14621
+ this.cleanupExpiredDedupEntries();
14622
+ const mid = this.byIdempotencyToken.get(token);
14623
+ if (mid)
14624
+ return this.byId.get(mid);
14625
+ return void 0;
14626
+ }
14627
+ /** Get all un-ACKed records. */
14628
+ unacked() {
14629
+ return [...this.byId.values()].filter(
14630
+ (r) => r.ack_stage === 0 /* ACK_STAGE_UNSPECIFIED */ || r.ack_stage === 1 /* RECEIVED */ || r.ack_stage === 2 /* READ */
14631
+ );
14632
+ }
14633
+ /** Get N most recent records. */
14634
+ recent(n = 50) {
14635
+ const ids = this.order.slice(-n);
14636
+ return ids.map((id) => this.byId.get(id)).filter(Boolean);
14637
+ }
14638
+ /** Update envelope state for a message. */
14639
+ updateState(messageId, newState) {
14640
+ const rec = this.byId.get(messageId);
14641
+ if (rec) {
14642
+ rec.envelope.state = newState;
14643
+ this.dirty = true;
14644
+ }
14645
+ return rec;
14646
+ }
14647
+ /** Return unacked outgoing messages for reconciliation. */
14648
+ reconcile() {
14649
+ return this.unacked().filter((r) => r.direction === "out");
14650
+ }
14651
+ /** Force save to persistence. */
14652
+ flush() {
14653
+ this.dirty = true;
14654
+ this.saveToPersistence();
14655
+ }
14656
+ /** Clear all records. */
14657
+ clear() {
14658
+ this.byId.clear();
14659
+ this.byIdempotencyToken.clear();
14660
+ this.order = [];
14661
+ this.persistence.clear();
14662
+ this.dirty = false;
14663
+ }
14664
+ /** Get the count of records. */
14665
+ get size() {
14666
+ return this.byId.size;
14667
+ }
14668
+ };
14669
+
14670
+ // src/secrets/types.ts
14671
+ var SecretSource = /* @__PURE__ */ ((SecretSource2) => {
14672
+ SecretSource2["CLI"] = "cli";
14673
+ SecretSource2["ENV"] = "env";
14674
+ SecretSource2["SCOPED"] = "scoped";
14675
+ SecretSource2["GLOBAL"] = "global";
14676
+ return SecretSource2;
14677
+ })(SecretSource || {});
14678
+ var Scope = class {
14679
+ constructor(name = null) {
14680
+ this.name = name;
14681
+ }
14682
+ get isGlobal() {
14683
+ return this.name === null;
14684
+ }
14685
+ label() {
14686
+ return this.name ?? "global";
14687
+ }
14688
+ };
14689
+ var SecretKey = class {
14690
+ constructor(key) {
14691
+ this.key = key;
14692
+ if (!key || key.split(".").some((p) => p.trim() === "")) {
14693
+ throw new Error("secret key must be dotted identifiers without empty segments");
14694
+ }
14695
+ }
14696
+ };
14697
+ var SecretValue = class _SecretValue {
14698
+ constructor(value) {
14699
+ this.value = value;
14700
+ if (value.length > _SecretValue.MAX_LEN) {
14701
+ throw new Error("secret value exceeds maximum allowed length (8KB)");
14702
+ }
14703
+ }
14704
+ static MAX_LEN = 8 * 1024;
14705
+ };
14706
+
14707
+ // src/secrets/errors.ts
14708
+ var SecretError = class extends Error {
14709
+ };
14710
+ var SecretNotFound = class extends SecretError {
14711
+ constructor(scope, key) {
14712
+ super(`secret not found: scope=${scope} key=${key}`);
14713
+ this.scope = scope;
14714
+ this.key = key;
14715
+ }
14716
+ };
14717
+ var SecretBackendError = class extends SecretError {
14718
+ };
14719
+ var SecretPermissionError = class extends SecretError {
14720
+ };
14721
+ var SecretValidationError = class extends SecretError {
14722
+ };
14723
+
14724
+ // src/secrets/backend.ts
14725
+ var Secrets = class {
14726
+ constructor(backend) {
14727
+ this.backend = backend;
14728
+ }
14729
+ set(scope, key, value) {
14730
+ return this.backend.set(scope, key, value);
14731
+ }
14732
+ get(scope, key) {
14733
+ return this.backend.get(scope, key);
14734
+ }
14735
+ list(scope) {
14736
+ return this.backend.list(scope);
14737
+ }
14738
+ };
14739
+
14740
+ // src/secrets/resolver.ts
14741
+ var Resolver = class {
14742
+ constructor(backend, env = process.env) {
14743
+ this.backend = backend;
14744
+ this.env = env;
14745
+ }
14746
+ async resolve(key, scope, opts) {
14747
+ const explicit = opts?.explicit ?? null;
14748
+ const envVar = opts?.envVar ?? null;
14749
+ if (explicit !== null)
14750
+ return [explicit, "cli" /* CLI */];
14751
+ if (envVar && this.env[envVar] && this.env[envVar] !== "")
14752
+ return [this.env[envVar], "env" /* ENV */];
13136
14753
  try {
13137
14754
  const v = await this.backend.get(scope, key);
13138
14755
  return [v, scope.isGlobal ? "global" /* GLOBAL */ : "scoped" /* SCOPED */];
@@ -13147,28 +14764,28 @@ var Resolver = class {
13147
14764
  };
13148
14765
 
13149
14766
  // src/secrets/backends/file.ts
13150
- var import_node_fs = require("node:fs");
13151
- var import_node_path4 = require("node:path");
14767
+ var import_node_fs3 = require("node:fs");
14768
+ var import_node_path5 = require("node:path");
13152
14769
  function defaultPath() {
13153
14770
  const isWin = process.platform === "win32";
13154
14771
  if (isWin) {
13155
- const base2 = process.env.APPDATA || (0, import_node_path4.join)(process.env.USERPROFILE || "", "AppData", "Roaming");
13156
- return (0, import_node_path4.join)(base2, "sw4rm", "secrets.json");
14772
+ const base2 = process.env.APPDATA || (0, import_node_path5.join)(process.env.USERPROFILE || "", "AppData", "Roaming");
14773
+ return (0, import_node_path5.join)(base2, "sw4rm", "secrets.json");
13157
14774
  }
13158
14775
  const xdg = process.env.XDG_CONFIG_HOME;
13159
- const base = xdg && xdg.length > 0 ? xdg : (0, import_node_path4.join)(process.env.HOME || "", ".config");
13160
- return (0, import_node_path4.join)(base, "sw4rm", "secrets.json");
14776
+ const base = xdg && xdg.length > 0 ? xdg : (0, import_node_path5.join)(process.env.HOME || "", ".config");
14777
+ return (0, import_node_path5.join)(base, "sw4rm", "secrets.json");
13161
14778
  }
13162
14779
  var FileBackend = class {
13163
14780
  path;
13164
- constructor(path4) {
13165
- this.path = path4 ?? defaultPath();
13166
- (0, import_node_fs.mkdirSync)((0, import_node_path4.dirname)(this.path), { recursive: true });
14781
+ constructor(path7) {
14782
+ this.path = path7 ?? defaultPath();
14783
+ (0, import_node_fs3.mkdirSync)((0, import_node_path5.dirname)(this.path), { recursive: true });
13167
14784
  try {
13168
- (0, import_node_fs.chmodSync)((0, import_node_path4.dirname)(this.path), 448);
14785
+ (0, import_node_fs3.chmodSync)((0, import_node_path5.dirname)(this.path), 448);
13169
14786
  } catch {
13170
14787
  }
13171
- if (!(0, import_node_fs.existsSync)(this.path)) {
14788
+ if (!(0, import_node_fs3.existsSync)(this.path)) {
13172
14789
  this.safeWrite({});
13173
14790
  this.enforceFilePerms();
13174
14791
  } else {
@@ -13178,17 +14795,17 @@ var FileBackend = class {
13178
14795
  enforceFilePerms() {
13179
14796
  if (process.platform !== "win32") {
13180
14797
  try {
13181
- (0, import_node_fs.chmodSync)(this.path, 384);
14798
+ (0, import_node_fs3.chmodSync)(this.path, 384);
13182
14799
  } catch (e) {
13183
14800
  throw new SecretPermissionError(String(e));
13184
14801
  }
13185
14802
  }
13186
14803
  }
13187
14804
  safeWrite(obj) {
13188
- const tmp = (0, import_node_path4.join)((0, import_node_path4.dirname)(this.path), `.secrets.${Date.now()}.${Math.random().toString(16).slice(2)}`);
14805
+ const tmp = (0, import_node_path5.join)((0, import_node_path5.dirname)(this.path), `.secrets.${Date.now()}.${Math.random().toString(16).slice(2)}`);
13189
14806
  try {
13190
- (0, import_node_fs.writeFileSync)(tmp, JSON.stringify(obj, null, 2), { encoding: "utf8", mode: 384 });
13191
- (0, import_node_fs.renameSync)(tmp, this.path);
14807
+ (0, import_node_fs3.writeFileSync)(tmp, JSON.stringify(obj, null, 2), { encoding: "utf8", mode: 384 });
14808
+ (0, import_node_fs3.renameSync)(tmp, this.path);
13192
14809
  this.enforceFilePerms();
13193
14810
  } catch (e) {
13194
14811
  throw new SecretBackendError(String(e));
@@ -13196,7 +14813,7 @@ var FileBackend = class {
13196
14813
  }
13197
14814
  load() {
13198
14815
  try {
13199
- const s = (0, import_node_fs.readFileSync)(this.path, { encoding: "utf8" });
14816
+ const s = (0, import_node_fs3.readFileSync)(this.path, { encoding: "utf8" });
13200
14817
  return JSON.parse(s);
13201
14818
  } catch (e) {
13202
14819
  if (e.code === "ENOENT")
@@ -13292,58 +14909,940 @@ async function selectBackend(mode) {
13292
14909
  }
13293
14910
  }
13294
14911
 
14912
+ // src/llm/client.ts
14913
+ var LlmError = class extends Error {
14914
+ constructor(message) {
14915
+ super(message);
14916
+ this.name = "LlmError";
14917
+ Object.setPrototypeOf(this, new.target.prototype);
14918
+ }
14919
+ };
14920
+ var LlmAuthenticationError = class extends LlmError {
14921
+ constructor(message) {
14922
+ super(message);
14923
+ this.name = "LlmAuthenticationError";
14924
+ }
14925
+ };
14926
+ var LlmRateLimitError = class extends LlmError {
14927
+ constructor(message) {
14928
+ super(message);
14929
+ this.name = "LlmRateLimitError";
14930
+ }
14931
+ };
14932
+ var LlmTimeoutError = class extends LlmError {
14933
+ constructor(message) {
14934
+ super(message);
14935
+ this.name = "LlmTimeoutError";
14936
+ }
14937
+ };
14938
+ var LlmContextLengthError = class extends LlmError {
14939
+ constructor(message) {
14940
+ super(message);
14941
+ this.name = "LlmContextLengthError";
14942
+ }
14943
+ };
14944
+
14945
+ // src/llm/rateLimiter.ts
14946
+ function envBool(name, defaultVal) {
14947
+ const raw = (process.env[name] ?? defaultVal).toLowerCase();
14948
+ return !["0", "false", "no"].includes(raw);
14949
+ }
14950
+ function buildRateLimiterConfig(overrides) {
14951
+ return {
14952
+ tokensPerMinute: overrides?.tokensPerMinute ?? parseInt(process.env["LLM_RATE_LIMIT_TOKENS_PER_MIN"] ?? "250000", 10),
14953
+ burstAllowance: overrides?.burstAllowance ?? 1,
14954
+ minTokensPerRequest: overrides?.minTokensPerRequest ?? 100,
14955
+ maxWaitSeconds: overrides?.maxWaitSeconds ?? 120,
14956
+ enabled: overrides?.enabled ?? envBool("LLM_RATE_LIMIT_ENABLED", "1"),
14957
+ adaptiveEnabled: overrides?.adaptiveEnabled ?? envBool("LLM_RATE_LIMIT_ADAPTIVE", "1"),
14958
+ reductionFactor: overrides?.reductionFactor ?? parseFloat(process.env["LLM_RATE_LIMIT_REDUCTION_FACTOR"] ?? "0.7"),
14959
+ recoveryFactor: overrides?.recoveryFactor ?? parseFloat(process.env["LLM_RATE_LIMIT_RECOVERY_FACTOR"] ?? "1.1"),
14960
+ cooldownSeconds: overrides?.cooldownSeconds ?? parseFloat(process.env["LLM_RATE_LIMIT_COOLDOWN_SECONDS"] ?? "30"),
14961
+ successesForRecovery: overrides?.successesForRecovery ?? parseInt(
14962
+ process.env["LLM_RATE_LIMIT_RECOVERY_SUCCESS_THRESHOLD"] ?? "20",
14963
+ 10
14964
+ )
14965
+ };
14966
+ }
14967
+ var TokenBucket = class {
14968
+ config;
14969
+ baseTpm;
14970
+ currentTpm;
14971
+ minTpm;
14972
+ tokens;
14973
+ lastRefill;
14974
+ lastRateLimitTime = null;
14975
+ successesSinceLimit = 0;
14976
+ constructor(config) {
14977
+ this.config = buildRateLimiterConfig(config);
14978
+ this.baseTpm = this.config.tokensPerMinute;
14979
+ this.currentTpm = this.config.tokensPerMinute;
14980
+ this.minTpm = Math.max(1e3, this.baseTpm * 0.25);
14981
+ this.tokens = this.currentTpm;
14982
+ this.lastRefill = performance.now();
14983
+ }
14984
+ // -- Internal helpers ----------------------------------------------------
14985
+ refill() {
14986
+ const now = performance.now();
14987
+ const elapsedSeconds = (now - this.lastRefill) / 1e3;
14988
+ const refill = elapsedSeconds * (this.currentTpm / 60);
14989
+ this.tokens = Math.min(
14990
+ this.tokens + refill,
14991
+ this.currentTpm * this.config.burstAllowance
14992
+ );
14993
+ this.lastRefill = now;
14994
+ this.maybeRecover(now);
14995
+ }
14996
+ maybeRecover(now) {
14997
+ if (!this.config.adaptiveEnabled)
14998
+ return;
14999
+ if (this.currentTpm >= this.baseTpm)
15000
+ return;
15001
+ if (this.lastRateLimitTime === null)
15002
+ return;
15003
+ if ((now - this.lastRateLimitTime) / 1e3 < this.config.cooldownSeconds)
15004
+ return;
15005
+ if (this.successesSinceLimit < this.config.successesForRecovery)
15006
+ return;
15007
+ const newLimit = Math.min(
15008
+ this.baseTpm,
15009
+ this.currentTpm * this.config.recoveryFactor
15010
+ );
15011
+ if (newLimit > this.currentTpm) {
15012
+ this.currentTpm = newLimit;
15013
+ this.successesSinceLimit = 0;
15014
+ }
15015
+ }
15016
+ // -- Public API ----------------------------------------------------------
15017
+ /**
15018
+ * Acquire tokens, waiting if necessary.
15019
+ *
15020
+ * @param estimatedTokens - Estimated token count for the request.
15021
+ * @returns Time spent waiting in milliseconds (0 if immediate).
15022
+ * @throws Error if waiting exceeds {@link RateLimiterConfig.maxWaitSeconds}.
15023
+ */
15024
+ async acquire(estimatedTokens) {
15025
+ if (!this.config.enabled)
15026
+ return 0;
15027
+ estimatedTokens = Math.max(estimatedTokens, this.config.minTokensPerRequest);
15028
+ const waitStart = performance.now();
15029
+ for (; ; ) {
15030
+ this.refill();
15031
+ if (this.tokens >= estimatedTokens) {
15032
+ this.tokens -= estimatedTokens;
15033
+ return performance.now() - waitStart;
15034
+ }
15035
+ const elapsed = (performance.now() - waitStart) / 1e3;
15036
+ if (elapsed >= this.config.maxWaitSeconds) {
15037
+ throw new Error(
15038
+ `Rate limiter: waited ${elapsed.toFixed(1)}s for ${estimatedTokens} tokens`
15039
+ );
15040
+ }
15041
+ await new Promise((resolve) => setTimeout(resolve, 250));
15042
+ }
15043
+ }
15044
+ /**
15045
+ * Record a 429 event -- adaptively reduce budget.
15046
+ *
15047
+ * Call this when the upstream API returns HTTP 429 or an equivalent
15048
+ * rate-limit error.
15049
+ */
15050
+ recordRateLimit() {
15051
+ if (!(this.config.enabled && this.config.adaptiveEnabled))
15052
+ return;
15053
+ this.lastRateLimitTime = performance.now();
15054
+ this.successesSinceLimit = 0;
15055
+ const newLimit = Math.max(
15056
+ this.minTpm,
15057
+ this.currentTpm * this.config.reductionFactor
15058
+ );
15059
+ if (newLimit < this.currentTpm) {
15060
+ this.currentTpm = newLimit;
15061
+ this.tokens = Math.min(this.tokens, this.currentTpm);
15062
+ }
15063
+ }
15064
+ /**
15065
+ * Record a successful request for adaptive recovery.
15066
+ *
15067
+ * Call this after each successful API response.
15068
+ */
15069
+ recordSuccess() {
15070
+ if (!(this.config.enabled && this.config.adaptiveEnabled))
15071
+ return;
15072
+ this.successesSinceLimit += 1;
15073
+ }
15074
+ /** Current available token count. */
15075
+ get availableTokens() {
15076
+ return this.tokens;
15077
+ }
15078
+ /** Current tokens-per-minute budget (may be reduced after 429). */
15079
+ get currentTokensPerMinute() {
15080
+ return this.currentTpm;
15081
+ }
15082
+ };
15083
+ var globalBucket = null;
15084
+ function getGlobalRateLimiter(config) {
15085
+ if (globalBucket === null) {
15086
+ globalBucket = new TokenBucket(config);
15087
+ }
15088
+ return globalBucket;
15089
+ }
15090
+ function resetGlobalRateLimiter() {
15091
+ globalBucket = null;
15092
+ }
15093
+
15094
+ // src/llm/mock.ts
15095
+ var MockLlmClient = class {
15096
+ /** The model name returned in responses. */
15097
+ defaultModel;
15098
+ responses;
15099
+ responseIndex = 0;
15100
+ responseGenerator;
15101
+ _callCount = 0;
15102
+ _callHistory = [];
15103
+ constructor(opts) {
15104
+ this.defaultModel = opts?.defaultModel ?? "mock-model";
15105
+ this.responses = opts?.responses ?? [];
15106
+ this.responseGenerator = opts?.responseGenerator;
15107
+ }
15108
+ /** Number of queries made to this client. */
15109
+ get callCount() {
15110
+ return this._callCount;
15111
+ }
15112
+ /** History of all calls made to this client. */
15113
+ get callHistory() {
15114
+ return this._callHistory;
15115
+ }
15116
+ /** Reset call count, history, and response index. */
15117
+ reset() {
15118
+ this._callCount = 0;
15119
+ this._callHistory.length = 0;
15120
+ this.responseIndex = 0;
15121
+ }
15122
+ /**
15123
+ * Return a mock response.
15124
+ *
15125
+ * Priority for determining response content:
15126
+ * 1. `responseGenerator` function (if provided)
15127
+ * 2. `responses` array (cycles through entries)
15128
+ * 3. Default echo: "Mock response to: <prompt>"
15129
+ *
15130
+ * @param prompt - The prompt (recorded in history).
15131
+ * @param opts - Optional query configuration (recorded in history).
15132
+ * @returns LlmResponse with mock content.
15133
+ */
15134
+ async query(prompt, opts) {
15135
+ const model = opts?.model ?? this.defaultModel;
15136
+ const maxTokens = opts?.maxTokens ?? 4096;
15137
+ const temperature = opts?.temperature ?? 1;
15138
+ this._callCount += 1;
15139
+ this._callHistory.push({
15140
+ prompt,
15141
+ systemPrompt: opts?.systemPrompt,
15142
+ maxTokens,
15143
+ temperature,
15144
+ model
15145
+ });
15146
+ let content;
15147
+ if (this.responseGenerator) {
15148
+ content = this.responseGenerator(prompt);
15149
+ } else if (this.responses.length > 0) {
15150
+ content = this.responses[this.responseIndex % this.responses.length];
15151
+ this.responseIndex += 1;
15152
+ } else {
15153
+ content = `Mock response to: ${prompt.slice(0, 100)}`;
15154
+ }
15155
+ return {
15156
+ content,
15157
+ model,
15158
+ usage: {
15159
+ input_tokens: Math.max(Math.floor(prompt.length / 4), 1),
15160
+ output_tokens: Math.max(Math.floor(content.length / 4), 1)
15161
+ },
15162
+ metadata: { mock: true, call_count: this._callCount }
15163
+ };
15164
+ }
15165
+ /**
15166
+ * Stream a mock response.
15167
+ *
15168
+ * Yields the response word by word to simulate streaming.
15169
+ *
15170
+ * @param prompt - The prompt (recorded in history).
15171
+ * @param opts - Optional query configuration.
15172
+ * @yields Words from the mock response.
15173
+ */
15174
+ async *streamQuery(prompt, opts) {
15175
+ const response = await this.query(prompt, opts);
15176
+ const words = response.content.split(" ");
15177
+ for (let i = 0; i < words.length; i++) {
15178
+ yield words[i] + (i < words.length - 1 ? " " : "");
15179
+ }
15180
+ }
15181
+ };
15182
+
15183
+ // src/llm/groq.ts
15184
+ var import_node_fs4 = __toESM(require("node:fs"), 1);
15185
+ var import_node_os = __toESM(require("node:os"), 1);
15186
+ var import_node_path6 = __toESM(require("node:path"), 1);
15187
+ var DEFAULT_MODEL = "llama-3.3-70b-versatile";
15188
+ var BASE_URL = "https://api.groq.com/openai/v1/chat/completions";
15189
+ var GroqClient = class _GroqClient {
15190
+ /** The resolved API key. */
15191
+ apiKey;
15192
+ /** The default model used when none is specified per-call. */
15193
+ defaultModel;
15194
+ timeoutMs;
15195
+ rateLimiter;
15196
+ constructor(opts) {
15197
+ this.defaultModel = opts?.defaultModel ?? process.env["GROQ_DEFAULT_MODEL"] ?? DEFAULT_MODEL;
15198
+ const envKey = process.env["GROQ_API_KEY"]?.trim();
15199
+ const resolved = opts?.apiKey ?? envKey ?? _GroqClient.loadKeyFile();
15200
+ if (!resolved) {
15201
+ throw new LlmAuthenticationError(
15202
+ "No Groq API key. Set GROQ_API_KEY, pass apiKey, or create ~/.groq"
15203
+ );
15204
+ }
15205
+ this.apiKey = resolved;
15206
+ this.timeoutMs = opts?.timeoutMs ?? 12e4;
15207
+ this.rateLimiter = getGlobalRateLimiter();
15208
+ }
15209
+ /**
15210
+ * Load API key from ~/.groq file.
15211
+ *
15212
+ * @returns The key string, or null if the file does not exist.
15213
+ */
15214
+ static loadKeyFile() {
15215
+ try {
15216
+ const keyPath = import_node_path6.default.join(import_node_os.default.homedir(), ".groq");
15217
+ if (import_node_fs4.default.existsSync(keyPath)) {
15218
+ return import_node_fs4.default.readFileSync(keyPath, "utf-8").trim();
15219
+ }
15220
+ } catch {
15221
+ }
15222
+ return null;
15223
+ }
15224
+ // -- Helpers -------------------------------------------------------------
15225
+ estimateTokens(prompt, systemPrompt) {
15226
+ let total = prompt.length;
15227
+ if (systemPrompt)
15228
+ total += systemPrompt.length;
15229
+ return Math.max(Math.floor(total / 4), 100);
15230
+ }
15231
+ buildMessages(prompt, systemPrompt) {
15232
+ const messages = [];
15233
+ if (systemPrompt) {
15234
+ messages.push({ role: "system", content: systemPrompt });
15235
+ }
15236
+ messages.push({ role: "user", content: prompt });
15237
+ return messages;
15238
+ }
15239
+ /**
15240
+ * Map an HTTP error response to the appropriate LlmError subclass.
15241
+ *
15242
+ * @param status - HTTP status code.
15243
+ * @param body - Parsed response body (if available).
15244
+ * @param message - Raw error message.
15245
+ */
15246
+ mapError(status, body, message) {
15247
+ if (status === 401 || status === 403) {
15248
+ return new LlmAuthenticationError(`Groq auth failed (${status}): ${message}`);
15249
+ }
15250
+ if (status === 429) {
15251
+ this.rateLimiter.recordRateLimit();
15252
+ return new LlmRateLimitError(`Groq rate limit exceeded: ${message}`);
15253
+ }
15254
+ if (status === 408 || status === 504) {
15255
+ return new LlmTimeoutError(`Groq request timed out (${status}): ${message}`);
15256
+ }
15257
+ const errorObj = body?.["error"];
15258
+ const code = errorObj?.["code"];
15259
+ if (code === "context_length_exceeded") {
15260
+ return new LlmContextLengthError(`Groq context length exceeded: ${message}`);
15261
+ }
15262
+ return new LlmError(`Groq API error (${status}): ${message}`);
15263
+ }
15264
+ // -- Public API ----------------------------------------------------------
15265
+ /**
15266
+ * Send a query to Groq and get a complete response.
15267
+ *
15268
+ * @param prompt - The user prompt/query.
15269
+ * @param opts - Optional query configuration.
15270
+ * @returns LlmResponse with generated content and metadata.
15271
+ */
15272
+ async query(prompt, opts) {
15273
+ const useModel = opts?.model ?? this.defaultModel;
15274
+ const maxTokens = opts?.maxTokens ?? 4096;
15275
+ const temperature = opts?.temperature ?? 1;
15276
+ const systemPrompt = opts?.systemPrompt;
15277
+ const estimated = this.estimateTokens(prompt, systemPrompt);
15278
+ await this.rateLimiter.acquire(estimated);
15279
+ const body = {
15280
+ model: useModel,
15281
+ messages: this.buildMessages(prompt, systemPrompt),
15282
+ max_tokens: maxTokens,
15283
+ temperature
15284
+ };
15285
+ let response;
15286
+ try {
15287
+ const controller = new AbortController();
15288
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
15289
+ response = await fetch(BASE_URL, {
15290
+ method: "POST",
15291
+ headers: {
15292
+ "Content-Type": "application/json",
15293
+ "Authorization": `Bearer ${this.apiKey}`
15294
+ },
15295
+ body: JSON.stringify(body),
15296
+ signal: controller.signal
15297
+ });
15298
+ clearTimeout(timer);
15299
+ } catch (err) {
15300
+ if (err instanceof Error && err.name === "AbortError") {
15301
+ throw new LlmTimeoutError(`Groq request timed out after ${this.timeoutMs}ms`);
15302
+ }
15303
+ throw new LlmError(`Groq network error: ${String(err)}`);
15304
+ }
15305
+ if (!response.ok) {
15306
+ let errorBody = null;
15307
+ let errorMessage = response.statusText;
15308
+ try {
15309
+ errorBody = await response.json();
15310
+ const errorObj = errorBody?.["error"];
15311
+ errorMessage = errorObj?.["message"] ?? errorMessage;
15312
+ } catch {
15313
+ }
15314
+ throw this.mapError(response.status, errorBody, errorMessage);
15315
+ }
15316
+ const data = await response.json();
15317
+ this.rateLimiter.recordSuccess();
15318
+ const choices = data["choices"];
15319
+ const firstChoice = choices?.[0];
15320
+ const messageObj = firstChoice?.["message"];
15321
+ const content = messageObj?.["content"] ?? "";
15322
+ const usageObj = data["usage"];
15323
+ let usage;
15324
+ if (usageObj) {
15325
+ usage = {
15326
+ input_tokens: usageObj["prompt_tokens"] ?? 0,
15327
+ output_tokens: usageObj["completion_tokens"] ?? 0
15328
+ };
15329
+ }
15330
+ return {
15331
+ content,
15332
+ model: data["model"] ?? useModel,
15333
+ usage
15334
+ };
15335
+ }
15336
+ /**
15337
+ * Stream a query response chunk by chunk.
15338
+ *
15339
+ * Uses Server-Sent Events (SSE) streaming from the Groq API.
15340
+ *
15341
+ * @param prompt - The user prompt/query.
15342
+ * @param opts - Optional query configuration.
15343
+ * @yields Text chunks as they arrive from the API.
15344
+ */
15345
+ async *streamQuery(prompt, opts) {
15346
+ const useModel = opts?.model ?? this.defaultModel;
15347
+ const maxTokens = opts?.maxTokens ?? 4096;
15348
+ const temperature = opts?.temperature ?? 1;
15349
+ const systemPrompt = opts?.systemPrompt;
15350
+ const estimated = this.estimateTokens(prompt, systemPrompt);
15351
+ await this.rateLimiter.acquire(estimated);
15352
+ const body = {
15353
+ model: useModel,
15354
+ messages: this.buildMessages(prompt, systemPrompt),
15355
+ max_tokens: maxTokens,
15356
+ temperature,
15357
+ stream: true
15358
+ };
15359
+ let response;
15360
+ try {
15361
+ const controller = new AbortController();
15362
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
15363
+ response = await fetch(BASE_URL, {
15364
+ method: "POST",
15365
+ headers: {
15366
+ "Content-Type": "application/json",
15367
+ "Authorization": `Bearer ${this.apiKey}`
15368
+ },
15369
+ body: JSON.stringify(body),
15370
+ signal: controller.signal
15371
+ });
15372
+ clearTimeout(timer);
15373
+ } catch (err) {
15374
+ if (err instanceof Error && err.name === "AbortError") {
15375
+ throw new LlmTimeoutError(`Groq request timed out after ${this.timeoutMs}ms`);
15376
+ }
15377
+ throw new LlmError(`Groq network error: ${String(err)}`);
15378
+ }
15379
+ if (!response.ok) {
15380
+ let errorBody = null;
15381
+ let errorMessage = response.statusText;
15382
+ try {
15383
+ errorBody = await response.json();
15384
+ const errorObj = errorBody?.["error"];
15385
+ errorMessage = errorObj?.["message"] ?? errorMessage;
15386
+ } catch {
15387
+ }
15388
+ throw this.mapError(response.status, errorBody, errorMessage);
15389
+ }
15390
+ if (!response.body) {
15391
+ throw new LlmError("Groq streaming response has no body");
15392
+ }
15393
+ const reader = response.body.getReader();
15394
+ const decoder = new TextDecoder();
15395
+ let buffer = "";
15396
+ let streamCompleted = false;
15397
+ try {
15398
+ for (; ; ) {
15399
+ const { done, value } = await reader.read();
15400
+ if (done)
15401
+ break;
15402
+ buffer += decoder.decode(value, { stream: true });
15403
+ const lines = buffer.split("\n");
15404
+ buffer = lines.pop() ?? "";
15405
+ for (const line of lines) {
15406
+ const trimmed = line.trim();
15407
+ if (!trimmed || !trimmed.startsWith("data: "))
15408
+ continue;
15409
+ const payload = trimmed.slice(6);
15410
+ if (payload === "[DONE]") {
15411
+ streamCompleted = true;
15412
+ return;
15413
+ }
15414
+ try {
15415
+ const chunk = JSON.parse(payload);
15416
+ const choices = chunk["choices"];
15417
+ const delta = choices?.[0]?.["delta"];
15418
+ const content = delta?.["content"];
15419
+ if (content)
15420
+ yield content;
15421
+ } catch {
15422
+ }
15423
+ }
15424
+ }
15425
+ streamCompleted = true;
15426
+ } finally {
15427
+ reader.releaseLock();
15428
+ if (streamCompleted)
15429
+ this.rateLimiter.recordSuccess();
15430
+ }
15431
+ }
15432
+ };
15433
+
15434
+ // src/llm/anthropic.ts
15435
+ var import_node_fs5 = __toESM(require("node:fs"), 1);
15436
+ var import_node_os2 = __toESM(require("node:os"), 1);
15437
+ var import_node_path7 = __toESM(require("node:path"), 1);
15438
+ var DEFAULT_MODEL2 = "claude-sonnet-4-20250514";
15439
+ var BASE_URL2 = "https://api.anthropic.com/v1/messages";
15440
+ var ANTHROPIC_VERSION = "2023-06-01";
15441
+ var AnthropicClient = class _AnthropicClient {
15442
+ /** The resolved API key. */
15443
+ apiKey;
15444
+ /** The default model used when none is specified per-call. */
15445
+ defaultModel;
15446
+ timeoutMs;
15447
+ rateLimiter;
15448
+ constructor(opts) {
15449
+ this.defaultModel = opts?.defaultModel ?? process.env["ANTHROPIC_DEFAULT_MODEL"] ?? DEFAULT_MODEL2;
15450
+ const envKey = process.env["ANTHROPIC_API_KEY"]?.trim();
15451
+ const resolved = opts?.apiKey ?? envKey ?? _AnthropicClient.loadKeyFile();
15452
+ if (!resolved) {
15453
+ throw new LlmAuthenticationError(
15454
+ "No Anthropic API key. Set ANTHROPIC_API_KEY, pass apiKey, or create ~/.anthropic"
15455
+ );
15456
+ }
15457
+ this.apiKey = resolved;
15458
+ this.timeoutMs = opts?.timeoutMs ?? 3e5;
15459
+ this.rateLimiter = getGlobalRateLimiter();
15460
+ }
15461
+ /**
15462
+ * Load API key from ~/.anthropic file.
15463
+ *
15464
+ * @returns The key string, or null if the file does not exist.
15465
+ */
15466
+ static loadKeyFile() {
15467
+ try {
15468
+ const keyPath = import_node_path7.default.join(import_node_os2.default.homedir(), ".anthropic");
15469
+ if (import_node_fs5.default.existsSync(keyPath)) {
15470
+ return import_node_fs5.default.readFileSync(keyPath, "utf-8").trim();
15471
+ }
15472
+ } catch {
15473
+ }
15474
+ return null;
15475
+ }
15476
+ // -- Helpers -------------------------------------------------------------
15477
+ estimateTokens(prompt, systemPrompt) {
15478
+ let total = prompt.length;
15479
+ if (systemPrompt)
15480
+ total += systemPrompt.length;
15481
+ return Math.max(Math.floor(total / 4), 100);
15482
+ }
15483
+ /**
15484
+ * Map an HTTP error response to the appropriate LlmError subclass.
15485
+ *
15486
+ * @param status - HTTP status code.
15487
+ * @param body - Parsed response body (if available).
15488
+ * @param message - Raw error message.
15489
+ */
15490
+ mapError(status, body, message) {
15491
+ if (status === 401 || status === 403) {
15492
+ return new LlmAuthenticationError(
15493
+ `Anthropic auth failed (${status}): ${message}`
15494
+ );
15495
+ }
15496
+ if (status === 429) {
15497
+ this.rateLimiter.recordRateLimit();
15498
+ return new LlmRateLimitError(
15499
+ `Anthropic rate limit exceeded: ${message}`
15500
+ );
15501
+ }
15502
+ if (status === 408 || status === 504) {
15503
+ return new LlmTimeoutError(
15504
+ `Anthropic request timed out (${status}): ${message}`
15505
+ );
15506
+ }
15507
+ const errorType = body?.["error"];
15508
+ const errType = errorType?.["type"];
15509
+ if (errType === "invalid_request_error") {
15510
+ const msg = message.toLowerCase();
15511
+ if (msg.includes("context") || msg.includes("token")) {
15512
+ return new LlmContextLengthError(
15513
+ `Anthropic context length exceeded: ${message}`
15514
+ );
15515
+ }
15516
+ }
15517
+ const lowerMsg = message.toLowerCase();
15518
+ if (lowerMsg.includes("credit balance") || lowerMsg.includes("billing")) {
15519
+ return new LlmAuthenticationError(
15520
+ `Anthropic billing error: ${message}`
15521
+ );
15522
+ }
15523
+ return new LlmError(`Anthropic API error (${status}): ${message}`);
15524
+ }
15525
+ // -- Public API ----------------------------------------------------------
15526
+ /**
15527
+ * Send a query to Anthropic and get a complete response.
15528
+ *
15529
+ * System prompts are sent via the top-level `system` parameter rather
15530
+ * than as a system message in the messages array, per the Anthropic API
15531
+ * specification.
15532
+ *
15533
+ * @param prompt - The user prompt/query.
15534
+ * @param opts - Optional query configuration.
15535
+ * @returns LlmResponse with generated content and metadata.
15536
+ */
15537
+ async query(prompt, opts) {
15538
+ const useModel = opts?.model ?? this.defaultModel;
15539
+ const maxTokens = opts?.maxTokens ?? 4096;
15540
+ const temperature = opts?.temperature ?? 1;
15541
+ const systemPrompt = opts?.systemPrompt;
15542
+ const estimated = this.estimateTokens(prompt, systemPrompt);
15543
+ await this.rateLimiter.acquire(estimated);
15544
+ const requestBody = {
15545
+ model: useModel,
15546
+ messages: [{ role: "user", content: prompt }],
15547
+ max_tokens: maxTokens,
15548
+ temperature
15549
+ };
15550
+ if (systemPrompt) {
15551
+ requestBody["system"] = systemPrompt;
15552
+ }
15553
+ let response;
15554
+ try {
15555
+ const controller = new AbortController();
15556
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
15557
+ response = await fetch(BASE_URL2, {
15558
+ method: "POST",
15559
+ headers: {
15560
+ "Content-Type": "application/json",
15561
+ "x-api-key": this.apiKey,
15562
+ "anthropic-version": ANTHROPIC_VERSION
15563
+ },
15564
+ body: JSON.stringify(requestBody),
15565
+ signal: controller.signal
15566
+ });
15567
+ clearTimeout(timer);
15568
+ } catch (err) {
15569
+ if (err instanceof Error && err.name === "AbortError") {
15570
+ throw new LlmTimeoutError(
15571
+ `Anthropic request timed out after ${this.timeoutMs}ms`
15572
+ );
15573
+ }
15574
+ throw new LlmError(`Anthropic network error: ${String(err)}`);
15575
+ }
15576
+ if (!response.ok) {
15577
+ let errorBody = null;
15578
+ let errorMessage = response.statusText;
15579
+ try {
15580
+ errorBody = await response.json();
15581
+ const errorObj = errorBody?.["error"];
15582
+ errorMessage = errorObj?.["message"] ?? errorMessage;
15583
+ } catch {
15584
+ }
15585
+ throw this.mapError(response.status, errorBody, errorMessage);
15586
+ }
15587
+ const data = await response.json();
15588
+ this.rateLimiter.recordSuccess();
15589
+ const contentBlocks = data["content"];
15590
+ const textParts = [];
15591
+ if (contentBlocks) {
15592
+ for (const block of contentBlocks) {
15593
+ if (block["type"] === "text" && typeof block["text"] === "string") {
15594
+ textParts.push(block["text"]);
15595
+ }
15596
+ }
15597
+ }
15598
+ const content = textParts.join("").trim();
15599
+ const usageObj = data["usage"];
15600
+ const inputTokens = usageObj?.["input_tokens"] ?? 0;
15601
+ const outputTokens = usageObj?.["output_tokens"] ?? 0;
15602
+ return {
15603
+ content,
15604
+ model: data["model"] ?? useModel,
15605
+ usage: {
15606
+ input_tokens: inputTokens,
15607
+ output_tokens: outputTokens
15608
+ }
15609
+ };
15610
+ }
15611
+ /**
15612
+ * Stream a query response chunk by chunk.
15613
+ *
15614
+ * Uses Server-Sent Events (SSE) streaming from the Anthropic API.
15615
+ * System prompts are sent via the top-level `system` parameter.
15616
+ *
15617
+ * @param prompt - The user prompt/query.
15618
+ * @param opts - Optional query configuration.
15619
+ * @yields Text chunks as they arrive from the API.
15620
+ */
15621
+ async *streamQuery(prompt, opts) {
15622
+ const useModel = opts?.model ?? this.defaultModel;
15623
+ const maxTokens = opts?.maxTokens ?? 4096;
15624
+ const temperature = opts?.temperature ?? 1;
15625
+ const systemPrompt = opts?.systemPrompt;
15626
+ const estimated = this.estimateTokens(prompt, systemPrompt);
15627
+ await this.rateLimiter.acquire(estimated);
15628
+ const requestBody = {
15629
+ model: useModel,
15630
+ messages: [{ role: "user", content: prompt }],
15631
+ max_tokens: maxTokens,
15632
+ temperature,
15633
+ stream: true
15634
+ };
15635
+ if (systemPrompt) {
15636
+ requestBody["system"] = systemPrompt;
15637
+ }
15638
+ let response;
15639
+ try {
15640
+ const controller = new AbortController();
15641
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
15642
+ response = await fetch(BASE_URL2, {
15643
+ method: "POST",
15644
+ headers: {
15645
+ "Content-Type": "application/json",
15646
+ "x-api-key": this.apiKey,
15647
+ "anthropic-version": ANTHROPIC_VERSION
15648
+ },
15649
+ body: JSON.stringify(requestBody),
15650
+ signal: controller.signal
15651
+ });
15652
+ clearTimeout(timer);
15653
+ } catch (err) {
15654
+ if (err instanceof Error && err.name === "AbortError") {
15655
+ throw new LlmTimeoutError(
15656
+ `Anthropic request timed out after ${this.timeoutMs}ms`
15657
+ );
15658
+ }
15659
+ throw new LlmError(`Anthropic network error: ${String(err)}`);
15660
+ }
15661
+ if (!response.ok) {
15662
+ let errorBody = null;
15663
+ let errorMessage = response.statusText;
15664
+ try {
15665
+ errorBody = await response.json();
15666
+ const errorObj = errorBody?.["error"];
15667
+ errorMessage = errorObj?.["message"] ?? errorMessage;
15668
+ } catch {
15669
+ }
15670
+ throw this.mapError(response.status, errorBody, errorMessage);
15671
+ }
15672
+ if (!response.body) {
15673
+ throw new LlmError("Anthropic streaming response has no body");
15674
+ }
15675
+ const reader = response.body.getReader();
15676
+ const decoder = new TextDecoder();
15677
+ let buffer = "";
15678
+ let streamCompleted = false;
15679
+ try {
15680
+ for (; ; ) {
15681
+ const { done, value } = await reader.read();
15682
+ if (done)
15683
+ break;
15684
+ buffer += decoder.decode(value, { stream: true });
15685
+ const lines = buffer.split("\n");
15686
+ buffer = lines.pop() ?? "";
15687
+ for (const line of lines) {
15688
+ const trimmed = line.trim();
15689
+ if (!trimmed || !trimmed.startsWith("data: "))
15690
+ continue;
15691
+ const payload = trimmed.slice(6);
15692
+ try {
15693
+ const event = JSON.parse(payload);
15694
+ const eventType = event["type"];
15695
+ if (eventType === "content_block_delta") {
15696
+ const delta = event["delta"];
15697
+ if (delta?.["type"] === "text_delta") {
15698
+ const text = delta["text"];
15699
+ if (text)
15700
+ yield text;
15701
+ }
15702
+ } else if (eventType === "message_stop") {
15703
+ streamCompleted = true;
15704
+ return;
15705
+ }
15706
+ } catch {
15707
+ }
15708
+ }
15709
+ }
15710
+ streamCompleted = true;
15711
+ } finally {
15712
+ reader.releaseLock();
15713
+ if (streamCompleted)
15714
+ this.rateLimiter.recordSuccess();
15715
+ }
15716
+ }
15717
+ };
15718
+
15719
+ // src/llm/factory.ts
15720
+ function createLlmClient(opts) {
15721
+ const clientType = (opts?.clientType ?? process.env["LLM_CLIENT_TYPE"] ?? "mock").toLowerCase();
15722
+ const model = opts?.model ?? process.env["LLM_DEFAULT_MODEL"];
15723
+ if (clientType === "mock") {
15724
+ return new MockLlmClient({
15725
+ defaultModel: model ?? "mock-model"
15726
+ });
15727
+ }
15728
+ if (clientType === "groq") {
15729
+ return new GroqClient({
15730
+ apiKey: opts?.apiKey,
15731
+ defaultModel: model,
15732
+ timeoutMs: opts?.timeoutMs
15733
+ });
15734
+ }
15735
+ if (clientType === "anthropic") {
15736
+ return new AnthropicClient({
15737
+ apiKey: opts?.apiKey,
15738
+ defaultModel: model,
15739
+ timeoutMs: opts?.timeoutMs
15740
+ });
15741
+ }
15742
+ throw new Error(
15743
+ `Unknown LLM client type: "${clientType}". Valid types: "groq", "anthropic", "mock"`
15744
+ );
15745
+ }
15746
+
13295
15747
  // src/index.ts
13296
- var version = "0.4.0";
15748
+ var version = "0.6.0";
13297
15749
  // Annotate the CommonJS export names for ESM import in node:
13298
15750
  0 && (module.exports = {
13299
15751
  ACKLifecycleManager,
15752
+ AGENT_STATE_FAILED,
15753
+ AGENT_STATE_INITIALIZING,
15754
+ AGENT_STATE_RUNNING,
15755
+ AGENT_STATE_SHUTTING_DOWN,
13300
15756
  AckStage,
13301
15757
  ActivityBuffer,
13302
15758
  ActivityBufferSync,
13303
15759
  ActivityClient,
13304
15760
  AgentState,
13305
15761
  AgentStateMachine,
15762
+ AnthropicClient,
13306
15763
  ArtifactType,
13307
15764
  BaseClient,
13308
15765
  BordaCountAggregator,
15766
+ BufferFullError,
13309
15767
  CT_AGENT_REPORT_V1,
13310
15768
  CT_SCHEDULER_COMMAND_V1,
15769
+ CancellationManager,
15770
+ CancellationValidationError,
15771
+ CommunicationClass,
13311
15772
  ConfidenceWeightedAggregator,
13312
15773
  ConnectorClient,
15774
+ DEDUP_WINDOW_S,
15775
+ DEFAULT_ACK_TIMEOUT_MS,
15776
+ DEFAULT_BACKOFF_MULTIPLIER,
15777
+ DEFAULT_EFFECTIVE_MAX_REDIRECTS,
13313
15778
  DEFAULT_ESCALATION_POLICY,
13314
15779
  DEFAULT_EXECUTION_POLICY,
15780
+ DEFAULT_INITIAL_BACKOFF_MS,
15781
+ DEFAULT_MAX_BACKOFF_MS,
15782
+ DEFAULT_MAX_REDIRECTS,
15783
+ DEFAULT_MAX_RETRIES_ON_OVERLOADED,
13315
15784
  DEFAULT_NEGOTIATION_POLICY,
15785
+ DEFAULT_PEER_LIVENESS_THRESHOLD_MS,
15786
+ DebateIntensity,
13316
15787
  DecisionOutcome,
13317
15788
  DefaultWorktreePolicy,
15789
+ DuplicateDetectedError,
15790
+ EnvelopeState,
13318
15791
  ErrorCode,
13319
15792
  ErrorCodeMapper,
13320
15793
  FileBackend,
15794
+ GatewayRedirectEmitter,
15795
+ GatewayValidationError,
15796
+ GroqClient,
13321
15797
  HITLClient,
13322
15798
  HandoffClient,
13323
15799
  HandoffStatus,
13324
15800
  HandoffTimeoutError,
13325
15801
  HandoffValidationError,
13326
15802
  HitlMode,
15803
+ HitlReasonType,
15804
+ InMemoryAuditor,
15805
+ InMemoryNegotiationRoomStore,
13327
15806
  InMemoryPolicyStore,
13328
15807
  InterceptorChain,
13329
15808
  JSONFilePersistence,
13330
15809
  JsonFilePolicyStore,
13331
15810
  KeyringBackend,
15811
+ LlmAuthenticationError,
15812
+ LlmContextLengthError,
15813
+ LlmError,
15814
+ LlmRateLimitError,
15815
+ LlmTimeoutError,
13332
15816
  LoggingClient,
15817
+ MIN_GRACE_PERIOD_MS,
13333
15818
  MajorityVoteAggregator,
13334
15819
  MaxEntriesStrategy,
13335
15820
  MessageProcessor,
13336
15821
  MessageType,
15822
+ MockLlmClient,
15823
+ NON_SERVING_AGENT_STATES,
13337
15824
  NegotiationClient,
15825
+ NegotiationError,
13338
15826
  NegotiationRoomClient,
15827
+ NegotiationRoomStoreError,
13339
15828
  NegotiationTimeoutError,
13340
15829
  NegotiationValidationError,
15830
+ NoOpAuditor,
13341
15831
  NodeStatus,
15832
+ PeerSelector,
15833
+ PermissionError,
15834
+ PersistentActivityBuffer,
13342
15835
  PersistentWorktreeState,
13343
15836
  PolicyStoreError,
15837
+ PolicyViolationError,
15838
+ PreemptionError,
15839
+ REGISTRATION_TYPE_STANDARD_AGENT,
15840
+ REGISTRATION_TYPE_SWARM_GATEWAY,
15841
+ RETRY_AFTER_JITTER_RATIO,
13344
15842
  ReasoningClient,
13345
15843
  RegistryClient,
13346
15844
  Resolver,
15845
+ RouteError,
13347
15846
  RouterClient,
13348
15847
  RuntimePersistence,
13349
15848
  SchedulerClient,
@@ -13361,35 +15860,63 @@ var version = "0.4.0";
13361
15860
  SimpleAverageAggregator,
13362
15861
  StateTransitionError,
13363
15862
  Sw4rmError,
15863
+ TimeoutError,
15864
+ TokenBucket,
13364
15865
  ToolClient,
13365
15866
  TriggerType,
15867
+ ValidationError,
13366
15868
  VotingAnalyzer,
13367
15869
  WorkflowClient,
13368
15870
  WorkflowCycleError,
13369
15871
  WorkflowStatus,
13370
15872
  WorkflowValidationError,
13371
15873
  WorktreeClient,
15874
+ WorktreeError,
15875
+ WorktreeStateEnum,
15876
+ WorktreeTransitionError,
13372
15877
  aggregateVotes,
13373
15878
  buildAckEnvelope,
13374
15879
  buildEnvelope,
15880
+ buildRateLimiterConfig,
15881
+ computeEnvelopeHash,
13375
15882
  computeIdempotencyToken,
15883
+ createLlmClient,
13376
15884
  createResilientIncomingStream,
15885
+ createSimpleProof,
13377
15886
  decodeAgentReportV1,
13378
15887
  decodeBase64,
15888
+ defaultAgentConfig,
15889
+ defaultEndpoints,
15890
+ defaultRetryPolicy,
15891
+ defaultSW4RMConfig,
15892
+ delegateToSwarm,
13379
15893
  durationToMs,
13380
15894
  encodeSchedulerCommandV1,
15895
+ getConfig,
15896
+ getDefaultStore,
15897
+ getGlobalRateLimiter,
13381
15898
  getValidTransitions,
15899
+ isTerminalEnvelopeState,
13382
15900
  isValidTransition,
15901
+ isValidWorktreeTransition,
15902
+ loadConfig,
15903
+ loadConfigFromEnv,
13383
15904
  loggingInterceptor,
13384
15905
  mapGrpcStatusToErrorCode,
13385
15906
  msToDuration,
13386
15907
  normalizeReportPaths,
13387
15908
  nowTimestamp,
13388
15909
  parseNegotiationEvent,
15910
+ resetConfig,
15911
+ resetDefaultStore,
15912
+ resetGlobalRateLimiter,
13389
15913
  selectBackend,
13390
15914
  sendMessageWithAck,
15915
+ setConfig,
13391
15916
  timingInterceptor,
15917
+ updateEnvelopeState,
13392
15918
  uuidv4,
15919
+ verifyAuditProof,
13393
15920
  version
13394
15921
  });
13395
15922
  /*! Bundled license information: