agentid-sdk 0.1.37 → 0.1.40

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.
@@ -1,14 +1,86 @@
1
1
  // src/adapters.ts
2
+ function getLastUserMessage(req) {
3
+ const messages = req?.messages;
4
+ if (!Array.isArray(messages)) return null;
5
+ let lastUser = null;
6
+ for (const msg of messages) {
7
+ if (msg && typeof msg === "object" && msg.role === "user") {
8
+ lastUser = msg;
9
+ }
10
+ }
11
+ return lastUser;
12
+ }
13
+ function normalizeFilename(value, fallback) {
14
+ if (typeof value !== "string") {
15
+ return fallback;
16
+ }
17
+ const trimmed = value.trim();
18
+ return trimmed.length > 0 ? trimmed : fallback;
19
+ }
20
+ function parseDataUrl(value) {
21
+ if (!value.startsWith("data:")) {
22
+ return null;
23
+ }
24
+ const commaIndex = value.indexOf(",");
25
+ if (commaIndex === -1) {
26
+ return null;
27
+ }
28
+ const header = value.slice(5, commaIndex);
29
+ if (!/;base64/i.test(header)) {
30
+ return null;
31
+ }
32
+ const mimeType = header.split(";")[0]?.trim().toLowerCase() || null;
33
+ return { mimeType };
34
+ }
35
+ function inferAttachmentExtension(mimeType) {
36
+ switch (mimeType) {
37
+ case "application/pdf":
38
+ return "pdf";
39
+ case "image/png":
40
+ return "png";
41
+ case "image/jpeg":
42
+ return "jpg";
43
+ case "image/webp":
44
+ return "webp";
45
+ case "image/gif":
46
+ return "gif";
47
+ case "text/plain":
48
+ return "txt";
49
+ default:
50
+ return "bin";
51
+ }
52
+ }
53
+ function defaultFilenameForMimeType(mimeType) {
54
+ return `attachment.${inferAttachmentExtension(mimeType)}`;
55
+ }
56
+ function normalizeFileAttachment(part) {
57
+ const file = part?.file;
58
+ const rawContent = typeof file?.file_data === "string" && file.file_data.trim().length > 0 ? file.file_data.trim() : null;
59
+ if (!rawContent) {
60
+ return null;
61
+ }
62
+ const detectedMimeType = parseDataUrl(rawContent)?.mimeType ?? null;
63
+ return {
64
+ filename: normalizeFilename(file?.filename, defaultFilenameForMimeType(detectedMimeType)),
65
+ ...detectedMimeType ? { mime_type: detectedMimeType } : {},
66
+ content_base64: rawContent
67
+ };
68
+ }
69
+ function normalizeImageAttachment(part) {
70
+ const imageUrl = typeof part?.image_url?.url === "string" && part.image_url.url.trim().length > 0 ? part.image_url.url.trim() : null;
71
+ if (!imageUrl || !imageUrl.startsWith("data:")) {
72
+ return null;
73
+ }
74
+ const detectedMimeType = parseDataUrl(imageUrl)?.mimeType ?? "image/png";
75
+ return {
76
+ filename: defaultFilenameForMimeType(detectedMimeType),
77
+ mime_type: detectedMimeType,
78
+ content_base64: imageUrl
79
+ };
80
+ }
2
81
  var OpenAIAdapter = class {
3
82
  extractInput(req) {
4
- const messages = req?.messages;
5
- if (!Array.isArray(messages)) return null;
6
- let lastUser = null;
7
- for (const msg of messages) {
8
- if (msg && typeof msg === "object" && msg.role === "user") {
9
- lastUser = msg;
10
- }
11
- }
83
+ const lastUser = getLastUserMessage(req);
12
84
  if (!lastUser) return null;
13
85
  const content = lastUser.content;
14
86
  if (typeof content === "string") return content;
@@ -23,6 +95,34 @@ var OpenAIAdapter = class {
23
95
  }
24
96
  return null;
25
97
  }
98
+ extractAttachments(req) {
99
+ const lastUser = getLastUserMessage(req);
100
+ if (!lastUser) return [];
101
+ const content = lastUser?.content;
102
+ if (!Array.isArray(content)) {
103
+ return [];
104
+ }
105
+ const attachments = [];
106
+ for (const part of content) {
107
+ if (!part || typeof part !== "object") {
108
+ continue;
109
+ }
110
+ if (part.type === "file") {
111
+ const attachment = normalizeFileAttachment(part);
112
+ if (attachment) {
113
+ attachments.push(attachment);
114
+ }
115
+ continue;
116
+ }
117
+ if (part.type === "image_url") {
118
+ const attachment = normalizeImageAttachment(part);
119
+ if (attachment) {
120
+ attachments.push(attachment);
121
+ }
122
+ }
123
+ }
124
+ return attachments;
125
+ }
26
126
  getModelName(req, res) {
27
127
  const model = res?.model ?? req?.model ?? "unknown";
28
128
  return String(model);
@@ -902,8 +1002,173 @@ function detectNationalIdentifiers(text, options = {}) {
902
1002
  return results;
903
1003
  }
904
1004
 
1005
+ // src/secret-patterns.ts
1006
+ var SDK_SECRET_PATTERN_DEFINITIONS = [
1007
+ {
1008
+ id: "openai_api_key",
1009
+ placeholderType: "OPENAI_API_KEY",
1010
+ patternSource: "\\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\\b",
1011
+ flags: "iu",
1012
+ prefilterTerms: ["sk-", "proj-", "openai"]
1013
+ },
1014
+ {
1015
+ id: "aws_access_key",
1016
+ placeholderType: "AWS_ACCESS_KEY",
1017
+ patternSource: "\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b",
1018
+ flags: "iu",
1019
+ prefilterTerms: ["akia", "asia", "aws"]
1020
+ },
1021
+ {
1022
+ id: "github_token",
1023
+ placeholderType: "GITHUB_TOKEN",
1024
+ patternSource: "\\b(?:gh[pousr]_[A-Za-z0-9]{24,255}|github_pat_[A-Za-z0-9_]{20,255})\\b",
1025
+ flags: "iu",
1026
+ prefilterTerms: ["ghp_", "gho_", "ghu_", "ghs_", "ghr_", "github_pat_"]
1027
+ },
1028
+ {
1029
+ id: "slack_token",
1030
+ placeholderType: "SLACK_TOKEN",
1031
+ patternSource: "\\bxox(?:a|b|p|r|s)-[A-Za-z0-9-]{10,200}\\b",
1032
+ flags: "iu",
1033
+ prefilterTerms: ["xoxa-", "xoxb-", "xoxp-", "xoxr-", "xoxs-", "slack"]
1034
+ },
1035
+ {
1036
+ id: "slack_webhook_url",
1037
+ placeholderType: "SLACK_WEBHOOK_URL",
1038
+ patternSource: "https:\\/\\/hooks\\.slack\\.com\\/services\\/[A-Za-z0-9/_-]{20,}",
1039
+ flags: "iu",
1040
+ prefilterTerms: ["hooks.slack.com/services", "slack"]
1041
+ },
1042
+ {
1043
+ id: "discord_webhook_url",
1044
+ placeholderType: "DISCORD_WEBHOOK_URL",
1045
+ patternSource: "https:\\/\\/discord(?:app)?\\.com\\/api\\/webhooks\\/\\d+\\/[A-Za-z0-9_-]{16,}",
1046
+ flags: "iu",
1047
+ prefilterTerms: ["discord.com/api/webhooks", "discordapp.com/api/webhooks", "discord"]
1048
+ },
1049
+ {
1050
+ id: "stripe_secret_key",
1051
+ placeholderType: "STRIPE_SECRET_KEY",
1052
+ patternSource: "\\b(?:sk|pk|ak|rk)_(?:live|test)_[A-Za-z0-9]+\\b",
1053
+ flags: "iu",
1054
+ prefilterTerms: [
1055
+ "sk_live_",
1056
+ "pk_live_",
1057
+ "sk_test_",
1058
+ "pk_test_",
1059
+ "ak_live_",
1060
+ "ak_test_",
1061
+ "rk_live_",
1062
+ "rk_test_",
1063
+ "stripe"
1064
+ ]
1065
+ },
1066
+ {
1067
+ id: "google_api_key",
1068
+ placeholderType: "GOOGLE_API_KEY",
1069
+ patternSource: "\\bAIza[0-9A-Za-z_-]{35}\\b",
1070
+ flags: "iu",
1071
+ prefilterTerms: ["aiza", "google"]
1072
+ },
1073
+ {
1074
+ id: "anthropic_api_key",
1075
+ placeholderType: "ANTHROPIC_API_KEY",
1076
+ patternSource: "\\bsk-ant-(?:api\\d{2}-)?[A-Za-z0-9_-]{20,}\\b",
1077
+ flags: "iu",
1078
+ prefilterTerms: ["sk-ant-", "anthropic"]
1079
+ },
1080
+ {
1081
+ id: "evm_private_key",
1082
+ placeholderType: "EVM_PRIVATE_KEY",
1083
+ patternSource: "\\b0x[a-fA-F0-9]{64}\\b",
1084
+ flags: "iu",
1085
+ prefilterTerms: ["0x", "ethereum", "evm", "private key"]
1086
+ },
1087
+ {
1088
+ id: "jwt_token",
1089
+ placeholderType: "JWT_TOKEN",
1090
+ patternSource: "\\beyJ[A-Za-z0-9_-]{6,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\b",
1091
+ flags: "iu",
1092
+ prefilterTerms: ["eyj", "jwt", "bearer"]
1093
+ },
1094
+ {
1095
+ id: "bearer_token",
1096
+ placeholderType: "BEARER_TOKEN",
1097
+ patternSource: "\\bauthorization\\b\\s*[:=]\\s*bearer\\s+[A-Za-z0-9._~+\\/-]{16,}|\\bbearer\\s+[A-Za-z0-9._~+\\/-]{24,}",
1098
+ flags: "iu",
1099
+ prefilterTerms: ["authorization", "bearer"]
1100
+ },
1101
+ {
1102
+ id: "api_key_header",
1103
+ placeholderType: "API_KEY_HEADER",
1104
+ patternSource: "\\bx[-_]?api[-_]?key\\b\\s*[:=]\\s*[A-Za-z0-9._~+\\/-]{16,}",
1105
+ flags: "iu",
1106
+ prefilterTerms: ["x-api-key", "api-key", "x_api_key", "api_key"]
1107
+ },
1108
+ {
1109
+ id: "credential_assignment",
1110
+ placeholderType: "CREDENTIAL_ASSIGNMENT",
1111
+ patternSource: `(?:\\b|["'])(?:api(?:[_-]?|\\s+)key|access(?:[_-]?|\\s+)token|auth(?:[_-]?|\\s+)token|client(?:[_-]?|\\s+)secret|private(?:[_-]?|\\s+)key)(?:\\b|["'])\\s*(?::|=|=>)\\s*(?:"[A-Za-z0-9._~+\\/=:-]{16,}"|'[A-Za-z0-9._~+\\/=:-]{16,}'|[A-Za-z0-9._~+\\/=:-]{16,})`,
1112
+ flags: "iu",
1113
+ prefilterTerms: [
1114
+ "api key",
1115
+ "apikey",
1116
+ "api_key",
1117
+ "access token",
1118
+ "access_token",
1119
+ "auth token",
1120
+ "client secret",
1121
+ "private key"
1122
+ ]
1123
+ },
1124
+ {
1125
+ id: "password_assignment",
1126
+ placeholderType: "PASSWORD_ASSIGNMENT",
1127
+ patternSource: `(?:\\b|["'])(?:password|passwd|pwd|heslo)(?:\\b|["'])\\s*(?:(?::|=|=>)|(?:is|are|was|were|je)\\b)?\\s*(?:"[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,}"|'[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,}'|[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,})`,
1128
+ flags: "iu",
1129
+ prefilterTerms: ["password", "passwd", "pwd", "heslo"]
1130
+ },
1131
+ {
1132
+ id: "private_key_material",
1133
+ placeholderType: "PRIVATE_KEY_MATERIAL",
1134
+ patternSource: "-----BEGIN (?:(?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY|PGP PRIVATE KEY BLOCK|CERTIFICATE)-----[\\s\\S]{20,12000}(?:-----END (?:(?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY|PGP PRIVATE KEY BLOCK|CERTIFICATE)-----|$)",
1135
+ flags: "iu",
1136
+ prefilterTerms: ["begin private key", "begin pgp private key block", "private key"]
1137
+ },
1138
+ {
1139
+ id: "azure_connection_string",
1140
+ placeholderType: "AZURE_CONNECTION_STRING",
1141
+ patternSource: "\\bDefaultEndpointsProtocol=https;AccountName=[A-Za-z0-9.-]{3,};AccountKey=[A-Za-z0-9+/=]{20,}(?:;EndpointSuffix=[A-Za-z0-9.-]+)?\\b",
1142
+ flags: "iu",
1143
+ prefilterTerms: ["defaultendpointsprotocol", "accountname", "accountkey", "azure"]
1144
+ },
1145
+ {
1146
+ id: "azure_sas_token",
1147
+ placeholderType: "AZURE_SAS_TOKEN",
1148
+ patternSource: "\\bsv=[^\\s&]{2,}&[^\\s]{0,200}\\bsig=[A-Za-z0-9%/+_-]{16,}",
1149
+ flags: "iu",
1150
+ prefilterTerms: ["sv=", "sig=", "accountkey", "azure"]
1151
+ }
1152
+ ];
1153
+ function ensureGlobalFlag(flags) {
1154
+ const normalized = new Set(flags.split(""));
1155
+ normalized.add("g");
1156
+ return [...normalized].join("");
1157
+ }
1158
+ var COMPILED_SDK_SECRET_PATTERNS = SDK_SECRET_PATTERN_DEFINITIONS.map((definition) => ({
1159
+ ...definition,
1160
+ scanRegex: new RegExp(definition.patternSource, ensureGlobalFlag(definition.flags)),
1161
+ prefilterTermsLower: definition.prefilterTerms.map((term) => term.toLowerCase())
1162
+ }));
1163
+ function getSdkSecretDetectionMatchers() {
1164
+ return COMPILED_SDK_SECRET_PATTERNS;
1165
+ }
1166
+
905
1167
  // src/pii.ts
906
1168
  var defaultScanDeadlineMs = 100;
1169
+ var sdkSecretMatchers = getSdkSecretDetectionMatchers();
1170
+ var DISCORD_WEBHOOK_TOKEN_RE = /https:\/\/discord(?:app)?\.com\/api\/webhooks\/\d+\/([A-Za-z0-9_-]{16,})/giu;
1171
+ var BASIC_AUTH_PASSWORD_RE = /\/\/[^:\s/?#@]+:([^@\s/?#]+)@/giu;
907
1172
  function countDigits2(value) {
908
1173
  let count = 0;
909
1174
  for (const ch of value) {
@@ -928,15 +1193,32 @@ function luhnCheck(value) {
928
1193
  return sum % 10 === 0;
929
1194
  }
930
1195
  function normalizeDetections(text, detections) {
931
- const sorted = detections.filter((d) => d.start >= 0 && d.end > d.start && d.end <= text.length).sort((a, b) => a.start - b.start || b.end - b.start - (a.end - a.start));
1196
+ const sorted = detections.filter((d) => d.start >= 0 && d.end > d.start && d.end <= text.length).sort(
1197
+ (a, b) => detectionPriority(b.type) - detectionPriority(a.type) || a.start - b.start || b.end - b.start - (a.end - a.start)
1198
+ );
932
1199
  const kept = [];
933
- let cursor = 0;
934
1200
  for (const d of sorted) {
935
- if (d.start < cursor) continue;
1201
+ if (kept.some((candidate) => rangesOverlap(candidate, d))) continue;
936
1202
  kept.push(d);
937
- cursor = d.end;
938
1203
  }
939
- return kept;
1204
+ return kept.sort((a, b) => a.start - b.start || a.end - b.end);
1205
+ }
1206
+ function rangesOverlap(left, right) {
1207
+ return left.start < right.end && right.start < left.end;
1208
+ }
1209
+ function detectionPriority(type) {
1210
+ if (/^(?:OPENAI_API_KEY|AWS_ACCESS_KEY|GITHUB_TOKEN|SLACK_TOKEN|SLACK_WEBHOOK_URL|DISCORD_WEBHOOK_URL|STRIPE_SECRET_KEY|GOOGLE_API_KEY|ANTHROPIC_API_KEY|EVM_PRIVATE_KEY|JWT_TOKEN|BEARER_TOKEN|API_KEY_HEADER|AZURE_CONNECTION_STRING|AZURE_SAS_TOKEN)$/u.test(
1211
+ type
1212
+ )) {
1213
+ return 100;
1214
+ }
1215
+ if (/^(?:CREDENTIAL_ASSIGNMENT|PASSWORD_ASSIGNMENT|PRIVATE_KEY_MATERIAL|ENV_SECRET_ASSIGNMENT)$/u.test(type)) {
1216
+ return 80;
1217
+ }
1218
+ if (type === "PERSON_NAME" || type === "PERSON") {
1219
+ return 10;
1220
+ }
1221
+ return 50;
940
1222
  }
941
1223
  var PHONE_CONTEXT_KEYWORDS = [
942
1224
  "tel",
@@ -946,6 +1228,8 @@ var PHONE_CONTEXT_KEYWORDS = [
946
1228
  "call",
947
1229
  "contact",
948
1230
  "number",
1231
+ "cislo",
1232
+ "\u010D\xEDslo",
949
1233
  "hotline",
950
1234
  "support",
951
1235
  "infoline",
@@ -971,6 +1255,59 @@ var PHONE_CONTEXT_RE = new RegExp(
971
1255
  "iu"
972
1256
  );
973
1257
  var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1258
+ "name",
1259
+ "names",
1260
+ "namen",
1261
+ "firstname",
1262
+ "lastname",
1263
+ "first",
1264
+ "last",
1265
+ "forename",
1266
+ "surname",
1267
+ "family",
1268
+ "given",
1269
+ "jmeno",
1270
+ "jake",
1271
+ "jaky",
1272
+ "jaka",
1273
+ "jsem",
1274
+ "jsme",
1275
+ "napsal",
1276
+ "napsali",
1277
+ "napsala",
1278
+ "napsane",
1279
+ "pouzil",
1280
+ "pouzili",
1281
+ "prijmeni",
1282
+ "vorname",
1283
+ "nachname",
1284
+ "familienname",
1285
+ "what",
1286
+ "which",
1287
+ "whose",
1288
+ "did",
1289
+ "we",
1290
+ "write",
1291
+ "wrote",
1292
+ "written",
1293
+ "type",
1294
+ "typed",
1295
+ "use",
1296
+ "used",
1297
+ "wie",
1298
+ "welchen",
1299
+ "welche",
1300
+ "welches",
1301
+ "haben",
1302
+ "wir",
1303
+ "geschrieben",
1304
+ "getippt",
1305
+ "quel",
1306
+ "quelle",
1307
+ "nom",
1308
+ "que",
1309
+ "cual",
1310
+ "nombre",
974
1311
  "write",
975
1312
  "code",
976
1313
  "script",
@@ -997,6 +1334,52 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
997
1334
  "security",
998
1335
  "instructions",
999
1336
  "instruction",
1337
+ "google",
1338
+ "form",
1339
+ "forms",
1340
+ "engineering",
1341
+ "leadership",
1342
+ "weekly",
1343
+ "daily",
1344
+ "monthly",
1345
+ "quarterly",
1346
+ "sync",
1347
+ "office",
1348
+ "updates",
1349
+ "update",
1350
+ "meeting",
1351
+ "meetings",
1352
+ "agenda",
1353
+ "minutes",
1354
+ "subject",
1355
+ "calendar",
1356
+ "roadmap",
1357
+ "platform",
1358
+ "product",
1359
+ "design",
1360
+ "operations",
1361
+ "business",
1362
+ "newsletter",
1363
+ "report",
1364
+ "reports",
1365
+ "amazon",
1366
+ "web",
1367
+ "services",
1368
+ "aws",
1369
+ "velka",
1370
+ "transformace",
1371
+ "project",
1372
+ "projekt",
1373
+ "program",
1374
+ "initiative",
1375
+ "iniciativa",
1376
+ "migration",
1377
+ "migrace",
1378
+ "test",
1379
+ "uuid",
1380
+ "fixture",
1381
+ "data",
1382
+ "firma",
1000
1383
  "rules",
1001
1384
  "rule",
1002
1385
  "json",
@@ -1009,10 +1392,22 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1009
1392
  "agentid",
1010
1393
  "risk",
1011
1394
  "score",
1012
- "summary"
1395
+ "summary",
1396
+ "hi",
1397
+ "hello",
1398
+ "hey",
1399
+ "dear",
1400
+ "team",
1401
+ "ahoj",
1402
+ "dobry",
1403
+ "dobryden",
1404
+ "zdravim"
1013
1405
  ]);
1014
1406
  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;
1015
1407
  var TECHNICAL_CONTEXT_SYMBOL_REGEX = /:\/\/|`|\{|\}|\[|\]|\(|\)|;|\$|=>|::|\/\//;
1408
+ var NAME_LABEL_QUESTION_CONTEXT_REGEX = /\b(?:jak(?:e|y|a|ou)|kter(?:e|y|a|ou)|co|what|which|whose|wie|welch(?:e|er|es|en|em)?|quel(?:le|s|les)?|que|cual(?:es)?|wat|welke|jaki|jakie|jaka)\b[\s\S]{0,80}\b(?:jmeno|prijmeni|name|names|namen|nom|nombre|nome|naam|imie|nazwisko|meno)\b[\s\S]{0,96}\b(?:napsal\p{L}*|napsan\p{L}*|psal\p{L}*|pouzil\p{L}*|pouzili\p{L}*|write|wrote|written|type|typed|enter(?:ed)?|use(?:d)?|say|said|geschrieben|getippt|eingetragen|ecrit|escrib\p{L}*|scritt\p{L}*)\b/iu;
1409
+ var NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX = /(?:[:=]|=>|-|\b(?:is|was|je|jsou|jmenuje|called|named|ist|sind|lautet|est|es)\b)\s*$/iu;
1410
+ var BIRTH_NUMBER_CONTEXT_RE = /\b(?:rodn[eé]\s*(?:č[ií]slo|cislo)|r\.?\s*c\.?|birth\s+number)\b[^0-9]{0,80}(\d{6}(?:\/?\d{3,4})?)\b/giu;
1016
1411
  function hasPhoneContext(text, matchStartIndex, windowSize = 50) {
1017
1412
  const start = Math.max(0, matchStartIndex - windowSize);
1018
1413
  const windowLower = text.slice(start, matchStartIndex).toLowerCase();
@@ -1029,6 +1424,16 @@ function buildContextWindow(source, index, length) {
1029
1424
  function isTechnicalContext(contextWindow) {
1030
1425
  return TECHNICAL_CONTEXT_WORD_REGEX.test(contextWindow) || TECHNICAL_CONTEXT_SYMBOL_REGEX.test(contextWindow);
1031
1426
  }
1427
+ function isNameLabelQuestionContext(contextWindow) {
1428
+ const normalized = normalizePersonWord(contextWindow);
1429
+ if (!normalized.trim()) {
1430
+ return false;
1431
+ }
1432
+ if (!NAME_LABEL_QUESTION_CONTEXT_REGEX.test(normalized)) {
1433
+ return false;
1434
+ }
1435
+ return !NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX.test(normalized.slice(-32));
1436
+ }
1032
1437
  function isLikelyPersonNameCandidate(candidate, contextWindow) {
1033
1438
  const words = candidate.trim().split(/\s+/);
1034
1439
  if (words.length !== 2) {
@@ -1037,6 +1442,9 @@ function isLikelyPersonNameCandidate(candidate, contextWindow) {
1037
1442
  if (isTechnicalContext(contextWindow)) {
1038
1443
  return false;
1039
1444
  }
1445
+ if (isNameLabelQuestionContext(contextWindow)) {
1446
+ return false;
1447
+ }
1040
1448
  for (const rawWord of words) {
1041
1449
  const normalized = normalizePersonWord(rawWord);
1042
1450
  if (normalized.length < 2) {
@@ -1057,63 +1465,135 @@ var PIIManager = class {
1057
1465
  *
1058
1466
  * Zero-dependency fallback with strict checksum validation for CEE national IDs.
1059
1467
  */
1060
- anonymize(text) {
1468
+ anonymize(text, options) {
1061
1469
  if (!text) return { maskedText: text, mapping: {} };
1062
1470
  try {
1063
1471
  const detections = [];
1064
- const emailRe = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
1065
- for (const m of text.matchAll(emailRe)) {
1066
- if (m.index == null) continue;
1067
- detections.push({ start: m.index, end: m.index + m[0].length, type: "EMAIL", text: m[0] });
1068
- }
1069
- const ibanRe = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/gi;
1070
- for (const m of text.matchAll(ibanRe)) {
1071
- if (m.index == null) continue;
1072
- detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
1073
- }
1074
- const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
1075
- for (const m of text.matchAll(ccRe)) {
1076
- if (m.index == null) continue;
1077
- const digits = countDigits2(m[0]);
1078
- if (digits < 12 || digits > 19) continue;
1079
- if (!luhnCheck(m[0])) continue;
1080
- detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
1472
+ const loweredText = text.toLowerCase();
1473
+ const resolvedOptions = {
1474
+ pii: options?.pii !== false,
1475
+ secrets: options?.secrets !== false
1476
+ };
1477
+ if (!resolvedOptions.pii && !resolvedOptions.secrets) {
1478
+ return { maskedText: text, mapping: {} };
1081
1479
  }
1082
- const phoneRe = /(?<!\d)(?:\+?\d[\d\s().-]{7,}\d)(?!\d)/g;
1083
- for (const m of text.matchAll(phoneRe)) {
1084
- if (m.index == null) continue;
1085
- const candidate = m[0];
1086
- const digits = countDigits2(candidate);
1087
- if (digits < 9 || digits > 15) continue;
1088
- const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
1089
- if (!isStrongInternational) {
1090
- const hasContext = hasPhoneContext(text, m.index);
1091
- if (!hasContext) continue;
1480
+ if (resolvedOptions.pii) {
1481
+ const emailRe = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
1482
+ for (const m of text.matchAll(emailRe)) {
1483
+ if (m.index == null) continue;
1484
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "EMAIL", text: m[0] });
1092
1485
  }
1093
- detections.push({ start: m.index, end: m.index + m[0].length, type: "PHONE", text: m[0] });
1094
- }
1095
- const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
1096
- for (const m of text.matchAll(personRe)) {
1097
- if (m.index == null) continue;
1098
- const candidate = m[0];
1099
- const contextWindow = buildContextWindow(text, m.index, candidate.length);
1100
- if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
1101
- continue;
1486
+ const ibanRe = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/gi;
1487
+ for (const m of text.matchAll(ibanRe)) {
1488
+ if (m.index == null) continue;
1489
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
1102
1490
  }
1103
- detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
1104
- }
1105
- const nationalIdMatches = detectNationalIdentifiers(text, {
1106
- deadlineMs: defaultScanDeadlineMs,
1107
- allowContextBirthNumberFallback: false
1108
- });
1109
- for (const match of nationalIdMatches) {
1110
- if (match.start < 0 || match.end <= match.start) continue;
1111
- detections.push({
1112
- start: match.start,
1113
- end: match.end,
1114
- type: "NATIONAL_ID",
1115
- text: text.slice(match.start, match.end)
1491
+ const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
1492
+ for (const m of text.matchAll(ccRe)) {
1493
+ if (m.index == null) continue;
1494
+ const digits = countDigits2(m[0]);
1495
+ if (digits < 12 || digits > 19) continue;
1496
+ if (!luhnCheck(m[0])) continue;
1497
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
1498
+ }
1499
+ const phoneRe = /(?<!\d)(?:\+?\d[\d\s().-]{7,}\d)(?!\d)/g;
1500
+ for (const m of text.matchAll(phoneRe)) {
1501
+ if (m.index == null) continue;
1502
+ const candidate = m[0];
1503
+ const digits = countDigits2(candidate);
1504
+ if (digits < 9 || digits > 15) continue;
1505
+ const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
1506
+ if (!isStrongInternational) {
1507
+ const hasContext = hasPhoneContext(text, m.index);
1508
+ if (!hasContext) continue;
1509
+ }
1510
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "PHONE", text: m[0] });
1511
+ }
1512
+ const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
1513
+ for (const m of text.matchAll(personRe)) {
1514
+ if (m.index == null) continue;
1515
+ const candidate = m[0];
1516
+ const contextWindow = buildContextWindow(text, m.index, candidate.length);
1517
+ if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
1518
+ continue;
1519
+ }
1520
+ detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
1521
+ }
1522
+ BIRTH_NUMBER_CONTEXT_RE.lastIndex = 0;
1523
+ for (const match of text.matchAll(BIRTH_NUMBER_CONTEXT_RE)) {
1524
+ if (match.index == null) continue;
1525
+ const value = match[1] ?? "";
1526
+ if (!/^\d{6}(?:\/?\d{3,4})?$/.test(value)) continue;
1527
+ const localIndex = match[0].lastIndexOf(value);
1528
+ const start = match.index + Math.max(0, localIndex);
1529
+ detections.push({
1530
+ start,
1531
+ end: start + value.length,
1532
+ type: "BIRTH_NUMBER",
1533
+ text: value
1534
+ });
1535
+ }
1536
+ const nationalIdMatches = detectNationalIdentifiers(text, {
1537
+ deadlineMs: defaultScanDeadlineMs,
1538
+ allowContextBirthNumberFallback: false
1116
1539
  });
1540
+ for (const match of nationalIdMatches) {
1541
+ if (match.start < 0 || match.end <= match.start) continue;
1542
+ detections.push({
1543
+ start: match.start,
1544
+ end: match.end,
1545
+ type: "NATIONAL_ID",
1546
+ text: text.slice(match.start, match.end)
1547
+ });
1548
+ }
1549
+ }
1550
+ if (resolvedOptions.secrets) {
1551
+ BASIC_AUTH_PASSWORD_RE.lastIndex = 0;
1552
+ for (const match of text.matchAll(BASIC_AUTH_PASSWORD_RE)) {
1553
+ if (match.index == null) continue;
1554
+ const password = match[1] ?? "";
1555
+ if (!password) continue;
1556
+ const localIndex = match[0].lastIndexOf(password);
1557
+ const start = match.index + Math.max(0, localIndex);
1558
+ detections.push({
1559
+ start,
1560
+ end: start + password.length,
1561
+ type: "BASIC_AUTH_PASSWORD",
1562
+ text: password
1563
+ });
1564
+ }
1565
+ DISCORD_WEBHOOK_TOKEN_RE.lastIndex = 0;
1566
+ for (const match of text.matchAll(DISCORD_WEBHOOK_TOKEN_RE)) {
1567
+ if (match.index == null) continue;
1568
+ const token = match[1] ?? "";
1569
+ if (!token) continue;
1570
+ const localIndex = match[0].lastIndexOf(token);
1571
+ const start = match.index + Math.max(0, localIndex);
1572
+ detections.push({
1573
+ start,
1574
+ end: start + token.length,
1575
+ type: "DISCORD_WEBHOOK_TOKEN",
1576
+ text: token
1577
+ });
1578
+ }
1579
+ for (const matcher of sdkSecretMatchers) {
1580
+ if (matcher.id === "discord_webhook_url") {
1581
+ continue;
1582
+ }
1583
+ if (matcher.prefilterTermsLower.length > 0 && !matcher.prefilterTermsLower.some((term) => loweredText.includes(term))) {
1584
+ continue;
1585
+ }
1586
+ matcher.scanRegex.lastIndex = 0;
1587
+ for (const match of text.matchAll(matcher.scanRegex)) {
1588
+ if (match.index == null) continue;
1589
+ detections.push({
1590
+ start: match.index,
1591
+ end: match.index + match[0].length,
1592
+ type: matcher.placeholderType,
1593
+ text: match[0]
1594
+ });
1595
+ }
1596
+ }
1117
1597
  }
1118
1598
  const kept = normalizeDetections(text, detections);
1119
1599
  if (!kept.length) return { maskedText: text, mapping: {} };
@@ -1642,14 +2122,14 @@ async function reportSecurityEvent(options) {
1642
2122
  const inputValue = options.storePii ? snippet : snippetHash;
1643
2123
  const eventId = createEventId(options.eventId ?? options.clientEventId);
1644
2124
  const metadata = {
2125
+ ...options.telemetryMetadata ?? {},
1645
2126
  source: options.source,
1646
2127
  detector: options.detector,
1647
2128
  trigger_rule: options.triggerRule,
1648
2129
  language: options.language,
1649
2130
  ai_scan_status: options.aiStatus ?? null,
1650
2131
  reason: options.reason ?? null,
1651
- client_event_id: eventId,
1652
- ...options.telemetryMetadata ?? {}
2132
+ client_event_id: eventId
1653
2133
  };
1654
2134
  if (options.storePii) {
1655
2135
  metadata.snippet = snippet;
@@ -1810,7 +2290,7 @@ function getInjectionScanner() {
1810
2290
 
1811
2291
  // src/sdk-version.ts
1812
2292
  var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
1813
- var AGENTID_SDK_VERSION_HEADER = "js-0.1.37".trim().length > 0 ? "js-0.1.37" : FALLBACK_SDK_VERSION;
2293
+ var AGENTID_SDK_VERSION_HEADER = "js-0.1.40".trim().length > 0 ? "js-0.1.40" : FALLBACK_SDK_VERSION;
1814
2294
 
1815
2295
  // src/local-security-enforcer.ts
1816
2296
  var DEFAULT_FAIL_OPEN_CONFIG = {
@@ -1821,7 +2301,9 @@ var DEFAULT_FAIL_OPEN_CONFIG = {
1821
2301
  block_on_heuristic: false,
1822
2302
  inject_transparency_metadata: false,
1823
2303
  block_pii_leakage: false,
1824
- enable_sdk_pii_masking: false,
2304
+ enable_sdk_pii_masking: true,
2305
+ block_secret_leakage: false,
2306
+ enable_sdk_secret_masking: true,
1825
2307
  block_db_access: false,
1826
2308
  block_code_execution: false,
1827
2309
  block_toxicity: false
@@ -1863,11 +2345,11 @@ function detectCapabilityViolation(text, config) {
1863
2345
  }
1864
2346
  return null;
1865
2347
  }
1866
- function redactPiiStrict(pii, text) {
2348
+ function redactPiiStrict(pii, text, options) {
1867
2349
  if (!text) {
1868
2350
  return { redactedText: text, changed: false };
1869
2351
  }
1870
- const masked = pii.anonymize(text);
2352
+ const masked = pii.anonymize(text, options);
1871
2353
  let redactedText = masked.maskedText;
1872
2354
  const placeholders = Object.keys(masked.mapping).sort((a, b) => b.length - a.length);
1873
2355
  for (const placeholder of placeholders) {
@@ -1896,7 +2378,7 @@ var LocalSecurityEnforcer = class {
1896
2378
  `AgentID: Security policy blocked (${violationType})`
1897
2379
  );
1898
2380
  }
1899
- if (!config.block_pii_leakage) {
2381
+ if (!config.block_pii_leakage && !config.block_secret_leakage) {
1900
2382
  return {
1901
2383
  sanitizedInput: input,
1902
2384
  events: []
@@ -1906,10 +2388,13 @@ var LocalSecurityEnforcer = class {
1906
2388
  throw new SecurityPolicyViolationError(
1907
2389
  "PII_LEAKAGE_STRICT",
1908
2390
  "BLOCKED",
1909
- "AgentID: Streaming is not supported when Strict PII Mode is enabled. Please disable streaming or adjust security settings."
2391
+ "AgentID: Streaming is not supported when strict masking/blocking mode is enabled. Please disable streaming or adjust security settings."
1910
2392
  );
1911
2393
  }
1912
- const strictRedaction = redactPiiStrict(this.pii, input);
2394
+ const strictRedaction = redactPiiStrict(this.pii, input, {
2395
+ pii: config.block_pii_leakage,
2396
+ secrets: config.block_secret_leakage
2397
+ });
1913
2398
  return {
1914
2399
  sanitizedInput: strictRedaction.redactedText,
1915
2400
  events: strictRedaction.changed ? [
@@ -2035,6 +2520,16 @@ function normalizeCapabilityConfig(payload) {
2035
2520
  "enable_sdk_pii_masking",
2036
2521
  false
2037
2522
  ),
2523
+ block_secret_leakage: readOptionalBooleanField(
2524
+ body,
2525
+ "block_secret_leakage",
2526
+ false
2527
+ ),
2528
+ enable_sdk_secret_masking: readOptionalBooleanField(
2529
+ body,
2530
+ "enable_sdk_secret_masking",
2531
+ false
2532
+ ),
2038
2533
  block_db_access: readBooleanField(body, "block_db_access", "block_db"),
2039
2534
  block_code_execution: readBooleanField(
2040
2535
  body,
@@ -2215,9 +2710,18 @@ var INGEST_MAX_ATTEMPTS = 3;
2215
2710
  var INGEST_RETRY_DELAYS_MS = [250, 500];
2216
2711
  var GUARD_VERDICT_CACHE_TTL_MS = 0;
2217
2712
  var MAX_INGEST_TEXT_CHARS = 32e3;
2713
+ var OPENAI_TELEMETRY_FIELD = "agentid_telemetry";
2218
2714
  function normalizeBaseUrl3(baseUrl) {
2219
2715
  return baseUrl.replace(/\/+$/, "");
2220
2716
  }
2717
+ function firstNonEmptyString(...values) {
2718
+ for (const value of values) {
2719
+ if (typeof value === "string" && value.trim().length > 0) {
2720
+ return value.trim();
2721
+ }
2722
+ }
2723
+ return void 0;
2724
+ }
2221
2725
  function isAbortSignalLike(value) {
2222
2726
  if (!value || typeof value !== "object") return false;
2223
2727
  const candidate = value;
@@ -2379,6 +2883,424 @@ function createCorrelationId(seed) {
2379
2883
  }
2380
2884
  return createPseudoUuidV42();
2381
2885
  }
2886
+ function getObjectString(value, ...keys) {
2887
+ for (const key of keys) {
2888
+ const candidate = value?.[key];
2889
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
2890
+ return candidate.trim();
2891
+ }
2892
+ }
2893
+ return void 0;
2894
+ }
2895
+ function getObjectNumber(value, ...keys) {
2896
+ for (const key of keys) {
2897
+ const candidate = value?.[key];
2898
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
2899
+ return candidate;
2900
+ }
2901
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
2902
+ const parsed = Number(candidate);
2903
+ if (Number.isFinite(parsed)) {
2904
+ return parsed;
2905
+ }
2906
+ }
2907
+ }
2908
+ return void 0;
2909
+ }
2910
+ function normalizeTelemetryString(value) {
2911
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
2912
+ }
2913
+ function normalizeTelemetryCategory(value) {
2914
+ const normalized = normalizeTelemetryString(value);
2915
+ if (!normalized) return void 0;
2916
+ return normalized.toLowerCase().replace(/[\s-]+/g, "_");
2917
+ }
2918
+ function toSnakeToken(value) {
2919
+ return value.trim().replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_").toLowerCase();
2920
+ }
2921
+ function hasUsageSignals(value) {
2922
+ if (!value) return false;
2923
+ for (const entry of Object.values(value)) {
2924
+ if (typeof entry === "number" && Number.isFinite(entry) && entry > 0) {
2925
+ return true;
2926
+ }
2927
+ if (typeof entry === "string" && entry.trim().length > 0) {
2928
+ const parsed = Number(entry);
2929
+ if (Number.isFinite(parsed) && parsed > 0) {
2930
+ return true;
2931
+ }
2932
+ }
2933
+ }
2934
+ return false;
2935
+ }
2936
+ function truncatePromptPreflightPreview(value, maxChars = 280) {
2937
+ const normalized = value.trim();
2938
+ if (normalized.length <= maxChars) {
2939
+ return normalized;
2940
+ }
2941
+ return `${normalized.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
2942
+ }
2943
+ function formatPromptPreflightReason(reason) {
2944
+ const normalized = normalizeTelemetryString(reason);
2945
+ if (!normalized) {
2946
+ return void 0;
2947
+ }
2948
+ return normalized.replace(/[_-]+/g, " ");
2949
+ }
2950
+ function summarizePromptPreflightResult(params) {
2951
+ const reason = formatPromptPreflightReason(
2952
+ params.localFallbackApplied ? params.localFallbackReason ?? void 0 : params.verdict.reason
2953
+ ) ?? "policy evaluation";
2954
+ if (!params.verdict.allowed && !params.localFallbackApplied) {
2955
+ return `Blocked the prompt before model execution because ${reason}.`;
2956
+ }
2957
+ if (params.localFallbackApplied) {
2958
+ return `Guard preflight degraded, so the SDK applied local fallback checks before model execution (${reason}).`;
2959
+ }
2960
+ if (params.verdict.shadow_mode && params.verdict.shadow_blocked) {
2961
+ return "Evaluated the prompt in shadow mode before model execution; shadow policy would have blocked it.";
2962
+ }
2963
+ if (params.verdict.simulated_decision === "masked" || params.verdict.detected_pii) {
2964
+ return "Evaluated the prompt before model execution and masked sensitive content where needed.";
2965
+ }
2966
+ return "Evaluated the prompt and attachments against guardrails before model execution.";
2967
+ }
2968
+ function buildPromptPreflightTelemetry(params) {
2969
+ const baseTelemetry = createAgentIdTelemetryContext(params.telemetry);
2970
+ const baseStepName = firstNonEmptyString(
2971
+ baseTelemetry?.workflow_step_name,
2972
+ baseTelemetry?.workflowStepName
2973
+ );
2974
+ const stepName = baseStepName ? `${toSnakeToken(baseStepName)}_preflight` : "prompt_preflight";
2975
+ const summary = summarizePromptPreflightResult({
2976
+ verdict: params.verdict,
2977
+ localFallbackApplied: params.local_fallback_applied,
2978
+ localFallbackReason: params.local_fallback_reason
2979
+ });
2980
+ return mergeTelemetryContexts(baseTelemetry, {
2981
+ workflow_step_id: createAgentIdCorrelationId(),
2982
+ workflow_step_name: stepName,
2983
+ event_title: "Prompt Preflight Evaluated",
2984
+ event_category: "guard",
2985
+ event_subtype: "prompt_preflight_evaluated",
2986
+ event_status: !params.verdict.allowed && !params.local_fallback_applied ? "blocked" : "completed",
2987
+ step_summary: summary,
2988
+ input_preview: truncatePromptPreflightPreview(params.input),
2989
+ output_preview: summary,
2990
+ runtime_surface: params.runtime_surface ?? "openai_sdk_guard",
2991
+ guard_event_id: params.guard_event_id ?? void 0,
2992
+ guard_latency_ms: params.guard_latency_ms ?? void 0,
2993
+ preflight_for_client_event_id: params.preflight_for_client_event_id,
2994
+ preflight_logged_via_sdk: true,
2995
+ lifecycle_status: "preflight_only"
2996
+ });
2997
+ }
2998
+ function inferOperationCategory(telemetry, eventType) {
2999
+ const explicitCategory = normalizeTelemetryCategory(
3000
+ telemetry?.event_category ?? telemetry?.eventCategory
3001
+ );
3002
+ if (explicitCategory === "ai" || explicitCategory === "llm" || explicitCategory === "inference") {
3003
+ return "ai";
3004
+ }
3005
+ if (explicitCategory === "guard" || explicitCategory === "security") {
3006
+ return "guard";
3007
+ }
3008
+ if (explicitCategory === "tool") return "tool";
3009
+ if (explicitCategory === "delivery" || explicitCategory === "send") return "delivery";
3010
+ if (explicitCategory === "inbox" || explicitCategory === "reply") return "inbox";
3011
+ if (explicitCategory === "workflow" || explicitCategory === "agent") return "workflow";
3012
+ if (explicitCategory === "compliance" || explicitCategory === "transparency") {
3013
+ return "compliance";
3014
+ }
3015
+ if (explicitCategory === "operational" || explicitCategory === "ops") {
3016
+ return "operational";
3017
+ }
3018
+ const haystack = [
3019
+ eventType,
3020
+ telemetry?.event_subtype,
3021
+ telemetry?.eventSubtype,
3022
+ telemetry?.tool_name,
3023
+ telemetry?.toolName,
3024
+ telemetry?.tool_target_type,
3025
+ telemetry?.toolTargetType,
3026
+ telemetry?.workflow_name,
3027
+ telemetry?.workflowName,
3028
+ telemetry?.workflow_step_name,
3029
+ telemetry?.workflowStepName,
3030
+ getObjectString(telemetry, "operation_family", "domain")
3031
+ ].filter((entry) => typeof entry === "string" && entry.trim().length > 0).join(" ").replace(/[_./-]+/g, " ").toLowerCase();
3032
+ if (/\b(llm|ai|inference|completion|summary|classification|draft)\b/.test(haystack)) {
3033
+ return "ai";
3034
+ }
3035
+ if (/\b(guard|security|policy|pii|prompt[_ ]?injection|review)\b/.test(haystack)) {
3036
+ return "guard";
3037
+ }
3038
+ if (/\b(reply|inbox|inbound|received|bounce|opened|followup)\b/.test(haystack)) {
3039
+ return "inbox";
3040
+ }
3041
+ if (/\b(email|mail|send|delivery|delivered|slack|sms|webhook|notification)\b/.test(haystack)) {
3042
+ return "delivery";
3043
+ }
3044
+ if (/\b(workflow|step|run|agent)\b/.test(haystack)) {
3045
+ return "workflow";
3046
+ }
3047
+ if (/\b(compliance|transparency|audit|evidence)\b/.test(haystack)) {
3048
+ return "compliance";
3049
+ }
3050
+ if (/\b(tool|lookup|search|query|retrieve|fetch|crm|invoice|payment|ledger|expense|payroll|tax|finance|cv|resume|candidate|applicant|recruit|interview|screen|document|file|attachment|extract|parse|ocr|classify|sync|import|export|record|database|sql|shell|terminal|script)\b/.test(
3051
+ haystack
3052
+ )) {
3053
+ return "tool";
3054
+ }
3055
+ return "operational";
3056
+ }
3057
+ function inferOperationStatus(params) {
3058
+ const explicitStatus = normalizeTelemetryString(params.eventStatus)?.toLowerCase();
3059
+ if (explicitStatus === "started" || explicitStatus === "completed" || explicitStatus === "failed") {
3060
+ return explicitStatus;
3061
+ }
3062
+ if (explicitStatus === "blocked" || explicitStatus === "skipped") {
3063
+ return explicitStatus;
3064
+ }
3065
+ const normalizedEventType = normalizeTelemetryString(params.eventType)?.toLowerCase();
3066
+ if (normalizedEventType === "start") return "started";
3067
+ if (normalizedEventType === "error") return "failed";
3068
+ if (normalizedEventType === "security_block") return "blocked";
3069
+ if (normalizedEventType === "human_override") return "completed";
3070
+ if (normalizedEventType === "complete") return "completed";
3071
+ return params.severity === "error" ? "failed" : "completed";
3072
+ }
3073
+ function deriveOperationEventType(params) {
3074
+ const explicit = normalizeTelemetryString(params.explicitEventType);
3075
+ if (explicit) {
3076
+ return explicit;
3077
+ }
3078
+ if (params.status === "started") return "start";
3079
+ if (params.status === "failed") return "error";
3080
+ if (params.status === "blocked") {
3081
+ return params.category === "guard" ? "security_block" : "error";
3082
+ }
3083
+ return "complete";
3084
+ }
3085
+ function deriveSubtypeBase(telemetry) {
3086
+ const toolName = normalizeTelemetryString(telemetry?.tool_name ?? telemetry?.toolName);
3087
+ if (toolName) {
3088
+ const tokens = toSnakeToken(toolName).split("_").filter(Boolean);
3089
+ if (tokens.length > 1 && ["workflow", "agent", "operation", "ops", "hr", "finance", "compliance"].includes(tokens[0])) {
3090
+ return tokens.slice(1).join("_");
3091
+ }
3092
+ return tokens.join("_");
3093
+ }
3094
+ const workflowName = normalizeTelemetryString(
3095
+ telemetry?.workflow_step_name ?? telemetry?.workflowStepName ?? telemetry?.workflow_name ?? telemetry?.workflowName
3096
+ );
3097
+ if (workflowName) {
3098
+ return toSnakeToken(workflowName);
3099
+ }
3100
+ return void 0;
3101
+ }
3102
+ function deriveOperationSubtype(params) {
3103
+ const explicitSubtype = normalizeTelemetryString(params.explicitSubtype);
3104
+ if (explicitSubtype) {
3105
+ return toSnakeToken(explicitSubtype);
3106
+ }
3107
+ const base = deriveSubtypeBase(params.telemetry);
3108
+ const suffix = params.status === "started" ? "started" : params.status === "failed" ? "failed" : params.status === "blocked" ? "blocked" : params.status === "skipped" ? "skipped" : "completed";
3109
+ if (base) {
3110
+ return `${base}_${suffix}`;
3111
+ }
3112
+ if (params.eventType === "start") return `${params.category}_started`;
3113
+ if (params.eventType === "error") return `${params.category}_failed`;
3114
+ if (params.eventType === "security_block") return `${params.category}_blocked`;
3115
+ return `${params.category}_completed`;
3116
+ }
3117
+ function inferOperationSeverity(params) {
3118
+ if (params.explicitSeverity) {
3119
+ return params.explicitSeverity;
3120
+ }
3121
+ if (params.status === "failed" || params.status === "blocked") {
3122
+ return "error";
3123
+ }
3124
+ if (params.status === "skipped") {
3125
+ return "warning";
3126
+ }
3127
+ return "info";
3128
+ }
3129
+ function createAgentIdCorrelationId(seed) {
3130
+ return createCorrelationId(seed);
3131
+ }
3132
+ function createAgentIdTelemetryContext(value) {
3133
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
3134
+ return void 0;
3135
+ }
3136
+ const raw = { ...value };
3137
+ const normalized = {};
3138
+ const assignString = (key, ...aliases) => {
3139
+ const next = getObjectString(raw, key, ...aliases);
3140
+ if (next) {
3141
+ normalized[key] = next;
3142
+ }
3143
+ };
3144
+ const assignNumber = (key, ...aliases) => {
3145
+ const next = getObjectNumber(raw, key, ...aliases);
3146
+ if (typeof next === "number") {
3147
+ normalized[key] = next;
3148
+ }
3149
+ };
3150
+ assignString("workflow_id", "workflowId");
3151
+ assignString("workflow_run_id", "workflowRunId");
3152
+ assignString("workflow_step_id", "workflowStepId");
3153
+ assignString("workflow_name", "workflowName");
3154
+ assignString("workflow_step_name", "workflowStepName");
3155
+ assignNumber("workflow_step_index", "workflowStepIndex");
3156
+ assignString("parent_event_id", "parentEventId");
3157
+ assignString("tool_name", "toolName");
3158
+ assignString("tool_target", "toolTarget");
3159
+ assignString("tool_target_type", "toolTargetType");
3160
+ assignString("event_title", "eventTitle");
3161
+ assignString("event_status", "eventStatus");
3162
+ assignString("event_category", "eventCategory");
3163
+ assignString("event_subtype", "eventSubtype");
3164
+ const consumedKeys = /* @__PURE__ */ new Set([
3165
+ "workflow_id",
3166
+ "workflowId",
3167
+ "workflow_run_id",
3168
+ "workflowRunId",
3169
+ "workflow_step_id",
3170
+ "workflowStepId",
3171
+ "workflow_name",
3172
+ "workflowName",
3173
+ "workflow_step_name",
3174
+ "workflowStepName",
3175
+ "workflow_step_index",
3176
+ "workflowStepIndex",
3177
+ "parent_event_id",
3178
+ "parentEventId",
3179
+ "tool_name",
3180
+ "toolName",
3181
+ "tool_target",
3182
+ "toolTarget",
3183
+ "tool_target_type",
3184
+ "toolTargetType",
3185
+ "event_title",
3186
+ "eventTitle",
3187
+ "event_status",
3188
+ "eventStatus",
3189
+ "event_category",
3190
+ "eventCategory",
3191
+ "event_subtype",
3192
+ "eventSubtype"
3193
+ ]);
3194
+ for (const [key, entry] of Object.entries(raw)) {
3195
+ if (consumedKeys.has(key) || entry === void 0) {
3196
+ continue;
3197
+ }
3198
+ if (typeof entry === "string") {
3199
+ if (entry.trim().length > 0) {
3200
+ normalized[key] = entry.trim();
3201
+ }
3202
+ continue;
3203
+ }
3204
+ normalized[key] = entry;
3205
+ }
3206
+ if (typeof normalized.workflow_id !== "string" && typeof normalized.workflow_run_id === "string") {
3207
+ normalized.workflow_id = normalized.workflow_run_id;
3208
+ }
3209
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
3210
+ }
3211
+ function createAgentIdOperationLog(params) {
3212
+ const telemetry = createAgentIdTelemetryContext(params.telemetry);
3213
+ const category = inferOperationCategory(
3214
+ createAgentIdTelemetryContext({
3215
+ ...telemetry ?? {},
3216
+ event_category: params.event_category ?? telemetry?.event_category
3217
+ }),
3218
+ params.event_type
3219
+ );
3220
+ const status = inferOperationStatus({
3221
+ eventStatus: normalizeTelemetryString(params.event_status) ?? normalizeTelemetryString(telemetry?.event_status ?? telemetry?.eventStatus),
3222
+ eventType: params.event_type,
3223
+ severity: params.severity
3224
+ });
3225
+ const eventType = deriveOperationEventType({
3226
+ explicitEventType: params.event_type,
3227
+ status,
3228
+ category
3229
+ });
3230
+ const subtype = deriveOperationSubtype({
3231
+ explicitSubtype: normalizeTelemetryString(params.event_subtype) ?? normalizeTelemetryString(telemetry?.event_subtype ?? telemetry?.eventSubtype),
3232
+ telemetry,
3233
+ category,
3234
+ status,
3235
+ eventType
3236
+ });
3237
+ const severity = inferOperationSeverity({
3238
+ explicitSeverity: params.severity,
3239
+ status
3240
+ });
3241
+ const usage = params.usage;
3242
+ const clientEventId = normalizeTelemetryString(params.client_event_id) ?? normalizeTelemetryString(telemetry?.client_event_id);
3243
+ const modelUsed = category === "ai" || hasUsageSignals(usage) || typeof params.model === "string" && params.model.trim().length > 0 && params.model.trim().toLowerCase() !== "not_applicable";
3244
+ const metadata = {
3245
+ ...params.metadata ?? {},
3246
+ ...telemetry ?? {},
3247
+ event_category: category,
3248
+ event_subtype: subtype,
3249
+ event_status: status,
3250
+ status,
3251
+ model_used: modelUsed,
3252
+ spend_bearing: category === "ai" && hasUsageSignals(usage)
3253
+ };
3254
+ if (clientEventId && typeof metadata.client_event_id !== "string") {
3255
+ metadata.client_event_id = clientEventId;
3256
+ }
3257
+ return {
3258
+ event_id: normalizeTelemetryString(params.event_id) ?? createEventId2(),
3259
+ system_id: params.system_id,
3260
+ user_id: params.user_id,
3261
+ request_identity: params.request_identity,
3262
+ input: params.input ?? "",
3263
+ output: params.output ?? "",
3264
+ model: normalizeTelemetryString(params.model) ?? "not_applicable",
3265
+ usage,
3266
+ tokens: params.tokens,
3267
+ latency: params.latency,
3268
+ metadata,
3269
+ event_type: eventType,
3270
+ severity,
3271
+ timestamp: params.timestamp,
3272
+ client_capabilities: params.client_capabilities
3273
+ };
3274
+ }
3275
+ function asTelemetryContext(value) {
3276
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
3277
+ return void 0;
3278
+ }
3279
+ return createAgentIdTelemetryContext(value);
3280
+ }
3281
+ function mergeTelemetryContexts(...contexts) {
3282
+ const merged = {};
3283
+ let hasValues = false;
3284
+ for (const context of contexts) {
3285
+ if (!context) {
3286
+ continue;
3287
+ }
3288
+ Object.assign(merged, createAgentIdTelemetryContext(context));
3289
+ hasValues = true;
3290
+ }
3291
+ return hasValues ? createAgentIdTelemetryContext(merged) : void 0;
3292
+ }
3293
+ function extractRequestTelemetryContext(requestBody) {
3294
+ return asTelemetryContext(requestBody[OPENAI_TELEMETRY_FIELD]);
3295
+ }
3296
+ function stripRequestTelemetryContext(requestBody) {
3297
+ if (!Object.prototype.hasOwnProperty.call(requestBody, OPENAI_TELEMETRY_FIELD)) {
3298
+ return requestBody;
3299
+ }
3300
+ const nextRequestBody = { ...requestBody };
3301
+ delete nextRequestBody[OPENAI_TELEMETRY_FIELD];
3302
+ return nextRequestBody;
3303
+ }
2382
3304
  async function waitForRetry(attemptIndex) {
2383
3305
  const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
2384
3306
  if (!delay) return;
@@ -2558,6 +3480,61 @@ function createStreamingPlaceholderRewriter(piiManager, mapping) {
2558
3480
  }
2559
3481
  };
2560
3482
  }
3483
+ var TYPED_PLACEHOLDER_RE = /<[A-Z][A-Z0-9_]*_\d+>/g;
3484
+ function derivePlaceholderMappingFromTransform(source, transformed) {
3485
+ if (!source || !transformed || source === transformed) {
3486
+ return {};
3487
+ }
3488
+ const placeholders = [...transformed.matchAll(TYPED_PLACEHOLDER_RE)].map((match) => ({
3489
+ token: match[0],
3490
+ start: match.index ?? 0,
3491
+ end: (match.index ?? 0) + match[0].length
3492
+ }));
3493
+ if (placeholders.length === 0) {
3494
+ return {};
3495
+ }
3496
+ const mapping = {};
3497
+ let sourceCursor = 0;
3498
+ let transformedCursor = 0;
3499
+ for (const placeholder of placeholders) {
3500
+ const literalBefore = transformed.slice(transformedCursor, placeholder.start);
3501
+ if (literalBefore) {
3502
+ const literalIndex = source.indexOf(literalBefore, sourceCursor);
3503
+ if (literalIndex < 0) {
3504
+ return {};
3505
+ }
3506
+ sourceCursor = literalIndex + literalBefore.length;
3507
+ }
3508
+ const nextPlaceholderStart = placeholders.find((candidate) => candidate.start > placeholder.start)?.start ?? transformed.length;
3509
+ const literalAfter = transformed.slice(placeholder.end, nextPlaceholderStart);
3510
+ const nextLiteralIndex = literalAfter ? source.indexOf(literalAfter, sourceCursor) : nextPlaceholderStart >= transformed.length ? source.length : sourceCursor;
3511
+ if (nextLiteralIndex < sourceCursor) {
3512
+ return {};
3513
+ }
3514
+ const originalValue = source.slice(sourceCursor, nextLiteralIndex);
3515
+ if (originalValue.length > 0 && typeof mapping[placeholder.token] !== "string") {
3516
+ mapping[placeholder.token] = originalValue;
3517
+ }
3518
+ sourceCursor = nextLiteralIndex;
3519
+ transformedCursor = placeholder.end;
3520
+ }
3521
+ return mapping;
3522
+ }
3523
+ function mergePiiMappings(primary, fallback) {
3524
+ const merged = { ...primary };
3525
+ for (const [placeholder, value] of Object.entries(fallback)) {
3526
+ if (typeof merged[placeholder] !== "string" && typeof value === "string") {
3527
+ merged[placeholder] = value;
3528
+ }
3529
+ }
3530
+ return merged;
3531
+ }
3532
+ function textContainsMappingPlaceholder(text, mapping) {
3533
+ if (!text || !mapping) {
3534
+ return false;
3535
+ }
3536
+ return Object.keys(mapping).some((placeholder) => placeholder.length > 0 && text.includes(placeholder));
3537
+ }
2561
3538
  var SecurityBlockError = class extends Error {
2562
3539
  constructor(reason = "guard_denied") {
2563
3540
  super(`AgentID: Security Blocked (${reason})`);
@@ -2582,6 +3559,7 @@ var AgentID = class {
2582
3559
  this.apiKey = resolveConfiguredApiKey(config.apiKey);
2583
3560
  this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
2584
3561
  this.configuredPiiMasking = typeof config.piiMasking === "boolean" ? config.piiMasking : null;
3562
+ this.configuredSecretMasking = typeof config.secretMasking === "boolean" ? config.secretMasking : null;
2585
3563
  this.checkInjection = config.checkInjection !== false;
2586
3564
  this.clientFastFail = config.clientFastFail === true || config.client_fast_fail === true;
2587
3565
  this.aiScanEnabled = config.aiScanEnabled !== false;
@@ -2603,6 +3581,9 @@ var AgentID = class {
2603
3581
  get piiMasking() {
2604
3582
  return this.configuredPiiMasking ?? void 0;
2605
3583
  }
3584
+ get secretMasking() {
3585
+ return this.configuredSecretMasking ?? void 0;
3586
+ }
2606
3587
  resolveEffectivePiiMasking(config) {
2607
3588
  if (config?.enable_sdk_pii_masking === true) {
2608
3589
  return true;
@@ -2612,12 +3593,24 @@ var AgentID = class {
2612
3593
  }
2613
3594
  return false;
2614
3595
  }
3596
+ resolveEffectiveSecretMasking(config) {
3597
+ if (config?.enable_sdk_secret_masking === true || config?.enable_sdk_pii_masking === true) {
3598
+ return true;
3599
+ }
3600
+ if (this.configuredSecretMasking !== null) {
3601
+ return this.configuredSecretMasking;
3602
+ }
3603
+ return false;
3604
+ }
2615
3605
  getEffectivePiiMasking(options) {
2616
3606
  return this.resolveEffectivePiiMasking(this.getCachedCapabilityConfig(options));
2617
3607
  }
2618
3608
  getEffectivePiiMaskingForConfig(capabilityConfig) {
2619
3609
  return this.resolveEffectivePiiMasking(capabilityConfig);
2620
3610
  }
3611
+ getEffectiveSecretMaskingForConfig(capabilityConfig) {
3612
+ return this.resolveEffectiveSecretMasking(capabilityConfig);
3613
+ }
2621
3614
  buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig) {
2622
3615
  return {
2623
3616
  capabilities: {
@@ -2625,6 +3618,9 @@ var AgentID = class {
2625
3618
  pii_masking_enabled: this.resolveEffectivePiiMasking(
2626
3619
  capabilityConfig ?? this.getCachedCapabilityConfig()
2627
3620
  ),
3621
+ secret_masking_enabled: this.resolveEffectiveSecretMasking(
3622
+ capabilityConfig ?? this.getCachedCapabilityConfig()
3623
+ ),
2628
3624
  framework
2629
3625
  }
2630
3626
  };
@@ -2717,6 +3713,23 @@ var AgentID = class {
2717
3713
  const config = await this.getCapabilityConfig(false, options);
2718
3714
  return config.strict_security_mode || config.failure_mode === "fail_close";
2719
3715
  }
3716
+ buildFailOpenGuardVerdict(reason, input, options) {
3717
+ const capabilityConfig = this.getCachedCapabilityConfig(options);
3718
+ const shouldMaskPii = capabilityConfig.block_pii_leakage || this.resolveEffectivePiiMasking(capabilityConfig);
3719
+ const shouldMaskSecrets = capabilityConfig.block_secret_leakage === true || this.resolveEffectiveSecretMasking(capabilityConfig);
3720
+ const response = { allowed: true, reason };
3721
+ if (input && (shouldMaskPii || shouldMaskSecrets)) {
3722
+ const masked = this.pii.anonymize(input, {
3723
+ pii: shouldMaskPii,
3724
+ secrets: shouldMaskSecrets
3725
+ });
3726
+ if (masked.maskedText !== input) {
3727
+ response.transformed_input = masked.maskedText;
3728
+ response.detected_pii = Object.keys(masked.mapping).length > 0;
3729
+ }
3730
+ }
3731
+ return response;
3732
+ }
2720
3733
  maybeRaiseStrictIngestDependencyError(params) {
2721
3734
  if (params.result.ok) {
2722
3735
  return;
@@ -2764,10 +3777,13 @@ var AgentID = class {
2764
3777
  systemId: params.systemId,
2765
3778
  eventId: params.clientEventId,
2766
3779
  clientEventId: params.clientEventId,
2767
- telemetryMetadata: buildSdkTimingMetadata({
2768
- sdkConfigFetchMs: params.sdkConfigFetchMs,
2769
- sdkConfigVersion: params.capabilityConfig.version
2770
- })
3780
+ telemetryMetadata: mergeTelemetryContexts(
3781
+ params.telemetryMetadata,
3782
+ buildSdkTimingMetadata({
3783
+ sdkConfigFetchMs: params.sdkConfigFetchMs,
3784
+ sdkConfigVersion: params.capabilityConfig.version
3785
+ })
3786
+ )
2771
3787
  });
2772
3788
  }
2773
3789
  try {
@@ -2784,7 +3800,8 @@ var AgentID = class {
2784
3800
  actionTaken: event.actionTaken,
2785
3801
  apiKey: params.apiKey,
2786
3802
  sdkConfigFetchMs: params.sdkConfigFetchMs,
2787
- sdkLocalScanMs
3803
+ sdkLocalScanMs,
3804
+ telemetryMetadata: params.telemetryMetadata
2788
3805
  });
2789
3806
  }
2790
3807
  return {
@@ -2799,7 +3816,8 @@ var AgentID = class {
2799
3816
  actionTaken: error.actionTaken,
2800
3817
  apiKey: params.apiKey,
2801
3818
  sdkConfigFetchMs: params.sdkConfigFetchMs,
2802
- sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
3819
+ sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt),
3820
+ telemetryMetadata: params.telemetryMetadata
2803
3821
  });
2804
3822
  }
2805
3823
  throw error;
@@ -2813,7 +3831,7 @@ var AgentID = class {
2813
3831
  );
2814
3832
  let sanitizedInput = params.input;
2815
3833
  let sdkLocalScanMs = 0;
2816
- if (this.configuredPiiMasking === null) {
3834
+ if (this.configuredPiiMasking === null || this.configuredSecretMasking === null) {
2817
3835
  const refreshed = await this.refreshCapabilityConfigBeforeClientControl({
2818
3836
  capabilityConfig,
2819
3837
  sdkConfigFetchMs,
@@ -2824,8 +3842,12 @@ var AgentID = class {
2824
3842
  }
2825
3843
  if (!this.clientFastFail) {
2826
3844
  const effectivePiiMasking2 = this.resolveEffectivePiiMasking(capabilityConfig);
2827
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2) {
2828
- const masked = this.pii.anonymize(sanitizedInput);
3845
+ const effectiveSecretMasking2 = this.resolveEffectiveSecretMasking(capabilityConfig);
3846
+ if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2 || !capabilityConfig.block_secret_leakage && effectiveSecretMasking2) {
3847
+ const masked = this.pii.anonymize(sanitizedInput, {
3848
+ pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking2,
3849
+ secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking2
3850
+ });
2829
3851
  return {
2830
3852
  sanitizedInput: masked.maskedText,
2831
3853
  capabilityConfig,
@@ -2857,13 +3879,18 @@ var AgentID = class {
2857
3879
  apiKey: effectiveApiKey,
2858
3880
  clientEventId: params.clientEventId,
2859
3881
  sdkConfigFetchMs,
3882
+ telemetryMetadata: params.telemetryMetadata,
2860
3883
  runPromptInjectionCheck: !params.skipInjectionScan
2861
3884
  });
2862
3885
  sanitizedInput = enforced.sanitizedInput;
2863
3886
  sdkLocalScanMs = enforced.sdkLocalScanMs;
2864
3887
  const effectivePiiMasking = this.resolveEffectivePiiMasking(capabilityConfig);
2865
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking) {
2866
- const masked = this.pii.anonymize(sanitizedInput);
3888
+ const effectiveSecretMasking = this.resolveEffectiveSecretMasking(capabilityConfig);
3889
+ if (!capabilityConfig.block_pii_leakage && effectivePiiMasking || !capabilityConfig.block_secret_leakage && effectiveSecretMasking) {
3890
+ const masked = this.pii.anonymize(sanitizedInput, {
3891
+ pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking,
3892
+ secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking
3893
+ });
2867
3894
  return {
2868
3895
  sanitizedInput: masked.maskedText,
2869
3896
  capabilityConfig,
@@ -2899,6 +3926,7 @@ var AgentID = class {
2899
3926
  apiKey: effectiveApiKey,
2900
3927
  clientEventId: params.clientEventId,
2901
3928
  sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
3929
+ telemetryMetadata: params.telemetryMetadata,
2902
3930
  runPromptInjectionCheck: true
2903
3931
  });
2904
3932
  return {
@@ -2942,12 +3970,43 @@ var AgentID = class {
2942
3970
  })
2943
3971
  });
2944
3972
  }
2945
- withMaskedOpenAIRequest(req, maskedText) {
3973
+ withMaskedOpenAIRequest(req, maskedText, options) {
2946
3974
  const messages = Array.isArray(req?.messages) ? req.messages : null;
2947
3975
  if (!messages) {
2948
3976
  return req;
2949
3977
  }
2950
- const newMessages = [...messages];
3978
+ const newMessages = messages.map((message2) => {
3979
+ if (!message2 || typeof message2 !== "object") {
3980
+ return message2;
3981
+ }
3982
+ const typedMessage = message2;
3983
+ const currentContent2 = typedMessage.content;
3984
+ if (typeof currentContent2 === "string") {
3985
+ return {
3986
+ ...typedMessage,
3987
+ content: this.pii.anonymize(currentContent2, options).maskedText
3988
+ };
3989
+ }
3990
+ if (Array.isArray(currentContent2)) {
3991
+ return {
3992
+ ...typedMessage,
3993
+ content: currentContent2.map((part) => {
3994
+ if (!part || typeof part !== "object") {
3995
+ return part;
3996
+ }
3997
+ const typedPart = part;
3998
+ if (typeof typedPart.text !== "string") {
3999
+ return part;
4000
+ }
4001
+ return {
4002
+ ...typedPart,
4003
+ text: this.pii.anonymize(typedPart.text, options).maskedText
4004
+ };
4005
+ })
4006
+ };
4007
+ }
4008
+ return message2;
4009
+ });
2951
4010
  let lastUserIdx = null;
2952
4011
  for (let i = 0; i < newMessages.length; i += 1) {
2953
4012
  const msg = newMessages[i];
@@ -2962,9 +4021,30 @@ var AgentID = class {
2962
4021
  if (!message || typeof message !== "object") {
2963
4022
  return req;
2964
4023
  }
4024
+ const currentContent = message.content;
4025
+ let nextContent = maskedText;
4026
+ if (Array.isArray(currentContent)) {
4027
+ let textReplaced = false;
4028
+ const preservedParts = [];
4029
+ for (const part of currentContent) {
4030
+ if (!part || typeof part !== "object" || part.type !== "text" || typeof part.text !== "string") {
4031
+ preservedParts.push(part);
4032
+ continue;
4033
+ }
4034
+ if (textReplaced) {
4035
+ continue;
4036
+ }
4037
+ textReplaced = true;
4038
+ preservedParts.push({
4039
+ ...part,
4040
+ text: maskedText
4041
+ });
4042
+ }
4043
+ nextContent = textReplaced ? preservedParts : [{ type: "text", text: maskedText }, ...currentContent];
4044
+ }
2965
4045
  newMessages[lastUserIdx] = {
2966
4046
  ...message,
2967
- content: maskedText
4047
+ content: nextContent
2968
4048
  };
2969
4049
  if (!req || typeof req !== "object") {
2970
4050
  return req;
@@ -2983,6 +4063,7 @@ var AgentID = class {
2983
4063
  event_type: "security_policy_violation",
2984
4064
  severity: "high",
2985
4065
  metadata: {
4066
+ ...params.telemetryMetadata ?? {},
2986
4067
  event_type: "security_policy_violation",
2987
4068
  severity: "high",
2988
4069
  system_id: params.systemId,
@@ -3010,6 +4091,7 @@ var AgentID = class {
3010
4091
  event_type: "security_alert",
3011
4092
  severity: "warning",
3012
4093
  metadata: {
4094
+ ...params.guardParams.metadata ?? {},
3013
4095
  source: "guard",
3014
4096
  status: params.status,
3015
4097
  guard_reason: params.reason,
@@ -3138,7 +4220,13 @@ var AgentID = class {
3138
4220
  guardParams: params,
3139
4221
  apiKey: effectiveApiKey
3140
4222
  });
3141
- return withGuardLatency({ allowed: true, reason: "system_failure_fail_open" });
4223
+ return withGuardLatency(
4224
+ this.buildFailOpenGuardVerdict(
4225
+ "system_failure_fail_open",
4226
+ params.input,
4227
+ { apiKey: effectiveApiKey }
4228
+ )
4229
+ );
3142
4230
  }
3143
4231
  this.cacheGuardVerdict(guardCacheKey, verdict);
3144
4232
  return withGuardLatency(verdict);
@@ -3173,7 +4261,11 @@ var AgentID = class {
3173
4261
  if (effectiveStrictMode) {
3174
4262
  return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
3175
4263
  }
3176
- return withGuardLatency({ allowed: true, reason: "timeout_fallback" });
4264
+ return withGuardLatency(
4265
+ this.buildFailOpenGuardVerdict("timeout_fallback", params.input, {
4266
+ apiKey: effectiveApiKey
4267
+ })
4268
+ );
3177
4269
  }
3178
4270
  console.warn(
3179
4271
  effectiveStrictMode ? "[AgentID] Guard check failed (Strict mode active):" : "[AgentID] Guard check failed (Fail-Open active):",
@@ -3188,7 +4280,11 @@ var AgentID = class {
3188
4280
  if (effectiveStrictMode) {
3189
4281
  return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
3190
4282
  }
3191
- return withGuardLatency({ allowed: true, reason: "guard_unreachable" });
4283
+ return withGuardLatency(
4284
+ this.buildFailOpenGuardVerdict("guard_unreachable", params.input, {
4285
+ apiKey: effectiveApiKey
4286
+ })
4287
+ );
3192
4288
  } finally {
3193
4289
  clearTimeout(timeoutId);
3194
4290
  }
@@ -3197,13 +4293,23 @@ var AgentID = class {
3197
4293
  if (effectiveStrictMode) {
3198
4294
  return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
3199
4295
  }
3200
- return withGuardLatency({ allowed: true, reason: "timeout_fallback" });
4296
+ return withGuardLatency(
4297
+ this.buildFailOpenGuardVerdict("timeout_fallback", params.input, {
4298
+ apiKey: effectiveApiKey
4299
+ })
4300
+ );
3201
4301
  }
3202
4302
  if (typeof lastStatusCode === "number" && lastStatusCode >= 500) {
3203
4303
  if (effectiveStrictMode) {
3204
4304
  return withGuardLatency({ allowed: false, reason: "server_error" });
3205
4305
  }
3206
- return withGuardLatency({ allowed: true, reason: "system_failure_fail_open" });
4306
+ return withGuardLatency(
4307
+ this.buildFailOpenGuardVerdict(
4308
+ "system_failure_fail_open",
4309
+ params.input,
4310
+ { apiKey: effectiveApiKey }
4311
+ )
4312
+ );
3207
4313
  }
3208
4314
  console.warn(
3209
4315
  effectiveStrictMode ? "[AgentID] Guard check failed (Strict mode active):" : "[AgentID] Guard check failed (Fail-Open active):",
@@ -3212,7 +4318,11 @@ var AgentID = class {
3212
4318
  if (effectiveStrictMode) {
3213
4319
  return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
3214
4320
  }
3215
- return withGuardLatency({ allowed: true, reason: "guard_unreachable" });
4321
+ return withGuardLatency(
4322
+ this.buildFailOpenGuardVerdict("guard_unreachable", params.input, {
4323
+ apiKey: effectiveApiKey
4324
+ })
4325
+ );
3216
4326
  }
3217
4327
  async sendIngest(params, options, internal) {
3218
4328
  const ingestStartedAt = Date.now();
@@ -3452,21 +4562,29 @@ var AgentID = class {
3452
4562
  wrapCompletion(completion, options) {
3453
4563
  if (typeof completion === "string") {
3454
4564
  const masked = this.pii.anonymize(completion);
4565
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4566
+ completion,
4567
+ options?.piiMapping
4568
+ );
3455
4569
  return {
3456
4570
  mode: "static",
3457
4571
  rawOutput: completion,
3458
4572
  transformedOutput: masked.maskedText,
3459
- outputMasked: masked.maskedText !== completion
4573
+ outputMasked: masked.maskedText !== completion || placeholderOutputMasked
3460
4574
  };
3461
4575
  }
3462
4576
  if (!isAsyncIterable(completion)) {
3463
4577
  const asText = String(completion ?? "");
3464
4578
  const masked = this.pii.anonymize(asText);
4579
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4580
+ asText,
4581
+ options?.piiMapping
4582
+ );
3465
4583
  return {
3466
4584
  mode: "static",
3467
4585
  rawOutput: asText,
3468
4586
  transformedOutput: masked.maskedText,
3469
- outputMasked: masked.maskedText !== asText
4587
+ outputMasked: masked.maskedText !== asText || placeholderOutputMasked
3470
4588
  };
3471
4589
  }
3472
4590
  const source = completion;
@@ -3476,8 +4594,10 @@ var AgentID = class {
3476
4594
  const isOpenAIStreamFinishChunk = this.isOpenAIStreamFinishChunk.bind(this);
3477
4595
  const rewriteOpenAIStreamChunkForClient = this.rewriteOpenAIStreamChunkForClient.bind(this);
3478
4596
  const createSyntheticOpenAIStreamChunk = this.createSyntheticOpenAIStreamChunk.bind(this);
4597
+ const setOpenAIStreamChunkText = this.setOpenAIStreamChunkText.bind(this);
3479
4598
  const piiManager = this.pii;
3480
4599
  const streamRewriter = options?.deanonymizeForClient === true && options.piiMapping ? createStreamingPlaceholderRewriter(piiManager, options.piiMapping) : null;
4600
+ const maskForClient = options?.maskForClient === true && streamRewriter === null;
3481
4601
  let lastUsage;
3482
4602
  let resolveDone = null;
3483
4603
  let rejectDone = null;
@@ -3490,12 +4610,17 @@ var AgentID = class {
3490
4610
  try {
3491
4611
  let finishChunkFlushed = false;
3492
4612
  let lastChunkTemplate;
4613
+ let clientRawText = "";
4614
+ let clientMaskFlushed = false;
3493
4615
  for await (const chunk of source) {
3494
4616
  const chunkText = extractStreamChunkText(chunk);
3495
- const isFinishChunk = streamRewriter ? isOpenAIStreamFinishChunk(chunk) : false;
4617
+ const isFinishChunk = streamRewriter || maskForClient ? isOpenAIStreamFinishChunk(chunk) : false;
3496
4618
  if (chunkText) {
3497
4619
  await collector.push(chunkText);
3498
4620
  lastChunkTemplate = chunk;
4621
+ if (maskForClient) {
4622
+ clientRawText += chunkText;
4623
+ }
3499
4624
  }
3500
4625
  const chunkUsage = extractStreamChunkUsage(chunk);
3501
4626
  if (chunkUsage) {
@@ -3515,6 +4640,28 @@ var AgentID = class {
3515
4640
  }
3516
4641
  continue;
3517
4642
  }
4643
+ if (maskForClient) {
4644
+ if (isFinishChunk) {
4645
+ const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
4646
+ clientMaskFlushed = true;
4647
+ if (maskedClientText.length > 0) {
4648
+ yield createSyntheticOpenAIStreamChunk(
4649
+ maskedClientText,
4650
+ lastChunkTemplate ?? chunk
4651
+ );
4652
+ }
4653
+ if (chunkText) {
4654
+ setOpenAIStreamChunkText(chunk, "");
4655
+ }
4656
+ yield chunk;
4657
+ finishChunkFlushed = true;
4658
+ continue;
4659
+ }
4660
+ if (!chunkText) {
4661
+ yield chunk;
4662
+ }
4663
+ continue;
4664
+ }
3518
4665
  yield chunk;
3519
4666
  }
3520
4667
  if (streamRewriter && !finishChunkFlushed) {
@@ -3526,14 +4673,27 @@ var AgentID = class {
3526
4673
  );
3527
4674
  }
3528
4675
  }
4676
+ if (maskForClient && !clientMaskFlushed) {
4677
+ const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
4678
+ if (maskedClientText.length > 0) {
4679
+ yield createSyntheticOpenAIStreamChunk(
4680
+ maskedClientText,
4681
+ lastChunkTemplate
4682
+ );
4683
+ }
4684
+ }
3529
4685
  await collector.close();
3530
4686
  const rawOutput = await collector.result;
3531
4687
  const masked = piiManager.anonymize(rawOutput);
4688
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4689
+ rawOutput,
4690
+ options?.piiMapping
4691
+ );
3532
4692
  resolveDone?.({
3533
4693
  mode: "static",
3534
4694
  rawOutput,
3535
4695
  transformedOutput: masked.maskedText,
3536
- outputMasked: masked.maskedText !== rawOutput,
4696
+ outputMasked: masked.maskedText !== rawOutput || placeholderOutputMasked,
3537
4697
  usage: lastUsage
3538
4698
  });
3539
4699
  } catch (error) {
@@ -3568,6 +4728,37 @@ var AgentID = class {
3568
4728
  );
3569
4729
  }
3570
4730
  }
4731
+ buildOperationLogParams(params) {
4732
+ return createAgentIdOperationLog(params);
4733
+ }
4734
+ async logOperation(params, options) {
4735
+ return this.log(this.buildOperationLogParams(params), options);
4736
+ }
4737
+ async logPromptPreflightStep(params, options) {
4738
+ const telemetry = buildPromptPreflightTelemetry(params);
4739
+ const summary = firstNonEmptyString(telemetry?.step_summary, telemetry?.stepSummary) ?? summarizePromptPreflightResult({
4740
+ verdict: params.verdict,
4741
+ localFallbackApplied: params.local_fallback_applied,
4742
+ localFallbackReason: params.local_fallback_reason
4743
+ });
4744
+ await this.logOperation(
4745
+ {
4746
+ system_id: params.system_id,
4747
+ user_id: params.user_id,
4748
+ request_identity: params.request_identity,
4749
+ input: params.input,
4750
+ output: summary,
4751
+ model: "not_applicable",
4752
+ latency: params.guard_latency_ms ?? void 0,
4753
+ telemetry,
4754
+ client_capabilities: params.client_capabilities
4755
+ },
4756
+ options
4757
+ );
4758
+ }
4759
+ operation(params, options) {
4760
+ return this.logOperation(params, options);
4761
+ }
3571
4762
  /**
3572
4763
  * Analytics alias for telemetry logging.
3573
4764
  */
@@ -3612,49 +4803,62 @@ var AgentID = class {
3612
4803
  if (typeof originalCreate !== "function") return originalCreate;
3613
4804
  return async (...args) => {
3614
4805
  const normalizedCreateArgs = normalizeOpenAICreateArgs(args);
3615
- const req = normalizedCreateArgs?.[0] ?? {};
4806
+ const rawReq = normalizedCreateArgs?.[0] ?? {};
4807
+ const requestTelemetry = extractRequestTelemetryContext(rawReq);
4808
+ const telemetryMetadata = mergeTelemetryContexts(
4809
+ options.telemetry,
4810
+ requestTelemetry
4811
+ );
4812
+ const providerReq = stripRequestTelemetryContext(rawReq);
3616
4813
  const pipelineStartedAt = Date.now();
3617
- const requestLevelApiKey = options.resolveApiKey?.(req) ?? options.apiKey ?? options.api_key;
4814
+ const requestLevelApiKey = options.resolveApiKey?.(rawReq) ?? options.apiKey ?? options.api_key;
3618
4815
  const effectiveApiKey = this.resolveApiKey(requestLevelApiKey);
3619
4816
  const requestOptions = { apiKey: effectiveApiKey };
3620
- const clientEventId = this.resolveClientEventId(req);
4817
+ const clientEventId = this.resolveClientEventId(rawReq);
3621
4818
  const effectiveStrictMode = await this.resolveEffectiveStrictMode(requestOptions);
3622
- const stream = adapter.isStream(req);
4819
+ const stream = adapter.isStream(providerReq);
3623
4820
  let capabilityConfig = this.getCachedCapabilityConfig(requestOptions);
3624
- const userText = adapter.extractInput(req);
3625
- let maskedText = userText;
3626
- let maskedReq = req;
3627
- let createArgs = normalizedCreateArgs;
4821
+ const userText = adapter.extractInput(providerReq);
4822
+ const requestAttachments = adapter.extractAttachments(providerReq);
4823
+ const hasGuardContent = userText !== null || requestAttachments.length > 0;
4824
+ let maskedText = userText ?? "";
4825
+ let maskedReq = providerReq;
4826
+ let createArgs = providerReq === rawReq ? normalizedCreateArgs : [{ ...providerReq }, ...normalizedCreateArgs.slice(1)];
3628
4827
  let mapping = {};
3629
- let shouldDeanonymize = false;
3630
4828
  let sdkConfigFetchMs = 0;
3631
4829
  let sdkLocalScanMs = 0;
3632
- if (userText) {
4830
+ let providerMaskingOptions;
4831
+ if (hasGuardContent) {
3633
4832
  const prepared = await this.prepareInputForDispatch({
3634
- input: userText,
4833
+ input: userText ?? "",
3635
4834
  systemId,
3636
4835
  stream,
3637
- clientEventId
4836
+ clientEventId,
4837
+ telemetryMetadata
3638
4838
  }, requestOptions);
3639
4839
  capabilityConfig = prepared.capabilityConfig;
4840
+ providerMaskingOptions = {
4841
+ pii: !capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig),
4842
+ secrets: !capabilityConfig.block_secret_leakage && this.resolveEffectiveSecretMasking(capabilityConfig)
4843
+ };
3640
4844
  maskedText = prepared.sanitizedInput;
3641
4845
  mapping = prepared.piiMapping ?? {};
3642
- shouldDeanonymize = prepared.shouldDeanonymize === true;
3643
4846
  sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
3644
4847
  sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
3645
- if (maskedText !== userText) {
4848
+ if (maskedText !== (userText ?? "")) {
3646
4849
  maskedReq = this.withMaskedOpenAIRequest(
3647
- req,
3648
- maskedText
4850
+ providerReq,
4851
+ maskedText,
4852
+ providerMaskingOptions
3649
4853
  );
3650
- const nextCreateArgs = [...normalizedCreateArgs];
4854
+ const nextCreateArgs = [...createArgs];
3651
4855
  nextCreateArgs[0] = maskedReq;
3652
4856
  createArgs = nextCreateArgs;
3653
4857
  }
3654
4858
  }
3655
- if (!maskedText) {
4859
+ if (!hasGuardContent) {
3656
4860
  throw new Error(
3657
- "AgentID: No user message found. Security guard requires string input."
4861
+ "AgentID: No user message or supported inline attachment found. Security guard requires prompt content."
3658
4862
  );
3659
4863
  }
3660
4864
  const verdict = await this.guard({
@@ -3665,6 +4869,8 @@ var AgentID = class {
3665
4869
  client_event_id: clientEventId,
3666
4870
  expected_languages: expectedLanguages,
3667
4871
  request_identity: options.request_identity,
4872
+ metadata: telemetryMetadata,
4873
+ attachments: requestAttachments,
3668
4874
  client_capabilities: this.buildClientCapabilities(
3669
4875
  "openai",
3670
4876
  false,
@@ -3686,22 +4892,44 @@ var AgentID = class {
3686
4892
  apiKey: effectiveApiKey,
3687
4893
  clientEventId,
3688
4894
  sdkConfigFetchMs,
4895
+ telemetryMetadata,
3689
4896
  runPromptInjectionCheck: true
3690
4897
  });
3691
4898
  maskedText = fallback.sanitizedInput;
3692
4899
  sdkLocalScanMs = fallback.sdkLocalScanMs;
3693
4900
  }
3694
4901
  } else {
4902
+ await this.logPromptPreflightStep(
4903
+ {
4904
+ system_id: systemId,
4905
+ user_id: options.user_id,
4906
+ request_identity: options.request_identity,
4907
+ input: maskedText,
4908
+ telemetry: telemetryMetadata,
4909
+ verdict,
4910
+ guard_event_id: verdict.guard_event_id ?? null,
4911
+ guard_latency_ms: 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),
4912
+ preflight_for_client_event_id: typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId,
4913
+ client_capabilities: this.buildClientCapabilities(
4914
+ "openai",
4915
+ false,
4916
+ capabilityConfig
4917
+ ),
4918
+ runtime_surface: "openai_sdk_guard"
4919
+ },
4920
+ requestOptions
4921
+ );
3695
4922
  throw new SecurityBlockError(verdict.reason ?? "guard_denied");
3696
4923
  }
3697
4924
  }
3698
- const currentRequestInput = adapter.extractInput(maskedReq);
3699
- if (maskedText !== currentRequestInput) {
4925
+ const currentRequestInput = adapter.extractInput(maskedReq) ?? "";
4926
+ if (maskedText !== currentRequestInput || providerMaskingOptions?.pii === true || providerMaskingOptions?.secrets === true) {
3700
4927
  maskedReq = this.withMaskedOpenAIRequest(
3701
- req,
3702
- maskedText
4928
+ providerReq,
4929
+ maskedText,
4930
+ providerMaskingOptions
3703
4931
  );
3704
- const nextCreateArgs = [...normalizedCreateArgs];
4932
+ const nextCreateArgs = [...createArgs];
3705
4933
  nextCreateArgs[0] = maskedReq;
3706
4934
  createArgs = nextCreateArgs;
3707
4935
  }
@@ -3712,15 +4940,45 @@ var AgentID = class {
3712
4940
  const isShadowMode = verdict.shadow_mode === true;
3713
4941
  const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
3714
4942
  if (transformedInput !== maskedText) {
4943
+ const serverDerivedMapping = derivePlaceholderMappingFromTransform(
4944
+ maskedText,
4945
+ transformedInput
4946
+ );
4947
+ if (Object.keys(serverDerivedMapping).length > 0) {
4948
+ mapping = mergePiiMappings(mapping, serverDerivedMapping);
4949
+ }
3715
4950
  maskedText = transformedInput;
3716
4951
  maskedReq = this.withMaskedOpenAIRequest(
3717
- req,
3718
- transformedInput
4952
+ providerReq,
4953
+ transformedInput,
4954
+ providerMaskingOptions
3719
4955
  );
3720
- const nextCreateArgs = [...normalizedCreateArgs];
4956
+ const nextCreateArgs = [...createArgs];
3721
4957
  nextCreateArgs[0] = maskedReq;
3722
4958
  createArgs = nextCreateArgs;
3723
4959
  }
4960
+ await this.logPromptPreflightStep(
4961
+ {
4962
+ system_id: systemId,
4963
+ user_id: options.user_id,
4964
+ request_identity: options.request_identity,
4965
+ input: maskedText,
4966
+ telemetry: telemetryMetadata,
4967
+ verdict,
4968
+ guard_event_id: guardEventId,
4969
+ guard_latency_ms: guardLatencyMs,
4970
+ preflight_for_client_event_id: canonicalClientEventId,
4971
+ client_capabilities: this.buildClientCapabilities(
4972
+ "openai",
4973
+ false,
4974
+ capabilityConfig
4975
+ ),
4976
+ local_fallback_applied: localFallbackApplied,
4977
+ local_fallback_reason: localFallbackReason,
4978
+ runtime_surface: "openai_sdk_guard"
4979
+ },
4980
+ requestOptions
4981
+ );
3724
4982
  if (stream) {
3725
4983
  const modelStartedAt2 = Date.now();
3726
4984
  const streamResponse = await originalCreate.apply(compTarget, createArgs);
@@ -3732,14 +4990,15 @@ var AgentID = class {
3732
4990
  })(),
3733
4991
  {
3734
4992
  piiMapping: mapping,
3735
- deanonymizeForClient: shouldDeanonymize
4993
+ deanonymizeForClient: false,
4994
+ maskForClient: !isShadowMode
3736
4995
  }
3737
4996
  );
3738
4997
  if (maskedText && wrappedCompletion.mode === "stream") {
3739
4998
  void wrappedCompletion.done.then(async (result) => {
3740
4999
  const modelLatencyMs2 = Math.max(0, Date.now() - modelStartedAt2);
3741
5000
  const totalPipelineLatencyMs2 = Math.max(0, Date.now() - pipelineStartedAt);
3742
- const outputForLog = isShadowMode ? result.rawOutput : result.transformedOutput;
5001
+ const outputForLog = result.transformedOutput;
3743
5002
  const ingestResult = await this.sendIngest({
3744
5003
  event_id: canonicalClientEventId,
3745
5004
  system_id: systemId,
@@ -3751,29 +5010,32 @@ var AgentID = class {
3751
5010
  usage: result.usage,
3752
5011
  latency: modelLatencyMs2,
3753
5012
  event_type: "complete",
3754
- metadata: {
3755
- transformed_input: maskedText,
3756
- transformed_output: result.transformedOutput,
3757
- output_masked: result.outputMasked,
3758
- shadow_mode: isShadowMode,
3759
- simulated_decision: verdict.simulated_decision ?? null,
3760
- simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
3761
- response_streamed: true,
3762
- sdk_local_fallback_applied: localFallbackApplied,
3763
- sdk_local_fallback_reason: localFallbackReason,
3764
- guard_latency_ms: guardLatencyMs,
3765
- model_latency_ms: modelLatencyMs2,
3766
- total_pipeline_latency_ms: totalPipelineLatencyMs2,
3767
- guard_event_id: guardEventId,
3768
- client_event_id: canonicalClientEventId,
3769
- transparency,
3770
- ...buildSdkTimingMetadata({
5013
+ metadata: mergeTelemetryContexts(
5014
+ telemetryMetadata,
5015
+ {
5016
+ transformed_input: maskedText,
5017
+ transformed_output: result.transformedOutput,
5018
+ output_masked: result.outputMasked,
5019
+ shadow_mode: isShadowMode,
5020
+ simulated_decision: verdict.simulated_decision ?? null,
5021
+ simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
5022
+ response_streamed: true,
5023
+ sdk_local_fallback_applied: localFallbackApplied,
5024
+ sdk_local_fallback_reason: localFallbackReason,
5025
+ guard_latency_ms: guardLatencyMs,
5026
+ model_latency_ms: modelLatencyMs2,
5027
+ total_pipeline_latency_ms: totalPipelineLatencyMs2,
5028
+ guard_event_id: guardEventId,
5029
+ client_event_id: canonicalClientEventId,
5030
+ transparency
5031
+ },
5032
+ buildSdkTimingMetadata({
3771
5033
  sdkConfigFetchMs,
3772
5034
  sdkLocalScanMs,
3773
5035
  sdkGuardMs: guardLatencyMs,
3774
5036
  sdkConfigVersion: capabilityConfig.version
3775
5037
  })
3776
- },
5038
+ ),
3777
5039
  client_capabilities: this.buildClientCapabilities(
3778
5040
  "openai",
3779
5041
  false,
@@ -3804,10 +5066,13 @@ var AgentID = class {
3804
5066
  const totalPipelineLatencyMs = Math.max(0, Date.now() - pipelineStartedAt);
3805
5067
  if (maskedText) {
3806
5068
  const output = adapter.extractOutput(res);
3807
- const wrappedCompletion = this.wrapCompletion(output);
5069
+ const wrappedCompletion = this.wrapCompletion(output, {
5070
+ piiMapping: mapping,
5071
+ deanonymizeForClient: false
5072
+ });
3808
5073
  const model = adapter.getModelName(maskedReq, res);
3809
5074
  const usage = adapter.getTokenUsage(res);
3810
- const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
5075
+ const outputForLog = wrappedCompletion.transformedOutput;
3811
5076
  const ingestResult = await this.sendIngest({
3812
5077
  event_id: canonicalClientEventId,
3813
5078
  system_id: systemId,
@@ -3819,29 +5084,32 @@ var AgentID = class {
3819
5084
  usage,
3820
5085
  latency: modelLatencyMs,
3821
5086
  event_type: "complete",
3822
- metadata: {
3823
- transformed_input: maskedText,
3824
- transformed_output: wrappedCompletion.transformedOutput,
3825
- output_masked: wrappedCompletion.outputMasked,
3826
- shadow_mode: isShadowMode,
3827
- simulated_decision: verdict.simulated_decision ?? null,
3828
- simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
3829
- response_streamed: false,
3830
- sdk_local_fallback_applied: localFallbackApplied,
3831
- sdk_local_fallback_reason: localFallbackReason,
3832
- guard_latency_ms: guardLatencyMs,
3833
- model_latency_ms: modelLatencyMs,
3834
- total_pipeline_latency_ms: totalPipelineLatencyMs,
3835
- guard_event_id: guardEventId,
3836
- client_event_id: canonicalClientEventId,
3837
- transparency,
3838
- ...buildSdkTimingMetadata({
5087
+ metadata: mergeTelemetryContexts(
5088
+ telemetryMetadata,
5089
+ {
5090
+ transformed_input: maskedText,
5091
+ transformed_output: wrappedCompletion.transformedOutput,
5092
+ output_masked: wrappedCompletion.outputMasked,
5093
+ shadow_mode: isShadowMode,
5094
+ simulated_decision: verdict.simulated_decision ?? null,
5095
+ simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
5096
+ response_streamed: false,
5097
+ sdk_local_fallback_applied: localFallbackApplied,
5098
+ sdk_local_fallback_reason: localFallbackReason,
5099
+ guard_latency_ms: guardLatencyMs,
5100
+ model_latency_ms: modelLatencyMs,
5101
+ total_pipeline_latency_ms: totalPipelineLatencyMs,
5102
+ guard_event_id: guardEventId,
5103
+ client_event_id: canonicalClientEventId,
5104
+ transparency
5105
+ },
5106
+ buildSdkTimingMetadata({
3839
5107
  sdkConfigFetchMs,
3840
5108
  sdkLocalScanMs,
3841
5109
  sdkGuardMs: guardLatencyMs,
3842
5110
  sdkConfigVersion: capabilityConfig.version
3843
5111
  })
3844
- },
5112
+ ),
3845
5113
  client_capabilities: this.buildClientCapabilities(
3846
5114
  "openai",
3847
5115
  false,
@@ -3858,17 +5126,21 @@ var AgentID = class {
3858
5126
  );
3859
5127
  }
3860
5128
  }
3861
- if (!capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig) && shouldDeanonymize) {
3862
- const deanon = this.pii.deanonymize(adapter.extractOutput(res), mapping);
5129
+ if (!isShadowMode && maskedText) {
5130
+ const output = adapter.extractOutput(res);
5131
+ const maskedOutput = this.wrapCompletion(output, {
5132
+ piiMapping: mapping,
5133
+ deanonymizeForClient: false
5134
+ }).transformedOutput;
3863
5135
  try {
3864
5136
  if (Array.isArray(res?.choices)) {
3865
5137
  for (const choice of res.choices) {
3866
5138
  const typedChoice = choice;
3867
5139
  if (typedChoice?.message && typeof typedChoice.message.content === "string") {
3868
- typedChoice.message.content = deanon;
5140
+ typedChoice.message.content = maskedOutput;
3869
5141
  }
3870
5142
  if (typedChoice?.delta && typeof typedChoice.delta.content === "string") {
3871
- typedChoice.delta.content = deanon;
5143
+ typedChoice.delta.content = maskedOutput;
3872
5144
  }
3873
5145
  }
3874
5146
  }
@@ -3893,6 +5165,155 @@ var AgentID = class {
3893
5165
  });
3894
5166
  }
3895
5167
  };
5168
+ function mergeWorkflowTrailRequestOptions(base, override) {
5169
+ const apiKey = firstNonEmptyString(override?.apiKey, base?.apiKey);
5170
+ return apiKey ? { apiKey } : void 0;
5171
+ }
5172
+ function appendWorkflowErrorMetadata(metadata, error) {
5173
+ const nextMetadata = { ...metadata ?? {} };
5174
+ if (error instanceof Error) {
5175
+ if (typeof nextMetadata.error_name !== "string") {
5176
+ nextMetadata.error_name = error.name;
5177
+ }
5178
+ if (typeof nextMetadata.error_message !== "string" && error.message.trim().length > 0) {
5179
+ nextMetadata.error_message = error.message.trim();
5180
+ }
5181
+ return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
5182
+ }
5183
+ if (typeof nextMetadata.error_message !== "string" && typeof error !== "undefined") {
5184
+ const errorMessage = String(error).trim();
5185
+ if (errorMessage.length > 0) {
5186
+ nextMetadata.error_message = errorMessage;
5187
+ }
5188
+ }
5189
+ return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
5190
+ }
5191
+ var AgentIDWorkflowStep = class {
5192
+ constructor(params) {
5193
+ this.trail = params.trail;
5194
+ this.workflowStepId = params.workflowStepId;
5195
+ this.startEventId = params.startEventId;
5196
+ this.telemetry = params.telemetry;
5197
+ this.startedAtMs = params.startedAtMs;
5198
+ }
5199
+ resolveStepTelemetry(telemetry) {
5200
+ return mergeTelemetryContexts(
5201
+ this.telemetry,
5202
+ createAgentIdTelemetryContext({
5203
+ workflow_step_id: this.workflowStepId,
5204
+ parent_event_id: this.startEventId
5205
+ }),
5206
+ telemetry
5207
+ );
5208
+ }
5209
+ async log(params = {}, options) {
5210
+ return this.trail.logStep(
5211
+ {
5212
+ ...params,
5213
+ telemetry: this.resolveStepTelemetry(params.telemetry)
5214
+ },
5215
+ options
5216
+ );
5217
+ }
5218
+ async complete(params = {}, options) {
5219
+ return this.log(
5220
+ {
5221
+ ...params,
5222
+ latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
5223
+ event_status: params.event_status ?? "completed"
5224
+ },
5225
+ options
5226
+ );
5227
+ }
5228
+ async fail(error, params = {}, options) {
5229
+ return this.log(
5230
+ {
5231
+ ...params,
5232
+ latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
5233
+ metadata: appendWorkflowErrorMetadata(params.metadata, error),
5234
+ event_type: params.event_type ?? "error",
5235
+ event_status: params.event_status ?? "failed",
5236
+ severity: params.severity ?? "error"
5237
+ },
5238
+ options
5239
+ );
5240
+ }
5241
+ };
5242
+ var AgentIDWorkflowTrail = class {
5243
+ constructor(options) {
5244
+ this.agent = options.agent;
5245
+ this.systemId = options.system_id;
5246
+ this.userId = options.user_id;
5247
+ this.requestIdentity = options.request_identity;
5248
+ this.telemetry = createAgentIdTelemetryContext(options.telemetry);
5249
+ this.clientCapabilities = options.client_capabilities;
5250
+ this.requestOptions = options.requestOptions;
5251
+ }
5252
+ async logStep(params = {}, options) {
5253
+ const payload = this.agent.buildOperationLogParams({
5254
+ ...params,
5255
+ system_id: this.systemId,
5256
+ user_id: this.userId,
5257
+ request_identity: this.requestIdentity,
5258
+ telemetry: mergeTelemetryContexts(this.telemetry, params.telemetry),
5259
+ client_capabilities: params.client_capabilities ?? this.clientCapabilities
5260
+ });
5261
+ await this.agent.log(
5262
+ payload,
5263
+ mergeWorkflowTrailRequestOptions(this.requestOptions, options)
5264
+ );
5265
+ return payload;
5266
+ }
5267
+ async startStep(params = {}, options) {
5268
+ const startedAtMs = Date.now();
5269
+ const requestedTelemetry = createAgentIdTelemetryContext(params.telemetry);
5270
+ const workflowStepId = firstNonEmptyString(requestedTelemetry?.workflow_step_id, requestedTelemetry?.workflowStepId) ?? createAgentIdCorrelationId();
5271
+ const startTelemetry = mergeTelemetryContexts(
5272
+ requestedTelemetry,
5273
+ createAgentIdTelemetryContext({
5274
+ workflow_step_id: workflowStepId
5275
+ })
5276
+ );
5277
+ const startPayload = await this.logStep(
5278
+ {
5279
+ ...params,
5280
+ telemetry: startTelemetry,
5281
+ event_type: params.event_type ?? "start",
5282
+ event_status: params.event_status ?? "started"
5283
+ },
5284
+ options
5285
+ );
5286
+ return new AgentIDWorkflowStep({
5287
+ trail: this,
5288
+ workflowStepId,
5289
+ startEventId: startPayload.event_id ?? createEventId2(),
5290
+ telemetry: startTelemetry,
5291
+ startedAtMs
5292
+ });
5293
+ }
5294
+ async runStep(params, run, hooks, options) {
5295
+ const step = await this.startStep(params, options);
5296
+ try {
5297
+ const result = await run();
5298
+ const completeParams = {
5299
+ ...hooks?.complete ?? {},
5300
+ ...hooks?.onComplete?.(result) ?? {}
5301
+ };
5302
+ await step.complete(completeParams, options);
5303
+ return result;
5304
+ } catch (error) {
5305
+ const failParams = {
5306
+ ...hooks?.fail ?? {},
5307
+ ...hooks?.onError?.(error) ?? {}
5308
+ };
5309
+ await step.fail(error, failParams, options);
5310
+ throw error;
5311
+ }
5312
+ }
5313
+ };
5314
+ function createAgentIdWorkflowTrail(options) {
5315
+ return new AgentIDWorkflowTrail(options);
5316
+ }
3896
5317
 
3897
5318
  export {
3898
5319
  OpenAIAdapter,
@@ -3900,7 +5321,13 @@ export {
3900
5321
  scanWithRegex,
3901
5322
  InjectionScanner,
3902
5323
  getInjectionScanner,
5324
+ createAgentIdCorrelationId,
5325
+ createAgentIdTelemetryContext,
5326
+ createAgentIdOperationLog,
3903
5327
  SecurityBlockError,
3904
5328
  DependencyError,
3905
- AgentID
5329
+ AgentID,
5330
+ AgentIDWorkflowStep,
5331
+ AgentIDWorkflowTrail,
5332
+ createAgentIdWorkflowTrail
3906
5333
  };