agentid-sdk 0.1.41 → 0.1.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,6 @@
1
1
  // src/adapters.ts
2
+ var MAX_GUARD_ATTACHMENTS = 4;
3
+ var MAX_PROMPT_CONTEXT_CHARS = 64e3;
2
4
  function getLastUserMessage(req) {
3
5
  const messages = req?.messages;
4
6
  if (!Array.isArray(messages)) return null;
@@ -78,31 +80,79 @@ function normalizeImageAttachment(part) {
78
80
  content_base64: imageUrl
79
81
  };
80
82
  }
81
- var OpenAIAdapter = class {
82
- extractInput(req) {
83
- const lastUser = getLastUserMessage(req);
84
- if (!lastUser) return null;
85
- const content = lastUser.content;
86
- if (typeof content === "string") return content;
87
- if (Array.isArray(content)) {
88
- const parts = [];
89
- for (const part of content) {
90
- if (part && typeof part === "object" && typeof part.text === "string") {
91
- parts.push(part.text);
92
- }
83
+ function truncatePromptContext(value) {
84
+ if (value.length <= MAX_PROMPT_CONTEXT_CHARS) {
85
+ return value;
86
+ }
87
+ const headChars = Math.floor((MAX_PROMPT_CONTEXT_CHARS - 32) / 2);
88
+ const tailChars = MAX_PROMPT_CONTEXT_CHARS - headChars - 32;
89
+ return `${value.slice(0, headChars)}
90
+ [...TRUNCATED CONTEXT...]
91
+ ${value.slice(-tailChars)}`;
92
+ }
93
+ function formatPromptContextRole(role) {
94
+ return typeof role === "string" && role.trim().length > 0 ? role.trim() : "message";
95
+ }
96
+ function extractTextParts(content) {
97
+ if (typeof content === "string" && content.length > 0) {
98
+ return [content];
99
+ }
100
+ if (!Array.isArray(content)) {
101
+ return [];
102
+ }
103
+ const parts = [];
104
+ for (const part of content) {
105
+ if (!part || typeof part !== "object") {
106
+ continue;
107
+ }
108
+ if (typeof part.text === "string") {
109
+ const text = part.text;
110
+ if (text.length > 0) {
111
+ parts.push(text);
93
112
  }
94
- return parts.length ? parts.join("") : null;
95
113
  }
96
- return null;
97
114
  }
98
- extractAttachments(req) {
99
- const lastUser = getLastUserMessage(req);
100
- if (!lastUser) return [];
101
- const content = lastUser?.content;
115
+ return parts;
116
+ }
117
+ function extractAttachmentPlaceholders(content) {
118
+ if (!Array.isArray(content)) {
119
+ return [];
120
+ }
121
+ const placeholders = [];
122
+ for (const part of content) {
123
+ if (!part || typeof part !== "object") {
124
+ continue;
125
+ }
126
+ const typedPart = part;
127
+ if (typedPart.type === "file") {
128
+ placeholders.push(
129
+ `[attachment:${normalizeFilename(typedPart.file?.filename, "attachment.bin")}]`
130
+ );
131
+ continue;
132
+ }
133
+ if (typedPart.type === "image_url") {
134
+ const imageUrl = typedPart.image_url?.url;
135
+ placeholders.push(
136
+ imageUrl?.startsWith("data:") ? "[attachment:image]" : "[attachment:image_url]"
137
+ );
138
+ }
139
+ }
140
+ return placeholders;
141
+ }
142
+ function collectUserAttachments(req) {
143
+ const messages = req?.messages;
144
+ if (!Array.isArray(messages)) {
145
+ return [];
146
+ }
147
+ const attachments = [];
148
+ for (const message of messages) {
149
+ if (!message || typeof message !== "object" || message.role !== "user") {
150
+ continue;
151
+ }
152
+ const content = message.content;
102
153
  if (!Array.isArray(content)) {
103
- return [];
154
+ continue;
104
155
  }
105
- const attachments = [];
106
156
  for (const part of content) {
107
157
  if (!part || typeof part !== "object") {
108
158
  continue;
@@ -121,7 +171,57 @@ var OpenAIAdapter = class {
121
171
  }
122
172
  }
123
173
  }
124
- return attachments;
174
+ }
175
+ return attachments.slice(-MAX_GUARD_ATTACHMENTS);
176
+ }
177
+ function serializeOpenAIPromptContext(req) {
178
+ const messages = req?.messages;
179
+ if (!Array.isArray(messages)) {
180
+ return null;
181
+ }
182
+ const entries = [];
183
+ for (const message of messages) {
184
+ if (!message || typeof message !== "object") {
185
+ continue;
186
+ }
187
+ const role = formatPromptContextRole(message.role);
188
+ const content = message.content;
189
+ const fragments = [
190
+ ...extractTextParts(content),
191
+ ...extractAttachmentPlaceholders(content)
192
+ ].filter((fragment) => fragment.length > 0);
193
+ if (fragments.length === 0) {
194
+ continue;
195
+ }
196
+ entries.push(`[${role}] ${fragments.join("\n")}`);
197
+ }
198
+ if (entries.length === 0) {
199
+ return null;
200
+ }
201
+ return truncatePromptContext(entries.join("\n\n"));
202
+ }
203
+ var OpenAIAdapter = class {
204
+ extractInput(req) {
205
+ const lastUser = getLastUserMessage(req);
206
+ if (!lastUser) return null;
207
+ const content = lastUser.content;
208
+ if (typeof content === "string") return content;
209
+ if (Array.isArray(content)) {
210
+ const parts = [];
211
+ for (const part of content) {
212
+ if (part && typeof part === "object" && typeof part.text === "string") {
213
+ parts.push(part.text);
214
+ }
215
+ }
216
+ return parts.length ? parts.join("") : null;
217
+ }
218
+ return null;
219
+ }
220
+ extractAttachments(req) {
221
+ return collectUserAttachments(req);
222
+ }
223
+ extractPromptContext(req) {
224
+ return serializeOpenAIPromptContext(req);
125
225
  }
126
226
  getModelName(req, res) {
127
227
  const model = res?.model ?? req?.model ?? "unknown";
@@ -1006,49 +1106,49 @@ function detectNationalIdentifiers(text, options = {}) {
1006
1106
  var SDK_SECRET_PATTERN_DEFINITIONS = [
1007
1107
  {
1008
1108
  id: "openai_api_key",
1009
- placeholderType: "OPENAI_API_KEY",
1109
+ placeholderType: "SECRET",
1010
1110
  patternSource: "\\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\\b",
1011
1111
  flags: "iu",
1012
1112
  prefilterTerms: ["sk-", "proj-", "openai"]
1013
1113
  },
1014
1114
  {
1015
1115
  id: "aws_access_key",
1016
- placeholderType: "AWS_ACCESS_KEY",
1116
+ placeholderType: "SECRET",
1017
1117
  patternSource: "\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b",
1018
1118
  flags: "iu",
1019
1119
  prefilterTerms: ["akia", "asia", "aws"]
1020
1120
  },
1021
1121
  {
1022
1122
  id: "github_token",
1023
- placeholderType: "GITHUB_TOKEN",
1123
+ placeholderType: "SECRET",
1024
1124
  patternSource: "\\b(?:gh[pousr]_[A-Za-z0-9]{24,255}|github_pat_[A-Za-z0-9_]{20,255})\\b",
1025
1125
  flags: "iu",
1026
1126
  prefilterTerms: ["ghp_", "gho_", "ghu_", "ghs_", "ghr_", "github_pat_"]
1027
1127
  },
1028
1128
  {
1029
1129
  id: "slack_token",
1030
- placeholderType: "SLACK_TOKEN",
1130
+ placeholderType: "SECRET",
1031
1131
  patternSource: "\\bxox(?:a|b|p|r|s)-[A-Za-z0-9-]{10,200}\\b",
1032
1132
  flags: "iu",
1033
1133
  prefilterTerms: ["xoxa-", "xoxb-", "xoxp-", "xoxr-", "xoxs-", "slack"]
1034
1134
  },
1035
1135
  {
1036
1136
  id: "slack_webhook_url",
1037
- placeholderType: "SLACK_WEBHOOK_URL",
1137
+ placeholderType: "SECRET",
1038
1138
  patternSource: "https:\\/\\/hooks\\.slack\\.com\\/services\\/[A-Za-z0-9/_-]{20,}",
1039
1139
  flags: "iu",
1040
1140
  prefilterTerms: ["hooks.slack.com/services", "slack"]
1041
1141
  },
1042
1142
  {
1043
1143
  id: "discord_webhook_url",
1044
- placeholderType: "DISCORD_WEBHOOK_URL",
1144
+ placeholderType: "SECRET",
1045
1145
  patternSource: "https:\\/\\/discord(?:app)?\\.com\\/api\\/webhooks\\/\\d+\\/[A-Za-z0-9_-]{16,}",
1046
1146
  flags: "iu",
1047
1147
  prefilterTerms: ["discord.com/api/webhooks", "discordapp.com/api/webhooks", "discord"]
1048
1148
  },
1049
1149
  {
1050
1150
  id: "stripe_secret_key",
1051
- placeholderType: "STRIPE_SECRET_KEY",
1151
+ placeholderType: "SECRET",
1052
1152
  patternSource: "\\b(?:sk|pk|ak|rk)_(?:live|test)_[A-Za-z0-9]+\\b",
1053
1153
  flags: "iu",
1054
1154
  prefilterTerms: [
@@ -1065,49 +1165,49 @@ var SDK_SECRET_PATTERN_DEFINITIONS = [
1065
1165
  },
1066
1166
  {
1067
1167
  id: "google_api_key",
1068
- placeholderType: "GOOGLE_API_KEY",
1168
+ placeholderType: "SECRET",
1069
1169
  patternSource: "\\bAIza[0-9A-Za-z_-]{35}\\b",
1070
1170
  flags: "iu",
1071
1171
  prefilterTerms: ["aiza", "google"]
1072
1172
  },
1073
1173
  {
1074
1174
  id: "anthropic_api_key",
1075
- placeholderType: "ANTHROPIC_API_KEY",
1175
+ placeholderType: "SECRET",
1076
1176
  patternSource: "\\bsk-ant-(?:api\\d{2}-)?[A-Za-z0-9_-]{20,}\\b",
1077
1177
  flags: "iu",
1078
1178
  prefilterTerms: ["sk-ant-", "anthropic"]
1079
1179
  },
1080
1180
  {
1081
1181
  id: "evm_private_key",
1082
- placeholderType: "EVM_PRIVATE_KEY",
1182
+ placeholderType: "SECRET",
1083
1183
  patternSource: "\\b0x[a-fA-F0-9]{64}\\b",
1084
1184
  flags: "iu",
1085
1185
  prefilterTerms: ["0x", "ethereum", "evm", "private key"]
1086
1186
  },
1087
1187
  {
1088
1188
  id: "jwt_token",
1089
- placeholderType: "JWT_TOKEN",
1189
+ placeholderType: "SECRET",
1090
1190
  patternSource: "\\beyJ[A-Za-z0-9_-]{6,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\b",
1091
1191
  flags: "iu",
1092
1192
  prefilterTerms: ["eyj", "jwt", "bearer"]
1093
1193
  },
1094
1194
  {
1095
1195
  id: "bearer_token",
1096
- placeholderType: "BEARER_TOKEN",
1196
+ placeholderType: "SECRET",
1097
1197
  patternSource: "\\bauthorization\\b\\s*[:=]\\s*bearer\\s+[A-Za-z0-9._~+\\/-]{16,}|\\bbearer\\s+[A-Za-z0-9._~+\\/-]{24,}",
1098
1198
  flags: "iu",
1099
1199
  prefilterTerms: ["authorization", "bearer"]
1100
1200
  },
1101
1201
  {
1102
1202
  id: "api_key_header",
1103
- placeholderType: "API_KEY_HEADER",
1203
+ placeholderType: "SECRET",
1104
1204
  patternSource: "\\bx[-_]?api[-_]?key\\b\\s*[:=]\\s*[A-Za-z0-9._~+\\/-]{16,}",
1105
1205
  flags: "iu",
1106
1206
  prefilterTerms: ["x-api-key", "api-key", "x_api_key", "api_key"]
1107
1207
  },
1108
1208
  {
1109
1209
  id: "credential_assignment",
1110
- placeholderType: "CREDENTIAL_ASSIGNMENT",
1210
+ placeholderType: "SECRET",
1111
1211
  patternSource: `(?:\\b|["'])(?:api(?:[_-]?|\\s+)key|access(?:[_-]?|\\s+)token|auth(?:[_-]?|\\s+)token|client(?:[_-]?|\\s+)secret|private(?:[_-]?|\\s+)key)(?:\\b|["'])\\s*(?::|=|=>)\\s*(?:"[A-Za-z0-9._~+\\/=:-]{16,}"|'[A-Za-z0-9._~+\\/=:-]{16,}'|[A-Za-z0-9._~+\\/=:-]{16,})`,
1112
1212
  flags: "iu",
1113
1213
  prefilterTerms: [
@@ -1123,28 +1223,28 @@ var SDK_SECRET_PATTERN_DEFINITIONS = [
1123
1223
  },
1124
1224
  {
1125
1225
  id: "password_assignment",
1126
- placeholderType: "PASSWORD_ASSIGNMENT",
1226
+ placeholderType: "PASSWORD",
1127
1227
  patternSource: `(?:\\b|["'])(?:password|passwd|pwd|heslo)(?:\\b|["'])\\s*(?:(?::|=|=>)|(?:is|are|was|were|je)\\b)?\\s*(?:"[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,}"|'[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,}'|[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,})`,
1128
1228
  flags: "iu",
1129
1229
  prefilterTerms: ["password", "passwd", "pwd", "heslo"]
1130
1230
  },
1131
1231
  {
1132
1232
  id: "private_key_material",
1133
- placeholderType: "PRIVATE_KEY_MATERIAL",
1233
+ placeholderType: "SECRET",
1134
1234
  patternSource: "-----BEGIN (?:(?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY|PGP PRIVATE KEY BLOCK|CERTIFICATE)-----[\\s\\S]{20,12000}(?:-----END (?:(?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY|PGP PRIVATE KEY BLOCK|CERTIFICATE)-----|$)",
1135
1235
  flags: "iu",
1136
1236
  prefilterTerms: ["begin private key", "begin pgp private key block", "private key"]
1137
1237
  },
1138
1238
  {
1139
1239
  id: "azure_connection_string",
1140
- placeholderType: "AZURE_CONNECTION_STRING",
1240
+ placeholderType: "SECRET",
1141
1241
  patternSource: "\\bDefaultEndpointsProtocol=https;AccountName=[A-Za-z0-9.-]{3,};AccountKey=[A-Za-z0-9+/=]{20,}(?:;EndpointSuffix=[A-Za-z0-9.-]+)?\\b",
1142
1242
  flags: "iu",
1143
1243
  prefilterTerms: ["defaultendpointsprotocol", "accountname", "accountkey", "azure"]
1144
1244
  },
1145
1245
  {
1146
1246
  id: "azure_sas_token",
1147
- placeholderType: "AZURE_SAS_TOKEN",
1247
+ placeholderType: "SECRET",
1148
1248
  patternSource: "\\bsv=[^\\s&]{2,}&[^\\s]{0,200}\\bsig=[A-Za-z0-9%/+_-]{16,}",
1149
1249
  flags: "iu",
1150
1250
  prefilterTerms: ["sv=", "sig=", "accountkey", "azure"]
@@ -1207,19 +1307,70 @@ function rangesOverlap(left, right) {
1207
1307
  return left.start < right.end && right.start < left.end;
1208
1308
  }
1209
1309
  function detectionPriority(type) {
1210
- if (/^(?:OPENAI_API_KEY|AWS_ACCESS_KEY|GITHUB_TOKEN|SLACK_TOKEN|SLACK_WEBHOOK_URL|DISCORD_WEBHOOK_URL|STRIPE_SECRET_KEY|GOOGLE_API_KEY|ANTHROPIC_API_KEY|EVM_PRIVATE_KEY|JWT_TOKEN|BEARER_TOKEN|API_KEY_HEADER|AZURE_CONNECTION_STRING|AZURE_SAS_TOKEN)$/u.test(
1211
- type
1212
- )) {
1310
+ const normalizedType = toPlaceholderType(type);
1311
+ if (normalizedType === "SECRET") {
1213
1312
  return 100;
1214
1313
  }
1215
- if (/^(?:CREDENTIAL_ASSIGNMENT|PASSWORD_ASSIGNMENT|PRIVATE_KEY_MATERIAL|ENV_SECRET_ASSIGNMENT)$/u.test(type)) {
1314
+ if (normalizedType === "PASSWORD") {
1315
+ return 90;
1316
+ }
1317
+ if (/^(?:CREDENTIAL_ASSIGNMENT|PRIVATE_KEY_MATERIAL|ENV_SECRET_ASSIGNMENT)$/u.test(
1318
+ normalizedType
1319
+ )) {
1216
1320
  return 80;
1217
1321
  }
1218
- if (type === "PERSON_NAME" || type === "PERSON") {
1322
+ if (normalizedType === "PERSON_NAME" || normalizedType === "PERSON") {
1219
1323
  return 10;
1220
1324
  }
1221
1325
  return 50;
1222
1326
  }
1327
+ function isPasswordPlaceholderType(type) {
1328
+ return /^(?:PASSWORD_ASSIGNMENT|BASIC_AUTH_PASSWORD)$/u.test(type);
1329
+ }
1330
+ function isGenericSecretPlaceholderType(type) {
1331
+ return /^(?: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|CREDENTIAL_ASSIGNMENT|PRIVATE_KEY_MATERIAL|ENV_SECRET_ASSIGNMENT|AZURE_CONNECTION_STRING|AZURE_SAS_TOKEN|DISCORD_WEBHOOK_TOKEN)$/u.test(
1332
+ type
1333
+ );
1334
+ }
1335
+ function toPlaceholderType(type) {
1336
+ const normalized = String(type ?? "").trim().toUpperCase();
1337
+ if (isPasswordPlaceholderType(normalized)) {
1338
+ return "PASSWORD";
1339
+ }
1340
+ if (isGenericSecretPlaceholderType(normalized)) {
1341
+ return "SECRET";
1342
+ }
1343
+ return normalized || "PII";
1344
+ }
1345
+ function trimLeadingAddressContext(value) {
1346
+ const trimmed = value.replace(
1347
+ /^(?:(?:na\s+)?adrese|(?:se\s+)?(?:s[ií]dlem|bydli[sš]t[ěe]m|bytem|adresa(?:\s+bydli[sš]t[ěe])?))\s*[:,-]?\s*/iu,
1348
+ ""
1349
+ );
1350
+ if (!trimmed || trimmed === value) {
1351
+ return { text: value, offset: 0 };
1352
+ }
1353
+ return {
1354
+ text: trimmed,
1355
+ offset: value.indexOf(trimmed)
1356
+ };
1357
+ }
1358
+ function normalizeDetection(detection) {
1359
+ if (detection.type !== "ADDRESS") {
1360
+ return detection;
1361
+ }
1362
+ const trimmed = trimLeadingAddressContext(detection.text);
1363
+ if (trimmed.offset <= 0 || trimmed.text === detection.text) {
1364
+ return detection;
1365
+ }
1366
+ const start = detection.start + trimmed.offset;
1367
+ return {
1368
+ ...detection,
1369
+ start,
1370
+ end: start + trimmed.text.length,
1371
+ text: trimmed.text
1372
+ };
1373
+ }
1223
1374
  var PHONE_CONTEXT_KEYWORDS = [
1224
1375
  "tel",
1225
1376
  "phone",
@@ -1334,6 +1485,19 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1334
1485
  "security",
1335
1486
  "instructions",
1336
1487
  "instruction",
1488
+ "authorized",
1489
+ "audit",
1490
+ "article",
1491
+ "compliance",
1492
+ "global",
1493
+ "governance",
1494
+ "charter",
1495
+ "initialization",
1496
+ "sequence",
1497
+ "prefix",
1498
+ "prefixes",
1499
+ "priority",
1500
+ "violation",
1337
1501
  "google",
1338
1502
  "form",
1339
1503
  "forms",
@@ -1408,6 +1572,21 @@ var TECHNICAL_CONTEXT_SYMBOL_REGEX = /:\/\/|`|\{|\}|\[|\]|\(|\)|;|\$|=>|::|\/\//
1408
1572
  var NAME_LABEL_QUESTION_CONTEXT_REGEX = /\b(?:jak(?:e|y|a|ou)|kter(?:e|y|a|ou)|co|what|which|whose|wie|welch(?:e|er|es|en|em)?|quel(?:le|s|les)?|que|cual(?:es)?|wat|welke|jaki|jakie|jaka)\b[\s\S]{0,80}\b(?:jmeno|prijmeni|name|names|namen|nom|nombre|nome|naam|imie|nazwisko|meno)\b[\s\S]{0,96}\b(?:napsal\p{L}*|napsan\p{L}*|psal\p{L}*|pouzil\p{L}*|pouzili\p{L}*|write|wrote|written|type|typed|enter(?:ed)?|use(?:d)?|say|said|geschrieben|getippt|eingetragen|ecrit|escrib\p{L}*|scritt\p{L}*)\b/iu;
1409
1573
  var NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX = /(?:[:=]|=>|-|\b(?:is|was|je|jsou|jmenuje|called|named|ist|sind|lautet|est|es)\b)\s*$/iu;
1410
1574
  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;
1575
+ var ADDRESS_HOUSE_NUMBER_PATTERN = String.raw`\d{1,5}(?:\/\d{1,5}[A-Za-z]?)?[A-Za-z]?`;
1576
+ var ADDRESS_POSTAL_CODE_PATTERN = String.raw`(?:\d{3}\s?\d{2}|\d{5})`;
1577
+ var ADDRESS_STREET_LABEL_PATTERN = String.raw`(?:ulici|ulice|ul\.?|street|st\.?|road|rd\.?|avenue|ave\.?|n[aá]m[eě]st[ií]|t[řr][íi]da|alej|n[aá]b[řr]ež[ií])`;
1578
+ var ADDRESS_WITH_ANCHOR_RE = new RegExp(
1579
+ String.raw`\b(?:bydl[ií]m\s+na|bydlim\s+na|bytem|bydli[sš]t[eě]|adresa|na\s+ulici|v\s+ulici|doru[cč]ovac[ií]\s+adresa|koresponden[cč]n[ií]\s+adresa|faktura[cč]n[ií]\s+adresa|se\s+s[ií]dlem|z[ií]ju\s+v|ziju\s+v|zjiu\s+v)\b[\s,:-]{0,12}((?:(?:${ADDRESS_STREET_LABEL_PATTERN})\s+)?(?:\p{L}[\p{L}'’-]{2,}\s+){0,4}${ADDRESS_HOUSE_NUMBER_PATTERN}(?:(?:,\s*|\s+)(?:${ADDRESS_POSTAL_CODE_PATTERN}))?(?:(?:,\s*|\s+)(?:v|ve)\s+)?(?:(?:,\s*|\s+)(?:\p{L}[\p{L}'’-]{2,})(?:\s+\p{L}[\p{L}'’-]{2,}){0,2})?)`,
1580
+ "giu"
1581
+ );
1582
+ var ADDRESS_CITY_NUMBER_WITH_ANCHOR_RE = new RegExp(
1583
+ String.raw`\b(?:z[ií]ju\s+v|ziju\s+v|zjiu\s+v|v\s+obci|v\s+katastru\s+obce)\b[\s,:-]{0,12}((?:\p{L}[\p{L}'’-]{2,})(?:\s+\p{L}[\p{L}'’-]{2,}){0,2}\s+${ADDRESS_HOUSE_NUMBER_PATTERN})`,
1584
+ "giu"
1585
+ );
1586
+ var ADDRESS_STANDALONE_RE = new RegExp(
1587
+ String.raw`\b((?:(?:${ADDRESS_STREET_LABEL_PATTERN})\s+)?(?:\p{L}[\p{L}'’-]{2,}\s+){0,4}${ADDRESS_HOUSE_NUMBER_PATTERN}(?:,\s*|\s+)(?:${ADDRESS_POSTAL_CODE_PATTERN})(?:,\s*|\s+)(?:\p{L}[\p{L}'’-]{2,}(?:\s+\p{L}[\p{L}'’-]{2,}){0,2}))`,
1588
+ "gu"
1589
+ );
1411
1590
  function hasPhoneContext(text, matchStartIndex, windowSize = 50) {
1412
1591
  const start = Math.max(0, matchStartIndex - windowSize);
1413
1592
  const windowLower = text.slice(start, matchStartIndex).toLowerCase();
@@ -1459,6 +1638,26 @@ function isLikelyPersonNameCandidate(candidate, contextWindow) {
1459
1638
  }
1460
1639
  return true;
1461
1640
  }
1641
+ function isLikelyAddressCandidate(candidate) {
1642
+ if (!/\d/u.test(candidate)) {
1643
+ return false;
1644
+ }
1645
+ const normalized = normalizePersonWord(candidate);
1646
+ const words = candidate.trim().split(/\s+/).filter(Boolean);
1647
+ if (words.length < 2) {
1648
+ return false;
1649
+ }
1650
+ const numberIndex = words.findIndex((word) => /\d/u.test(word));
1651
+ if (numberIndex <= 0) {
1652
+ return false;
1653
+ }
1654
+ const letterWordRe = /^\p{L}[\p{L}'’-]*$/u;
1655
+ const beforeCount = words.slice(0, numberIndex).filter((word) => letterWordRe.test(word)).length;
1656
+ const afterCount = words.slice(numberIndex + 1).filter((word) => letterWordRe.test(word)).length;
1657
+ return /\b(?:ulici|ulice|ul\.|street|road|avenue|namesti|trida|alej|nabrezi)\b/iu.test(
1658
+ normalized
1659
+ ) || /\b\d{3}\s?\d{2}\b|\b\d{5}\b/u.test(candidate) || beforeCount >= 1 && afterCount >= 1;
1660
+ }
1462
1661
  var PIIManager = class {
1463
1662
  /**
1464
1663
  * Reversible local-first masking using <TYPE_INDEX> placeholders.
@@ -1539,13 +1738,55 @@ var PIIManager = class {
1539
1738
  });
1540
1739
  for (const match of nationalIdMatches) {
1541
1740
  if (match.start < 0 || match.end <= match.start) continue;
1741
+ const detectionType = match.type === "address_postal" ? "ADDRESS" : match.type === "birth_number" ? "BIRTH_NUMBER" : "NATIONAL_ID";
1542
1742
  detections.push({
1543
1743
  start: match.start,
1544
1744
  end: match.end,
1545
- type: "NATIONAL_ID",
1745
+ type: detectionType,
1546
1746
  text: text.slice(match.start, match.end)
1547
1747
  });
1548
1748
  }
1749
+ ADDRESS_WITH_ANCHOR_RE.lastIndex = 0;
1750
+ for (const match of text.matchAll(ADDRESS_WITH_ANCHOR_RE)) {
1751
+ if (match.index == null) continue;
1752
+ const value = match[1] ?? "";
1753
+ if (!value || !isLikelyAddressCandidate(value)) continue;
1754
+ const localIndex = match[0].lastIndexOf(value);
1755
+ const start = match.index + Math.max(0, localIndex);
1756
+ detections.push({
1757
+ start,
1758
+ end: start + value.length,
1759
+ type: "ADDRESS",
1760
+ text: value
1761
+ });
1762
+ }
1763
+ ADDRESS_CITY_NUMBER_WITH_ANCHOR_RE.lastIndex = 0;
1764
+ for (const match of text.matchAll(ADDRESS_CITY_NUMBER_WITH_ANCHOR_RE)) {
1765
+ if (match.index == null) continue;
1766
+ const value = match[1] ?? "";
1767
+ if (!value || !isLikelyAddressCandidate(value)) continue;
1768
+ const localIndex = match[0].lastIndexOf(value);
1769
+ const start = match.index + Math.max(0, localIndex);
1770
+ detections.push({
1771
+ start,
1772
+ end: start + value.length,
1773
+ type: "ADDRESS",
1774
+ text: value
1775
+ });
1776
+ }
1777
+ ADDRESS_STANDALONE_RE.lastIndex = 0;
1778
+ for (const match of text.matchAll(ADDRESS_STANDALONE_RE)) {
1779
+ if (match.index == null) continue;
1780
+ const value = match[1] ?? match[0];
1781
+ if (!value || !isLikelyAddressCandidate(value)) continue;
1782
+ const start = match.index;
1783
+ detections.push({
1784
+ start,
1785
+ end: start + value.length,
1786
+ type: "ADDRESS",
1787
+ text: value
1788
+ });
1789
+ }
1549
1790
  }
1550
1791
  if (resolvedOptions.secrets) {
1551
1792
  BASIC_AUTH_PASSWORD_RE.lastIndex = 0;
@@ -1595,13 +1836,17 @@ var PIIManager = class {
1595
1836
  }
1596
1837
  }
1597
1838
  }
1598
- const kept = normalizeDetections(text, detections);
1839
+ const kept = normalizeDetections(
1840
+ text,
1841
+ detections.map((detection) => normalizeDetection(detection))
1842
+ );
1599
1843
  if (!kept.length) return { maskedText: text, mapping: {} };
1600
1844
  const counters = {};
1601
1845
  const mapping = {};
1602
1846
  const replacements = kept.map((d) => {
1603
- counters[d.type] = (counters[d.type] ?? 0) + 1;
1604
- const placeholder = `<${d.type}_${counters[d.type]}>`;
1847
+ const placeholderType = toPlaceholderType(d.type);
1848
+ counters[placeholderType] = (counters[placeholderType] ?? 0) + 1;
1849
+ const placeholder = `<${placeholderType}_${counters[placeholderType]}>`;
1605
1850
  mapping[placeholder] = d.text;
1606
1851
  return { ...d, placeholder };
1607
1852
  });
@@ -1707,7 +1952,6 @@ var MAX_ANALYSIS_WINDOW = 8192;
1707
1952
  var WINDOW_SLICE_SIZE = 4e3;
1708
1953
  var WORD_BOUNDARY_SCAN = 120;
1709
1954
  var AI_TIMEOUT_MS = 2e3;
1710
- var TELEMETRY_SNIPPET_LIMIT = 4e3;
1711
1955
  var AI_OPENAI_MODEL = "gpt-4o-mini";
1712
1956
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
1713
1957
  var EN_STOPWORDS = /* @__PURE__ */ new Set([
@@ -1892,143 +2136,6 @@ function getOpenAiApiKey() {
1892
2136
  }
1893
2137
  return key.trim();
1894
2138
  }
1895
- async function sha256Hex(text) {
1896
- const data = new TextEncoder().encode(text ?? "");
1897
- const subtle = globalThis.crypto?.subtle;
1898
- if (subtle?.digest) {
1899
- const buf = await subtle.digest("SHA-256", data);
1900
- return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("");
1901
- }
1902
- return sha256HexFallback(data);
1903
- }
1904
- function sha256HexFallback(data) {
1905
- const K = [
1906
- 1116352408,
1907
- 1899447441,
1908
- 3049323471,
1909
- 3921009573,
1910
- 961987163,
1911
- 1508970993,
1912
- 2453635748,
1913
- 2870763221,
1914
- 3624381080,
1915
- 310598401,
1916
- 607225278,
1917
- 1426881987,
1918
- 1925078388,
1919
- 2162078206,
1920
- 2614888103,
1921
- 3248222580,
1922
- 3835390401,
1923
- 4022224774,
1924
- 264347078,
1925
- 604807628,
1926
- 770255983,
1927
- 1249150122,
1928
- 1555081692,
1929
- 1996064986,
1930
- 2554220882,
1931
- 2821834349,
1932
- 2952996808,
1933
- 3210313671,
1934
- 3336571891,
1935
- 3584528711,
1936
- 113926993,
1937
- 338241895,
1938
- 666307205,
1939
- 773529912,
1940
- 1294757372,
1941
- 1396182291,
1942
- 1695183700,
1943
- 1986661051,
1944
- 2177026350,
1945
- 2456956037,
1946
- 2730485921,
1947
- 2820302411,
1948
- 3259730800,
1949
- 3345764771,
1950
- 3516065817,
1951
- 3600352804,
1952
- 4094571909,
1953
- 275423344,
1954
- 430227734,
1955
- 506948616,
1956
- 659060556,
1957
- 883997877,
1958
- 958139571,
1959
- 1322822218,
1960
- 1537002063,
1961
- 1747873779,
1962
- 1955562222,
1963
- 2024104815,
1964
- 2227730452,
1965
- 2361852424,
1966
- 2428436474,
1967
- 2756734187,
1968
- 3204031479,
1969
- 3329325298
1970
- ];
1971
- const H = [
1972
- 1779033703,
1973
- 3144134277,
1974
- 1013904242,
1975
- 2773480762,
1976
- 1359893119,
1977
- 2600822924,
1978
- 528734635,
1979
- 1541459225
1980
- ];
1981
- const length = data.length;
1982
- const bitLengthHi = Math.floor(length * 8 / 4294967296);
1983
- const bitLengthLo = length * 8 >>> 0;
1984
- const paddedLength = length + 9 + 63 >> 6 << 6 >>> 0;
1985
- const padded = new Uint8Array(paddedLength);
1986
- padded.set(data);
1987
- padded[length] = 128;
1988
- const view = new DataView(padded.buffer);
1989
- view.setUint32(paddedLength - 8, bitLengthHi, false);
1990
- view.setUint32(paddedLength - 4, bitLengthLo, false);
1991
- const w = new Uint32Array(64);
1992
- for (let offset = 0; offset < paddedLength; offset += 64) {
1993
- for (let i = 0; i < 16; i += 1) {
1994
- w[i] = view.getUint32(offset + i * 4, false);
1995
- }
1996
- for (let i = 16; i < 64; i += 1) {
1997
- const s0 = rightRotate(w[i - 15], 7) ^ rightRotate(w[i - 15], 18) ^ w[i - 15] >>> 3;
1998
- const s1 = rightRotate(w[i - 2], 17) ^ rightRotate(w[i - 2], 19) ^ w[i - 2] >>> 10;
1999
- w[i] = (w[i - 16] + s0 >>> 0) + (w[i - 7] + s1 >>> 0) >>> 0;
2000
- }
2001
- let [a, b, c, d, e, f, g, h] = H;
2002
- for (let i = 0; i < 64; i += 1) {
2003
- const S1 = rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25);
2004
- const ch = e & f ^ ~e & g;
2005
- const temp1 = ((h + S1 >>> 0) + (ch + K[i] >>> 0) >>> 0) + w[i] >>> 0;
2006
- const S0 = rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22);
2007
- const maj = a & b ^ a & c ^ b & c;
2008
- const temp2 = S0 + maj >>> 0;
2009
- h = g;
2010
- g = f;
2011
- f = e;
2012
- e = d + temp1 >>> 0;
2013
- d = c;
2014
- c = b;
2015
- b = a;
2016
- a = temp1 + temp2 >>> 0;
2017
- }
2018
- H[0] = H[0] + a >>> 0;
2019
- H[1] = H[1] + b >>> 0;
2020
- H[2] = H[2] + c >>> 0;
2021
- H[3] = H[3] + d >>> 0;
2022
- H[4] = H[4] + e >>> 0;
2023
- H[5] = H[5] + f >>> 0;
2024
- H[6] = H[6] + g >>> 0;
2025
- H[7] = H[7] + h >>> 0;
2026
- }
2027
- return H.map((value) => value.toString(16).padStart(8, "0")).join("");
2028
- }
2029
- function rightRotate(value, shift) {
2030
- return value >>> shift | value << 32 - shift;
2031
- }
2032
2139
  function safeJsonParse(raw) {
2033
2140
  try {
2034
2141
  return JSON.parse(raw);
@@ -2104,22 +2211,11 @@ async function runAICheck(anonymizedWindow) {
2104
2211
  clearTimeout(timeout);
2105
2212
  }
2106
2213
  }
2107
- function truncateSnippet(value) {
2108
- if (!value) {
2109
- return "";
2110
- }
2111
- if (value.length <= TELEMETRY_SNIPPET_LIMIT) {
2112
- return value;
2113
- }
2114
- return value.slice(0, TELEMETRY_SNIPPET_LIMIT);
2115
- }
2116
2214
  async function reportSecurityEvent(options) {
2117
2215
  if (typeof fetch !== "function") {
2118
2216
  return;
2119
2217
  }
2120
- const snippet = truncateSnippet(options.snippet);
2121
- const snippetHash = snippet ? await sha256Hex(snippet) : "";
2122
- const inputValue = options.storePii ? snippet : snippetHash;
2218
+ const inputValue = "[REDACTED]";
2123
2219
  const eventId = createEventId(options.eventId ?? options.clientEventId);
2124
2220
  const metadata = {
2125
2221
  ...options.telemetryMetadata ?? {},
@@ -2129,13 +2225,9 @@ async function reportSecurityEvent(options) {
2129
2225
  language: options.language,
2130
2226
  ai_scan_status: options.aiStatus ?? null,
2131
2227
  reason: options.reason ?? null,
2132
- client_event_id: eventId
2228
+ client_event_id: eventId,
2229
+ transformed_input: "[REDACTED]"
2133
2230
  };
2134
- if (options.storePii) {
2135
- metadata.snippet = snippet;
2136
- } else {
2137
- metadata.snippet_hash = snippetHash;
2138
- }
2139
2231
  const payload = {
2140
2232
  event_id: eventId,
2141
2233
  system_id: options.systemId,
@@ -2290,7 +2382,7 @@ function getInjectionScanner() {
2290
2382
 
2291
2383
  // src/sdk-version.ts
2292
2384
  var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
2293
- var AGENTID_SDK_VERSION_HEADER = "js-0.1.41".trim().length > 0 ? "js-0.1.41" : FALLBACK_SDK_VERSION;
2385
+ var AGENTID_SDK_VERSION_HEADER = "js-0.1.42".trim().length > 0 ? "js-0.1.42" : FALLBACK_SDK_VERSION;
2294
2386
 
2295
2387
  // src/local-security-enforcer.ts
2296
2388
  var DEFAULT_FAIL_OPEN_CONFIG = {
@@ -2824,8 +2916,8 @@ function isInfrastructureGuardReason(reason) {
2824
2916
  if (!reason) return false;
2825
2917
  return reason === "system_failure" || reason === "system_failure_db_unavailable" || reason === "logging_failed" || reason === "server_error" || reason === "guard_unreachable" || reason === "api_key_pepper_missing" || reason === "encryption_key_missing";
2826
2918
  }
2827
- function isGuardFailureEligibleForLocalFallback(reason) {
2828
- return reason === "network_error_strict_mode" || reason === "server_error" || isInfrastructureGuardReason(reason);
2919
+ function isFailOpenGuardBypassReason(reason) {
2920
+ return reason === "timeout_fallback" || reason === "guard_unreachable" || reason === "system_failure_fail_open";
2829
2921
  }
2830
2922
  function isFailCloseIngestReason(reason) {
2831
2923
  if (!reason) return false;
@@ -2860,6 +2952,14 @@ function sanitizeIngestText(value) {
2860
2952
  const text = typeof value === "string" ? value : String(value ?? "");
2861
2953
  return text.slice(0, MAX_INGEST_TEXT_CHARS);
2862
2954
  }
2955
+ function getZeroRetentionInput(rawInput, candidateInput) {
2956
+ const raw = typeof rawInput === "string" ? rawInput : "";
2957
+ const candidate = typeof candidateInput === "string" ? candidateInput : "";
2958
+ if (candidate.length > 0 && candidate !== raw) {
2959
+ return candidate;
2960
+ }
2961
+ return "[REDACTED]";
2962
+ }
2863
2963
  function normalizeExpectedLanguages(value) {
2864
2964
  if (!Array.isArray(value)) {
2865
2965
  return void 0;
@@ -3535,6 +3635,29 @@ function textContainsMappingPlaceholder(text, mapping) {
3535
3635
  }
3536
3636
  return Object.keys(mapping).some((placeholder) => placeholder.length > 0 && text.includes(placeholder));
3537
3637
  }
3638
+ function isSecretPlaceholder(placeholder) {
3639
+ const normalized = placeholder.replace(/[<>]/g, "").replace(/_\d+$/u, "").toUpperCase();
3640
+ return normalized.includes("PASSWORD") || normalized.includes("SECRET") || normalized.includes("TOKEN") || normalized.includes("API_KEY") || normalized.includes("CREDENTIAL") || normalized.includes("PRIVATE_KEY");
3641
+ }
3642
+ function getMaskingTelemetryFromMapping(mapping) {
3643
+ const placeholders = Object.keys(mapping ?? {}).filter((placeholder) => placeholder.length > 0);
3644
+ return {
3645
+ piiApplied: placeholders.some((placeholder) => !isSecretPlaceholder(placeholder)),
3646
+ secretApplied: placeholders.some(isSecretPlaceholder)
3647
+ };
3648
+ }
3649
+ function normalizePiiMapping(value) {
3650
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
3651
+ return void 0;
3652
+ }
3653
+ const entries = Object.entries(value).filter(
3654
+ ([placeholder, replacement]) => placeholder.length > 0 && typeof replacement === "string"
3655
+ );
3656
+ if (entries.length === 0) {
3657
+ return void 0;
3658
+ }
3659
+ return Object.fromEntries(entries);
3660
+ }
3538
3661
  var SecurityBlockError = class extends Error {
3539
3662
  constructor(reason = "guard_denied") {
3540
3663
  super(`AgentID: Security Blocked (${reason})`);
@@ -3612,16 +3735,18 @@ var AgentID = class {
3612
3735
  getEffectiveSecretMaskingForConfig(capabilityConfig) {
3613
3736
  return this.resolveEffectiveSecretMasking(capabilityConfig);
3614
3737
  }
3615
- buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig) {
3738
+ buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig, appliedMasking) {
3739
+ const piiMaskingEnabled = typeof appliedMasking?.piiApplied === "boolean" ? appliedMasking.piiApplied : this.resolveEffectivePiiMasking(
3740
+ capabilityConfig ?? this.getCachedCapabilityConfig()
3741
+ );
3742
+ const secretMaskingEnabled = typeof appliedMasking?.secretApplied === "boolean" ? appliedMasking.secretApplied : this.resolveEffectiveSecretMasking(
3743
+ capabilityConfig ?? this.getCachedCapabilityConfig()
3744
+ );
3616
3745
  return {
3617
3746
  capabilities: {
3618
3747
  has_feedback_handler: hasFeedbackHandler,
3619
- pii_masking_enabled: this.resolveEffectivePiiMasking(
3620
- capabilityConfig ?? this.getCachedCapabilityConfig()
3621
- ),
3622
- secret_masking_enabled: this.resolveEffectiveSecretMasking(
3623
- capabilityConfig ?? this.getCachedCapabilityConfig()
3624
- ),
3748
+ pii_masking_enabled: piiMaskingEnabled,
3749
+ secret_masking_enabled: secretMaskingEnabled,
3625
3750
  framework
3626
3751
  }
3627
3752
  };
@@ -3648,11 +3773,12 @@ var AgentID = class {
3648
3773
  return createEventId2();
3649
3774
  }
3650
3775
  buildGuardCacheKey(params, apiKey) {
3651
- if (!params.system_id || !params.input) {
3776
+ const cacheInputSource = typeof params.prompt_context === "string" && params.prompt_context.trim().length > 0 ? params.prompt_context : params.input;
3777
+ if (!params.system_id || !cacheInputSource) {
3652
3778
  return null;
3653
3779
  }
3654
3780
  const userId = params.user_id?.trim() ?? "";
3655
- const normalizedInput = params.input.trim().replace(/\s+/g, " ").slice(0, 2048);
3781
+ const normalizedInput = cacheInputSource.trim().replace(/\s+/g, " ").slice(0, 2048);
3656
3782
  const keyPrefix = apiKey?.slice(0, 24) ?? "";
3657
3783
  return `${keyPrefix}|${params.system_id}|${userId}|${normalizedInput.length}|${normalizedInput}`;
3658
3784
  }
@@ -3716,20 +3842,7 @@ var AgentID = class {
3716
3842
  return config.strict_security_mode || config.failure_mode === "fail_close";
3717
3843
  }
3718
3844
  buildFailOpenGuardVerdict(reason, input, options) {
3719
- const capabilityConfig = this.getCachedCapabilityConfig(options);
3720
- const shouldMaskPii = capabilityConfig.block_pii_leakage || this.resolveEffectivePiiMasking(capabilityConfig);
3721
- const shouldMaskSecrets = capabilityConfig.block_secret_leakage === true || this.resolveEffectiveSecretMasking(capabilityConfig);
3722
3845
  const response = { allowed: true, reason };
3723
- if (input && (shouldMaskPii || shouldMaskSecrets)) {
3724
- const masked = this.pii.anonymize(input, {
3725
- pii: shouldMaskPii,
3726
- secrets: shouldMaskSecrets
3727
- });
3728
- if (masked.maskedText !== input) {
3729
- response.transformed_input = masked.maskedText;
3730
- response.detected_pii = Object.keys(masked.mapping).length > 0;
3731
- }
3732
- }
3733
3846
  return response;
3734
3847
  }
3735
3848
  maybeRaiseStrictIngestDependencyError(params) {
@@ -3758,6 +3871,43 @@ var AgentID = class {
3758
3871
  }
3759
3872
  return config.block_on_heuristic;
3760
3873
  }
3874
+ buildInlineAttachmentPromptScanInput(attachments, maxChars = 6e3) {
3875
+ if (!Array.isArray(attachments) || attachments.length === 0) {
3876
+ return "";
3877
+ }
3878
+ const text = attachments.slice(0, 4).map((attachment) => {
3879
+ const attachmentText = typeof attachment?.text === "string" ? attachment.text.trim() : "";
3880
+ if (!attachmentText) {
3881
+ return "";
3882
+ }
3883
+ const filename = typeof attachment.filename === "string" && attachment.filename.trim().length > 0 ? attachment.filename.trim() : "attachment";
3884
+ return `[Attachment: ${filename}]
3885
+ ${attachmentText}`;
3886
+ }).filter(Boolean).join("\n\n");
3887
+ if (!text || text.length <= maxChars) {
3888
+ return text;
3889
+ }
3890
+ const headBudget = Math.max(256, Math.floor(maxChars * 0.55));
3891
+ const tailBudget = Math.max(128, maxChars - headBudget - 16);
3892
+ return `${text.slice(0, headBudget)}
3893
+
3894
+ [...]
3895
+
3896
+ ${text.slice(-tailBudget)}`;
3897
+ }
3898
+ buildPromptInjectionScanInput(params) {
3899
+ const source = typeof params.promptContext === "string" && params.promptContext.trim().length > 0 ? params.promptContext : params.input;
3900
+ const attachmentInput = this.buildInlineAttachmentPromptScanInput(params.attachments);
3901
+ if (!source) {
3902
+ return attachmentInput;
3903
+ }
3904
+ if (!attachmentInput) {
3905
+ return source;
3906
+ }
3907
+ return `${source}
3908
+
3909
+ ${attachmentInput}`;
3910
+ }
3761
3911
  async refreshCapabilityConfigBeforeClientControl(params) {
3762
3912
  const refreshed = await this.getCapabilityConfigWithTelemetry(true, params.options);
3763
3913
  return {
@@ -3767,9 +3917,14 @@ var AgentID = class {
3767
3917
  }
3768
3918
  async applyLocalPolicyChecks(params) {
3769
3919
  const localScanStartedAt = Date.now();
3770
- if (params.runPromptInjectionCheck && params.input && this.shouldRunLocalInjectionScan(params.capabilityConfig)) {
3920
+ const promptScanInput = this.buildPromptInjectionScanInput({
3921
+ input: params.input,
3922
+ promptContext: params.promptContext,
3923
+ capabilityConfig: params.capabilityConfig
3924
+ });
3925
+ if (params.runPromptInjectionCheck && promptScanInput && this.shouldRunLocalInjectionScan(params.capabilityConfig)) {
3771
3926
  await this.injectionScanner.scan({
3772
- prompt: params.input,
3927
+ prompt: promptScanInput,
3773
3928
  apiKey: params.apiKey,
3774
3929
  baseUrl: this.baseUrl,
3775
3930
  aiScanEnabled: this.aiScanEnabled,
@@ -3796,6 +3951,9 @@ var AgentID = class {
3796
3951
  });
3797
3952
  const sdkLocalScanMs = Math.max(0, Date.now() - localScanStartedAt);
3798
3953
  for (const event of enforced.events) {
3954
+ if (event.violationType === "PII_LEAKAGE_STRICT" && event.actionTaken === "REDACTED") {
3955
+ continue;
3956
+ }
3799
3957
  this.logSecurityPolicyViolation({
3800
3958
  systemId: params.systemId,
3801
3959
  violationType: event.violationType,
@@ -3807,7 +3965,9 @@ var AgentID = class {
3807
3965
  });
3808
3966
  }
3809
3967
  return {
3810
- sanitizedInput: enforced.sanitizedInput,
3968
+ sanitizedInput: enforced.events.some(
3969
+ (event) => event.violationType === "PII_LEAKAGE_STRICT" && event.actionTaken === "REDACTED"
3970
+ ) ? params.input : enforced.sanitizedInput,
3811
3971
  sdkLocalScanMs
3812
3972
  };
3813
3973
  } catch (error) {
@@ -3843,22 +4003,6 @@ var AgentID = class {
3843
4003
  sdkConfigFetchMs = refreshed.sdkConfigFetchMs;
3844
4004
  }
3845
4005
  if (!this.clientFastFail) {
3846
- const effectivePiiMasking2 = this.resolveEffectivePiiMasking(capabilityConfig);
3847
- const effectiveSecretMasking2 = this.resolveEffectiveSecretMasking(capabilityConfig);
3848
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2 || !capabilityConfig.block_secret_leakage && effectiveSecretMasking2) {
3849
- const masked = this.pii.anonymize(sanitizedInput, {
3850
- pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking2,
3851
- secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking2
3852
- });
3853
- return {
3854
- sanitizedInput: masked.maskedText,
3855
- capabilityConfig,
3856
- sdkConfigFetchMs,
3857
- sdkLocalScanMs,
3858
- piiMapping: masked.mapping,
3859
- shouldDeanonymize: Object.keys(masked.mapping).length > 0
3860
- };
3861
- }
3862
4006
  return {
3863
4007
  sanitizedInput,
3864
4008
  capabilityConfig,
@@ -3875,6 +4019,7 @@ var AgentID = class {
3875
4019
  sdkConfigFetchMs = refreshedConfig.sdkConfigFetchMs;
3876
4020
  const enforced = await this.applyLocalPolicyChecks({
3877
4021
  input: params.input,
4022
+ promptContext: params.promptContext,
3878
4023
  systemId: params.systemId,
3879
4024
  stream: params.stream,
3880
4025
  capabilityConfig,
@@ -3886,22 +4031,6 @@ var AgentID = class {
3886
4031
  });
3887
4032
  sanitizedInput = enforced.sanitizedInput;
3888
4033
  sdkLocalScanMs = enforced.sdkLocalScanMs;
3889
- const effectivePiiMasking = this.resolveEffectivePiiMasking(capabilityConfig);
3890
- const effectiveSecretMasking = this.resolveEffectiveSecretMasking(capabilityConfig);
3891
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking || !capabilityConfig.block_secret_leakage && effectiveSecretMasking) {
3892
- const masked = this.pii.anonymize(sanitizedInput, {
3893
- pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking,
3894
- secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking
3895
- });
3896
- return {
3897
- sanitizedInput: masked.maskedText,
3898
- capabilityConfig,
3899
- sdkConfigFetchMs,
3900
- sdkLocalScanMs,
3901
- piiMapping: masked.mapping,
3902
- shouldDeanonymize: Object.keys(masked.mapping).length > 0
3903
- };
3904
- }
3905
4034
  return {
3906
4035
  sanitizedInput,
3907
4036
  capabilityConfig,
@@ -3922,6 +4051,7 @@ var AgentID = class {
3922
4051
  });
3923
4052
  const enforced = await this.applyLocalPolicyChecks({
3924
4053
  input: params.input,
4054
+ promptContext: params.promptContext,
3925
4055
  systemId: params.systemId,
3926
4056
  stream: params.stream,
3927
4057
  capabilityConfig: refreshedConfig.capabilityConfig,
@@ -3938,77 +4068,71 @@ var AgentID = class {
3938
4068
  sdkLocalScanMs: enforced.sdkLocalScanMs
3939
4069
  };
3940
4070
  }
4071
+ async runLocalPromptInjectionFallback(params, options) {
4072
+ const effectiveApiKey = this.resolveApiKey(options?.apiKey);
4073
+ const resolvedConfig = params.capabilityConfig && typeof params.sdkConfigFetchMs === "number" ? {
4074
+ capabilityConfig: params.capabilityConfig,
4075
+ sdkConfigFetchMs: params.sdkConfigFetchMs
4076
+ } : await this.getCapabilityConfigWithTelemetry(false, options);
4077
+ const refreshedConfig = await this.refreshCapabilityConfigBeforeClientControl({
4078
+ capabilityConfig: resolvedConfig.capabilityConfig,
4079
+ sdkConfigFetchMs: resolvedConfig.sdkConfigFetchMs,
4080
+ options
4081
+ });
4082
+ const localScanStartedAt = Date.now();
4083
+ const promptScanInput = this.buildPromptInjectionScanInput({
4084
+ input: params.input,
4085
+ promptContext: params.promptContext,
4086
+ capabilityConfig: refreshedConfig.capabilityConfig,
4087
+ attachments: params.attachments
4088
+ });
4089
+ if (promptScanInput && this.shouldRunLocalInjectionScan(refreshedConfig.capabilityConfig)) {
4090
+ await this.injectionScanner.scan({
4091
+ prompt: promptScanInput,
4092
+ apiKey: effectiveApiKey,
4093
+ baseUrl: this.baseUrl,
4094
+ aiScanEnabled: this.aiScanEnabled,
4095
+ storePii: this.storePii,
4096
+ piiManager: this.pii,
4097
+ source: "js_sdk",
4098
+ systemId: params.systemId,
4099
+ eventId: params.clientEventId,
4100
+ clientEventId: params.clientEventId,
4101
+ telemetryMetadata: mergeTelemetryContexts(
4102
+ params.telemetryMetadata,
4103
+ buildSdkTimingMetadata({
4104
+ sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
4105
+ sdkConfigVersion: refreshedConfig.capabilityConfig.version
4106
+ })
4107
+ )
4108
+ });
4109
+ }
4110
+ return {
4111
+ capabilityConfig: refreshedConfig.capabilityConfig,
4112
+ sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
4113
+ sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
4114
+ };
4115
+ }
3941
4116
  async scanPromptInjection(input, options) {
3942
4117
  if (!input) {
3943
4118
  return;
3944
4119
  }
3945
- const initialConfig = await this.getCapabilityConfigWithTelemetry(
3946
- false,
4120
+ await this.runLocalPromptInjectionFallback(
4121
+ {
4122
+ input,
4123
+ attachments: options?.attachments,
4124
+ systemId: options?.systemId,
4125
+ clientEventId: options?.clientEventId
4126
+ },
3947
4127
  options
3948
4128
  );
3949
- const refreshedConfig = await this.refreshCapabilityConfigBeforeClientControl({
3950
- capabilityConfig: initialConfig.capabilityConfig,
3951
- sdkConfigFetchMs: initialConfig.sdkConfigFetchMs,
3952
- options
3953
- });
3954
- if (!this.shouldRunLocalInjectionScan(refreshedConfig.capabilityConfig)) {
3955
- return;
3956
- }
3957
- const effectiveApiKey = this.resolveApiKey(options?.apiKey);
3958
- await this.injectionScanner.scan({
3959
- prompt: input,
3960
- apiKey: effectiveApiKey,
3961
- baseUrl: this.baseUrl,
3962
- aiScanEnabled: this.aiScanEnabled,
3963
- storePii: this.storePii,
3964
- piiManager: this.pii,
3965
- source: "js_sdk",
3966
- systemId: options?.systemId,
3967
- eventId: options?.clientEventId,
3968
- clientEventId: options?.clientEventId,
3969
- telemetryMetadata: buildSdkTimingMetadata({
3970
- sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
3971
- sdkConfigVersion: refreshedConfig.capabilityConfig.version
3972
- })
3973
- });
3974
4129
  }
3975
- withMaskedOpenAIRequest(req, maskedText, options) {
4130
+ withMaskedOpenAIRequest(req, maskedText) {
3976
4131
  const messages = Array.isArray(req?.messages) ? req.messages : null;
3977
4132
  if (!messages) {
3978
4133
  return req;
3979
4134
  }
3980
- const newMessages = messages.map((message2) => {
3981
- if (!message2 || typeof message2 !== "object") {
3982
- return message2;
3983
- }
3984
- const typedMessage = message2;
3985
- const currentContent2 = typedMessage.content;
3986
- if (typeof currentContent2 === "string") {
3987
- return {
3988
- ...typedMessage,
3989
- content: this.pii.anonymize(currentContent2, options).maskedText
3990
- };
3991
- }
3992
- if (Array.isArray(currentContent2)) {
3993
- return {
3994
- ...typedMessage,
3995
- content: currentContent2.map((part) => {
3996
- if (!part || typeof part !== "object") {
3997
- return part;
3998
- }
3999
- const typedPart = part;
4000
- if (typeof typedPart.text !== "string") {
4001
- return part;
4002
- }
4003
- return {
4004
- ...typedPart,
4005
- text: this.pii.anonymize(typedPart.text, options).maskedText
4006
- };
4007
- })
4008
- };
4009
- }
4010
- return message2;
4011
- });
4135
+ const newMessages = messages.map((message2) => message2);
4012
4136
  let lastUserIdx = null;
4013
4137
  for (let i = 0; i < newMessages.length; i += 1) {
4014
4138
  const msg = newMessages[i];
@@ -4042,7 +4166,7 @@ var AgentID = class {
4042
4166
  text: maskedText
4043
4167
  });
4044
4168
  }
4045
- nextContent = textReplaced ? preservedParts : [{ type: "text", text: maskedText }, ...currentContent];
4169
+ nextContent = textReplaced ? preservedParts : maskedText.length > 0 ? [{ type: "text", text: maskedText }, ...currentContent] : currentContent;
4046
4170
  }
4047
4171
  newMessages[lastUserIdx] = {
4048
4172
  ...message,
@@ -4059,7 +4183,7 @@ var AgentID = class {
4059
4183
  logSecurityPolicyViolation(params) {
4060
4184
  this.log({
4061
4185
  system_id: params.systemId,
4062
- input: "[REDACTED_SAMPLE]",
4186
+ input: "[REDACTED]",
4063
4187
  output: "",
4064
4188
  model: "agentid.policy.enforcer",
4065
4189
  event_type: "security_policy_violation",
@@ -4070,7 +4194,7 @@ var AgentID = class {
4070
4194
  severity: "high",
4071
4195
  system_id: params.systemId,
4072
4196
  violation_type: params.violationType,
4073
- input_snippet: "[REDACTED_SAMPLE]",
4197
+ input_snippet: "[REDACTED]",
4074
4198
  action_taken: params.actionTaken,
4075
4199
  ...buildSdkTimingMetadata({
4076
4200
  sdkConfigFetchMs: params.sdkConfigFetchMs,
@@ -4083,17 +4207,19 @@ var AgentID = class {
4083
4207
  }, { apiKey: params.apiKey });
4084
4208
  }
4085
4209
  logGuardFallback(params) {
4210
+ const retainedInput = getZeroRetentionInput(params.guardParams.input, void 0);
4086
4211
  this.log(
4087
4212
  {
4088
4213
  system_id: params.guardParams.system_id,
4089
4214
  user_id: params.guardParams.user_id,
4090
- input: params.guardParams.input,
4215
+ input: retainedInput,
4091
4216
  output: "",
4092
4217
  model: params.guardParams.model ?? "unknown",
4093
4218
  event_type: "security_alert",
4094
4219
  severity: "warning",
4095
4220
  metadata: {
4096
4221
  ...params.guardParams.metadata ?? {},
4222
+ transformed_input: retainedInput,
4097
4223
  source: "guard",
4098
4224
  status: params.status,
4099
4225
  guard_reason: params.reason,
@@ -4587,11 +4713,12 @@ var AgentID = class {
4587
4713
  completion,
4588
4714
  options?.piiMapping
4589
4715
  );
4716
+ const transformedOutput = options?.deanonymizeForClient === true && options.piiMapping ? this.pii.deanonymize(completion, options.piiMapping) : masked.maskedText;
4590
4717
  return {
4591
4718
  mode: "static",
4592
4719
  rawOutput: completion,
4593
- transformedOutput: masked.maskedText,
4594
- outputMasked: masked.maskedText !== completion || placeholderOutputMasked
4720
+ transformedOutput,
4721
+ outputMasked: transformedOutput !== completion || placeholderOutputMasked
4595
4722
  };
4596
4723
  }
4597
4724
  if (!isAsyncIterable(completion)) {
@@ -4601,11 +4728,12 @@ var AgentID = class {
4601
4728
  asText,
4602
4729
  options?.piiMapping
4603
4730
  );
4731
+ const transformedOutput = options?.deanonymizeForClient === true && options.piiMapping ? this.pii.deanonymize(asText, options.piiMapping) : masked.maskedText;
4604
4732
  return {
4605
4733
  mode: "static",
4606
4734
  rawOutput: asText,
4607
- transformedOutput: masked.maskedText,
4608
- outputMasked: masked.maskedText !== asText || placeholderOutputMasked
4735
+ transformedOutput,
4736
+ outputMasked: transformedOutput !== asText || placeholderOutputMasked
4609
4737
  };
4610
4738
  }
4611
4739
  const source = completion;
@@ -4800,6 +4928,7 @@ var AgentID = class {
4800
4928
  */
4801
4929
  wrapOpenAI(openai, options) {
4802
4930
  const systemId = options.system_id;
4931
+ const deanonymizeOutputForClient = options.deanonymizeOutputForClient === true || options.deanonymize_output_for_client === true;
4803
4932
  const expectedLanguages = normalizeExpectedLanguages(
4804
4933
  options.expected_languages ?? options.expectedLanguages
4805
4934
  );
@@ -4840,38 +4969,48 @@ var AgentID = class {
4840
4969
  const stream = adapter.isStream(providerReq);
4841
4970
  let capabilityConfig = this.getCachedCapabilityConfig(requestOptions);
4842
4971
  const userText = adapter.extractInput(providerReq);
4843
- const requestAttachments = adapter.extractAttachments(providerReq);
4972
+ const rawPromptContext = adapter.extractPromptContext(providerReq);
4973
+ let requestAttachments = adapter.extractAttachments(providerReq);
4844
4974
  const hasGuardContent = userText !== null || requestAttachments.length > 0;
4845
4975
  let maskedText = userText ?? "";
4846
4976
  let maskedReq = providerReq;
4847
4977
  let createArgs = providerReq === rawReq ? normalizedCreateArgs : [{ ...providerReq }, ...normalizedCreateArgs.slice(1)];
4848
4978
  let mapping = {};
4979
+ let clientInputMaskingTelemetry = {
4980
+ piiApplied: false,
4981
+ secretApplied: false
4982
+ };
4849
4983
  let sdkConfigFetchMs = 0;
4850
4984
  let sdkLocalScanMs = 0;
4851
- let providerMaskingOptions;
4852
4985
  if (hasGuardContent) {
4853
4986
  const prepared = await this.prepareInputForDispatch({
4854
4987
  input: userText ?? "",
4988
+ promptContext: rawPromptContext ?? void 0,
4855
4989
  systemId,
4856
4990
  stream,
4857
4991
  clientEventId,
4858
4992
  telemetryMetadata
4859
4993
  }, requestOptions);
4860
4994
  capabilityConfig = prepared.capabilityConfig;
4861
- providerMaskingOptions = {
4862
- pii: !capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig),
4863
- secrets: !capabilityConfig.block_secret_leakage && this.resolveEffectiveSecretMasking(capabilityConfig)
4864
- };
4865
4995
  maskedText = prepared.sanitizedInput;
4866
- mapping = prepared.piiMapping ?? {};
4996
+ const preparedPiiMapping = normalizePiiMapping(prepared.piiMapping);
4997
+ const preparedMaskingTelemetry = getMaskingTelemetryFromMapping(
4998
+ preparedPiiMapping
4999
+ );
5000
+ clientInputMaskingTelemetry = {
5001
+ piiApplied: preparedMaskingTelemetry.piiApplied || maskedText !== (userText ?? ""),
5002
+ secretApplied: preparedMaskingTelemetry.secretApplied
5003
+ };
5004
+ mapping = preparedPiiMapping ?? {};
4867
5005
  sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
4868
5006
  sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
4869
- if (maskedText !== (userText ?? "")) {
5007
+ const shouldProtectRequestHistory = maskedText !== (userText ?? "");
5008
+ if (shouldProtectRequestHistory) {
4870
5009
  maskedReq = this.withMaskedOpenAIRequest(
4871
5010
  providerReq,
4872
- maskedText,
4873
- providerMaskingOptions
5011
+ maskedText
4874
5012
  );
5013
+ requestAttachments = adapter.extractAttachments(maskedReq);
4875
5014
  const nextCreateArgs = [...createArgs];
4876
5015
  nextCreateArgs[0] = maskedReq;
4877
5016
  createArgs = nextCreateArgs;
@@ -4882,8 +5021,16 @@ var AgentID = class {
4882
5021
  "AgentID: No user message or supported inline attachment found. Security guard requires prompt content."
4883
5022
  );
4884
5023
  }
5024
+ const promptContextForGuard = adapter.extractPromptContext(maskedReq) ?? rawPromptContext ?? void 0;
5025
+ const clientCapabilities = this.buildClientCapabilities(
5026
+ "openai",
5027
+ false,
5028
+ capabilityConfig,
5029
+ clientInputMaskingTelemetry
5030
+ );
4885
5031
  const verdict = await this.guard({
4886
5032
  input: maskedText,
5033
+ prompt_context: promptContextForGuard,
4887
5034
  system_id: systemId,
4888
5035
  model: adapter.getModelName(maskedReq),
4889
5036
  user_id: options.user_id,
@@ -4892,63 +5039,54 @@ var AgentID = class {
4892
5039
  request_identity: options.request_identity,
4893
5040
  metadata: telemetryMetadata,
4894
5041
  attachments: requestAttachments,
4895
- client_capabilities: this.buildClientCapabilities(
4896
- "openai",
4897
- false,
4898
- capabilityConfig
4899
- )
5042
+ client_capabilities: clientCapabilities
4900
5043
  }, requestOptions);
4901
5044
  let localFallbackApplied = false;
4902
5045
  let localFallbackReason = null;
4903
5046
  if (!verdict.allowed) {
4904
- if (effectiveStrictMode && isGuardFailureEligibleForLocalFallback(verdict.reason)) {
4905
- localFallbackApplied = true;
4906
- localFallbackReason = verdict.reason ?? "guard_unreachable";
4907
- if (sdkLocalScanMs === 0) {
4908
- const fallback = await this.applyLocalPolicyChecks({
4909
- input: maskedText,
4910
- systemId,
4911
- stream,
4912
- capabilityConfig,
4913
- apiKey: effectiveApiKey,
4914
- clientEventId,
4915
- sdkConfigFetchMs,
4916
- telemetryMetadata,
4917
- runPromptInjectionCheck: true
4918
- });
4919
- maskedText = fallback.sanitizedInput;
4920
- sdkLocalScanMs = fallback.sdkLocalScanMs;
4921
- }
4922
- } else {
4923
- await this.logPromptPreflightStep(
4924
- {
4925
- system_id: systemId,
4926
- user_id: options.user_id,
4927
- request_identity: options.request_identity,
4928
- input: maskedText,
4929
- telemetry: telemetryMetadata,
4930
- verdict,
4931
- guard_event_id: verdict.guard_event_id ?? null,
4932
- 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),
4933
- preflight_for_client_event_id: typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId,
4934
- client_capabilities: this.buildClientCapabilities(
4935
- "openai",
4936
- false,
4937
- capabilityConfig
4938
- ),
4939
- runtime_surface: "openai_sdk_guard"
4940
- },
4941
- requestOptions
4942
- );
4943
- throw new SecurityBlockError(verdict.reason ?? "guard_denied");
4944
- }
5047
+ await this.logPromptPreflightStep(
5048
+ {
5049
+ system_id: systemId,
5050
+ user_id: options.user_id,
5051
+ request_identity: options.request_identity,
5052
+ input: getZeroRetentionInput(userText ?? "", maskedText),
5053
+ telemetry: telemetryMetadata,
5054
+ verdict,
5055
+ guard_event_id: verdict.guard_event_id ?? null,
5056
+ 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),
5057
+ preflight_for_client_event_id: typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId,
5058
+ client_capabilities: clientCapabilities,
5059
+ runtime_surface: "openai_sdk_guard"
5060
+ },
5061
+ requestOptions
5062
+ );
5063
+ throw new SecurityBlockError(verdict.reason ?? "guard_denied");
5064
+ }
5065
+ if (isFailOpenGuardBypassReason(verdict.reason)) {
5066
+ const fallback = await this.runLocalPromptInjectionFallback(
5067
+ {
5068
+ input: userText ?? "",
5069
+ promptContext: rawPromptContext ?? void 0,
5070
+ attachments: requestAttachments,
5071
+ systemId,
5072
+ clientEventId,
5073
+ capabilityConfig,
5074
+ sdkConfigFetchMs,
5075
+ telemetryMetadata
5076
+ },
5077
+ requestOptions
5078
+ );
5079
+ capabilityConfig = fallback.capabilityConfig;
5080
+ sdkConfigFetchMs = fallback.sdkConfigFetchMs;
5081
+ sdkLocalScanMs += fallback.sdkLocalScanMs;
5082
+ localFallbackApplied = true;
5083
+ localFallbackReason = verdict.reason ?? null;
4945
5084
  }
4946
5085
  const currentRequestInput = adapter.extractInput(maskedReq) ?? "";
4947
- if (maskedText !== currentRequestInput || providerMaskingOptions?.pii === true || providerMaskingOptions?.secrets === true) {
5086
+ if (maskedText !== currentRequestInput) {
4948
5087
  maskedReq = this.withMaskedOpenAIRequest(
4949
5088
  providerReq,
4950
- maskedText,
4951
- providerMaskingOptions
5089
+ maskedText
4952
5090
  );
4953
5091
  const nextCreateArgs = [...createArgs];
4954
5092
  nextCreateArgs[0] = maskedReq;
@@ -4971,29 +5109,29 @@ var AgentID = class {
4971
5109
  maskedText = transformedInput;
4972
5110
  maskedReq = this.withMaskedOpenAIRequest(
4973
5111
  providerReq,
4974
- transformedInput,
4975
- providerMaskingOptions
5112
+ transformedInput
4976
5113
  );
4977
5114
  const nextCreateArgs = [...createArgs];
4978
5115
  nextCreateArgs[0] = maskedReq;
4979
5116
  createArgs = nextCreateArgs;
4980
5117
  }
5118
+ const shouldDeanonymizeForClient = deanonymizeOutputForClient && !isShadowMode && Object.keys(mapping).length > 0;
5119
+ const retainedInputForLogs = getZeroRetentionInput(
5120
+ userText ?? "",
5121
+ maskedText
5122
+ );
4981
5123
  await this.logPromptPreflightStep(
4982
5124
  {
4983
5125
  system_id: systemId,
4984
5126
  user_id: options.user_id,
4985
5127
  request_identity: options.request_identity,
4986
- input: maskedText,
5128
+ input: retainedInputForLogs,
4987
5129
  telemetry: telemetryMetadata,
4988
5130
  verdict,
4989
5131
  guard_event_id: guardEventId,
4990
5132
  guard_latency_ms: guardLatencyMs,
4991
5133
  preflight_for_client_event_id: canonicalClientEventId,
4992
- client_capabilities: this.buildClientCapabilities(
4993
- "openai",
4994
- false,
4995
- capabilityConfig
4996
- ),
5134
+ client_capabilities: clientCapabilities,
4997
5135
  local_fallback_applied: localFallbackApplied,
4998
5136
  local_fallback_reason: localFallbackReason,
4999
5137
  runtime_surface: "openai_sdk_guard"
@@ -5011,12 +5149,13 @@ var AgentID = class {
5011
5149
  })(),
5012
5150
  {
5013
5151
  piiMapping: mapping,
5014
- deanonymizeForClient: false,
5015
- maskForClient: !isShadowMode
5152
+ deanonymizeForClient: shouldDeanonymizeForClient,
5153
+ maskForClient: !isShadowMode && !shouldDeanonymizeForClient
5016
5154
  }
5017
5155
  );
5018
5156
  if (maskedText && wrappedCompletion.mode === "stream") {
5019
5157
  void wrappedCompletion.done.then(async (result) => {
5158
+ const effectiveInputMaskingTelemetry = getMaskingTelemetryFromMapping(mapping);
5020
5159
  const modelLatencyMs2 = Math.max(0, Date.now() - modelStartedAt2);
5021
5160
  const totalPipelineLatencyMs2 = Math.max(0, Date.now() - pipelineStartedAt);
5022
5161
  const outputForLog = result.transformedOutput;
@@ -5025,7 +5164,7 @@ var AgentID = class {
5025
5164
  system_id: systemId,
5026
5165
  user_id: options.user_id,
5027
5166
  request_identity: options.request_identity,
5028
- input: maskedText,
5167
+ input: retainedInputForLogs,
5029
5168
  output: outputForLog,
5030
5169
  model: adapter.getModelName(maskedReq),
5031
5170
  usage: result.usage,
@@ -5034,9 +5173,17 @@ var AgentID = class {
5034
5173
  metadata: mergeTelemetryContexts(
5035
5174
  telemetryMetadata,
5036
5175
  {
5037
- transformed_input: maskedText,
5176
+ transformed_input: retainedInputForLogs,
5038
5177
  transformed_output: result.transformedOutput,
5039
5178
  output_masked: result.outputMasked,
5179
+ client_side_pii_masking_applied: clientInputMaskingTelemetry.piiApplied,
5180
+ client_side_secret_masking_applied: clientInputMaskingTelemetry.secretApplied,
5181
+ server_side_pii_masking_applied: effectiveInputMaskingTelemetry.piiApplied && !clientInputMaskingTelemetry.piiApplied,
5182
+ server_side_secret_masking_applied: effectiveInputMaskingTelemetry.secretApplied && !clientInputMaskingTelemetry.secretApplied,
5183
+ effective_pii_masking_applied: effectiveInputMaskingTelemetry.piiApplied,
5184
+ effective_secret_masking_applied: effectiveInputMaskingTelemetry.secretApplied,
5185
+ effective_input_was_transformed: retainedInputForLogs !== "[REDACTED]",
5186
+ effective_output_was_transformed: result.outputMasked,
5040
5187
  shadow_mode: isShadowMode,
5041
5188
  simulated_decision: verdict.simulated_decision ?? null,
5042
5189
  simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
@@ -5057,11 +5204,7 @@ var AgentID = class {
5057
5204
  sdkConfigVersion: capabilityConfig.version
5058
5205
  })
5059
5206
  ),
5060
- client_capabilities: this.buildClientCapabilities(
5061
- "openai",
5062
- false,
5063
- capabilityConfig
5064
- )
5207
+ client_capabilities: clientCapabilities
5065
5208
  }, requestOptions);
5066
5209
  if (!ingestResult.ok) {
5067
5210
  this.maybeRaiseStrictIngestDependencyError({
@@ -5086,6 +5229,7 @@ var AgentID = class {
5086
5229
  const modelLatencyMs = Math.max(0, Date.now() - modelStartedAt);
5087
5230
  const totalPipelineLatencyMs = Math.max(0, Date.now() - pipelineStartedAt);
5088
5231
  if (maskedText) {
5232
+ const effectiveInputMaskingTelemetry = getMaskingTelemetryFromMapping(mapping);
5089
5233
  const output = adapter.extractOutput(res);
5090
5234
  const wrappedCompletion = this.wrapCompletion(output, {
5091
5235
  piiMapping: mapping,
@@ -5099,7 +5243,7 @@ var AgentID = class {
5099
5243
  system_id: systemId,
5100
5244
  user_id: options.user_id,
5101
5245
  request_identity: options.request_identity,
5102
- input: maskedText,
5246
+ input: retainedInputForLogs,
5103
5247
  output: outputForLog,
5104
5248
  model,
5105
5249
  usage,
@@ -5108,9 +5252,17 @@ var AgentID = class {
5108
5252
  metadata: mergeTelemetryContexts(
5109
5253
  telemetryMetadata,
5110
5254
  {
5111
- transformed_input: maskedText,
5255
+ transformed_input: retainedInputForLogs,
5112
5256
  transformed_output: wrappedCompletion.transformedOutput,
5113
5257
  output_masked: wrappedCompletion.outputMasked,
5258
+ client_side_pii_masking_applied: clientInputMaskingTelemetry.piiApplied,
5259
+ client_side_secret_masking_applied: clientInputMaskingTelemetry.secretApplied,
5260
+ server_side_pii_masking_applied: effectiveInputMaskingTelemetry.piiApplied && !clientInputMaskingTelemetry.piiApplied,
5261
+ server_side_secret_masking_applied: effectiveInputMaskingTelemetry.secretApplied && !clientInputMaskingTelemetry.secretApplied,
5262
+ effective_pii_masking_applied: effectiveInputMaskingTelemetry.piiApplied,
5263
+ effective_secret_masking_applied: effectiveInputMaskingTelemetry.secretApplied,
5264
+ effective_input_was_transformed: retainedInputForLogs !== "[REDACTED]",
5265
+ effective_output_was_transformed: wrappedCompletion.outputMasked,
5114
5266
  shadow_mode: isShadowMode,
5115
5267
  simulated_decision: verdict.simulated_decision ?? null,
5116
5268
  simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
@@ -5131,11 +5283,7 @@ var AgentID = class {
5131
5283
  sdkConfigVersion: capabilityConfig.version
5132
5284
  })
5133
5285
  ),
5134
- client_capabilities: this.buildClientCapabilities(
5135
- "openai",
5136
- false,
5137
- capabilityConfig
5138
- )
5286
+ client_capabilities: clientCapabilities
5139
5287
  }, requestOptions);
5140
5288
  if (!ingestResult.ok) {
5141
5289
  this.maybeRaiseStrictIngestDependencyError({
@@ -5149,7 +5297,7 @@ var AgentID = class {
5149
5297
  }
5150
5298
  if (!isShadowMode && maskedText) {
5151
5299
  const output = adapter.extractOutput(res);
5152
- const maskedOutput = this.wrapCompletion(output, {
5300
+ const clientFacingOutput = shouldDeanonymizeForClient ? this.pii.deanonymize(String(output ?? ""), mapping) : this.wrapCompletion(output, {
5153
5301
  piiMapping: mapping,
5154
5302
  deanonymizeForClient: false
5155
5303
  }).transformedOutput;
@@ -5158,10 +5306,10 @@ var AgentID = class {
5158
5306
  for (const choice of res.choices) {
5159
5307
  const typedChoice = choice;
5160
5308
  if (typedChoice?.message && typeof typedChoice.message.content === "string") {
5161
- typedChoice.message.content = maskedOutput;
5309
+ typedChoice.message.content = clientFacingOutput;
5162
5310
  }
5163
5311
  if (typedChoice?.delta && typeof typedChoice.delta.content === "string") {
5164
- typedChoice.delta.content = maskedOutput;
5312
+ typedChoice.delta.content = clientFacingOutput;
5165
5313
  }
5166
5314
  }
5167
5315
  }