agentid-sdk 0.1.22 → 0.1.24
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 +73 -0
- package/dist/{agentid-BmsXTOCc.d.mts → agentid-BGCUoYV7.d.mts} +17 -2
- package/dist/{agentid-BmsXTOCc.d.ts → agentid-BGCUoYV7.d.ts} +17 -2
- package/dist/{chunk-FVTL572H.mjs → chunk-JLHAS2EE.mjs} +235 -32
- package/dist/index.d.mts +25 -2
- package/dist/index.d.ts +25 -2
- package/dist/index.js +396 -32
- package/dist/index.mjs +161 -1
- package/dist/langchain.d.mts +1 -1
- package/dist/langchain.d.ts +1 -1
- package/dist/langchain.js +50 -5
- package/dist/langchain.mjs +50 -5
- package/package.json +10 -2
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AgentID: () => AgentID,
|
|
34
|
+
AgentIDTransparencyBadge: () => AgentIDTransparencyBadge,
|
|
34
35
|
InjectionScanner: () => InjectionScanner,
|
|
35
36
|
OpenAIAdapter: () => OpenAIAdapter,
|
|
36
37
|
PIIManager: () => PIIManager,
|
|
@@ -84,7 +85,7 @@ var OpenAIAdapter = class {
|
|
|
84
85
|
|
|
85
86
|
// src/sdk-version.ts
|
|
86
87
|
var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
|
|
87
|
-
var AGENTID_SDK_VERSION_HEADER = "js-0.1.
|
|
88
|
+
var AGENTID_SDK_VERSION_HEADER = "js-0.1.24".trim().length > 0 ? "js-0.1.24" : FALLBACK_SDK_VERSION;
|
|
88
89
|
|
|
89
90
|
// src/pii-national-identifiers.ts
|
|
90
91
|
var MAX_CANDIDATES_PER_RULE = 256;
|
|
@@ -1016,11 +1017,87 @@ var PHONE_CONTEXT_RE = new RegExp(
|
|
|
1016
1017
|
`(?:^|[^\\p{L}])(?:${PHONE_CONTEXT_KEYWORDS.map(escapeRegex).join("|")})(?:$|[^\\p{L}])`,
|
|
1017
1018
|
"iu"
|
|
1018
1019
|
);
|
|
1020
|
+
var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
|
|
1021
|
+
"write",
|
|
1022
|
+
"code",
|
|
1023
|
+
"script",
|
|
1024
|
+
"query",
|
|
1025
|
+
"curl",
|
|
1026
|
+
"http",
|
|
1027
|
+
"https",
|
|
1028
|
+
"import",
|
|
1029
|
+
"python",
|
|
1030
|
+
"javascript",
|
|
1031
|
+
"typescript",
|
|
1032
|
+
"node",
|
|
1033
|
+
"bash",
|
|
1034
|
+
"powershell",
|
|
1035
|
+
"shell",
|
|
1036
|
+
"command",
|
|
1037
|
+
"example",
|
|
1038
|
+
"demo",
|
|
1039
|
+
"developer",
|
|
1040
|
+
"mode",
|
|
1041
|
+
"system",
|
|
1042
|
+
"prompt",
|
|
1043
|
+
"policy",
|
|
1044
|
+
"security",
|
|
1045
|
+
"instructions",
|
|
1046
|
+
"instruction",
|
|
1047
|
+
"rules",
|
|
1048
|
+
"rule",
|
|
1049
|
+
"json",
|
|
1050
|
+
"output",
|
|
1051
|
+
"input",
|
|
1052
|
+
"database",
|
|
1053
|
+
"sql",
|
|
1054
|
+
"mongo",
|
|
1055
|
+
"openai",
|
|
1056
|
+
"agentid",
|
|
1057
|
+
"risk",
|
|
1058
|
+
"score",
|
|
1059
|
+
"summary"
|
|
1060
|
+
]);
|
|
1061
|
+
var TECHNICAL_CONTEXT_WORD_REGEX = /\b(?:curl|http|https|import|python|javascript|typescript|sql|nosql|mongo|database|query|script|code|os\.system|eval|exec|node|npm|api|endpoint|regex|json|xml|yaml|bash|powershell)\b/i;
|
|
1062
|
+
var TECHNICAL_CONTEXT_SYMBOL_REGEX = /:\/\/|`|\{|\}|\[|\]|\(|\)|;|\$|=>|::|\/\//;
|
|
1019
1063
|
function hasPhoneContext(text, matchStartIndex, windowSize = 50) {
|
|
1020
1064
|
const start = Math.max(0, matchStartIndex - windowSize);
|
|
1021
1065
|
const windowLower = text.slice(start, matchStartIndex).toLowerCase();
|
|
1022
1066
|
return PHONE_CONTEXT_RE.test(windowLower);
|
|
1023
1067
|
}
|
|
1068
|
+
function normalizePersonWord(value) {
|
|
1069
|
+
return value.normalize("NFD").replace(/\p{M}+/gu, "").toLowerCase();
|
|
1070
|
+
}
|
|
1071
|
+
function buildContextWindow(source, index, length) {
|
|
1072
|
+
const start = Math.max(0, index - 28);
|
|
1073
|
+
const end = Math.min(source.length, index + length + 28);
|
|
1074
|
+
return source.slice(start, end);
|
|
1075
|
+
}
|
|
1076
|
+
function isTechnicalContext(contextWindow) {
|
|
1077
|
+
return TECHNICAL_CONTEXT_WORD_REGEX.test(contextWindow) || TECHNICAL_CONTEXT_SYMBOL_REGEX.test(contextWindow);
|
|
1078
|
+
}
|
|
1079
|
+
function isLikelyPersonNameCandidate(candidate, contextWindow) {
|
|
1080
|
+
const words = candidate.trim().split(/\s+/);
|
|
1081
|
+
if (words.length !== 2) {
|
|
1082
|
+
return false;
|
|
1083
|
+
}
|
|
1084
|
+
if (isTechnicalContext(contextWindow)) {
|
|
1085
|
+
return false;
|
|
1086
|
+
}
|
|
1087
|
+
for (const rawWord of words) {
|
|
1088
|
+
const normalized = normalizePersonWord(rawWord);
|
|
1089
|
+
if (normalized.length < 2) {
|
|
1090
|
+
return false;
|
|
1091
|
+
}
|
|
1092
|
+
if (PERSON_NAME_STOPWORDS.has(normalized)) {
|
|
1093
|
+
return false;
|
|
1094
|
+
}
|
|
1095
|
+
if (!/^\p{L}[\p{L}'-]+$/u.test(rawWord)) {
|
|
1096
|
+
return false;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
return true;
|
|
1100
|
+
}
|
|
1024
1101
|
var PIIManager = class {
|
|
1025
1102
|
/**
|
|
1026
1103
|
* Reversible local-first masking using <TYPE_INDEX> placeholders.
|
|
@@ -1065,7 +1142,12 @@ var PIIManager = class {
|
|
|
1065
1142
|
const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
|
|
1066
1143
|
for (const m of text.matchAll(personRe)) {
|
|
1067
1144
|
if (m.index == null) continue;
|
|
1068
|
-
|
|
1145
|
+
const candidate = m[0];
|
|
1146
|
+
const contextWindow = buildContextWindow(text, m.index, candidate.length);
|
|
1147
|
+
if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
|
|
1148
|
+
continue;
|
|
1149
|
+
}
|
|
1150
|
+
detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
|
|
1069
1151
|
}
|
|
1070
1152
|
const nationalIdMatches = detectNationalIdentifiers(text, {
|
|
1071
1153
|
deadlineMs: defaultScanDeadlineMs,
|
|
@@ -1120,12 +1202,21 @@ var DEFAULT_FAIL_OPEN_CONFIG = {
|
|
|
1120
1202
|
strict_security_mode: false,
|
|
1121
1203
|
failure_mode: "fail_open",
|
|
1122
1204
|
block_on_heuristic: false,
|
|
1205
|
+
inject_transparency_metadata: false,
|
|
1123
1206
|
block_pii_leakage: false,
|
|
1124
1207
|
block_db_access: false,
|
|
1125
1208
|
block_code_execution: false,
|
|
1126
1209
|
block_toxicity: false
|
|
1127
1210
|
};
|
|
1128
1211
|
var SQL_DATABASE_ACCESS_PATTERN = /\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION|ALTER)\b[\s\S]+?\b(FROM|INTO|TABLE|DATABASE|VIEW|INDEX)\b/i;
|
|
1212
|
+
var NOSQL_DATABASE_ACCESS_PATTERNS = [
|
|
1213
|
+
/\bdb\.[A-Za-z_][A-Za-z0-9_]*\.(find|findOne|aggregate|updateOne|updateMany|deleteOne|deleteMany|insertOne|insertMany)\s*\(/i,
|
|
1214
|
+
/\b(collection|mongodb)\.(find|findOne|aggregate|updateOne|updateMany|deleteOne|deleteMany|insertOne|insertMany)\s*\(/i,
|
|
1215
|
+
/\b\$where\b/i,
|
|
1216
|
+
/\b\$expr\b/i,
|
|
1217
|
+
/\b\$regex\b/i,
|
|
1218
|
+
/\bMongoClient\.connect\s*\(/i
|
|
1219
|
+
];
|
|
1129
1220
|
var PYTHON_GENERAL_RCE_PATTERN = /(import\s+(os|sys|subprocess)|from\s+(os|sys|subprocess)\s+import|exec\s*\(|eval\s*\(|__import__)/i;
|
|
1130
1221
|
var SHELL_BASH_RCE_PATTERN = /(wget\s+|curl\s+|rm\s+-rf|chmod\s+\+x|cat\s+\/etc\/passwd|\/bin\/sh|\/bin\/bash)/i;
|
|
1131
1222
|
var JAVASCRIPT_RCE_PATTERN = /(new\s+Function\(|process\.env|child_process)/i;
|
|
@@ -1139,8 +1230,15 @@ var SecurityPolicyViolationError = class extends Error {
|
|
|
1139
1230
|
}
|
|
1140
1231
|
};
|
|
1141
1232
|
function detectCapabilityViolation(text, config) {
|
|
1142
|
-
if (config.block_db_access
|
|
1143
|
-
|
|
1233
|
+
if (config.block_db_access) {
|
|
1234
|
+
if (SQL_DATABASE_ACCESS_PATTERN.test(text)) {
|
|
1235
|
+
return "SQL_INJECTION_ATTEMPT";
|
|
1236
|
+
}
|
|
1237
|
+
for (const pattern of NOSQL_DATABASE_ACCESS_PATTERNS) {
|
|
1238
|
+
if (pattern.test(text)) {
|
|
1239
|
+
return "SQL_INJECTION_ATTEMPT";
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1144
1242
|
}
|
|
1145
1243
|
if (config.block_code_execution && (PYTHON_GENERAL_RCE_PATTERN.test(text) || SHELL_BASH_RCE_PATTERN.test(text) || JAVASCRIPT_RCE_PATTERN.test(text))) {
|
|
1146
1244
|
return "RCE_ATTEMPT";
|
|
@@ -1287,6 +1385,11 @@ function normalizeCapabilityConfig(payload) {
|
|
|
1287
1385
|
strict_security_mode: effectiveStrictMode,
|
|
1288
1386
|
failure_mode: effectiveStrictMode ? "fail_close" : "fail_open",
|
|
1289
1387
|
block_on_heuristic: blockOnHeuristic,
|
|
1388
|
+
inject_transparency_metadata: readOptionalBooleanAliases(
|
|
1389
|
+
body,
|
|
1390
|
+
["inject_transparency_metadata", "transparency_metadata_enabled"],
|
|
1391
|
+
false
|
|
1392
|
+
),
|
|
1290
1393
|
block_pii_leakage: readBooleanField(body, "block_pii_leakage", "block_pii"),
|
|
1291
1394
|
block_db_access: readBooleanField(body, "block_db_access", "block_db"),
|
|
1292
1395
|
block_code_execution: readBooleanField(
|
|
@@ -1473,15 +1576,15 @@ var DE_STOPWORDS = /* @__PURE__ */ new Set(["bitte", "anweisung", "system", "reg
|
|
|
1473
1576
|
var HEURISTIC_RULES = [
|
|
1474
1577
|
{
|
|
1475
1578
|
name: "heuristic_combo_ignore_instructions",
|
|
1476
|
-
re: /\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b[\s\S]{0,
|
|
1579
|
+
re: /\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b[\s\S]{0,160}\b(instruction(?:s)?|previous|system|developer|policy|rules?|guardrails|safety|instrukce|pokyny|pravidla|systemove?|bezpecnost(?:ni)?|politika)\b/i
|
|
1477
1580
|
},
|
|
1478
1581
|
{
|
|
1479
1582
|
name: "heuristic_combo_instruction_override_reverse",
|
|
1480
|
-
re: /\b(instruction(?:s)?|previous|system|developer|policy|rules
|
|
1583
|
+
re: /\b(instruction(?:s)?|previous|system|developer|policy|rules?|guardrails|safety|instrukce|pokyny|pravidla|systemove?|bezpecnost(?:ni)?|politika)\b[\s\S]{0,160}\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b/i
|
|
1481
1584
|
},
|
|
1482
1585
|
{
|
|
1483
1586
|
name: "heuristic_combo_exfil_system_prompt",
|
|
1484
|
-
re: /\b(show|reveal|print|dump|leak|display|expose|tell|extract|ukaz|zobraz|vypis|odhal|prozrad)\b[\s\S]{0,
|
|
1587
|
+
re: /\b(show|reveal|print|dump|leak|display|expose|tell|extract|ukaz|zobraz|vypis|odhal|prozrad)\b[\s\S]{0,180}\b(system prompt|system instruction(?:s)?|developer message|hidden prompt|internal instruction(?:s)?|policy|guardrails|interni instrukce|systemove nastaveni)\b/i
|
|
1485
1588
|
},
|
|
1486
1589
|
{
|
|
1487
1590
|
name: "heuristic_role_prefix_system_developer",
|
|
@@ -1490,6 +1593,14 @@ var HEURISTIC_RULES = [
|
|
|
1490
1593
|
{
|
|
1491
1594
|
name: "heuristic_delimiter_system_prompt",
|
|
1492
1595
|
re: /\b(begin|start)\s+(system|developer)\s+prompt\b|\bend\s+(system|developer)\s+prompt\b/i
|
|
1596
|
+
},
|
|
1597
|
+
{
|
|
1598
|
+
name: "heuristic_developer_mode_override",
|
|
1599
|
+
re: /\b(developer\s*mode|dev\s*mode)\b[\s\S]{0,200}\b(ignore|bypass|disable|override|ignoruj|obejdi|zapomen)\b/i
|
|
1600
|
+
},
|
|
1601
|
+
{
|
|
1602
|
+
name: "heuristic_czech_injection_phrase",
|
|
1603
|
+
re: /\b(zapomen|ignoruj)\b[\s\S]{0,220}\b(predchozi\s+instrukce|bezpecnostni\s+pravidla|systemove\s+nastaveni)\b/i
|
|
1493
1604
|
}
|
|
1494
1605
|
];
|
|
1495
1606
|
var scannerSingleton = null;
|
|
@@ -1540,6 +1651,9 @@ ${input.slice(-WINDOW_SLICE_SIZE)}`;
|
|
|
1540
1651
|
[...]
|
|
1541
1652
|
${input.slice(tailStart)}`;
|
|
1542
1653
|
}
|
|
1654
|
+
function normalizeForHeuristics(input) {
|
|
1655
|
+
return input.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/\s+/g, " ").trim();
|
|
1656
|
+
}
|
|
1543
1657
|
function scoreStopwords(tokens, stopwords) {
|
|
1544
1658
|
let score = 0;
|
|
1545
1659
|
for (const token of tokens) {
|
|
@@ -1582,9 +1696,10 @@ function findRegexMatch(prompt) {
|
|
|
1582
1696
|
if (!prompt) {
|
|
1583
1697
|
return null;
|
|
1584
1698
|
}
|
|
1699
|
+
const normalizedPrompt = normalizeForHeuristics(prompt);
|
|
1585
1700
|
for (const rule of HEURISTIC_RULES) {
|
|
1586
1701
|
try {
|
|
1587
|
-
const match = rule.re.exec(
|
|
1702
|
+
const match = rule.re.exec(normalizedPrompt);
|
|
1588
1703
|
if (match && typeof match[0] === "string" && match[0].trim()) {
|
|
1589
1704
|
return {
|
|
1590
1705
|
rule: rule.name,
|
|
@@ -1993,6 +2108,53 @@ async function safeReadJson2(response) {
|
|
|
1993
2108
|
return null;
|
|
1994
2109
|
}
|
|
1995
2110
|
}
|
|
2111
|
+
function coerceTransparencyMetadata(value) {
|
|
2112
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2113
|
+
return void 0;
|
|
2114
|
+
}
|
|
2115
|
+
const raw = value;
|
|
2116
|
+
if (raw.is_ai_generated !== true) {
|
|
2117
|
+
return void 0;
|
|
2118
|
+
}
|
|
2119
|
+
if (raw.disclosure !== "You are interacting with an AI.") {
|
|
2120
|
+
return void 0;
|
|
2121
|
+
}
|
|
2122
|
+
if (raw.article !== "EU_AI_ACT_ARTICLE_50") {
|
|
2123
|
+
return void 0;
|
|
2124
|
+
}
|
|
2125
|
+
if (raw.injection_mode !== "deterministic") {
|
|
2126
|
+
return void 0;
|
|
2127
|
+
}
|
|
2128
|
+
return {
|
|
2129
|
+
is_ai_generated: true,
|
|
2130
|
+
disclosure: "You are interacting with an AI.",
|
|
2131
|
+
article: "EU_AI_ACT_ARTICLE_50",
|
|
2132
|
+
injection_mode: "deterministic"
|
|
2133
|
+
};
|
|
2134
|
+
}
|
|
2135
|
+
function attachTransparencyMetadata(target, transparency) {
|
|
2136
|
+
if (!transparency) {
|
|
2137
|
+
return target;
|
|
2138
|
+
}
|
|
2139
|
+
if (!target || typeof target !== "object" && typeof target !== "function") {
|
|
2140
|
+
return target;
|
|
2141
|
+
}
|
|
2142
|
+
try {
|
|
2143
|
+
Object.defineProperty(target, "agentid_transparency", {
|
|
2144
|
+
value: transparency,
|
|
2145
|
+
enumerable: false,
|
|
2146
|
+
configurable: true,
|
|
2147
|
+
writable: false
|
|
2148
|
+
});
|
|
2149
|
+
return target;
|
|
2150
|
+
} catch {
|
|
2151
|
+
try {
|
|
2152
|
+
target.agentid_transparency = transparency;
|
|
2153
|
+
} catch {
|
|
2154
|
+
}
|
|
2155
|
+
return target;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
1996
2158
|
function createCompletionChunkCollector() {
|
|
1997
2159
|
if (typeof TransformStream === "function") {
|
|
1998
2160
|
const stream = new TransformStream({
|
|
@@ -2317,6 +2479,16 @@ var AgentID = class {
|
|
|
2317
2479
|
* strictMode=true: FAIL-CLOSED and throws on connectivity/timeouts.
|
|
2318
2480
|
*/
|
|
2319
2481
|
async guard(params, options) {
|
|
2482
|
+
const guardStartedAt = Date.now();
|
|
2483
|
+
const withGuardLatency = (response) => {
|
|
2484
|
+
if (typeof response.guard_latency_ms === "number" && Number.isFinite(response.guard_latency_ms)) {
|
|
2485
|
+
return response;
|
|
2486
|
+
}
|
|
2487
|
+
return {
|
|
2488
|
+
...response,
|
|
2489
|
+
guard_latency_ms: Math.max(0, Date.now() - guardStartedAt)
|
|
2490
|
+
};
|
|
2491
|
+
};
|
|
2320
2492
|
const effectiveApiKey = this.resolveApiKey(options?.apiKey);
|
|
2321
2493
|
const effectiveStrictMode = await this.resolveEffectiveStrictMode({
|
|
2322
2494
|
apiKey: effectiveApiKey
|
|
@@ -2328,7 +2500,7 @@ var AgentID = class {
|
|
|
2328
2500
|
const guardCacheKey = this.buildGuardCacheKey(payload);
|
|
2329
2501
|
const cachedVerdict = this.readCachedGuardVerdict(guardCacheKey);
|
|
2330
2502
|
if (cachedVerdict) {
|
|
2331
|
-
return cachedVerdict;
|
|
2503
|
+
return withGuardLatency(cachedVerdict);
|
|
2332
2504
|
}
|
|
2333
2505
|
const correlationId = createCorrelationId(payload.client_event_id);
|
|
2334
2506
|
let lastStatusCode = null;
|
|
@@ -2352,7 +2524,12 @@ var AgentID = class {
|
|
|
2352
2524
|
lastStatusCode = res.status;
|
|
2353
2525
|
const responseBody = await safeReadJson2(res);
|
|
2354
2526
|
if (responseBody && typeof responseBody.allowed === "boolean") {
|
|
2355
|
-
const
|
|
2527
|
+
const rawVerdict = responseBody;
|
|
2528
|
+
const transparency = coerceTransparencyMetadata(rawVerdict.transparency);
|
|
2529
|
+
const verdict = {
|
|
2530
|
+
...rawVerdict,
|
|
2531
|
+
...transparency ? { transparency } : {}
|
|
2532
|
+
};
|
|
2356
2533
|
const infrastructureFailure = verdict.allowed === false && (isInfrastructureGuardReason(verdict.reason) || !verdict.reason && res.status >= 500);
|
|
2357
2534
|
if (infrastructureFailure) {
|
|
2358
2535
|
if (attempt < GUARD_MAX_ATTEMPTS - 1) {
|
|
@@ -2363,7 +2540,10 @@ var AgentID = class {
|
|
|
2363
2540
|
console.warn(
|
|
2364
2541
|
`[AgentID] Guard API infrastructure failure in strict mode (${verdict.reason ?? `http_${res.status}`}). Blocking request.`
|
|
2365
2542
|
);
|
|
2366
|
-
return {
|
|
2543
|
+
return withGuardLatency({
|
|
2544
|
+
allowed: false,
|
|
2545
|
+
reason: verdict.reason ?? "network_error_strict_mode"
|
|
2546
|
+
});
|
|
2367
2547
|
}
|
|
2368
2548
|
console.warn(
|
|
2369
2549
|
`[AgentID] Guard API infrastructure fallback in fail-open mode (${verdict.reason ?? `http_${res.status}`}).`
|
|
@@ -2374,10 +2554,10 @@ var AgentID = class {
|
|
|
2374
2554
|
guardParams: params,
|
|
2375
2555
|
apiKey: effectiveApiKey
|
|
2376
2556
|
});
|
|
2377
|
-
return { allowed: true, reason: "system_failure_fail_open" };
|
|
2557
|
+
return withGuardLatency({ allowed: true, reason: "system_failure_fail_open" });
|
|
2378
2558
|
}
|
|
2379
2559
|
this.cacheGuardVerdict(guardCacheKey, verdict);
|
|
2380
|
-
return verdict;
|
|
2560
|
+
return withGuardLatency(verdict);
|
|
2381
2561
|
}
|
|
2382
2562
|
if (!res.ok) {
|
|
2383
2563
|
if (res.status >= 500 && attempt < GUARD_MAX_ATTEMPTS - 1) {
|
|
@@ -2407,9 +2587,9 @@ var AgentID = class {
|
|
|
2407
2587
|
apiKey: effectiveApiKey
|
|
2408
2588
|
});
|
|
2409
2589
|
if (effectiveStrictMode) {
|
|
2410
|
-
return { allowed: false, reason: "network_error_strict_mode" };
|
|
2590
|
+
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
2411
2591
|
}
|
|
2412
|
-
return { allowed: true, reason: "timeout_fallback" };
|
|
2592
|
+
return withGuardLatency({ allowed: true, reason: "timeout_fallback" });
|
|
2413
2593
|
}
|
|
2414
2594
|
console.warn(
|
|
2415
2595
|
effectiveStrictMode ? "[AgentID] Guard check failed (Strict mode active):" : "[AgentID] Guard check failed (Fail-Open active):",
|
|
@@ -2422,33 +2602,33 @@ var AgentID = class {
|
|
|
2422
2602
|
apiKey: effectiveApiKey
|
|
2423
2603
|
});
|
|
2424
2604
|
if (effectiveStrictMode) {
|
|
2425
|
-
return { allowed: false, reason: "network_error_strict_mode" };
|
|
2605
|
+
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
2426
2606
|
}
|
|
2427
|
-
return { allowed: true, reason: "guard_unreachable" };
|
|
2607
|
+
return withGuardLatency({ allowed: true, reason: "guard_unreachable" });
|
|
2428
2608
|
} finally {
|
|
2429
2609
|
clearTimeout(timeoutId);
|
|
2430
2610
|
}
|
|
2431
2611
|
}
|
|
2432
2612
|
if (lastAbort) {
|
|
2433
2613
|
if (effectiveStrictMode) {
|
|
2434
|
-
return { allowed: false, reason: "network_error_strict_mode" };
|
|
2614
|
+
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
2435
2615
|
}
|
|
2436
|
-
return { allowed: true, reason: "timeout_fallback" };
|
|
2616
|
+
return withGuardLatency({ allowed: true, reason: "timeout_fallback" });
|
|
2437
2617
|
}
|
|
2438
2618
|
if (typeof lastStatusCode === "number" && lastStatusCode >= 500) {
|
|
2439
2619
|
if (effectiveStrictMode) {
|
|
2440
|
-
return { allowed: false, reason: "server_error" };
|
|
2620
|
+
return withGuardLatency({ allowed: false, reason: "server_error" });
|
|
2441
2621
|
}
|
|
2442
|
-
return { allowed: true, reason: "system_failure_fail_open" };
|
|
2622
|
+
return withGuardLatency({ allowed: true, reason: "system_failure_fail_open" });
|
|
2443
2623
|
}
|
|
2444
2624
|
console.warn(
|
|
2445
2625
|
effectiveStrictMode ? "[AgentID] Guard check failed (Strict mode active):" : "[AgentID] Guard check failed (Fail-Open active):",
|
|
2446
2626
|
lastError
|
|
2447
2627
|
);
|
|
2448
2628
|
if (effectiveStrictMode) {
|
|
2449
|
-
return { allowed: false, reason: "network_error_strict_mode" };
|
|
2629
|
+
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
2450
2630
|
}
|
|
2451
|
-
return { allowed: true, reason: "guard_unreachable" };
|
|
2631
|
+
return withGuardLatency({ allowed: true, reason: "guard_unreachable" });
|
|
2452
2632
|
}
|
|
2453
2633
|
async sendIngest(params, options) {
|
|
2454
2634
|
const effectiveApiKey = this.resolveApiKey(options?.apiKey);
|
|
@@ -2457,13 +2637,18 @@ var AgentID = class {
|
|
|
2457
2637
|
const metadata = {
|
|
2458
2638
|
...params.metadata ?? {}
|
|
2459
2639
|
};
|
|
2640
|
+
const metadataClientEventId = typeof metadata.client_event_id === "string" && isUuidLike(metadata.client_event_id) ? metadata.client_event_id : null;
|
|
2641
|
+
const canonicalClientEventId = metadataClientEventId ?? eventId;
|
|
2642
|
+
if (!metadataClientEventId) {
|
|
2643
|
+
metadata.client_event_id = canonicalClientEventId;
|
|
2644
|
+
}
|
|
2460
2645
|
if (!Object.prototype.hasOwnProperty.call(metadata, "agentid_base_url")) {
|
|
2461
2646
|
metadata.agentid_base_url = this.baseUrl;
|
|
2462
2647
|
}
|
|
2463
2648
|
void this.getCapabilityConfig(false, { apiKey: effectiveApiKey }).catch(() => void 0);
|
|
2464
2649
|
const payload = {
|
|
2465
2650
|
...params,
|
|
2466
|
-
event_id:
|
|
2651
|
+
event_id: canonicalClientEventId,
|
|
2467
2652
|
timestamp,
|
|
2468
2653
|
input: sanitizeIngestText(params.input),
|
|
2469
2654
|
output: sanitizeIngestText(params.output),
|
|
@@ -2480,6 +2665,7 @@ var AgentID = class {
|
|
|
2480
2665
|
headers: {
|
|
2481
2666
|
"Content-Type": "application/json",
|
|
2482
2667
|
"x-agentid-api-key": effectiveApiKey,
|
|
2668
|
+
"x-correlation-id": canonicalClientEventId,
|
|
2483
2669
|
"X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER
|
|
2484
2670
|
},
|
|
2485
2671
|
body: JSON.stringify(payload),
|
|
@@ -2663,6 +2849,7 @@ var AgentID = class {
|
|
|
2663
2849
|
return async (...args) => {
|
|
2664
2850
|
const normalizedCreateArgs = normalizeOpenAICreateArgs(args);
|
|
2665
2851
|
const req = normalizedCreateArgs?.[0] ?? {};
|
|
2852
|
+
const pipelineStartedAt = Date.now();
|
|
2666
2853
|
const requestLevelApiKey = options.resolveApiKey?.(req) ?? options.apiKey ?? options.api_key;
|
|
2667
2854
|
const effectiveApiKey = this.resolveApiKey(requestLevelApiKey);
|
|
2668
2855
|
const requestOptions = { apiKey: effectiveApiKey };
|
|
@@ -2730,6 +2917,8 @@ var AgentID = class {
|
|
|
2730
2917
|
}
|
|
2731
2918
|
const canonicalClientEventId = typeof verdict.client_event_id === "string" && isUuidLike(verdict.client_event_id) ? verdict.client_event_id : clientEventId;
|
|
2732
2919
|
const guardEventId = typeof verdict.guard_event_id === "string" && verdict.guard_event_id.length > 0 ? verdict.guard_event_id : null;
|
|
2920
|
+
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);
|
|
2921
|
+
const transparency = coerceTransparencyMetadata(verdict.transparency);
|
|
2733
2922
|
const isShadowMode = verdict.shadow_mode === true;
|
|
2734
2923
|
const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
|
|
2735
2924
|
if (transformedInput !== maskedText) {
|
|
@@ -2743,6 +2932,7 @@ var AgentID = class {
|
|
|
2743
2932
|
createArgs = nextCreateArgs;
|
|
2744
2933
|
}
|
|
2745
2934
|
if (stream) {
|
|
2935
|
+
const modelStartedAt2 = Date.now();
|
|
2746
2936
|
const streamResponse = await originalCreate.apply(compTarget, createArgs);
|
|
2747
2937
|
const wrappedCompletion = this.wrapCompletion(
|
|
2748
2938
|
isAsyncIterable(streamResponse) ? streamResponse : (async function* () {
|
|
@@ -2753,6 +2943,8 @@ var AgentID = class {
|
|
|
2753
2943
|
);
|
|
2754
2944
|
if (maskedText && wrappedCompletion.mode === "stream") {
|
|
2755
2945
|
void wrappedCompletion.done.then(async (result) => {
|
|
2946
|
+
const modelLatencyMs2 = Math.max(0, Date.now() - modelStartedAt2);
|
|
2947
|
+
const totalPipelineLatencyMs2 = Math.max(0, Date.now() - pipelineStartedAt);
|
|
2756
2948
|
const outputForLog = isShadowMode ? result.rawOutput : result.transformedOutput;
|
|
2757
2949
|
const ingestResult = await this.sendIngest({
|
|
2758
2950
|
event_id: canonicalClientEventId,
|
|
@@ -2762,7 +2954,7 @@ var AgentID = class {
|
|
|
2762
2954
|
output: outputForLog,
|
|
2763
2955
|
model: adapter.getModelName(maskedReq),
|
|
2764
2956
|
usage: void 0,
|
|
2765
|
-
latency:
|
|
2957
|
+
latency: modelLatencyMs2,
|
|
2766
2958
|
event_type: "complete",
|
|
2767
2959
|
metadata: {
|
|
2768
2960
|
transformed_input: maskedText,
|
|
@@ -2772,8 +2964,12 @@ var AgentID = class {
|
|
|
2772
2964
|
simulated_decision: verdict.simulated_decision ?? null,
|
|
2773
2965
|
simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
|
|
2774
2966
|
response_streamed: true,
|
|
2967
|
+
guard_latency_ms: guardLatencyMs,
|
|
2968
|
+
model_latency_ms: modelLatencyMs2,
|
|
2969
|
+
total_pipeline_latency_ms: totalPipelineLatencyMs2,
|
|
2775
2970
|
guard_event_id: guardEventId,
|
|
2776
|
-
client_event_id: canonicalClientEventId
|
|
2971
|
+
client_event_id: canonicalClientEventId,
|
|
2972
|
+
transparency
|
|
2777
2973
|
},
|
|
2778
2974
|
client_capabilities: this.buildClientCapabilities("openai", false)
|
|
2779
2975
|
}, requestOptions);
|
|
@@ -2786,11 +2982,15 @@ var AgentID = class {
|
|
|
2786
2982
|
console.error("[AgentID] Stream completion wrapping failed:", error);
|
|
2787
2983
|
});
|
|
2788
2984
|
}
|
|
2789
|
-
|
|
2985
|
+
if (wrappedCompletion.mode === "stream") {
|
|
2986
|
+
return attachTransparencyMetadata(wrappedCompletion.completion, transparency);
|
|
2987
|
+
}
|
|
2988
|
+
return attachTransparencyMetadata(streamResponse, transparency);
|
|
2790
2989
|
}
|
|
2791
|
-
const
|
|
2990
|
+
const modelStartedAt = Date.now();
|
|
2792
2991
|
const res = await originalCreate.apply(compTarget, createArgs);
|
|
2793
|
-
const
|
|
2992
|
+
const modelLatencyMs = Math.max(0, Date.now() - modelStartedAt);
|
|
2993
|
+
const totalPipelineLatencyMs = Math.max(0, Date.now() - pipelineStartedAt);
|
|
2794
2994
|
if (maskedText) {
|
|
2795
2995
|
const output = adapter.extractOutput(res);
|
|
2796
2996
|
const wrappedCompletion = this.wrapCompletion(output);
|
|
@@ -2805,7 +3005,7 @@ var AgentID = class {
|
|
|
2805
3005
|
output: outputForLog,
|
|
2806
3006
|
model,
|
|
2807
3007
|
usage,
|
|
2808
|
-
latency,
|
|
3008
|
+
latency: modelLatencyMs,
|
|
2809
3009
|
event_type: "complete",
|
|
2810
3010
|
metadata: {
|
|
2811
3011
|
transformed_input: maskedText,
|
|
@@ -2815,8 +3015,12 @@ var AgentID = class {
|
|
|
2815
3015
|
simulated_decision: verdict.simulated_decision ?? null,
|
|
2816
3016
|
simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
|
|
2817
3017
|
response_streamed: false,
|
|
3018
|
+
guard_latency_ms: guardLatencyMs,
|
|
3019
|
+
model_latency_ms: modelLatencyMs,
|
|
3020
|
+
total_pipeline_latency_ms: totalPipelineLatencyMs,
|
|
2818
3021
|
guard_event_id: guardEventId,
|
|
2819
|
-
client_event_id: canonicalClientEventId
|
|
3022
|
+
client_event_id: canonicalClientEventId,
|
|
3023
|
+
transparency
|
|
2820
3024
|
},
|
|
2821
3025
|
client_capabilities: this.buildClientCapabilities("openai", false)
|
|
2822
3026
|
}, requestOptions);
|
|
@@ -2843,7 +3047,7 @@ var AgentID = class {
|
|
|
2843
3047
|
} catch {
|
|
2844
3048
|
}
|
|
2845
3049
|
}
|
|
2846
|
-
return res;
|
|
3050
|
+
return attachTransparencyMetadata(res, transparency);
|
|
2847
3051
|
};
|
|
2848
3052
|
}
|
|
2849
3053
|
});
|
|
@@ -2861,9 +3065,169 @@ var AgentID = class {
|
|
|
2861
3065
|
});
|
|
2862
3066
|
}
|
|
2863
3067
|
};
|
|
3068
|
+
|
|
3069
|
+
// src/transparency-badge.tsx
|
|
3070
|
+
var React = __toESM(require("react"));
|
|
3071
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
3072
|
+
var DEFAULT_MESSAGE = "You are interacting with an AI.";
|
|
3073
|
+
var DEFAULT_BASE_URL = "https://api.getagentid.com/v1";
|
|
3074
|
+
function resolveBadgeMessage(params) {
|
|
3075
|
+
if (typeof params.message === "string" && params.message.trim().length > 0) {
|
|
3076
|
+
return params.message.trim();
|
|
3077
|
+
}
|
|
3078
|
+
if (params.metadata?.disclosure) {
|
|
3079
|
+
return params.metadata.disclosure;
|
|
3080
|
+
}
|
|
3081
|
+
return DEFAULT_MESSAGE;
|
|
3082
|
+
}
|
|
3083
|
+
function normalizeBaseUrl4(baseUrl) {
|
|
3084
|
+
const candidate = typeof baseUrl === "string" && baseUrl.trim().length > 0 ? baseUrl.trim() : DEFAULT_BASE_URL;
|
|
3085
|
+
return candidate.replace(/\/+$/, "");
|
|
3086
|
+
}
|
|
3087
|
+
function createEventId2() {
|
|
3088
|
+
try {
|
|
3089
|
+
if (typeof globalThis !== "undefined" && globalThis.crypto?.randomUUID) {
|
|
3090
|
+
return globalThis.crypto.randomUUID();
|
|
3091
|
+
}
|
|
3092
|
+
} catch {
|
|
3093
|
+
}
|
|
3094
|
+
const seed = Math.random().toString(16).slice(2).padEnd(12, "0").slice(0, 12);
|
|
3095
|
+
return `00000000-0000-4000-8000-${seed}`;
|
|
3096
|
+
}
|
|
3097
|
+
async function sendTransparencyBadgeRenderedTelemetry(params) {
|
|
3098
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3099
|
+
const eventId = createEventId2();
|
|
3100
|
+
const payload = {
|
|
3101
|
+
event_id: eventId,
|
|
3102
|
+
system_id: params.telemetry.systemId,
|
|
3103
|
+
input: "__agentid_transparency_badge_rendered__",
|
|
3104
|
+
output: params.disclosureText,
|
|
3105
|
+
model: params.telemetry.model ?? "agentid-transparency-badge",
|
|
3106
|
+
user_id: params.telemetry.userId,
|
|
3107
|
+
event_type: "transparency_badge_rendered",
|
|
3108
|
+
severity: "info",
|
|
3109
|
+
timestamp,
|
|
3110
|
+
metadata: {
|
|
3111
|
+
compliance_event: "transparency_badge_rendered",
|
|
3112
|
+
rendered_at: timestamp,
|
|
3113
|
+
placement: params.placement,
|
|
3114
|
+
disclosure_text: params.disclosureText,
|
|
3115
|
+
...params.telemetry.metadata ?? {}
|
|
3116
|
+
}
|
|
3117
|
+
};
|
|
3118
|
+
const targetIngestUrl = typeof params.telemetry.ingestUrl === "string" && params.telemetry.ingestUrl.trim().length > 0 ? params.telemetry.ingestUrl.trim() : `${normalizeBaseUrl4(params.telemetry.baseUrl)}/ingest`;
|
|
3119
|
+
const headers = {
|
|
3120
|
+
"Content-Type": "application/json",
|
|
3121
|
+
"X-AgentID-SDK-Version": "js-1.1.0",
|
|
3122
|
+
...params.telemetry.headers ?? {}
|
|
3123
|
+
};
|
|
3124
|
+
if (typeof params.telemetry.apiKey === "string" && params.telemetry.apiKey.trim().length > 0) {
|
|
3125
|
+
headers["x-agentid-api-key"] = params.telemetry.apiKey.trim();
|
|
3126
|
+
}
|
|
3127
|
+
const response = await fetch(targetIngestUrl, {
|
|
3128
|
+
method: "POST",
|
|
3129
|
+
headers,
|
|
3130
|
+
body: JSON.stringify(payload),
|
|
3131
|
+
keepalive: true
|
|
3132
|
+
});
|
|
3133
|
+
if (!response.ok) {
|
|
3134
|
+
throw new Error(
|
|
3135
|
+
`AgentID transparency badge telemetry failed (status=${response.status})`
|
|
3136
|
+
);
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
function AgentIDTransparencyBadge(props) {
|
|
3140
|
+
const placement = props.placement ?? "chat-header";
|
|
3141
|
+
const fixed = props.fixed ?? true;
|
|
3142
|
+
const text = resolveBadgeMessage({
|
|
3143
|
+
metadata: props.metadata,
|
|
3144
|
+
message: props.message
|
|
3145
|
+
});
|
|
3146
|
+
const hasLoggedRenderRef = React.useRef(false);
|
|
3147
|
+
React.useEffect(() => {
|
|
3148
|
+
if (hasLoggedRenderRef.current) {
|
|
3149
|
+
return;
|
|
3150
|
+
}
|
|
3151
|
+
hasLoggedRenderRef.current = true;
|
|
3152
|
+
void sendTransparencyBadgeRenderedTelemetry({
|
|
3153
|
+
telemetry: props.telemetry,
|
|
3154
|
+
disclosureText: text,
|
|
3155
|
+
placement
|
|
3156
|
+
}).catch((error) => {
|
|
3157
|
+
if (typeof props.telemetry.onError === "function") {
|
|
3158
|
+
props.telemetry.onError(error);
|
|
3159
|
+
return;
|
|
3160
|
+
}
|
|
3161
|
+
console.warn(error);
|
|
3162
|
+
});
|
|
3163
|
+
}, [placement, props.telemetry, text]);
|
|
3164
|
+
const containerStyle = placement === "watermark-overlay" ? {
|
|
3165
|
+
position: fixed ? "fixed" : "absolute",
|
|
3166
|
+
right: 16,
|
|
3167
|
+
bottom: 16,
|
|
3168
|
+
zIndex: 2147483e3,
|
|
3169
|
+
pointerEvents: "none",
|
|
3170
|
+
opacity: 0.95
|
|
3171
|
+
} : {
|
|
3172
|
+
position: fixed ? "fixed" : "sticky",
|
|
3173
|
+
top: 0,
|
|
3174
|
+
left: 0,
|
|
3175
|
+
right: 0,
|
|
3176
|
+
zIndex: 2147483e3,
|
|
3177
|
+
pointerEvents: "none"
|
|
3178
|
+
};
|
|
3179
|
+
const badgeStyle = placement === "watermark-overlay" ? {
|
|
3180
|
+
display: "inline-flex",
|
|
3181
|
+
alignItems: "center",
|
|
3182
|
+
gap: 8,
|
|
3183
|
+
background: "rgba(15, 23, 42, 0.9)",
|
|
3184
|
+
color: "#f8fafc",
|
|
3185
|
+
borderRadius: 9999,
|
|
3186
|
+
padding: "8px 12px",
|
|
3187
|
+
fontFamily: "ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif",
|
|
3188
|
+
fontSize: 12,
|
|
3189
|
+
fontWeight: 600,
|
|
3190
|
+
boxShadow: "0 8px 24px rgba(15, 23, 42, 0.28)",
|
|
3191
|
+
pointerEvents: "none"
|
|
3192
|
+
} : {
|
|
3193
|
+
display: "flex",
|
|
3194
|
+
alignItems: "center",
|
|
3195
|
+
justifyContent: "center",
|
|
3196
|
+
gap: 8,
|
|
3197
|
+
background: "#0f172a",
|
|
3198
|
+
color: "#f8fafc",
|
|
3199
|
+
borderBottom: "1px solid rgba(148, 163, 184, 0.35)",
|
|
3200
|
+
padding: "9px 12px",
|
|
3201
|
+
fontFamily: "ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif",
|
|
3202
|
+
fontSize: 13,
|
|
3203
|
+
fontWeight: 600,
|
|
3204
|
+
pointerEvents: "none"
|
|
3205
|
+
};
|
|
3206
|
+
const iconStyle = {
|
|
3207
|
+
width: 22,
|
|
3208
|
+
height: 22,
|
|
3209
|
+
minWidth: 22,
|
|
3210
|
+
borderRadius: 9999,
|
|
3211
|
+
background: "#2563eb",
|
|
3212
|
+
color: "#eff6ff",
|
|
3213
|
+
display: "inline-flex",
|
|
3214
|
+
alignItems: "center",
|
|
3215
|
+
justifyContent: "center",
|
|
3216
|
+
fontSize: 10,
|
|
3217
|
+
fontWeight: 800,
|
|
3218
|
+
letterSpacing: 0.5,
|
|
3219
|
+
lineHeight: 1,
|
|
3220
|
+
border: "1px solid rgba(191, 219, 254, 0.55)"
|
|
3221
|
+
};
|
|
3222
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: props.className, style: containerStyle, "aria-live": "polite", role: "status", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: badgeStyle, children: [
|
|
3223
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", style: iconStyle, children: "AI" }),
|
|
3224
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: text })
|
|
3225
|
+
] }) });
|
|
3226
|
+
}
|
|
2864
3227
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2865
3228
|
0 && (module.exports = {
|
|
2866
3229
|
AgentID,
|
|
3230
|
+
AgentIDTransparencyBadge,
|
|
2867
3231
|
InjectionScanner,
|
|
2868
3232
|
OpenAIAdapter,
|
|
2869
3233
|
PIIManager,
|