@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/dist/index.js CHANGED
@@ -59,6 +59,7 @@ __export(src_ts_exports, {
59
59
  classifyMemoryWrite: () => classifyMemoryWrite,
60
60
  columnAad: () => columnAad,
61
61
  commitMemoryVersion: () => commitMemoryVersion,
62
+ configureEvents: () => configureEvents,
62
63
  containsEvasionCharacters: () => containsEvasionCharacters,
63
64
  containsSecret: () => containsSecret,
64
65
  createFileLogger: () => createFileLogger,
@@ -74,6 +75,7 @@ __export(src_ts_exports, {
74
75
  encryptForOrg: () => encryptForOrg,
75
76
  encryptMemoryContent: () => encryptMemoryContent,
76
77
  encryptedLength: () => encryptedLength,
78
+ eventsAreOn: () => eventsAreOn,
77
79
  flushTelemetry: () => flushTelemetry,
78
80
  generateKeypair: () => generateKeypair,
79
81
  getActiveAgentMemory: () => getActiveAgentMemory,
@@ -102,6 +104,7 @@ __export(src_ts_exports, {
102
104
  pubkeyToHex: () => pubkeyToHex,
103
105
  recordCall: () => recordCall,
104
106
  recordDuration: () => recordDuration,
107
+ recordEvent: () => recordEvent,
105
108
  redactJsonStrings: () => redactJsonStrings,
106
109
  redactSecrets: () => redactSecrets,
107
110
  resolve: () => resolve,
@@ -597,6 +600,59 @@ function canonicalAllow(data) {
597
600
  return verdict === "ALLOW" || verdict === "GREEN";
598
601
  }
599
602
 
603
+ // src-ts/opentel/events.ts
604
+ var SLOW_MS = 1500;
605
+ var SUCCESS_SAMPLE_RATE = 10;
606
+ var logger = null;
607
+ var eventsEnabled = false;
608
+ var sdkVersion = "";
609
+ var eventSource = "sdk";
610
+ var hashAgentKey = null;
611
+ function eventsOptedOut() {
612
+ const flag = process.env.ATBASH_TELEMETRY_EVENTS_DISABLED?.trim().toLowerCase();
613
+ return Boolean(flag && ["1", "true", "yes", "on"].includes(flag));
614
+ }
615
+ function configureEvents(next, opts = {}) {
616
+ logger = next;
617
+ eventsEnabled = next !== null && !eventsOptedOut();
618
+ if (opts.version) sdkVersion = opts.version;
619
+ if (opts.source) eventSource = opts.source;
620
+ hashAgentKey = opts.hashAgentKey ?? null;
621
+ }
622
+ function eventsAreOn() {
623
+ return eventsEnabled && logger !== null;
624
+ }
625
+ function sampleRateFor(e) {
626
+ if (e.status === "error") return 1;
627
+ if (e.durationMs >= SLOW_MS) return 1;
628
+ return Math.random() < 1 / SUCCESS_SAMPLE_RATE ? SUCCESS_SAMPLE_RATE : 0;
629
+ }
630
+ function recordEvent(e) {
631
+ if (!eventsAreOn()) return;
632
+ const sampleRate = sampleRateFor(e);
633
+ if (sampleRate === 0) return;
634
+ try {
635
+ const attributes = {
636
+ "function.name": e.functionName,
637
+ "duration_ms": Math.round(e.durationMs),
638
+ status: e.status,
639
+ source: eventSource,
640
+ // Honeycomb reweights counts and percentiles by this. It is per-event
641
+ // because the sampling is biased by outcome and latency.
642
+ sampleRate
643
+ };
644
+ if (sdkVersion) attributes["sdk.version"] = sdkVersion;
645
+ if (e.agentPubkey && hashAgentKey) attributes["agent.hash"] = hashAgentKey(e.agentPubkey);
646
+ if (e.chain) attributes["chain"] = e.chain;
647
+ if (e.errorClass) attributes["error.class"] = e.errorClass;
648
+ if (e.errorStatus !== void 0) attributes["error.status"] = e.errorStatus;
649
+ if (e.errorPath) attributes["error.path"] = e.errorPath;
650
+ if (e.outcome) attributes["outcome"] = e.outcome;
651
+ logger.emit({ body: e.functionName, attributes });
652
+ } catch {
653
+ }
654
+ }
655
+
600
656
  // src-ts/opentel/telemetry.ts
601
657
  var import_node_fs2 = require("fs");
602
658
  var import_node_os2 = require("os");
@@ -604,7 +660,11 @@ var import_node_path2 = require("path");
604
660
  var import_exporter_metrics_otlp_http = require("@opentelemetry/exporter-metrics-otlp-http");
605
661
  var import_resources = require("@opentelemetry/resources");
606
662
  var import_sdk_metrics = require("@opentelemetry/sdk-metrics");
663
+ var import_exporter_logs_otlp_http = require("@opentelemetry/exporter-logs-otlp-http");
664
+ var import_sdk_logs = require("@opentelemetry/sdk-logs");
665
+ var import_node_crypto = require("crypto");
607
666
  var meterProvider = null;
667
+ var loggerProvider = null;
608
668
  var callCounter = null;
609
669
  var durationHistogram = null;
610
670
  var defaultSource = "sdk";
@@ -631,6 +691,41 @@ function autoInit() {
631
691
  if (isTelemetryOptedOut()) return;
632
692
  setupTelemetry({ enabled: true });
633
693
  }
694
+ function defaultAgentKeyHasher(pubkeyHex) {
695
+ return (0, import_node_crypto.createHash)("sha256").update(pubkeyHex).digest("hex");
696
+ }
697
+ var counterHasher = null;
698
+ function hashAgentKeyOrDrop(pubkeyHex) {
699
+ return counterHasher ? counterHasher(pubkeyHex) : void 0;
700
+ }
701
+ function customCollector() {
702
+ const url = process.env.ATBASH_TELEMETRY_COLLECTOR_URL?.trim();
703
+ if (!url) return null;
704
+ const loopback = /^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(:|\/|$)/i.test(url);
705
+ if (loopback && process.env.ATBASH_TELEMETRY_ALLOW_LOOPBACK !== "1") {
706
+ throw new Error(
707
+ "ATBASH_TELEMETRY_COLLECTOR_URL is a loopback address; set ATBASH_TELEMETRY_ALLOW_LOOPBACK=1 to allow it."
708
+ );
709
+ }
710
+ if (!loopback && !/^https:\/\//i.test(url)) {
711
+ throw new Error("ATBASH_TELEMETRY_COLLECTOR_URL must be https (loopback excepted).");
712
+ }
713
+ let headers = {};
714
+ const raw = process.env.ATBASH_TELEMETRY_COLLECTOR_HEADERS?.trim();
715
+ if (raw) {
716
+ try {
717
+ const parsed = JSON.parse(raw);
718
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
719
+ headers = Object.fromEntries(
720
+ Object.entries(parsed).map(([k, v]) => [k, String(v)])
721
+ );
722
+ }
723
+ } catch {
724
+ throw new Error("ATBASH_TELEMETRY_COLLECTOR_HEADERS must be a JSON object of header names to values.");
725
+ }
726
+ }
727
+ return { url: url.replace(/\/+$/, ""), headers: () => headers };
728
+ }
634
729
  function setupTelemetry(config) {
635
730
  if (!config.enabled) return;
636
731
  if (isTelemetryOptedOut()) return;
@@ -642,16 +737,20 @@ function setupTelemetry(config) {
642
737
  requestedExportIntervalMs = config.exportIntervalMs;
643
738
  }
644
739
  if (meterProvider) return;
645
- if (!config.endpoint || !config.getAuthHeaders) return;
646
- if (/^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0)(:|\/|$)/i.test(
740
+ const collector = customCollector();
741
+ if (!collector && (!config.endpoint || !config.getAuthHeaders)) return;
742
+ if (!collector && /^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0)(:|\/|$)/i.test(
647
743
  config.endpoint
648
744
  ))
649
745
  return;
650
- const proxyUrl = `${config.endpoint.replace(/\/+$/, "")}/api/telemetry`;
651
- const getAuthHeaders = config.getAuthHeaders;
746
+ const destination = collector ?? {
747
+ url: `${config.endpoint.replace(/\/+$/, "")}/api/telemetry`,
748
+ headers: () => config.getAuthHeaders()
749
+ };
750
+ const proxyUrl = destination.url;
652
751
  const exporter = new import_exporter_metrics_otlp_http.OTLPMetricExporter({
653
- url: proxyUrl,
654
- headers: async () => getAuthHeaders(),
752
+ url: collector ? `${proxyUrl}/v1/metrics` : proxyUrl,
753
+ headers: async () => destination.headers(),
655
754
  // DELTA, not the OTel default of CUMULATIVE.
656
755
  //
657
756
  // A cumulative counter reports a running total, and the backend recovers
@@ -683,6 +782,21 @@ function setupTelemetry(config) {
683
782
  description: "SDK function execution duration",
684
783
  unit: "ms"
685
784
  });
785
+ counterHasher = config.hashAgentKey ?? defaultAgentKeyHasher;
786
+ const logExporter = new import_exporter_logs_otlp_http.OTLPLogExporter({
787
+ // A real collector takes OTLP at its own signal paths; the Atbash proxy
788
+ // takes a query parameter, because it is one authenticated route.
789
+ url: collector ? `${proxyUrl}/v1/logs` : `${proxyUrl}?signal=logs`,
790
+ headers: async () => destination.headers()
791
+ });
792
+ loggerProvider = new import_sdk_logs.LoggerProvider({
793
+ resource: (0, import_resources.resourceFromAttributes)({ "service.name": "atbash-sdk" }),
794
+ processors: [new import_sdk_logs.BatchLogRecordProcessor({ exporter: logExporter })]
795
+ });
796
+ configureEvents(loggerProvider.getLogger("atbash-sdk"), {
797
+ source: config.source ?? defaultSource,
798
+ hashAgentKey: config.hashAgentKey ?? defaultAgentKeyHasher
799
+ });
686
800
  }
687
801
  function recordCall(functionName, source, agentPubkey) {
688
802
  autoInit();
@@ -690,7 +804,10 @@ function recordCall(functionName, source, agentPubkey) {
690
804
  callCounter.add(1, {
691
805
  "function.name": functionName,
692
806
  source: source ?? defaultSource,
693
- ...agentPubkey && { "agent.pubkey": agentPubkey }
807
+ // Hashed on this path too. The counters and the events export to the same
808
+ // place in the same request, so a raw key here would make hashing it on
809
+ // the event beside it pointless.
810
+ ...agentPubkey && { "agent.hash": hashAgentKeyOrDrop(agentPubkey) }
694
811
  });
695
812
  }
696
813
  function recordDuration(functionName, durationMs, status, source) {
@@ -702,15 +819,16 @@ function recordDuration(functionName, durationMs, status, source) {
702
819
  });
703
820
  }
704
821
  async function flushTelemetry() {
705
- if (!meterProvider) return;
706
- await meterProvider.forceFlush();
822
+ await Promise.all([meterProvider?.forceFlush(), loggerProvider?.forceFlush()]);
707
823
  }
708
824
  async function shutdownTelemetry() {
709
- if (!meterProvider) return;
710
- await meterProvider.shutdown();
825
+ await Promise.all([meterProvider?.shutdown(), loggerProvider?.shutdown()]);
711
826
  meterProvider = null;
827
+ loggerProvider = null;
712
828
  callCounter = null;
713
829
  durationHistogram = null;
830
+ counterHasher = null;
831
+ configureEvents(null);
714
832
  defaultSource = "sdk";
715
833
  sourceExplicitlySet = false;
716
834
  requestedExportIntervalMs = void 0;
@@ -812,6 +930,13 @@ function resolveConstructorChain(options) {
812
930
  }
813
931
  return chainForNetwork(options.network ?? forcedChainNetwork() ?? "private");
814
932
  }
933
+ function errorDetail(err) {
934
+ if (!(err instanceof AtbashAPIError)) return {};
935
+ return {
936
+ errorStatus: err.status,
937
+ ...err.path ? { errorPath: err.path } : {}
938
+ };
939
+ }
815
940
  var Atbash = class _Atbash {
816
941
  auth;
817
942
  endpoint;
@@ -1022,7 +1147,7 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
1022
1147
  *
1023
1148
  * @param logger - The host logger, when one was supplied.
1024
1149
  */
1025
- static warnOnStrandedKey(logger) {
1150
+ static warnOnStrandedKey(logger2) {
1026
1151
  const stranded = strandedAgentKey();
1027
1152
  if (!stranded) return;
1028
1153
  let identity;
@@ -1031,7 +1156,7 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
1031
1156
  } catch {
1032
1157
  identity = "(unreadable)";
1033
1158
  }
1034
- logger?.warn?.(
1159
+ logger2?.warn?.(
1035
1160
  `[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.`
1036
1161
  );
1037
1162
  }
@@ -1790,10 +1915,28 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
1790
1915
  recordCall(name, void 0, agentPubkey);
1791
1916
  try {
1792
1917
  const result = await fn();
1793
- recordDuration(name, performance.now() - start, "success");
1918
+ const durationMs = performance.now() - start;
1919
+ recordDuration(name, durationMs, "success");
1920
+ recordEvent({
1921
+ functionName: name,
1922
+ durationMs,
1923
+ status: "success",
1924
+ agentPubkey,
1925
+ chain: this.blockchainRid
1926
+ });
1794
1927
  return result;
1795
1928
  } catch (err) {
1796
- recordDuration(name, performance.now() - start, "error");
1929
+ const durationMs = performance.now() - start;
1930
+ recordDuration(name, durationMs, "error");
1931
+ recordEvent({
1932
+ functionName: name,
1933
+ durationMs,
1934
+ status: "error",
1935
+ agentPubkey,
1936
+ chain: this.blockchainRid,
1937
+ errorClass: err instanceof Error ? err.constructor.name : typeof err,
1938
+ ...errorDetail(err)
1939
+ });
1797
1940
  throw err;
1798
1941
  }
1799
1942
  }
@@ -2286,6 +2429,47 @@ async function scanMemoryBatch(entries, auth, opts) {
2286
2429
  return results;
2287
2430
  }
2288
2431
 
2432
+ // src-ts/memory/telemetry.ts
2433
+ function metricName(action) {
2434
+ return `memory.${action}`;
2435
+ }
2436
+ function recordMemoryCall(action, startedAt, agentPubkey, status, err) {
2437
+ const name = metricName(action);
2438
+ const durationMs = performance.now() - startedAt;
2439
+ recordCall(name, void 0, agentPubkey);
2440
+ recordDuration(name, durationMs, status);
2441
+ recordEvent({
2442
+ functionName: name,
2443
+ durationMs,
2444
+ status,
2445
+ agentPubkey,
2446
+ ...err !== void 0 && {
2447
+ errorClass: err instanceof Error ? err.constructor.name : typeof err,
2448
+ // The chain transport is where the failures are, so the status and the
2449
+ // route are the whole of what makes one diagnosable.
2450
+ ...err instanceof AtbashAPIError && {
2451
+ errorStatus: err.status,
2452
+ ...err.path ? { errorPath: err.path } : {}
2453
+ }
2454
+ }
2455
+ });
2456
+ }
2457
+ function recordMemoryGuard(verdict, committed, blocked, startedAt, agentPubkey) {
2458
+ const durationMs = performance.now() - startedAt;
2459
+ recordCall("memory.guard", void 0, agentPubkey);
2460
+ recordDuration("memory.guard", durationMs, blocked ? "error" : "success");
2461
+ recordEvent({
2462
+ functionName: "memory.guard",
2463
+ durationMs,
2464
+ // A block is the outcome worth keeping every one of; the sampler keeps
2465
+ // errors whole, and a refused write is an error from the agent's side.
2466
+ status: blocked ? "error" : "success",
2467
+ agentPubkey,
2468
+ errorClass: blocked ? `memory-blocked:${verdict}` : void 0,
2469
+ outcome: `${verdict}/${committed ? "committed" : "uncommitted"}`
2470
+ });
2471
+ }
2472
+
2289
2473
  // src-ts/memory/transport.ts
2290
2474
  var DEFAULT_TIMEOUT_MS = 12e4;
2291
2475
  function transport(opts) {
@@ -2298,24 +2482,39 @@ async function failure(action, resp) {
2298
2482
  );
2299
2483
  }
2300
2484
  async function memoryQuery(action, auth, blockchainRid, opts, filePath, extra = {}) {
2485
+ const start = performance.now();
2301
2486
  const params = new URLSearchParams({ action, agent: auth.pubkey });
2302
2487
  if (filePath !== null) params.set("file_path", filePath);
2303
2488
  for (const [key, value] of Object.entries(extra)) params.set(key, String(value));
2304
- const resp = await transport(opts).get(
2305
- `/api/risk-engine?${params.toString()}`,
2306
- void 0,
2307
- agentAuthHeaders(auth, blockchainRid)
2308
- );
2309
- if (resp.status !== 200) throw await failure(action, resp);
2310
- return resp.json();
2489
+ try {
2490
+ const resp = await transport(opts).get(
2491
+ `/api/risk-engine?${params.toString()}`,
2492
+ void 0,
2493
+ agentAuthHeaders(auth, blockchainRid)
2494
+ );
2495
+ if (resp.status !== 200) throw await failure(action, resp);
2496
+ const body = await resp.json();
2497
+ recordMemoryCall(action, start, auth.pubkey, "success");
2498
+ return body;
2499
+ } catch (err) {
2500
+ recordMemoryCall(action, start, auth.pubkey, "error", err);
2501
+ throw err;
2502
+ }
2311
2503
  }
2312
2504
  async function memorySubmit(action, auth, opts, signedField, signedHex) {
2313
- const resp = await transport(opts).post("/api/risk-engine", {
2314
- action,
2315
- agentPubkey: auth.pubkey,
2316
- [signedField]: signedHex
2317
- });
2318
- if (resp.status !== 200) throw await failure(action, resp);
2505
+ const start = performance.now();
2506
+ try {
2507
+ const resp = await transport(opts).post("/api/risk-engine", {
2508
+ action,
2509
+ agentPubkey: auth.pubkey,
2510
+ [signedField]: signedHex
2511
+ });
2512
+ if (resp.status !== 200) throw await failure(action, resp);
2513
+ recordMemoryCall(action, start, auth.pubkey, "success");
2514
+ } catch (err) {
2515
+ recordMemoryCall(action, start, auth.pubkey, "error", err);
2516
+ throw err;
2517
+ }
2319
2518
  }
2320
2519
 
2321
2520
  // src-ts/memory/chain.ts
@@ -2569,8 +2768,8 @@ function classifyMemoryWrite(event, ctx, opts = {}) {
2569
2768
  var import_node_fs4 = require("fs");
2570
2769
  var import_node_os4 = __toESM(require("os"));
2571
2770
  var import_node_path4 = __toESM(require("path"));
2572
- function emitDebugProbe(event, ctx, memEntry, logger) {
2573
- if (!logger?.info) return;
2771
+ function emitDebugProbe(event, ctx, memEntry, logger2) {
2772
+ if (!logger2?.info) return;
2574
2773
  const ev = event ?? {};
2575
2774
  const c = ctx ?? {};
2576
2775
  const argsCandidate = ev.params ?? c.params ?? ev.args ?? c.args ?? ev.arguments ?? c.arguments;
@@ -2580,7 +2779,7 @@ function emitDebugProbe(event, ctx, memEntry, logger) {
2580
2779
  const editsArr = Array.isArray(argsObj.edits) ? argsObj.edits : null;
2581
2780
  const firstEditKeys = editsArr && editsArr[0] && typeof editsArr[0] === "object" ? Object.keys(editsArr[0]).slice(0, 10) : null;
2582
2781
  const tool = ev.toolName ?? c.tool?.name ?? c.toolName ?? c.name ?? "(none)";
2583
- logger.info("[atbash][probe] before_tool_call", {
2782
+ logger2.info("[atbash][probe] before_tool_call", {
2584
2783
  toolName: tool,
2585
2784
  eventKeys: Object.keys(ev).slice(0, 20),
2586
2785
  ctxKeys: Object.keys(c).slice(0, 20),
@@ -2608,6 +2807,20 @@ async function resultingDocument(memEntry, event, ctx) {
2608
2807
  return native.applyMemoryEdits(current, edits);
2609
2808
  }
2610
2809
  async function guardMemoryWrite(input) {
2810
+ const start = performance.now();
2811
+ const result = await guardMemoryWriteInner(input);
2812
+ if (result.handled) {
2813
+ recordMemoryGuard(
2814
+ result.scanResult?.verdict ?? "unscanned",
2815
+ result.committed === true,
2816
+ result.decision?.block === true,
2817
+ start,
2818
+ input.auth.pubkey
2819
+ );
2820
+ }
2821
+ return result;
2822
+ }
2823
+ async function guardMemoryWriteInner(input) {
2611
2824
  const {
2612
2825
  event,
2613
2826
  ctx,
@@ -2621,7 +2834,7 @@ async function guardMemoryWrite(input) {
2621
2834
  toolNames,
2622
2835
  enforce = true,
2623
2836
  debug = false,
2624
- logger,
2837
+ logger: logger2,
2625
2838
  agentHomeDirs,
2626
2839
  memoryRoot
2627
2840
  } = input;
@@ -2630,7 +2843,7 @@ async function guardMemoryWrite(input) {
2630
2843
  memEntry = classifyMemoryWrite(event, ctx, { patterns, toolNames });
2631
2844
  } catch (err) {
2632
2845
  const why = err instanceof Error ? err.message : String(err);
2633
- logger?.warn?.("[atbash] memory classifier refused this tool call's input", { reason: why });
2846
+ logger2?.warn?.("[atbash] memory classifier refused this tool call's input", { reason: why });
2634
2847
  if (!enforce) return { handled: false };
2635
2848
  return {
2636
2849
  handled: true,
@@ -2641,14 +2854,14 @@ async function guardMemoryWrite(input) {
2641
2854
  }
2642
2855
  };
2643
2856
  }
2644
- if (debug) emitDebugProbe(event, ctx, memEntry, logger);
2857
+ if (debug) emitDebugProbe(event, ctx, memEntry, logger2);
2645
2858
  if (!memEntry) return { handled: false };
2646
2859
  let document;
2647
2860
  try {
2648
2861
  document = await resultingDocument(memEntry, event, ctx);
2649
2862
  } catch (err) {
2650
2863
  const reason = err instanceof Error ? err.message : String(err);
2651
- logger?.warn?.("[atbash] memory edit could not be applied", { path: memEntry.key, reason });
2864
+ logger2?.warn?.("[atbash] memory edit could not be applied", { path: memEntry.key, reason });
2652
2865
  return {
2653
2866
  handled: true,
2654
2867
  decision: enforce ? { allow: false, block: true, reason: `Memory edit refused: ${reason}` } : { allow: true, reason: `Memory edit refused: ${reason}` },
@@ -2666,7 +2879,7 @@ async function guardMemoryWrite(input) {
2666
2879
  });
2667
2880
  } catch (err) {
2668
2881
  const reason = err instanceof Error ? err.message : String(err);
2669
- logger?.warn?.("[atbash] memory scan failed", {
2882
+ logger2?.warn?.("[atbash] memory scan failed", {
2670
2883
  path: memEntry.key,
2671
2884
  reason
2672
2885
  });
@@ -2676,7 +2889,7 @@ async function guardMemoryWrite(input) {
2676
2889
  };
2677
2890
  }
2678
2891
  if (scanResult.verdict === "red") {
2679
- logger?.warn?.("[atbash] memory BLOCK", {
2892
+ logger2?.warn?.("[atbash] memory BLOCK", {
2680
2893
  path: memEntry.key,
2681
2894
  reason: scanResult.reason
2682
2895
  });
@@ -2698,7 +2911,7 @@ async function guardMemoryWrite(input) {
2698
2911
  }
2699
2912
  const filePath = memorySlotFor(memEntry.key, memoryRoot, agentHomeDirs);
2700
2913
  if (filePath === null) {
2701
- logger?.info?.(
2914
+ logger2?.info?.(
2702
2915
  `[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.`,
2703
2916
  { path: memEntry.key, verdict: scanResult.verdict, score: scanResult.score }
2704
2917
  );
@@ -2720,7 +2933,7 @@ async function guardMemoryWrite(input) {
2720
2933
  });
2721
2934
  } catch (err) {
2722
2935
  const reason = err instanceof Error ? err.message : String(err);
2723
- logger?.warn?.("[atbash] memory commit to chain failed", {
2936
+ logger2?.warn?.("[atbash] memory commit to chain failed", {
2724
2937
  path: memEntry.key,
2725
2938
  filePath,
2726
2939
  reason
@@ -2732,7 +2945,7 @@ async function guardMemoryWrite(input) {
2732
2945
  committed: false
2733
2946
  };
2734
2947
  }
2735
- logger?.info?.(
2948
+ logger2?.info?.(
2736
2949
  scanResult.verdict === "yellow" ? "[atbash] memory ALLOW (yellow, low score)" : "[atbash] memory ALLOW",
2737
2950
  {
2738
2951
  path: memEntry.key,
@@ -3645,6 +3858,7 @@ function diffMemorySnapshots(before, after) {
3645
3858
  classifyMemoryWrite,
3646
3859
  columnAad,
3647
3860
  commitMemoryVersion,
3861
+ configureEvents,
3648
3862
  containsEvasionCharacters,
3649
3863
  containsSecret,
3650
3864
  createFileLogger,
@@ -3660,6 +3874,7 @@ function diffMemorySnapshots(before, after) {
3660
3874
  encryptForOrg,
3661
3875
  encryptMemoryContent,
3662
3876
  encryptedLength,
3877
+ eventsAreOn,
3663
3878
  flushTelemetry,
3664
3879
  generateKeypair,
3665
3880
  getActiveAgentMemory,
@@ -3688,6 +3903,7 @@ function diffMemorySnapshots(before, after) {
3688
3903
  pubkeyToHex,
3689
3904
  recordCall,
3690
3905
  recordDuration,
3906
+ recordEvent,
3691
3907
  redactJsonStrings,
3692
3908
  redactSecrets,
3693
3909
  resolve,