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.
package/dist/index.js CHANGED
@@ -21,27 +21,106 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AgentID: () => AgentID,
24
+ AgentIDWorkflowStep: () => AgentIDWorkflowStep,
25
+ AgentIDWorkflowTrail: () => AgentIDWorkflowTrail,
24
26
  DependencyError: () => DependencyError,
25
27
  InjectionScanner: () => InjectionScanner,
26
28
  OpenAIAdapter: () => OpenAIAdapter,
27
29
  PIIManager: () => PIIManager,
28
30
  SecurityBlockError: () => SecurityBlockError,
31
+ createAgentIdCorrelationId: () => createAgentIdCorrelationId,
32
+ createAgentIdOperationLog: () => createAgentIdOperationLog,
33
+ createAgentIdTelemetryContext: () => createAgentIdTelemetryContext,
34
+ createAgentIdWorkflowTrail: () => createAgentIdWorkflowTrail,
29
35
  getInjectionScanner: () => getInjectionScanner,
36
+ protectMessageHistory: () => protectMessageHistory,
30
37
  scanWithRegex: () => scanWithRegex
31
38
  });
32
39
  module.exports = __toCommonJS(index_exports);
33
40
 
34
41
  // src/adapters.ts
42
+ function getLastUserMessage(req) {
43
+ const messages = req?.messages;
44
+ if (!Array.isArray(messages)) return null;
45
+ let lastUser = null;
46
+ for (const msg of messages) {
47
+ if (msg && typeof msg === "object" && msg.role === "user") {
48
+ lastUser = msg;
49
+ }
50
+ }
51
+ return lastUser;
52
+ }
53
+ function normalizeFilename(value, fallback) {
54
+ if (typeof value !== "string") {
55
+ return fallback;
56
+ }
57
+ const trimmed = value.trim();
58
+ return trimmed.length > 0 ? trimmed : fallback;
59
+ }
60
+ function parseDataUrl(value) {
61
+ if (!value.startsWith("data:")) {
62
+ return null;
63
+ }
64
+ const commaIndex = value.indexOf(",");
65
+ if (commaIndex === -1) {
66
+ return null;
67
+ }
68
+ const header = value.slice(5, commaIndex);
69
+ if (!/;base64/i.test(header)) {
70
+ return null;
71
+ }
72
+ const mimeType = header.split(";")[0]?.trim().toLowerCase() || null;
73
+ return { mimeType };
74
+ }
75
+ function inferAttachmentExtension(mimeType) {
76
+ switch (mimeType) {
77
+ case "application/pdf":
78
+ return "pdf";
79
+ case "image/png":
80
+ return "png";
81
+ case "image/jpeg":
82
+ return "jpg";
83
+ case "image/webp":
84
+ return "webp";
85
+ case "image/gif":
86
+ return "gif";
87
+ case "text/plain":
88
+ return "txt";
89
+ default:
90
+ return "bin";
91
+ }
92
+ }
93
+ function defaultFilenameForMimeType(mimeType) {
94
+ return `attachment.${inferAttachmentExtension(mimeType)}`;
95
+ }
96
+ function normalizeFileAttachment(part) {
97
+ const file = part?.file;
98
+ const rawContent = typeof file?.file_data === "string" && file.file_data.trim().length > 0 ? file.file_data.trim() : null;
99
+ if (!rawContent) {
100
+ return null;
101
+ }
102
+ const detectedMimeType = parseDataUrl(rawContent)?.mimeType ?? null;
103
+ return {
104
+ filename: normalizeFilename(file?.filename, defaultFilenameForMimeType(detectedMimeType)),
105
+ ...detectedMimeType ? { mime_type: detectedMimeType } : {},
106
+ content_base64: rawContent
107
+ };
108
+ }
109
+ function normalizeImageAttachment(part) {
110
+ const imageUrl = typeof part?.image_url?.url === "string" && part.image_url.url.trim().length > 0 ? part.image_url.url.trim() : null;
111
+ if (!imageUrl || !imageUrl.startsWith("data:")) {
112
+ return null;
113
+ }
114
+ const detectedMimeType = parseDataUrl(imageUrl)?.mimeType ?? "image/png";
115
+ return {
116
+ filename: defaultFilenameForMimeType(detectedMimeType),
117
+ mime_type: detectedMimeType,
118
+ content_base64: imageUrl
119
+ };
120
+ }
35
121
  var OpenAIAdapter = class {
36
122
  extractInput(req) {
37
- const messages = req?.messages;
38
- if (!Array.isArray(messages)) return null;
39
- let lastUser = null;
40
- for (const msg of messages) {
41
- if (msg && typeof msg === "object" && msg.role === "user") {
42
- lastUser = msg;
43
- }
44
- }
123
+ const lastUser = getLastUserMessage(req);
45
124
  if (!lastUser) return null;
46
125
  const content = lastUser.content;
47
126
  if (typeof content === "string") return content;
@@ -56,6 +135,34 @@ var OpenAIAdapter = class {
56
135
  }
57
136
  return null;
58
137
  }
138
+ extractAttachments(req) {
139
+ const lastUser = getLastUserMessage(req);
140
+ if (!lastUser) return [];
141
+ const content = lastUser?.content;
142
+ if (!Array.isArray(content)) {
143
+ return [];
144
+ }
145
+ const attachments = [];
146
+ for (const part of content) {
147
+ if (!part || typeof part !== "object") {
148
+ continue;
149
+ }
150
+ if (part.type === "file") {
151
+ const attachment = normalizeFileAttachment(part);
152
+ if (attachment) {
153
+ attachments.push(attachment);
154
+ }
155
+ continue;
156
+ }
157
+ if (part.type === "image_url") {
158
+ const attachment = normalizeImageAttachment(part);
159
+ if (attachment) {
160
+ attachments.push(attachment);
161
+ }
162
+ }
163
+ }
164
+ return attachments;
165
+ }
59
166
  getModelName(req, res) {
60
167
  const model = res?.model ?? req?.model ?? "unknown";
61
168
  return String(model);
@@ -75,7 +182,7 @@ var OpenAIAdapter = class {
75
182
 
76
183
  // src/sdk-version.ts
77
184
  var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
78
- var AGENTID_SDK_VERSION_HEADER = "js-0.1.37".trim().length > 0 ? "js-0.1.37" : FALLBACK_SDK_VERSION;
185
+ var AGENTID_SDK_VERSION_HEADER = "js-0.1.40".trim().length > 0 ? "js-0.1.40" : FALLBACK_SDK_VERSION;
79
186
 
80
187
  // src/pii-national-identifiers.ts
81
188
  var MAX_CANDIDATES_PER_RULE = 256;
@@ -939,8 +1046,173 @@ function detectNationalIdentifiers(text, options = {}) {
939
1046
  return results;
940
1047
  }
941
1048
 
1049
+ // src/secret-patterns.ts
1050
+ var SDK_SECRET_PATTERN_DEFINITIONS = [
1051
+ {
1052
+ id: "openai_api_key",
1053
+ placeholderType: "OPENAI_API_KEY",
1054
+ patternSource: "\\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\\b",
1055
+ flags: "iu",
1056
+ prefilterTerms: ["sk-", "proj-", "openai"]
1057
+ },
1058
+ {
1059
+ id: "aws_access_key",
1060
+ placeholderType: "AWS_ACCESS_KEY",
1061
+ patternSource: "\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b",
1062
+ flags: "iu",
1063
+ prefilterTerms: ["akia", "asia", "aws"]
1064
+ },
1065
+ {
1066
+ id: "github_token",
1067
+ placeholderType: "GITHUB_TOKEN",
1068
+ patternSource: "\\b(?:gh[pousr]_[A-Za-z0-9]{24,255}|github_pat_[A-Za-z0-9_]{20,255})\\b",
1069
+ flags: "iu",
1070
+ prefilterTerms: ["ghp_", "gho_", "ghu_", "ghs_", "ghr_", "github_pat_"]
1071
+ },
1072
+ {
1073
+ id: "slack_token",
1074
+ placeholderType: "SLACK_TOKEN",
1075
+ patternSource: "\\bxox(?:a|b|p|r|s)-[A-Za-z0-9-]{10,200}\\b",
1076
+ flags: "iu",
1077
+ prefilterTerms: ["xoxa-", "xoxb-", "xoxp-", "xoxr-", "xoxs-", "slack"]
1078
+ },
1079
+ {
1080
+ id: "slack_webhook_url",
1081
+ placeholderType: "SLACK_WEBHOOK_URL",
1082
+ patternSource: "https:\\/\\/hooks\\.slack\\.com\\/services\\/[A-Za-z0-9/_-]{20,}",
1083
+ flags: "iu",
1084
+ prefilterTerms: ["hooks.slack.com/services", "slack"]
1085
+ },
1086
+ {
1087
+ id: "discord_webhook_url",
1088
+ placeholderType: "DISCORD_WEBHOOK_URL",
1089
+ patternSource: "https:\\/\\/discord(?:app)?\\.com\\/api\\/webhooks\\/\\d+\\/[A-Za-z0-9_-]{16,}",
1090
+ flags: "iu",
1091
+ prefilterTerms: ["discord.com/api/webhooks", "discordapp.com/api/webhooks", "discord"]
1092
+ },
1093
+ {
1094
+ id: "stripe_secret_key",
1095
+ placeholderType: "STRIPE_SECRET_KEY",
1096
+ patternSource: "\\b(?:sk|pk|ak|rk)_(?:live|test)_[A-Za-z0-9]+\\b",
1097
+ flags: "iu",
1098
+ prefilterTerms: [
1099
+ "sk_live_",
1100
+ "pk_live_",
1101
+ "sk_test_",
1102
+ "pk_test_",
1103
+ "ak_live_",
1104
+ "ak_test_",
1105
+ "rk_live_",
1106
+ "rk_test_",
1107
+ "stripe"
1108
+ ]
1109
+ },
1110
+ {
1111
+ id: "google_api_key",
1112
+ placeholderType: "GOOGLE_API_KEY",
1113
+ patternSource: "\\bAIza[0-9A-Za-z_-]{35}\\b",
1114
+ flags: "iu",
1115
+ prefilterTerms: ["aiza", "google"]
1116
+ },
1117
+ {
1118
+ id: "anthropic_api_key",
1119
+ placeholderType: "ANTHROPIC_API_KEY",
1120
+ patternSource: "\\bsk-ant-(?:api\\d{2}-)?[A-Za-z0-9_-]{20,}\\b",
1121
+ flags: "iu",
1122
+ prefilterTerms: ["sk-ant-", "anthropic"]
1123
+ },
1124
+ {
1125
+ id: "evm_private_key",
1126
+ placeholderType: "EVM_PRIVATE_KEY",
1127
+ patternSource: "\\b0x[a-fA-F0-9]{64}\\b",
1128
+ flags: "iu",
1129
+ prefilterTerms: ["0x", "ethereum", "evm", "private key"]
1130
+ },
1131
+ {
1132
+ id: "jwt_token",
1133
+ placeholderType: "JWT_TOKEN",
1134
+ patternSource: "\\beyJ[A-Za-z0-9_-]{6,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\b",
1135
+ flags: "iu",
1136
+ prefilterTerms: ["eyj", "jwt", "bearer"]
1137
+ },
1138
+ {
1139
+ id: "bearer_token",
1140
+ placeholderType: "BEARER_TOKEN",
1141
+ patternSource: "\\bauthorization\\b\\s*[:=]\\s*bearer\\s+[A-Za-z0-9._~+\\/-]{16,}|\\bbearer\\s+[A-Za-z0-9._~+\\/-]{24,}",
1142
+ flags: "iu",
1143
+ prefilterTerms: ["authorization", "bearer"]
1144
+ },
1145
+ {
1146
+ id: "api_key_header",
1147
+ placeholderType: "API_KEY_HEADER",
1148
+ patternSource: "\\bx[-_]?api[-_]?key\\b\\s*[:=]\\s*[A-Za-z0-9._~+\\/-]{16,}",
1149
+ flags: "iu",
1150
+ prefilterTerms: ["x-api-key", "api-key", "x_api_key", "api_key"]
1151
+ },
1152
+ {
1153
+ id: "credential_assignment",
1154
+ placeholderType: "CREDENTIAL_ASSIGNMENT",
1155
+ 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,})`,
1156
+ flags: "iu",
1157
+ prefilterTerms: [
1158
+ "api key",
1159
+ "apikey",
1160
+ "api_key",
1161
+ "access token",
1162
+ "access_token",
1163
+ "auth token",
1164
+ "client secret",
1165
+ "private key"
1166
+ ]
1167
+ },
1168
+ {
1169
+ id: "password_assignment",
1170
+ placeholderType: "PASSWORD_ASSIGNMENT",
1171
+ 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,})`,
1172
+ flags: "iu",
1173
+ prefilterTerms: ["password", "passwd", "pwd", "heslo"]
1174
+ },
1175
+ {
1176
+ id: "private_key_material",
1177
+ placeholderType: "PRIVATE_KEY_MATERIAL",
1178
+ 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)-----|$)",
1179
+ flags: "iu",
1180
+ prefilterTerms: ["begin private key", "begin pgp private key block", "private key"]
1181
+ },
1182
+ {
1183
+ id: "azure_connection_string",
1184
+ placeholderType: "AZURE_CONNECTION_STRING",
1185
+ patternSource: "\\bDefaultEndpointsProtocol=https;AccountName=[A-Za-z0-9.-]{3,};AccountKey=[A-Za-z0-9+/=]{20,}(?:;EndpointSuffix=[A-Za-z0-9.-]+)?\\b",
1186
+ flags: "iu",
1187
+ prefilterTerms: ["defaultendpointsprotocol", "accountname", "accountkey", "azure"]
1188
+ },
1189
+ {
1190
+ id: "azure_sas_token",
1191
+ placeholderType: "AZURE_SAS_TOKEN",
1192
+ patternSource: "\\bsv=[^\\s&]{2,}&[^\\s]{0,200}\\bsig=[A-Za-z0-9%/+_-]{16,}",
1193
+ flags: "iu",
1194
+ prefilterTerms: ["sv=", "sig=", "accountkey", "azure"]
1195
+ }
1196
+ ];
1197
+ function ensureGlobalFlag(flags) {
1198
+ const normalized = new Set(flags.split(""));
1199
+ normalized.add("g");
1200
+ return [...normalized].join("");
1201
+ }
1202
+ var COMPILED_SDK_SECRET_PATTERNS = SDK_SECRET_PATTERN_DEFINITIONS.map((definition) => ({
1203
+ ...definition,
1204
+ scanRegex: new RegExp(definition.patternSource, ensureGlobalFlag(definition.flags)),
1205
+ prefilterTermsLower: definition.prefilterTerms.map((term) => term.toLowerCase())
1206
+ }));
1207
+ function getSdkSecretDetectionMatchers() {
1208
+ return COMPILED_SDK_SECRET_PATTERNS;
1209
+ }
1210
+
942
1211
  // src/pii.ts
943
1212
  var defaultScanDeadlineMs = 100;
1213
+ var sdkSecretMatchers = getSdkSecretDetectionMatchers();
1214
+ var DISCORD_WEBHOOK_TOKEN_RE = /https:\/\/discord(?:app)?\.com\/api\/webhooks\/\d+\/([A-Za-z0-9_-]{16,})/giu;
1215
+ var BASIC_AUTH_PASSWORD_RE = /\/\/[^:\s/?#@]+:([^@\s/?#]+)@/giu;
944
1216
  function countDigits2(value) {
945
1217
  let count = 0;
946
1218
  for (const ch of value) {
@@ -965,15 +1237,32 @@ function luhnCheck(value) {
965
1237
  return sum % 10 === 0;
966
1238
  }
967
1239
  function normalizeDetections(text, detections) {
968
- 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));
1240
+ const sorted = detections.filter((d) => d.start >= 0 && d.end > d.start && d.end <= text.length).sort(
1241
+ (a, b) => detectionPriority(b.type) - detectionPriority(a.type) || a.start - b.start || b.end - b.start - (a.end - a.start)
1242
+ );
969
1243
  const kept = [];
970
- let cursor = 0;
971
1244
  for (const d of sorted) {
972
- if (d.start < cursor) continue;
1245
+ if (kept.some((candidate) => rangesOverlap(candidate, d))) continue;
973
1246
  kept.push(d);
974
- cursor = d.end;
975
1247
  }
976
- return kept;
1248
+ return kept.sort((a, b) => a.start - b.start || a.end - b.end);
1249
+ }
1250
+ function rangesOverlap(left, right) {
1251
+ return left.start < right.end && right.start < left.end;
1252
+ }
1253
+ function detectionPriority(type) {
1254
+ 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(
1255
+ type
1256
+ )) {
1257
+ return 100;
1258
+ }
1259
+ if (/^(?:CREDENTIAL_ASSIGNMENT|PASSWORD_ASSIGNMENT|PRIVATE_KEY_MATERIAL|ENV_SECRET_ASSIGNMENT)$/u.test(type)) {
1260
+ return 80;
1261
+ }
1262
+ if (type === "PERSON_NAME" || type === "PERSON") {
1263
+ return 10;
1264
+ }
1265
+ return 50;
977
1266
  }
978
1267
  var PHONE_CONTEXT_KEYWORDS = [
979
1268
  "tel",
@@ -983,6 +1272,8 @@ var PHONE_CONTEXT_KEYWORDS = [
983
1272
  "call",
984
1273
  "contact",
985
1274
  "number",
1275
+ "cislo",
1276
+ "\u010D\xEDslo",
986
1277
  "hotline",
987
1278
  "support",
988
1279
  "infoline",
@@ -1008,6 +1299,59 @@ var PHONE_CONTEXT_RE = new RegExp(
1008
1299
  "iu"
1009
1300
  );
1010
1301
  var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1302
+ "name",
1303
+ "names",
1304
+ "namen",
1305
+ "firstname",
1306
+ "lastname",
1307
+ "first",
1308
+ "last",
1309
+ "forename",
1310
+ "surname",
1311
+ "family",
1312
+ "given",
1313
+ "jmeno",
1314
+ "jake",
1315
+ "jaky",
1316
+ "jaka",
1317
+ "jsem",
1318
+ "jsme",
1319
+ "napsal",
1320
+ "napsali",
1321
+ "napsala",
1322
+ "napsane",
1323
+ "pouzil",
1324
+ "pouzili",
1325
+ "prijmeni",
1326
+ "vorname",
1327
+ "nachname",
1328
+ "familienname",
1329
+ "what",
1330
+ "which",
1331
+ "whose",
1332
+ "did",
1333
+ "we",
1334
+ "write",
1335
+ "wrote",
1336
+ "written",
1337
+ "type",
1338
+ "typed",
1339
+ "use",
1340
+ "used",
1341
+ "wie",
1342
+ "welchen",
1343
+ "welche",
1344
+ "welches",
1345
+ "haben",
1346
+ "wir",
1347
+ "geschrieben",
1348
+ "getippt",
1349
+ "quel",
1350
+ "quelle",
1351
+ "nom",
1352
+ "que",
1353
+ "cual",
1354
+ "nombre",
1011
1355
  "write",
1012
1356
  "code",
1013
1357
  "script",
@@ -1034,6 +1378,52 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1034
1378
  "security",
1035
1379
  "instructions",
1036
1380
  "instruction",
1381
+ "google",
1382
+ "form",
1383
+ "forms",
1384
+ "engineering",
1385
+ "leadership",
1386
+ "weekly",
1387
+ "daily",
1388
+ "monthly",
1389
+ "quarterly",
1390
+ "sync",
1391
+ "office",
1392
+ "updates",
1393
+ "update",
1394
+ "meeting",
1395
+ "meetings",
1396
+ "agenda",
1397
+ "minutes",
1398
+ "subject",
1399
+ "calendar",
1400
+ "roadmap",
1401
+ "platform",
1402
+ "product",
1403
+ "design",
1404
+ "operations",
1405
+ "business",
1406
+ "newsletter",
1407
+ "report",
1408
+ "reports",
1409
+ "amazon",
1410
+ "web",
1411
+ "services",
1412
+ "aws",
1413
+ "velka",
1414
+ "transformace",
1415
+ "project",
1416
+ "projekt",
1417
+ "program",
1418
+ "initiative",
1419
+ "iniciativa",
1420
+ "migration",
1421
+ "migrace",
1422
+ "test",
1423
+ "uuid",
1424
+ "fixture",
1425
+ "data",
1426
+ "firma",
1037
1427
  "rules",
1038
1428
  "rule",
1039
1429
  "json",
@@ -1046,10 +1436,22 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1046
1436
  "agentid",
1047
1437
  "risk",
1048
1438
  "score",
1049
- "summary"
1439
+ "summary",
1440
+ "hi",
1441
+ "hello",
1442
+ "hey",
1443
+ "dear",
1444
+ "team",
1445
+ "ahoj",
1446
+ "dobry",
1447
+ "dobryden",
1448
+ "zdravim"
1050
1449
  ]);
1051
1450
  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;
1052
1451
  var TECHNICAL_CONTEXT_SYMBOL_REGEX = /:\/\/|`|\{|\}|\[|\]|\(|\)|;|\$|=>|::|\/\//;
1452
+ 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;
1453
+ var NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX = /(?:[:=]|=>|-|\b(?:is|was|je|jsou|jmenuje|called|named|ist|sind|lautet|est|es)\b)\s*$/iu;
1454
+ 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;
1053
1455
  function hasPhoneContext(text, matchStartIndex, windowSize = 50) {
1054
1456
  const start = Math.max(0, matchStartIndex - windowSize);
1055
1457
  const windowLower = text.slice(start, matchStartIndex).toLowerCase();
@@ -1066,6 +1468,16 @@ function buildContextWindow(source, index, length) {
1066
1468
  function isTechnicalContext(contextWindow) {
1067
1469
  return TECHNICAL_CONTEXT_WORD_REGEX.test(contextWindow) || TECHNICAL_CONTEXT_SYMBOL_REGEX.test(contextWindow);
1068
1470
  }
1471
+ function isNameLabelQuestionContext(contextWindow) {
1472
+ const normalized = normalizePersonWord(contextWindow);
1473
+ if (!normalized.trim()) {
1474
+ return false;
1475
+ }
1476
+ if (!NAME_LABEL_QUESTION_CONTEXT_REGEX.test(normalized)) {
1477
+ return false;
1478
+ }
1479
+ return !NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX.test(normalized.slice(-32));
1480
+ }
1069
1481
  function isLikelyPersonNameCandidate(candidate, contextWindow) {
1070
1482
  const words = candidate.trim().split(/\s+/);
1071
1483
  if (words.length !== 2) {
@@ -1074,6 +1486,9 @@ function isLikelyPersonNameCandidate(candidate, contextWindow) {
1074
1486
  if (isTechnicalContext(contextWindow)) {
1075
1487
  return false;
1076
1488
  }
1489
+ if (isNameLabelQuestionContext(contextWindow)) {
1490
+ return false;
1491
+ }
1077
1492
  for (const rawWord of words) {
1078
1493
  const normalized = normalizePersonWord(rawWord);
1079
1494
  if (normalized.length < 2) {
@@ -1094,63 +1509,135 @@ var PIIManager = class {
1094
1509
  *
1095
1510
  * Zero-dependency fallback with strict checksum validation for CEE national IDs.
1096
1511
  */
1097
- anonymize(text) {
1512
+ anonymize(text, options) {
1098
1513
  if (!text) return { maskedText: text, mapping: {} };
1099
1514
  try {
1100
1515
  const detections = [];
1101
- const emailRe = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
1102
- for (const m of text.matchAll(emailRe)) {
1103
- if (m.index == null) continue;
1104
- detections.push({ start: m.index, end: m.index + m[0].length, type: "EMAIL", text: m[0] });
1105
- }
1106
- const ibanRe = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/gi;
1107
- for (const m of text.matchAll(ibanRe)) {
1108
- if (m.index == null) continue;
1109
- detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
1110
- }
1111
- const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
1112
- for (const m of text.matchAll(ccRe)) {
1113
- if (m.index == null) continue;
1114
- const digits = countDigits2(m[0]);
1115
- if (digits < 12 || digits > 19) continue;
1116
- if (!luhnCheck(m[0])) continue;
1117
- detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
1516
+ const loweredText = text.toLowerCase();
1517
+ const resolvedOptions = {
1518
+ pii: options?.pii !== false,
1519
+ secrets: options?.secrets !== false
1520
+ };
1521
+ if (!resolvedOptions.pii && !resolvedOptions.secrets) {
1522
+ return { maskedText: text, mapping: {} };
1118
1523
  }
1119
- const phoneRe = /(?<!\d)(?:\+?\d[\d\s().-]{7,}\d)(?!\d)/g;
1120
- for (const m of text.matchAll(phoneRe)) {
1121
- if (m.index == null) continue;
1122
- const candidate = m[0];
1123
- const digits = countDigits2(candidate);
1124
- if (digits < 9 || digits > 15) continue;
1125
- const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
1126
- if (!isStrongInternational) {
1127
- const hasContext = hasPhoneContext(text, m.index);
1128
- if (!hasContext) continue;
1524
+ if (resolvedOptions.pii) {
1525
+ const emailRe = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
1526
+ for (const m of text.matchAll(emailRe)) {
1527
+ if (m.index == null) continue;
1528
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "EMAIL", text: m[0] });
1129
1529
  }
1130
- detections.push({ start: m.index, end: m.index + m[0].length, type: "PHONE", text: m[0] });
1131
- }
1132
- const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
1133
- for (const m of text.matchAll(personRe)) {
1134
- if (m.index == null) continue;
1135
- const candidate = m[0];
1136
- const contextWindow = buildContextWindow(text, m.index, candidate.length);
1137
- if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
1138
- continue;
1530
+ const ibanRe = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/gi;
1531
+ for (const m of text.matchAll(ibanRe)) {
1532
+ if (m.index == null) continue;
1533
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
1139
1534
  }
1140
- detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
1141
- }
1142
- const nationalIdMatches = detectNationalIdentifiers(text, {
1143
- deadlineMs: defaultScanDeadlineMs,
1144
- allowContextBirthNumberFallback: false
1145
- });
1146
- for (const match of nationalIdMatches) {
1147
- if (match.start < 0 || match.end <= match.start) continue;
1148
- detections.push({
1149
- start: match.start,
1150
- end: match.end,
1151
- type: "NATIONAL_ID",
1152
- text: text.slice(match.start, match.end)
1535
+ const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
1536
+ for (const m of text.matchAll(ccRe)) {
1537
+ if (m.index == null) continue;
1538
+ const digits = countDigits2(m[0]);
1539
+ if (digits < 12 || digits > 19) continue;
1540
+ if (!luhnCheck(m[0])) continue;
1541
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
1542
+ }
1543
+ const phoneRe = /(?<!\d)(?:\+?\d[\d\s().-]{7,}\d)(?!\d)/g;
1544
+ for (const m of text.matchAll(phoneRe)) {
1545
+ if (m.index == null) continue;
1546
+ const candidate = m[0];
1547
+ const digits = countDigits2(candidate);
1548
+ if (digits < 9 || digits > 15) continue;
1549
+ const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
1550
+ if (!isStrongInternational) {
1551
+ const hasContext = hasPhoneContext(text, m.index);
1552
+ if (!hasContext) continue;
1553
+ }
1554
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "PHONE", text: m[0] });
1555
+ }
1556
+ const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
1557
+ for (const m of text.matchAll(personRe)) {
1558
+ if (m.index == null) continue;
1559
+ const candidate = m[0];
1560
+ const contextWindow = buildContextWindow(text, m.index, candidate.length);
1561
+ if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
1562
+ continue;
1563
+ }
1564
+ detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
1565
+ }
1566
+ BIRTH_NUMBER_CONTEXT_RE.lastIndex = 0;
1567
+ for (const match of text.matchAll(BIRTH_NUMBER_CONTEXT_RE)) {
1568
+ if (match.index == null) continue;
1569
+ const value = match[1] ?? "";
1570
+ if (!/^\d{6}(?:\/?\d{3,4})?$/.test(value)) continue;
1571
+ const localIndex = match[0].lastIndexOf(value);
1572
+ const start = match.index + Math.max(0, localIndex);
1573
+ detections.push({
1574
+ start,
1575
+ end: start + value.length,
1576
+ type: "BIRTH_NUMBER",
1577
+ text: value
1578
+ });
1579
+ }
1580
+ const nationalIdMatches = detectNationalIdentifiers(text, {
1581
+ deadlineMs: defaultScanDeadlineMs,
1582
+ allowContextBirthNumberFallback: false
1153
1583
  });
1584
+ for (const match of nationalIdMatches) {
1585
+ if (match.start < 0 || match.end <= match.start) continue;
1586
+ detections.push({
1587
+ start: match.start,
1588
+ end: match.end,
1589
+ type: "NATIONAL_ID",
1590
+ text: text.slice(match.start, match.end)
1591
+ });
1592
+ }
1593
+ }
1594
+ if (resolvedOptions.secrets) {
1595
+ BASIC_AUTH_PASSWORD_RE.lastIndex = 0;
1596
+ for (const match of text.matchAll(BASIC_AUTH_PASSWORD_RE)) {
1597
+ if (match.index == null) continue;
1598
+ const password = match[1] ?? "";
1599
+ if (!password) continue;
1600
+ const localIndex = match[0].lastIndexOf(password);
1601
+ const start = match.index + Math.max(0, localIndex);
1602
+ detections.push({
1603
+ start,
1604
+ end: start + password.length,
1605
+ type: "BASIC_AUTH_PASSWORD",
1606
+ text: password
1607
+ });
1608
+ }
1609
+ DISCORD_WEBHOOK_TOKEN_RE.lastIndex = 0;
1610
+ for (const match of text.matchAll(DISCORD_WEBHOOK_TOKEN_RE)) {
1611
+ if (match.index == null) continue;
1612
+ const token = match[1] ?? "";
1613
+ if (!token) continue;
1614
+ const localIndex = match[0].lastIndexOf(token);
1615
+ const start = match.index + Math.max(0, localIndex);
1616
+ detections.push({
1617
+ start,
1618
+ end: start + token.length,
1619
+ type: "DISCORD_WEBHOOK_TOKEN",
1620
+ text: token
1621
+ });
1622
+ }
1623
+ for (const matcher of sdkSecretMatchers) {
1624
+ if (matcher.id === "discord_webhook_url") {
1625
+ continue;
1626
+ }
1627
+ if (matcher.prefilterTermsLower.length > 0 && !matcher.prefilterTermsLower.some((term) => loweredText.includes(term))) {
1628
+ continue;
1629
+ }
1630
+ matcher.scanRegex.lastIndex = 0;
1631
+ for (const match of text.matchAll(matcher.scanRegex)) {
1632
+ if (match.index == null) continue;
1633
+ detections.push({
1634
+ start: match.index,
1635
+ end: match.index + match[0].length,
1636
+ type: matcher.placeholderType,
1637
+ text: match[0]
1638
+ });
1639
+ }
1640
+ }
1154
1641
  }
1155
1642
  const kept = normalizeDetections(text, detections);
1156
1643
  if (!kept.length) return { maskedText: text, mapping: {} };
@@ -1195,7 +1682,9 @@ var DEFAULT_FAIL_OPEN_CONFIG = {
1195
1682
  block_on_heuristic: false,
1196
1683
  inject_transparency_metadata: false,
1197
1684
  block_pii_leakage: false,
1198
- enable_sdk_pii_masking: false,
1685
+ enable_sdk_pii_masking: true,
1686
+ block_secret_leakage: false,
1687
+ enable_sdk_secret_masking: true,
1199
1688
  block_db_access: false,
1200
1689
  block_code_execution: false,
1201
1690
  block_toxicity: false
@@ -1237,11 +1726,11 @@ function detectCapabilityViolation(text, config) {
1237
1726
  }
1238
1727
  return null;
1239
1728
  }
1240
- function redactPiiStrict(pii, text) {
1729
+ function redactPiiStrict(pii, text, options) {
1241
1730
  if (!text) {
1242
1731
  return { redactedText: text, changed: false };
1243
1732
  }
1244
- const masked = pii.anonymize(text);
1733
+ const masked = pii.anonymize(text, options);
1245
1734
  let redactedText = masked.maskedText;
1246
1735
  const placeholders = Object.keys(masked.mapping).sort((a, b) => b.length - a.length);
1247
1736
  for (const placeholder of placeholders) {
@@ -1270,7 +1759,7 @@ var LocalSecurityEnforcer = class {
1270
1759
  `AgentID: Security policy blocked (${violationType})`
1271
1760
  );
1272
1761
  }
1273
- if (!config.block_pii_leakage) {
1762
+ if (!config.block_pii_leakage && !config.block_secret_leakage) {
1274
1763
  return {
1275
1764
  sanitizedInput: input,
1276
1765
  events: []
@@ -1280,10 +1769,13 @@ var LocalSecurityEnforcer = class {
1280
1769
  throw new SecurityPolicyViolationError(
1281
1770
  "PII_LEAKAGE_STRICT",
1282
1771
  "BLOCKED",
1283
- "AgentID: Streaming is not supported when Strict PII Mode is enabled. Please disable streaming or adjust security settings."
1772
+ "AgentID: Streaming is not supported when strict masking/blocking mode is enabled. Please disable streaming or adjust security settings."
1284
1773
  );
1285
1774
  }
1286
- const strictRedaction = redactPiiStrict(this.pii, input);
1775
+ const strictRedaction = redactPiiStrict(this.pii, input, {
1776
+ pii: config.block_pii_leakage,
1777
+ secrets: config.block_secret_leakage
1778
+ });
1287
1779
  return {
1288
1780
  sanitizedInput: strictRedaction.redactedText,
1289
1781
  events: strictRedaction.changed ? [
@@ -1409,6 +1901,16 @@ function normalizeCapabilityConfig(payload) {
1409
1901
  "enable_sdk_pii_masking",
1410
1902
  false
1411
1903
  ),
1904
+ block_secret_leakage: readOptionalBooleanField(
1905
+ body,
1906
+ "block_secret_leakage",
1907
+ false
1908
+ ),
1909
+ enable_sdk_secret_masking: readOptionalBooleanField(
1910
+ body,
1911
+ "enable_sdk_secret_masking",
1912
+ false
1913
+ ),
1412
1914
  block_db_access: readBooleanField(body, "block_db_access", "block_db"),
1413
1915
  block_code_execution: readBooleanField(
1414
1916
  body,
@@ -2069,14 +2571,14 @@ async function reportSecurityEvent(options) {
2069
2571
  const inputValue = options.storePii ? snippet : snippetHash;
2070
2572
  const eventId = createEventId(options.eventId ?? options.clientEventId);
2071
2573
  const metadata = {
2574
+ ...options.telemetryMetadata ?? {},
2072
2575
  source: options.source,
2073
2576
  detector: options.detector,
2074
2577
  trigger_rule: options.triggerRule,
2075
2578
  language: options.language,
2076
2579
  ai_scan_status: options.aiStatus ?? null,
2077
2580
  reason: options.reason ?? null,
2078
- client_event_id: eventId,
2079
- ...options.telemetryMetadata ?? {}
2581
+ client_event_id: eventId
2080
2582
  };
2081
2583
  if (options.storePii) {
2082
2584
  metadata.snippet = snippet;
@@ -2248,9 +2750,18 @@ var INGEST_MAX_ATTEMPTS = 3;
2248
2750
  var INGEST_RETRY_DELAYS_MS = [250, 500];
2249
2751
  var GUARD_VERDICT_CACHE_TTL_MS = 0;
2250
2752
  var MAX_INGEST_TEXT_CHARS = 32e3;
2753
+ var OPENAI_TELEMETRY_FIELD = "agentid_telemetry";
2251
2754
  function normalizeBaseUrl3(baseUrl) {
2252
2755
  return baseUrl.replace(/\/+$/, "");
2253
2756
  }
2757
+ function firstNonEmptyString(...values) {
2758
+ for (const value of values) {
2759
+ if (typeof value === "string" && value.trim().length > 0) {
2760
+ return value.trim();
2761
+ }
2762
+ }
2763
+ return void 0;
2764
+ }
2254
2765
  function isAbortSignalLike(value) {
2255
2766
  if (!value || typeof value !== "object") return false;
2256
2767
  const candidate = value;
@@ -2412,6 +2923,424 @@ function createCorrelationId(seed) {
2412
2923
  }
2413
2924
  return createPseudoUuidV42();
2414
2925
  }
2926
+ function getObjectString(value, ...keys) {
2927
+ for (const key of keys) {
2928
+ const candidate = value?.[key];
2929
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
2930
+ return candidate.trim();
2931
+ }
2932
+ }
2933
+ return void 0;
2934
+ }
2935
+ function getObjectNumber(value, ...keys) {
2936
+ for (const key of keys) {
2937
+ const candidate = value?.[key];
2938
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
2939
+ return candidate;
2940
+ }
2941
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
2942
+ const parsed = Number(candidate);
2943
+ if (Number.isFinite(parsed)) {
2944
+ return parsed;
2945
+ }
2946
+ }
2947
+ }
2948
+ return void 0;
2949
+ }
2950
+ function normalizeTelemetryString(value) {
2951
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
2952
+ }
2953
+ function normalizeTelemetryCategory(value) {
2954
+ const normalized = normalizeTelemetryString(value);
2955
+ if (!normalized) return void 0;
2956
+ return normalized.toLowerCase().replace(/[\s-]+/g, "_");
2957
+ }
2958
+ function toSnakeToken(value) {
2959
+ return value.trim().replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_").toLowerCase();
2960
+ }
2961
+ function hasUsageSignals(value) {
2962
+ if (!value) return false;
2963
+ for (const entry of Object.values(value)) {
2964
+ if (typeof entry === "number" && Number.isFinite(entry) && entry > 0) {
2965
+ return true;
2966
+ }
2967
+ if (typeof entry === "string" && entry.trim().length > 0) {
2968
+ const parsed = Number(entry);
2969
+ if (Number.isFinite(parsed) && parsed > 0) {
2970
+ return true;
2971
+ }
2972
+ }
2973
+ }
2974
+ return false;
2975
+ }
2976
+ function truncatePromptPreflightPreview(value, maxChars = 280) {
2977
+ const normalized = value.trim();
2978
+ if (normalized.length <= maxChars) {
2979
+ return normalized;
2980
+ }
2981
+ return `${normalized.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
2982
+ }
2983
+ function formatPromptPreflightReason(reason) {
2984
+ const normalized = normalizeTelemetryString(reason);
2985
+ if (!normalized) {
2986
+ return void 0;
2987
+ }
2988
+ return normalized.replace(/[_-]+/g, " ");
2989
+ }
2990
+ function summarizePromptPreflightResult(params) {
2991
+ const reason = formatPromptPreflightReason(
2992
+ params.localFallbackApplied ? params.localFallbackReason ?? void 0 : params.verdict.reason
2993
+ ) ?? "policy evaluation";
2994
+ if (!params.verdict.allowed && !params.localFallbackApplied) {
2995
+ return `Blocked the prompt before model execution because ${reason}.`;
2996
+ }
2997
+ if (params.localFallbackApplied) {
2998
+ return `Guard preflight degraded, so the SDK applied local fallback checks before model execution (${reason}).`;
2999
+ }
3000
+ if (params.verdict.shadow_mode && params.verdict.shadow_blocked) {
3001
+ return "Evaluated the prompt in shadow mode before model execution; shadow policy would have blocked it.";
3002
+ }
3003
+ if (params.verdict.simulated_decision === "masked" || params.verdict.detected_pii) {
3004
+ return "Evaluated the prompt before model execution and masked sensitive content where needed.";
3005
+ }
3006
+ return "Evaluated the prompt and attachments against guardrails before model execution.";
3007
+ }
3008
+ function buildPromptPreflightTelemetry(params) {
3009
+ const baseTelemetry = createAgentIdTelemetryContext(params.telemetry);
3010
+ const baseStepName = firstNonEmptyString(
3011
+ baseTelemetry?.workflow_step_name,
3012
+ baseTelemetry?.workflowStepName
3013
+ );
3014
+ const stepName = baseStepName ? `${toSnakeToken(baseStepName)}_preflight` : "prompt_preflight";
3015
+ const summary = summarizePromptPreflightResult({
3016
+ verdict: params.verdict,
3017
+ localFallbackApplied: params.local_fallback_applied,
3018
+ localFallbackReason: params.local_fallback_reason
3019
+ });
3020
+ return mergeTelemetryContexts(baseTelemetry, {
3021
+ workflow_step_id: createAgentIdCorrelationId(),
3022
+ workflow_step_name: stepName,
3023
+ event_title: "Prompt Preflight Evaluated",
3024
+ event_category: "guard",
3025
+ event_subtype: "prompt_preflight_evaluated",
3026
+ event_status: !params.verdict.allowed && !params.local_fallback_applied ? "blocked" : "completed",
3027
+ step_summary: summary,
3028
+ input_preview: truncatePromptPreflightPreview(params.input),
3029
+ output_preview: summary,
3030
+ runtime_surface: params.runtime_surface ?? "openai_sdk_guard",
3031
+ guard_event_id: params.guard_event_id ?? void 0,
3032
+ guard_latency_ms: params.guard_latency_ms ?? void 0,
3033
+ preflight_for_client_event_id: params.preflight_for_client_event_id,
3034
+ preflight_logged_via_sdk: true,
3035
+ lifecycle_status: "preflight_only"
3036
+ });
3037
+ }
3038
+ function inferOperationCategory(telemetry, eventType) {
3039
+ const explicitCategory = normalizeTelemetryCategory(
3040
+ telemetry?.event_category ?? telemetry?.eventCategory
3041
+ );
3042
+ if (explicitCategory === "ai" || explicitCategory === "llm" || explicitCategory === "inference") {
3043
+ return "ai";
3044
+ }
3045
+ if (explicitCategory === "guard" || explicitCategory === "security") {
3046
+ return "guard";
3047
+ }
3048
+ if (explicitCategory === "tool") return "tool";
3049
+ if (explicitCategory === "delivery" || explicitCategory === "send") return "delivery";
3050
+ if (explicitCategory === "inbox" || explicitCategory === "reply") return "inbox";
3051
+ if (explicitCategory === "workflow" || explicitCategory === "agent") return "workflow";
3052
+ if (explicitCategory === "compliance" || explicitCategory === "transparency") {
3053
+ return "compliance";
3054
+ }
3055
+ if (explicitCategory === "operational" || explicitCategory === "ops") {
3056
+ return "operational";
3057
+ }
3058
+ const haystack = [
3059
+ eventType,
3060
+ telemetry?.event_subtype,
3061
+ telemetry?.eventSubtype,
3062
+ telemetry?.tool_name,
3063
+ telemetry?.toolName,
3064
+ telemetry?.tool_target_type,
3065
+ telemetry?.toolTargetType,
3066
+ telemetry?.workflow_name,
3067
+ telemetry?.workflowName,
3068
+ telemetry?.workflow_step_name,
3069
+ telemetry?.workflowStepName,
3070
+ getObjectString(telemetry, "operation_family", "domain")
3071
+ ].filter((entry) => typeof entry === "string" && entry.trim().length > 0).join(" ").replace(/[_./-]+/g, " ").toLowerCase();
3072
+ if (/\b(llm|ai|inference|completion|summary|classification|draft)\b/.test(haystack)) {
3073
+ return "ai";
3074
+ }
3075
+ if (/\b(guard|security|policy|pii|prompt[_ ]?injection|review)\b/.test(haystack)) {
3076
+ return "guard";
3077
+ }
3078
+ if (/\b(reply|inbox|inbound|received|bounce|opened|followup)\b/.test(haystack)) {
3079
+ return "inbox";
3080
+ }
3081
+ if (/\b(email|mail|send|delivery|delivered|slack|sms|webhook|notification)\b/.test(haystack)) {
3082
+ return "delivery";
3083
+ }
3084
+ if (/\b(workflow|step|run|agent)\b/.test(haystack)) {
3085
+ return "workflow";
3086
+ }
3087
+ if (/\b(compliance|transparency|audit|evidence)\b/.test(haystack)) {
3088
+ return "compliance";
3089
+ }
3090
+ 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(
3091
+ haystack
3092
+ )) {
3093
+ return "tool";
3094
+ }
3095
+ return "operational";
3096
+ }
3097
+ function inferOperationStatus(params) {
3098
+ const explicitStatus = normalizeTelemetryString(params.eventStatus)?.toLowerCase();
3099
+ if (explicitStatus === "started" || explicitStatus === "completed" || explicitStatus === "failed") {
3100
+ return explicitStatus;
3101
+ }
3102
+ if (explicitStatus === "blocked" || explicitStatus === "skipped") {
3103
+ return explicitStatus;
3104
+ }
3105
+ const normalizedEventType = normalizeTelemetryString(params.eventType)?.toLowerCase();
3106
+ if (normalizedEventType === "start") return "started";
3107
+ if (normalizedEventType === "error") return "failed";
3108
+ if (normalizedEventType === "security_block") return "blocked";
3109
+ if (normalizedEventType === "human_override") return "completed";
3110
+ if (normalizedEventType === "complete") return "completed";
3111
+ return params.severity === "error" ? "failed" : "completed";
3112
+ }
3113
+ function deriveOperationEventType(params) {
3114
+ const explicit = normalizeTelemetryString(params.explicitEventType);
3115
+ if (explicit) {
3116
+ return explicit;
3117
+ }
3118
+ if (params.status === "started") return "start";
3119
+ if (params.status === "failed") return "error";
3120
+ if (params.status === "blocked") {
3121
+ return params.category === "guard" ? "security_block" : "error";
3122
+ }
3123
+ return "complete";
3124
+ }
3125
+ function deriveSubtypeBase(telemetry) {
3126
+ const toolName = normalizeTelemetryString(telemetry?.tool_name ?? telemetry?.toolName);
3127
+ if (toolName) {
3128
+ const tokens = toSnakeToken(toolName).split("_").filter(Boolean);
3129
+ if (tokens.length > 1 && ["workflow", "agent", "operation", "ops", "hr", "finance", "compliance"].includes(tokens[0])) {
3130
+ return tokens.slice(1).join("_");
3131
+ }
3132
+ return tokens.join("_");
3133
+ }
3134
+ const workflowName = normalizeTelemetryString(
3135
+ telemetry?.workflow_step_name ?? telemetry?.workflowStepName ?? telemetry?.workflow_name ?? telemetry?.workflowName
3136
+ );
3137
+ if (workflowName) {
3138
+ return toSnakeToken(workflowName);
3139
+ }
3140
+ return void 0;
3141
+ }
3142
+ function deriveOperationSubtype(params) {
3143
+ const explicitSubtype = normalizeTelemetryString(params.explicitSubtype);
3144
+ if (explicitSubtype) {
3145
+ return toSnakeToken(explicitSubtype);
3146
+ }
3147
+ const base = deriveSubtypeBase(params.telemetry);
3148
+ const suffix = params.status === "started" ? "started" : params.status === "failed" ? "failed" : params.status === "blocked" ? "blocked" : params.status === "skipped" ? "skipped" : "completed";
3149
+ if (base) {
3150
+ return `${base}_${suffix}`;
3151
+ }
3152
+ if (params.eventType === "start") return `${params.category}_started`;
3153
+ if (params.eventType === "error") return `${params.category}_failed`;
3154
+ if (params.eventType === "security_block") return `${params.category}_blocked`;
3155
+ return `${params.category}_completed`;
3156
+ }
3157
+ function inferOperationSeverity(params) {
3158
+ if (params.explicitSeverity) {
3159
+ return params.explicitSeverity;
3160
+ }
3161
+ if (params.status === "failed" || params.status === "blocked") {
3162
+ return "error";
3163
+ }
3164
+ if (params.status === "skipped") {
3165
+ return "warning";
3166
+ }
3167
+ return "info";
3168
+ }
3169
+ function createAgentIdCorrelationId(seed) {
3170
+ return createCorrelationId(seed);
3171
+ }
3172
+ function createAgentIdTelemetryContext(value) {
3173
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
3174
+ return void 0;
3175
+ }
3176
+ const raw = { ...value };
3177
+ const normalized = {};
3178
+ const assignString = (key, ...aliases) => {
3179
+ const next = getObjectString(raw, key, ...aliases);
3180
+ if (next) {
3181
+ normalized[key] = next;
3182
+ }
3183
+ };
3184
+ const assignNumber = (key, ...aliases) => {
3185
+ const next = getObjectNumber(raw, key, ...aliases);
3186
+ if (typeof next === "number") {
3187
+ normalized[key] = next;
3188
+ }
3189
+ };
3190
+ assignString("workflow_id", "workflowId");
3191
+ assignString("workflow_run_id", "workflowRunId");
3192
+ assignString("workflow_step_id", "workflowStepId");
3193
+ assignString("workflow_name", "workflowName");
3194
+ assignString("workflow_step_name", "workflowStepName");
3195
+ assignNumber("workflow_step_index", "workflowStepIndex");
3196
+ assignString("parent_event_id", "parentEventId");
3197
+ assignString("tool_name", "toolName");
3198
+ assignString("tool_target", "toolTarget");
3199
+ assignString("tool_target_type", "toolTargetType");
3200
+ assignString("event_title", "eventTitle");
3201
+ assignString("event_status", "eventStatus");
3202
+ assignString("event_category", "eventCategory");
3203
+ assignString("event_subtype", "eventSubtype");
3204
+ const consumedKeys = /* @__PURE__ */ new Set([
3205
+ "workflow_id",
3206
+ "workflowId",
3207
+ "workflow_run_id",
3208
+ "workflowRunId",
3209
+ "workflow_step_id",
3210
+ "workflowStepId",
3211
+ "workflow_name",
3212
+ "workflowName",
3213
+ "workflow_step_name",
3214
+ "workflowStepName",
3215
+ "workflow_step_index",
3216
+ "workflowStepIndex",
3217
+ "parent_event_id",
3218
+ "parentEventId",
3219
+ "tool_name",
3220
+ "toolName",
3221
+ "tool_target",
3222
+ "toolTarget",
3223
+ "tool_target_type",
3224
+ "toolTargetType",
3225
+ "event_title",
3226
+ "eventTitle",
3227
+ "event_status",
3228
+ "eventStatus",
3229
+ "event_category",
3230
+ "eventCategory",
3231
+ "event_subtype",
3232
+ "eventSubtype"
3233
+ ]);
3234
+ for (const [key, entry] of Object.entries(raw)) {
3235
+ if (consumedKeys.has(key) || entry === void 0) {
3236
+ continue;
3237
+ }
3238
+ if (typeof entry === "string") {
3239
+ if (entry.trim().length > 0) {
3240
+ normalized[key] = entry.trim();
3241
+ }
3242
+ continue;
3243
+ }
3244
+ normalized[key] = entry;
3245
+ }
3246
+ if (typeof normalized.workflow_id !== "string" && typeof normalized.workflow_run_id === "string") {
3247
+ normalized.workflow_id = normalized.workflow_run_id;
3248
+ }
3249
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
3250
+ }
3251
+ function createAgentIdOperationLog(params) {
3252
+ const telemetry = createAgentIdTelemetryContext(params.telemetry);
3253
+ const category = inferOperationCategory(
3254
+ createAgentIdTelemetryContext({
3255
+ ...telemetry ?? {},
3256
+ event_category: params.event_category ?? telemetry?.event_category
3257
+ }),
3258
+ params.event_type
3259
+ );
3260
+ const status = inferOperationStatus({
3261
+ eventStatus: normalizeTelemetryString(params.event_status) ?? normalizeTelemetryString(telemetry?.event_status ?? telemetry?.eventStatus),
3262
+ eventType: params.event_type,
3263
+ severity: params.severity
3264
+ });
3265
+ const eventType = deriveOperationEventType({
3266
+ explicitEventType: params.event_type,
3267
+ status,
3268
+ category
3269
+ });
3270
+ const subtype = deriveOperationSubtype({
3271
+ explicitSubtype: normalizeTelemetryString(params.event_subtype) ?? normalizeTelemetryString(telemetry?.event_subtype ?? telemetry?.eventSubtype),
3272
+ telemetry,
3273
+ category,
3274
+ status,
3275
+ eventType
3276
+ });
3277
+ const severity = inferOperationSeverity({
3278
+ explicitSeverity: params.severity,
3279
+ status
3280
+ });
3281
+ const usage = params.usage;
3282
+ const clientEventId = normalizeTelemetryString(params.client_event_id) ?? normalizeTelemetryString(telemetry?.client_event_id);
3283
+ const modelUsed = category === "ai" || hasUsageSignals(usage) || typeof params.model === "string" && params.model.trim().length > 0 && params.model.trim().toLowerCase() !== "not_applicable";
3284
+ const metadata = {
3285
+ ...params.metadata ?? {},
3286
+ ...telemetry ?? {},
3287
+ event_category: category,
3288
+ event_subtype: subtype,
3289
+ event_status: status,
3290
+ status,
3291
+ model_used: modelUsed,
3292
+ spend_bearing: category === "ai" && hasUsageSignals(usage)
3293
+ };
3294
+ if (clientEventId && typeof metadata.client_event_id !== "string") {
3295
+ metadata.client_event_id = clientEventId;
3296
+ }
3297
+ return {
3298
+ event_id: normalizeTelemetryString(params.event_id) ?? createEventId2(),
3299
+ system_id: params.system_id,
3300
+ user_id: params.user_id,
3301
+ request_identity: params.request_identity,
3302
+ input: params.input ?? "",
3303
+ output: params.output ?? "",
3304
+ model: normalizeTelemetryString(params.model) ?? "not_applicable",
3305
+ usage,
3306
+ tokens: params.tokens,
3307
+ latency: params.latency,
3308
+ metadata,
3309
+ event_type: eventType,
3310
+ severity,
3311
+ timestamp: params.timestamp,
3312
+ client_capabilities: params.client_capabilities
3313
+ };
3314
+ }
3315
+ function asTelemetryContext(value) {
3316
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
3317
+ return void 0;
3318
+ }
3319
+ return createAgentIdTelemetryContext(value);
3320
+ }
3321
+ function mergeTelemetryContexts(...contexts) {
3322
+ const merged = {};
3323
+ let hasValues = false;
3324
+ for (const context of contexts) {
3325
+ if (!context) {
3326
+ continue;
3327
+ }
3328
+ Object.assign(merged, createAgentIdTelemetryContext(context));
3329
+ hasValues = true;
3330
+ }
3331
+ return hasValues ? createAgentIdTelemetryContext(merged) : void 0;
3332
+ }
3333
+ function extractRequestTelemetryContext(requestBody) {
3334
+ return asTelemetryContext(requestBody[OPENAI_TELEMETRY_FIELD]);
3335
+ }
3336
+ function stripRequestTelemetryContext(requestBody) {
3337
+ if (!Object.prototype.hasOwnProperty.call(requestBody, OPENAI_TELEMETRY_FIELD)) {
3338
+ return requestBody;
3339
+ }
3340
+ const nextRequestBody = { ...requestBody };
3341
+ delete nextRequestBody[OPENAI_TELEMETRY_FIELD];
3342
+ return nextRequestBody;
3343
+ }
2415
3344
  async function waitForRetry(attemptIndex) {
2416
3345
  const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
2417
3346
  if (!delay) return;
@@ -2591,6 +3520,61 @@ function createStreamingPlaceholderRewriter(piiManager, mapping) {
2591
3520
  }
2592
3521
  };
2593
3522
  }
3523
+ var TYPED_PLACEHOLDER_RE = /<[A-Z][A-Z0-9_]*_\d+>/g;
3524
+ function derivePlaceholderMappingFromTransform(source, transformed) {
3525
+ if (!source || !transformed || source === transformed) {
3526
+ return {};
3527
+ }
3528
+ const placeholders = [...transformed.matchAll(TYPED_PLACEHOLDER_RE)].map((match) => ({
3529
+ token: match[0],
3530
+ start: match.index ?? 0,
3531
+ end: (match.index ?? 0) + match[0].length
3532
+ }));
3533
+ if (placeholders.length === 0) {
3534
+ return {};
3535
+ }
3536
+ const mapping = {};
3537
+ let sourceCursor = 0;
3538
+ let transformedCursor = 0;
3539
+ for (const placeholder of placeholders) {
3540
+ const literalBefore = transformed.slice(transformedCursor, placeholder.start);
3541
+ if (literalBefore) {
3542
+ const literalIndex = source.indexOf(literalBefore, sourceCursor);
3543
+ if (literalIndex < 0) {
3544
+ return {};
3545
+ }
3546
+ sourceCursor = literalIndex + literalBefore.length;
3547
+ }
3548
+ const nextPlaceholderStart = placeholders.find((candidate) => candidate.start > placeholder.start)?.start ?? transformed.length;
3549
+ const literalAfter = transformed.slice(placeholder.end, nextPlaceholderStart);
3550
+ const nextLiteralIndex = literalAfter ? source.indexOf(literalAfter, sourceCursor) : nextPlaceholderStart >= transformed.length ? source.length : sourceCursor;
3551
+ if (nextLiteralIndex < sourceCursor) {
3552
+ return {};
3553
+ }
3554
+ const originalValue = source.slice(sourceCursor, nextLiteralIndex);
3555
+ if (originalValue.length > 0 && typeof mapping[placeholder.token] !== "string") {
3556
+ mapping[placeholder.token] = originalValue;
3557
+ }
3558
+ sourceCursor = nextLiteralIndex;
3559
+ transformedCursor = placeholder.end;
3560
+ }
3561
+ return mapping;
3562
+ }
3563
+ function mergePiiMappings(primary, fallback) {
3564
+ const merged = { ...primary };
3565
+ for (const [placeholder, value] of Object.entries(fallback)) {
3566
+ if (typeof merged[placeholder] !== "string" && typeof value === "string") {
3567
+ merged[placeholder] = value;
3568
+ }
3569
+ }
3570
+ return merged;
3571
+ }
3572
+ function textContainsMappingPlaceholder(text, mapping) {
3573
+ if (!text || !mapping) {
3574
+ return false;
3575
+ }
3576
+ return Object.keys(mapping).some((placeholder) => placeholder.length > 0 && text.includes(placeholder));
3577
+ }
2594
3578
  var SecurityBlockError = class extends Error {
2595
3579
  constructor(reason = "guard_denied") {
2596
3580
  super(`AgentID: Security Blocked (${reason})`);
@@ -2615,6 +3599,7 @@ var AgentID = class {
2615
3599
  this.apiKey = resolveConfiguredApiKey(config.apiKey);
2616
3600
  this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
2617
3601
  this.configuredPiiMasking = typeof config.piiMasking === "boolean" ? config.piiMasking : null;
3602
+ this.configuredSecretMasking = typeof config.secretMasking === "boolean" ? config.secretMasking : null;
2618
3603
  this.checkInjection = config.checkInjection !== false;
2619
3604
  this.clientFastFail = config.clientFastFail === true || config.client_fast_fail === true;
2620
3605
  this.aiScanEnabled = config.aiScanEnabled !== false;
@@ -2636,6 +3621,9 @@ var AgentID = class {
2636
3621
  get piiMasking() {
2637
3622
  return this.configuredPiiMasking ?? void 0;
2638
3623
  }
3624
+ get secretMasking() {
3625
+ return this.configuredSecretMasking ?? void 0;
3626
+ }
2639
3627
  resolveEffectivePiiMasking(config) {
2640
3628
  if (config?.enable_sdk_pii_masking === true) {
2641
3629
  return true;
@@ -2645,12 +3633,24 @@ var AgentID = class {
2645
3633
  }
2646
3634
  return false;
2647
3635
  }
3636
+ resolveEffectiveSecretMasking(config) {
3637
+ if (config?.enable_sdk_secret_masking === true || config?.enable_sdk_pii_masking === true) {
3638
+ return true;
3639
+ }
3640
+ if (this.configuredSecretMasking !== null) {
3641
+ return this.configuredSecretMasking;
3642
+ }
3643
+ return false;
3644
+ }
2648
3645
  getEffectivePiiMasking(options) {
2649
3646
  return this.resolveEffectivePiiMasking(this.getCachedCapabilityConfig(options));
2650
3647
  }
2651
3648
  getEffectivePiiMaskingForConfig(capabilityConfig) {
2652
3649
  return this.resolveEffectivePiiMasking(capabilityConfig);
2653
3650
  }
3651
+ getEffectiveSecretMaskingForConfig(capabilityConfig) {
3652
+ return this.resolveEffectiveSecretMasking(capabilityConfig);
3653
+ }
2654
3654
  buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig) {
2655
3655
  return {
2656
3656
  capabilities: {
@@ -2658,6 +3658,9 @@ var AgentID = class {
2658
3658
  pii_masking_enabled: this.resolveEffectivePiiMasking(
2659
3659
  capabilityConfig ?? this.getCachedCapabilityConfig()
2660
3660
  ),
3661
+ secret_masking_enabled: this.resolveEffectiveSecretMasking(
3662
+ capabilityConfig ?? this.getCachedCapabilityConfig()
3663
+ ),
2661
3664
  framework
2662
3665
  }
2663
3666
  };
@@ -2750,6 +3753,23 @@ var AgentID = class {
2750
3753
  const config = await this.getCapabilityConfig(false, options);
2751
3754
  return config.strict_security_mode || config.failure_mode === "fail_close";
2752
3755
  }
3756
+ buildFailOpenGuardVerdict(reason, input, options) {
3757
+ const capabilityConfig = this.getCachedCapabilityConfig(options);
3758
+ const shouldMaskPii = capabilityConfig.block_pii_leakage || this.resolveEffectivePiiMasking(capabilityConfig);
3759
+ const shouldMaskSecrets = capabilityConfig.block_secret_leakage === true || this.resolveEffectiveSecretMasking(capabilityConfig);
3760
+ const response = { allowed: true, reason };
3761
+ if (input && (shouldMaskPii || shouldMaskSecrets)) {
3762
+ const masked = this.pii.anonymize(input, {
3763
+ pii: shouldMaskPii,
3764
+ secrets: shouldMaskSecrets
3765
+ });
3766
+ if (masked.maskedText !== input) {
3767
+ response.transformed_input = masked.maskedText;
3768
+ response.detected_pii = Object.keys(masked.mapping).length > 0;
3769
+ }
3770
+ }
3771
+ return response;
3772
+ }
2753
3773
  maybeRaiseStrictIngestDependencyError(params) {
2754
3774
  if (params.result.ok) {
2755
3775
  return;
@@ -2797,10 +3817,13 @@ var AgentID = class {
2797
3817
  systemId: params.systemId,
2798
3818
  eventId: params.clientEventId,
2799
3819
  clientEventId: params.clientEventId,
2800
- telemetryMetadata: buildSdkTimingMetadata({
2801
- sdkConfigFetchMs: params.sdkConfigFetchMs,
2802
- sdkConfigVersion: params.capabilityConfig.version
2803
- })
3820
+ telemetryMetadata: mergeTelemetryContexts(
3821
+ params.telemetryMetadata,
3822
+ buildSdkTimingMetadata({
3823
+ sdkConfigFetchMs: params.sdkConfigFetchMs,
3824
+ sdkConfigVersion: params.capabilityConfig.version
3825
+ })
3826
+ )
2804
3827
  });
2805
3828
  }
2806
3829
  try {
@@ -2817,7 +3840,8 @@ var AgentID = class {
2817
3840
  actionTaken: event.actionTaken,
2818
3841
  apiKey: params.apiKey,
2819
3842
  sdkConfigFetchMs: params.sdkConfigFetchMs,
2820
- sdkLocalScanMs
3843
+ sdkLocalScanMs,
3844
+ telemetryMetadata: params.telemetryMetadata
2821
3845
  });
2822
3846
  }
2823
3847
  return {
@@ -2832,7 +3856,8 @@ var AgentID = class {
2832
3856
  actionTaken: error.actionTaken,
2833
3857
  apiKey: params.apiKey,
2834
3858
  sdkConfigFetchMs: params.sdkConfigFetchMs,
2835
- sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
3859
+ sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt),
3860
+ telemetryMetadata: params.telemetryMetadata
2836
3861
  });
2837
3862
  }
2838
3863
  throw error;
@@ -2846,7 +3871,7 @@ var AgentID = class {
2846
3871
  );
2847
3872
  let sanitizedInput = params.input;
2848
3873
  let sdkLocalScanMs = 0;
2849
- if (this.configuredPiiMasking === null) {
3874
+ if (this.configuredPiiMasking === null || this.configuredSecretMasking === null) {
2850
3875
  const refreshed = await this.refreshCapabilityConfigBeforeClientControl({
2851
3876
  capabilityConfig,
2852
3877
  sdkConfigFetchMs,
@@ -2857,8 +3882,12 @@ var AgentID = class {
2857
3882
  }
2858
3883
  if (!this.clientFastFail) {
2859
3884
  const effectivePiiMasking2 = this.resolveEffectivePiiMasking(capabilityConfig);
2860
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2) {
2861
- const masked = this.pii.anonymize(sanitizedInput);
3885
+ const effectiveSecretMasking2 = this.resolveEffectiveSecretMasking(capabilityConfig);
3886
+ if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2 || !capabilityConfig.block_secret_leakage && effectiveSecretMasking2) {
3887
+ const masked = this.pii.anonymize(sanitizedInput, {
3888
+ pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking2,
3889
+ secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking2
3890
+ });
2862
3891
  return {
2863
3892
  sanitizedInput: masked.maskedText,
2864
3893
  capabilityConfig,
@@ -2890,13 +3919,18 @@ var AgentID = class {
2890
3919
  apiKey: effectiveApiKey,
2891
3920
  clientEventId: params.clientEventId,
2892
3921
  sdkConfigFetchMs,
3922
+ telemetryMetadata: params.telemetryMetadata,
2893
3923
  runPromptInjectionCheck: !params.skipInjectionScan
2894
3924
  });
2895
3925
  sanitizedInput = enforced.sanitizedInput;
2896
3926
  sdkLocalScanMs = enforced.sdkLocalScanMs;
2897
3927
  const effectivePiiMasking = this.resolveEffectivePiiMasking(capabilityConfig);
2898
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking) {
2899
- const masked = this.pii.anonymize(sanitizedInput);
3928
+ const effectiveSecretMasking = this.resolveEffectiveSecretMasking(capabilityConfig);
3929
+ if (!capabilityConfig.block_pii_leakage && effectivePiiMasking || !capabilityConfig.block_secret_leakage && effectiveSecretMasking) {
3930
+ const masked = this.pii.anonymize(sanitizedInput, {
3931
+ pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking,
3932
+ secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking
3933
+ });
2900
3934
  return {
2901
3935
  sanitizedInput: masked.maskedText,
2902
3936
  capabilityConfig,
@@ -2932,6 +3966,7 @@ var AgentID = class {
2932
3966
  apiKey: effectiveApiKey,
2933
3967
  clientEventId: params.clientEventId,
2934
3968
  sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
3969
+ telemetryMetadata: params.telemetryMetadata,
2935
3970
  runPromptInjectionCheck: true
2936
3971
  });
2937
3972
  return {
@@ -2975,12 +4010,43 @@ var AgentID = class {
2975
4010
  })
2976
4011
  });
2977
4012
  }
2978
- withMaskedOpenAIRequest(req, maskedText) {
4013
+ withMaskedOpenAIRequest(req, maskedText, options) {
2979
4014
  const messages = Array.isArray(req?.messages) ? req.messages : null;
2980
4015
  if (!messages) {
2981
4016
  return req;
2982
4017
  }
2983
- const newMessages = [...messages];
4018
+ const newMessages = messages.map((message2) => {
4019
+ if (!message2 || typeof message2 !== "object") {
4020
+ return message2;
4021
+ }
4022
+ const typedMessage = message2;
4023
+ const currentContent2 = typedMessage.content;
4024
+ if (typeof currentContent2 === "string") {
4025
+ return {
4026
+ ...typedMessage,
4027
+ content: this.pii.anonymize(currentContent2, options).maskedText
4028
+ };
4029
+ }
4030
+ if (Array.isArray(currentContent2)) {
4031
+ return {
4032
+ ...typedMessage,
4033
+ content: currentContent2.map((part) => {
4034
+ if (!part || typeof part !== "object") {
4035
+ return part;
4036
+ }
4037
+ const typedPart = part;
4038
+ if (typeof typedPart.text !== "string") {
4039
+ return part;
4040
+ }
4041
+ return {
4042
+ ...typedPart,
4043
+ text: this.pii.anonymize(typedPart.text, options).maskedText
4044
+ };
4045
+ })
4046
+ };
4047
+ }
4048
+ return message2;
4049
+ });
2984
4050
  let lastUserIdx = null;
2985
4051
  for (let i = 0; i < newMessages.length; i += 1) {
2986
4052
  const msg = newMessages[i];
@@ -2995,9 +4061,30 @@ var AgentID = class {
2995
4061
  if (!message || typeof message !== "object") {
2996
4062
  return req;
2997
4063
  }
4064
+ const currentContent = message.content;
4065
+ let nextContent = maskedText;
4066
+ if (Array.isArray(currentContent)) {
4067
+ let textReplaced = false;
4068
+ const preservedParts = [];
4069
+ for (const part of currentContent) {
4070
+ if (!part || typeof part !== "object" || part.type !== "text" || typeof part.text !== "string") {
4071
+ preservedParts.push(part);
4072
+ continue;
4073
+ }
4074
+ if (textReplaced) {
4075
+ continue;
4076
+ }
4077
+ textReplaced = true;
4078
+ preservedParts.push({
4079
+ ...part,
4080
+ text: maskedText
4081
+ });
4082
+ }
4083
+ nextContent = textReplaced ? preservedParts : [{ type: "text", text: maskedText }, ...currentContent];
4084
+ }
2998
4085
  newMessages[lastUserIdx] = {
2999
4086
  ...message,
3000
- content: maskedText
4087
+ content: nextContent
3001
4088
  };
3002
4089
  if (!req || typeof req !== "object") {
3003
4090
  return req;
@@ -3016,6 +4103,7 @@ var AgentID = class {
3016
4103
  event_type: "security_policy_violation",
3017
4104
  severity: "high",
3018
4105
  metadata: {
4106
+ ...params.telemetryMetadata ?? {},
3019
4107
  event_type: "security_policy_violation",
3020
4108
  severity: "high",
3021
4109
  system_id: params.systemId,
@@ -3043,6 +4131,7 @@ var AgentID = class {
3043
4131
  event_type: "security_alert",
3044
4132
  severity: "warning",
3045
4133
  metadata: {
4134
+ ...params.guardParams.metadata ?? {},
3046
4135
  source: "guard",
3047
4136
  status: params.status,
3048
4137
  guard_reason: params.reason,
@@ -3171,7 +4260,13 @@ var AgentID = class {
3171
4260
  guardParams: params,
3172
4261
  apiKey: effectiveApiKey
3173
4262
  });
3174
- return withGuardLatency({ allowed: true, reason: "system_failure_fail_open" });
4263
+ return withGuardLatency(
4264
+ this.buildFailOpenGuardVerdict(
4265
+ "system_failure_fail_open",
4266
+ params.input,
4267
+ { apiKey: effectiveApiKey }
4268
+ )
4269
+ );
3175
4270
  }
3176
4271
  this.cacheGuardVerdict(guardCacheKey, verdict);
3177
4272
  return withGuardLatency(verdict);
@@ -3206,7 +4301,11 @@ var AgentID = class {
3206
4301
  if (effectiveStrictMode) {
3207
4302
  return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
3208
4303
  }
3209
- return withGuardLatency({ allowed: true, reason: "timeout_fallback" });
4304
+ return withGuardLatency(
4305
+ this.buildFailOpenGuardVerdict("timeout_fallback", params.input, {
4306
+ apiKey: effectiveApiKey
4307
+ })
4308
+ );
3210
4309
  }
3211
4310
  console.warn(
3212
4311
  effectiveStrictMode ? "[AgentID] Guard check failed (Strict mode active):" : "[AgentID] Guard check failed (Fail-Open active):",
@@ -3221,7 +4320,11 @@ var AgentID = class {
3221
4320
  if (effectiveStrictMode) {
3222
4321
  return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
3223
4322
  }
3224
- return withGuardLatency({ allowed: true, reason: "guard_unreachable" });
4323
+ return withGuardLatency(
4324
+ this.buildFailOpenGuardVerdict("guard_unreachable", params.input, {
4325
+ apiKey: effectiveApiKey
4326
+ })
4327
+ );
3225
4328
  } finally {
3226
4329
  clearTimeout(timeoutId);
3227
4330
  }
@@ -3230,13 +4333,23 @@ var AgentID = class {
3230
4333
  if (effectiveStrictMode) {
3231
4334
  return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
3232
4335
  }
3233
- return withGuardLatency({ allowed: true, reason: "timeout_fallback" });
4336
+ return withGuardLatency(
4337
+ this.buildFailOpenGuardVerdict("timeout_fallback", params.input, {
4338
+ apiKey: effectiveApiKey
4339
+ })
4340
+ );
3234
4341
  }
3235
4342
  if (typeof lastStatusCode === "number" && lastStatusCode >= 500) {
3236
4343
  if (effectiveStrictMode) {
3237
4344
  return withGuardLatency({ allowed: false, reason: "server_error" });
3238
4345
  }
3239
- return withGuardLatency({ allowed: true, reason: "system_failure_fail_open" });
4346
+ return withGuardLatency(
4347
+ this.buildFailOpenGuardVerdict(
4348
+ "system_failure_fail_open",
4349
+ params.input,
4350
+ { apiKey: effectiveApiKey }
4351
+ )
4352
+ );
3240
4353
  }
3241
4354
  console.warn(
3242
4355
  effectiveStrictMode ? "[AgentID] Guard check failed (Strict mode active):" : "[AgentID] Guard check failed (Fail-Open active):",
@@ -3245,7 +4358,11 @@ var AgentID = class {
3245
4358
  if (effectiveStrictMode) {
3246
4359
  return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
3247
4360
  }
3248
- return withGuardLatency({ allowed: true, reason: "guard_unreachable" });
4361
+ return withGuardLatency(
4362
+ this.buildFailOpenGuardVerdict("guard_unreachable", params.input, {
4363
+ apiKey: effectiveApiKey
4364
+ })
4365
+ );
3249
4366
  }
3250
4367
  async sendIngest(params, options, internal) {
3251
4368
  const ingestStartedAt = Date.now();
@@ -3485,21 +4602,29 @@ var AgentID = class {
3485
4602
  wrapCompletion(completion, options) {
3486
4603
  if (typeof completion === "string") {
3487
4604
  const masked = this.pii.anonymize(completion);
4605
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4606
+ completion,
4607
+ options?.piiMapping
4608
+ );
3488
4609
  return {
3489
4610
  mode: "static",
3490
4611
  rawOutput: completion,
3491
4612
  transformedOutput: masked.maskedText,
3492
- outputMasked: masked.maskedText !== completion
4613
+ outputMasked: masked.maskedText !== completion || placeholderOutputMasked
3493
4614
  };
3494
4615
  }
3495
4616
  if (!isAsyncIterable(completion)) {
3496
4617
  const asText = String(completion ?? "");
3497
4618
  const masked = this.pii.anonymize(asText);
4619
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4620
+ asText,
4621
+ options?.piiMapping
4622
+ );
3498
4623
  return {
3499
4624
  mode: "static",
3500
4625
  rawOutput: asText,
3501
4626
  transformedOutput: masked.maskedText,
3502
- outputMasked: masked.maskedText !== asText
4627
+ outputMasked: masked.maskedText !== asText || placeholderOutputMasked
3503
4628
  };
3504
4629
  }
3505
4630
  const source = completion;
@@ -3509,8 +4634,10 @@ var AgentID = class {
3509
4634
  const isOpenAIStreamFinishChunk = this.isOpenAIStreamFinishChunk.bind(this);
3510
4635
  const rewriteOpenAIStreamChunkForClient = this.rewriteOpenAIStreamChunkForClient.bind(this);
3511
4636
  const createSyntheticOpenAIStreamChunk = this.createSyntheticOpenAIStreamChunk.bind(this);
4637
+ const setOpenAIStreamChunkText = this.setOpenAIStreamChunkText.bind(this);
3512
4638
  const piiManager = this.pii;
3513
4639
  const streamRewriter = options?.deanonymizeForClient === true && options.piiMapping ? createStreamingPlaceholderRewriter(piiManager, options.piiMapping) : null;
4640
+ const maskForClient = options?.maskForClient === true && streamRewriter === null;
3514
4641
  let lastUsage;
3515
4642
  let resolveDone = null;
3516
4643
  let rejectDone = null;
@@ -3523,12 +4650,17 @@ var AgentID = class {
3523
4650
  try {
3524
4651
  let finishChunkFlushed = false;
3525
4652
  let lastChunkTemplate;
4653
+ let clientRawText = "";
4654
+ let clientMaskFlushed = false;
3526
4655
  for await (const chunk of source) {
3527
4656
  const chunkText = extractStreamChunkText(chunk);
3528
- const isFinishChunk = streamRewriter ? isOpenAIStreamFinishChunk(chunk) : false;
4657
+ const isFinishChunk = streamRewriter || maskForClient ? isOpenAIStreamFinishChunk(chunk) : false;
3529
4658
  if (chunkText) {
3530
4659
  await collector.push(chunkText);
3531
4660
  lastChunkTemplate = chunk;
4661
+ if (maskForClient) {
4662
+ clientRawText += chunkText;
4663
+ }
3532
4664
  }
3533
4665
  const chunkUsage = extractStreamChunkUsage(chunk);
3534
4666
  if (chunkUsage) {
@@ -3548,6 +4680,28 @@ var AgentID = class {
3548
4680
  }
3549
4681
  continue;
3550
4682
  }
4683
+ if (maskForClient) {
4684
+ if (isFinishChunk) {
4685
+ const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
4686
+ clientMaskFlushed = true;
4687
+ if (maskedClientText.length > 0) {
4688
+ yield createSyntheticOpenAIStreamChunk(
4689
+ maskedClientText,
4690
+ lastChunkTemplate ?? chunk
4691
+ );
4692
+ }
4693
+ if (chunkText) {
4694
+ setOpenAIStreamChunkText(chunk, "");
4695
+ }
4696
+ yield chunk;
4697
+ finishChunkFlushed = true;
4698
+ continue;
4699
+ }
4700
+ if (!chunkText) {
4701
+ yield chunk;
4702
+ }
4703
+ continue;
4704
+ }
3551
4705
  yield chunk;
3552
4706
  }
3553
4707
  if (streamRewriter && !finishChunkFlushed) {
@@ -3559,14 +4713,27 @@ var AgentID = class {
3559
4713
  );
3560
4714
  }
3561
4715
  }
4716
+ if (maskForClient && !clientMaskFlushed) {
4717
+ const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
4718
+ if (maskedClientText.length > 0) {
4719
+ yield createSyntheticOpenAIStreamChunk(
4720
+ maskedClientText,
4721
+ lastChunkTemplate
4722
+ );
4723
+ }
4724
+ }
3562
4725
  await collector.close();
3563
4726
  const rawOutput = await collector.result;
3564
4727
  const masked = piiManager.anonymize(rawOutput);
4728
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4729
+ rawOutput,
4730
+ options?.piiMapping
4731
+ );
3565
4732
  resolveDone?.({
3566
4733
  mode: "static",
3567
4734
  rawOutput,
3568
4735
  transformedOutput: masked.maskedText,
3569
- outputMasked: masked.maskedText !== rawOutput,
4736
+ outputMasked: masked.maskedText !== rawOutput || placeholderOutputMasked,
3570
4737
  usage: lastUsage
3571
4738
  });
3572
4739
  } catch (error) {
@@ -3601,6 +4768,37 @@ var AgentID = class {
3601
4768
  );
3602
4769
  }
3603
4770
  }
4771
+ buildOperationLogParams(params) {
4772
+ return createAgentIdOperationLog(params);
4773
+ }
4774
+ async logOperation(params, options) {
4775
+ return this.log(this.buildOperationLogParams(params), options);
4776
+ }
4777
+ async logPromptPreflightStep(params, options) {
4778
+ const telemetry = buildPromptPreflightTelemetry(params);
4779
+ const summary = firstNonEmptyString(telemetry?.step_summary, telemetry?.stepSummary) ?? summarizePromptPreflightResult({
4780
+ verdict: params.verdict,
4781
+ localFallbackApplied: params.local_fallback_applied,
4782
+ localFallbackReason: params.local_fallback_reason
4783
+ });
4784
+ await this.logOperation(
4785
+ {
4786
+ system_id: params.system_id,
4787
+ user_id: params.user_id,
4788
+ request_identity: params.request_identity,
4789
+ input: params.input,
4790
+ output: summary,
4791
+ model: "not_applicable",
4792
+ latency: params.guard_latency_ms ?? void 0,
4793
+ telemetry,
4794
+ client_capabilities: params.client_capabilities
4795
+ },
4796
+ options
4797
+ );
4798
+ }
4799
+ operation(params, options) {
4800
+ return this.logOperation(params, options);
4801
+ }
3604
4802
  /**
3605
4803
  * Analytics alias for telemetry logging.
3606
4804
  */
@@ -3645,49 +4843,62 @@ var AgentID = class {
3645
4843
  if (typeof originalCreate !== "function") return originalCreate;
3646
4844
  return async (...args) => {
3647
4845
  const normalizedCreateArgs = normalizeOpenAICreateArgs(args);
3648
- const req = normalizedCreateArgs?.[0] ?? {};
4846
+ const rawReq = normalizedCreateArgs?.[0] ?? {};
4847
+ const requestTelemetry = extractRequestTelemetryContext(rawReq);
4848
+ const telemetryMetadata = mergeTelemetryContexts(
4849
+ options.telemetry,
4850
+ requestTelemetry
4851
+ );
4852
+ const providerReq = stripRequestTelemetryContext(rawReq);
3649
4853
  const pipelineStartedAt = Date.now();
3650
- const requestLevelApiKey = options.resolveApiKey?.(req) ?? options.apiKey ?? options.api_key;
4854
+ const requestLevelApiKey = options.resolveApiKey?.(rawReq) ?? options.apiKey ?? options.api_key;
3651
4855
  const effectiveApiKey = this.resolveApiKey(requestLevelApiKey);
3652
4856
  const requestOptions = { apiKey: effectiveApiKey };
3653
- const clientEventId = this.resolveClientEventId(req);
4857
+ const clientEventId = this.resolveClientEventId(rawReq);
3654
4858
  const effectiveStrictMode = await this.resolveEffectiveStrictMode(requestOptions);
3655
- const stream = adapter.isStream(req);
4859
+ const stream = adapter.isStream(providerReq);
3656
4860
  let capabilityConfig = this.getCachedCapabilityConfig(requestOptions);
3657
- const userText = adapter.extractInput(req);
3658
- let maskedText = userText;
3659
- let maskedReq = req;
3660
- let createArgs = normalizedCreateArgs;
4861
+ const userText = adapter.extractInput(providerReq);
4862
+ const requestAttachments = adapter.extractAttachments(providerReq);
4863
+ const hasGuardContent = userText !== null || requestAttachments.length > 0;
4864
+ let maskedText = userText ?? "";
4865
+ let maskedReq = providerReq;
4866
+ let createArgs = providerReq === rawReq ? normalizedCreateArgs : [{ ...providerReq }, ...normalizedCreateArgs.slice(1)];
3661
4867
  let mapping = {};
3662
- let shouldDeanonymize = false;
3663
4868
  let sdkConfigFetchMs = 0;
3664
4869
  let sdkLocalScanMs = 0;
3665
- if (userText) {
4870
+ let providerMaskingOptions;
4871
+ if (hasGuardContent) {
3666
4872
  const prepared = await this.prepareInputForDispatch({
3667
- input: userText,
4873
+ input: userText ?? "",
3668
4874
  systemId,
3669
4875
  stream,
3670
- clientEventId
4876
+ clientEventId,
4877
+ telemetryMetadata
3671
4878
  }, requestOptions);
3672
4879
  capabilityConfig = prepared.capabilityConfig;
4880
+ providerMaskingOptions = {
4881
+ pii: !capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig),
4882
+ secrets: !capabilityConfig.block_secret_leakage && this.resolveEffectiveSecretMasking(capabilityConfig)
4883
+ };
3673
4884
  maskedText = prepared.sanitizedInput;
3674
4885
  mapping = prepared.piiMapping ?? {};
3675
- shouldDeanonymize = prepared.shouldDeanonymize === true;
3676
4886
  sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
3677
4887
  sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
3678
- if (maskedText !== userText) {
4888
+ if (maskedText !== (userText ?? "")) {
3679
4889
  maskedReq = this.withMaskedOpenAIRequest(
3680
- req,
3681
- maskedText
4890
+ providerReq,
4891
+ maskedText,
4892
+ providerMaskingOptions
3682
4893
  );
3683
- const nextCreateArgs = [...normalizedCreateArgs];
4894
+ const nextCreateArgs = [...createArgs];
3684
4895
  nextCreateArgs[0] = maskedReq;
3685
4896
  createArgs = nextCreateArgs;
3686
4897
  }
3687
4898
  }
3688
- if (!maskedText) {
4899
+ if (!hasGuardContent) {
3689
4900
  throw new Error(
3690
- "AgentID: No user message found. Security guard requires string input."
4901
+ "AgentID: No user message or supported inline attachment found. Security guard requires prompt content."
3691
4902
  );
3692
4903
  }
3693
4904
  const verdict = await this.guard({
@@ -3698,6 +4909,8 @@ var AgentID = class {
3698
4909
  client_event_id: clientEventId,
3699
4910
  expected_languages: expectedLanguages,
3700
4911
  request_identity: options.request_identity,
4912
+ metadata: telemetryMetadata,
4913
+ attachments: requestAttachments,
3701
4914
  client_capabilities: this.buildClientCapabilities(
3702
4915
  "openai",
3703
4916
  false,
@@ -3719,22 +4932,44 @@ var AgentID = class {
3719
4932
  apiKey: effectiveApiKey,
3720
4933
  clientEventId,
3721
4934
  sdkConfigFetchMs,
4935
+ telemetryMetadata,
3722
4936
  runPromptInjectionCheck: true
3723
4937
  });
3724
4938
  maskedText = fallback.sanitizedInput;
3725
4939
  sdkLocalScanMs = fallback.sdkLocalScanMs;
3726
4940
  }
3727
4941
  } else {
4942
+ await this.logPromptPreflightStep(
4943
+ {
4944
+ system_id: systemId,
4945
+ user_id: options.user_id,
4946
+ request_identity: options.request_identity,
4947
+ input: maskedText,
4948
+ telemetry: telemetryMetadata,
4949
+ verdict,
4950
+ guard_event_id: verdict.guard_event_id ?? null,
4951
+ 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),
4952
+ preflight_for_client_event_id: typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId,
4953
+ client_capabilities: this.buildClientCapabilities(
4954
+ "openai",
4955
+ false,
4956
+ capabilityConfig
4957
+ ),
4958
+ runtime_surface: "openai_sdk_guard"
4959
+ },
4960
+ requestOptions
4961
+ );
3728
4962
  throw new SecurityBlockError(verdict.reason ?? "guard_denied");
3729
4963
  }
3730
4964
  }
3731
- const currentRequestInput = adapter.extractInput(maskedReq);
3732
- if (maskedText !== currentRequestInput) {
4965
+ const currentRequestInput = adapter.extractInput(maskedReq) ?? "";
4966
+ if (maskedText !== currentRequestInput || providerMaskingOptions?.pii === true || providerMaskingOptions?.secrets === true) {
3733
4967
  maskedReq = this.withMaskedOpenAIRequest(
3734
- req,
3735
- maskedText
4968
+ providerReq,
4969
+ maskedText,
4970
+ providerMaskingOptions
3736
4971
  );
3737
- const nextCreateArgs = [...normalizedCreateArgs];
4972
+ const nextCreateArgs = [...createArgs];
3738
4973
  nextCreateArgs[0] = maskedReq;
3739
4974
  createArgs = nextCreateArgs;
3740
4975
  }
@@ -3745,15 +4980,45 @@ var AgentID = class {
3745
4980
  const isShadowMode = verdict.shadow_mode === true;
3746
4981
  const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
3747
4982
  if (transformedInput !== maskedText) {
4983
+ const serverDerivedMapping = derivePlaceholderMappingFromTransform(
4984
+ maskedText,
4985
+ transformedInput
4986
+ );
4987
+ if (Object.keys(serverDerivedMapping).length > 0) {
4988
+ mapping = mergePiiMappings(mapping, serverDerivedMapping);
4989
+ }
3748
4990
  maskedText = transformedInput;
3749
4991
  maskedReq = this.withMaskedOpenAIRequest(
3750
- req,
3751
- transformedInput
4992
+ providerReq,
4993
+ transformedInput,
4994
+ providerMaskingOptions
3752
4995
  );
3753
- const nextCreateArgs = [...normalizedCreateArgs];
4996
+ const nextCreateArgs = [...createArgs];
3754
4997
  nextCreateArgs[0] = maskedReq;
3755
4998
  createArgs = nextCreateArgs;
3756
4999
  }
5000
+ await this.logPromptPreflightStep(
5001
+ {
5002
+ system_id: systemId,
5003
+ user_id: options.user_id,
5004
+ request_identity: options.request_identity,
5005
+ input: maskedText,
5006
+ telemetry: telemetryMetadata,
5007
+ verdict,
5008
+ guard_event_id: guardEventId,
5009
+ guard_latency_ms: guardLatencyMs,
5010
+ preflight_for_client_event_id: canonicalClientEventId,
5011
+ client_capabilities: this.buildClientCapabilities(
5012
+ "openai",
5013
+ false,
5014
+ capabilityConfig
5015
+ ),
5016
+ local_fallback_applied: localFallbackApplied,
5017
+ local_fallback_reason: localFallbackReason,
5018
+ runtime_surface: "openai_sdk_guard"
5019
+ },
5020
+ requestOptions
5021
+ );
3757
5022
  if (stream) {
3758
5023
  const modelStartedAt2 = Date.now();
3759
5024
  const streamResponse = await originalCreate.apply(compTarget, createArgs);
@@ -3765,14 +5030,15 @@ var AgentID = class {
3765
5030
  })(),
3766
5031
  {
3767
5032
  piiMapping: mapping,
3768
- deanonymizeForClient: shouldDeanonymize
5033
+ deanonymizeForClient: false,
5034
+ maskForClient: !isShadowMode
3769
5035
  }
3770
5036
  );
3771
5037
  if (maskedText && wrappedCompletion.mode === "stream") {
3772
5038
  void wrappedCompletion.done.then(async (result) => {
3773
5039
  const modelLatencyMs2 = Math.max(0, Date.now() - modelStartedAt2);
3774
5040
  const totalPipelineLatencyMs2 = Math.max(0, Date.now() - pipelineStartedAt);
3775
- const outputForLog = isShadowMode ? result.rawOutput : result.transformedOutput;
5041
+ const outputForLog = result.transformedOutput;
3776
5042
  const ingestResult = await this.sendIngest({
3777
5043
  event_id: canonicalClientEventId,
3778
5044
  system_id: systemId,
@@ -3784,29 +5050,32 @@ var AgentID = class {
3784
5050
  usage: result.usage,
3785
5051
  latency: modelLatencyMs2,
3786
5052
  event_type: "complete",
3787
- metadata: {
3788
- transformed_input: maskedText,
3789
- transformed_output: result.transformedOutput,
3790
- output_masked: result.outputMasked,
3791
- shadow_mode: isShadowMode,
3792
- simulated_decision: verdict.simulated_decision ?? null,
3793
- simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
3794
- response_streamed: true,
3795
- sdk_local_fallback_applied: localFallbackApplied,
3796
- sdk_local_fallback_reason: localFallbackReason,
3797
- guard_latency_ms: guardLatencyMs,
3798
- model_latency_ms: modelLatencyMs2,
3799
- total_pipeline_latency_ms: totalPipelineLatencyMs2,
3800
- guard_event_id: guardEventId,
3801
- client_event_id: canonicalClientEventId,
3802
- transparency,
3803
- ...buildSdkTimingMetadata({
5053
+ metadata: mergeTelemetryContexts(
5054
+ telemetryMetadata,
5055
+ {
5056
+ transformed_input: maskedText,
5057
+ transformed_output: result.transformedOutput,
5058
+ output_masked: result.outputMasked,
5059
+ shadow_mode: isShadowMode,
5060
+ simulated_decision: verdict.simulated_decision ?? null,
5061
+ simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
5062
+ response_streamed: true,
5063
+ sdk_local_fallback_applied: localFallbackApplied,
5064
+ sdk_local_fallback_reason: localFallbackReason,
5065
+ guard_latency_ms: guardLatencyMs,
5066
+ model_latency_ms: modelLatencyMs2,
5067
+ total_pipeline_latency_ms: totalPipelineLatencyMs2,
5068
+ guard_event_id: guardEventId,
5069
+ client_event_id: canonicalClientEventId,
5070
+ transparency
5071
+ },
5072
+ buildSdkTimingMetadata({
3804
5073
  sdkConfigFetchMs,
3805
5074
  sdkLocalScanMs,
3806
5075
  sdkGuardMs: guardLatencyMs,
3807
5076
  sdkConfigVersion: capabilityConfig.version
3808
5077
  })
3809
- },
5078
+ ),
3810
5079
  client_capabilities: this.buildClientCapabilities(
3811
5080
  "openai",
3812
5081
  false,
@@ -3837,10 +5106,13 @@ var AgentID = class {
3837
5106
  const totalPipelineLatencyMs = Math.max(0, Date.now() - pipelineStartedAt);
3838
5107
  if (maskedText) {
3839
5108
  const output = adapter.extractOutput(res);
3840
- const wrappedCompletion = this.wrapCompletion(output);
5109
+ const wrappedCompletion = this.wrapCompletion(output, {
5110
+ piiMapping: mapping,
5111
+ deanonymizeForClient: false
5112
+ });
3841
5113
  const model = adapter.getModelName(maskedReq, res);
3842
5114
  const usage = adapter.getTokenUsage(res);
3843
- const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
5115
+ const outputForLog = wrappedCompletion.transformedOutput;
3844
5116
  const ingestResult = await this.sendIngest({
3845
5117
  event_id: canonicalClientEventId,
3846
5118
  system_id: systemId,
@@ -3852,29 +5124,32 @@ var AgentID = class {
3852
5124
  usage,
3853
5125
  latency: modelLatencyMs,
3854
5126
  event_type: "complete",
3855
- metadata: {
3856
- transformed_input: maskedText,
3857
- transformed_output: wrappedCompletion.transformedOutput,
3858
- output_masked: wrappedCompletion.outputMasked,
3859
- shadow_mode: isShadowMode,
3860
- simulated_decision: verdict.simulated_decision ?? null,
3861
- simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
3862
- response_streamed: false,
3863
- sdk_local_fallback_applied: localFallbackApplied,
3864
- sdk_local_fallback_reason: localFallbackReason,
3865
- guard_latency_ms: guardLatencyMs,
3866
- model_latency_ms: modelLatencyMs,
3867
- total_pipeline_latency_ms: totalPipelineLatencyMs,
3868
- guard_event_id: guardEventId,
3869
- client_event_id: canonicalClientEventId,
3870
- transparency,
3871
- ...buildSdkTimingMetadata({
5127
+ metadata: mergeTelemetryContexts(
5128
+ telemetryMetadata,
5129
+ {
5130
+ transformed_input: maskedText,
5131
+ transformed_output: wrappedCompletion.transformedOutput,
5132
+ output_masked: wrappedCompletion.outputMasked,
5133
+ shadow_mode: isShadowMode,
5134
+ simulated_decision: verdict.simulated_decision ?? null,
5135
+ simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
5136
+ response_streamed: false,
5137
+ sdk_local_fallback_applied: localFallbackApplied,
5138
+ sdk_local_fallback_reason: localFallbackReason,
5139
+ guard_latency_ms: guardLatencyMs,
5140
+ model_latency_ms: modelLatencyMs,
5141
+ total_pipeline_latency_ms: totalPipelineLatencyMs,
5142
+ guard_event_id: guardEventId,
5143
+ client_event_id: canonicalClientEventId,
5144
+ transparency
5145
+ },
5146
+ buildSdkTimingMetadata({
3872
5147
  sdkConfigFetchMs,
3873
5148
  sdkLocalScanMs,
3874
5149
  sdkGuardMs: guardLatencyMs,
3875
5150
  sdkConfigVersion: capabilityConfig.version
3876
5151
  })
3877
- },
5152
+ ),
3878
5153
  client_capabilities: this.buildClientCapabilities(
3879
5154
  "openai",
3880
5155
  false,
@@ -3891,17 +5166,21 @@ var AgentID = class {
3891
5166
  );
3892
5167
  }
3893
5168
  }
3894
- if (!capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig) && shouldDeanonymize) {
3895
- const deanon = this.pii.deanonymize(adapter.extractOutput(res), mapping);
5169
+ if (!isShadowMode && maskedText) {
5170
+ const output = adapter.extractOutput(res);
5171
+ const maskedOutput = this.wrapCompletion(output, {
5172
+ piiMapping: mapping,
5173
+ deanonymizeForClient: false
5174
+ }).transformedOutput;
3896
5175
  try {
3897
5176
  if (Array.isArray(res?.choices)) {
3898
5177
  for (const choice of res.choices) {
3899
5178
  const typedChoice = choice;
3900
5179
  if (typedChoice?.message && typeof typedChoice.message.content === "string") {
3901
- typedChoice.message.content = deanon;
5180
+ typedChoice.message.content = maskedOutput;
3902
5181
  }
3903
5182
  if (typedChoice?.delta && typeof typedChoice.delta.content === "string") {
3904
- typedChoice.delta.content = deanon;
5183
+ typedChoice.delta.content = maskedOutput;
3905
5184
  }
3906
5185
  }
3907
5186
  }
@@ -3926,14 +5205,222 @@ var AgentID = class {
3926
5205
  });
3927
5206
  }
3928
5207
  };
5208
+ function mergeWorkflowTrailRequestOptions(base, override) {
5209
+ const apiKey = firstNonEmptyString(override?.apiKey, base?.apiKey);
5210
+ return apiKey ? { apiKey } : void 0;
5211
+ }
5212
+ function appendWorkflowErrorMetadata(metadata, error) {
5213
+ const nextMetadata = { ...metadata ?? {} };
5214
+ if (error instanceof Error) {
5215
+ if (typeof nextMetadata.error_name !== "string") {
5216
+ nextMetadata.error_name = error.name;
5217
+ }
5218
+ if (typeof nextMetadata.error_message !== "string" && error.message.trim().length > 0) {
5219
+ nextMetadata.error_message = error.message.trim();
5220
+ }
5221
+ return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
5222
+ }
5223
+ if (typeof nextMetadata.error_message !== "string" && typeof error !== "undefined") {
5224
+ const errorMessage = String(error).trim();
5225
+ if (errorMessage.length > 0) {
5226
+ nextMetadata.error_message = errorMessage;
5227
+ }
5228
+ }
5229
+ return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
5230
+ }
5231
+ var AgentIDWorkflowStep = class {
5232
+ constructor(params) {
5233
+ this.trail = params.trail;
5234
+ this.workflowStepId = params.workflowStepId;
5235
+ this.startEventId = params.startEventId;
5236
+ this.telemetry = params.telemetry;
5237
+ this.startedAtMs = params.startedAtMs;
5238
+ }
5239
+ resolveStepTelemetry(telemetry) {
5240
+ return mergeTelemetryContexts(
5241
+ this.telemetry,
5242
+ createAgentIdTelemetryContext({
5243
+ workflow_step_id: this.workflowStepId,
5244
+ parent_event_id: this.startEventId
5245
+ }),
5246
+ telemetry
5247
+ );
5248
+ }
5249
+ async log(params = {}, options) {
5250
+ return this.trail.logStep(
5251
+ {
5252
+ ...params,
5253
+ telemetry: this.resolveStepTelemetry(params.telemetry)
5254
+ },
5255
+ options
5256
+ );
5257
+ }
5258
+ async complete(params = {}, options) {
5259
+ return this.log(
5260
+ {
5261
+ ...params,
5262
+ latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
5263
+ event_status: params.event_status ?? "completed"
5264
+ },
5265
+ options
5266
+ );
5267
+ }
5268
+ async fail(error, params = {}, options) {
5269
+ return this.log(
5270
+ {
5271
+ ...params,
5272
+ latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
5273
+ metadata: appendWorkflowErrorMetadata(params.metadata, error),
5274
+ event_type: params.event_type ?? "error",
5275
+ event_status: params.event_status ?? "failed",
5276
+ severity: params.severity ?? "error"
5277
+ },
5278
+ options
5279
+ );
5280
+ }
5281
+ };
5282
+ var AgentIDWorkflowTrail = class {
5283
+ constructor(options) {
5284
+ this.agent = options.agent;
5285
+ this.systemId = options.system_id;
5286
+ this.userId = options.user_id;
5287
+ this.requestIdentity = options.request_identity;
5288
+ this.telemetry = createAgentIdTelemetryContext(options.telemetry);
5289
+ this.clientCapabilities = options.client_capabilities;
5290
+ this.requestOptions = options.requestOptions;
5291
+ }
5292
+ async logStep(params = {}, options) {
5293
+ const payload = this.agent.buildOperationLogParams({
5294
+ ...params,
5295
+ system_id: this.systemId,
5296
+ user_id: this.userId,
5297
+ request_identity: this.requestIdentity,
5298
+ telemetry: mergeTelemetryContexts(this.telemetry, params.telemetry),
5299
+ client_capabilities: params.client_capabilities ?? this.clientCapabilities
5300
+ });
5301
+ await this.agent.log(
5302
+ payload,
5303
+ mergeWorkflowTrailRequestOptions(this.requestOptions, options)
5304
+ );
5305
+ return payload;
5306
+ }
5307
+ async startStep(params = {}, options) {
5308
+ const startedAtMs = Date.now();
5309
+ const requestedTelemetry = createAgentIdTelemetryContext(params.telemetry);
5310
+ const workflowStepId = firstNonEmptyString(requestedTelemetry?.workflow_step_id, requestedTelemetry?.workflowStepId) ?? createAgentIdCorrelationId();
5311
+ const startTelemetry = mergeTelemetryContexts(
5312
+ requestedTelemetry,
5313
+ createAgentIdTelemetryContext({
5314
+ workflow_step_id: workflowStepId
5315
+ })
5316
+ );
5317
+ const startPayload = await this.logStep(
5318
+ {
5319
+ ...params,
5320
+ telemetry: startTelemetry,
5321
+ event_type: params.event_type ?? "start",
5322
+ event_status: params.event_status ?? "started"
5323
+ },
5324
+ options
5325
+ );
5326
+ return new AgentIDWorkflowStep({
5327
+ trail: this,
5328
+ workflowStepId,
5329
+ startEventId: startPayload.event_id ?? createEventId2(),
5330
+ telemetry: startTelemetry,
5331
+ startedAtMs
5332
+ });
5333
+ }
5334
+ async runStep(params, run, hooks, options) {
5335
+ const step = await this.startStep(params, options);
5336
+ try {
5337
+ const result = await run();
5338
+ const completeParams = {
5339
+ ...hooks?.complete ?? {},
5340
+ ...hooks?.onComplete?.(result) ?? {}
5341
+ };
5342
+ await step.complete(completeParams, options);
5343
+ return result;
5344
+ } catch (error) {
5345
+ const failParams = {
5346
+ ...hooks?.fail ?? {},
5347
+ ...hooks?.onError?.(error) ?? {}
5348
+ };
5349
+ await step.fail(error, failParams, options);
5350
+ throw error;
5351
+ }
5352
+ }
5353
+ };
5354
+ function createAgentIdWorkflowTrail(options) {
5355
+ return new AgentIDWorkflowTrail(options);
5356
+ }
5357
+
5358
+ // src/message-history.ts
5359
+ function isPlainRecord(value) {
5360
+ if (!value || typeof value !== "object") return false;
5361
+ const proto = Object.getPrototypeOf(value);
5362
+ return proto === Object.prototype || proto === null;
5363
+ }
5364
+ function protectMessageHistory(messages, options = { pii: true, secrets: true }) {
5365
+ const piiManager = new PIIManager();
5366
+ let textPartsCount = 0;
5367
+ let transformedTextPartsCount = 0;
5368
+ const protectString = (value) => {
5369
+ textPartsCount += 1;
5370
+ const masked = piiManager.anonymize(value, options).maskedText;
5371
+ if (masked !== value) {
5372
+ transformedTextPartsCount += 1;
5373
+ }
5374
+ return masked;
5375
+ };
5376
+ const visit = (value, key) => {
5377
+ if (typeof value === "string") {
5378
+ return key === "content" || key === "text" ? protectString(value) : value;
5379
+ }
5380
+ if (Array.isArray(value)) {
5381
+ let changed = false;
5382
+ const next = value.map((item) => {
5383
+ const protectedItem = visit(item);
5384
+ if (protectedItem !== item) changed = true;
5385
+ return protectedItem;
5386
+ });
5387
+ return changed ? next : value;
5388
+ }
5389
+ if (isPlainRecord(value)) {
5390
+ let changed = false;
5391
+ const next = {};
5392
+ for (const [entryKey, entryValue] of Object.entries(value)) {
5393
+ const protectedValue = visit(entryValue, entryKey);
5394
+ next[entryKey] = protectedValue;
5395
+ if (protectedValue !== entryValue) changed = true;
5396
+ }
5397
+ return changed ? next : value;
5398
+ }
5399
+ return value;
5400
+ };
5401
+ const protectedMessages = visit(messages);
5402
+ return {
5403
+ messages: protectedMessages,
5404
+ transformed: protectedMessages !== messages,
5405
+ textPartsCount,
5406
+ transformedTextPartsCount
5407
+ };
5408
+ }
3929
5409
  // Annotate the CommonJS export names for ESM import in node:
3930
5410
  0 && (module.exports = {
3931
5411
  AgentID,
5412
+ AgentIDWorkflowStep,
5413
+ AgentIDWorkflowTrail,
3932
5414
  DependencyError,
3933
5415
  InjectionScanner,
3934
5416
  OpenAIAdapter,
3935
5417
  PIIManager,
3936
5418
  SecurityBlockError,
5419
+ createAgentIdCorrelationId,
5420
+ createAgentIdOperationLog,
5421
+ createAgentIdTelemetryContext,
5422
+ createAgentIdWorkflowTrail,
3937
5423
  getInjectionScanner,
5424
+ protectMessageHistory,
3938
5425
  scanWithRegex
3939
5426
  });