@atbash/sdk 0.18.0-dev.0 → 0.19.0-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/README.md +75 -12
- package/dist/browser.d.mts +145 -1
- package/dist/browser.mjs +108 -25
- package/dist/index.d.mts +145 -1
- package/dist/index.d.ts +145 -1
- package/dist/index.js +256 -40
- package/dist/index.mjs +253 -40
- package/package.json +9 -6
package/dist/index.mjs
CHANGED
|
@@ -473,6 +473,59 @@ function canonicalAllow(data) {
|
|
|
473
473
|
return verdict === "ALLOW" || verdict === "GREEN";
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
+
// src-ts/opentel/events.ts
|
|
477
|
+
var SLOW_MS = 1500;
|
|
478
|
+
var SUCCESS_SAMPLE_RATE = 10;
|
|
479
|
+
var logger = null;
|
|
480
|
+
var eventsEnabled = false;
|
|
481
|
+
var sdkVersion = "";
|
|
482
|
+
var eventSource = "sdk";
|
|
483
|
+
var hashAgentKey = null;
|
|
484
|
+
function eventsOptedOut() {
|
|
485
|
+
const flag = process.env.ATBASH_TELEMETRY_EVENTS_DISABLED?.trim().toLowerCase();
|
|
486
|
+
return Boolean(flag && ["1", "true", "yes", "on"].includes(flag));
|
|
487
|
+
}
|
|
488
|
+
function configureEvents(next, opts = {}) {
|
|
489
|
+
logger = next;
|
|
490
|
+
eventsEnabled = next !== null && !eventsOptedOut();
|
|
491
|
+
if (opts.version) sdkVersion = opts.version;
|
|
492
|
+
if (opts.source) eventSource = opts.source;
|
|
493
|
+
hashAgentKey = opts.hashAgentKey ?? null;
|
|
494
|
+
}
|
|
495
|
+
function eventsAreOn() {
|
|
496
|
+
return eventsEnabled && logger !== null;
|
|
497
|
+
}
|
|
498
|
+
function sampleRateFor(e) {
|
|
499
|
+
if (e.status === "error") return 1;
|
|
500
|
+
if (e.durationMs >= SLOW_MS) return 1;
|
|
501
|
+
return Math.random() < 1 / SUCCESS_SAMPLE_RATE ? SUCCESS_SAMPLE_RATE : 0;
|
|
502
|
+
}
|
|
503
|
+
function recordEvent(e) {
|
|
504
|
+
if (!eventsAreOn()) return;
|
|
505
|
+
const sampleRate = sampleRateFor(e);
|
|
506
|
+
if (sampleRate === 0) return;
|
|
507
|
+
try {
|
|
508
|
+
const attributes = {
|
|
509
|
+
"function.name": e.functionName,
|
|
510
|
+
"duration_ms": Math.round(e.durationMs),
|
|
511
|
+
status: e.status,
|
|
512
|
+
source: eventSource,
|
|
513
|
+
// Honeycomb reweights counts and percentiles by this. It is per-event
|
|
514
|
+
// because the sampling is biased by outcome and latency.
|
|
515
|
+
sampleRate
|
|
516
|
+
};
|
|
517
|
+
if (sdkVersion) attributes["sdk.version"] = sdkVersion;
|
|
518
|
+
if (e.agentPubkey && hashAgentKey) attributes["agent.hash"] = hashAgentKey(e.agentPubkey);
|
|
519
|
+
if (e.chain) attributes["chain"] = e.chain;
|
|
520
|
+
if (e.errorClass) attributes["error.class"] = e.errorClass;
|
|
521
|
+
if (e.errorStatus !== void 0) attributes["error.status"] = e.errorStatus;
|
|
522
|
+
if (e.errorPath) attributes["error.path"] = e.errorPath;
|
|
523
|
+
if (e.outcome) attributes["outcome"] = e.outcome;
|
|
524
|
+
logger.emit({ body: e.functionName, attributes });
|
|
525
|
+
} catch {
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
476
529
|
// src-ts/opentel/telemetry.ts
|
|
477
530
|
import { readFileSync as readFileSync2 } from "fs";
|
|
478
531
|
import { homedir as homedir2 } from "os";
|
|
@@ -486,7 +539,11 @@ import {
|
|
|
486
539
|
MeterProvider,
|
|
487
540
|
PeriodicExportingMetricReader
|
|
488
541
|
} from "@opentelemetry/sdk-metrics";
|
|
542
|
+
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
543
|
+
import { BatchLogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
|
|
544
|
+
import { createHash } from "crypto";
|
|
489
545
|
var meterProvider = null;
|
|
546
|
+
var loggerProvider = null;
|
|
490
547
|
var callCounter = null;
|
|
491
548
|
var durationHistogram = null;
|
|
492
549
|
var defaultSource = "sdk";
|
|
@@ -513,6 +570,41 @@ function autoInit() {
|
|
|
513
570
|
if (isTelemetryOptedOut()) return;
|
|
514
571
|
setupTelemetry({ enabled: true });
|
|
515
572
|
}
|
|
573
|
+
function defaultAgentKeyHasher(pubkeyHex) {
|
|
574
|
+
return createHash("sha256").update(pubkeyHex).digest("hex");
|
|
575
|
+
}
|
|
576
|
+
var counterHasher = null;
|
|
577
|
+
function hashAgentKeyOrDrop(pubkeyHex) {
|
|
578
|
+
return counterHasher ? counterHasher(pubkeyHex) : void 0;
|
|
579
|
+
}
|
|
580
|
+
function customCollector() {
|
|
581
|
+
const url = process.env.ATBASH_TELEMETRY_COLLECTOR_URL?.trim();
|
|
582
|
+
if (!url) return null;
|
|
583
|
+
const loopback = /^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(:|\/|$)/i.test(url);
|
|
584
|
+
if (loopback && process.env.ATBASH_TELEMETRY_ALLOW_LOOPBACK !== "1") {
|
|
585
|
+
throw new Error(
|
|
586
|
+
"ATBASH_TELEMETRY_COLLECTOR_URL is a loopback address; set ATBASH_TELEMETRY_ALLOW_LOOPBACK=1 to allow it."
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
if (!loopback && !/^https:\/\//i.test(url)) {
|
|
590
|
+
throw new Error("ATBASH_TELEMETRY_COLLECTOR_URL must be https (loopback excepted).");
|
|
591
|
+
}
|
|
592
|
+
let headers = {};
|
|
593
|
+
const raw = process.env.ATBASH_TELEMETRY_COLLECTOR_HEADERS?.trim();
|
|
594
|
+
if (raw) {
|
|
595
|
+
try {
|
|
596
|
+
const parsed = JSON.parse(raw);
|
|
597
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
598
|
+
headers = Object.fromEntries(
|
|
599
|
+
Object.entries(parsed).map(([k, v]) => [k, String(v)])
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
} catch {
|
|
603
|
+
throw new Error("ATBASH_TELEMETRY_COLLECTOR_HEADERS must be a JSON object of header names to values.");
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return { url: url.replace(/\/+$/, ""), headers: () => headers };
|
|
607
|
+
}
|
|
516
608
|
function setupTelemetry(config) {
|
|
517
609
|
if (!config.enabled) return;
|
|
518
610
|
if (isTelemetryOptedOut()) return;
|
|
@@ -524,16 +616,20 @@ function setupTelemetry(config) {
|
|
|
524
616
|
requestedExportIntervalMs = config.exportIntervalMs;
|
|
525
617
|
}
|
|
526
618
|
if (meterProvider) return;
|
|
527
|
-
|
|
528
|
-
if (
|
|
619
|
+
const collector = customCollector();
|
|
620
|
+
if (!collector && (!config.endpoint || !config.getAuthHeaders)) return;
|
|
621
|
+
if (!collector && /^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0)(:|\/|$)/i.test(
|
|
529
622
|
config.endpoint
|
|
530
623
|
))
|
|
531
624
|
return;
|
|
532
|
-
const
|
|
533
|
-
|
|
625
|
+
const destination = collector ?? {
|
|
626
|
+
url: `${config.endpoint.replace(/\/+$/, "")}/api/telemetry`,
|
|
627
|
+
headers: () => config.getAuthHeaders()
|
|
628
|
+
};
|
|
629
|
+
const proxyUrl = destination.url;
|
|
534
630
|
const exporter = new OTLPMetricExporter({
|
|
535
|
-
url: proxyUrl,
|
|
536
|
-
headers: async () =>
|
|
631
|
+
url: collector ? `${proxyUrl}/v1/metrics` : proxyUrl,
|
|
632
|
+
headers: async () => destination.headers(),
|
|
537
633
|
// DELTA, not the OTel default of CUMULATIVE.
|
|
538
634
|
//
|
|
539
635
|
// A cumulative counter reports a running total, and the backend recovers
|
|
@@ -565,6 +661,21 @@ function setupTelemetry(config) {
|
|
|
565
661
|
description: "SDK function execution duration",
|
|
566
662
|
unit: "ms"
|
|
567
663
|
});
|
|
664
|
+
counterHasher = config.hashAgentKey ?? defaultAgentKeyHasher;
|
|
665
|
+
const logExporter = new OTLPLogExporter({
|
|
666
|
+
// A real collector takes OTLP at its own signal paths; the Atbash proxy
|
|
667
|
+
// takes a query parameter, because it is one authenticated route.
|
|
668
|
+
url: collector ? `${proxyUrl}/v1/logs` : `${proxyUrl}?signal=logs`,
|
|
669
|
+
headers: async () => destination.headers()
|
|
670
|
+
});
|
|
671
|
+
loggerProvider = new LoggerProvider({
|
|
672
|
+
resource: resourceFromAttributes({ "service.name": "atbash-sdk" }),
|
|
673
|
+
processors: [new BatchLogRecordProcessor({ exporter: logExporter })]
|
|
674
|
+
});
|
|
675
|
+
configureEvents(loggerProvider.getLogger("atbash-sdk"), {
|
|
676
|
+
source: config.source ?? defaultSource,
|
|
677
|
+
hashAgentKey: config.hashAgentKey ?? defaultAgentKeyHasher
|
|
678
|
+
});
|
|
568
679
|
}
|
|
569
680
|
function recordCall(functionName, source, agentPubkey) {
|
|
570
681
|
autoInit();
|
|
@@ -572,7 +683,10 @@ function recordCall(functionName, source, agentPubkey) {
|
|
|
572
683
|
callCounter.add(1, {
|
|
573
684
|
"function.name": functionName,
|
|
574
685
|
source: source ?? defaultSource,
|
|
575
|
-
|
|
686
|
+
// Hashed on this path too. The counters and the events export to the same
|
|
687
|
+
// place in the same request, so a raw key here would make hashing it on
|
|
688
|
+
// the event beside it pointless.
|
|
689
|
+
...agentPubkey && { "agent.hash": hashAgentKeyOrDrop(agentPubkey) }
|
|
576
690
|
});
|
|
577
691
|
}
|
|
578
692
|
function recordDuration(functionName, durationMs, status, source) {
|
|
@@ -584,15 +698,16 @@ function recordDuration(functionName, durationMs, status, source) {
|
|
|
584
698
|
});
|
|
585
699
|
}
|
|
586
700
|
async function flushTelemetry() {
|
|
587
|
-
|
|
588
|
-
await meterProvider.forceFlush();
|
|
701
|
+
await Promise.all([meterProvider?.forceFlush(), loggerProvider?.forceFlush()]);
|
|
589
702
|
}
|
|
590
703
|
async function shutdownTelemetry() {
|
|
591
|
-
|
|
592
|
-
await meterProvider.shutdown();
|
|
704
|
+
await Promise.all([meterProvider?.shutdown(), loggerProvider?.shutdown()]);
|
|
593
705
|
meterProvider = null;
|
|
706
|
+
loggerProvider = null;
|
|
594
707
|
callCounter = null;
|
|
595
708
|
durationHistogram = null;
|
|
709
|
+
counterHasher = null;
|
|
710
|
+
configureEvents(null);
|
|
596
711
|
defaultSource = "sdk";
|
|
597
712
|
sourceExplicitlySet = false;
|
|
598
713
|
requestedExportIntervalMs = void 0;
|
|
@@ -700,6 +815,13 @@ function resolveConstructorChain(options) {
|
|
|
700
815
|
}
|
|
701
816
|
return chainForNetwork(options.network ?? forcedChainNetwork() ?? "private");
|
|
702
817
|
}
|
|
818
|
+
function errorDetail(err) {
|
|
819
|
+
if (!(err instanceof AtbashAPIError)) return {};
|
|
820
|
+
return {
|
|
821
|
+
errorStatus: err.status,
|
|
822
|
+
...err.path ? { errorPath: err.path } : {}
|
|
823
|
+
};
|
|
824
|
+
}
|
|
703
825
|
var Atbash = class _Atbash {
|
|
704
826
|
auth;
|
|
705
827
|
endpoint;
|
|
@@ -910,7 +1032,7 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
|
|
|
910
1032
|
*
|
|
911
1033
|
* @param logger - The host logger, when one was supplied.
|
|
912
1034
|
*/
|
|
913
|
-
static warnOnStrandedKey(
|
|
1035
|
+
static warnOnStrandedKey(logger2) {
|
|
914
1036
|
const stranded = strandedAgentKey();
|
|
915
1037
|
if (!stranded) return;
|
|
916
1038
|
let identity;
|
|
@@ -919,7 +1041,7 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
|
|
|
919
1041
|
} catch {
|
|
920
1042
|
identity = "(unreadable)";
|
|
921
1043
|
}
|
|
922
|
-
|
|
1044
|
+
logger2?.warn?.(
|
|
923
1045
|
`[atbash] "agentKey" in config.json is ignored \u2014 settings do not choose the signing key. It holds ${identity}; this client signs as the key file or ATBASH_AGENT_KEY instead. Move it into the key file, or delete the field, to silence this.`
|
|
924
1046
|
);
|
|
925
1047
|
}
|
|
@@ -1678,10 +1800,28 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
|
|
|
1678
1800
|
recordCall(name, void 0, agentPubkey);
|
|
1679
1801
|
try {
|
|
1680
1802
|
const result = await fn();
|
|
1681
|
-
|
|
1803
|
+
const durationMs = performance.now() - start;
|
|
1804
|
+
recordDuration(name, durationMs, "success");
|
|
1805
|
+
recordEvent({
|
|
1806
|
+
functionName: name,
|
|
1807
|
+
durationMs,
|
|
1808
|
+
status: "success",
|
|
1809
|
+
agentPubkey,
|
|
1810
|
+
chain: this.blockchainRid
|
|
1811
|
+
});
|
|
1682
1812
|
return result;
|
|
1683
1813
|
} catch (err) {
|
|
1684
|
-
|
|
1814
|
+
const durationMs = performance.now() - start;
|
|
1815
|
+
recordDuration(name, durationMs, "error");
|
|
1816
|
+
recordEvent({
|
|
1817
|
+
functionName: name,
|
|
1818
|
+
durationMs,
|
|
1819
|
+
status: "error",
|
|
1820
|
+
agentPubkey,
|
|
1821
|
+
chain: this.blockchainRid,
|
|
1822
|
+
errorClass: err instanceof Error ? err.constructor.name : typeof err,
|
|
1823
|
+
...errorDetail(err)
|
|
1824
|
+
});
|
|
1685
1825
|
throw err;
|
|
1686
1826
|
}
|
|
1687
1827
|
}
|
|
@@ -2174,6 +2314,47 @@ async function scanMemoryBatch(entries, auth, opts) {
|
|
|
2174
2314
|
return results;
|
|
2175
2315
|
}
|
|
2176
2316
|
|
|
2317
|
+
// src-ts/memory/telemetry.ts
|
|
2318
|
+
function metricName(action) {
|
|
2319
|
+
return `memory.${action}`;
|
|
2320
|
+
}
|
|
2321
|
+
function recordMemoryCall(action, startedAt, agentPubkey, status, err) {
|
|
2322
|
+
const name = metricName(action);
|
|
2323
|
+
const durationMs = performance.now() - startedAt;
|
|
2324
|
+
recordCall(name, void 0, agentPubkey);
|
|
2325
|
+
recordDuration(name, durationMs, status);
|
|
2326
|
+
recordEvent({
|
|
2327
|
+
functionName: name,
|
|
2328
|
+
durationMs,
|
|
2329
|
+
status,
|
|
2330
|
+
agentPubkey,
|
|
2331
|
+
...err !== void 0 && {
|
|
2332
|
+
errorClass: err instanceof Error ? err.constructor.name : typeof err,
|
|
2333
|
+
// The chain transport is where the failures are, so the status and the
|
|
2334
|
+
// route are the whole of what makes one diagnosable.
|
|
2335
|
+
...err instanceof AtbashAPIError && {
|
|
2336
|
+
errorStatus: err.status,
|
|
2337
|
+
...err.path ? { errorPath: err.path } : {}
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
});
|
|
2341
|
+
}
|
|
2342
|
+
function recordMemoryGuard(verdict, committed, blocked, startedAt, agentPubkey) {
|
|
2343
|
+
const durationMs = performance.now() - startedAt;
|
|
2344
|
+
recordCall("memory.guard", void 0, agentPubkey);
|
|
2345
|
+
recordDuration("memory.guard", durationMs, blocked ? "error" : "success");
|
|
2346
|
+
recordEvent({
|
|
2347
|
+
functionName: "memory.guard",
|
|
2348
|
+
durationMs,
|
|
2349
|
+
// A block is the outcome worth keeping every one of; the sampler keeps
|
|
2350
|
+
// errors whole, and a refused write is an error from the agent's side.
|
|
2351
|
+
status: blocked ? "error" : "success",
|
|
2352
|
+
agentPubkey,
|
|
2353
|
+
errorClass: blocked ? `memory-blocked:${verdict}` : void 0,
|
|
2354
|
+
outcome: `${verdict}/${committed ? "committed" : "uncommitted"}`
|
|
2355
|
+
});
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2177
2358
|
// src-ts/memory/transport.ts
|
|
2178
2359
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
2179
2360
|
function transport(opts) {
|
|
@@ -2186,24 +2367,39 @@ async function failure(action, resp) {
|
|
|
2186
2367
|
);
|
|
2187
2368
|
}
|
|
2188
2369
|
async function memoryQuery(action, auth, blockchainRid, opts, filePath, extra = {}) {
|
|
2370
|
+
const start = performance.now();
|
|
2189
2371
|
const params = new URLSearchParams({ action, agent: auth.pubkey });
|
|
2190
2372
|
if (filePath !== null) params.set("file_path", filePath);
|
|
2191
2373
|
for (const [key, value] of Object.entries(extra)) params.set(key, String(value));
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2374
|
+
try {
|
|
2375
|
+
const resp = await transport(opts).get(
|
|
2376
|
+
`/api/risk-engine?${params.toString()}`,
|
|
2377
|
+
void 0,
|
|
2378
|
+
agentAuthHeaders(auth, blockchainRid)
|
|
2379
|
+
);
|
|
2380
|
+
if (resp.status !== 200) throw await failure(action, resp);
|
|
2381
|
+
const body = await resp.json();
|
|
2382
|
+
recordMemoryCall(action, start, auth.pubkey, "success");
|
|
2383
|
+
return body;
|
|
2384
|
+
} catch (err) {
|
|
2385
|
+
recordMemoryCall(action, start, auth.pubkey, "error", err);
|
|
2386
|
+
throw err;
|
|
2387
|
+
}
|
|
2199
2388
|
}
|
|
2200
2389
|
async function memorySubmit(action, auth, opts, signedField, signedHex) {
|
|
2201
|
-
const
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2390
|
+
const start = performance.now();
|
|
2391
|
+
try {
|
|
2392
|
+
const resp = await transport(opts).post("/api/risk-engine", {
|
|
2393
|
+
action,
|
|
2394
|
+
agentPubkey: auth.pubkey,
|
|
2395
|
+
[signedField]: signedHex
|
|
2396
|
+
});
|
|
2397
|
+
if (resp.status !== 200) throw await failure(action, resp);
|
|
2398
|
+
recordMemoryCall(action, start, auth.pubkey, "success");
|
|
2399
|
+
} catch (err) {
|
|
2400
|
+
recordMemoryCall(action, start, auth.pubkey, "error", err);
|
|
2401
|
+
throw err;
|
|
2402
|
+
}
|
|
2207
2403
|
}
|
|
2208
2404
|
|
|
2209
2405
|
// src-ts/memory/chain.ts
|
|
@@ -2457,8 +2653,8 @@ function classifyMemoryWrite(event, ctx, opts = {}) {
|
|
|
2457
2653
|
import { promises as fs } from "fs";
|
|
2458
2654
|
import os from "os";
|
|
2459
2655
|
import path from "path";
|
|
2460
|
-
function emitDebugProbe(event, ctx, memEntry,
|
|
2461
|
-
if (!
|
|
2656
|
+
function emitDebugProbe(event, ctx, memEntry, logger2) {
|
|
2657
|
+
if (!logger2?.info) return;
|
|
2462
2658
|
const ev = event ?? {};
|
|
2463
2659
|
const c = ctx ?? {};
|
|
2464
2660
|
const argsCandidate = ev.params ?? c.params ?? ev.args ?? c.args ?? ev.arguments ?? c.arguments;
|
|
@@ -2468,7 +2664,7 @@ function emitDebugProbe(event, ctx, memEntry, logger) {
|
|
|
2468
2664
|
const editsArr = Array.isArray(argsObj.edits) ? argsObj.edits : null;
|
|
2469
2665
|
const firstEditKeys = editsArr && editsArr[0] && typeof editsArr[0] === "object" ? Object.keys(editsArr[0]).slice(0, 10) : null;
|
|
2470
2666
|
const tool = ev.toolName ?? c.tool?.name ?? c.toolName ?? c.name ?? "(none)";
|
|
2471
|
-
|
|
2667
|
+
logger2.info("[atbash][probe] before_tool_call", {
|
|
2472
2668
|
toolName: tool,
|
|
2473
2669
|
eventKeys: Object.keys(ev).slice(0, 20),
|
|
2474
2670
|
ctxKeys: Object.keys(c).slice(0, 20),
|
|
@@ -2496,6 +2692,20 @@ async function resultingDocument(memEntry, event, ctx) {
|
|
|
2496
2692
|
return native.applyMemoryEdits(current, edits);
|
|
2497
2693
|
}
|
|
2498
2694
|
async function guardMemoryWrite(input) {
|
|
2695
|
+
const start = performance.now();
|
|
2696
|
+
const result = await guardMemoryWriteInner(input);
|
|
2697
|
+
if (result.handled) {
|
|
2698
|
+
recordMemoryGuard(
|
|
2699
|
+
result.scanResult?.verdict ?? "unscanned",
|
|
2700
|
+
result.committed === true,
|
|
2701
|
+
result.decision?.block === true,
|
|
2702
|
+
start,
|
|
2703
|
+
input.auth.pubkey
|
|
2704
|
+
);
|
|
2705
|
+
}
|
|
2706
|
+
return result;
|
|
2707
|
+
}
|
|
2708
|
+
async function guardMemoryWriteInner(input) {
|
|
2499
2709
|
const {
|
|
2500
2710
|
event,
|
|
2501
2711
|
ctx,
|
|
@@ -2509,7 +2719,7 @@ async function guardMemoryWrite(input) {
|
|
|
2509
2719
|
toolNames,
|
|
2510
2720
|
enforce = true,
|
|
2511
2721
|
debug = false,
|
|
2512
|
-
logger,
|
|
2722
|
+
logger: logger2,
|
|
2513
2723
|
agentHomeDirs,
|
|
2514
2724
|
memoryRoot
|
|
2515
2725
|
} = input;
|
|
@@ -2518,7 +2728,7 @@ async function guardMemoryWrite(input) {
|
|
|
2518
2728
|
memEntry = classifyMemoryWrite(event, ctx, { patterns, toolNames });
|
|
2519
2729
|
} catch (err) {
|
|
2520
2730
|
const why = err instanceof Error ? err.message : String(err);
|
|
2521
|
-
|
|
2731
|
+
logger2?.warn?.("[atbash] memory classifier refused this tool call's input", { reason: why });
|
|
2522
2732
|
if (!enforce) return { handled: false };
|
|
2523
2733
|
return {
|
|
2524
2734
|
handled: true,
|
|
@@ -2529,14 +2739,14 @@ async function guardMemoryWrite(input) {
|
|
|
2529
2739
|
}
|
|
2530
2740
|
};
|
|
2531
2741
|
}
|
|
2532
|
-
if (debug) emitDebugProbe(event, ctx, memEntry,
|
|
2742
|
+
if (debug) emitDebugProbe(event, ctx, memEntry, logger2);
|
|
2533
2743
|
if (!memEntry) return { handled: false };
|
|
2534
2744
|
let document;
|
|
2535
2745
|
try {
|
|
2536
2746
|
document = await resultingDocument(memEntry, event, ctx);
|
|
2537
2747
|
} catch (err) {
|
|
2538
2748
|
const reason = err instanceof Error ? err.message : String(err);
|
|
2539
|
-
|
|
2749
|
+
logger2?.warn?.("[atbash] memory edit could not be applied", { path: memEntry.key, reason });
|
|
2540
2750
|
return {
|
|
2541
2751
|
handled: true,
|
|
2542
2752
|
decision: enforce ? { allow: false, block: true, reason: `Memory edit refused: ${reason}` } : { allow: true, reason: `Memory edit refused: ${reason}` },
|
|
@@ -2554,7 +2764,7 @@ async function guardMemoryWrite(input) {
|
|
|
2554
2764
|
});
|
|
2555
2765
|
} catch (err) {
|
|
2556
2766
|
const reason = err instanceof Error ? err.message : String(err);
|
|
2557
|
-
|
|
2767
|
+
logger2?.warn?.("[atbash] memory scan failed", {
|
|
2558
2768
|
path: memEntry.key,
|
|
2559
2769
|
reason
|
|
2560
2770
|
});
|
|
@@ -2564,7 +2774,7 @@ async function guardMemoryWrite(input) {
|
|
|
2564
2774
|
};
|
|
2565
2775
|
}
|
|
2566
2776
|
if (scanResult.verdict === "red") {
|
|
2567
|
-
|
|
2777
|
+
logger2?.warn?.("[atbash] memory BLOCK", {
|
|
2568
2778
|
path: memEntry.key,
|
|
2569
2779
|
reason: scanResult.reason
|
|
2570
2780
|
});
|
|
@@ -2586,7 +2796,7 @@ async function guardMemoryWrite(input) {
|
|
|
2586
2796
|
}
|
|
2587
2797
|
const filePath = memorySlotFor(memEntry.key, memoryRoot, agentHomeDirs);
|
|
2588
2798
|
if (filePath === null) {
|
|
2589
|
-
|
|
2799
|
+
logger2?.info?.(
|
|
2590
2800
|
`[atbash] memory scanned but not recorded \u2014 ${memEntry.key} is not inside an agent home (${(agentHomeDirs ?? native.defaultAgentHomeDirs()).join(", ")}) in your home directory, so it has no chain slot of its own.`,
|
|
2591
2801
|
{ path: memEntry.key, verdict: scanResult.verdict, score: scanResult.score }
|
|
2592
2802
|
);
|
|
@@ -2608,7 +2818,7 @@ async function guardMemoryWrite(input) {
|
|
|
2608
2818
|
});
|
|
2609
2819
|
} catch (err) {
|
|
2610
2820
|
const reason = err instanceof Error ? err.message : String(err);
|
|
2611
|
-
|
|
2821
|
+
logger2?.warn?.("[atbash] memory commit to chain failed", {
|
|
2612
2822
|
path: memEntry.key,
|
|
2613
2823
|
filePath,
|
|
2614
2824
|
reason
|
|
@@ -2620,7 +2830,7 @@ async function guardMemoryWrite(input) {
|
|
|
2620
2830
|
committed: false
|
|
2621
2831
|
};
|
|
2622
2832
|
}
|
|
2623
|
-
|
|
2833
|
+
logger2?.info?.(
|
|
2624
2834
|
scanResult.verdict === "yellow" ? "[atbash] memory ALLOW (yellow, low score)" : "[atbash] memory ALLOW",
|
|
2625
2835
|
{
|
|
2626
2836
|
path: memEntry.key,
|
|
@@ -3532,6 +3742,7 @@ export {
|
|
|
3532
3742
|
classifyMemoryWrite,
|
|
3533
3743
|
columnAad,
|
|
3534
3744
|
commitMemoryVersion,
|
|
3745
|
+
configureEvents,
|
|
3535
3746
|
containsEvasionCharacters,
|
|
3536
3747
|
containsSecret,
|
|
3537
3748
|
createFileLogger,
|
|
@@ -3547,6 +3758,7 @@ export {
|
|
|
3547
3758
|
encryptForOrg,
|
|
3548
3759
|
encryptMemoryContent,
|
|
3549
3760
|
encryptedLength,
|
|
3761
|
+
eventsAreOn,
|
|
3550
3762
|
flushTelemetry,
|
|
3551
3763
|
generateKeypair,
|
|
3552
3764
|
getActiveAgentMemory,
|
|
@@ -3575,6 +3787,7 @@ export {
|
|
|
3575
3787
|
pubkeyToHex,
|
|
3576
3788
|
recordCall,
|
|
3577
3789
|
recordDuration,
|
|
3790
|
+
recordEvent,
|
|
3578
3791
|
redactJsonStrings,
|
|
3579
3792
|
redactSecrets,
|
|
3580
3793
|
resolve,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atbash/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0-dev.0",
|
|
4
4
|
"description": "TypeScript SDK for Atbash — the safety layer that evaluates AI agent actions against operator-defined policies before execution.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"atbash",
|
|
@@ -70,8 +70,11 @@
|
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@opentelemetry/api": "^1.9.1",
|
|
73
|
+
"@opentelemetry/api-logs": "^0.223.0",
|
|
74
|
+
"@opentelemetry/exporter-logs-otlp-http": "^0.223.0",
|
|
73
75
|
"@opentelemetry/exporter-metrics-otlp-http": "^0.219.0",
|
|
74
76
|
"@opentelemetry/resources": "^2.7.1",
|
|
77
|
+
"@opentelemetry/sdk-logs": "^0.223.0",
|
|
75
78
|
"@opentelemetry/sdk-metrics": "^2.7.1"
|
|
76
79
|
},
|
|
77
80
|
"devDependencies": {
|
|
@@ -92,10 +95,10 @@
|
|
|
92
95
|
"typescript-eslint": "^8.62.1"
|
|
93
96
|
},
|
|
94
97
|
"optionalDependencies": {
|
|
95
|
-
"@atbash/sdk-linux-x64-gnu": "0.
|
|
96
|
-
"@atbash/sdk-linux-arm64-gnu": "0.
|
|
97
|
-
"@atbash/sdk-linux-x64-musl": "0.
|
|
98
|
-
"@atbash/sdk-darwin-arm64": "0.
|
|
99
|
-
"@atbash/sdk-win32-x64-msvc": "0.
|
|
98
|
+
"@atbash/sdk-linux-x64-gnu": "0.19.0-dev.0",
|
|
99
|
+
"@atbash/sdk-linux-arm64-gnu": "0.19.0-dev.0",
|
|
100
|
+
"@atbash/sdk-linux-x64-musl": "0.19.0-dev.0",
|
|
101
|
+
"@atbash/sdk-darwin-arm64": "0.19.0-dev.0",
|
|
102
|
+
"@atbash/sdk-win32-x64-msvc": "0.19.0-dev.0"
|
|
100
103
|
}
|
|
101
104
|
}
|