agentid-sdk 0.1.12 → 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 +174 -38
- package/dist/index.mjs +174 -38
- package/dist/{langchain-BGP3qxvW.d.mts → langchain-CmUK7sna.d.mts} +7 -0
- package/dist/{langchain-BGP3qxvW.d.ts → langchain-CmUK7sna.d.ts} +7 -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,18 +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
|
+
}
|
|
1900
|
+
function createEventId(seed) {
|
|
1901
|
+
if (isUuidLike(seed)) return seed;
|
|
1902
|
+
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
1903
|
+
return globalThis.crypto.randomUUID();
|
|
1904
|
+
}
|
|
1905
|
+
return createPseudoUuidV4();
|
|
1906
|
+
}
|
|
1885
1907
|
function createCorrelationId(seed) {
|
|
1886
1908
|
if (isUuidLike(seed)) return seed;
|
|
1887
1909
|
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
1888
1910
|
return globalThis.crypto.randomUUID();
|
|
1889
1911
|
}
|
|
1890
|
-
return
|
|
1912
|
+
return createPseudoUuidV4();
|
|
1891
1913
|
}
|
|
1892
1914
|
async function waitForRetry(attemptIndex) {
|
|
1893
1915
|
const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
|
|
1894
1916
|
if (!delay) return;
|
|
1895
1917
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1896
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
|
+
}
|
|
1897
1924
|
async function safeReadJson2(response) {
|
|
1898
1925
|
try {
|
|
1899
1926
|
return await response.json();
|
|
@@ -1968,6 +1995,8 @@ function createCompletionChunkCollector() {
|
|
|
1968
1995
|
var AgentID = class {
|
|
1969
1996
|
constructor(config) {
|
|
1970
1997
|
this.injectionScanner = getInjectionScanner();
|
|
1998
|
+
this.requestClientEventIds = /* @__PURE__ */ new WeakMap();
|
|
1999
|
+
this.recentGuardVerdicts = /* @__PURE__ */ new Map();
|
|
1971
2000
|
this.apiKey = config.apiKey.trim();
|
|
1972
2001
|
this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
|
|
1973
2002
|
this.piiMasking = Boolean(config.piiMasking);
|
|
@@ -1996,6 +2025,60 @@ var AgentID = class {
|
|
|
1996
2025
|
}
|
|
1997
2026
|
return this.apiKey;
|
|
1998
2027
|
}
|
|
2028
|
+
resolveClientEventId(requestBody) {
|
|
2029
|
+
const directClientEventId = requestBody.client_event_id;
|
|
2030
|
+
if (typeof directClientEventId === "string" && isUuidLike(directClientEventId)) {
|
|
2031
|
+
return directClientEventId;
|
|
2032
|
+
}
|
|
2033
|
+
const metadata = requestBody.metadata;
|
|
2034
|
+
if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
|
|
2035
|
+
const metadataClientEventId = metadata.client_event_id;
|
|
2036
|
+
if (typeof metadataClientEventId === "string" && isUuidLike(metadataClientEventId)) {
|
|
2037
|
+
return metadataClientEventId;
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
const cached = this.requestClientEventIds.get(requestBody);
|
|
2041
|
+
if (cached) {
|
|
2042
|
+
return cached;
|
|
2043
|
+
}
|
|
2044
|
+
const generated = createEventId();
|
|
2045
|
+
this.requestClientEventIds.set(requestBody, generated);
|
|
2046
|
+
return generated;
|
|
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
|
+
}
|
|
1999
2082
|
async getCapabilityConfig(force = false, options) {
|
|
2000
2083
|
const effectiveApiKey = this.resolveApiKey(options?.apiKey);
|
|
2001
2084
|
return ensureCapabilityConfig({
|
|
@@ -2153,6 +2236,11 @@ var AgentID = class {
|
|
|
2153
2236
|
...params,
|
|
2154
2237
|
client_capabilities: params.client_capabilities ?? this.buildClientCapabilities()
|
|
2155
2238
|
};
|
|
2239
|
+
const guardCacheKey = this.buildGuardCacheKey(payload);
|
|
2240
|
+
const cachedVerdict = this.readCachedGuardVerdict(guardCacheKey);
|
|
2241
|
+
if (cachedVerdict) {
|
|
2242
|
+
return cachedVerdict;
|
|
2243
|
+
}
|
|
2156
2244
|
const correlationId = createCorrelationId(payload.client_event_id);
|
|
2157
2245
|
let lastStatusCode = null;
|
|
2158
2246
|
let lastAbort = false;
|
|
@@ -2199,6 +2287,7 @@ var AgentID = class {
|
|
|
2199
2287
|
});
|
|
2200
2288
|
return { allowed: true, reason: "system_failure_fail_open" };
|
|
2201
2289
|
}
|
|
2290
|
+
this.cacheGuardVerdict(guardCacheKey, verdict);
|
|
2202
2291
|
return verdict;
|
|
2203
2292
|
}
|
|
2204
2293
|
if (!res.ok) {
|
|
@@ -2272,6 +2361,59 @@ var AgentID = class {
|
|
|
2272
2361
|
}
|
|
2273
2362
|
return { allowed: true, reason: "guard_unreachable" };
|
|
2274
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
|
+
}
|
|
2275
2417
|
extractStreamChunkText(chunk) {
|
|
2276
2418
|
if (typeof chunk === "string") {
|
|
2277
2419
|
return chunk;
|
|
@@ -2373,35 +2515,11 @@ var AgentID = class {
|
|
|
2373
2515
|
log(params, options) {
|
|
2374
2516
|
queueMicrotask(() => {
|
|
2375
2517
|
void (async () => {
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
const metadata = {
|
|
2382
|
-
...params.metadata ?? {}
|
|
2383
|
-
};
|
|
2384
|
-
if (!Object.prototype.hasOwnProperty.call(metadata, "agentid_base_url")) {
|
|
2385
|
-
metadata.agentid_base_url = this.baseUrl;
|
|
2386
|
-
}
|
|
2387
|
-
await fetch(`${this.baseUrl}/ingest`, {
|
|
2388
|
-
method: "POST",
|
|
2389
|
-
keepalive: true,
|
|
2390
|
-
headers: {
|
|
2391
|
-
"Content-Type": "application/json",
|
|
2392
|
-
"x-agentid-api-key": effectiveApiKey,
|
|
2393
|
-
"X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER2
|
|
2394
|
-
},
|
|
2395
|
-
body: JSON.stringify({
|
|
2396
|
-
...params,
|
|
2397
|
-
event_id: eventId,
|
|
2398
|
-
timestamp,
|
|
2399
|
-
metadata,
|
|
2400
|
-
client_capabilities: params.client_capabilities ?? this.buildClientCapabilities()
|
|
2401
|
-
})
|
|
2402
|
-
});
|
|
2403
|
-
} catch (error) {
|
|
2404
|
-
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
|
+
);
|
|
2405
2523
|
}
|
|
2406
2524
|
})();
|
|
2407
2525
|
});
|
|
@@ -2501,7 +2619,7 @@ var AgentID = class {
|
|
|
2501
2619
|
"AgentID: No user message found. Security guard requires string input."
|
|
2502
2620
|
);
|
|
2503
2621
|
}
|
|
2504
|
-
const clientEventId =
|
|
2622
|
+
const clientEventId = this.resolveClientEventId(req);
|
|
2505
2623
|
const verdict = await this.guard({
|
|
2506
2624
|
input: maskedText,
|
|
2507
2625
|
system_id: systemId,
|
|
@@ -2515,6 +2633,8 @@ var AgentID = class {
|
|
|
2515
2633
|
`AgentID: Security Blocked (${verdict.reason ?? "guard_denied"})`
|
|
2516
2634
|
);
|
|
2517
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;
|
|
2518
2638
|
const isShadowMode = verdict.shadow_mode === true;
|
|
2519
2639
|
const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
|
|
2520
2640
|
if (transformedInput !== maskedText) {
|
|
@@ -2537,10 +2657,10 @@ var AgentID = class {
|
|
|
2537
2657
|
})()
|
|
2538
2658
|
);
|
|
2539
2659
|
if (maskedText && wrappedCompletion.mode === "stream") {
|
|
2540
|
-
void wrappedCompletion.done.then((result) => {
|
|
2660
|
+
void wrappedCompletion.done.then(async (result) => {
|
|
2541
2661
|
const outputForLog = isShadowMode ? result.rawOutput : result.transformedOutput;
|
|
2542
|
-
this.
|
|
2543
|
-
event_id:
|
|
2662
|
+
const ingestResult = await this.sendIngest({
|
|
2663
|
+
event_id: canonicalClientEventId,
|
|
2544
2664
|
system_id: systemId,
|
|
2545
2665
|
user_id: options.user_id,
|
|
2546
2666
|
input: maskedText,
|
|
@@ -2548,6 +2668,7 @@ var AgentID = class {
|
|
|
2548
2668
|
model: adapter.getModelName(maskedReq),
|
|
2549
2669
|
usage: void 0,
|
|
2550
2670
|
latency: void 0,
|
|
2671
|
+
event_type: "complete",
|
|
2551
2672
|
metadata: {
|
|
2552
2673
|
transformed_input: maskedText,
|
|
2553
2674
|
transformed_output: result.transformedOutput,
|
|
@@ -2555,10 +2676,17 @@ var AgentID = class {
|
|
|
2555
2676
|
shadow_mode: isShadowMode,
|
|
2556
2677
|
simulated_decision: verdict.simulated_decision ?? null,
|
|
2557
2678
|
simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
|
|
2558
|
-
response_streamed: true
|
|
2679
|
+
response_streamed: true,
|
|
2680
|
+
guard_event_id: guardEventId,
|
|
2681
|
+
client_event_id: canonicalClientEventId
|
|
2559
2682
|
},
|
|
2560
2683
|
client_capabilities: this.buildClientCapabilities("openai", false)
|
|
2561
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
|
+
}
|
|
2562
2690
|
}).catch((error) => {
|
|
2563
2691
|
console.error("[AgentID] Stream completion wrapping failed:", error);
|
|
2564
2692
|
});
|
|
@@ -2574,8 +2702,8 @@ var AgentID = class {
|
|
|
2574
2702
|
const model = adapter.getModelName(maskedReq, res);
|
|
2575
2703
|
const usage = adapter.getTokenUsage(res);
|
|
2576
2704
|
const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
|
|
2577
|
-
this.
|
|
2578
|
-
event_id:
|
|
2705
|
+
const ingestResult = await this.sendIngest({
|
|
2706
|
+
event_id: canonicalClientEventId,
|
|
2579
2707
|
system_id: systemId,
|
|
2580
2708
|
user_id: options.user_id,
|
|
2581
2709
|
input: maskedText,
|
|
@@ -2583,6 +2711,7 @@ var AgentID = class {
|
|
|
2583
2711
|
model,
|
|
2584
2712
|
usage,
|
|
2585
2713
|
latency,
|
|
2714
|
+
event_type: "complete",
|
|
2586
2715
|
metadata: {
|
|
2587
2716
|
transformed_input: maskedText,
|
|
2588
2717
|
transformed_output: wrappedCompletion.transformedOutput,
|
|
@@ -2590,10 +2719,17 @@ var AgentID = class {
|
|
|
2590
2719
|
shadow_mode: isShadowMode,
|
|
2591
2720
|
simulated_decision: verdict.simulated_decision ?? null,
|
|
2592
2721
|
simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
|
|
2593
|
-
response_streamed: false
|
|
2722
|
+
response_streamed: false,
|
|
2723
|
+
guard_event_id: guardEventId,
|
|
2724
|
+
client_event_id: canonicalClientEventId
|
|
2594
2725
|
},
|
|
2595
2726
|
client_capabilities: this.buildClientCapabilities("openai", false)
|
|
2596
2727
|
}, requestOptions);
|
|
2728
|
+
if (!ingestResult.ok) {
|
|
2729
|
+
console.warn(
|
|
2730
|
+
`[AgentID] Ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
|
|
2731
|
+
);
|
|
2732
|
+
}
|
|
2597
2733
|
}
|
|
2598
2734
|
if (!capabilityConfig.block_pii_leakage && this.piiMasking && shouldDeanonymize) {
|
|
2599
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,18 +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
|
+
}
|
|
1862
|
+
function createEventId(seed) {
|
|
1863
|
+
if (isUuidLike(seed)) return seed;
|
|
1864
|
+
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
1865
|
+
return globalThis.crypto.randomUUID();
|
|
1866
|
+
}
|
|
1867
|
+
return createPseudoUuidV4();
|
|
1868
|
+
}
|
|
1847
1869
|
function createCorrelationId(seed) {
|
|
1848
1870
|
if (isUuidLike(seed)) return seed;
|
|
1849
1871
|
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
1850
1872
|
return globalThis.crypto.randomUUID();
|
|
1851
1873
|
}
|
|
1852
|
-
return
|
|
1874
|
+
return createPseudoUuidV4();
|
|
1853
1875
|
}
|
|
1854
1876
|
async function waitForRetry(attemptIndex) {
|
|
1855
1877
|
const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
|
|
1856
1878
|
if (!delay) return;
|
|
1857
1879
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1858
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
|
+
}
|
|
1859
1886
|
async function safeReadJson2(response) {
|
|
1860
1887
|
try {
|
|
1861
1888
|
return await response.json();
|
|
@@ -1930,6 +1957,8 @@ function createCompletionChunkCollector() {
|
|
|
1930
1957
|
var AgentID = class {
|
|
1931
1958
|
constructor(config) {
|
|
1932
1959
|
this.injectionScanner = getInjectionScanner();
|
|
1960
|
+
this.requestClientEventIds = /* @__PURE__ */ new WeakMap();
|
|
1961
|
+
this.recentGuardVerdicts = /* @__PURE__ */ new Map();
|
|
1933
1962
|
this.apiKey = config.apiKey.trim();
|
|
1934
1963
|
this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
|
|
1935
1964
|
this.piiMasking = Boolean(config.piiMasking);
|
|
@@ -1958,6 +1987,60 @@ var AgentID = class {
|
|
|
1958
1987
|
}
|
|
1959
1988
|
return this.apiKey;
|
|
1960
1989
|
}
|
|
1990
|
+
resolveClientEventId(requestBody) {
|
|
1991
|
+
const directClientEventId = requestBody.client_event_id;
|
|
1992
|
+
if (typeof directClientEventId === "string" && isUuidLike(directClientEventId)) {
|
|
1993
|
+
return directClientEventId;
|
|
1994
|
+
}
|
|
1995
|
+
const metadata = requestBody.metadata;
|
|
1996
|
+
if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
|
|
1997
|
+
const metadataClientEventId = metadata.client_event_id;
|
|
1998
|
+
if (typeof metadataClientEventId === "string" && isUuidLike(metadataClientEventId)) {
|
|
1999
|
+
return metadataClientEventId;
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
const cached = this.requestClientEventIds.get(requestBody);
|
|
2003
|
+
if (cached) {
|
|
2004
|
+
return cached;
|
|
2005
|
+
}
|
|
2006
|
+
const generated = createEventId();
|
|
2007
|
+
this.requestClientEventIds.set(requestBody, generated);
|
|
2008
|
+
return generated;
|
|
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
|
+
}
|
|
1961
2044
|
async getCapabilityConfig(force = false, options) {
|
|
1962
2045
|
const effectiveApiKey = this.resolveApiKey(options?.apiKey);
|
|
1963
2046
|
return ensureCapabilityConfig({
|
|
@@ -2115,6 +2198,11 @@ var AgentID = class {
|
|
|
2115
2198
|
...params,
|
|
2116
2199
|
client_capabilities: params.client_capabilities ?? this.buildClientCapabilities()
|
|
2117
2200
|
};
|
|
2201
|
+
const guardCacheKey = this.buildGuardCacheKey(payload);
|
|
2202
|
+
const cachedVerdict = this.readCachedGuardVerdict(guardCacheKey);
|
|
2203
|
+
if (cachedVerdict) {
|
|
2204
|
+
return cachedVerdict;
|
|
2205
|
+
}
|
|
2118
2206
|
const correlationId = createCorrelationId(payload.client_event_id);
|
|
2119
2207
|
let lastStatusCode = null;
|
|
2120
2208
|
let lastAbort = false;
|
|
@@ -2161,6 +2249,7 @@ var AgentID = class {
|
|
|
2161
2249
|
});
|
|
2162
2250
|
return { allowed: true, reason: "system_failure_fail_open" };
|
|
2163
2251
|
}
|
|
2252
|
+
this.cacheGuardVerdict(guardCacheKey, verdict);
|
|
2164
2253
|
return verdict;
|
|
2165
2254
|
}
|
|
2166
2255
|
if (!res.ok) {
|
|
@@ -2234,6 +2323,59 @@ var AgentID = class {
|
|
|
2234
2323
|
}
|
|
2235
2324
|
return { allowed: true, reason: "guard_unreachable" };
|
|
2236
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
|
+
}
|
|
2237
2379
|
extractStreamChunkText(chunk) {
|
|
2238
2380
|
if (typeof chunk === "string") {
|
|
2239
2381
|
return chunk;
|
|
@@ -2335,35 +2477,11 @@ var AgentID = class {
|
|
|
2335
2477
|
log(params, options) {
|
|
2336
2478
|
queueMicrotask(() => {
|
|
2337
2479
|
void (async () => {
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
const metadata = {
|
|
2344
|
-
...params.metadata ?? {}
|
|
2345
|
-
};
|
|
2346
|
-
if (!Object.prototype.hasOwnProperty.call(metadata, "agentid_base_url")) {
|
|
2347
|
-
metadata.agentid_base_url = this.baseUrl;
|
|
2348
|
-
}
|
|
2349
|
-
await fetch(`${this.baseUrl}/ingest`, {
|
|
2350
|
-
method: "POST",
|
|
2351
|
-
keepalive: true,
|
|
2352
|
-
headers: {
|
|
2353
|
-
"Content-Type": "application/json",
|
|
2354
|
-
"x-agentid-api-key": effectiveApiKey,
|
|
2355
|
-
"X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER2
|
|
2356
|
-
},
|
|
2357
|
-
body: JSON.stringify({
|
|
2358
|
-
...params,
|
|
2359
|
-
event_id: eventId,
|
|
2360
|
-
timestamp,
|
|
2361
|
-
metadata,
|
|
2362
|
-
client_capabilities: params.client_capabilities ?? this.buildClientCapabilities()
|
|
2363
|
-
})
|
|
2364
|
-
});
|
|
2365
|
-
} catch (error) {
|
|
2366
|
-
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
|
+
);
|
|
2367
2485
|
}
|
|
2368
2486
|
})();
|
|
2369
2487
|
});
|
|
@@ -2463,7 +2581,7 @@ var AgentID = class {
|
|
|
2463
2581
|
"AgentID: No user message found. Security guard requires string input."
|
|
2464
2582
|
);
|
|
2465
2583
|
}
|
|
2466
|
-
const clientEventId =
|
|
2584
|
+
const clientEventId = this.resolveClientEventId(req);
|
|
2467
2585
|
const verdict = await this.guard({
|
|
2468
2586
|
input: maskedText,
|
|
2469
2587
|
system_id: systemId,
|
|
@@ -2477,6 +2595,8 @@ var AgentID = class {
|
|
|
2477
2595
|
`AgentID: Security Blocked (${verdict.reason ?? "guard_denied"})`
|
|
2478
2596
|
);
|
|
2479
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;
|
|
2480
2600
|
const isShadowMode = verdict.shadow_mode === true;
|
|
2481
2601
|
const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
|
|
2482
2602
|
if (transformedInput !== maskedText) {
|
|
@@ -2499,10 +2619,10 @@ var AgentID = class {
|
|
|
2499
2619
|
})()
|
|
2500
2620
|
);
|
|
2501
2621
|
if (maskedText && wrappedCompletion.mode === "stream") {
|
|
2502
|
-
void wrappedCompletion.done.then((result) => {
|
|
2622
|
+
void wrappedCompletion.done.then(async (result) => {
|
|
2503
2623
|
const outputForLog = isShadowMode ? result.rawOutput : result.transformedOutput;
|
|
2504
|
-
this.
|
|
2505
|
-
event_id:
|
|
2624
|
+
const ingestResult = await this.sendIngest({
|
|
2625
|
+
event_id: canonicalClientEventId,
|
|
2506
2626
|
system_id: systemId,
|
|
2507
2627
|
user_id: options.user_id,
|
|
2508
2628
|
input: maskedText,
|
|
@@ -2510,6 +2630,7 @@ var AgentID = class {
|
|
|
2510
2630
|
model: adapter.getModelName(maskedReq),
|
|
2511
2631
|
usage: void 0,
|
|
2512
2632
|
latency: void 0,
|
|
2633
|
+
event_type: "complete",
|
|
2513
2634
|
metadata: {
|
|
2514
2635
|
transformed_input: maskedText,
|
|
2515
2636
|
transformed_output: result.transformedOutput,
|
|
@@ -2517,10 +2638,17 @@ var AgentID = class {
|
|
|
2517
2638
|
shadow_mode: isShadowMode,
|
|
2518
2639
|
simulated_decision: verdict.simulated_decision ?? null,
|
|
2519
2640
|
simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
|
|
2520
|
-
response_streamed: true
|
|
2641
|
+
response_streamed: true,
|
|
2642
|
+
guard_event_id: guardEventId,
|
|
2643
|
+
client_event_id: canonicalClientEventId
|
|
2521
2644
|
},
|
|
2522
2645
|
client_capabilities: this.buildClientCapabilities("openai", false)
|
|
2523
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
|
+
}
|
|
2524
2652
|
}).catch((error) => {
|
|
2525
2653
|
console.error("[AgentID] Stream completion wrapping failed:", error);
|
|
2526
2654
|
});
|
|
@@ -2536,8 +2664,8 @@ var AgentID = class {
|
|
|
2536
2664
|
const model = adapter.getModelName(maskedReq, res);
|
|
2537
2665
|
const usage = adapter.getTokenUsage(res);
|
|
2538
2666
|
const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
|
|
2539
|
-
this.
|
|
2540
|
-
event_id:
|
|
2667
|
+
const ingestResult = await this.sendIngest({
|
|
2668
|
+
event_id: canonicalClientEventId,
|
|
2541
2669
|
system_id: systemId,
|
|
2542
2670
|
user_id: options.user_id,
|
|
2543
2671
|
input: maskedText,
|
|
@@ -2545,6 +2673,7 @@ var AgentID = class {
|
|
|
2545
2673
|
model,
|
|
2546
2674
|
usage,
|
|
2547
2675
|
latency,
|
|
2676
|
+
event_type: "complete",
|
|
2548
2677
|
metadata: {
|
|
2549
2678
|
transformed_input: maskedText,
|
|
2550
2679
|
transformed_output: wrappedCompletion.transformedOutput,
|
|
@@ -2552,10 +2681,17 @@ var AgentID = class {
|
|
|
2552
2681
|
shadow_mode: isShadowMode,
|
|
2553
2682
|
simulated_decision: verdict.simulated_decision ?? null,
|
|
2554
2683
|
simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
|
|
2555
|
-
response_streamed: false
|
|
2684
|
+
response_streamed: false,
|
|
2685
|
+
guard_event_id: guardEventId,
|
|
2686
|
+
client_event_id: canonicalClientEventId
|
|
2556
2687
|
},
|
|
2557
2688
|
client_capabilities: this.buildClientCapabilities("openai", false)
|
|
2558
2689
|
}, requestOptions);
|
|
2690
|
+
if (!ingestResult.ok) {
|
|
2691
|
+
console.warn(
|
|
2692
|
+
`[AgentID] Ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
|
|
2693
|
+
);
|
|
2694
|
+
}
|
|
2559
2695
|
}
|
|
2560
2696
|
if (!capabilityConfig.block_pii_leakage && this.piiMasking && shouldDeanonymize) {
|
|
2561
2697
|
const deanon = this.pii.deanonymize(adapter.extractOutput(res), mapping);
|
|
@@ -82,9 +82,15 @@ declare class AgentID {
|
|
|
82
82
|
private pii;
|
|
83
83
|
private localEnforcer;
|
|
84
84
|
private injectionScanner;
|
|
85
|
+
private requestClientEventIds;
|
|
86
|
+
private recentGuardVerdicts;
|
|
85
87
|
constructor(config: AgentIDConfig);
|
|
86
88
|
private buildClientCapabilities;
|
|
87
89
|
private resolveApiKey;
|
|
90
|
+
private resolveClientEventId;
|
|
91
|
+
private buildGuardCacheKey;
|
|
92
|
+
private readCachedGuardVerdict;
|
|
93
|
+
private cacheGuardVerdict;
|
|
88
94
|
getCapabilityConfig(force?: boolean, options?: RequestOptions): Promise<CapabilityConfig>;
|
|
89
95
|
private getCachedCapabilityConfig;
|
|
90
96
|
prepareInputForDispatch(params: {
|
|
@@ -103,6 +109,7 @@ declare class AgentID {
|
|
|
103
109
|
* strictMode=true: FAIL-CLOSED and throws on connectivity/timeouts.
|
|
104
110
|
*/
|
|
105
111
|
guard(params: GuardParams, options?: RequestOptions): Promise<GuardResponse>;
|
|
112
|
+
private sendIngest;
|
|
106
113
|
private extractStreamChunkText;
|
|
107
114
|
private wrapCompletion;
|
|
108
115
|
/**
|
|
@@ -82,9 +82,15 @@ declare class AgentID {
|
|
|
82
82
|
private pii;
|
|
83
83
|
private localEnforcer;
|
|
84
84
|
private injectionScanner;
|
|
85
|
+
private requestClientEventIds;
|
|
86
|
+
private recentGuardVerdicts;
|
|
85
87
|
constructor(config: AgentIDConfig);
|
|
86
88
|
private buildClientCapabilities;
|
|
87
89
|
private resolveApiKey;
|
|
90
|
+
private resolveClientEventId;
|
|
91
|
+
private buildGuardCacheKey;
|
|
92
|
+
private readCachedGuardVerdict;
|
|
93
|
+
private cacheGuardVerdict;
|
|
88
94
|
getCapabilityConfig(force?: boolean, options?: RequestOptions): Promise<CapabilityConfig>;
|
|
89
95
|
private getCachedCapabilityConfig;
|
|
90
96
|
prepareInputForDispatch(params: {
|
|
@@ -103,6 +109,7 @@ declare class AgentID {
|
|
|
103
109
|
* strictMode=true: FAIL-CLOSED and throws on connectivity/timeouts.
|
|
104
110
|
*/
|
|
105
111
|
guard(params: GuardParams, options?: RequestOptions): Promise<GuardResponse>;
|
|
112
|
+
private sendIngest;
|
|
106
113
|
private extractStreamChunkText;
|
|
107
114
|
private wrapCompletion;
|
|
108
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';
|