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 +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +146 -38
- package/dist/index.mjs +146 -38
- package/dist/{langchain-CUyC7jmr.d.mts → langchain-CmUK7sna.d.mts} +5 -0
- package/dist/{langchain-CUyC7jmr.d.ts → langchain-CmUK7sna.d.ts} +5 -0
- package/dist/langchain.d.mts +1 -1
- package/dist/langchain.d.ts +1 -1
- package/package.json +1 -1
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-
|
|
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-
|
|
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
|
|
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
|
|
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
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
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.
|
|
2571
|
-
event_id:
|
|
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.
|
|
2606
|
-
event_id:
|
|
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
|
|
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
|
|
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
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
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.
|
|
2533
|
-
event_id:
|
|
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.
|
|
2568
|
-
event_id:
|
|
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
|
/**
|
package/dist/langchain.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { a as AgentIDCallbackHandler } from './langchain-
|
|
1
|
+
export { a as AgentIDCallbackHandler } from './langchain-CmUK7sna.mjs';
|
package/dist/langchain.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { a as AgentIDCallbackHandler } from './langchain-
|
|
1
|
+
export { a as AgentIDCallbackHandler } from './langchain-CmUK7sna.js';
|