agentid-sdk 0.1.13 → 0.1.14

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,59 @@ 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
+ const retryable = response.status >= 500 || response.status === 429;
2402
+ if (retryable && attempt < INGEST_MAX_ATTEMPTS - 1) {
2403
+ await waitForIngestRetry(attempt);
2404
+ continue;
2405
+ }
2406
+ return { ok: false, status: response.status, reason };
2407
+ } catch {
2408
+ if (attempt < INGEST_MAX_ATTEMPTS - 1) {
2409
+ await waitForIngestRetry(attempt);
2410
+ continue;
2411
+ }
2412
+ return { ok: false, status: null, reason: "network_error" };
2413
+ }
2414
+ }
2415
+ return { ok: false, status: null, reason: "unknown_ingest_failure" };
2416
+ }
2303
2417
  extractStreamChunkText(chunk) {
2304
2418
  if (typeof chunk === "string") {
2305
2419
  return chunk;
@@ -2401,35 +2515,11 @@ var AgentID = class {
2401
2515
  log(params, options) {
2402
2516
  queueMicrotask(() => {
2403
2517
  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);
2518
+ const result = await this.sendIngest(params, options);
2519
+ if (!result.ok) {
2520
+ console.warn(
2521
+ `[AgentID] Ingest telemetry failed (status=${result.status ?? "network"}, reason=${result.reason ?? "unknown"}).`
2522
+ );
2433
2523
  }
2434
2524
  })();
2435
2525
  });
@@ -2543,6 +2633,8 @@ var AgentID = class {
2543
2633
  `AgentID: Security Blocked (${verdict.reason ?? "guard_denied"})`
2544
2634
  );
2545
2635
  }
2636
+ const canonicalClientEventId = typeof verdict.client_event_id === "string" && isUuidLike(verdict.client_event_id) ? verdict.client_event_id : clientEventId;
2637
+ const guardEventId = typeof verdict.guard_event_id === "string" && verdict.guard_event_id.length > 0 ? verdict.guard_event_id : null;
2546
2638
  const isShadowMode = verdict.shadow_mode === true;
2547
2639
  const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
2548
2640
  if (transformedInput !== maskedText) {
@@ -2565,10 +2657,10 @@ var AgentID = class {
2565
2657
  })()
2566
2658
  );
2567
2659
  if (maskedText && wrappedCompletion.mode === "stream") {
2568
- void wrappedCompletion.done.then((result) => {
2660
+ void wrappedCompletion.done.then(async (result) => {
2569
2661
  const outputForLog = isShadowMode ? result.rawOutput : result.transformedOutput;
2570
- this.log({
2571
- event_id: clientEventId,
2662
+ const ingestResult = await this.sendIngest({
2663
+ event_id: canonicalClientEventId,
2572
2664
  system_id: systemId,
2573
2665
  user_id: options.user_id,
2574
2666
  input: maskedText,
@@ -2576,6 +2668,7 @@ var AgentID = class {
2576
2668
  model: adapter.getModelName(maskedReq),
2577
2669
  usage: void 0,
2578
2670
  latency: void 0,
2671
+ event_type: "complete",
2579
2672
  metadata: {
2580
2673
  transformed_input: maskedText,
2581
2674
  transformed_output: result.transformedOutput,
@@ -2583,10 +2676,17 @@ var AgentID = class {
2583
2676
  shadow_mode: isShadowMode,
2584
2677
  simulated_decision: verdict.simulated_decision ?? null,
2585
2678
  simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
2586
- response_streamed: true
2679
+ response_streamed: true,
2680
+ guard_event_id: guardEventId,
2681
+ client_event_id: canonicalClientEventId
2587
2682
  },
2588
2683
  client_capabilities: this.buildClientCapabilities("openai", false)
2589
2684
  }, requestOptions);
2685
+ if (!ingestResult.ok) {
2686
+ console.warn(
2687
+ `[AgentID] Stream ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
2688
+ );
2689
+ }
2590
2690
  }).catch((error) => {
2591
2691
  console.error("[AgentID] Stream completion wrapping failed:", error);
2592
2692
  });
@@ -2602,8 +2702,8 @@ var AgentID = class {
2602
2702
  const model = adapter.getModelName(maskedReq, res);
2603
2703
  const usage = adapter.getTokenUsage(res);
2604
2704
  const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
2605
- this.log({
2606
- event_id: clientEventId,
2705
+ const ingestResult = await this.sendIngest({
2706
+ event_id: canonicalClientEventId,
2607
2707
  system_id: systemId,
2608
2708
  user_id: options.user_id,
2609
2709
  input: maskedText,
@@ -2611,6 +2711,7 @@ var AgentID = class {
2611
2711
  model,
2612
2712
  usage,
2613
2713
  latency,
2714
+ event_type: "complete",
2614
2715
  metadata: {
2615
2716
  transformed_input: maskedText,
2616
2717
  transformed_output: wrappedCompletion.transformedOutput,
@@ -2618,10 +2719,17 @@ var AgentID = class {
2618
2719
  shadow_mode: isShadowMode,
2619
2720
  simulated_decision: verdict.simulated_decision ?? null,
2620
2721
  simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
2621
- response_streamed: false
2722
+ response_streamed: false,
2723
+ guard_event_id: guardEventId,
2724
+ client_event_id: canonicalClientEventId
2622
2725
  },
2623
2726
  client_capabilities: this.buildClientCapabilities("openai", false)
2624
2727
  }, requestOptions);
2728
+ if (!ingestResult.ok) {
2729
+ console.warn(
2730
+ `[AgentID] Ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
2731
+ );
2732
+ }
2625
2733
  }
2626
2734
  if (!capabilityConfig.block_pii_leakage && this.piiMasking && shouldDeanonymize) {
2627
2735
  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,59 @@ 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
+ const retryable = response.status >= 500 || response.status === 429;
2364
+ if (retryable && attempt < INGEST_MAX_ATTEMPTS - 1) {
2365
+ await waitForIngestRetry(attempt);
2366
+ continue;
2367
+ }
2368
+ return { ok: false, status: response.status, reason };
2369
+ } catch {
2370
+ if (attempt < INGEST_MAX_ATTEMPTS - 1) {
2371
+ await waitForIngestRetry(attempt);
2372
+ continue;
2373
+ }
2374
+ return { ok: false, status: null, reason: "network_error" };
2375
+ }
2376
+ }
2377
+ return { ok: false, status: null, reason: "unknown_ingest_failure" };
2378
+ }
2265
2379
  extractStreamChunkText(chunk) {
2266
2380
  if (typeof chunk === "string") {
2267
2381
  return chunk;
@@ -2363,35 +2477,11 @@ var AgentID = class {
2363
2477
  log(params, options) {
2364
2478
  queueMicrotask(() => {
2365
2479
  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);
2480
+ const result = await this.sendIngest(params, options);
2481
+ if (!result.ok) {
2482
+ console.warn(
2483
+ `[AgentID] Ingest telemetry failed (status=${result.status ?? "network"}, reason=${result.reason ?? "unknown"}).`
2484
+ );
2395
2485
  }
2396
2486
  })();
2397
2487
  });
@@ -2505,6 +2595,8 @@ var AgentID = class {
2505
2595
  `AgentID: Security Blocked (${verdict.reason ?? "guard_denied"})`
2506
2596
  );
2507
2597
  }
2598
+ const canonicalClientEventId = typeof verdict.client_event_id === "string" && isUuidLike(verdict.client_event_id) ? verdict.client_event_id : clientEventId;
2599
+ const guardEventId = typeof verdict.guard_event_id === "string" && verdict.guard_event_id.length > 0 ? verdict.guard_event_id : null;
2508
2600
  const isShadowMode = verdict.shadow_mode === true;
2509
2601
  const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
2510
2602
  if (transformedInput !== maskedText) {
@@ -2527,10 +2619,10 @@ var AgentID = class {
2527
2619
  })()
2528
2620
  );
2529
2621
  if (maskedText && wrappedCompletion.mode === "stream") {
2530
- void wrappedCompletion.done.then((result) => {
2622
+ void wrappedCompletion.done.then(async (result) => {
2531
2623
  const outputForLog = isShadowMode ? result.rawOutput : result.transformedOutput;
2532
- this.log({
2533
- event_id: clientEventId,
2624
+ const ingestResult = await this.sendIngest({
2625
+ event_id: canonicalClientEventId,
2534
2626
  system_id: systemId,
2535
2627
  user_id: options.user_id,
2536
2628
  input: maskedText,
@@ -2538,6 +2630,7 @@ var AgentID = class {
2538
2630
  model: adapter.getModelName(maskedReq),
2539
2631
  usage: void 0,
2540
2632
  latency: void 0,
2633
+ event_type: "complete",
2541
2634
  metadata: {
2542
2635
  transformed_input: maskedText,
2543
2636
  transformed_output: result.transformedOutput,
@@ -2545,10 +2638,17 @@ var AgentID = class {
2545
2638
  shadow_mode: isShadowMode,
2546
2639
  simulated_decision: verdict.simulated_decision ?? null,
2547
2640
  simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
2548
- response_streamed: true
2641
+ response_streamed: true,
2642
+ guard_event_id: guardEventId,
2643
+ client_event_id: canonicalClientEventId
2549
2644
  },
2550
2645
  client_capabilities: this.buildClientCapabilities("openai", false)
2551
2646
  }, requestOptions);
2647
+ if (!ingestResult.ok) {
2648
+ console.warn(
2649
+ `[AgentID] Stream ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
2650
+ );
2651
+ }
2552
2652
  }).catch((error) => {
2553
2653
  console.error("[AgentID] Stream completion wrapping failed:", error);
2554
2654
  });
@@ -2564,8 +2664,8 @@ var AgentID = class {
2564
2664
  const model = adapter.getModelName(maskedReq, res);
2565
2665
  const usage = adapter.getTokenUsage(res);
2566
2666
  const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
2567
- this.log({
2568
- event_id: clientEventId,
2667
+ const ingestResult = await this.sendIngest({
2668
+ event_id: canonicalClientEventId,
2569
2669
  system_id: systemId,
2570
2670
  user_id: options.user_id,
2571
2671
  input: maskedText,
@@ -2573,6 +2673,7 @@ var AgentID = class {
2573
2673
  model,
2574
2674
  usage,
2575
2675
  latency,
2676
+ event_type: "complete",
2576
2677
  metadata: {
2577
2678
  transformed_input: maskedText,
2578
2679
  transformed_output: wrappedCompletion.transformedOutput,
@@ -2580,10 +2681,17 @@ var AgentID = class {
2580
2681
  shadow_mode: isShadowMode,
2581
2682
  simulated_decision: verdict.simulated_decision ?? null,
2582
2683
  simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
2583
- response_streamed: false
2684
+ response_streamed: false,
2685
+ guard_event_id: guardEventId,
2686
+ client_event_id: canonicalClientEventId
2584
2687
  },
2585
2688
  client_capabilities: this.buildClientCapabilities("openai", false)
2586
2689
  }, requestOptions);
2690
+ if (!ingestResult.ok) {
2691
+ console.warn(
2692
+ `[AgentID] Ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
2693
+ );
2694
+ }
2587
2695
  }
2588
2696
  if (!capabilityConfig.block_pii_leakage && this.piiMasking && shouldDeanonymize) {
2589
2697
  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.14",
4
4
  "description": "AgentID JavaScript/TypeScript SDK for guard, ingest, tracing, and analytics.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://agentid.ai",