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 +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +149 -38
- package/dist/index.mjs +149 -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,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
|
-
|
|
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);
|
|
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.
|
|
2571
|
-
event_id:
|
|
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.
|
|
2606
|
-
event_id:
|
|
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
|
|
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,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
|
-
|
|
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);
|
|
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.
|
|
2533
|
-
event_id:
|
|
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.
|
|
2568
|
-
event_id:
|
|
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
|
/**
|
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';
|