@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.
- package/README.md +178 -1
- package/dist/cjs/index.cjs +2819 -292
- package/dist/esm/index.js +2736 -284
- package/dist/types/agentConfig.d.ts +245 -0
- package/dist/types/audit.d.ts +214 -0
- package/dist/types/clients/handoff.d.ts +44 -1
- package/dist/types/clients/negotiationRoom.d.ts +81 -5
- package/dist/types/clients/negotiationRoomStore.d.ts +155 -0
- package/dist/types/clients/workflow.d.ts +15 -0
- package/dist/types/constants/index.d.ts +100 -0
- package/dist/types/index.d.ts +14 -5
- package/dist/types/internal/baseClient.d.ts +6 -0
- package/dist/types/internal/envelope.d.ts +16 -0
- package/dist/types/internal/errorMapping.d.ts +116 -0
- package/dist/types/internal/worktreeState.d.ts +60 -0
- package/dist/types/llm/anthropic.d.ts +83 -0
- package/dist/types/llm/client.d.ts +107 -0
- package/dist/types/llm/factory.d.ts +69 -0
- package/dist/types/llm/groq.d.ts +79 -0
- package/dist/types/llm/index.d.ts +45 -0
- package/dist/types/llm/mock.d.ts +89 -0
- package/dist/types/llm/rateLimiter.d.ts +101 -0
- package/dist/types/persistentActivityBuffer.d.ts +94 -0
- package/dist/types/runtime/cancellation.d.ts +41 -0
- package/dist/types/runtime/delegation.d.ts +20 -0
- package/dist/types/runtime/gateway.d.ts +80 -0
- package/package.json +4 -2
- package/protos/activity.proto +24 -0
- package/protos/common.proto +141 -0
- package/protos/connector.proto +29 -0
- package/protos/handoff.proto +105 -0
- package/protos/hitl.proto +23 -0
- package/protos/logging.proto +20 -0
- package/protos/negotiation.proto +57 -0
- package/protos/negotiation_room.proto +220 -0
- package/protos/policy.proto +55 -0
- package/protos/reasoning.proto +41 -0
- package/protos/registry.proto +47 -0
- package/protos/router.proto +16 -0
- package/protos/scheduler.proto +52 -0
- package/protos/scheduler_policy.proto +36 -0
- package/protos/tool.proto +47 -0
- package/protos/workflow.proto +116 -0
- package/protos/worktree.proto +33 -0
package/dist/cjs/index.cjs
CHANGED
|
@@ -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 =
|
|
1859
|
+
module2.exports = fetch2;
|
|
1860
1860
|
var asPromise = require_aspromise();
|
|
1861
1861
|
var inquire2 = require_inquire();
|
|
1862
|
-
var
|
|
1863
|
-
function
|
|
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(
|
|
1871
|
-
if (!options.xhr &&
|
|
1872
|
-
return
|
|
1873
|
-
return err && typeof XMLHttpRequest !== "undefined" ?
|
|
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
|
|
1875
|
+
return fetch2.xhr(filename, options, callback);
|
|
1876
1876
|
}
|
|
1877
|
-
|
|
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
|
|
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
|
-
|
|
1918
|
-
return /^(?:\/|\w+:)/.test(
|
|
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
|
-
|
|
1928
|
-
|
|
1929
|
-
var parts =
|
|
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
|
-
|
|
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(
|
|
2100
|
-
if (util.isString(
|
|
2101
|
-
|
|
2102
|
-
else if (!Array.isArray(
|
|
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 (
|
|
2104
|
+
if (path7 && path7.length && path7[0] === "")
|
|
2105
2105
|
throw Error("path must be relative");
|
|
2106
2106
|
var ptr = this;
|
|
2107
|
-
while (
|
|
2108
|
-
var part =
|
|
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(
|
|
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(
|
|
2152
|
-
if (
|
|
2151
|
+
if (util.isString(path7) && path7.length) {
|
|
2152
|
+
if (path7 === ".")
|
|
2153
2153
|
return this.root;
|
|
2154
|
-
|
|
2155
|
-
} else if (!
|
|
2154
|
+
path7 = path7.split(".");
|
|
2155
|
+
} else if (!path7.length)
|
|
2156
2156
|
return this;
|
|
2157
|
-
var flatPath =
|
|
2158
|
-
if (
|
|
2159
|
-
return this.root.lookup(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
2184
|
+
var found = this.get(path7[0]);
|
|
2185
2185
|
var exact = null;
|
|
2186
2186
|
if (found) {
|
|
2187
|
-
if (
|
|
2187
|
+
if (path7.length === 1) {
|
|
2188
2188
|
exact = found;
|
|
2189
2189
|
} else if (found instanceof Namespace) {
|
|
2190
|
-
|
|
2191
|
-
exact = found._lookupImpl(
|
|
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(
|
|
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(
|
|
2202
|
-
var found = this.lookup(
|
|
2201
|
+
Namespace.prototype.lookupType = function lookupType(path7) {
|
|
2202
|
+
var found = this.lookup(path7, [Type]);
|
|
2203
2203
|
if (!found)
|
|
2204
|
-
throw Error("no such type: " +
|
|
2204
|
+
throw Error("no such type: " + path7);
|
|
2205
2205
|
return found;
|
|
2206
2206
|
};
|
|
2207
|
-
Namespace.prototype.lookupEnum = function lookupEnum(
|
|
2208
|
-
var found = this.lookup(
|
|
2207
|
+
Namespace.prototype.lookupEnum = function lookupEnum(path7) {
|
|
2208
|
+
var found = this.lookup(path7, [Enum]);
|
|
2209
2209
|
if (!found)
|
|
2210
|
-
throw Error("no such Enum '" +
|
|
2210
|
+
throw Error("no such Enum '" + path7 + "' in " + this);
|
|
2211
2211
|
return found;
|
|
2212
2212
|
};
|
|
2213
|
-
Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(
|
|
2214
|
-
var found = this.lookup(
|
|
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 '" +
|
|
2216
|
+
throw Error("no such Type or Enum '" + path7 + "' in " + this);
|
|
2217
2217
|
return found;
|
|
2218
2218
|
};
|
|
2219
|
-
Namespace.prototype.lookupService = function lookupService(
|
|
2220
|
-
var found = this.lookup(
|
|
2219
|
+
Namespace.prototype.lookupService = function lookupService(path7) {
|
|
2220
|
+
var found = this.lookup(path7, [Service]);
|
|
2221
2221
|
if (!found)
|
|
2222
|
-
throw Error("no such Service '" +
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
3624
|
-
function setProp(dst2,
|
|
3625
|
-
var part =
|
|
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 (
|
|
3630
|
-
dst2[part] = setProp(dst2[part] || {},
|
|
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 (!
|
|
3643
|
+
if (!path7)
|
|
3644
3644
|
throw TypeError("path must be specified");
|
|
3645
|
-
|
|
3646
|
-
return setProp(dst,
|
|
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
|
|
4193
|
+
var path7 = [this.name], ptr = this.parent;
|
|
4194
4194
|
while (ptr) {
|
|
4195
|
-
|
|
4195
|
+
path7.unshift(ptr.name);
|
|
4196
4196
|
ptr = ptr.parent;
|
|
4197
4197
|
}
|
|
4198
|
-
return
|
|
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
|
|
8181
|
-
var
|
|
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 (
|
|
8186
|
+
if (path7.isAbsolute(target)) {
|
|
8187
8187
|
return target;
|
|
8188
8188
|
}
|
|
8189
8189
|
for (const directory of includePaths) {
|
|
8190
|
-
const fullPath =
|
|
8190
|
+
const fullPath = path7.join(directory, target);
|
|
8191
8191
|
try {
|
|
8192
|
-
|
|
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
|
-
|
|
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 ??
|
|
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 =
|
|
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
|
-
|
|
10420
|
-
|
|
10421
|
-
|
|
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
|
-
|
|
10450
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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 {
|
|
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/
|
|
11700
|
-
var
|
|
11701
|
-
var
|
|
11702
|
-
var
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
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
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
11712
|
-
|
|
11713
|
-
|
|
11714
|
-
|
|
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
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
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
|
-
|
|
11721
|
-
|
|
11722
|
-
|
|
11723
|
-
|
|
11724
|
-
|
|
11725
|
-
|
|
11726
|
-
|
|
11727
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
13881
|
+
var import_node_crypto4 = __toESM(require("node:crypto"), 1);
|
|
12929
13882
|
function computeIdempotencyToken(input) {
|
|
12930
|
-
const h =
|
|
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
|
-
|
|
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/
|
|
13054
|
-
var
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
return
|
|
13060
|
-
})(
|
|
13061
|
-
var
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
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
|
-
|
|
13069
|
-
|
|
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
|
-
|
|
13073
|
-
|
|
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
|
-
|
|
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
|
-
|
|
13088
|
-
}
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
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
|
-
|
|
13113
|
-
|
|
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
|
-
|
|
13116
|
-
|
|
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
|
-
|
|
13119
|
-
|
|
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
|
-
|
|
13124
|
-
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
|
|
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
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
|
|
13134
|
-
|
|
13135
|
-
|
|
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
|
|
13151
|
-
var
|
|
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,
|
|
13156
|
-
return (0,
|
|
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,
|
|
13160
|
-
return (0,
|
|
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(
|
|
13165
|
-
this.path =
|
|
13166
|
-
(0,
|
|
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,
|
|
14785
|
+
(0, import_node_fs3.chmodSync)((0, import_node_path5.dirname)(this.path), 448);
|
|
13169
14786
|
} catch {
|
|
13170
14787
|
}
|
|
13171
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
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,
|
|
13191
|
-
(0,
|
|
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,
|
|
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.
|
|
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:
|