agentid-sdk 0.1.24 → 0.1.26
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/README.md +28 -5
- package/dist/{agentid-BGCUoYV7.d.mts → agentid-DviYzyAM.d.mts} +49 -4
- package/dist/{agentid-BGCUoYV7.d.ts → agentid-DviYzyAM.d.ts} +49 -4
- package/dist/{chunk-JLHAS2EE.mjs → chunk-JIQGHFHI.mjs} +493 -54
- package/dist/index.d.mts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +496 -56
- package/dist/index.mjs +3 -1
- package/dist/langchain.d.mts +4 -1
- package/dist/langchain.d.ts +4 -1
- package/dist/langchain.js +111 -20
- package/dist/langchain.mjs +111 -20
- package/package.json +1 -1
|
@@ -1149,6 +1149,79 @@ var PIIManager = class {
|
|
|
1149
1149
|
}
|
|
1150
1150
|
};
|
|
1151
1151
|
|
|
1152
|
+
// src/context-intent.ts
|
|
1153
|
+
var EDUCATIONAL_MARKERS = [
|
|
1154
|
+
"explain",
|
|
1155
|
+
"analysis",
|
|
1156
|
+
"analyze",
|
|
1157
|
+
"analyse",
|
|
1158
|
+
"review",
|
|
1159
|
+
"summarize",
|
|
1160
|
+
"summarise",
|
|
1161
|
+
"summary",
|
|
1162
|
+
"plain-language explanation",
|
|
1163
|
+
"red flags",
|
|
1164
|
+
"security workshop",
|
|
1165
|
+
"training",
|
|
1166
|
+
"lesson",
|
|
1167
|
+
"quoted attack",
|
|
1168
|
+
"quoted example",
|
|
1169
|
+
"attack example",
|
|
1170
|
+
"security event",
|
|
1171
|
+
"security log",
|
|
1172
|
+
"audit log",
|
|
1173
|
+
"incident report",
|
|
1174
|
+
"trace timeline"
|
|
1175
|
+
];
|
|
1176
|
+
var WARNING_MARKERS = [
|
|
1177
|
+
"dangerous",
|
|
1178
|
+
"risky",
|
|
1179
|
+
"risk",
|
|
1180
|
+
"warning",
|
|
1181
|
+
"warn",
|
|
1182
|
+
"malicious",
|
|
1183
|
+
"security indicator",
|
|
1184
|
+
"red flags"
|
|
1185
|
+
];
|
|
1186
|
+
var NON_EXECUTION_MARKERS = [
|
|
1187
|
+
"do not execute",
|
|
1188
|
+
"do not run",
|
|
1189
|
+
"do not return commands",
|
|
1190
|
+
"do not output commands",
|
|
1191
|
+
"do not provide executable steps",
|
|
1192
|
+
"for explanation only",
|
|
1193
|
+
"non-executable"
|
|
1194
|
+
];
|
|
1195
|
+
function normalizeIntentInput(input) {
|
|
1196
|
+
return input.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/\s+/g, " ").trim();
|
|
1197
|
+
}
|
|
1198
|
+
function hasAnyMarker(input, markers) {
|
|
1199
|
+
return markers.some((marker) => input.includes(marker));
|
|
1200
|
+
}
|
|
1201
|
+
function classifyInjectionContextIntent(input) {
|
|
1202
|
+
const normalized = normalizeIntentInput(input ?? "");
|
|
1203
|
+
if (!normalized) {
|
|
1204
|
+
return {
|
|
1205
|
+
educational: false,
|
|
1206
|
+
quotedExample: false,
|
|
1207
|
+
warningOnly: false,
|
|
1208
|
+
nonExecutableConstraint: false,
|
|
1209
|
+
promptInjectionExempt: false
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
const educational = hasAnyMarker(normalized, EDUCATIONAL_MARKERS);
|
|
1213
|
+
const warningOnly = hasAnyMarker(normalized, WARNING_MARKERS);
|
|
1214
|
+
const nonExecutableConstraint = hasAnyMarker(normalized, NON_EXECUTION_MARKERS);
|
|
1215
|
+
const quotedExample = /["'`]/.test(input) || normalized.includes("quoted") || normalized.includes("quote") || normalized.includes("phrase") || normalized.includes("attack example");
|
|
1216
|
+
return {
|
|
1217
|
+
educational,
|
|
1218
|
+
quotedExample,
|
|
1219
|
+
warningOnly,
|
|
1220
|
+
nonExecutableConstraint,
|
|
1221
|
+
promptInjectionExempt: educational && (quotedExample || warningOnly || nonExecutableConstraint || normalized.includes("prompt injection indicator") || normalized.includes("jailbreak prompt"))
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1152
1225
|
// src/security.ts
|
|
1153
1226
|
var MAX_ANALYSIS_WINDOW = 8192;
|
|
1154
1227
|
var WINDOW_SLICE_SIZE = 4e3;
|
|
@@ -1156,6 +1229,7 @@ var WORD_BOUNDARY_SCAN = 120;
|
|
|
1156
1229
|
var AI_TIMEOUT_MS = 2e3;
|
|
1157
1230
|
var TELEMETRY_SNIPPET_LIMIT = 4e3;
|
|
1158
1231
|
var AI_OPENAI_MODEL = "gpt-4o-mini";
|
|
1232
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
1159
1233
|
var EN_STOPWORDS = /* @__PURE__ */ new Set([
|
|
1160
1234
|
"the",
|
|
1161
1235
|
"and",
|
|
@@ -1203,6 +1277,25 @@ var piiSingleton = null;
|
|
|
1203
1277
|
function normalizeBaseUrl(baseUrl) {
|
|
1204
1278
|
return (baseUrl || "").replace(/\/+$/, "");
|
|
1205
1279
|
}
|
|
1280
|
+
function createPseudoUuidV4() {
|
|
1281
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
|
|
1282
|
+
const random = Math.floor(Math.random() * 16);
|
|
1283
|
+
const nibble = char === "x" ? random : random & 3 | 8;
|
|
1284
|
+
return nibble.toString(16);
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
function isUuidLike(value) {
|
|
1288
|
+
return typeof value === "string" && UUID_RE.test(value);
|
|
1289
|
+
}
|
|
1290
|
+
function createEventId(seed) {
|
|
1291
|
+
if (isUuidLike(seed)) {
|
|
1292
|
+
return seed;
|
|
1293
|
+
}
|
|
1294
|
+
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
1295
|
+
return globalThis.crypto.randomUUID();
|
|
1296
|
+
}
|
|
1297
|
+
return createPseudoUuidV4();
|
|
1298
|
+
}
|
|
1206
1299
|
function getSharedPIIManager() {
|
|
1207
1300
|
if (!piiSingleton) {
|
|
1208
1301
|
piiSingleton = new PIIManager();
|
|
@@ -1291,6 +1384,10 @@ function findRegexMatch(prompt) {
|
|
|
1291
1384
|
if (!prompt) {
|
|
1292
1385
|
return null;
|
|
1293
1386
|
}
|
|
1387
|
+
const contextIntent = classifyInjectionContextIntent(prompt);
|
|
1388
|
+
if (contextIntent.promptInjectionExempt) {
|
|
1389
|
+
return null;
|
|
1390
|
+
}
|
|
1294
1391
|
const normalizedPrompt = normalizeForHeuristics(prompt);
|
|
1295
1392
|
for (const rule of HEURISTIC_RULES) {
|
|
1296
1393
|
try {
|
|
@@ -1416,13 +1513,16 @@ async function reportSecurityEvent(options) {
|
|
|
1416
1513
|
const snippet = truncateSnippet(options.snippet);
|
|
1417
1514
|
const snippetHash = snippet ? await sha256Hex(snippet) : "";
|
|
1418
1515
|
const inputValue = options.storePii ? snippet : snippetHash;
|
|
1516
|
+
const eventId = createEventId(options.eventId ?? options.clientEventId);
|
|
1419
1517
|
const metadata = {
|
|
1420
1518
|
source: options.source,
|
|
1421
1519
|
detector: options.detector,
|
|
1422
1520
|
trigger_rule: options.triggerRule,
|
|
1423
1521
|
language: options.language,
|
|
1424
1522
|
ai_scan_status: options.aiStatus ?? null,
|
|
1425
|
-
reason: options.reason ?? null
|
|
1523
|
+
reason: options.reason ?? null,
|
|
1524
|
+
client_event_id: eventId,
|
|
1525
|
+
...options.telemetryMetadata ?? {}
|
|
1426
1526
|
};
|
|
1427
1527
|
if (options.storePii) {
|
|
1428
1528
|
metadata.snippet = snippet;
|
|
@@ -1430,11 +1530,14 @@ async function reportSecurityEvent(options) {
|
|
|
1430
1530
|
metadata.snippet_hash = snippetHash;
|
|
1431
1531
|
}
|
|
1432
1532
|
const payload = {
|
|
1533
|
+
event_id: eventId,
|
|
1534
|
+
system_id: options.systemId,
|
|
1433
1535
|
input: inputValue,
|
|
1434
1536
|
output: "",
|
|
1435
1537
|
model: "agentid.local_injection_scanner",
|
|
1436
1538
|
event_type: options.outcome === "blocked" ? "security_block" : "security_alert",
|
|
1437
1539
|
severity: options.outcome === "blocked" ? "error" : "warning",
|
|
1540
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1438
1541
|
metadata
|
|
1439
1542
|
};
|
|
1440
1543
|
void fetch(`${normalizeBaseUrl(options.baseUrl)}/ingest`, {
|
|
@@ -1464,7 +1567,11 @@ var InjectionScanner = class _InjectionScanner {
|
|
|
1464
1567
|
aiScanEnabled: options?.aiScanEnabled,
|
|
1465
1568
|
storePii: options?.storePii,
|
|
1466
1569
|
piiManager: options?.piiManager,
|
|
1467
|
-
source: options?.source
|
|
1570
|
+
source: options?.source,
|
|
1571
|
+
systemId: options?.systemId,
|
|
1572
|
+
eventId: options?.eventId,
|
|
1573
|
+
clientEventId: options?.clientEventId,
|
|
1574
|
+
telemetryMetadata: options?.telemetryMetadata
|
|
1468
1575
|
});
|
|
1469
1576
|
}
|
|
1470
1577
|
async scan(params) {
|
|
@@ -1476,6 +1583,11 @@ var InjectionScanner = class _InjectionScanner {
|
|
|
1476
1583
|
const storePii = params.storePii === true;
|
|
1477
1584
|
const aiScanEnabled = params.aiScanEnabled !== false;
|
|
1478
1585
|
const language = detectLanguageTag(prompt);
|
|
1586
|
+
const scanStartedAt = Date.now();
|
|
1587
|
+
const buildTelemetryMetadata = () => ({
|
|
1588
|
+
...params.telemetryMetadata ?? {},
|
|
1589
|
+
sdk_local_scan_ms: Math.max(0, Date.now() - scanStartedAt)
|
|
1590
|
+
});
|
|
1479
1591
|
const regexMatch = findRegexMatch(prompt);
|
|
1480
1592
|
if (regexMatch) {
|
|
1481
1593
|
await reportSecurityEvent({
|
|
@@ -1487,7 +1599,11 @@ var InjectionScanner = class _InjectionScanner {
|
|
|
1487
1599
|
triggerRule: regexMatch.rule,
|
|
1488
1600
|
snippet: regexMatch.snippet,
|
|
1489
1601
|
storePii,
|
|
1490
|
-
language
|
|
1602
|
+
language,
|
|
1603
|
+
systemId: params.systemId,
|
|
1604
|
+
eventId: params.eventId,
|
|
1605
|
+
clientEventId: params.clientEventId,
|
|
1606
|
+
telemetryMetadata: buildTelemetryMetadata()
|
|
1491
1607
|
});
|
|
1492
1608
|
throw new Error(`AgentID: Prompt injection blocked (${regexMatch.rule})`);
|
|
1493
1609
|
}
|
|
@@ -1508,7 +1624,11 @@ var InjectionScanner = class _InjectionScanner {
|
|
|
1508
1624
|
storePii,
|
|
1509
1625
|
language,
|
|
1510
1626
|
aiStatus: "skipped",
|
|
1511
|
-
reason: "ai_scan_disabled_for_high_risk_language"
|
|
1627
|
+
reason: "ai_scan_disabled_for_high_risk_language",
|
|
1628
|
+
systemId: params.systemId,
|
|
1629
|
+
eventId: params.eventId,
|
|
1630
|
+
clientEventId: params.clientEventId,
|
|
1631
|
+
telemetryMetadata: buildTelemetryMetadata()
|
|
1512
1632
|
});
|
|
1513
1633
|
return;
|
|
1514
1634
|
}
|
|
@@ -1527,7 +1647,11 @@ var InjectionScanner = class _InjectionScanner {
|
|
|
1527
1647
|
storePii,
|
|
1528
1648
|
language,
|
|
1529
1649
|
aiStatus: aiResult.status,
|
|
1530
|
-
reason: aiResult.reason
|
|
1650
|
+
reason: aiResult.reason,
|
|
1651
|
+
systemId: params.systemId,
|
|
1652
|
+
eventId: params.eventId,
|
|
1653
|
+
clientEventId: params.clientEventId,
|
|
1654
|
+
telemetryMetadata: buildTelemetryMetadata()
|
|
1531
1655
|
});
|
|
1532
1656
|
return;
|
|
1533
1657
|
}
|
|
@@ -1543,7 +1667,11 @@ var InjectionScanner = class _InjectionScanner {
|
|
|
1543
1667
|
storePii,
|
|
1544
1668
|
language,
|
|
1545
1669
|
aiStatus: aiResult.status,
|
|
1546
|
-
reason: aiResult.reason
|
|
1670
|
+
reason: aiResult.reason,
|
|
1671
|
+
systemId: params.systemId,
|
|
1672
|
+
eventId: params.eventId,
|
|
1673
|
+
clientEventId: params.clientEventId,
|
|
1674
|
+
telemetryMetadata: buildTelemetryMetadata()
|
|
1547
1675
|
});
|
|
1548
1676
|
throw new Error(`AgentID: Prompt injection blocked (${aiResult.reason})`);
|
|
1549
1677
|
}
|
|
@@ -1555,7 +1683,7 @@ function getInjectionScanner() {
|
|
|
1555
1683
|
|
|
1556
1684
|
// src/sdk-version.ts
|
|
1557
1685
|
var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
|
|
1558
|
-
var AGENTID_SDK_VERSION_HEADER = "js-0.1.
|
|
1686
|
+
var AGENTID_SDK_VERSION_HEADER = "js-0.1.26".trim().length > 0 ? "js-0.1.26" : FALLBACK_SDK_VERSION;
|
|
1559
1687
|
|
|
1560
1688
|
// src/local-security-enforcer.ts
|
|
1561
1689
|
var DEFAULT_FAIL_OPEN_CONFIG = {
|
|
@@ -1565,6 +1693,7 @@ var DEFAULT_FAIL_OPEN_CONFIG = {
|
|
|
1565
1693
|
block_on_heuristic: false,
|
|
1566
1694
|
inject_transparency_metadata: false,
|
|
1567
1695
|
block_pii_leakage: false,
|
|
1696
|
+
enable_sdk_pii_masking: false,
|
|
1568
1697
|
block_db_access: false,
|
|
1569
1698
|
block_code_execution: false,
|
|
1570
1699
|
block_toxicity: false
|
|
@@ -1667,8 +1796,8 @@ var LocalSecurityEnforcer = class {
|
|
|
1667
1796
|
|
|
1668
1797
|
// src/capability-config.ts
|
|
1669
1798
|
var CONFIG_TTL_MS = 5 * 60 * 1e3;
|
|
1670
|
-
var CONFIG_TIMEOUT_MS =
|
|
1671
|
-
var CONFIG_RETRY_DELAY_MS =
|
|
1799
|
+
var CONFIG_TIMEOUT_MS = 1500;
|
|
1800
|
+
var CONFIG_RETRY_DELAY_MS = 150;
|
|
1672
1801
|
var MAX_CAPABILITY_CACHE_ENTRIES = 500;
|
|
1673
1802
|
var CapabilityConfigFetchError = class extends Error {
|
|
1674
1803
|
constructor(message, params) {
|
|
@@ -1752,6 +1881,11 @@ function normalizeCapabilityConfig(payload) {
|
|
|
1752
1881
|
false
|
|
1753
1882
|
),
|
|
1754
1883
|
block_pii_leakage: readBooleanField(body, "block_pii_leakage", "block_pii"),
|
|
1884
|
+
enable_sdk_pii_masking: readOptionalBooleanField(
|
|
1885
|
+
body,
|
|
1886
|
+
"enable_sdk_pii_masking",
|
|
1887
|
+
false
|
|
1888
|
+
),
|
|
1755
1889
|
block_db_access: readBooleanField(body, "block_db_access", "block_db"),
|
|
1756
1890
|
block_code_execution: readBooleanField(
|
|
1757
1891
|
body,
|
|
@@ -2004,6 +2138,19 @@ function normalizeIngestTimeoutMs(value) {
|
|
|
2004
2138
|
}
|
|
2005
2139
|
return rounded;
|
|
2006
2140
|
}
|
|
2141
|
+
function setFiniteDurationMetadata(metadata, key, value) {
|
|
2142
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2143
|
+
metadata[key] = Math.max(0, Math.trunc(value));
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
function buildSdkTimingMetadata(params) {
|
|
2147
|
+
const metadata = {};
|
|
2148
|
+
setFiniteDurationMetadata(metadata, "sdk_config_fetch_ms", params.sdkConfigFetchMs);
|
|
2149
|
+
setFiniteDurationMetadata(metadata, "sdk_local_scan_ms", params.sdkLocalScanMs);
|
|
2150
|
+
setFiniteDurationMetadata(metadata, "sdk_guard_ms", params.sdkGuardMs);
|
|
2151
|
+
setFiniteDurationMetadata(metadata, "sdk_ingest_ms", params.sdkIngestMs);
|
|
2152
|
+
return metadata;
|
|
2153
|
+
}
|
|
2007
2154
|
function resolveConfiguredApiKey(value) {
|
|
2008
2155
|
const explicit = typeof value === "string" ? value.trim() : "";
|
|
2009
2156
|
const fromEnv = globalThis.process?.env?.AGENTID_API_KEY ?? "";
|
|
@@ -2017,13 +2164,32 @@ function isInfrastructureGuardReason(reason) {
|
|
|
2017
2164
|
if (!reason) return false;
|
|
2018
2165
|
return reason === "system_failure" || reason === "system_failure_db_unavailable" || reason === "logging_failed" || reason === "server_error" || reason === "guard_unreachable" || reason === "api_key_pepper_missing" || reason === "encryption_key_missing";
|
|
2019
2166
|
}
|
|
2020
|
-
function
|
|
2167
|
+
function isGuardFailureEligibleForLocalFallback(reason) {
|
|
2168
|
+
return reason === "network_error_strict_mode" || reason === "server_error" || isInfrastructureGuardReason(reason);
|
|
2169
|
+
}
|
|
2170
|
+
function isFailCloseIngestReason(reason) {
|
|
2171
|
+
if (!reason) return false;
|
|
2172
|
+
return reason === "system_failure" || reason === "system_failure_db_unavailable" || reason === "server_error" || reason === "redis_rate_limit_unavailable" || reason === "redis_quota_unavailable" || reason === "redis_token_quota_unavailable";
|
|
2173
|
+
}
|
|
2174
|
+
function shouldEscalateIngestFailure(params) {
|
|
2175
|
+
if (!params.strictMode) {
|
|
2176
|
+
return false;
|
|
2177
|
+
}
|
|
2178
|
+
if (params.status === null) {
|
|
2179
|
+
return true;
|
|
2180
|
+
}
|
|
2181
|
+
if (params.status >= 500) {
|
|
2182
|
+
return true;
|
|
2183
|
+
}
|
|
2184
|
+
return isFailCloseIngestReason(params.reason);
|
|
2185
|
+
}
|
|
2186
|
+
function isUuidLike2(value) {
|
|
2021
2187
|
if (!value) return false;
|
|
2022
2188
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(
|
|
2023
2189
|
value
|
|
2024
2190
|
);
|
|
2025
2191
|
}
|
|
2026
|
-
function
|
|
2192
|
+
function createPseudoUuidV42() {
|
|
2027
2193
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (token) => {
|
|
2028
2194
|
const rand = Math.floor(Math.random() * 16);
|
|
2029
2195
|
const value = token === "x" ? rand : rand & 3 | 8;
|
|
@@ -2034,19 +2200,28 @@ function sanitizeIngestText(value) {
|
|
|
2034
2200
|
const text = typeof value === "string" ? value : String(value ?? "");
|
|
2035
2201
|
return text.slice(0, MAX_INGEST_TEXT_CHARS);
|
|
2036
2202
|
}
|
|
2037
|
-
function
|
|
2038
|
-
if (
|
|
2203
|
+
function normalizeExpectedLanguages(value) {
|
|
2204
|
+
if (!Array.isArray(value)) {
|
|
2205
|
+
return void 0;
|
|
2206
|
+
}
|
|
2207
|
+
const normalized = [...new Set(
|
|
2208
|
+
value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0)
|
|
2209
|
+
)];
|
|
2210
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
2211
|
+
}
|
|
2212
|
+
function createEventId2(seed) {
|
|
2213
|
+
if (isUuidLike2(seed)) return seed;
|
|
2039
2214
|
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
2040
2215
|
return globalThis.crypto.randomUUID();
|
|
2041
2216
|
}
|
|
2042
|
-
return
|
|
2217
|
+
return createPseudoUuidV42();
|
|
2043
2218
|
}
|
|
2044
2219
|
function createCorrelationId(seed) {
|
|
2045
|
-
if (
|
|
2220
|
+
if (isUuidLike2(seed)) return seed;
|
|
2046
2221
|
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
2047
2222
|
return globalThis.crypto.randomUUID();
|
|
2048
2223
|
}
|
|
2049
|
-
return
|
|
2224
|
+
return createPseudoUuidV42();
|
|
2050
2225
|
}
|
|
2051
2226
|
async function waitForRetry(attemptIndex) {
|
|
2052
2227
|
const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
|
|
@@ -2183,28 +2358,60 @@ var SecurityBlockError = class extends Error {
|
|
|
2183
2358
|
this.reason = reason;
|
|
2184
2359
|
}
|
|
2185
2360
|
};
|
|
2361
|
+
var DependencyError = class extends Error {
|
|
2362
|
+
constructor(params) {
|
|
2363
|
+
const statusLabel = typeof params.status === "number" ? String(params.status) : "network";
|
|
2364
|
+
super(`AgentID dependency failure (${params.dependency}): ${params.reason} [${statusLabel}]`);
|
|
2365
|
+
this.name = "DependencyError";
|
|
2366
|
+
this.dependency = params.dependency;
|
|
2367
|
+
this.reason = params.reason;
|
|
2368
|
+
this.status = params.status;
|
|
2369
|
+
}
|
|
2370
|
+
};
|
|
2186
2371
|
var AgentID = class {
|
|
2187
2372
|
constructor(config = {}) {
|
|
2188
2373
|
this.injectionScanner = getInjectionScanner();
|
|
2189
2374
|
this.recentGuardVerdicts = /* @__PURE__ */ new Map();
|
|
2190
2375
|
this.apiKey = resolveConfiguredApiKey(config.apiKey);
|
|
2191
2376
|
this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
|
|
2192
|
-
this.
|
|
2377
|
+
this.configuredPiiMasking = typeof config.piiMasking === "boolean" ? config.piiMasking : null;
|
|
2193
2378
|
this.checkInjection = config.checkInjection !== false;
|
|
2379
|
+
this.clientFastFail = config.clientFastFail === true || config.client_fast_fail === true;
|
|
2194
2380
|
this.aiScanEnabled = config.aiScanEnabled !== false;
|
|
2195
2381
|
this.storePii = config.storePii === true;
|
|
2196
2382
|
this.strictMode = config.strictMode === true;
|
|
2383
|
+
if (typeof config.failureMode !== "undefined" && config.failureMode !== "fail_open" && config.failureMode !== "fail_close") {
|
|
2384
|
+
throw new Error("AgentID invalid failureMode. Use 'fail_open' or 'fail_close'.");
|
|
2385
|
+
}
|
|
2386
|
+
if (this.strictMode && config.failureMode === "fail_open") {
|
|
2387
|
+
throw new Error("AgentID strictMode=true conflicts with failureMode='fail_open'.");
|
|
2388
|
+
}
|
|
2389
|
+
this.configuredFailureMode = this.strictMode ? "fail_close" : config.failureMode ?? null;
|
|
2197
2390
|
this.guardTimeoutMs = normalizeGuardTimeoutMs(config.guardTimeoutMs);
|
|
2198
2391
|
this.ingestTimeoutMs = normalizeIngestTimeoutMs(config.ingestTimeoutMs);
|
|
2199
2392
|
this.pii = new PIIManager();
|
|
2200
2393
|
this.localEnforcer = new LocalSecurityEnforcer(this.pii);
|
|
2201
2394
|
void this.getCapabilityConfig();
|
|
2202
2395
|
}
|
|
2203
|
-
|
|
2396
|
+
get piiMasking() {
|
|
2397
|
+
return this.configuredPiiMasking ?? void 0;
|
|
2398
|
+
}
|
|
2399
|
+
resolveEffectivePiiMasking(config) {
|
|
2400
|
+
if (this.configuredPiiMasking !== null) {
|
|
2401
|
+
return this.configuredPiiMasking;
|
|
2402
|
+
}
|
|
2403
|
+
return config?.enable_sdk_pii_masking === true;
|
|
2404
|
+
}
|
|
2405
|
+
getEffectivePiiMasking(options) {
|
|
2406
|
+
return this.resolveEffectivePiiMasking(this.getCachedCapabilityConfig(options));
|
|
2407
|
+
}
|
|
2408
|
+
buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig) {
|
|
2204
2409
|
return {
|
|
2205
2410
|
capabilities: {
|
|
2206
2411
|
has_feedback_handler: hasFeedbackHandler,
|
|
2207
|
-
pii_masking_enabled: this.
|
|
2412
|
+
pii_masking_enabled: this.resolveEffectivePiiMasking(
|
|
2413
|
+
capabilityConfig ?? this.getCachedCapabilityConfig()
|
|
2414
|
+
),
|
|
2208
2415
|
framework
|
|
2209
2416
|
}
|
|
2210
2417
|
};
|
|
@@ -2218,17 +2425,17 @@ var AgentID = class {
|
|
|
2218
2425
|
}
|
|
2219
2426
|
resolveClientEventId(requestBody) {
|
|
2220
2427
|
const directClientEventId = requestBody.client_event_id;
|
|
2221
|
-
if (typeof directClientEventId === "string" &&
|
|
2428
|
+
if (typeof directClientEventId === "string" && isUuidLike2(directClientEventId)) {
|
|
2222
2429
|
return directClientEventId;
|
|
2223
2430
|
}
|
|
2224
2431
|
const metadata = requestBody.metadata;
|
|
2225
2432
|
if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
|
|
2226
2433
|
const metadataClientEventId = metadata.client_event_id;
|
|
2227
|
-
if (typeof metadataClientEventId === "string" &&
|
|
2434
|
+
if (typeof metadataClientEventId === "string" && isUuidLike2(metadataClientEventId)) {
|
|
2228
2435
|
return metadataClientEventId;
|
|
2229
2436
|
}
|
|
2230
2437
|
}
|
|
2231
|
-
return
|
|
2438
|
+
return createEventId2();
|
|
2232
2439
|
}
|
|
2233
2440
|
buildGuardCacheKey(params) {
|
|
2234
2441
|
if (!params.system_id || !params.input) {
|
|
@@ -2272,6 +2479,14 @@ var AgentID = class {
|
|
|
2272
2479
|
force
|
|
2273
2480
|
});
|
|
2274
2481
|
}
|
|
2482
|
+
async getCapabilityConfigWithTelemetry(force = false, options) {
|
|
2483
|
+
const configStartedAt = Date.now();
|
|
2484
|
+
const capabilityConfig = await this.getCapabilityConfig(force, options);
|
|
2485
|
+
return {
|
|
2486
|
+
capabilityConfig,
|
|
2487
|
+
sdkConfigFetchMs: Math.max(0, Date.now() - configStartedAt)
|
|
2488
|
+
};
|
|
2489
|
+
}
|
|
2275
2490
|
getCachedCapabilityConfig(options) {
|
|
2276
2491
|
const effectiveApiKey = this.resolveApiKey(options?.apiKey);
|
|
2277
2492
|
return getCachedCapabilityConfig({
|
|
@@ -2280,12 +2495,32 @@ var AgentID = class {
|
|
|
2280
2495
|
});
|
|
2281
2496
|
}
|
|
2282
2497
|
async resolveEffectiveStrictMode(options) {
|
|
2283
|
-
if (this.strictMode) {
|
|
2498
|
+
if (this.strictMode || this.configuredFailureMode === "fail_close") {
|
|
2284
2499
|
return true;
|
|
2285
2500
|
}
|
|
2501
|
+
if (this.configuredFailureMode === "fail_open") {
|
|
2502
|
+
return false;
|
|
2503
|
+
}
|
|
2286
2504
|
const config = await this.getCapabilityConfig(false, options);
|
|
2287
2505
|
return config.strict_security_mode || config.failure_mode === "fail_close";
|
|
2288
2506
|
}
|
|
2507
|
+
maybeRaiseStrictIngestDependencyError(params) {
|
|
2508
|
+
if (params.result.ok) {
|
|
2509
|
+
return;
|
|
2510
|
+
}
|
|
2511
|
+
if (!shouldEscalateIngestFailure({
|
|
2512
|
+
strictMode: params.strictMode,
|
|
2513
|
+
status: params.result.status,
|
|
2514
|
+
reason: params.result.reason
|
|
2515
|
+
})) {
|
|
2516
|
+
return;
|
|
2517
|
+
}
|
|
2518
|
+
throw new DependencyError({
|
|
2519
|
+
dependency: "ingest",
|
|
2520
|
+
reason: params.result.reason ?? "ingest_failed",
|
|
2521
|
+
status: params.result.status
|
|
2522
|
+
});
|
|
2523
|
+
}
|
|
2289
2524
|
shouldRunLocalInjectionScan(config) {
|
|
2290
2525
|
if (!this.checkInjection) {
|
|
2291
2526
|
return false;
|
|
@@ -2295,37 +2530,45 @@ var AgentID = class {
|
|
|
2295
2530
|
}
|
|
2296
2531
|
return config.block_on_heuristic;
|
|
2297
2532
|
}
|
|
2298
|
-
async
|
|
2299
|
-
const
|
|
2300
|
-
|
|
2301
|
-
if (!params.skipInjectionScan && params.input && this.shouldRunLocalInjectionScan(capabilityConfig)) {
|
|
2533
|
+
async applyLocalPolicyChecks(params) {
|
|
2534
|
+
const localScanStartedAt = Date.now();
|
|
2535
|
+
if (params.runPromptInjectionCheck && params.input && this.shouldRunLocalInjectionScan(params.capabilityConfig)) {
|
|
2302
2536
|
await this.injectionScanner.scan({
|
|
2303
2537
|
prompt: params.input,
|
|
2304
|
-
apiKey:
|
|
2538
|
+
apiKey: params.apiKey,
|
|
2305
2539
|
baseUrl: this.baseUrl,
|
|
2306
2540
|
aiScanEnabled: this.aiScanEnabled,
|
|
2307
2541
|
storePii: this.storePii,
|
|
2308
2542
|
piiManager: this.pii,
|
|
2309
|
-
source: "js_sdk"
|
|
2543
|
+
source: "js_sdk",
|
|
2544
|
+
systemId: params.systemId,
|
|
2545
|
+
eventId: params.clientEventId,
|
|
2546
|
+
clientEventId: params.clientEventId,
|
|
2547
|
+
telemetryMetadata: buildSdkTimingMetadata({
|
|
2548
|
+
sdkConfigFetchMs: params.sdkConfigFetchMs
|
|
2549
|
+
})
|
|
2310
2550
|
});
|
|
2311
2551
|
}
|
|
2312
2552
|
try {
|
|
2313
2553
|
const enforced = this.localEnforcer.enforce({
|
|
2314
2554
|
input: params.input,
|
|
2315
2555
|
stream: params.stream,
|
|
2316
|
-
config: capabilityConfig
|
|
2556
|
+
config: params.capabilityConfig
|
|
2317
2557
|
});
|
|
2558
|
+
const sdkLocalScanMs = Math.max(0, Date.now() - localScanStartedAt);
|
|
2318
2559
|
for (const event of enforced.events) {
|
|
2319
2560
|
this.logSecurityPolicyViolation({
|
|
2320
2561
|
systemId: params.systemId,
|
|
2321
2562
|
violationType: event.violationType,
|
|
2322
2563
|
actionTaken: event.actionTaken,
|
|
2323
|
-
apiKey:
|
|
2564
|
+
apiKey: params.apiKey,
|
|
2565
|
+
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
2566
|
+
sdkLocalScanMs
|
|
2324
2567
|
});
|
|
2325
2568
|
}
|
|
2326
2569
|
return {
|
|
2327
2570
|
sanitizedInput: enforced.sanitizedInput,
|
|
2328
|
-
|
|
2571
|
+
sdkLocalScanMs
|
|
2329
2572
|
};
|
|
2330
2573
|
} catch (error) {
|
|
2331
2574
|
if (error instanceof SecurityPolicyViolationError) {
|
|
@@ -2333,17 +2576,76 @@ var AgentID = class {
|
|
|
2333
2576
|
systemId: params.systemId,
|
|
2334
2577
|
violationType: error.violationType,
|
|
2335
2578
|
actionTaken: error.actionTaken,
|
|
2336
|
-
apiKey:
|
|
2579
|
+
apiKey: params.apiKey,
|
|
2580
|
+
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
2581
|
+
sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
|
|
2337
2582
|
});
|
|
2338
2583
|
}
|
|
2339
2584
|
throw error;
|
|
2340
2585
|
}
|
|
2341
2586
|
}
|
|
2587
|
+
async prepareInputForDispatch(params, options) {
|
|
2588
|
+
const effectiveApiKey = this.resolveApiKey(options?.apiKey);
|
|
2589
|
+
const { capabilityConfig, sdkConfigFetchMs } = await this.getCapabilityConfigWithTelemetry(
|
|
2590
|
+
false,
|
|
2591
|
+
options
|
|
2592
|
+
);
|
|
2593
|
+
if (!this.clientFastFail) {
|
|
2594
|
+
return {
|
|
2595
|
+
sanitizedInput: params.input,
|
|
2596
|
+
capabilityConfig,
|
|
2597
|
+
sdkConfigFetchMs,
|
|
2598
|
+
sdkLocalScanMs: 0
|
|
2599
|
+
};
|
|
2600
|
+
}
|
|
2601
|
+
const enforced = await this.applyLocalPolicyChecks({
|
|
2602
|
+
input: params.input,
|
|
2603
|
+
systemId: params.systemId,
|
|
2604
|
+
stream: params.stream,
|
|
2605
|
+
capabilityConfig,
|
|
2606
|
+
apiKey: effectiveApiKey,
|
|
2607
|
+
clientEventId: params.clientEventId,
|
|
2608
|
+
sdkConfigFetchMs,
|
|
2609
|
+
runPromptInjectionCheck: !params.skipInjectionScan
|
|
2610
|
+
});
|
|
2611
|
+
return {
|
|
2612
|
+
sanitizedInput: enforced.sanitizedInput,
|
|
2613
|
+
capabilityConfig,
|
|
2614
|
+
sdkConfigFetchMs,
|
|
2615
|
+
sdkLocalScanMs: enforced.sdkLocalScanMs
|
|
2616
|
+
};
|
|
2617
|
+
}
|
|
2618
|
+
async applyLocalFallbackForGuardFailure(params, options) {
|
|
2619
|
+
const effectiveApiKey = this.resolveApiKey(options?.apiKey);
|
|
2620
|
+
const resolvedConfig = params.capabilityConfig && typeof params.sdkConfigFetchMs === "number" ? {
|
|
2621
|
+
capabilityConfig: params.capabilityConfig,
|
|
2622
|
+
sdkConfigFetchMs: params.sdkConfigFetchMs
|
|
2623
|
+
} : await this.getCapabilityConfigWithTelemetry(false, options);
|
|
2624
|
+
const enforced = await this.applyLocalPolicyChecks({
|
|
2625
|
+
input: params.input,
|
|
2626
|
+
systemId: params.systemId,
|
|
2627
|
+
stream: params.stream,
|
|
2628
|
+
capabilityConfig: resolvedConfig.capabilityConfig,
|
|
2629
|
+
apiKey: effectiveApiKey,
|
|
2630
|
+
clientEventId: params.clientEventId,
|
|
2631
|
+
sdkConfigFetchMs: resolvedConfig.sdkConfigFetchMs,
|
|
2632
|
+
runPromptInjectionCheck: true
|
|
2633
|
+
});
|
|
2634
|
+
return {
|
|
2635
|
+
sanitizedInput: enforced.sanitizedInput,
|
|
2636
|
+
capabilityConfig: resolvedConfig.capabilityConfig,
|
|
2637
|
+
sdkConfigFetchMs: resolvedConfig.sdkConfigFetchMs,
|
|
2638
|
+
sdkLocalScanMs: enforced.sdkLocalScanMs
|
|
2639
|
+
};
|
|
2640
|
+
}
|
|
2342
2641
|
async scanPromptInjection(input, options) {
|
|
2343
2642
|
if (!input) {
|
|
2344
2643
|
return;
|
|
2345
2644
|
}
|
|
2346
|
-
const capabilityConfig = await this.
|
|
2645
|
+
const { capabilityConfig, sdkConfigFetchMs } = await this.getCapabilityConfigWithTelemetry(
|
|
2646
|
+
false,
|
|
2647
|
+
options
|
|
2648
|
+
);
|
|
2347
2649
|
if (!this.shouldRunLocalInjectionScan(capabilityConfig)) {
|
|
2348
2650
|
return;
|
|
2349
2651
|
}
|
|
@@ -2355,7 +2657,13 @@ var AgentID = class {
|
|
|
2355
2657
|
aiScanEnabled: this.aiScanEnabled,
|
|
2356
2658
|
storePii: this.storePii,
|
|
2357
2659
|
piiManager: this.pii,
|
|
2358
|
-
source: "js_sdk"
|
|
2660
|
+
source: "js_sdk",
|
|
2661
|
+
systemId: options?.systemId,
|
|
2662
|
+
eventId: options?.clientEventId,
|
|
2663
|
+
clientEventId: options?.clientEventId,
|
|
2664
|
+
telemetryMetadata: buildSdkTimingMetadata({
|
|
2665
|
+
sdkConfigFetchMs
|
|
2666
|
+
})
|
|
2359
2667
|
});
|
|
2360
2668
|
}
|
|
2361
2669
|
withMaskedOpenAIRequest(req, maskedText) {
|
|
@@ -2404,7 +2712,11 @@ var AgentID = class {
|
|
|
2404
2712
|
system_id: params.systemId,
|
|
2405
2713
|
violation_type: params.violationType,
|
|
2406
2714
|
input_snippet: "[REDACTED_SAMPLE]",
|
|
2407
|
-
action_taken: params.actionTaken
|
|
2715
|
+
action_taken: params.actionTaken,
|
|
2716
|
+
...buildSdkTimingMetadata({
|
|
2717
|
+
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
2718
|
+
sdkLocalScanMs: params.sdkLocalScanMs
|
|
2719
|
+
})
|
|
2408
2720
|
}
|
|
2409
2721
|
}, { apiKey: params.apiKey });
|
|
2410
2722
|
}
|
|
@@ -2430,6 +2742,42 @@ var AgentID = class {
|
|
|
2430
2742
|
{ apiKey: params.apiKey }
|
|
2431
2743
|
);
|
|
2432
2744
|
}
|
|
2745
|
+
async finalizeIngestTelemetry(params) {
|
|
2746
|
+
const controller = new AbortController();
|
|
2747
|
+
const timeoutId = setTimeout(
|
|
2748
|
+
() => controller.abort(),
|
|
2749
|
+
Math.min(this.ingestTimeoutMs, 2e3)
|
|
2750
|
+
);
|
|
2751
|
+
try {
|
|
2752
|
+
const response = await fetch(`${this.baseUrl}/ingest/finalize`, {
|
|
2753
|
+
method: "POST",
|
|
2754
|
+
headers: {
|
|
2755
|
+
"Content-Type": "application/json",
|
|
2756
|
+
"x-agentid-api-key": params.apiKey,
|
|
2757
|
+
"x-correlation-id": params.clientEventId,
|
|
2758
|
+
"X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER
|
|
2759
|
+
},
|
|
2760
|
+
body: JSON.stringify({
|
|
2761
|
+
client_event_id: params.clientEventId,
|
|
2762
|
+
system_id: params.systemId,
|
|
2763
|
+
sdk_ingest_ms: params.sdkIngestMs
|
|
2764
|
+
}),
|
|
2765
|
+
signal: controller.signal
|
|
2766
|
+
});
|
|
2767
|
+
if (!response.ok) {
|
|
2768
|
+
console.warn(
|
|
2769
|
+
`[AgentID] Ingest telemetry finalize failed (status=${response.status}, client_event_id=${params.clientEventId}).`
|
|
2770
|
+
);
|
|
2771
|
+
}
|
|
2772
|
+
} catch (error) {
|
|
2773
|
+
const label = error && typeof error === "object" && error.name === "AbortError" ? "timeout" : "network";
|
|
2774
|
+
console.warn(
|
|
2775
|
+
`[AgentID] Ingest telemetry finalize failed (${label}, client_event_id=${params.clientEventId}).`
|
|
2776
|
+
);
|
|
2777
|
+
} finally {
|
|
2778
|
+
clearTimeout(timeoutId);
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2433
2781
|
/**
|
|
2434
2782
|
* GUARD: Checks limits, PII, and security before execution.
|
|
2435
2783
|
* strictMode=false (default): FAIL-OPEN on connectivity/timeouts.
|
|
@@ -2587,15 +2935,16 @@ var AgentID = class {
|
|
|
2587
2935
|
}
|
|
2588
2936
|
return withGuardLatency({ allowed: true, reason: "guard_unreachable" });
|
|
2589
2937
|
}
|
|
2590
|
-
async sendIngest(params, options) {
|
|
2938
|
+
async sendIngest(params, options, internal) {
|
|
2939
|
+
const ingestStartedAt = Date.now();
|
|
2591
2940
|
const effectiveApiKey = this.resolveApiKey(options?.apiKey);
|
|
2592
|
-
const
|
|
2941
|
+
const transportEventId = createEventId2(internal?.transportEventId ?? params.event_id);
|
|
2593
2942
|
const timestamp = params.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2594
2943
|
const metadata = {
|
|
2595
2944
|
...params.metadata ?? {}
|
|
2596
2945
|
};
|
|
2597
|
-
const metadataClientEventId = typeof metadata.client_event_id === "string" &&
|
|
2598
|
-
const canonicalClientEventId = metadataClientEventId ??
|
|
2946
|
+
const metadataClientEventId = typeof metadata.client_event_id === "string" && isUuidLike2(metadata.client_event_id) ? metadata.client_event_id : null;
|
|
2947
|
+
const canonicalClientEventId = metadataClientEventId ?? transportEventId;
|
|
2599
2948
|
if (!metadataClientEventId) {
|
|
2600
2949
|
metadata.client_event_id = canonicalClientEventId;
|
|
2601
2950
|
}
|
|
@@ -2605,7 +2954,7 @@ var AgentID = class {
|
|
|
2605
2954
|
void this.getCapabilityConfig(false, { apiKey: effectiveApiKey }).catch(() => void 0);
|
|
2606
2955
|
const payload = {
|
|
2607
2956
|
...params,
|
|
2608
|
-
event_id: canonicalClientEventId,
|
|
2957
|
+
event_id: internal?.transportEventId ? transportEventId : canonicalClientEventId,
|
|
2609
2958
|
timestamp,
|
|
2610
2959
|
input: sanitizeIngestText(params.input),
|
|
2611
2960
|
output: sanitizeIngestText(params.output),
|
|
@@ -2630,6 +2979,14 @@ var AgentID = class {
|
|
|
2630
2979
|
});
|
|
2631
2980
|
const responseBody = await safeReadJson2(response);
|
|
2632
2981
|
if (response.ok) {
|
|
2982
|
+
if (!internal?.disableFinalize) {
|
|
2983
|
+
void this.finalizeIngestTelemetry({
|
|
2984
|
+
apiKey: effectiveApiKey,
|
|
2985
|
+
clientEventId: canonicalClientEventId,
|
|
2986
|
+
systemId: params.system_id,
|
|
2987
|
+
sdkIngestMs: Math.max(0, Date.now() - ingestStartedAt)
|
|
2988
|
+
});
|
|
2989
|
+
}
|
|
2633
2990
|
return { ok: true, status: response.status, reason: null };
|
|
2634
2991
|
}
|
|
2635
2992
|
const reason = responseBody && typeof responseBody === "object" && typeof responseBody.reason === "string" ? responseBody.reason ?? null : null;
|
|
@@ -2757,8 +3114,15 @@ var AgentID = class {
|
|
|
2757
3114
|
* Returns a Promise so callers can await persistence when needed.
|
|
2758
3115
|
*/
|
|
2759
3116
|
async log(params, options) {
|
|
2760
|
-
const
|
|
3117
|
+
const effectiveApiKey = this.resolveApiKey(options?.apiKey);
|
|
3118
|
+
const requestOptions = { apiKey: effectiveApiKey };
|
|
3119
|
+
const effectiveStrictMode = await this.resolveEffectiveStrictMode(requestOptions);
|
|
3120
|
+
const result = await this.sendIngest(params, requestOptions);
|
|
2761
3121
|
if (!result.ok) {
|
|
3122
|
+
this.maybeRaiseStrictIngestDependencyError({
|
|
3123
|
+
strictMode: effectiveStrictMode,
|
|
3124
|
+
result
|
|
3125
|
+
});
|
|
2762
3126
|
console.warn(
|
|
2763
3127
|
`[AgentID] Ingest telemetry failed (status=${result.status ?? "network"}, reason=${result.reason ?? "unknown"}).`
|
|
2764
3128
|
);
|
|
@@ -2784,6 +3148,9 @@ var AgentID = class {
|
|
|
2784
3148
|
*/
|
|
2785
3149
|
wrapOpenAI(openai, options) {
|
|
2786
3150
|
const systemId = options.system_id;
|
|
3151
|
+
const expectedLanguages = normalizeExpectedLanguages(
|
|
3152
|
+
options.expected_languages ?? options.expectedLanguages
|
|
3153
|
+
);
|
|
2787
3154
|
const adapter = new OpenAIAdapter();
|
|
2788
3155
|
const wrapChatCompletions = (chatObj) => {
|
|
2789
3156
|
if (!chatObj || typeof chatObj !== "object") return chatObj;
|
|
@@ -2810,6 +3177,8 @@ var AgentID = class {
|
|
|
2810
3177
|
const requestLevelApiKey = options.resolveApiKey?.(req) ?? options.apiKey ?? options.api_key;
|
|
2811
3178
|
const effectiveApiKey = this.resolveApiKey(requestLevelApiKey);
|
|
2812
3179
|
const requestOptions = { apiKey: effectiveApiKey };
|
|
3180
|
+
const clientEventId = this.resolveClientEventId(req);
|
|
3181
|
+
const effectiveStrictMode = await this.resolveEffectiveStrictMode(requestOptions);
|
|
2813
3182
|
const stream = adapter.isStream(req);
|
|
2814
3183
|
let capabilityConfig = this.getCachedCapabilityConfig(requestOptions);
|
|
2815
3184
|
const userText = adapter.extractInput(req);
|
|
@@ -2818,16 +3187,19 @@ var AgentID = class {
|
|
|
2818
3187
|
let createArgs = normalizedCreateArgs;
|
|
2819
3188
|
let mapping = {};
|
|
2820
3189
|
let shouldDeanonymize = false;
|
|
3190
|
+
let sdkConfigFetchMs = 0;
|
|
3191
|
+
let sdkLocalScanMs = 0;
|
|
2821
3192
|
if (userText) {
|
|
2822
|
-
await this.scanPromptInjection(userText, requestOptions);
|
|
2823
3193
|
const prepared = await this.prepareInputForDispatch({
|
|
2824
3194
|
input: userText,
|
|
2825
3195
|
systemId,
|
|
2826
3196
|
stream,
|
|
2827
|
-
|
|
3197
|
+
clientEventId
|
|
2828
3198
|
}, requestOptions);
|
|
2829
3199
|
capabilityConfig = prepared.capabilityConfig;
|
|
2830
3200
|
maskedText = prepared.sanitizedInput;
|
|
3201
|
+
sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
|
|
3202
|
+
sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
|
|
2831
3203
|
if (maskedText !== userText) {
|
|
2832
3204
|
maskedReq = this.withMaskedOpenAIRequest(
|
|
2833
3205
|
req,
|
|
@@ -2837,7 +3209,8 @@ var AgentID = class {
|
|
|
2837
3209
|
nextCreateArgs[0] = maskedReq;
|
|
2838
3210
|
createArgs = nextCreateArgs;
|
|
2839
3211
|
}
|
|
2840
|
-
|
|
3212
|
+
const effectivePiiMasking = this.resolveEffectivePiiMasking(capabilityConfig);
|
|
3213
|
+
if (!capabilityConfig.block_pii_leakage && effectivePiiMasking) {
|
|
2841
3214
|
if (stream) {
|
|
2842
3215
|
console.warn("AgentID: PII masking is disabled for streaming responses.");
|
|
2843
3216
|
} else {
|
|
@@ -2860,19 +3233,54 @@ var AgentID = class {
|
|
|
2860
3233
|
"AgentID: No user message found. Security guard requires string input."
|
|
2861
3234
|
);
|
|
2862
3235
|
}
|
|
2863
|
-
const clientEventId = this.resolveClientEventId(req);
|
|
2864
3236
|
const verdict = await this.guard({
|
|
2865
3237
|
input: maskedText,
|
|
2866
3238
|
system_id: systemId,
|
|
2867
3239
|
model: adapter.getModelName(maskedReq),
|
|
2868
3240
|
user_id: options.user_id,
|
|
2869
3241
|
client_event_id: clientEventId,
|
|
2870
|
-
|
|
3242
|
+
expected_languages: expectedLanguages,
|
|
3243
|
+
client_capabilities: this.buildClientCapabilities(
|
|
3244
|
+
"openai",
|
|
3245
|
+
false,
|
|
3246
|
+
capabilityConfig
|
|
3247
|
+
)
|
|
2871
3248
|
}, requestOptions);
|
|
3249
|
+
let localFallbackApplied = false;
|
|
3250
|
+
let localFallbackReason = null;
|
|
2872
3251
|
if (!verdict.allowed) {
|
|
2873
|
-
|
|
3252
|
+
if (effectiveStrictMode && isGuardFailureEligibleForLocalFallback(verdict.reason)) {
|
|
3253
|
+
localFallbackApplied = true;
|
|
3254
|
+
localFallbackReason = verdict.reason ?? "guard_unreachable";
|
|
3255
|
+
if (sdkLocalScanMs === 0) {
|
|
3256
|
+
const fallback = await this.applyLocalPolicyChecks({
|
|
3257
|
+
input: maskedText,
|
|
3258
|
+
systemId,
|
|
3259
|
+
stream,
|
|
3260
|
+
capabilityConfig,
|
|
3261
|
+
apiKey: effectiveApiKey,
|
|
3262
|
+
clientEventId,
|
|
3263
|
+
sdkConfigFetchMs,
|
|
3264
|
+
runPromptInjectionCheck: true
|
|
3265
|
+
});
|
|
3266
|
+
maskedText = fallback.sanitizedInput;
|
|
3267
|
+
sdkLocalScanMs = fallback.sdkLocalScanMs;
|
|
3268
|
+
}
|
|
3269
|
+
} else {
|
|
3270
|
+
throw new SecurityBlockError(verdict.reason ?? "guard_denied");
|
|
3271
|
+
}
|
|
2874
3272
|
}
|
|
2875
|
-
const
|
|
3273
|
+
const currentRequestInput = adapter.extractInput(maskedReq);
|
|
3274
|
+
if (maskedText !== currentRequestInput) {
|
|
3275
|
+
maskedReq = this.withMaskedOpenAIRequest(
|
|
3276
|
+
req,
|
|
3277
|
+
maskedText
|
|
3278
|
+
);
|
|
3279
|
+
const nextCreateArgs = [...normalizedCreateArgs];
|
|
3280
|
+
nextCreateArgs[0] = maskedReq;
|
|
3281
|
+
createArgs = nextCreateArgs;
|
|
3282
|
+
}
|
|
3283
|
+
const canonicalClientEventId = typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId;
|
|
2876
3284
|
const guardEventId = typeof verdict.guard_event_id === "string" && verdict.guard_event_id.length > 0 ? verdict.guard_event_id : null;
|
|
2877
3285
|
const guardLatencyMs = typeof verdict.guard_latency_ms === "number" && Number.isFinite(verdict.guard_latency_ms) ? Math.max(0, Math.trunc(verdict.guard_latency_ms)) : Math.max(0, Date.now() - pipelineStartedAt);
|
|
2878
3286
|
const transparency = coerceTransparencyMetadata(verdict.transparency);
|
|
@@ -2921,16 +3329,31 @@ var AgentID = class {
|
|
|
2921
3329
|
simulated_decision: verdict.simulated_decision ?? null,
|
|
2922
3330
|
simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
|
|
2923
3331
|
response_streamed: true,
|
|
3332
|
+
sdk_local_fallback_applied: localFallbackApplied,
|
|
3333
|
+
sdk_local_fallback_reason: localFallbackReason,
|
|
2924
3334
|
guard_latency_ms: guardLatencyMs,
|
|
2925
3335
|
model_latency_ms: modelLatencyMs2,
|
|
2926
3336
|
total_pipeline_latency_ms: totalPipelineLatencyMs2,
|
|
2927
3337
|
guard_event_id: guardEventId,
|
|
2928
3338
|
client_event_id: canonicalClientEventId,
|
|
2929
|
-
transparency
|
|
3339
|
+
transparency,
|
|
3340
|
+
...buildSdkTimingMetadata({
|
|
3341
|
+
sdkConfigFetchMs,
|
|
3342
|
+
sdkLocalScanMs,
|
|
3343
|
+
sdkGuardMs: guardLatencyMs
|
|
3344
|
+
})
|
|
2930
3345
|
},
|
|
2931
|
-
client_capabilities: this.buildClientCapabilities(
|
|
3346
|
+
client_capabilities: this.buildClientCapabilities(
|
|
3347
|
+
"openai",
|
|
3348
|
+
false,
|
|
3349
|
+
capabilityConfig
|
|
3350
|
+
)
|
|
2932
3351
|
}, requestOptions);
|
|
2933
3352
|
if (!ingestResult.ok) {
|
|
3353
|
+
this.maybeRaiseStrictIngestDependencyError({
|
|
3354
|
+
strictMode: effectiveStrictMode,
|
|
3355
|
+
result: ingestResult
|
|
3356
|
+
});
|
|
2934
3357
|
console.warn(
|
|
2935
3358
|
`[AgentID] Stream ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
|
|
2936
3359
|
);
|
|
@@ -2972,22 +3395,37 @@ var AgentID = class {
|
|
|
2972
3395
|
simulated_decision: verdict.simulated_decision ?? null,
|
|
2973
3396
|
simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
|
|
2974
3397
|
response_streamed: false,
|
|
3398
|
+
sdk_local_fallback_applied: localFallbackApplied,
|
|
3399
|
+
sdk_local_fallback_reason: localFallbackReason,
|
|
2975
3400
|
guard_latency_ms: guardLatencyMs,
|
|
2976
3401
|
model_latency_ms: modelLatencyMs,
|
|
2977
3402
|
total_pipeline_latency_ms: totalPipelineLatencyMs,
|
|
2978
3403
|
guard_event_id: guardEventId,
|
|
2979
3404
|
client_event_id: canonicalClientEventId,
|
|
2980
|
-
transparency
|
|
3405
|
+
transparency,
|
|
3406
|
+
...buildSdkTimingMetadata({
|
|
3407
|
+
sdkConfigFetchMs,
|
|
3408
|
+
sdkLocalScanMs,
|
|
3409
|
+
sdkGuardMs: guardLatencyMs
|
|
3410
|
+
})
|
|
2981
3411
|
},
|
|
2982
|
-
client_capabilities: this.buildClientCapabilities(
|
|
3412
|
+
client_capabilities: this.buildClientCapabilities(
|
|
3413
|
+
"openai",
|
|
3414
|
+
false,
|
|
3415
|
+
capabilityConfig
|
|
3416
|
+
)
|
|
2983
3417
|
}, requestOptions);
|
|
2984
3418
|
if (!ingestResult.ok) {
|
|
3419
|
+
this.maybeRaiseStrictIngestDependencyError({
|
|
3420
|
+
strictMode: effectiveStrictMode,
|
|
3421
|
+
result: ingestResult
|
|
3422
|
+
});
|
|
2985
3423
|
console.warn(
|
|
2986
3424
|
`[AgentID] Ingest telemetry failed (status=${ingestResult.status ?? "network"}, reason=${ingestResult.reason ?? "unknown"}).`
|
|
2987
3425
|
);
|
|
2988
3426
|
}
|
|
2989
3427
|
}
|
|
2990
|
-
if (!capabilityConfig.block_pii_leakage && this.
|
|
3428
|
+
if (!capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig) && shouldDeanonymize) {
|
|
2991
3429
|
const deanon = this.pii.deanonymize(adapter.extractOutput(res), mapping);
|
|
2992
3430
|
try {
|
|
2993
3431
|
if (Array.isArray(res?.choices)) {
|
|
@@ -3030,5 +3468,6 @@ export {
|
|
|
3030
3468
|
InjectionScanner,
|
|
3031
3469
|
getInjectionScanner,
|
|
3032
3470
|
SecurityBlockError,
|
|
3471
|
+
DependencyError,
|
|
3033
3472
|
AgentID
|
|
3034
3473
|
};
|