@atbash/sdk 0.10.9-dev.0 → 0.10.10-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.d.mts +83 -17
- package/dist/browser.mjs +120 -67
- package/dist/browser.mjs.map +1 -1
- package/dist/index.d.mts +83 -17
- package/dist/index.d.ts +83 -17
- package/dist/index.js +234 -105
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +234 -105
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -3111,8 +3111,8 @@ var HttpClient = class {
|
|
|
3111
3111
|
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
3112
3112
|
this.timeoutMs = timeoutMs;
|
|
3113
3113
|
}
|
|
3114
|
-
buildUrl(
|
|
3115
|
-
const url = new URL(this.baseUrl +
|
|
3114
|
+
buildUrl(path7, query) {
|
|
3115
|
+
const url = new URL(this.baseUrl + path7);
|
|
3116
3116
|
if (query) {
|
|
3117
3117
|
for (const [k, v] of Object.entries(query)) {
|
|
3118
3118
|
if (v !== void 0 && v !== null && v !== "") {
|
|
@@ -3122,14 +3122,14 @@ var HttpClient = class {
|
|
|
3122
3122
|
}
|
|
3123
3123
|
return url.toString();
|
|
3124
3124
|
}
|
|
3125
|
-
async get(
|
|
3126
|
-
return this.fetch(this.buildUrl(
|
|
3125
|
+
async get(path7, query, headers) {
|
|
3126
|
+
return this.fetch(this.buildUrl(path7, query), {
|
|
3127
3127
|
method: "GET",
|
|
3128
3128
|
...headers && { headers }
|
|
3129
3129
|
});
|
|
3130
3130
|
}
|
|
3131
|
-
async post(
|
|
3132
|
-
return this.fetch(this.buildUrl(
|
|
3131
|
+
async post(path7, body, headers) {
|
|
3132
|
+
return this.fetch(this.buildUrl(path7), {
|
|
3133
3133
|
method: "POST",
|
|
3134
3134
|
headers: { "Content-Type": "application/json", ...headers },
|
|
3135
3135
|
body: JSON.stringify(body)
|
|
@@ -3462,6 +3462,16 @@ var Atbash = class _Atbash {
|
|
|
3462
3462
|
* calls don't re-hit the dashboard. Cleared by `clearChainCache()`.
|
|
3463
3463
|
*/
|
|
3464
3464
|
_chainCache = /* @__PURE__ */ new Map();
|
|
3465
|
+
/**
|
|
3466
|
+
* Short-TTL cache for `/api/ai/exists`. The `registered` field is
|
|
3467
|
+
* monotonic (once true, stays true), so most calls in a burst re-fetch
|
|
3468
|
+
* data that hasn't changed. The `org_encryption_pubkey` field CAN change
|
|
3469
|
+
* — an org toggling encryption mid-session — so the TTL is deliberately
|
|
3470
|
+
* short (see `AGENT_EXISTS_TTL_MS`). Keyed by (pubkey, network) so
|
|
3471
|
+
* cross-agent / cross-network calls don't collide.
|
|
3472
|
+
*/
|
|
3473
|
+
_agentExistsCache = null;
|
|
3474
|
+
static AGENT_EXISTS_TTL_MS = 5e3;
|
|
3465
3475
|
/**
|
|
3466
3476
|
* Cached bearer token for risk-engine / insurance read calls. Built
|
|
3467
3477
|
* lazily as a signed `log_tool_call` tx and refreshed every 4 min so
|
|
@@ -3561,9 +3571,18 @@ var Atbash = class _Atbash {
|
|
|
3561
3571
|
*/
|
|
3562
3572
|
async checkAgentExists(pubkey, opts) {
|
|
3563
3573
|
const pk = pubkey ?? this.auth.pubkey;
|
|
3574
|
+
const network = opts?.network;
|
|
3575
|
+
const now = Date.now();
|
|
3576
|
+
const cached = this._agentExistsCache;
|
|
3577
|
+
if (cached && cached.pubkey === pk && cached.network === network && cached.expiresAt > now) {
|
|
3578
|
+
if (pk === this.auth.pubkey) {
|
|
3579
|
+
this._orgKeyFromChain = cached.orgKey;
|
|
3580
|
+
}
|
|
3581
|
+
return cached.registered;
|
|
3582
|
+
}
|
|
3564
3583
|
return this.track("checkAgentExists", pk, async () => {
|
|
3565
3584
|
const query = { pubkey: pk };
|
|
3566
|
-
if (
|
|
3585
|
+
if (network) query.network = network;
|
|
3567
3586
|
const resp = await this.http.get(
|
|
3568
3587
|
"/api/ai/exists",
|
|
3569
3588
|
query,
|
|
@@ -3571,11 +3590,21 @@ var Atbash = class _Atbash {
|
|
|
3571
3590
|
);
|
|
3572
3591
|
await this.raiseIfError(resp);
|
|
3573
3592
|
const data = await this.json(resp);
|
|
3593
|
+
const registered = Boolean(data?.registered);
|
|
3594
|
+
const orgKey = typeof data?.org_encryption_pubkey === "string" && data.org_encryption_pubkey ? data.org_encryption_pubkey : null;
|
|
3595
|
+
if (registered) {
|
|
3596
|
+
this._agentExistsCache = {
|
|
3597
|
+
pubkey: pk,
|
|
3598
|
+
network,
|
|
3599
|
+
expiresAt: Date.now() + _Atbash.AGENT_EXISTS_TTL_MS,
|
|
3600
|
+
registered,
|
|
3601
|
+
orgKey
|
|
3602
|
+
};
|
|
3603
|
+
}
|
|
3574
3604
|
if (pk === this.auth.pubkey) {
|
|
3575
|
-
|
|
3576
|
-
this._orgKeyFromChain = typeof key3 === "string" && key3 ? key3 : null;
|
|
3605
|
+
this._orgKeyFromChain = orgKey;
|
|
3577
3606
|
}
|
|
3578
|
-
return
|
|
3607
|
+
return registered;
|
|
3579
3608
|
});
|
|
3580
3609
|
}
|
|
3581
3610
|
/* ── log_tool_call (sign-only) ─────────────────────────────────────────── */
|
|
@@ -3656,12 +3685,19 @@ var Atbash = class _Atbash {
|
|
|
3656
3685
|
}
|
|
3657
3686
|
let chainOpts = options.chainOpts;
|
|
3658
3687
|
if (options.orgName) {
|
|
3659
|
-
const
|
|
3660
|
-
if (
|
|
3661
|
-
chainOpts = { network:
|
|
3662
|
-
} else
|
|
3663
|
-
const
|
|
3664
|
-
|
|
3688
|
+
const cached = this._chainCache.get(options.orgName);
|
|
3689
|
+
if (cached) {
|
|
3690
|
+
chainOpts = { network: cached.network };
|
|
3691
|
+
} else {
|
|
3692
|
+
const mapNetwork = await this.getActiveNetworkForOrg(options.orgName);
|
|
3693
|
+
if (mapNetwork) {
|
|
3694
|
+
const chain = mapNetwork === "private" ? PRIVATE_CHAIN : PUBLIC_CHAIN;
|
|
3695
|
+
this._chainCache.set(options.orgName, chain);
|
|
3696
|
+
chainOpts = { network: mapNetwork };
|
|
3697
|
+
} else if (!chainOpts?.blockchainRid) {
|
|
3698
|
+
const resolved = await this.resolveChainFromMap(options.orgName, null);
|
|
3699
|
+
chainOpts = { ...chainOpts, network: resolved.network };
|
|
3700
|
+
}
|
|
3665
3701
|
}
|
|
3666
3702
|
}
|
|
3667
3703
|
const brid = this.bridFromChainOpts(chainOpts);
|
|
@@ -4110,6 +4146,10 @@ var Atbash = class _Atbash {
|
|
|
4110
4146
|
clearChainCache() {
|
|
4111
4147
|
this._chainCache.clear();
|
|
4112
4148
|
}
|
|
4149
|
+
/** Drop the short-TTL `/api/ai/exists` cache. Useful in tests. */
|
|
4150
|
+
clearAgentExistsCache() {
|
|
4151
|
+
this._agentExistsCache = null;
|
|
4152
|
+
}
|
|
4113
4153
|
/* ── internals ─────────────────────────────────────────────────────────── */
|
|
4114
4154
|
/**
|
|
4115
4155
|
* Wrap an SDK method body in telemetry — records the call at start
|
|
@@ -4459,24 +4499,29 @@ async function scanMemory(entry, auth, opts) {
|
|
|
4459
4499
|
toolArgsJson: opts?.toolArgsJson ?? JSON.stringify({ key: entry.key, source: entry.source }),
|
|
4460
4500
|
mode: "memory-scan"
|
|
4461
4501
|
});
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
return {
|
|
4467
|
-
safe: false,
|
|
4468
|
-
verdict: "red",
|
|
4469
|
-
reason: unknownAction ? `judge returned unrecognised action_type "${result.actionType}"` : "judge returned no verdict",
|
|
4470
|
-
confidence: result.confidence,
|
|
4471
|
-
score: native.defaultScoreForVerdict("red"),
|
|
4472
|
-
toolCallId: result.toolCallId
|
|
4473
|
-
};
|
|
4502
|
+
if (result.verdict === "No verdict" && result.status !== "logged") {
|
|
4503
|
+
throw new Error(
|
|
4504
|
+
`memory scan: judge returned no verdict without an audit-tier marker (status: ${result.status || "absent"})`
|
|
4505
|
+
);
|
|
4474
4506
|
}
|
|
4475
|
-
const
|
|
4476
|
-
|
|
4507
|
+
const KNOWN_ACTIONS = ["allow", "block", "hold_for_user_confirm"];
|
|
4508
|
+
const action = result.actionType.trim().toLowerCase();
|
|
4509
|
+
if (result.verdict !== "No verdict" && !KNOWN_ACTIONS.includes(action)) {
|
|
4510
|
+
throw new Error(
|
|
4511
|
+
`memory scan: unrecognized action_type from judge (${result.actionType || "absent"})`
|
|
4512
|
+
);
|
|
4513
|
+
}
|
|
4514
|
+
const mapped = native.mapVerdict(
|
|
4515
|
+
action,
|
|
4477
4516
|
result.confidence,
|
|
4478
4517
|
threshold
|
|
4479
4518
|
);
|
|
4519
|
+
let verdict = mapped;
|
|
4520
|
+
if (result.verdict === "BLOCK") {
|
|
4521
|
+
verdict = "red";
|
|
4522
|
+
} else if (result.verdict === "HOLD" && mapped === "green") {
|
|
4523
|
+
verdict = "yellow";
|
|
4524
|
+
}
|
|
4480
4525
|
const parsed = native.parseScoreFromReason(result.reason);
|
|
4481
4526
|
const score = result.score ?? parsed.score ?? native.defaultScoreForVerdict(verdict);
|
|
4482
4527
|
return {
|
|
@@ -9382,8 +9427,8 @@ Reporter$3.prototype.wrapResult = function wrapResult(result) {
|
|
|
9382
9427
|
errors: state2.errors
|
|
9383
9428
|
};
|
|
9384
9429
|
};
|
|
9385
|
-
function ReporterError$1(
|
|
9386
|
-
this.path =
|
|
9430
|
+
function ReporterError$1(path7, msg) {
|
|
9431
|
+
this.path = path7;
|
|
9387
9432
|
this.rethrow(msg);
|
|
9388
9433
|
}
|
|
9389
9434
|
inherits$v(ReporterError$1, Error);
|
|
@@ -29604,8 +29649,8 @@ Reporter.prototype.wrapResult = function wrapResult2(result) {
|
|
|
29604
29649
|
errors: state2.errors
|
|
29605
29650
|
};
|
|
29606
29651
|
};
|
|
29607
|
-
function ReporterError(
|
|
29608
|
-
this.path =
|
|
29652
|
+
function ReporterError(path7, msg) {
|
|
29653
|
+
this.path = path7;
|
|
29609
29654
|
this.rethrow(msg);
|
|
29610
29655
|
}
|
|
29611
29656
|
inherits(ReporterError, Error);
|
|
@@ -32635,8 +32680,8 @@ var parseUtil = {};
|
|
|
32635
32680
|
const errors_js_12 = errors$3;
|
|
32636
32681
|
const en_js_12 = __importDefault2(en);
|
|
32637
32682
|
const makeIssue = (params) => {
|
|
32638
|
-
const { data, path:
|
|
32639
|
-
const fullPath = [...
|
|
32683
|
+
const { data, path: path7, errorMaps, issueData } = params;
|
|
32684
|
+
const fullPath = [...path7, ...issueData.path || []];
|
|
32640
32685
|
const fullIssue = {
|
|
32641
32686
|
...issueData,
|
|
32642
32687
|
path: fullPath
|
|
@@ -32773,11 +32818,11 @@ var errorUtil_js_1 = errorUtil$1;
|
|
|
32773
32818
|
var parseUtil_js_1 = parseUtil;
|
|
32774
32819
|
var util_js_1 = util;
|
|
32775
32820
|
var ParseInputLazyPath = class {
|
|
32776
|
-
constructor(parent, value,
|
|
32821
|
+
constructor(parent, value, path7, key3) {
|
|
32777
32822
|
this._cachedPath = [];
|
|
32778
32823
|
this.parent = parent;
|
|
32779
32824
|
this.data = value;
|
|
32780
|
-
this._path =
|
|
32825
|
+
this._path = path7;
|
|
32781
32826
|
this._key = key3;
|
|
32782
32827
|
}
|
|
32783
32828
|
get path() {
|
|
@@ -39683,21 +39728,21 @@ function createTimeoutController(timeout) {
|
|
|
39683
39728
|
const timeoutId = setTimeout(() => controller.abort(timeoutError), timeout);
|
|
39684
39729
|
return { controller, timeoutId };
|
|
39685
39730
|
}
|
|
39686
|
-
function handleRequest(method,
|
|
39731
|
+
function handleRequest(method, path7, endpoint, timeout, postObject) {
|
|
39687
39732
|
return __awaiter$2(this, void 0, void 0, function* () {
|
|
39688
39733
|
if (method == enums_1$2.Method.GET) {
|
|
39689
|
-
return yield get(
|
|
39734
|
+
return yield get(path7, endpoint, timeout);
|
|
39690
39735
|
} else {
|
|
39691
|
-
return yield post(
|
|
39736
|
+
return yield post(path7, endpoint, timeout, postObject);
|
|
39692
39737
|
}
|
|
39693
39738
|
});
|
|
39694
39739
|
}
|
|
39695
|
-
function get(
|
|
39740
|
+
function get(path7, endpoint, timeout) {
|
|
39696
39741
|
return __awaiter$2(this, void 0, void 0, function* () {
|
|
39697
|
-
logger.debug(`GET URL ${new URL(
|
|
39742
|
+
logger.debug(`GET URL ${new URL(path7, endpoint).href}`);
|
|
39698
39743
|
try {
|
|
39699
39744
|
const { controller, timeoutId } = createTimeoutController(timeout);
|
|
39700
|
-
const response = yield fetch(new URL(
|
|
39745
|
+
const response = yield fetch(new URL(path7, endpoint).href, {
|
|
39701
39746
|
signal: controller === null || controller === void 0 ? void 0 : controller.signal
|
|
39702
39747
|
});
|
|
39703
39748
|
if (timeoutId)
|
|
@@ -39735,9 +39780,9 @@ function constructBufferResponseBody(response) {
|
|
|
39735
39780
|
return responseText ? responseText : response.statusText;
|
|
39736
39781
|
});
|
|
39737
39782
|
}
|
|
39738
|
-
function post(
|
|
39783
|
+
function post(path7, endpoint, timeout, requestBody) {
|
|
39739
39784
|
return __awaiter$2(this, void 0, void 0, function* () {
|
|
39740
|
-
logger.debug(`POST URL ${new URL(
|
|
39785
|
+
logger.debug(`POST URL ${new URL(path7, endpoint).href}`);
|
|
39741
39786
|
logger.debug(`POST body ${JSON.stringify(requestBody)}`);
|
|
39742
39787
|
if (buffer_1.Buffer.isBuffer(requestBody)) {
|
|
39743
39788
|
try {
|
|
@@ -39751,7 +39796,7 @@ function post(path6, endpoint, timeout, requestBody) {
|
|
|
39751
39796
|
},
|
|
39752
39797
|
signal: controller === null || controller === void 0 ? void 0 : controller.signal
|
|
39753
39798
|
};
|
|
39754
|
-
const response = yield fetch(new URL(
|
|
39799
|
+
const response = yield fetch(new URL(path7, endpoint).href, requestOptions);
|
|
39755
39800
|
if (timeoutId)
|
|
39756
39801
|
clearTimeout(timeoutId);
|
|
39757
39802
|
const transactionTimestamp = response.headers.get("X-Transaction-Timestamp");
|
|
@@ -39762,7 +39807,7 @@ function post(path6, endpoint, timeout, requestBody) {
|
|
|
39762
39807
|
} else {
|
|
39763
39808
|
try {
|
|
39764
39809
|
const { controller, timeoutId } = createTimeoutController(timeout);
|
|
39765
|
-
const response = yield fetch(new URL(
|
|
39810
|
+
const response = yield fetch(new URL(path7, endpoint).href, {
|
|
39766
39811
|
method: "post",
|
|
39767
39812
|
body: JSON.stringify(requestBody),
|
|
39768
39813
|
headers: {
|
|
@@ -39942,10 +39987,10 @@ function requireFailoverStrategies() {
|
|
|
39942
39987
|
}
|
|
39943
39988
|
}
|
|
39944
39989
|
function abortOnError(_a2) {
|
|
39945
|
-
return __awaiter2(this, arguments, void 0, function* ({ method, path:
|
|
39990
|
+
return __awaiter2(this, arguments, void 0, function* ({ method, path: path7, config: config2, postObject, timeoutOverride }) {
|
|
39946
39991
|
return yield retryRequest({
|
|
39947
39992
|
method,
|
|
39948
|
-
path:
|
|
39993
|
+
path: path7,
|
|
39949
39994
|
config: config2,
|
|
39950
39995
|
postObject,
|
|
39951
39996
|
timeoutOverride,
|
|
@@ -39956,10 +40001,10 @@ function requireFailoverStrategies() {
|
|
|
39956
40001
|
});
|
|
39957
40002
|
}
|
|
39958
40003
|
function tryNextOnError(_a2) {
|
|
39959
|
-
return __awaiter2(this, arguments, void 0, function* ({ method, path:
|
|
40004
|
+
return __awaiter2(this, arguments, void 0, function* ({ method, path: path7, config: config2, postObject, timeoutOverride }) {
|
|
39960
40005
|
return yield retryRequest({
|
|
39961
40006
|
method,
|
|
39962
|
-
path:
|
|
40007
|
+
path: path7,
|
|
39963
40008
|
config: config2,
|
|
39964
40009
|
postObject,
|
|
39965
40010
|
timeoutOverride,
|
|
@@ -39975,7 +40020,7 @@ function requireFailoverStrategies() {
|
|
|
39975
40020
|
return endpointPoolLength - (endpointPoolLength - 1) / 3;
|
|
39976
40021
|
}
|
|
39977
40022
|
function queryMajority(_a2) {
|
|
39978
|
-
return __awaiter2(this, arguments, void 0, function* ({ method, path:
|
|
40023
|
+
return __awaiter2(this, arguments, void 0, function* ({ method, path: path7, config: config2, postObject, timeoutOverride }) {
|
|
39979
40024
|
var _b;
|
|
39980
40025
|
const bftMajorityThreshold = calculateBftMajorityThreshold(config2.endpointPool.length);
|
|
39981
40026
|
const failureThreshold = config2.endpointPool.length - bftMajorityThreshold + 1;
|
|
@@ -39986,7 +40031,7 @@ function requireFailoverStrategies() {
|
|
|
39986
40031
|
const promises = availableNodes.map((node2) => __awaiter2(this, void 0, void 0, function* () {
|
|
39987
40032
|
try {
|
|
39988
40033
|
const requestTimeout = timeoutOverride !== null && timeoutOverride !== void 0 ? timeoutOverride : config2.responseTimeout;
|
|
39989
|
-
const response = yield (0, httpUtil_1.handleRequest)(method,
|
|
40034
|
+
const response = yield (0, httpUtil_1.handleRequest)(method, path7, node2.url, requestTimeout, postObject);
|
|
39990
40035
|
const { statusCode } = response;
|
|
39991
40036
|
if (statusCode && (0, http_utils_1.isSuccessfulStatusCode)(statusCode)) {
|
|
39992
40037
|
outcomes.push({ type: "SUCCESS", result: response });
|
|
@@ -40033,7 +40078,7 @@ function requireFailoverStrategies() {
|
|
|
40033
40078
|
});
|
|
40034
40079
|
}
|
|
40035
40080
|
function singleEndpoint(_a2) {
|
|
40036
|
-
return __awaiter2(this, arguments, void 0, function* ({ method, path:
|
|
40081
|
+
return __awaiter2(this, arguments, void 0, function* ({ method, path: path7, config: config2, postObject, timeoutOverride }) {
|
|
40037
40082
|
let statusCode = null;
|
|
40038
40083
|
let rspBody = null;
|
|
40039
40084
|
let error4 = null;
|
|
@@ -40044,7 +40089,7 @@ function requireFailoverStrategies() {
|
|
|
40044
40089
|
}
|
|
40045
40090
|
for (let attempt = 0; attempt < config2.attemptsPerEndpoint; attempt++) {
|
|
40046
40091
|
const requestTimeout = timeoutOverride !== null && timeoutOverride !== void 0 ? timeoutOverride : config2.responseTimeout;
|
|
40047
|
-
const response = yield (0, httpUtil_1.handleRequest)(method,
|
|
40092
|
+
const response = yield (0, httpUtil_1.handleRequest)(method, path7, endpoint.url, requestTimeout, postObject);
|
|
40048
40093
|
if (response) {
|
|
40049
40094
|
({ error: error4, statusCode, rspBody, transactionTimestamp } = response);
|
|
40050
40095
|
}
|
|
@@ -40059,7 +40104,7 @@ function requireFailoverStrategies() {
|
|
|
40059
40104
|
});
|
|
40060
40105
|
}
|
|
40061
40106
|
function retryRequest(_a2) {
|
|
40062
|
-
return __awaiter2(this, arguments, void 0, function* ({ method, path:
|
|
40107
|
+
return __awaiter2(this, arguments, void 0, function* ({ method, path: path7, config: config2, postObject, useNextNodeOnError, recoveryThreshold, timeoutOverride }) {
|
|
40063
40108
|
var _b, _c, _d;
|
|
40064
40109
|
let statusCode = null;
|
|
40065
40110
|
let rspBody = null;
|
|
@@ -40070,7 +40115,7 @@ function requireFailoverStrategies() {
|
|
|
40070
40115
|
for (const node2 of availableNodes) {
|
|
40071
40116
|
for (let attempt = 0; attempt < config2.attemptsPerEndpoint; attempt++) {
|
|
40072
40117
|
const requestTimeout = timeoutOverride !== null && timeoutOverride !== void 0 ? timeoutOverride : config2.responseTimeout;
|
|
40073
|
-
const response = yield (0, httpUtil_1.handleRequest)(method,
|
|
40118
|
+
const response = yield (0, httpUtil_1.handleRequest)(method, path7, node2.url, requestTimeout, postObject);
|
|
40074
40119
|
error4 = (_b = response === null || response === void 0 ? void 0 : response.error) !== null && _b !== void 0 ? _b : null;
|
|
40075
40120
|
statusCode = (_c = response === null || response === void 0 ? void 0 : response.statusCode) !== null && _c !== void 0 ? _c : null;
|
|
40076
40121
|
rspBody = (_d = response === null || response === void 0 ? void 0 : response.rspBody) !== null && _d !== void 0 ? _d : null;
|
|
@@ -40213,19 +40258,19 @@ function requireRequestWithFailoverStrategy() {
|
|
|
40213
40258
|
const enums_12 = enums;
|
|
40214
40259
|
const failoverStrategies_1 = requireFailoverStrategies();
|
|
40215
40260
|
function requestWithFailoverStrategy$1(method_1, path_1, config_1, postObject_1) {
|
|
40216
|
-
return __awaiter2(this, arguments, void 0, function* (method,
|
|
40261
|
+
return __awaiter2(this, arguments, void 0, function* (method, path7, config2, postObject, forceSingleEndpoint = false, timeoutOverride) {
|
|
40217
40262
|
switch (config2.failoverStrategy) {
|
|
40218
40263
|
case enums_12.FailoverStrategy.AbortOnError:
|
|
40219
|
-
return yield (0, failoverStrategies_1.abortOnError)({ method, path:
|
|
40264
|
+
return yield (0, failoverStrategies_1.abortOnError)({ method, path: path7, config: config2, postObject, timeoutOverride });
|
|
40220
40265
|
case enums_12.FailoverStrategy.TryNextOnError:
|
|
40221
|
-
return yield (0, failoverStrategies_1.tryNextOnError)({ method, path:
|
|
40266
|
+
return yield (0, failoverStrategies_1.tryNextOnError)({ method, path: path7, config: config2, postObject, timeoutOverride });
|
|
40222
40267
|
case enums_12.FailoverStrategy.SingleEndpoint:
|
|
40223
|
-
return yield (0, failoverStrategies_1.singleEndpoint)({ method, path:
|
|
40268
|
+
return yield (0, failoverStrategies_1.singleEndpoint)({ method, path: path7, config: config2, postObject, timeoutOverride });
|
|
40224
40269
|
case enums_12.FailoverStrategy.QueryMajority:
|
|
40225
40270
|
if (forceSingleEndpoint) {
|
|
40226
|
-
return yield (0, failoverStrategies_1.singleEndpoint)({ method, path:
|
|
40271
|
+
return yield (0, failoverStrategies_1.singleEndpoint)({ method, path: path7, config: config2, postObject, timeoutOverride });
|
|
40227
40272
|
}
|
|
40228
|
-
return yield (0, failoverStrategies_1.queryMajority)({ method, path:
|
|
40273
|
+
return yield (0, failoverStrategies_1.queryMajority)({ method, path: path7, config: config2, postObject, timeoutOverride });
|
|
40229
40274
|
default:
|
|
40230
40275
|
throw new Error(`Unsupported failover strategy: ${config2.failoverStrategy}`);
|
|
40231
40276
|
}
|
|
@@ -41424,7 +41469,7 @@ var networkSettings = {};
|
|
|
41424
41469
|
const restNetworkSettingsValidationContext = RestNetworkSettingsSchema.safeParse(networkSettings2);
|
|
41425
41470
|
if ("error" in restNetworkSettingsValidationContext) {
|
|
41426
41471
|
const { error: { issues } = {} } = restNetworkSettingsValidationContext;
|
|
41427
|
-
const errorMessage2 = issues === null || issues === void 0 ? void 0 : issues.map(({ message, path:
|
|
41472
|
+
const errorMessage2 = issues === null || issues === void 0 ? void 0 : issues.map(({ message, path: path7 }) => `${path7[0]}: ${message}`).join(", ");
|
|
41428
41473
|
if (throwOnError) {
|
|
41429
41474
|
throw new Error(errorMessage2);
|
|
41430
41475
|
}
|
|
@@ -42806,6 +42851,7 @@ function classifyMemoryWrite(event, ctx, opts = {}) {
|
|
|
42806
42851
|
}
|
|
42807
42852
|
|
|
42808
42853
|
// src-ts/memory/guard.ts
|
|
42854
|
+
var import_node_path4 = __toESM(require("path"));
|
|
42809
42855
|
function emitDebugProbe(event, ctx, memEntry, logger2) {
|
|
42810
42856
|
if (!logger2?.info) return;
|
|
42811
42857
|
const ev = event ?? {};
|
|
@@ -42842,7 +42888,8 @@ async function guardMemoryWrite(input) {
|
|
|
42842
42888
|
toolNames,
|
|
42843
42889
|
enforce = true,
|
|
42844
42890
|
debug: debug2 = false,
|
|
42845
|
-
logger: logger2
|
|
42891
|
+
logger: logger2,
|
|
42892
|
+
memoryFilePath
|
|
42846
42893
|
} = input;
|
|
42847
42894
|
const memEntry = classifyMemoryWrite(event, ctx, { patterns, toolNames });
|
|
42848
42895
|
if (debug2) emitDebugProbe(event, ctx, memEntry, logger2);
|
|
@@ -42878,17 +42925,28 @@ async function guardMemoryWrite(input) {
|
|
|
42878
42925
|
committed: false
|
|
42879
42926
|
};
|
|
42880
42927
|
}
|
|
42881
|
-
|
|
42882
|
-
|
|
42883
|
-
|
|
42884
|
-
|
|
42885
|
-
|
|
42886
|
-
|
|
42887
|
-
|
|
42888
|
-
|
|
42889
|
-
|
|
42928
|
+
const isManagedMemoryFile = memoryFilePath !== void 0 && import_node_path4.default.resolve(memEntry.key) === import_node_path4.default.resolve(memoryFilePath);
|
|
42929
|
+
if (isManagedMemoryFile) {
|
|
42930
|
+
commitMemoryVersion(memEntry.value, auth, {
|
|
42931
|
+
score: scanResult.score,
|
|
42932
|
+
orgName,
|
|
42933
|
+
endpoint
|
|
42934
|
+
}).catch((err) => {
|
|
42935
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
42936
|
+
logger2?.warn?.("[atbash] memory commit to chain failed", {
|
|
42937
|
+
path: memEntry.key,
|
|
42938
|
+
reason
|
|
42939
|
+
});
|
|
42890
42940
|
});
|
|
42891
|
-
}
|
|
42941
|
+
} else {
|
|
42942
|
+
logger2?.info?.(
|
|
42943
|
+
"[atbash] scanned but not committed \u2014 not the managed memory file",
|
|
42944
|
+
{
|
|
42945
|
+
path: memEntry.key,
|
|
42946
|
+
memoryFilePath: memoryFilePath ?? "(not configured)"
|
|
42947
|
+
}
|
|
42948
|
+
);
|
|
42949
|
+
}
|
|
42892
42950
|
logger2?.info?.(
|
|
42893
42951
|
scanResult.verdict === "yellow" ? "[atbash] memory HOLD" : "[atbash] memory ALLOW",
|
|
42894
42952
|
{ path: memEntry.key, score: scanResult.score, reason: scanResult.reason }
|
|
@@ -42897,7 +42955,7 @@ async function guardMemoryWrite(input) {
|
|
|
42897
42955
|
handled: true,
|
|
42898
42956
|
decision: { allow: true },
|
|
42899
42957
|
scanResult,
|
|
42900
|
-
committed:
|
|
42958
|
+
committed: isManagedMemoryFile
|
|
42901
42959
|
};
|
|
42902
42960
|
}
|
|
42903
42961
|
|
|
@@ -42916,26 +42974,26 @@ async function syncLocalMemory(auth, pointer, opts = {}) {
|
|
|
42916
42974
|
const now = Date.now();
|
|
42917
42975
|
const withinTtl = !opts.force && now - pointer.checkedAt < ttl;
|
|
42918
42976
|
if (withinTtl) {
|
|
42919
|
-
return { drifted: false, pointer };
|
|
42977
|
+
return { drifted: false, checked: false, pointer };
|
|
42920
42978
|
}
|
|
42921
42979
|
const currentId = await getActiveMemoryId(auth, opts.chainOpts);
|
|
42922
42980
|
const nextPointer = { activeId: currentId, checkedAt: now };
|
|
42923
42981
|
if (currentId === pointer.activeId) {
|
|
42924
|
-
return { drifted: false, pointer: nextPointer };
|
|
42982
|
+
return { drifted: false, checked: true, pointer: nextPointer };
|
|
42925
42983
|
}
|
|
42926
42984
|
if (currentId === null) {
|
|
42927
|
-
return { drifted: true, current: null, pointer: nextPointer };
|
|
42985
|
+
return { drifted: true, checked: true, current: null, pointer: nextPointer };
|
|
42928
42986
|
}
|
|
42929
42987
|
const row = await getMemoryById(currentId, auth, opts.chainOpts);
|
|
42930
42988
|
if (row.decryptError) {
|
|
42931
42989
|
throw new MemoryIntegrityError(currentId, row.decryptError);
|
|
42932
42990
|
}
|
|
42933
|
-
return { drifted: true, current: row, pointer: nextPointer };
|
|
42991
|
+
return { drifted: true, checked: true, current: row, pointer: nextPointer };
|
|
42934
42992
|
}
|
|
42935
42993
|
|
|
42936
42994
|
// src-ts/memory/pointer-store.ts
|
|
42937
42995
|
var import_node_fs4 = require("fs");
|
|
42938
|
-
var
|
|
42996
|
+
var import_node_path5 = __toESM(require("path"));
|
|
42939
42997
|
var EMPTY = { version: 1, agents: {} };
|
|
42940
42998
|
var PointerStore = class {
|
|
42941
42999
|
constructor(filePath) {
|
|
@@ -42977,19 +43035,19 @@ var PointerStore = class {
|
|
|
42977
43035
|
this.cache = { ...EMPTY, agents: {} };
|
|
42978
43036
|
}
|
|
42979
43037
|
async persist(file) {
|
|
42980
|
-
await import_node_fs4.promises.mkdir(
|
|
43038
|
+
await import_node_fs4.promises.mkdir(import_node_path5.default.dirname(this.filePath), { recursive: true });
|
|
42981
43039
|
const tmp = `${this.filePath}.${process.pid}.tmp`;
|
|
42982
43040
|
await import_node_fs4.promises.writeFile(tmp, JSON.stringify(file, null, 2), "utf8");
|
|
42983
43041
|
await import_node_fs4.promises.rename(tmp, this.filePath);
|
|
42984
43042
|
}
|
|
42985
43043
|
};
|
|
42986
43044
|
function defaultPointerPath(workspaceDir = process.cwd()) {
|
|
42987
|
-
return
|
|
43045
|
+
return import_node_path5.default.join(workspaceDir, ".atbash", "memory-pointer.json");
|
|
42988
43046
|
}
|
|
42989
43047
|
|
|
42990
43048
|
// src-ts/memory/file-logger.ts
|
|
42991
43049
|
var import_node_fs5 = require("fs");
|
|
42992
|
-
var
|
|
43050
|
+
var import_node_path6 = __toESM(require("path"));
|
|
42993
43051
|
function formatMeta(meta) {
|
|
42994
43052
|
if (!meta || Object.keys(meta).length === 0) return "";
|
|
42995
43053
|
try {
|
|
@@ -43001,7 +43059,7 @@ function formatMeta(meta) {
|
|
|
43001
43059
|
function createFileLogger(filePath, upstream) {
|
|
43002
43060
|
let queue = Promise.resolve();
|
|
43003
43061
|
async function ensureDir() {
|
|
43004
|
-
await import_node_fs5.promises.mkdir(
|
|
43062
|
+
await import_node_fs5.promises.mkdir(import_node_path6.default.dirname(filePath), { recursive: true });
|
|
43005
43063
|
}
|
|
43006
43064
|
function append(level, message, meta) {
|
|
43007
43065
|
const line = `${(/* @__PURE__ */ new Date()).toISOString()} [${level}] ${message}${formatMeta(meta)}
|
|
@@ -43021,7 +43079,7 @@ function createFileLogger(filePath, upstream) {
|
|
|
43021
43079
|
};
|
|
43022
43080
|
}
|
|
43023
43081
|
function defaultPluginLogPath(workspaceDir = process.cwd()) {
|
|
43024
|
-
return
|
|
43082
|
+
return import_node_path6.default.join(workspaceDir, ".atbash", "plugin.log");
|
|
43025
43083
|
}
|
|
43026
43084
|
|
|
43027
43085
|
// src-ts/memory/read-classifier.ts
|
|
@@ -43036,13 +43094,13 @@ function classifyMemoryRead(event, ctx, opts = {}) {
|
|
|
43036
43094
|
|
|
43037
43095
|
// src-ts/memory/guard-manager.ts
|
|
43038
43096
|
var import_node_fs6 = require("fs");
|
|
43039
|
-
var
|
|
43097
|
+
var import_node_path7 = __toESM(require("path"));
|
|
43040
43098
|
var DEFAULT_SYNC_TTL_MS = 3e4;
|
|
43041
43099
|
var MemoryGuardManager = class {
|
|
43042
43100
|
constructor(opts) {
|
|
43043
43101
|
this.opts = opts;
|
|
43044
43102
|
const workspaceDir = opts.workspaceDir;
|
|
43045
|
-
this.memoryFilePath = opts.memoryFilePath ??
|
|
43103
|
+
this.memoryFilePath = opts.memoryFilePath ?? import_node_path7.default.join(workspaceDir, "MEMORY.md");
|
|
43046
43104
|
this.pointerStore = new PointerStore(opts.pointerFilePath ?? defaultPointerPath(workspaceDir));
|
|
43047
43105
|
this.logger = createFileLogger(
|
|
43048
43106
|
opts.logFilePath ?? defaultPluginLogPath(workspaceDir),
|
|
@@ -43072,7 +43130,11 @@ var MemoryGuardManager = class {
|
|
|
43072
43130
|
async runBootProbe() {
|
|
43073
43131
|
try {
|
|
43074
43132
|
const seed = { activeId: null, checkedAt: 0 };
|
|
43075
|
-
const result = await syncLocalMemory(this.opts.auth, seed, {
|
|
43133
|
+
const result = await syncLocalMemory(this.opts.auth, seed, {
|
|
43134
|
+
ttlMs: 0,
|
|
43135
|
+
force: true,
|
|
43136
|
+
chainOpts: this.opts.chainOpts
|
|
43137
|
+
});
|
|
43076
43138
|
if (!result.drifted && result.pointer.activeId == null) {
|
|
43077
43139
|
this.logger.info(
|
|
43078
43140
|
`[atbash] no active memory on chain for agent=${this.agentPubkeyHex.slice(0, 16)}\u2026 org=${this.opts.orgName ?? "(none)"} \u2014 either the agent isn't registered on this chain or hasn't written any memory. Sync will remain a no-op until a write lands.`
|
|
@@ -43104,15 +43166,19 @@ var MemoryGuardManager = class {
|
|
|
43104
43166
|
}
|
|
43105
43167
|
}
|
|
43106
43168
|
/**
|
|
43107
|
-
* Returns a `HookDecision` when the
|
|
43108
|
-
*
|
|
43109
|
-
*
|
|
43169
|
+
* Returns a `HookDecision` when the guard reached a decision about this event.
|
|
43170
|
+
* Returns `null` when it did not — either the event isn't memory-related, or it
|
|
43171
|
+
* is but the guard could not check it. In both cases the host falls through to
|
|
43172
|
+
* its own audit.
|
|
43173
|
+
*
|
|
43174
|
+
* A returned decision carries `audited` (see `HookDecision`). Only
|
|
43175
|
+
* `{ allow: true, audited: true }` means "checked and cleared"; anything else
|
|
43176
|
+
* that allows is a call the host still needs to judge.
|
|
43110
43177
|
*/
|
|
43111
43178
|
async handleBeforeToolCall(event, ctx) {
|
|
43112
43179
|
if (classifyMemoryRead(event, ctx, this.opts.memoryReadClassifier)) {
|
|
43113
43180
|
this.logger.info("[atbash] memory read intercepted \u2014 running sync check");
|
|
43114
|
-
|
|
43115
|
-
return readDecision ?? { allow: true };
|
|
43181
|
+
return await this.handleMemoryRead(event, ctx);
|
|
43116
43182
|
}
|
|
43117
43183
|
const guardLogger = {
|
|
43118
43184
|
info: (msg, meta) => this.logger.info(msg, meta && typeof meta === "object" ? meta : void 0),
|
|
@@ -43129,7 +43195,9 @@ var MemoryGuardManager = class {
|
|
|
43129
43195
|
toolNames: this.opts.memoryWriteToolNames,
|
|
43130
43196
|
enforce: this.enforce,
|
|
43131
43197
|
debug: this.opts.debug,
|
|
43132
|
-
logger: guardLogger
|
|
43198
|
+
logger: guardLogger,
|
|
43199
|
+
// Only this file may reach the single, path-less chain memory slot.
|
|
43200
|
+
memoryFilePath: this.memoryFilePath
|
|
43133
43201
|
});
|
|
43134
43202
|
return this.mapGuardResult(guard);
|
|
43135
43203
|
}
|
|
@@ -43147,30 +43215,81 @@ var MemoryGuardManager = class {
|
|
|
43147
43215
|
block: true,
|
|
43148
43216
|
blockReason: d.reason ?? "",
|
|
43149
43217
|
allow: false,
|
|
43150
|
-
reason: d.reason
|
|
43218
|
+
reason: d.reason,
|
|
43219
|
+
// A block IS a decision — the most thoroughly checked one the guard
|
|
43220
|
+
// makes. Without this a host following the documented `!audited ->
|
|
43221
|
+
// judge it yourself` rule would re-judge its way past a red scan.
|
|
43222
|
+
audited: true,
|
|
43223
|
+
...sr2 ? { verdict: sr2.verdict } : {}
|
|
43151
43224
|
};
|
|
43152
43225
|
}
|
|
43153
43226
|
this.logger.info(
|
|
43154
43227
|
`[atbash] guardMemoryWrite ALLOWED \u2014 verdict=${verdict} score=${score} committed=${guard.committed === true}`
|
|
43155
43228
|
);
|
|
43156
|
-
|
|
43229
|
+
if (sr2 === void 0) {
|
|
43230
|
+
return { allow: true, audited: false, reason: "memory scan did not run (observe mode)" };
|
|
43231
|
+
}
|
|
43232
|
+
if (sr2.verdict !== "green") {
|
|
43233
|
+
return {
|
|
43234
|
+
allow: true,
|
|
43235
|
+
audited: false,
|
|
43236
|
+
verdict: sr2.verdict,
|
|
43237
|
+
reason: `memory scan returned ${sr2.verdict} but this guard is not enforcing it`
|
|
43238
|
+
};
|
|
43239
|
+
}
|
|
43240
|
+
return { allow: true, audited: true, verdict: sr2.verdict };
|
|
43157
43241
|
}
|
|
43158
|
-
|
|
43242
|
+
/**
|
|
43243
|
+
* Whether the pointer state this manager tracks actually describes the file
|
|
43244
|
+
* this call is about to read.
|
|
43245
|
+
*
|
|
43246
|
+
* The classifier fires on nine patterns — including the bare tokens
|
|
43247
|
+
* `"memory/"`, `"CLAUDE.md"` and `"AGENTS.md"` — but the sync path only ever
|
|
43248
|
+
* reads, refreshes, or vouches for `this.memoryFilePath`. Without this check a
|
|
43249
|
+
* read of `/repo/CLAUDE.md` (or any path merely containing `memory/`) would
|
|
43250
|
+
* receive an `audited: true` for a file the guard never opened.
|
|
43251
|
+
*
|
|
43252
|
+
* Conservative on purpose: every path-shaped value found must resolve to the
|
|
43253
|
+
* managed file. If none is found, or any one differs, the answer is no. That
|
|
43254
|
+
* also covers events carrying two different path keys, where the classifier
|
|
43255
|
+
* and the host could otherwise disagree about which one is authoritative.
|
|
43256
|
+
*/
|
|
43257
|
+
vouchesForTarget(event, ctx) {
|
|
43258
|
+
const KEYS = ["path", "file_path", "filePath", "notebook_path", "notebookPath", "target"];
|
|
43259
|
+
const found = [];
|
|
43260
|
+
for (const src of [event, ctx]) {
|
|
43261
|
+
for (const bag of [src, src?.params]) {
|
|
43262
|
+
if (!bag || typeof bag !== "object") continue;
|
|
43263
|
+
const rec = bag;
|
|
43264
|
+
for (const k of KEYS) {
|
|
43265
|
+
if (typeof rec[k] === "string" && rec[k]) found.push(rec[k]);
|
|
43266
|
+
}
|
|
43267
|
+
}
|
|
43268
|
+
}
|
|
43269
|
+
if (found.length === 0) return false;
|
|
43270
|
+
const managed = import_node_path7.default.resolve(this.memoryFilePath);
|
|
43271
|
+
return found.every((p) => import_node_path7.default.resolve(p) === managed);
|
|
43272
|
+
}
|
|
43273
|
+
async handleMemoryRead(event, ctx) {
|
|
43159
43274
|
const pointer = await this.pointerStore.get(this.agentPubkeyHex);
|
|
43160
43275
|
let result;
|
|
43161
43276
|
try {
|
|
43162
|
-
result = await syncLocalMemory(this.opts.auth, pointer, {
|
|
43277
|
+
result = await syncLocalMemory(this.opts.auth, pointer, {
|
|
43278
|
+
ttlMs: this.ttlMs,
|
|
43279
|
+
chainOpts: this.opts.chainOpts
|
|
43280
|
+
});
|
|
43163
43281
|
} catch (err) {
|
|
43164
43282
|
if (err instanceof MemoryIntegrityError) {
|
|
43165
43283
|
const reason = `Memory integrity check failed on id ${err.id} \u2014 read blocked.`;
|
|
43166
43284
|
this.logger.warn("[atbash] MEMORY INTEGRITY FAILURE", { id: err.id, error: err.message });
|
|
43167
43285
|
if (!this.enforce) return null;
|
|
43168
|
-
return { block: true, blockReason: reason, allow: false, reason };
|
|
43286
|
+
return { block: true, blockReason: reason, allow: false, reason, audited: true };
|
|
43169
43287
|
}
|
|
43170
43288
|
const msg = err instanceof Error ? err.message : String(err);
|
|
43171
43289
|
this.logger.warn("[atbash] memory sync failed (serving local copy)", { error: msg });
|
|
43172
43290
|
return null;
|
|
43173
43291
|
}
|
|
43292
|
+
let onDiskIsCurrent = result.checked;
|
|
43174
43293
|
if (result.drifted) {
|
|
43175
43294
|
const fresh = result.current;
|
|
43176
43295
|
if (fresh) {
|
|
@@ -43178,7 +43297,7 @@ var MemoryGuardManager = class {
|
|
|
43178
43297
|
const reason = `Rolled-back memory version #${fresh.id} scored ${fresh.score} (below threshold ${this.rollbackMinScore}) \u2014 read blocked.`;
|
|
43179
43298
|
this.logger.warn("[atbash] blocking read on low-score rollback", { id: fresh.id, score: fresh.score });
|
|
43180
43299
|
if (!this.enforce) return null;
|
|
43181
|
-
return { block: true, blockReason: reason, allow: false, reason };
|
|
43300
|
+
return { block: true, blockReason: reason, allow: false, reason, audited: true };
|
|
43182
43301
|
}
|
|
43183
43302
|
this.logger.info("[atbash] memory drift detected \u2014 refreshing local file", {
|
|
43184
43303
|
id: fresh.id,
|
|
@@ -43189,16 +43308,26 @@ var MemoryGuardManager = class {
|
|
|
43189
43308
|
} catch (err) {
|
|
43190
43309
|
const msg = err instanceof Error ? err.message : String(err);
|
|
43191
43310
|
this.logger.warn("[atbash] failed to write refreshed memory (serving old)", { error: msg });
|
|
43311
|
+
onDiskIsCurrent = false;
|
|
43192
43312
|
}
|
|
43193
43313
|
} else {
|
|
43194
43314
|
this.logger.info("[atbash] active memory removed on chain", { pubkey: this.agentPubkeyHex });
|
|
43315
|
+
onDiskIsCurrent = false;
|
|
43195
43316
|
}
|
|
43196
43317
|
}
|
|
43197
|
-
|
|
43198
|
-
|
|
43318
|
+
if (onDiskIsCurrent) {
|
|
43319
|
+
await this.pointerStore.set(this.agentPubkeyHex, result.pointer);
|
|
43320
|
+
} else {
|
|
43321
|
+
this.logger.warn(
|
|
43322
|
+
"[atbash] not advancing memory pointer \u2014 local file is stale or revoked; reads stay unaudited until it is refreshed"
|
|
43323
|
+
);
|
|
43324
|
+
}
|
|
43325
|
+
if (!onDiskIsCurrent) return null;
|
|
43326
|
+
if (!this.vouchesForTarget(event, ctx)) return null;
|
|
43327
|
+
return { allow: true, audited: true };
|
|
43199
43328
|
}
|
|
43200
43329
|
async writeMemoryAtomic(content) {
|
|
43201
|
-
await import_node_fs6.promises.mkdir(
|
|
43330
|
+
await import_node_fs6.promises.mkdir(import_node_path7.default.dirname(this.memoryFilePath), { recursive: true });
|
|
43202
43331
|
const tmp = `${this.memoryFilePath}.${process.pid}.tmp`;
|
|
43203
43332
|
await import_node_fs6.promises.writeFile(tmp, content, "utf8");
|
|
43204
43333
|
await import_node_fs6.promises.rename(tmp, this.memoryFilePath);
|