agentid-sdk 0.1.13 → 0.1.15

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.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AgentID, a as AgentIDCallbackHandler, G as GuardParams, b as GuardResponse, L as LogParams, P as PreparedInput, R as RequestOptions } from './langchain-CUyC7jmr.mjs';
1
+ export { A as AgentID, a as AgentIDCallbackHandler, G as GuardParams, b as GuardResponse, L as LogParams, P as PreparedInput, R as RequestOptions } from './langchain-CmUK7sna.mjs';
2
2
 
3
3
  type PIIMapping = Record<string, string>;
4
4
  declare class PIIManager {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AgentID, a as AgentIDCallbackHandler, G as GuardParams, b as GuardResponse, L as LogParams, P as PreparedInput, R as RequestOptions } from './langchain-CUyC7jmr.js';
1
+ export { A as AgentID, a as AgentIDCallbackHandler, G as GuardParams, b as GuardResponse, L as LogParams, P as PreparedInput, R as RequestOptions } from './langchain-CmUK7sna.js';
2
2
 
3
3
  type PIIMapping = Record<string, string>;
4
4
  declare class PIIManager {
package/dist/index.js CHANGED
@@ -1809,6 +1809,10 @@ var MIN_GUARD_TIMEOUT_MS = 500;
1809
1809
  var MAX_GUARD_TIMEOUT_MS = 15e3;
1810
1810
  var GUARD_MAX_ATTEMPTS = 3;
1811
1811
  var GUARD_RETRY_DELAYS_MS = [250, 500];
1812
+ var INGEST_MAX_ATTEMPTS = 3;
1813
+ var INGEST_RETRY_DELAYS_MS = [250, 500];
1814
+ var GUARD_VERDICT_CACHE_TTL_MS = 15e3;
1815
+ var MAX_INGEST_TEXT_CHARS = 32e3;
1812
1816
  function normalizeBaseUrl3(baseUrl) {
1813
1817
  return baseUrl.replace(/\/+$/, "");
1814
1818
  }
@@ -1882,25 +1886,41 @@ function isUuidLike(value) {
1882
1886
  value
1883
1887
  );
1884
1888
  }
1889
+ function createPseudoUuidV4() {
1890
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (token) => {
1891
+ const rand = Math.floor(Math.random() * 16);
1892
+ const value = token === "x" ? rand : rand & 3 | 8;
1893
+ return value.toString(16);
1894
+ });
1895
+ }
1896
+ function sanitizeIngestText(value) {
1897
+ const text = typeof value === "string" ? value : String(value ?? "");
1898
+ return text.slice(0, MAX_INGEST_TEXT_CHARS);
1899
+ }
1885
1900
  function createEventId(seed) {
1886
1901
  if (isUuidLike(seed)) return seed;
1887
1902
  if (typeof globalThis.crypto?.randomUUID === "function") {
1888
1903
  return globalThis.crypto.randomUUID();
1889
1904
  }
1890
- return `evt_${Date.now()}_${Math.random().toString(36).slice(2)}`;
1905
+ return createPseudoUuidV4();
1891
1906
  }
1892
1907
  function createCorrelationId(seed) {
1893
1908
  if (isUuidLike(seed)) return seed;
1894
1909
  if (typeof globalThis.crypto?.randomUUID === "function") {
1895
1910
  return globalThis.crypto.randomUUID();
1896
1911
  }
1897
- return `cid_${Date.now()}_${Math.random().toString(36).slice(2)}`;
1912
+ return createPseudoUuidV4();
1898
1913
  }
1899
1914
  async function waitForRetry(attemptIndex) {
1900
1915
  const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
1901
1916
  if (!delay) return;
1902
1917
  await new Promise((resolve) => setTimeout(resolve, delay));
1903
1918
  }
1919
+ async function waitForIngestRetry(attemptIndex) {
1920
+ const delay = INGEST_RETRY_DELAYS_MS[attemptIndex];
1921
+ if (!delay) return;
1922
+ await new Promise((resolve) => setTimeout(resolve, delay));
1923
+ }
1904
1924
  async function safeReadJson2(response) {
1905
1925
  try {
1906
1926
  return await response.json();
@@ -1976,6 +1996,7 @@ var AgentID = class {
1976
1996
  constructor(config) {
1977
1997
  this.injectionScanner = getInjectionScanner();
1978
1998
  this.requestClientEventIds = /* @__PURE__ */ new WeakMap();
1999
+ this.recentGuardVerdicts = /* @__PURE__ */ new Map();
1979
2000
  this.apiKey = config.apiKey.trim();
1980
2001
  this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
1981
2002
  this.piiMasking = Boolean(config.piiMasking);
@@ -2024,6 +2045,40 @@ var AgentID = class {
2024
2045
  this.requestClientEventIds.set(requestBody, generated);
2025
2046
  return generated;
2026
2047
  }
2048
+ buildGuardCacheKey(params) {
2049
+ if (!params.system_id || !params.input) {
2050
+ return null;
2051
+ }
2052
+ const userId = params.user_id?.trim() ?? "";
2053
+ const normalizedInput = params.input.slice(0, 2048);
2054
+ return `${params.system_id}|${userId}|${normalizedInput.length}|${normalizedInput}`;
2055
+ }
2056
+ readCachedGuardVerdict(cacheKey) {
2057
+ if (!cacheKey) return null;
2058
+ const cached = this.recentGuardVerdicts.get(cacheKey);
2059
+ if (!cached) return null;
2060
+ if (Date.now() > cached.expiresAt) {
2061
+ this.recentGuardVerdicts.delete(cacheKey);
2062
+ return null;
2063
+ }
2064
+ return cached.verdict;
2065
+ }
2066
+ cacheGuardVerdict(cacheKey, verdict) {
2067
+ if (!cacheKey || !verdict.allowed) {
2068
+ return;
2069
+ }
2070
+ this.recentGuardVerdicts.set(cacheKey, {
2071
+ verdict,
2072
+ expiresAt: Date.now() + GUARD_VERDICT_CACHE_TTL_MS
2073
+ });
2074
+ if (this.recentGuardVerdicts.size > 100) {
2075
+ for (const [key, value] of this.recentGuardVerdicts.entries()) {
2076
+ if (Date.now() > value.expiresAt) {
2077
+ this.recentGuardVerdicts.delete(key);
2078
+ }
2079
+ }
2080
+ }
2081
+ }
2027
2082
  async getCapabilityConfig(force = false, options) {
2028
2083
  const effectiveApiKey = this.resolveApiKey(options?.apiKey);
2029
2084
  return ensureCapabilityConfig({
@@ -2181,6 +2236,11 @@ var AgentID = class {
2181
2236
  ...params,
2182
2237
  client_capabilities: params.client_capabilities ?? this.buildClientCapabilities()
2183
2238
  };
2239
+ const guardCacheKey = this.buildGuardCacheKey(payload);
2240
+ const cachedVerdict = this.readCachedGuardVerdict(guardCacheKey);
2241
+ if (cachedVerdict) {
2242
+ return cachedVerdict;
2243
+ }
2184
2244
  const correlationId = createCorrelationId(payload.client_event_id);
2185
2245
  let lastStatusCode = null;
2186
2246
  let lastAbort = false;
@@ -2227,6 +2287,7 @@ var AgentID = class {
2227
2287
  });
2228
2288
  return { allowed: true, reason: "system_failure_fail_open" };
2229
2289
  }
2290
+ this.cacheGuardVerdict(guardCacheKey, verdict);
2230
2291
  return verdict;
2231
2292
  }
2232
2293
  if (!res.ok) {
@@ -2300,6 +2361,62 @@ var AgentID = class {
2300
2361
  }
2301
2362
  return { allowed: true, reason: "guard_unreachable" };
2302
2363
  }
2364
+ async sendIngest(params, options) {
2365
+ const effectiveApiKey = this.resolveApiKey(options?.apiKey);
2366
+ const eventId = createEventId(params.event_id);
2367
+ const timestamp = params.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
2368
+ const metadata = {
2369
+ ...params.metadata ?? {}
2370
+ };
2371
+ if (!Object.prototype.hasOwnProperty.call(metadata, "agentid_base_url")) {
2372
+ metadata.agentid_base_url = this.baseUrl;
2373
+ }
2374
+ void this.getCapabilityConfig(false, { apiKey: effectiveApiKey }).catch(() => void 0);
2375
+ const payload = {
2376
+ ...params,
2377
+ event_id: eventId,
2378
+ timestamp,
2379
+ input: sanitizeIngestText(params.input),
2380
+ output: sanitizeIngestText(params.output),
2381
+ metadata,
2382
+ client_capabilities: params.client_capabilities ?? this.buildClientCapabilities()
2383
+ };
2384
+ for (let attempt = 0; attempt < INGEST_MAX_ATTEMPTS; attempt += 1) {
2385
+ try {
2386
+ const response = await fetch(`${this.baseUrl}/ingest`, {
2387
+ method: "POST",
2388
+ keepalive: true,
2389
+ headers: {
2390
+ "Content-Type": "application/json",
2391
+ "x-agentid-api-key": effectiveApiKey,
2392
+ "X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER2
2393
+ },
2394
+ body: JSON.stringify(payload)
2395
+ });
2396
+ const responseBody = await safeReadJson2(response);
2397
+ if (response.ok) {
2398
+ return { ok: true, status: response.status, reason: null };
2399
+ }
2400
+ const reason = responseBody && typeof responseBody === "object" && typeof responseBody.reason === "string" ? responseBody.reason ?? null : null;
2401
+ if (response.status === 409 && reason === "replay_detected") {
2402
+ return { ok: true, status: response.status, reason };
2403
+ }
2404
+ const retryable = response.status >= 500 || response.status === 429;
2405
+ if (retryable && attempt < INGEST_MAX_ATTEMPTS - 1) {
2406
+ await waitForIngestRetry(attempt);
2407
+ continue;
2408
+ }
2409
+ return { ok: false, status: response.status, reason };
2410
+ } catch {
2411
+ if (attempt < INGEST_MAX_ATTEMPTS - 1) {
2412
+ await waitForIngestRetry(attempt);
2413
+ continue;
2414
+ }
2415
+ return { ok: false, status: null, reason: "network_error" };
2416
+ }
2417
+ }
2418
+ return { ok: false, status: null, reason: "unknown_ingest_failure" };
2419
+ }
2303
2420
  extractStreamChunkText(chunk) {
2304
2421
  if (typeof chunk === "string") {
2305
2422
  return chunk;
@@ -2401,35 +2518,11 @@ var AgentID = class {
2401
2518
  log(params, options) {
2402
2519
  queueMicrotask(() => {
2403
2520
  void (async () => {
2404
- try {
2405
- const effectiveApiKey = this.resolveApiKey(options?.apiKey);
2406
- const eventId = params.event_id ?? createEventId();
2407
- const timestamp = params.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
2408
- void this.getCapabilityConfig(false, { apiKey: effectiveApiKey }).catch(() => void 0);
2409
- const metadata = {
2410
- ...params.metadata ?? {}
2411
- };
2412
- if (!Object.prototype.hasOwnProperty.call(metadata, "agentid_base_url")) {
2413
- metadata.agentid_base_url = this.baseUrl;
2414
- }
2415
- await fetch(`${this.baseUrl}/ingest`, {
2416
- method: "POST",
2417
- keepalive: true,
2418
- headers: {
2419
- "Content-Type": "application/json",
2420
- "x-agentid-api-key": effectiveApiKey,
2421
- "X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER2
2422
- },
2423
- body: JSON.stringify({
2424
- ...params,
2425
- event_id: eventId,
2426
- timestamp,
2427
- metadata,
2428
- client_capabilities: params.client_capabilities ?? this.buildClientCapabilities()
2429
- })
2430
- });
2431
- } catch (error) {
2432
- console.error("[AgentID] Log failed:", error);
2521
+ const result = await this.sendIngest(params, options);
2522
+ if (!result.ok) {
2523
+ console.warn(
2524
+ `[AgentID] Ingest telemetry failed (status=${result.status ?? "network"}, reason=${result.reason ?? "unknown"}).`
2525
+ );
2433
2526
  }
2434
2527
  })();
2435
2528
  });
@@ -2543,6 +2636,8 @@ var AgentID = class {
2543
2636
  `AgentID: Security Blocked (${verdict.reason ?? "guard_denied"})`
2544
2637
  );
2545
2638
  }
2639
+ const canonicalClientEventId = typeof verdict.client_event_id === "string" && isUuidLike(verdict.client_event_id) ? verdict.client_event_id : clientEventId;
2640
+ const guardEventId = typeof verdict.guard_event_id === "string" && verdict.guard_event_id.length > 0 ? verdict.guard_event_id : null;
2546
2641
  const isShadowMode = verdict.shadow_mode === true;
2547
2642
  const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
2548
2643
  if (transformedInput !== maskedText) {
@@ -2565,10 +2660,10 @@ var AgentID = class {
2565
2660
  })()
2566
2661
  );
2567
2662
  if (maskedText && wrappedCompletion.mode === "stream") {
2568
- void wrappedCompletion.done.then((result) => {
2663
+ void wrappedCompletion.done.then(async (result) => {
2569
2664
  const outputForLog = isShadowMode ? result.rawOutput : result.transformedOutput;
2570
- this.log({
2571
- event_id: clientEventId,
2665
+ const ingestResult = await this.sendIngest({
2666
+ event_id: canonicalClientEventId,
2572
2667
  system_id: systemId,
2573
2668
  user_id: options.user_id,
2574
2669
  input: maskedText,
@@ -2576,6 +2671,7 @@ var AgentID = class {
2576
2671
  model: adapter.getModelName(maskedReq),
2577
2672
  usage: void 0,
2578
2673
  latency: void 0,
2674
+ event_type: "complete",
2579
2675
  metadata: {
2580
2676
  transformed_input: maskedText,
2581
2677
  transformed_output: result.transformedOutput,
@@ -2583,10 +2679,17 @@ var AgentID = class {
2583
2679
  shadow_mode: isShadowMode,
2584
2680
  simulated_decision: verdict.simulated_decision ?? null,
2585
2681
  simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
2586
- response_streamed: true
2682
+ response_streamed: true,
2683
+ guard_event_id: guardEventId,
2684
+ client_event_id: canonicalClientEventId
2587
2685
  },
2588
2686
  client_capabilities: this.buildClientCapabilities("openai", false)
2589
2687
  }, requestOptions);
2688
+ if (!ingestResult.ok) {
2689
+ console.warn(
2690
+ `[AgentID] Stream ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
2691
+ );
2692
+ }
2590
2693
  }).catch((error) => {
2591
2694
  console.error("[AgentID] Stream completion wrapping failed:", error);
2592
2695
  });
@@ -2602,8 +2705,8 @@ var AgentID = class {
2602
2705
  const model = adapter.getModelName(maskedReq, res);
2603
2706
  const usage = adapter.getTokenUsage(res);
2604
2707
  const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
2605
- this.log({
2606
- event_id: clientEventId,
2708
+ const ingestResult = await this.sendIngest({
2709
+ event_id: canonicalClientEventId,
2607
2710
  system_id: systemId,
2608
2711
  user_id: options.user_id,
2609
2712
  input: maskedText,
@@ -2611,6 +2714,7 @@ var AgentID = class {
2611
2714
  model,
2612
2715
  usage,
2613
2716
  latency,
2717
+ event_type: "complete",
2614
2718
  metadata: {
2615
2719
  transformed_input: maskedText,
2616
2720
  transformed_output: wrappedCompletion.transformedOutput,
@@ -2618,10 +2722,17 @@ var AgentID = class {
2618
2722
  shadow_mode: isShadowMode,
2619
2723
  simulated_decision: verdict.simulated_decision ?? null,
2620
2724
  simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
2621
- response_streamed: false
2725
+ response_streamed: false,
2726
+ guard_event_id: guardEventId,
2727
+ client_event_id: canonicalClientEventId
2622
2728
  },
2623
2729
  client_capabilities: this.buildClientCapabilities("openai", false)
2624
2730
  }, requestOptions);
2731
+ if (!ingestResult.ok) {
2732
+ console.warn(
2733
+ `[AgentID] Ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
2734
+ );
2735
+ }
2625
2736
  }
2626
2737
  if (!capabilityConfig.block_pii_leakage && this.piiMasking && shouldDeanonymize) {
2627
2738
  const deanon = this.pii.deanonymize(adapter.extractOutput(res), mapping);
package/dist/index.mjs CHANGED
@@ -1771,6 +1771,10 @@ var MIN_GUARD_TIMEOUT_MS = 500;
1771
1771
  var MAX_GUARD_TIMEOUT_MS = 15e3;
1772
1772
  var GUARD_MAX_ATTEMPTS = 3;
1773
1773
  var GUARD_RETRY_DELAYS_MS = [250, 500];
1774
+ var INGEST_MAX_ATTEMPTS = 3;
1775
+ var INGEST_RETRY_DELAYS_MS = [250, 500];
1776
+ var GUARD_VERDICT_CACHE_TTL_MS = 15e3;
1777
+ var MAX_INGEST_TEXT_CHARS = 32e3;
1774
1778
  function normalizeBaseUrl3(baseUrl) {
1775
1779
  return baseUrl.replace(/\/+$/, "");
1776
1780
  }
@@ -1844,25 +1848,41 @@ function isUuidLike(value) {
1844
1848
  value
1845
1849
  );
1846
1850
  }
1851
+ function createPseudoUuidV4() {
1852
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (token) => {
1853
+ const rand = Math.floor(Math.random() * 16);
1854
+ const value = token === "x" ? rand : rand & 3 | 8;
1855
+ return value.toString(16);
1856
+ });
1857
+ }
1858
+ function sanitizeIngestText(value) {
1859
+ const text = typeof value === "string" ? value : String(value ?? "");
1860
+ return text.slice(0, MAX_INGEST_TEXT_CHARS);
1861
+ }
1847
1862
  function createEventId(seed) {
1848
1863
  if (isUuidLike(seed)) return seed;
1849
1864
  if (typeof globalThis.crypto?.randomUUID === "function") {
1850
1865
  return globalThis.crypto.randomUUID();
1851
1866
  }
1852
- return `evt_${Date.now()}_${Math.random().toString(36).slice(2)}`;
1867
+ return createPseudoUuidV4();
1853
1868
  }
1854
1869
  function createCorrelationId(seed) {
1855
1870
  if (isUuidLike(seed)) return seed;
1856
1871
  if (typeof globalThis.crypto?.randomUUID === "function") {
1857
1872
  return globalThis.crypto.randomUUID();
1858
1873
  }
1859
- return `cid_${Date.now()}_${Math.random().toString(36).slice(2)}`;
1874
+ return createPseudoUuidV4();
1860
1875
  }
1861
1876
  async function waitForRetry(attemptIndex) {
1862
1877
  const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
1863
1878
  if (!delay) return;
1864
1879
  await new Promise((resolve) => setTimeout(resolve, delay));
1865
1880
  }
1881
+ async function waitForIngestRetry(attemptIndex) {
1882
+ const delay = INGEST_RETRY_DELAYS_MS[attemptIndex];
1883
+ if (!delay) return;
1884
+ await new Promise((resolve) => setTimeout(resolve, delay));
1885
+ }
1866
1886
  async function safeReadJson2(response) {
1867
1887
  try {
1868
1888
  return await response.json();
@@ -1938,6 +1958,7 @@ var AgentID = class {
1938
1958
  constructor(config) {
1939
1959
  this.injectionScanner = getInjectionScanner();
1940
1960
  this.requestClientEventIds = /* @__PURE__ */ new WeakMap();
1961
+ this.recentGuardVerdicts = /* @__PURE__ */ new Map();
1941
1962
  this.apiKey = config.apiKey.trim();
1942
1963
  this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
1943
1964
  this.piiMasking = Boolean(config.piiMasking);
@@ -1986,6 +2007,40 @@ var AgentID = class {
1986
2007
  this.requestClientEventIds.set(requestBody, generated);
1987
2008
  return generated;
1988
2009
  }
2010
+ buildGuardCacheKey(params) {
2011
+ if (!params.system_id || !params.input) {
2012
+ return null;
2013
+ }
2014
+ const userId = params.user_id?.trim() ?? "";
2015
+ const normalizedInput = params.input.slice(0, 2048);
2016
+ return `${params.system_id}|${userId}|${normalizedInput.length}|${normalizedInput}`;
2017
+ }
2018
+ readCachedGuardVerdict(cacheKey) {
2019
+ if (!cacheKey) return null;
2020
+ const cached = this.recentGuardVerdicts.get(cacheKey);
2021
+ if (!cached) return null;
2022
+ if (Date.now() > cached.expiresAt) {
2023
+ this.recentGuardVerdicts.delete(cacheKey);
2024
+ return null;
2025
+ }
2026
+ return cached.verdict;
2027
+ }
2028
+ cacheGuardVerdict(cacheKey, verdict) {
2029
+ if (!cacheKey || !verdict.allowed) {
2030
+ return;
2031
+ }
2032
+ this.recentGuardVerdicts.set(cacheKey, {
2033
+ verdict,
2034
+ expiresAt: Date.now() + GUARD_VERDICT_CACHE_TTL_MS
2035
+ });
2036
+ if (this.recentGuardVerdicts.size > 100) {
2037
+ for (const [key, value] of this.recentGuardVerdicts.entries()) {
2038
+ if (Date.now() > value.expiresAt) {
2039
+ this.recentGuardVerdicts.delete(key);
2040
+ }
2041
+ }
2042
+ }
2043
+ }
1989
2044
  async getCapabilityConfig(force = false, options) {
1990
2045
  const effectiveApiKey = this.resolveApiKey(options?.apiKey);
1991
2046
  return ensureCapabilityConfig({
@@ -2143,6 +2198,11 @@ var AgentID = class {
2143
2198
  ...params,
2144
2199
  client_capabilities: params.client_capabilities ?? this.buildClientCapabilities()
2145
2200
  };
2201
+ const guardCacheKey = this.buildGuardCacheKey(payload);
2202
+ const cachedVerdict = this.readCachedGuardVerdict(guardCacheKey);
2203
+ if (cachedVerdict) {
2204
+ return cachedVerdict;
2205
+ }
2146
2206
  const correlationId = createCorrelationId(payload.client_event_id);
2147
2207
  let lastStatusCode = null;
2148
2208
  let lastAbort = false;
@@ -2189,6 +2249,7 @@ var AgentID = class {
2189
2249
  });
2190
2250
  return { allowed: true, reason: "system_failure_fail_open" };
2191
2251
  }
2252
+ this.cacheGuardVerdict(guardCacheKey, verdict);
2192
2253
  return verdict;
2193
2254
  }
2194
2255
  if (!res.ok) {
@@ -2262,6 +2323,62 @@ var AgentID = class {
2262
2323
  }
2263
2324
  return { allowed: true, reason: "guard_unreachable" };
2264
2325
  }
2326
+ async sendIngest(params, options) {
2327
+ const effectiveApiKey = this.resolveApiKey(options?.apiKey);
2328
+ const eventId = createEventId(params.event_id);
2329
+ const timestamp = params.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
2330
+ const metadata = {
2331
+ ...params.metadata ?? {}
2332
+ };
2333
+ if (!Object.prototype.hasOwnProperty.call(metadata, "agentid_base_url")) {
2334
+ metadata.agentid_base_url = this.baseUrl;
2335
+ }
2336
+ void this.getCapabilityConfig(false, { apiKey: effectiveApiKey }).catch(() => void 0);
2337
+ const payload = {
2338
+ ...params,
2339
+ event_id: eventId,
2340
+ timestamp,
2341
+ input: sanitizeIngestText(params.input),
2342
+ output: sanitizeIngestText(params.output),
2343
+ metadata,
2344
+ client_capabilities: params.client_capabilities ?? this.buildClientCapabilities()
2345
+ };
2346
+ for (let attempt = 0; attempt < INGEST_MAX_ATTEMPTS; attempt += 1) {
2347
+ try {
2348
+ const response = await fetch(`${this.baseUrl}/ingest`, {
2349
+ method: "POST",
2350
+ keepalive: true,
2351
+ headers: {
2352
+ "Content-Type": "application/json",
2353
+ "x-agentid-api-key": effectiveApiKey,
2354
+ "X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER2
2355
+ },
2356
+ body: JSON.stringify(payload)
2357
+ });
2358
+ const responseBody = await safeReadJson2(response);
2359
+ if (response.ok) {
2360
+ return { ok: true, status: response.status, reason: null };
2361
+ }
2362
+ const reason = responseBody && typeof responseBody === "object" && typeof responseBody.reason === "string" ? responseBody.reason ?? null : null;
2363
+ if (response.status === 409 && reason === "replay_detected") {
2364
+ return { ok: true, status: response.status, reason };
2365
+ }
2366
+ const retryable = response.status >= 500 || response.status === 429;
2367
+ if (retryable && attempt < INGEST_MAX_ATTEMPTS - 1) {
2368
+ await waitForIngestRetry(attempt);
2369
+ continue;
2370
+ }
2371
+ return { ok: false, status: response.status, reason };
2372
+ } catch {
2373
+ if (attempt < INGEST_MAX_ATTEMPTS - 1) {
2374
+ await waitForIngestRetry(attempt);
2375
+ continue;
2376
+ }
2377
+ return { ok: false, status: null, reason: "network_error" };
2378
+ }
2379
+ }
2380
+ return { ok: false, status: null, reason: "unknown_ingest_failure" };
2381
+ }
2265
2382
  extractStreamChunkText(chunk) {
2266
2383
  if (typeof chunk === "string") {
2267
2384
  return chunk;
@@ -2363,35 +2480,11 @@ var AgentID = class {
2363
2480
  log(params, options) {
2364
2481
  queueMicrotask(() => {
2365
2482
  void (async () => {
2366
- try {
2367
- const effectiveApiKey = this.resolveApiKey(options?.apiKey);
2368
- const eventId = params.event_id ?? createEventId();
2369
- const timestamp = params.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
2370
- void this.getCapabilityConfig(false, { apiKey: effectiveApiKey }).catch(() => void 0);
2371
- const metadata = {
2372
- ...params.metadata ?? {}
2373
- };
2374
- if (!Object.prototype.hasOwnProperty.call(metadata, "agentid_base_url")) {
2375
- metadata.agentid_base_url = this.baseUrl;
2376
- }
2377
- await fetch(`${this.baseUrl}/ingest`, {
2378
- method: "POST",
2379
- keepalive: true,
2380
- headers: {
2381
- "Content-Type": "application/json",
2382
- "x-agentid-api-key": effectiveApiKey,
2383
- "X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER2
2384
- },
2385
- body: JSON.stringify({
2386
- ...params,
2387
- event_id: eventId,
2388
- timestamp,
2389
- metadata,
2390
- client_capabilities: params.client_capabilities ?? this.buildClientCapabilities()
2391
- })
2392
- });
2393
- } catch (error) {
2394
- console.error("[AgentID] Log failed:", error);
2483
+ const result = await this.sendIngest(params, options);
2484
+ if (!result.ok) {
2485
+ console.warn(
2486
+ `[AgentID] Ingest telemetry failed (status=${result.status ?? "network"}, reason=${result.reason ?? "unknown"}).`
2487
+ );
2395
2488
  }
2396
2489
  })();
2397
2490
  });
@@ -2505,6 +2598,8 @@ var AgentID = class {
2505
2598
  `AgentID: Security Blocked (${verdict.reason ?? "guard_denied"})`
2506
2599
  );
2507
2600
  }
2601
+ const canonicalClientEventId = typeof verdict.client_event_id === "string" && isUuidLike(verdict.client_event_id) ? verdict.client_event_id : clientEventId;
2602
+ const guardEventId = typeof verdict.guard_event_id === "string" && verdict.guard_event_id.length > 0 ? verdict.guard_event_id : null;
2508
2603
  const isShadowMode = verdict.shadow_mode === true;
2509
2604
  const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
2510
2605
  if (transformedInput !== maskedText) {
@@ -2527,10 +2622,10 @@ var AgentID = class {
2527
2622
  })()
2528
2623
  );
2529
2624
  if (maskedText && wrappedCompletion.mode === "stream") {
2530
- void wrappedCompletion.done.then((result) => {
2625
+ void wrappedCompletion.done.then(async (result) => {
2531
2626
  const outputForLog = isShadowMode ? result.rawOutput : result.transformedOutput;
2532
- this.log({
2533
- event_id: clientEventId,
2627
+ const ingestResult = await this.sendIngest({
2628
+ event_id: canonicalClientEventId,
2534
2629
  system_id: systemId,
2535
2630
  user_id: options.user_id,
2536
2631
  input: maskedText,
@@ -2538,6 +2633,7 @@ var AgentID = class {
2538
2633
  model: adapter.getModelName(maskedReq),
2539
2634
  usage: void 0,
2540
2635
  latency: void 0,
2636
+ event_type: "complete",
2541
2637
  metadata: {
2542
2638
  transformed_input: maskedText,
2543
2639
  transformed_output: result.transformedOutput,
@@ -2545,10 +2641,17 @@ var AgentID = class {
2545
2641
  shadow_mode: isShadowMode,
2546
2642
  simulated_decision: verdict.simulated_decision ?? null,
2547
2643
  simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
2548
- response_streamed: true
2644
+ response_streamed: true,
2645
+ guard_event_id: guardEventId,
2646
+ client_event_id: canonicalClientEventId
2549
2647
  },
2550
2648
  client_capabilities: this.buildClientCapabilities("openai", false)
2551
2649
  }, requestOptions);
2650
+ if (!ingestResult.ok) {
2651
+ console.warn(
2652
+ `[AgentID] Stream ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
2653
+ );
2654
+ }
2552
2655
  }).catch((error) => {
2553
2656
  console.error("[AgentID] Stream completion wrapping failed:", error);
2554
2657
  });
@@ -2564,8 +2667,8 @@ var AgentID = class {
2564
2667
  const model = adapter.getModelName(maskedReq, res);
2565
2668
  const usage = adapter.getTokenUsage(res);
2566
2669
  const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
2567
- this.log({
2568
- event_id: clientEventId,
2670
+ const ingestResult = await this.sendIngest({
2671
+ event_id: canonicalClientEventId,
2569
2672
  system_id: systemId,
2570
2673
  user_id: options.user_id,
2571
2674
  input: maskedText,
@@ -2573,6 +2676,7 @@ var AgentID = class {
2573
2676
  model,
2574
2677
  usage,
2575
2678
  latency,
2679
+ event_type: "complete",
2576
2680
  metadata: {
2577
2681
  transformed_input: maskedText,
2578
2682
  transformed_output: wrappedCompletion.transformedOutput,
@@ -2580,10 +2684,17 @@ var AgentID = class {
2580
2684
  shadow_mode: isShadowMode,
2581
2685
  simulated_decision: verdict.simulated_decision ?? null,
2582
2686
  simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
2583
- response_streamed: false
2687
+ response_streamed: false,
2688
+ guard_event_id: guardEventId,
2689
+ client_event_id: canonicalClientEventId
2584
2690
  },
2585
2691
  client_capabilities: this.buildClientCapabilities("openai", false)
2586
2692
  }, requestOptions);
2693
+ if (!ingestResult.ok) {
2694
+ console.warn(
2695
+ `[AgentID] Ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
2696
+ );
2697
+ }
2587
2698
  }
2588
2699
  if (!capabilityConfig.block_pii_leakage && this.piiMasking && shouldDeanonymize) {
2589
2700
  const deanon = this.pii.deanonymize(adapter.extractOutput(res), mapping);
@@ -83,10 +83,14 @@ declare class AgentID {
83
83
  private localEnforcer;
84
84
  private injectionScanner;
85
85
  private requestClientEventIds;
86
+ private recentGuardVerdicts;
86
87
  constructor(config: AgentIDConfig);
87
88
  private buildClientCapabilities;
88
89
  private resolveApiKey;
89
90
  private resolveClientEventId;
91
+ private buildGuardCacheKey;
92
+ private readCachedGuardVerdict;
93
+ private cacheGuardVerdict;
90
94
  getCapabilityConfig(force?: boolean, options?: RequestOptions): Promise<CapabilityConfig>;
91
95
  private getCachedCapabilityConfig;
92
96
  prepareInputForDispatch(params: {
@@ -105,6 +109,7 @@ declare class AgentID {
105
109
  * strictMode=true: FAIL-CLOSED and throws on connectivity/timeouts.
106
110
  */
107
111
  guard(params: GuardParams, options?: RequestOptions): Promise<GuardResponse>;
112
+ private sendIngest;
108
113
  private extractStreamChunkText;
109
114
  private wrapCompletion;
110
115
  /**
@@ -83,10 +83,14 @@ declare class AgentID {
83
83
  private localEnforcer;
84
84
  private injectionScanner;
85
85
  private requestClientEventIds;
86
+ private recentGuardVerdicts;
86
87
  constructor(config: AgentIDConfig);
87
88
  private buildClientCapabilities;
88
89
  private resolveApiKey;
89
90
  private resolveClientEventId;
91
+ private buildGuardCacheKey;
92
+ private readCachedGuardVerdict;
93
+ private cacheGuardVerdict;
90
94
  getCapabilityConfig(force?: boolean, options?: RequestOptions): Promise<CapabilityConfig>;
91
95
  private getCachedCapabilityConfig;
92
96
  prepareInputForDispatch(params: {
@@ -105,6 +109,7 @@ declare class AgentID {
105
109
  * strictMode=true: FAIL-CLOSED and throws on connectivity/timeouts.
106
110
  */
107
111
  guard(params: GuardParams, options?: RequestOptions): Promise<GuardResponse>;
112
+ private sendIngest;
108
113
  private extractStreamChunkText;
109
114
  private wrapCompletion;
110
115
  /**
@@ -1 +1 @@
1
- export { a as AgentIDCallbackHandler } from './langchain-CUyC7jmr.mjs';
1
+ export { a as AgentIDCallbackHandler } from './langchain-CmUK7sna.mjs';
@@ -1 +1 @@
1
- export { a as AgentIDCallbackHandler } from './langchain-CUyC7jmr.js';
1
+ export { a as AgentIDCallbackHandler } from './langchain-CmUK7sna.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentid-sdk",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "AgentID JavaScript/TypeScript SDK for guard, ingest, tracing, and analytics.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://agentid.ai",