@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.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
- if (!config.endpoint || !config.getAuthHeaders) return;
528
- if (/^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0)(:|\/|$)/i.test(
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 proxyUrl = `${config.endpoint.replace(/\/+$/, "")}/api/telemetry`;
533
- const getAuthHeaders = config.getAuthHeaders;
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 () => getAuthHeaders(),
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
- ...agentPubkey && { "agent.pubkey": agentPubkey }
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
- if (!meterProvider) return;
588
- await meterProvider.forceFlush();
701
+ await Promise.all([meterProvider?.forceFlush(), loggerProvider?.forceFlush()]);
589
702
  }
590
703
  async function shutdownTelemetry() {
591
- if (!meterProvider) return;
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(logger) {
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
- logger?.warn?.(
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
- recordDuration(name, performance.now() - start, "success");
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
- recordDuration(name, performance.now() - start, "error");
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
- const resp = await transport(opts).get(
2193
- `/api/risk-engine?${params.toString()}`,
2194
- void 0,
2195
- agentAuthHeaders(auth, blockchainRid)
2196
- );
2197
- if (resp.status !== 200) throw await failure(action, resp);
2198
- return resp.json();
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 resp = await transport(opts).post("/api/risk-engine", {
2202
- action,
2203
- agentPubkey: auth.pubkey,
2204
- [signedField]: signedHex
2205
- });
2206
- if (resp.status !== 200) throw await failure(action, resp);
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, logger) {
2461
- if (!logger?.info) return;
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
- logger.info("[atbash][probe] before_tool_call", {
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
- logger?.warn?.("[atbash] memory classifier refused this tool call's input", { reason: why });
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, logger);
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
- logger?.warn?.("[atbash] memory edit could not be applied", { path: memEntry.key, reason });
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
- logger?.warn?.("[atbash] memory scan failed", {
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
- logger?.warn?.("[atbash] memory BLOCK", {
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
- logger?.info?.(
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
- logger?.warn?.("[atbash] memory commit to chain failed", {
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
- logger?.info?.(
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.18.0-dev.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.18.0-dev.0",
96
- "@atbash/sdk-linux-arm64-gnu": "0.18.0-dev.0",
97
- "@atbash/sdk-linux-x64-musl": "0.18.0-dev.0",
98
- "@atbash/sdk-darwin-arm64": "0.18.0-dev.0",
99
- "@atbash/sdk-win32-x64-msvc": "0.18.0-dev.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
  }