agentid-sdk 0.1.36 → 0.1.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,86 @@
1
1
  // src/adapters.ts
2
+ function getLastUserMessage(req) {
3
+ const messages = req?.messages;
4
+ if (!Array.isArray(messages)) return null;
5
+ let lastUser = null;
6
+ for (const msg of messages) {
7
+ if (msg && typeof msg === "object" && msg.role === "user") {
8
+ lastUser = msg;
9
+ }
10
+ }
11
+ return lastUser;
12
+ }
13
+ function normalizeFilename(value, fallback) {
14
+ if (typeof value !== "string") {
15
+ return fallback;
16
+ }
17
+ const trimmed = value.trim();
18
+ return trimmed.length > 0 ? trimmed : fallback;
19
+ }
20
+ function parseDataUrl(value) {
21
+ if (!value.startsWith("data:")) {
22
+ return null;
23
+ }
24
+ const commaIndex = value.indexOf(",");
25
+ if (commaIndex === -1) {
26
+ return null;
27
+ }
28
+ const header = value.slice(5, commaIndex);
29
+ if (!/;base64/i.test(header)) {
30
+ return null;
31
+ }
32
+ const mimeType = header.split(";")[0]?.trim().toLowerCase() || null;
33
+ return { mimeType };
34
+ }
35
+ function inferAttachmentExtension(mimeType) {
36
+ switch (mimeType) {
37
+ case "application/pdf":
38
+ return "pdf";
39
+ case "image/png":
40
+ return "png";
41
+ case "image/jpeg":
42
+ return "jpg";
43
+ case "image/webp":
44
+ return "webp";
45
+ case "image/gif":
46
+ return "gif";
47
+ case "text/plain":
48
+ return "txt";
49
+ default:
50
+ return "bin";
51
+ }
52
+ }
53
+ function defaultFilenameForMimeType(mimeType) {
54
+ return `attachment.${inferAttachmentExtension(mimeType)}`;
55
+ }
56
+ function normalizeFileAttachment(part) {
57
+ const file = part?.file;
58
+ const rawContent = typeof file?.file_data === "string" && file.file_data.trim().length > 0 ? file.file_data.trim() : null;
59
+ if (!rawContent) {
60
+ return null;
61
+ }
62
+ const detectedMimeType = parseDataUrl(rawContent)?.mimeType ?? null;
63
+ return {
64
+ filename: normalizeFilename(file?.filename, defaultFilenameForMimeType(detectedMimeType)),
65
+ ...detectedMimeType ? { mime_type: detectedMimeType } : {},
66
+ content_base64: rawContent
67
+ };
68
+ }
69
+ function normalizeImageAttachment(part) {
70
+ const imageUrl = typeof part?.image_url?.url === "string" && part.image_url.url.trim().length > 0 ? part.image_url.url.trim() : null;
71
+ if (!imageUrl || !imageUrl.startsWith("data:")) {
72
+ return null;
73
+ }
74
+ const detectedMimeType = parseDataUrl(imageUrl)?.mimeType ?? "image/png";
75
+ return {
76
+ filename: defaultFilenameForMimeType(detectedMimeType),
77
+ mime_type: detectedMimeType,
78
+ content_base64: imageUrl
79
+ };
80
+ }
2
81
  var OpenAIAdapter = class {
3
82
  extractInput(req) {
4
- const messages = req?.messages;
5
- if (!Array.isArray(messages)) return null;
6
- let lastUser = null;
7
- for (const msg of messages) {
8
- if (msg && typeof msg === "object" && msg.role === "user") {
9
- lastUser = msg;
10
- }
11
- }
83
+ const lastUser = getLastUserMessage(req);
12
84
  if (!lastUser) return null;
13
85
  const content = lastUser.content;
14
86
  if (typeof content === "string") return content;
@@ -23,6 +95,34 @@ var OpenAIAdapter = class {
23
95
  }
24
96
  return null;
25
97
  }
98
+ extractAttachments(req) {
99
+ const lastUser = getLastUserMessage(req);
100
+ if (!lastUser) return [];
101
+ const content = lastUser?.content;
102
+ if (!Array.isArray(content)) {
103
+ return [];
104
+ }
105
+ const attachments = [];
106
+ for (const part of content) {
107
+ if (!part || typeof part !== "object") {
108
+ continue;
109
+ }
110
+ if (part.type === "file") {
111
+ const attachment = normalizeFileAttachment(part);
112
+ if (attachment) {
113
+ attachments.push(attachment);
114
+ }
115
+ continue;
116
+ }
117
+ if (part.type === "image_url") {
118
+ const attachment = normalizeImageAttachment(part);
119
+ if (attachment) {
120
+ attachments.push(attachment);
121
+ }
122
+ }
123
+ }
124
+ return attachments;
125
+ }
26
126
  getModelName(req, res) {
27
127
  const model = res?.model ?? req?.model ?? "unknown";
28
128
  return String(model);
@@ -902,8 +1002,173 @@ function detectNationalIdentifiers(text, options = {}) {
902
1002
  return results;
903
1003
  }
904
1004
 
1005
+ // src/secret-patterns.ts
1006
+ var SDK_SECRET_PATTERN_DEFINITIONS = [
1007
+ {
1008
+ id: "openai_api_key",
1009
+ placeholderType: "OPENAI_API_KEY",
1010
+ patternSource: "\\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\\b",
1011
+ flags: "iu",
1012
+ prefilterTerms: ["sk-", "proj-", "openai"]
1013
+ },
1014
+ {
1015
+ id: "aws_access_key",
1016
+ placeholderType: "AWS_ACCESS_KEY",
1017
+ patternSource: "\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b",
1018
+ flags: "iu",
1019
+ prefilterTerms: ["akia", "asia", "aws"]
1020
+ },
1021
+ {
1022
+ id: "github_token",
1023
+ placeholderType: "GITHUB_TOKEN",
1024
+ patternSource: "\\b(?:gh[pousr]_[A-Za-z0-9]{24,255}|github_pat_[A-Za-z0-9_]{20,255})\\b",
1025
+ flags: "iu",
1026
+ prefilterTerms: ["ghp_", "gho_", "ghu_", "ghs_", "ghr_", "github_pat_"]
1027
+ },
1028
+ {
1029
+ id: "slack_token",
1030
+ placeholderType: "SLACK_TOKEN",
1031
+ patternSource: "\\bxox(?:a|b|p|r|s)-[A-Za-z0-9-]{10,200}\\b",
1032
+ flags: "iu",
1033
+ prefilterTerms: ["xoxa-", "xoxb-", "xoxp-", "xoxr-", "xoxs-", "slack"]
1034
+ },
1035
+ {
1036
+ id: "slack_webhook_url",
1037
+ placeholderType: "SLACK_WEBHOOK_URL",
1038
+ patternSource: "https:\\/\\/hooks\\.slack\\.com\\/services\\/[A-Za-z0-9/_-]{20,}",
1039
+ flags: "iu",
1040
+ prefilterTerms: ["hooks.slack.com/services", "slack"]
1041
+ },
1042
+ {
1043
+ id: "discord_webhook_url",
1044
+ placeholderType: "DISCORD_WEBHOOK_URL",
1045
+ patternSource: "https:\\/\\/discord(?:app)?\\.com\\/api\\/webhooks\\/\\d+\\/[A-Za-z0-9_-]{16,}",
1046
+ flags: "iu",
1047
+ prefilterTerms: ["discord.com/api/webhooks", "discordapp.com/api/webhooks", "discord"]
1048
+ },
1049
+ {
1050
+ id: "stripe_secret_key",
1051
+ placeholderType: "STRIPE_SECRET_KEY",
1052
+ patternSource: "\\b(?:sk|pk|ak|rk)_(?:live|test)_[A-Za-z0-9]+\\b",
1053
+ flags: "iu",
1054
+ prefilterTerms: [
1055
+ "sk_live_",
1056
+ "pk_live_",
1057
+ "sk_test_",
1058
+ "pk_test_",
1059
+ "ak_live_",
1060
+ "ak_test_",
1061
+ "rk_live_",
1062
+ "rk_test_",
1063
+ "stripe"
1064
+ ]
1065
+ },
1066
+ {
1067
+ id: "google_api_key",
1068
+ placeholderType: "GOOGLE_API_KEY",
1069
+ patternSource: "\\bAIza[0-9A-Za-z_-]{35}\\b",
1070
+ flags: "iu",
1071
+ prefilterTerms: ["aiza", "google"]
1072
+ },
1073
+ {
1074
+ id: "anthropic_api_key",
1075
+ placeholderType: "ANTHROPIC_API_KEY",
1076
+ patternSource: "\\bsk-ant-(?:api\\d{2}-)?[A-Za-z0-9_-]{20,}\\b",
1077
+ flags: "iu",
1078
+ prefilterTerms: ["sk-ant-", "anthropic"]
1079
+ },
1080
+ {
1081
+ id: "evm_private_key",
1082
+ placeholderType: "EVM_PRIVATE_KEY",
1083
+ patternSource: "\\b0x[a-fA-F0-9]{64}\\b",
1084
+ flags: "iu",
1085
+ prefilterTerms: ["0x", "ethereum", "evm", "private key"]
1086
+ },
1087
+ {
1088
+ id: "jwt_token",
1089
+ placeholderType: "JWT_TOKEN",
1090
+ patternSource: "\\beyJ[A-Za-z0-9_-]{6,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\b",
1091
+ flags: "iu",
1092
+ prefilterTerms: ["eyj", "jwt", "bearer"]
1093
+ },
1094
+ {
1095
+ id: "bearer_token",
1096
+ placeholderType: "BEARER_TOKEN",
1097
+ patternSource: "\\bauthorization\\b\\s*[:=]\\s*bearer\\s+[A-Za-z0-9._~+\\/-]{16,}|\\bbearer\\s+[A-Za-z0-9._~+\\/-]{24,}",
1098
+ flags: "iu",
1099
+ prefilterTerms: ["authorization", "bearer"]
1100
+ },
1101
+ {
1102
+ id: "api_key_header",
1103
+ placeholderType: "API_KEY_HEADER",
1104
+ patternSource: "\\bx[-_]?api[-_]?key\\b\\s*[:=]\\s*[A-Za-z0-9._~+\\/-]{16,}",
1105
+ flags: "iu",
1106
+ prefilterTerms: ["x-api-key", "api-key", "x_api_key", "api_key"]
1107
+ },
1108
+ {
1109
+ id: "credential_assignment",
1110
+ placeholderType: "CREDENTIAL_ASSIGNMENT",
1111
+ patternSource: `(?:\\b|["'])(?:api(?:[_-]?|\\s+)key|access(?:[_-]?|\\s+)token|auth(?:[_-]?|\\s+)token|client(?:[_-]?|\\s+)secret|private(?:[_-]?|\\s+)key)(?:\\b|["'])\\s*(?::|=|=>)\\s*(?:"[A-Za-z0-9._~+\\/=:-]{16,}"|'[A-Za-z0-9._~+\\/=:-]{16,}'|[A-Za-z0-9._~+\\/=:-]{16,})`,
1112
+ flags: "iu",
1113
+ prefilterTerms: [
1114
+ "api key",
1115
+ "apikey",
1116
+ "api_key",
1117
+ "access token",
1118
+ "access_token",
1119
+ "auth token",
1120
+ "client secret",
1121
+ "private key"
1122
+ ]
1123
+ },
1124
+ {
1125
+ id: "password_assignment",
1126
+ placeholderType: "PASSWORD_ASSIGNMENT",
1127
+ patternSource: `(?:\\b|["'])(?:password|passwd|pwd)(?:\\b|["'])\\s*(?:(?::|=|=>)|(?:is|are|was|were)\\b)\\s*(?:"[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,}"|'[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,}'|[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,})`,
1128
+ flags: "iu",
1129
+ prefilterTerms: ["password", "passwd", "pwd"]
1130
+ },
1131
+ {
1132
+ id: "private_key_material",
1133
+ placeholderType: "PRIVATE_KEY_MATERIAL",
1134
+ patternSource: "-----BEGIN (?:(?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY|PGP PRIVATE KEY BLOCK|CERTIFICATE)-----[\\s\\S]{20,12000}(?:-----END (?:(?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY|PGP PRIVATE KEY BLOCK|CERTIFICATE)-----|$)",
1135
+ flags: "iu",
1136
+ prefilterTerms: ["begin private key", "begin pgp private key block", "private key"]
1137
+ },
1138
+ {
1139
+ id: "azure_connection_string",
1140
+ placeholderType: "AZURE_CONNECTION_STRING",
1141
+ patternSource: "\\bDefaultEndpointsProtocol=https;AccountName=[A-Za-z0-9.-]{3,};AccountKey=[A-Za-z0-9+/=]{20,}(?:;EndpointSuffix=[A-Za-z0-9.-]+)?\\b",
1142
+ flags: "iu",
1143
+ prefilterTerms: ["defaultendpointsprotocol", "accountname", "accountkey", "azure"]
1144
+ },
1145
+ {
1146
+ id: "azure_sas_token",
1147
+ placeholderType: "AZURE_SAS_TOKEN",
1148
+ patternSource: "\\bsv=[^\\s&]{2,}&[^\\s]{0,200}\\bsig=[A-Za-z0-9%/+_-]{16,}",
1149
+ flags: "iu",
1150
+ prefilterTerms: ["sv=", "sig=", "accountkey", "azure"]
1151
+ }
1152
+ ];
1153
+ function ensureGlobalFlag(flags) {
1154
+ const normalized = new Set(flags.split(""));
1155
+ normalized.add("g");
1156
+ return [...normalized].join("");
1157
+ }
1158
+ var COMPILED_SDK_SECRET_PATTERNS = SDK_SECRET_PATTERN_DEFINITIONS.map((definition) => ({
1159
+ ...definition,
1160
+ scanRegex: new RegExp(definition.patternSource, ensureGlobalFlag(definition.flags)),
1161
+ prefilterTermsLower: definition.prefilterTerms.map((term) => term.toLowerCase())
1162
+ }));
1163
+ function getSdkSecretDetectionMatchers() {
1164
+ return COMPILED_SDK_SECRET_PATTERNS;
1165
+ }
1166
+
905
1167
  // src/pii.ts
906
1168
  var defaultScanDeadlineMs = 100;
1169
+ var sdkSecretMatchers = getSdkSecretDetectionMatchers();
1170
+ var DISCORD_WEBHOOK_TOKEN_RE = /https:\/\/discord(?:app)?\.com\/api\/webhooks\/\d+\/([A-Za-z0-9_-]{16,})/giu;
1171
+ var BASIC_AUTH_PASSWORD_RE = /\/\/[^:\s/?#@]+:([^@\s/?#]+)@/giu;
907
1172
  function countDigits2(value) {
908
1173
  let count = 0;
909
1174
  for (const ch of value) {
@@ -928,15 +1193,32 @@ function luhnCheck(value) {
928
1193
  return sum % 10 === 0;
929
1194
  }
930
1195
  function normalizeDetections(text, detections) {
931
- const sorted = detections.filter((d) => d.start >= 0 && d.end > d.start && d.end <= text.length).sort((a, b) => a.start - b.start || b.end - b.start - (a.end - a.start));
1196
+ const sorted = detections.filter((d) => d.start >= 0 && d.end > d.start && d.end <= text.length).sort(
1197
+ (a, b) => detectionPriority(b.type) - detectionPriority(a.type) || a.start - b.start || b.end - b.start - (a.end - a.start)
1198
+ );
932
1199
  const kept = [];
933
- let cursor = 0;
934
1200
  for (const d of sorted) {
935
- if (d.start < cursor) continue;
1201
+ if (kept.some((candidate) => rangesOverlap(candidate, d))) continue;
936
1202
  kept.push(d);
937
- cursor = d.end;
938
1203
  }
939
- return kept;
1204
+ return kept.sort((a, b) => a.start - b.start || a.end - b.end);
1205
+ }
1206
+ function rangesOverlap(left, right) {
1207
+ return left.start < right.end && right.start < left.end;
1208
+ }
1209
+ function detectionPriority(type) {
1210
+ if (/^(?:OPENAI_API_KEY|AWS_ACCESS_KEY|GITHUB_TOKEN|SLACK_TOKEN|SLACK_WEBHOOK_URL|DISCORD_WEBHOOK_URL|STRIPE_SECRET_KEY|GOOGLE_API_KEY|ANTHROPIC_API_KEY|EVM_PRIVATE_KEY|JWT_TOKEN|BEARER_TOKEN|API_KEY_HEADER|AZURE_CONNECTION_STRING|AZURE_SAS_TOKEN)$/u.test(
1211
+ type
1212
+ )) {
1213
+ return 100;
1214
+ }
1215
+ if (/^(?:CREDENTIAL_ASSIGNMENT|PASSWORD_ASSIGNMENT|PRIVATE_KEY_MATERIAL|ENV_SECRET_ASSIGNMENT)$/u.test(type)) {
1216
+ return 80;
1217
+ }
1218
+ if (type === "PERSON_NAME" || type === "PERSON") {
1219
+ return 10;
1220
+ }
1221
+ return 50;
940
1222
  }
941
1223
  var PHONE_CONTEXT_KEYWORDS = [
942
1224
  "tel",
@@ -971,6 +1253,59 @@ var PHONE_CONTEXT_RE = new RegExp(
971
1253
  "iu"
972
1254
  );
973
1255
  var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1256
+ "name",
1257
+ "names",
1258
+ "namen",
1259
+ "firstname",
1260
+ "lastname",
1261
+ "first",
1262
+ "last",
1263
+ "forename",
1264
+ "surname",
1265
+ "family",
1266
+ "given",
1267
+ "jmeno",
1268
+ "jake",
1269
+ "jaky",
1270
+ "jaka",
1271
+ "jsem",
1272
+ "jsme",
1273
+ "napsal",
1274
+ "napsali",
1275
+ "napsala",
1276
+ "napsane",
1277
+ "pouzil",
1278
+ "pouzili",
1279
+ "prijmeni",
1280
+ "vorname",
1281
+ "nachname",
1282
+ "familienname",
1283
+ "what",
1284
+ "which",
1285
+ "whose",
1286
+ "did",
1287
+ "we",
1288
+ "write",
1289
+ "wrote",
1290
+ "written",
1291
+ "type",
1292
+ "typed",
1293
+ "use",
1294
+ "used",
1295
+ "wie",
1296
+ "welchen",
1297
+ "welche",
1298
+ "welches",
1299
+ "haben",
1300
+ "wir",
1301
+ "geschrieben",
1302
+ "getippt",
1303
+ "quel",
1304
+ "quelle",
1305
+ "nom",
1306
+ "que",
1307
+ "cual",
1308
+ "nombre",
974
1309
  "write",
975
1310
  "code",
976
1311
  "script",
@@ -997,6 +1332,52 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
997
1332
  "security",
998
1333
  "instructions",
999
1334
  "instruction",
1335
+ "google",
1336
+ "form",
1337
+ "forms",
1338
+ "engineering",
1339
+ "leadership",
1340
+ "weekly",
1341
+ "daily",
1342
+ "monthly",
1343
+ "quarterly",
1344
+ "sync",
1345
+ "office",
1346
+ "updates",
1347
+ "update",
1348
+ "meeting",
1349
+ "meetings",
1350
+ "agenda",
1351
+ "minutes",
1352
+ "subject",
1353
+ "calendar",
1354
+ "roadmap",
1355
+ "platform",
1356
+ "product",
1357
+ "design",
1358
+ "operations",
1359
+ "business",
1360
+ "newsletter",
1361
+ "report",
1362
+ "reports",
1363
+ "amazon",
1364
+ "web",
1365
+ "services",
1366
+ "aws",
1367
+ "velka",
1368
+ "transformace",
1369
+ "project",
1370
+ "projekt",
1371
+ "program",
1372
+ "initiative",
1373
+ "iniciativa",
1374
+ "migration",
1375
+ "migrace",
1376
+ "test",
1377
+ "uuid",
1378
+ "fixture",
1379
+ "data",
1380
+ "firma",
1000
1381
  "rules",
1001
1382
  "rule",
1002
1383
  "json",
@@ -1009,10 +1390,22 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1009
1390
  "agentid",
1010
1391
  "risk",
1011
1392
  "score",
1012
- "summary"
1393
+ "summary",
1394
+ "hi",
1395
+ "hello",
1396
+ "hey",
1397
+ "dear",
1398
+ "team",
1399
+ "ahoj",
1400
+ "dobry",
1401
+ "dobryden",
1402
+ "zdravim"
1013
1403
  ]);
1014
1404
  var TECHNICAL_CONTEXT_WORD_REGEX = /\b(?:curl|http|https|import|python|javascript|typescript|sql|nosql|mongo|database|query|script|code|os\.system|eval|exec|node|npm|api|endpoint|regex|json|xml|yaml|bash|powershell)\b/i;
1015
1405
  var TECHNICAL_CONTEXT_SYMBOL_REGEX = /:\/\/|`|\{|\}|\[|\]|\(|\)|;|\$|=>|::|\/\//;
1406
+ 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;
1407
+ var NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX = /(?:[:=]|=>|-|\b(?:is|was|je|jsou|jmenuje|called|named|ist|sind|lautet|est|es)\b)\s*$/iu;
1408
+ var BIRTH_NUMBER_CONTEXT_RE = /\b(?:rodn[eé]\s*(?:č[ií]slo|cislo)|r\.?\s*c\.?|birth\s+number)\b[^0-9]{0,80}(\d{6}(?:\/?\d{3,4})?)\b/giu;
1016
1409
  function hasPhoneContext(text, matchStartIndex, windowSize = 50) {
1017
1410
  const start = Math.max(0, matchStartIndex - windowSize);
1018
1411
  const windowLower = text.slice(start, matchStartIndex).toLowerCase();
@@ -1029,6 +1422,16 @@ function buildContextWindow(source, index, length) {
1029
1422
  function isTechnicalContext(contextWindow) {
1030
1423
  return TECHNICAL_CONTEXT_WORD_REGEX.test(contextWindow) || TECHNICAL_CONTEXT_SYMBOL_REGEX.test(contextWindow);
1031
1424
  }
1425
+ function isNameLabelQuestionContext(contextWindow) {
1426
+ const normalized = normalizePersonWord(contextWindow);
1427
+ if (!normalized.trim()) {
1428
+ return false;
1429
+ }
1430
+ if (!NAME_LABEL_QUESTION_CONTEXT_REGEX.test(normalized)) {
1431
+ return false;
1432
+ }
1433
+ return !NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX.test(normalized.slice(-32));
1434
+ }
1032
1435
  function isLikelyPersonNameCandidate(candidate, contextWindow) {
1033
1436
  const words = candidate.trim().split(/\s+/);
1034
1437
  if (words.length !== 2) {
@@ -1037,6 +1440,9 @@ function isLikelyPersonNameCandidate(candidate, contextWindow) {
1037
1440
  if (isTechnicalContext(contextWindow)) {
1038
1441
  return false;
1039
1442
  }
1443
+ if (isNameLabelQuestionContext(contextWindow)) {
1444
+ return false;
1445
+ }
1040
1446
  for (const rawWord of words) {
1041
1447
  const normalized = normalizePersonWord(rawWord);
1042
1448
  if (normalized.length < 2) {
@@ -1057,63 +1463,135 @@ var PIIManager = class {
1057
1463
  *
1058
1464
  * Zero-dependency fallback with strict checksum validation for CEE national IDs.
1059
1465
  */
1060
- anonymize(text) {
1466
+ anonymize(text, options) {
1061
1467
  if (!text) return { maskedText: text, mapping: {} };
1062
1468
  try {
1063
1469
  const detections = [];
1064
- const emailRe = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
1065
- for (const m of text.matchAll(emailRe)) {
1066
- if (m.index == null) continue;
1067
- detections.push({ start: m.index, end: m.index + m[0].length, type: "EMAIL", text: m[0] });
1068
- }
1069
- const ibanRe = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/gi;
1070
- for (const m of text.matchAll(ibanRe)) {
1071
- if (m.index == null) continue;
1072
- detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
1073
- }
1074
- const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
1075
- for (const m of text.matchAll(ccRe)) {
1076
- if (m.index == null) continue;
1077
- const digits = countDigits2(m[0]);
1078
- if (digits < 12 || digits > 19) continue;
1079
- if (!luhnCheck(m[0])) continue;
1080
- detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
1470
+ const loweredText = text.toLowerCase();
1471
+ const resolvedOptions = {
1472
+ pii: options?.pii !== false,
1473
+ secrets: options?.secrets !== false
1474
+ };
1475
+ if (!resolvedOptions.pii && !resolvedOptions.secrets) {
1476
+ return { maskedText: text, mapping: {} };
1081
1477
  }
1082
- const phoneRe = /(?<!\d)(?:\+?\d[\d\s().-]{7,}\d)(?!\d)/g;
1083
- for (const m of text.matchAll(phoneRe)) {
1084
- if (m.index == null) continue;
1085
- const candidate = m[0];
1086
- const digits = countDigits2(candidate);
1087
- if (digits < 9 || digits > 15) continue;
1088
- const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
1089
- if (!isStrongInternational) {
1090
- const hasContext = hasPhoneContext(text, m.index);
1091
- if (!hasContext) continue;
1478
+ if (resolvedOptions.pii) {
1479
+ const emailRe = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
1480
+ for (const m of text.matchAll(emailRe)) {
1481
+ if (m.index == null) continue;
1482
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "EMAIL", text: m[0] });
1092
1483
  }
1093
- detections.push({ start: m.index, end: m.index + m[0].length, type: "PHONE", text: m[0] });
1094
- }
1095
- const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
1096
- for (const m of text.matchAll(personRe)) {
1097
- if (m.index == null) continue;
1098
- const candidate = m[0];
1099
- const contextWindow = buildContextWindow(text, m.index, candidate.length);
1100
- if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
1101
- continue;
1484
+ const ibanRe = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/gi;
1485
+ for (const m of text.matchAll(ibanRe)) {
1486
+ if (m.index == null) continue;
1487
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
1102
1488
  }
1103
- detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
1104
- }
1105
- const nationalIdMatches = detectNationalIdentifiers(text, {
1106
- deadlineMs: defaultScanDeadlineMs,
1107
- allowContextBirthNumberFallback: false
1108
- });
1109
- for (const match of nationalIdMatches) {
1110
- if (match.start < 0 || match.end <= match.start) continue;
1111
- detections.push({
1112
- start: match.start,
1113
- end: match.end,
1114
- type: "NATIONAL_ID",
1115
- text: text.slice(match.start, match.end)
1489
+ const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
1490
+ for (const m of text.matchAll(ccRe)) {
1491
+ if (m.index == null) continue;
1492
+ const digits = countDigits2(m[0]);
1493
+ if (digits < 12 || digits > 19) continue;
1494
+ if (!luhnCheck(m[0])) continue;
1495
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
1496
+ }
1497
+ const phoneRe = /(?<!\d)(?:\+?\d[\d\s().-]{7,}\d)(?!\d)/g;
1498
+ for (const m of text.matchAll(phoneRe)) {
1499
+ if (m.index == null) continue;
1500
+ const candidate = m[0];
1501
+ const digits = countDigits2(candidate);
1502
+ if (digits < 9 || digits > 15) continue;
1503
+ const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
1504
+ if (!isStrongInternational) {
1505
+ const hasContext = hasPhoneContext(text, m.index);
1506
+ if (!hasContext) continue;
1507
+ }
1508
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "PHONE", text: m[0] });
1509
+ }
1510
+ const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
1511
+ for (const m of text.matchAll(personRe)) {
1512
+ if (m.index == null) continue;
1513
+ const candidate = m[0];
1514
+ const contextWindow = buildContextWindow(text, m.index, candidate.length);
1515
+ if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
1516
+ continue;
1517
+ }
1518
+ detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
1519
+ }
1520
+ BIRTH_NUMBER_CONTEXT_RE.lastIndex = 0;
1521
+ for (const match of text.matchAll(BIRTH_NUMBER_CONTEXT_RE)) {
1522
+ if (match.index == null) continue;
1523
+ const value = match[1] ?? "";
1524
+ if (!/^\d{6}(?:\/?\d{3,4})?$/.test(value)) continue;
1525
+ const localIndex = match[0].lastIndexOf(value);
1526
+ const start = match.index + Math.max(0, localIndex);
1527
+ detections.push({
1528
+ start,
1529
+ end: start + value.length,
1530
+ type: "BIRTH_NUMBER",
1531
+ text: value
1532
+ });
1533
+ }
1534
+ const nationalIdMatches = detectNationalIdentifiers(text, {
1535
+ deadlineMs: defaultScanDeadlineMs,
1536
+ allowContextBirthNumberFallback: false
1116
1537
  });
1538
+ for (const match of nationalIdMatches) {
1539
+ if (match.start < 0 || match.end <= match.start) continue;
1540
+ detections.push({
1541
+ start: match.start,
1542
+ end: match.end,
1543
+ type: "NATIONAL_ID",
1544
+ text: text.slice(match.start, match.end)
1545
+ });
1546
+ }
1547
+ }
1548
+ if (resolvedOptions.secrets) {
1549
+ BASIC_AUTH_PASSWORD_RE.lastIndex = 0;
1550
+ for (const match of text.matchAll(BASIC_AUTH_PASSWORD_RE)) {
1551
+ if (match.index == null) continue;
1552
+ const password = match[1] ?? "";
1553
+ if (!password) continue;
1554
+ const localIndex = match[0].lastIndexOf(password);
1555
+ const start = match.index + Math.max(0, localIndex);
1556
+ detections.push({
1557
+ start,
1558
+ end: start + password.length,
1559
+ type: "BASIC_AUTH_PASSWORD",
1560
+ text: password
1561
+ });
1562
+ }
1563
+ DISCORD_WEBHOOK_TOKEN_RE.lastIndex = 0;
1564
+ for (const match of text.matchAll(DISCORD_WEBHOOK_TOKEN_RE)) {
1565
+ if (match.index == null) continue;
1566
+ const token = match[1] ?? "";
1567
+ if (!token) continue;
1568
+ const localIndex = match[0].lastIndexOf(token);
1569
+ const start = match.index + Math.max(0, localIndex);
1570
+ detections.push({
1571
+ start,
1572
+ end: start + token.length,
1573
+ type: "DISCORD_WEBHOOK_TOKEN",
1574
+ text: token
1575
+ });
1576
+ }
1577
+ for (const matcher of sdkSecretMatchers) {
1578
+ if (matcher.id === "discord_webhook_url") {
1579
+ continue;
1580
+ }
1581
+ if (matcher.prefilterTermsLower.length > 0 && !matcher.prefilterTermsLower.some((term) => loweredText.includes(term))) {
1582
+ continue;
1583
+ }
1584
+ matcher.scanRegex.lastIndex = 0;
1585
+ for (const match of text.matchAll(matcher.scanRegex)) {
1586
+ if (match.index == null) continue;
1587
+ detections.push({
1588
+ start: match.index,
1589
+ end: match.index + match[0].length,
1590
+ type: matcher.placeholderType,
1591
+ text: match[0]
1592
+ });
1593
+ }
1594
+ }
1117
1595
  }
1118
1596
  const kept = normalizeDetections(text, detections);
1119
1597
  if (!kept.length) return { maskedText: text, mapping: {} };
@@ -1642,14 +2120,14 @@ async function reportSecurityEvent(options) {
1642
2120
  const inputValue = options.storePii ? snippet : snippetHash;
1643
2121
  const eventId = createEventId(options.eventId ?? options.clientEventId);
1644
2122
  const metadata = {
2123
+ ...options.telemetryMetadata ?? {},
1645
2124
  source: options.source,
1646
2125
  detector: options.detector,
1647
2126
  trigger_rule: options.triggerRule,
1648
2127
  language: options.language,
1649
2128
  ai_scan_status: options.aiStatus ?? null,
1650
2129
  reason: options.reason ?? null,
1651
- client_event_id: eventId,
1652
- ...options.telemetryMetadata ?? {}
2130
+ client_event_id: eventId
1653
2131
  };
1654
2132
  if (options.storePii) {
1655
2133
  metadata.snippet = snippet;
@@ -1810,7 +2288,7 @@ function getInjectionScanner() {
1810
2288
 
1811
2289
  // src/sdk-version.ts
1812
2290
  var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
1813
- var AGENTID_SDK_VERSION_HEADER = "js-0.1.36".trim().length > 0 ? "js-0.1.36" : FALLBACK_SDK_VERSION;
2291
+ var AGENTID_SDK_VERSION_HEADER = "js-0.1.38".trim().length > 0 ? "js-0.1.38" : FALLBACK_SDK_VERSION;
1814
2292
 
1815
2293
  // src/local-security-enforcer.ts
1816
2294
  var DEFAULT_FAIL_OPEN_CONFIG = {
@@ -1822,6 +2300,8 @@ var DEFAULT_FAIL_OPEN_CONFIG = {
1822
2300
  inject_transparency_metadata: false,
1823
2301
  block_pii_leakage: false,
1824
2302
  enable_sdk_pii_masking: false,
2303
+ block_secret_leakage: false,
2304
+ enable_sdk_secret_masking: false,
1825
2305
  block_db_access: false,
1826
2306
  block_code_execution: false,
1827
2307
  block_toxicity: false
@@ -1863,11 +2343,11 @@ function detectCapabilityViolation(text, config) {
1863
2343
  }
1864
2344
  return null;
1865
2345
  }
1866
- function redactPiiStrict(pii, text) {
2346
+ function redactPiiStrict(pii, text, options) {
1867
2347
  if (!text) {
1868
2348
  return { redactedText: text, changed: false };
1869
2349
  }
1870
- const masked = pii.anonymize(text);
2350
+ const masked = pii.anonymize(text, options);
1871
2351
  let redactedText = masked.maskedText;
1872
2352
  const placeholders = Object.keys(masked.mapping).sort((a, b) => b.length - a.length);
1873
2353
  for (const placeholder of placeholders) {
@@ -1896,7 +2376,7 @@ var LocalSecurityEnforcer = class {
1896
2376
  `AgentID: Security policy blocked (${violationType})`
1897
2377
  );
1898
2378
  }
1899
- if (!config.block_pii_leakage) {
2379
+ if (!config.block_pii_leakage && !config.block_secret_leakage) {
1900
2380
  return {
1901
2381
  sanitizedInput: input,
1902
2382
  events: []
@@ -1906,10 +2386,13 @@ var LocalSecurityEnforcer = class {
1906
2386
  throw new SecurityPolicyViolationError(
1907
2387
  "PII_LEAKAGE_STRICT",
1908
2388
  "BLOCKED",
1909
- "AgentID: Streaming is not supported when Strict PII Mode is enabled. Please disable streaming or adjust security settings."
2389
+ "AgentID: Streaming is not supported when strict masking/blocking mode is enabled. Please disable streaming or adjust security settings."
1910
2390
  );
1911
2391
  }
1912
- const strictRedaction = redactPiiStrict(this.pii, input);
2392
+ const strictRedaction = redactPiiStrict(this.pii, input, {
2393
+ pii: config.block_pii_leakage,
2394
+ secrets: config.block_secret_leakage
2395
+ });
1913
2396
  return {
1914
2397
  sanitizedInput: strictRedaction.redactedText,
1915
2398
  events: strictRedaction.changed ? [
@@ -2035,6 +2518,16 @@ function normalizeCapabilityConfig(payload) {
2035
2518
  "enable_sdk_pii_masking",
2036
2519
  false
2037
2520
  ),
2521
+ block_secret_leakage: readOptionalBooleanField(
2522
+ body,
2523
+ "block_secret_leakage",
2524
+ false
2525
+ ),
2526
+ enable_sdk_secret_masking: readOptionalBooleanField(
2527
+ body,
2528
+ "enable_sdk_secret_masking",
2529
+ false
2530
+ ),
2038
2531
  block_db_access: readBooleanField(body, "block_db_access", "block_db"),
2039
2532
  block_code_execution: readBooleanField(
2040
2533
  body,
@@ -2215,9 +2708,18 @@ var INGEST_MAX_ATTEMPTS = 3;
2215
2708
  var INGEST_RETRY_DELAYS_MS = [250, 500];
2216
2709
  var GUARD_VERDICT_CACHE_TTL_MS = 0;
2217
2710
  var MAX_INGEST_TEXT_CHARS = 32e3;
2711
+ var OPENAI_TELEMETRY_FIELD = "agentid_telemetry";
2218
2712
  function normalizeBaseUrl3(baseUrl) {
2219
2713
  return baseUrl.replace(/\/+$/, "");
2220
2714
  }
2715
+ function firstNonEmptyString(...values) {
2716
+ for (const value of values) {
2717
+ if (typeof value === "string" && value.trim().length > 0) {
2718
+ return value.trim();
2719
+ }
2720
+ }
2721
+ return void 0;
2722
+ }
2221
2723
  function isAbortSignalLike(value) {
2222
2724
  if (!value || typeof value !== "object") return false;
2223
2725
  const candidate = value;
@@ -2379,6 +2881,424 @@ function createCorrelationId(seed) {
2379
2881
  }
2380
2882
  return createPseudoUuidV42();
2381
2883
  }
2884
+ function getObjectString(value, ...keys) {
2885
+ for (const key of keys) {
2886
+ const candidate = value?.[key];
2887
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
2888
+ return candidate.trim();
2889
+ }
2890
+ }
2891
+ return void 0;
2892
+ }
2893
+ function getObjectNumber(value, ...keys) {
2894
+ for (const key of keys) {
2895
+ const candidate = value?.[key];
2896
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
2897
+ return candidate;
2898
+ }
2899
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
2900
+ const parsed = Number(candidate);
2901
+ if (Number.isFinite(parsed)) {
2902
+ return parsed;
2903
+ }
2904
+ }
2905
+ }
2906
+ return void 0;
2907
+ }
2908
+ function normalizeTelemetryString(value) {
2909
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
2910
+ }
2911
+ function normalizeTelemetryCategory(value) {
2912
+ const normalized = normalizeTelemetryString(value);
2913
+ if (!normalized) return void 0;
2914
+ return normalized.toLowerCase().replace(/[\s-]+/g, "_");
2915
+ }
2916
+ function toSnakeToken(value) {
2917
+ return value.trim().replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_").toLowerCase();
2918
+ }
2919
+ function hasUsageSignals(value) {
2920
+ if (!value) return false;
2921
+ for (const entry of Object.values(value)) {
2922
+ if (typeof entry === "number" && Number.isFinite(entry) && entry > 0) {
2923
+ return true;
2924
+ }
2925
+ if (typeof entry === "string" && entry.trim().length > 0) {
2926
+ const parsed = Number(entry);
2927
+ if (Number.isFinite(parsed) && parsed > 0) {
2928
+ return true;
2929
+ }
2930
+ }
2931
+ }
2932
+ return false;
2933
+ }
2934
+ function truncatePromptPreflightPreview(value, maxChars = 280) {
2935
+ const normalized = value.trim();
2936
+ if (normalized.length <= maxChars) {
2937
+ return normalized;
2938
+ }
2939
+ return `${normalized.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
2940
+ }
2941
+ function formatPromptPreflightReason(reason) {
2942
+ const normalized = normalizeTelemetryString(reason);
2943
+ if (!normalized) {
2944
+ return void 0;
2945
+ }
2946
+ return normalized.replace(/[_-]+/g, " ");
2947
+ }
2948
+ function summarizePromptPreflightResult(params) {
2949
+ const reason = formatPromptPreflightReason(
2950
+ params.localFallbackApplied ? params.localFallbackReason ?? void 0 : params.verdict.reason
2951
+ ) ?? "policy evaluation";
2952
+ if (!params.verdict.allowed && !params.localFallbackApplied) {
2953
+ return `Blocked the prompt before model execution because ${reason}.`;
2954
+ }
2955
+ if (params.localFallbackApplied) {
2956
+ return `Guard preflight degraded, so the SDK applied local fallback checks before model execution (${reason}).`;
2957
+ }
2958
+ if (params.verdict.shadow_mode && params.verdict.shadow_blocked) {
2959
+ return "Evaluated the prompt in shadow mode before model execution; shadow policy would have blocked it.";
2960
+ }
2961
+ if (params.verdict.simulated_decision === "masked" || params.verdict.detected_pii) {
2962
+ return "Evaluated the prompt before model execution and masked sensitive content where needed.";
2963
+ }
2964
+ return "Evaluated the prompt and attachments against guardrails before model execution.";
2965
+ }
2966
+ function buildPromptPreflightTelemetry(params) {
2967
+ const baseTelemetry = createAgentIdTelemetryContext(params.telemetry);
2968
+ const baseStepName = firstNonEmptyString(
2969
+ baseTelemetry?.workflow_step_name,
2970
+ baseTelemetry?.workflowStepName
2971
+ );
2972
+ const stepName = baseStepName ? `${toSnakeToken(baseStepName)}_preflight` : "prompt_preflight";
2973
+ const summary = summarizePromptPreflightResult({
2974
+ verdict: params.verdict,
2975
+ localFallbackApplied: params.local_fallback_applied,
2976
+ localFallbackReason: params.local_fallback_reason
2977
+ });
2978
+ return mergeTelemetryContexts(baseTelemetry, {
2979
+ workflow_step_id: createAgentIdCorrelationId(),
2980
+ workflow_step_name: stepName,
2981
+ event_title: "Prompt Preflight Evaluated",
2982
+ event_category: "guard",
2983
+ event_subtype: "prompt_preflight_evaluated",
2984
+ event_status: !params.verdict.allowed && !params.local_fallback_applied ? "blocked" : "completed",
2985
+ step_summary: summary,
2986
+ input_preview: truncatePromptPreflightPreview(params.input),
2987
+ output_preview: summary,
2988
+ runtime_surface: params.runtime_surface ?? "openai_sdk_guard",
2989
+ guard_event_id: params.guard_event_id ?? void 0,
2990
+ guard_latency_ms: params.guard_latency_ms ?? void 0,
2991
+ preflight_for_client_event_id: params.preflight_for_client_event_id,
2992
+ preflight_logged_via_sdk: true,
2993
+ lifecycle_status: "preflight_only"
2994
+ });
2995
+ }
2996
+ function inferOperationCategory(telemetry, eventType) {
2997
+ const explicitCategory = normalizeTelemetryCategory(
2998
+ telemetry?.event_category ?? telemetry?.eventCategory
2999
+ );
3000
+ if (explicitCategory === "ai" || explicitCategory === "llm" || explicitCategory === "inference") {
3001
+ return "ai";
3002
+ }
3003
+ if (explicitCategory === "guard" || explicitCategory === "security") {
3004
+ return "guard";
3005
+ }
3006
+ if (explicitCategory === "tool") return "tool";
3007
+ if (explicitCategory === "delivery" || explicitCategory === "send") return "delivery";
3008
+ if (explicitCategory === "inbox" || explicitCategory === "reply") return "inbox";
3009
+ if (explicitCategory === "workflow" || explicitCategory === "agent") return "workflow";
3010
+ if (explicitCategory === "compliance" || explicitCategory === "transparency") {
3011
+ return "compliance";
3012
+ }
3013
+ if (explicitCategory === "operational" || explicitCategory === "ops") {
3014
+ return "operational";
3015
+ }
3016
+ const haystack = [
3017
+ eventType,
3018
+ telemetry?.event_subtype,
3019
+ telemetry?.eventSubtype,
3020
+ telemetry?.tool_name,
3021
+ telemetry?.toolName,
3022
+ telemetry?.tool_target_type,
3023
+ telemetry?.toolTargetType,
3024
+ telemetry?.workflow_name,
3025
+ telemetry?.workflowName,
3026
+ telemetry?.workflow_step_name,
3027
+ telemetry?.workflowStepName,
3028
+ getObjectString(telemetry, "operation_family", "domain")
3029
+ ].filter((entry) => typeof entry === "string" && entry.trim().length > 0).join(" ").replace(/[_./-]+/g, " ").toLowerCase();
3030
+ if (/\b(llm|ai|inference|completion|summary|classification|draft)\b/.test(haystack)) {
3031
+ return "ai";
3032
+ }
3033
+ if (/\b(guard|security|policy|pii|prompt[_ ]?injection|review)\b/.test(haystack)) {
3034
+ return "guard";
3035
+ }
3036
+ if (/\b(reply|inbox|inbound|received|bounce|opened|followup)\b/.test(haystack)) {
3037
+ return "inbox";
3038
+ }
3039
+ if (/\b(email|mail|send|delivery|delivered|slack|sms|webhook|notification)\b/.test(haystack)) {
3040
+ return "delivery";
3041
+ }
3042
+ if (/\b(workflow|step|run|agent)\b/.test(haystack)) {
3043
+ return "workflow";
3044
+ }
3045
+ if (/\b(compliance|transparency|audit|evidence)\b/.test(haystack)) {
3046
+ return "compliance";
3047
+ }
3048
+ 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(
3049
+ haystack
3050
+ )) {
3051
+ return "tool";
3052
+ }
3053
+ return "operational";
3054
+ }
3055
+ function inferOperationStatus(params) {
3056
+ const explicitStatus = normalizeTelemetryString(params.eventStatus)?.toLowerCase();
3057
+ if (explicitStatus === "started" || explicitStatus === "completed" || explicitStatus === "failed") {
3058
+ return explicitStatus;
3059
+ }
3060
+ if (explicitStatus === "blocked" || explicitStatus === "skipped") {
3061
+ return explicitStatus;
3062
+ }
3063
+ const normalizedEventType = normalizeTelemetryString(params.eventType)?.toLowerCase();
3064
+ if (normalizedEventType === "start") return "started";
3065
+ if (normalizedEventType === "error") return "failed";
3066
+ if (normalizedEventType === "security_block") return "blocked";
3067
+ if (normalizedEventType === "human_override") return "completed";
3068
+ if (normalizedEventType === "complete") return "completed";
3069
+ return params.severity === "error" ? "failed" : "completed";
3070
+ }
3071
+ function deriveOperationEventType(params) {
3072
+ const explicit = normalizeTelemetryString(params.explicitEventType);
3073
+ if (explicit) {
3074
+ return explicit;
3075
+ }
3076
+ if (params.status === "started") return "start";
3077
+ if (params.status === "failed") return "error";
3078
+ if (params.status === "blocked") {
3079
+ return params.category === "guard" ? "security_block" : "error";
3080
+ }
3081
+ return "complete";
3082
+ }
3083
+ function deriveSubtypeBase(telemetry) {
3084
+ const toolName = normalizeTelemetryString(telemetry?.tool_name ?? telemetry?.toolName);
3085
+ if (toolName) {
3086
+ const tokens = toSnakeToken(toolName).split("_").filter(Boolean);
3087
+ if (tokens.length > 1 && ["workflow", "agent", "operation", "ops", "hr", "finance", "compliance"].includes(tokens[0])) {
3088
+ return tokens.slice(1).join("_");
3089
+ }
3090
+ return tokens.join("_");
3091
+ }
3092
+ const workflowName = normalizeTelemetryString(
3093
+ telemetry?.workflow_step_name ?? telemetry?.workflowStepName ?? telemetry?.workflow_name ?? telemetry?.workflowName
3094
+ );
3095
+ if (workflowName) {
3096
+ return toSnakeToken(workflowName);
3097
+ }
3098
+ return void 0;
3099
+ }
3100
+ function deriveOperationSubtype(params) {
3101
+ const explicitSubtype = normalizeTelemetryString(params.explicitSubtype);
3102
+ if (explicitSubtype) {
3103
+ return toSnakeToken(explicitSubtype);
3104
+ }
3105
+ const base = deriveSubtypeBase(params.telemetry);
3106
+ const suffix = params.status === "started" ? "started" : params.status === "failed" ? "failed" : params.status === "blocked" ? "blocked" : params.status === "skipped" ? "skipped" : "completed";
3107
+ if (base) {
3108
+ return `${base}_${suffix}`;
3109
+ }
3110
+ if (params.eventType === "start") return `${params.category}_started`;
3111
+ if (params.eventType === "error") return `${params.category}_failed`;
3112
+ if (params.eventType === "security_block") return `${params.category}_blocked`;
3113
+ return `${params.category}_completed`;
3114
+ }
3115
+ function inferOperationSeverity(params) {
3116
+ if (params.explicitSeverity) {
3117
+ return params.explicitSeverity;
3118
+ }
3119
+ if (params.status === "failed" || params.status === "blocked") {
3120
+ return "error";
3121
+ }
3122
+ if (params.status === "skipped") {
3123
+ return "warning";
3124
+ }
3125
+ return "info";
3126
+ }
3127
+ function createAgentIdCorrelationId(seed) {
3128
+ return createCorrelationId(seed);
3129
+ }
3130
+ function createAgentIdTelemetryContext(value) {
3131
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
3132
+ return void 0;
3133
+ }
3134
+ const raw = { ...value };
3135
+ const normalized = {};
3136
+ const assignString = (key, ...aliases) => {
3137
+ const next = getObjectString(raw, key, ...aliases);
3138
+ if (next) {
3139
+ normalized[key] = next;
3140
+ }
3141
+ };
3142
+ const assignNumber = (key, ...aliases) => {
3143
+ const next = getObjectNumber(raw, key, ...aliases);
3144
+ if (typeof next === "number") {
3145
+ normalized[key] = next;
3146
+ }
3147
+ };
3148
+ assignString("workflow_id", "workflowId");
3149
+ assignString("workflow_run_id", "workflowRunId");
3150
+ assignString("workflow_step_id", "workflowStepId");
3151
+ assignString("workflow_name", "workflowName");
3152
+ assignString("workflow_step_name", "workflowStepName");
3153
+ assignNumber("workflow_step_index", "workflowStepIndex");
3154
+ assignString("parent_event_id", "parentEventId");
3155
+ assignString("tool_name", "toolName");
3156
+ assignString("tool_target", "toolTarget");
3157
+ assignString("tool_target_type", "toolTargetType");
3158
+ assignString("event_title", "eventTitle");
3159
+ assignString("event_status", "eventStatus");
3160
+ assignString("event_category", "eventCategory");
3161
+ assignString("event_subtype", "eventSubtype");
3162
+ const consumedKeys = /* @__PURE__ */ new Set([
3163
+ "workflow_id",
3164
+ "workflowId",
3165
+ "workflow_run_id",
3166
+ "workflowRunId",
3167
+ "workflow_step_id",
3168
+ "workflowStepId",
3169
+ "workflow_name",
3170
+ "workflowName",
3171
+ "workflow_step_name",
3172
+ "workflowStepName",
3173
+ "workflow_step_index",
3174
+ "workflowStepIndex",
3175
+ "parent_event_id",
3176
+ "parentEventId",
3177
+ "tool_name",
3178
+ "toolName",
3179
+ "tool_target",
3180
+ "toolTarget",
3181
+ "tool_target_type",
3182
+ "toolTargetType",
3183
+ "event_title",
3184
+ "eventTitle",
3185
+ "event_status",
3186
+ "eventStatus",
3187
+ "event_category",
3188
+ "eventCategory",
3189
+ "event_subtype",
3190
+ "eventSubtype"
3191
+ ]);
3192
+ for (const [key, entry] of Object.entries(raw)) {
3193
+ if (consumedKeys.has(key) || entry === void 0) {
3194
+ continue;
3195
+ }
3196
+ if (typeof entry === "string") {
3197
+ if (entry.trim().length > 0) {
3198
+ normalized[key] = entry.trim();
3199
+ }
3200
+ continue;
3201
+ }
3202
+ normalized[key] = entry;
3203
+ }
3204
+ if (typeof normalized.workflow_id !== "string" && typeof normalized.workflow_run_id === "string") {
3205
+ normalized.workflow_id = normalized.workflow_run_id;
3206
+ }
3207
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
3208
+ }
3209
+ function createAgentIdOperationLog(params) {
3210
+ const telemetry = createAgentIdTelemetryContext(params.telemetry);
3211
+ const category = inferOperationCategory(
3212
+ createAgentIdTelemetryContext({
3213
+ ...telemetry ?? {},
3214
+ event_category: params.event_category ?? telemetry?.event_category
3215
+ }),
3216
+ params.event_type
3217
+ );
3218
+ const status = inferOperationStatus({
3219
+ eventStatus: normalizeTelemetryString(params.event_status) ?? normalizeTelemetryString(telemetry?.event_status ?? telemetry?.eventStatus),
3220
+ eventType: params.event_type,
3221
+ severity: params.severity
3222
+ });
3223
+ const eventType = deriveOperationEventType({
3224
+ explicitEventType: params.event_type,
3225
+ status,
3226
+ category
3227
+ });
3228
+ const subtype = deriveOperationSubtype({
3229
+ explicitSubtype: normalizeTelemetryString(params.event_subtype) ?? normalizeTelemetryString(telemetry?.event_subtype ?? telemetry?.eventSubtype),
3230
+ telemetry,
3231
+ category,
3232
+ status,
3233
+ eventType
3234
+ });
3235
+ const severity = inferOperationSeverity({
3236
+ explicitSeverity: params.severity,
3237
+ status
3238
+ });
3239
+ const usage = params.usage;
3240
+ const clientEventId = normalizeTelemetryString(params.client_event_id) ?? normalizeTelemetryString(telemetry?.client_event_id);
3241
+ const modelUsed = category === "ai" || hasUsageSignals(usage) || typeof params.model === "string" && params.model.trim().length > 0 && params.model.trim().toLowerCase() !== "not_applicable";
3242
+ const metadata = {
3243
+ ...params.metadata ?? {},
3244
+ ...telemetry ?? {},
3245
+ event_category: category,
3246
+ event_subtype: subtype,
3247
+ event_status: status,
3248
+ status,
3249
+ model_used: modelUsed,
3250
+ spend_bearing: category === "ai" && hasUsageSignals(usage)
3251
+ };
3252
+ if (clientEventId && typeof metadata.client_event_id !== "string") {
3253
+ metadata.client_event_id = clientEventId;
3254
+ }
3255
+ return {
3256
+ event_id: normalizeTelemetryString(params.event_id) ?? createEventId2(),
3257
+ system_id: params.system_id,
3258
+ user_id: params.user_id,
3259
+ request_identity: params.request_identity,
3260
+ input: params.input ?? "",
3261
+ output: params.output ?? "",
3262
+ model: normalizeTelemetryString(params.model) ?? "not_applicable",
3263
+ usage,
3264
+ tokens: params.tokens,
3265
+ latency: params.latency,
3266
+ metadata,
3267
+ event_type: eventType,
3268
+ severity,
3269
+ timestamp: params.timestamp,
3270
+ client_capabilities: params.client_capabilities
3271
+ };
3272
+ }
3273
+ function asTelemetryContext(value) {
3274
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
3275
+ return void 0;
3276
+ }
3277
+ return createAgentIdTelemetryContext(value);
3278
+ }
3279
+ function mergeTelemetryContexts(...contexts) {
3280
+ const merged = {};
3281
+ let hasValues = false;
3282
+ for (const context of contexts) {
3283
+ if (!context) {
3284
+ continue;
3285
+ }
3286
+ Object.assign(merged, createAgentIdTelemetryContext(context));
3287
+ hasValues = true;
3288
+ }
3289
+ return hasValues ? createAgentIdTelemetryContext(merged) : void 0;
3290
+ }
3291
+ function extractRequestTelemetryContext(requestBody) {
3292
+ return asTelemetryContext(requestBody[OPENAI_TELEMETRY_FIELD]);
3293
+ }
3294
+ function stripRequestTelemetryContext(requestBody) {
3295
+ if (!Object.prototype.hasOwnProperty.call(requestBody, OPENAI_TELEMETRY_FIELD)) {
3296
+ return requestBody;
3297
+ }
3298
+ const nextRequestBody = { ...requestBody };
3299
+ delete nextRequestBody[OPENAI_TELEMETRY_FIELD];
3300
+ return nextRequestBody;
3301
+ }
2382
3302
  async function waitForRetry(attemptIndex) {
2383
3303
  const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
2384
3304
  if (!delay) return;
@@ -2558,6 +3478,61 @@ function createStreamingPlaceholderRewriter(piiManager, mapping) {
2558
3478
  }
2559
3479
  };
2560
3480
  }
3481
+ var TYPED_PLACEHOLDER_RE = /<[A-Z][A-Z0-9_]*_\d+>/g;
3482
+ function derivePlaceholderMappingFromTransform(source, transformed) {
3483
+ if (!source || !transformed || source === transformed) {
3484
+ return {};
3485
+ }
3486
+ const placeholders = [...transformed.matchAll(TYPED_PLACEHOLDER_RE)].map((match) => ({
3487
+ token: match[0],
3488
+ start: match.index ?? 0,
3489
+ end: (match.index ?? 0) + match[0].length
3490
+ }));
3491
+ if (placeholders.length === 0) {
3492
+ return {};
3493
+ }
3494
+ const mapping = {};
3495
+ let sourceCursor = 0;
3496
+ let transformedCursor = 0;
3497
+ for (const placeholder of placeholders) {
3498
+ const literalBefore = transformed.slice(transformedCursor, placeholder.start);
3499
+ if (literalBefore) {
3500
+ const literalIndex = source.indexOf(literalBefore, sourceCursor);
3501
+ if (literalIndex < 0) {
3502
+ return {};
3503
+ }
3504
+ sourceCursor = literalIndex + literalBefore.length;
3505
+ }
3506
+ const nextPlaceholderStart = placeholders.find((candidate) => candidate.start > placeholder.start)?.start ?? transformed.length;
3507
+ const literalAfter = transformed.slice(placeholder.end, nextPlaceholderStart);
3508
+ const nextLiteralIndex = literalAfter ? source.indexOf(literalAfter, sourceCursor) : nextPlaceholderStart >= transformed.length ? source.length : sourceCursor;
3509
+ if (nextLiteralIndex < sourceCursor) {
3510
+ return {};
3511
+ }
3512
+ const originalValue = source.slice(sourceCursor, nextLiteralIndex);
3513
+ if (originalValue.length > 0 && typeof mapping[placeholder.token] !== "string") {
3514
+ mapping[placeholder.token] = originalValue;
3515
+ }
3516
+ sourceCursor = nextLiteralIndex;
3517
+ transformedCursor = placeholder.end;
3518
+ }
3519
+ return mapping;
3520
+ }
3521
+ function mergePiiMappings(primary, fallback) {
3522
+ const merged = { ...primary };
3523
+ for (const [placeholder, value] of Object.entries(fallback)) {
3524
+ if (typeof merged[placeholder] !== "string" && typeof value === "string") {
3525
+ merged[placeholder] = value;
3526
+ }
3527
+ }
3528
+ return merged;
3529
+ }
3530
+ function textContainsMappingPlaceholder(text, mapping) {
3531
+ if (!text || !mapping) {
3532
+ return false;
3533
+ }
3534
+ return Object.keys(mapping).some((placeholder) => placeholder.length > 0 && text.includes(placeholder));
3535
+ }
2561
3536
  var SecurityBlockError = class extends Error {
2562
3537
  constructor(reason = "guard_denied") {
2563
3538
  super(`AgentID: Security Blocked (${reason})`);
@@ -2582,6 +3557,7 @@ var AgentID = class {
2582
3557
  this.apiKey = resolveConfiguredApiKey(config.apiKey);
2583
3558
  this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
2584
3559
  this.configuredPiiMasking = typeof config.piiMasking === "boolean" ? config.piiMasking : null;
3560
+ this.configuredSecretMasking = typeof config.secretMasking === "boolean" ? config.secretMasking : null;
2585
3561
  this.checkInjection = config.checkInjection !== false;
2586
3562
  this.clientFastFail = config.clientFastFail === true || config.client_fast_fail === true;
2587
3563
  this.aiScanEnabled = config.aiScanEnabled !== false;
@@ -2603,11 +3579,26 @@ var AgentID = class {
2603
3579
  get piiMasking() {
2604
3580
  return this.configuredPiiMasking ?? void 0;
2605
3581
  }
3582
+ get secretMasking() {
3583
+ return this.configuredSecretMasking ?? void 0;
3584
+ }
2606
3585
  resolveEffectivePiiMasking(config) {
3586
+ if (config?.enable_sdk_pii_masking === true) {
3587
+ return true;
3588
+ }
2607
3589
  if (this.configuredPiiMasking !== null) {
2608
3590
  return this.configuredPiiMasking;
2609
3591
  }
2610
- return config?.enable_sdk_pii_masking === true;
3592
+ return false;
3593
+ }
3594
+ resolveEffectiveSecretMasking(config) {
3595
+ if (config?.enable_sdk_secret_masking === true || config?.enable_sdk_pii_masking === true) {
3596
+ return true;
3597
+ }
3598
+ if (this.configuredSecretMasking !== null) {
3599
+ return this.configuredSecretMasking;
3600
+ }
3601
+ return false;
2611
3602
  }
2612
3603
  getEffectivePiiMasking(options) {
2613
3604
  return this.resolveEffectivePiiMasking(this.getCachedCapabilityConfig(options));
@@ -2615,6 +3606,9 @@ var AgentID = class {
2615
3606
  getEffectivePiiMaskingForConfig(capabilityConfig) {
2616
3607
  return this.resolveEffectivePiiMasking(capabilityConfig);
2617
3608
  }
3609
+ getEffectiveSecretMaskingForConfig(capabilityConfig) {
3610
+ return this.resolveEffectiveSecretMasking(capabilityConfig);
3611
+ }
2618
3612
  buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig) {
2619
3613
  return {
2620
3614
  capabilities: {
@@ -2622,6 +3616,9 @@ var AgentID = class {
2622
3616
  pii_masking_enabled: this.resolveEffectivePiiMasking(
2623
3617
  capabilityConfig ?? this.getCachedCapabilityConfig()
2624
3618
  ),
3619
+ secret_masking_enabled: this.resolveEffectiveSecretMasking(
3620
+ capabilityConfig ?? this.getCachedCapabilityConfig()
3621
+ ),
2625
3622
  framework
2626
3623
  }
2627
3624
  };
@@ -2761,10 +3758,13 @@ var AgentID = class {
2761
3758
  systemId: params.systemId,
2762
3759
  eventId: params.clientEventId,
2763
3760
  clientEventId: params.clientEventId,
2764
- telemetryMetadata: buildSdkTimingMetadata({
2765
- sdkConfigFetchMs: params.sdkConfigFetchMs,
2766
- sdkConfigVersion: params.capabilityConfig.version
2767
- })
3761
+ telemetryMetadata: mergeTelemetryContexts(
3762
+ params.telemetryMetadata,
3763
+ buildSdkTimingMetadata({
3764
+ sdkConfigFetchMs: params.sdkConfigFetchMs,
3765
+ sdkConfigVersion: params.capabilityConfig.version
3766
+ })
3767
+ )
2768
3768
  });
2769
3769
  }
2770
3770
  try {
@@ -2781,7 +3781,8 @@ var AgentID = class {
2781
3781
  actionTaken: event.actionTaken,
2782
3782
  apiKey: params.apiKey,
2783
3783
  sdkConfigFetchMs: params.sdkConfigFetchMs,
2784
- sdkLocalScanMs
3784
+ sdkLocalScanMs,
3785
+ telemetryMetadata: params.telemetryMetadata
2785
3786
  });
2786
3787
  }
2787
3788
  return {
@@ -2796,7 +3797,8 @@ var AgentID = class {
2796
3797
  actionTaken: error.actionTaken,
2797
3798
  apiKey: params.apiKey,
2798
3799
  sdkConfigFetchMs: params.sdkConfigFetchMs,
2799
- sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
3800
+ sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt),
3801
+ telemetryMetadata: params.telemetryMetadata
2800
3802
  });
2801
3803
  }
2802
3804
  throw error;
@@ -2810,7 +3812,7 @@ var AgentID = class {
2810
3812
  );
2811
3813
  let sanitizedInput = params.input;
2812
3814
  let sdkLocalScanMs = 0;
2813
- if (this.configuredPiiMasking === null) {
3815
+ if (this.configuredPiiMasking === null || this.configuredSecretMasking === null) {
2814
3816
  const refreshed = await this.refreshCapabilityConfigBeforeClientControl({
2815
3817
  capabilityConfig,
2816
3818
  sdkConfigFetchMs,
@@ -2821,8 +3823,12 @@ var AgentID = class {
2821
3823
  }
2822
3824
  if (!this.clientFastFail) {
2823
3825
  const effectivePiiMasking2 = this.resolveEffectivePiiMasking(capabilityConfig);
2824
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2) {
2825
- const masked = this.pii.anonymize(sanitizedInput);
3826
+ const effectiveSecretMasking2 = this.resolveEffectiveSecretMasking(capabilityConfig);
3827
+ if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2 || !capabilityConfig.block_secret_leakage && effectiveSecretMasking2) {
3828
+ const masked = this.pii.anonymize(sanitizedInput, {
3829
+ pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking2,
3830
+ secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking2
3831
+ });
2826
3832
  return {
2827
3833
  sanitizedInput: masked.maskedText,
2828
3834
  capabilityConfig,
@@ -2854,13 +3860,18 @@ var AgentID = class {
2854
3860
  apiKey: effectiveApiKey,
2855
3861
  clientEventId: params.clientEventId,
2856
3862
  sdkConfigFetchMs,
3863
+ telemetryMetadata: params.telemetryMetadata,
2857
3864
  runPromptInjectionCheck: !params.skipInjectionScan
2858
3865
  });
2859
3866
  sanitizedInput = enforced.sanitizedInput;
2860
3867
  sdkLocalScanMs = enforced.sdkLocalScanMs;
2861
3868
  const effectivePiiMasking = this.resolveEffectivePiiMasking(capabilityConfig);
2862
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking) {
2863
- const masked = this.pii.anonymize(sanitizedInput);
3869
+ const effectiveSecretMasking = this.resolveEffectiveSecretMasking(capabilityConfig);
3870
+ if (!capabilityConfig.block_pii_leakage && effectivePiiMasking || !capabilityConfig.block_secret_leakage && effectiveSecretMasking) {
3871
+ const masked = this.pii.anonymize(sanitizedInput, {
3872
+ pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking,
3873
+ secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking
3874
+ });
2864
3875
  return {
2865
3876
  sanitizedInput: masked.maskedText,
2866
3877
  capabilityConfig,
@@ -2896,6 +3907,7 @@ var AgentID = class {
2896
3907
  apiKey: effectiveApiKey,
2897
3908
  clientEventId: params.clientEventId,
2898
3909
  sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
3910
+ telemetryMetadata: params.telemetryMetadata,
2899
3911
  runPromptInjectionCheck: true
2900
3912
  });
2901
3913
  return {
@@ -2959,9 +3971,30 @@ var AgentID = class {
2959
3971
  if (!message || typeof message !== "object") {
2960
3972
  return req;
2961
3973
  }
3974
+ const currentContent = message.content;
3975
+ let nextContent = maskedText;
3976
+ if (Array.isArray(currentContent)) {
3977
+ let textReplaced = false;
3978
+ const preservedParts = [];
3979
+ for (const part of currentContent) {
3980
+ if (!part || typeof part !== "object" || part.type !== "text" || typeof part.text !== "string") {
3981
+ preservedParts.push(part);
3982
+ continue;
3983
+ }
3984
+ if (textReplaced) {
3985
+ continue;
3986
+ }
3987
+ textReplaced = true;
3988
+ preservedParts.push({
3989
+ ...part,
3990
+ text: maskedText
3991
+ });
3992
+ }
3993
+ nextContent = textReplaced ? preservedParts : [{ type: "text", text: maskedText }, ...currentContent];
3994
+ }
2962
3995
  newMessages[lastUserIdx] = {
2963
3996
  ...message,
2964
- content: maskedText
3997
+ content: nextContent
2965
3998
  };
2966
3999
  if (!req || typeof req !== "object") {
2967
4000
  return req;
@@ -2980,6 +4013,7 @@ var AgentID = class {
2980
4013
  event_type: "security_policy_violation",
2981
4014
  severity: "high",
2982
4015
  metadata: {
4016
+ ...params.telemetryMetadata ?? {},
2983
4017
  event_type: "security_policy_violation",
2984
4018
  severity: "high",
2985
4019
  system_id: params.systemId,
@@ -3007,6 +4041,7 @@ var AgentID = class {
3007
4041
  event_type: "security_alert",
3008
4042
  severity: "warning",
3009
4043
  metadata: {
4044
+ ...params.guardParams.metadata ?? {},
3010
4045
  source: "guard",
3011
4046
  status: params.status,
3012
4047
  guard_reason: params.reason,
@@ -3449,21 +4484,29 @@ var AgentID = class {
3449
4484
  wrapCompletion(completion, options) {
3450
4485
  if (typeof completion === "string") {
3451
4486
  const masked = this.pii.anonymize(completion);
4487
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4488
+ completion,
4489
+ options?.piiMapping
4490
+ );
3452
4491
  return {
3453
4492
  mode: "static",
3454
4493
  rawOutput: completion,
3455
4494
  transformedOutput: masked.maskedText,
3456
- outputMasked: masked.maskedText !== completion
4495
+ outputMasked: masked.maskedText !== completion || placeholderOutputMasked
3457
4496
  };
3458
4497
  }
3459
4498
  if (!isAsyncIterable(completion)) {
3460
4499
  const asText = String(completion ?? "");
3461
4500
  const masked = this.pii.anonymize(asText);
4501
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4502
+ asText,
4503
+ options?.piiMapping
4504
+ );
3462
4505
  return {
3463
4506
  mode: "static",
3464
4507
  rawOutput: asText,
3465
4508
  transformedOutput: masked.maskedText,
3466
- outputMasked: masked.maskedText !== asText
4509
+ outputMasked: masked.maskedText !== asText || placeholderOutputMasked
3467
4510
  };
3468
4511
  }
3469
4512
  const source = completion;
@@ -3473,8 +4516,10 @@ var AgentID = class {
3473
4516
  const isOpenAIStreamFinishChunk = this.isOpenAIStreamFinishChunk.bind(this);
3474
4517
  const rewriteOpenAIStreamChunkForClient = this.rewriteOpenAIStreamChunkForClient.bind(this);
3475
4518
  const createSyntheticOpenAIStreamChunk = this.createSyntheticOpenAIStreamChunk.bind(this);
4519
+ const setOpenAIStreamChunkText = this.setOpenAIStreamChunkText.bind(this);
3476
4520
  const piiManager = this.pii;
3477
4521
  const streamRewriter = options?.deanonymizeForClient === true && options.piiMapping ? createStreamingPlaceholderRewriter(piiManager, options.piiMapping) : null;
4522
+ const maskForClient = options?.maskForClient === true && streamRewriter === null;
3478
4523
  let lastUsage;
3479
4524
  let resolveDone = null;
3480
4525
  let rejectDone = null;
@@ -3487,12 +4532,17 @@ var AgentID = class {
3487
4532
  try {
3488
4533
  let finishChunkFlushed = false;
3489
4534
  let lastChunkTemplate;
4535
+ let clientRawText = "";
4536
+ let clientMaskFlushed = false;
3490
4537
  for await (const chunk of source) {
3491
4538
  const chunkText = extractStreamChunkText(chunk);
3492
- const isFinishChunk = streamRewriter ? isOpenAIStreamFinishChunk(chunk) : false;
4539
+ const isFinishChunk = streamRewriter || maskForClient ? isOpenAIStreamFinishChunk(chunk) : false;
3493
4540
  if (chunkText) {
3494
4541
  await collector.push(chunkText);
3495
4542
  lastChunkTemplate = chunk;
4543
+ if (maskForClient) {
4544
+ clientRawText += chunkText;
4545
+ }
3496
4546
  }
3497
4547
  const chunkUsage = extractStreamChunkUsage(chunk);
3498
4548
  if (chunkUsage) {
@@ -3512,6 +4562,28 @@ var AgentID = class {
3512
4562
  }
3513
4563
  continue;
3514
4564
  }
4565
+ if (maskForClient) {
4566
+ if (isFinishChunk) {
4567
+ const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
4568
+ clientMaskFlushed = true;
4569
+ if (maskedClientText.length > 0) {
4570
+ yield createSyntheticOpenAIStreamChunk(
4571
+ maskedClientText,
4572
+ lastChunkTemplate ?? chunk
4573
+ );
4574
+ }
4575
+ if (chunkText) {
4576
+ setOpenAIStreamChunkText(chunk, "");
4577
+ }
4578
+ yield chunk;
4579
+ finishChunkFlushed = true;
4580
+ continue;
4581
+ }
4582
+ if (!chunkText) {
4583
+ yield chunk;
4584
+ }
4585
+ continue;
4586
+ }
3515
4587
  yield chunk;
3516
4588
  }
3517
4589
  if (streamRewriter && !finishChunkFlushed) {
@@ -3523,14 +4595,27 @@ var AgentID = class {
3523
4595
  );
3524
4596
  }
3525
4597
  }
4598
+ if (maskForClient && !clientMaskFlushed) {
4599
+ const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
4600
+ if (maskedClientText.length > 0) {
4601
+ yield createSyntheticOpenAIStreamChunk(
4602
+ maskedClientText,
4603
+ lastChunkTemplate
4604
+ );
4605
+ }
4606
+ }
3526
4607
  await collector.close();
3527
4608
  const rawOutput = await collector.result;
3528
4609
  const masked = piiManager.anonymize(rawOutput);
4610
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4611
+ rawOutput,
4612
+ options?.piiMapping
4613
+ );
3529
4614
  resolveDone?.({
3530
4615
  mode: "static",
3531
4616
  rawOutput,
3532
4617
  transformedOutput: masked.maskedText,
3533
- outputMasked: masked.maskedText !== rawOutput,
4618
+ outputMasked: masked.maskedText !== rawOutput || placeholderOutputMasked,
3534
4619
  usage: lastUsage
3535
4620
  });
3536
4621
  } catch (error) {
@@ -3565,6 +4650,37 @@ var AgentID = class {
3565
4650
  );
3566
4651
  }
3567
4652
  }
4653
+ buildOperationLogParams(params) {
4654
+ return createAgentIdOperationLog(params);
4655
+ }
4656
+ async logOperation(params, options) {
4657
+ return this.log(this.buildOperationLogParams(params), options);
4658
+ }
4659
+ async logPromptPreflightStep(params, options) {
4660
+ const telemetry = buildPromptPreflightTelemetry(params);
4661
+ const summary = firstNonEmptyString(telemetry?.step_summary, telemetry?.stepSummary) ?? summarizePromptPreflightResult({
4662
+ verdict: params.verdict,
4663
+ localFallbackApplied: params.local_fallback_applied,
4664
+ localFallbackReason: params.local_fallback_reason
4665
+ });
4666
+ await this.logOperation(
4667
+ {
4668
+ system_id: params.system_id,
4669
+ user_id: params.user_id,
4670
+ request_identity: params.request_identity,
4671
+ input: params.input,
4672
+ output: summary,
4673
+ model: "not_applicable",
4674
+ latency: params.guard_latency_ms ?? void 0,
4675
+ telemetry,
4676
+ client_capabilities: params.client_capabilities
4677
+ },
4678
+ options
4679
+ );
4680
+ }
4681
+ operation(params, options) {
4682
+ return this.logOperation(params, options);
4683
+ }
3568
4684
  /**
3569
4685
  * Analytics alias for telemetry logging.
3570
4686
  */
@@ -3609,49 +4725,56 @@ var AgentID = class {
3609
4725
  if (typeof originalCreate !== "function") return originalCreate;
3610
4726
  return async (...args) => {
3611
4727
  const normalizedCreateArgs = normalizeOpenAICreateArgs(args);
3612
- const req = normalizedCreateArgs?.[0] ?? {};
4728
+ const rawReq = normalizedCreateArgs?.[0] ?? {};
4729
+ const requestTelemetry = extractRequestTelemetryContext(rawReq);
4730
+ const telemetryMetadata = mergeTelemetryContexts(
4731
+ options.telemetry,
4732
+ requestTelemetry
4733
+ );
4734
+ const providerReq = stripRequestTelemetryContext(rawReq);
3613
4735
  const pipelineStartedAt = Date.now();
3614
- const requestLevelApiKey = options.resolveApiKey?.(req) ?? options.apiKey ?? options.api_key;
4736
+ const requestLevelApiKey = options.resolveApiKey?.(rawReq) ?? options.apiKey ?? options.api_key;
3615
4737
  const effectiveApiKey = this.resolveApiKey(requestLevelApiKey);
3616
4738
  const requestOptions = { apiKey: effectiveApiKey };
3617
- const clientEventId = this.resolveClientEventId(req);
4739
+ const clientEventId = this.resolveClientEventId(rawReq);
3618
4740
  const effectiveStrictMode = await this.resolveEffectiveStrictMode(requestOptions);
3619
- const stream = adapter.isStream(req);
4741
+ const stream = adapter.isStream(providerReq);
3620
4742
  let capabilityConfig = this.getCachedCapabilityConfig(requestOptions);
3621
- const userText = adapter.extractInput(req);
3622
- let maskedText = userText;
3623
- let maskedReq = req;
3624
- let createArgs = normalizedCreateArgs;
4743
+ const userText = adapter.extractInput(providerReq);
4744
+ const requestAttachments = adapter.extractAttachments(providerReq);
4745
+ const hasGuardContent = userText !== null || requestAttachments.length > 0;
4746
+ let maskedText = userText ?? "";
4747
+ let maskedReq = providerReq;
4748
+ let createArgs = providerReq === rawReq ? normalizedCreateArgs : [{ ...providerReq }, ...normalizedCreateArgs.slice(1)];
3625
4749
  let mapping = {};
3626
- let shouldDeanonymize = false;
3627
4750
  let sdkConfigFetchMs = 0;
3628
4751
  let sdkLocalScanMs = 0;
3629
- if (userText) {
4752
+ if (hasGuardContent) {
3630
4753
  const prepared = await this.prepareInputForDispatch({
3631
- input: userText,
4754
+ input: userText ?? "",
3632
4755
  systemId,
3633
4756
  stream,
3634
- clientEventId
4757
+ clientEventId,
4758
+ telemetryMetadata
3635
4759
  }, requestOptions);
3636
4760
  capabilityConfig = prepared.capabilityConfig;
3637
4761
  maskedText = prepared.sanitizedInput;
3638
4762
  mapping = prepared.piiMapping ?? {};
3639
- shouldDeanonymize = prepared.shouldDeanonymize === true;
3640
4763
  sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
3641
4764
  sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
3642
- if (maskedText !== userText) {
4765
+ if (maskedText !== (userText ?? "")) {
3643
4766
  maskedReq = this.withMaskedOpenAIRequest(
3644
- req,
4767
+ providerReq,
3645
4768
  maskedText
3646
4769
  );
3647
- const nextCreateArgs = [...normalizedCreateArgs];
4770
+ const nextCreateArgs = [...createArgs];
3648
4771
  nextCreateArgs[0] = maskedReq;
3649
4772
  createArgs = nextCreateArgs;
3650
4773
  }
3651
4774
  }
3652
- if (!maskedText) {
4775
+ if (!hasGuardContent) {
3653
4776
  throw new Error(
3654
- "AgentID: No user message found. Security guard requires string input."
4777
+ "AgentID: No user message or supported inline attachment found. Security guard requires prompt content."
3655
4778
  );
3656
4779
  }
3657
4780
  const verdict = await this.guard({
@@ -3662,6 +4785,8 @@ var AgentID = class {
3662
4785
  client_event_id: clientEventId,
3663
4786
  expected_languages: expectedLanguages,
3664
4787
  request_identity: options.request_identity,
4788
+ metadata: telemetryMetadata,
4789
+ attachments: requestAttachments,
3665
4790
  client_capabilities: this.buildClientCapabilities(
3666
4791
  "openai",
3667
4792
  false,
@@ -3683,22 +4808,43 @@ var AgentID = class {
3683
4808
  apiKey: effectiveApiKey,
3684
4809
  clientEventId,
3685
4810
  sdkConfigFetchMs,
4811
+ telemetryMetadata,
3686
4812
  runPromptInjectionCheck: true
3687
4813
  });
3688
4814
  maskedText = fallback.sanitizedInput;
3689
4815
  sdkLocalScanMs = fallback.sdkLocalScanMs;
3690
4816
  }
3691
4817
  } else {
4818
+ await this.logPromptPreflightStep(
4819
+ {
4820
+ system_id: systemId,
4821
+ user_id: options.user_id,
4822
+ request_identity: options.request_identity,
4823
+ input: maskedText,
4824
+ telemetry: telemetryMetadata,
4825
+ verdict,
4826
+ guard_event_id: verdict.guard_event_id ?? null,
4827
+ 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),
4828
+ preflight_for_client_event_id: typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId,
4829
+ client_capabilities: this.buildClientCapabilities(
4830
+ "openai",
4831
+ false,
4832
+ capabilityConfig
4833
+ ),
4834
+ runtime_surface: "openai_sdk_guard"
4835
+ },
4836
+ requestOptions
4837
+ );
3692
4838
  throw new SecurityBlockError(verdict.reason ?? "guard_denied");
3693
4839
  }
3694
4840
  }
3695
- const currentRequestInput = adapter.extractInput(maskedReq);
4841
+ const currentRequestInput = adapter.extractInput(maskedReq) ?? "";
3696
4842
  if (maskedText !== currentRequestInput) {
3697
4843
  maskedReq = this.withMaskedOpenAIRequest(
3698
- req,
4844
+ providerReq,
3699
4845
  maskedText
3700
4846
  );
3701
- const nextCreateArgs = [...normalizedCreateArgs];
4847
+ const nextCreateArgs = [...createArgs];
3702
4848
  nextCreateArgs[0] = maskedReq;
3703
4849
  createArgs = nextCreateArgs;
3704
4850
  }
@@ -3709,15 +4855,44 @@ var AgentID = class {
3709
4855
  const isShadowMode = verdict.shadow_mode === true;
3710
4856
  const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
3711
4857
  if (transformedInput !== maskedText) {
4858
+ const serverDerivedMapping = derivePlaceholderMappingFromTransform(
4859
+ maskedText,
4860
+ transformedInput
4861
+ );
4862
+ if (Object.keys(serverDerivedMapping).length > 0) {
4863
+ mapping = mergePiiMappings(mapping, serverDerivedMapping);
4864
+ }
3712
4865
  maskedText = transformedInput;
3713
4866
  maskedReq = this.withMaskedOpenAIRequest(
3714
- req,
4867
+ providerReq,
3715
4868
  transformedInput
3716
4869
  );
3717
- const nextCreateArgs = [...normalizedCreateArgs];
4870
+ const nextCreateArgs = [...createArgs];
3718
4871
  nextCreateArgs[0] = maskedReq;
3719
4872
  createArgs = nextCreateArgs;
3720
4873
  }
4874
+ await this.logPromptPreflightStep(
4875
+ {
4876
+ system_id: systemId,
4877
+ user_id: options.user_id,
4878
+ request_identity: options.request_identity,
4879
+ input: maskedText,
4880
+ telemetry: telemetryMetadata,
4881
+ verdict,
4882
+ guard_event_id: guardEventId,
4883
+ guard_latency_ms: guardLatencyMs,
4884
+ preflight_for_client_event_id: canonicalClientEventId,
4885
+ client_capabilities: this.buildClientCapabilities(
4886
+ "openai",
4887
+ false,
4888
+ capabilityConfig
4889
+ ),
4890
+ local_fallback_applied: localFallbackApplied,
4891
+ local_fallback_reason: localFallbackReason,
4892
+ runtime_surface: "openai_sdk_guard"
4893
+ },
4894
+ requestOptions
4895
+ );
3721
4896
  if (stream) {
3722
4897
  const modelStartedAt2 = Date.now();
3723
4898
  const streamResponse = await originalCreate.apply(compTarget, createArgs);
@@ -3729,7 +4904,8 @@ var AgentID = class {
3729
4904
  })(),
3730
4905
  {
3731
4906
  piiMapping: mapping,
3732
- deanonymizeForClient: shouldDeanonymize
4907
+ deanonymizeForClient: false,
4908
+ maskForClient: !isShadowMode
3733
4909
  }
3734
4910
  );
3735
4911
  if (maskedText && wrappedCompletion.mode === "stream") {
@@ -3748,29 +4924,32 @@ var AgentID = class {
3748
4924
  usage: result.usage,
3749
4925
  latency: modelLatencyMs2,
3750
4926
  event_type: "complete",
3751
- metadata: {
3752
- transformed_input: maskedText,
3753
- transformed_output: result.transformedOutput,
3754
- output_masked: result.outputMasked,
3755
- shadow_mode: isShadowMode,
3756
- simulated_decision: verdict.simulated_decision ?? null,
3757
- simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
3758
- response_streamed: true,
3759
- sdk_local_fallback_applied: localFallbackApplied,
3760
- sdk_local_fallback_reason: localFallbackReason,
3761
- guard_latency_ms: guardLatencyMs,
3762
- model_latency_ms: modelLatencyMs2,
3763
- total_pipeline_latency_ms: totalPipelineLatencyMs2,
3764
- guard_event_id: guardEventId,
3765
- client_event_id: canonicalClientEventId,
3766
- transparency,
3767
- ...buildSdkTimingMetadata({
4927
+ metadata: mergeTelemetryContexts(
4928
+ telemetryMetadata,
4929
+ {
4930
+ transformed_input: maskedText,
4931
+ transformed_output: result.transformedOutput,
4932
+ output_masked: result.outputMasked,
4933
+ shadow_mode: isShadowMode,
4934
+ simulated_decision: verdict.simulated_decision ?? null,
4935
+ simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
4936
+ response_streamed: true,
4937
+ sdk_local_fallback_applied: localFallbackApplied,
4938
+ sdk_local_fallback_reason: localFallbackReason,
4939
+ guard_latency_ms: guardLatencyMs,
4940
+ model_latency_ms: modelLatencyMs2,
4941
+ total_pipeline_latency_ms: totalPipelineLatencyMs2,
4942
+ guard_event_id: guardEventId,
4943
+ client_event_id: canonicalClientEventId,
4944
+ transparency
4945
+ },
4946
+ buildSdkTimingMetadata({
3768
4947
  sdkConfigFetchMs,
3769
4948
  sdkLocalScanMs,
3770
4949
  sdkGuardMs: guardLatencyMs,
3771
4950
  sdkConfigVersion: capabilityConfig.version
3772
4951
  })
3773
- },
4952
+ ),
3774
4953
  client_capabilities: this.buildClientCapabilities(
3775
4954
  "openai",
3776
4955
  false,
@@ -3801,7 +4980,10 @@ var AgentID = class {
3801
4980
  const totalPipelineLatencyMs = Math.max(0, Date.now() - pipelineStartedAt);
3802
4981
  if (maskedText) {
3803
4982
  const output = adapter.extractOutput(res);
3804
- const wrappedCompletion = this.wrapCompletion(output);
4983
+ const wrappedCompletion = this.wrapCompletion(output, {
4984
+ piiMapping: mapping,
4985
+ deanonymizeForClient: false
4986
+ });
3805
4987
  const model = adapter.getModelName(maskedReq, res);
3806
4988
  const usage = adapter.getTokenUsage(res);
3807
4989
  const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
@@ -3816,29 +4998,32 @@ var AgentID = class {
3816
4998
  usage,
3817
4999
  latency: modelLatencyMs,
3818
5000
  event_type: "complete",
3819
- metadata: {
3820
- transformed_input: maskedText,
3821
- transformed_output: wrappedCompletion.transformedOutput,
3822
- output_masked: wrappedCompletion.outputMasked,
3823
- shadow_mode: isShadowMode,
3824
- simulated_decision: verdict.simulated_decision ?? null,
3825
- simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
3826
- response_streamed: false,
3827
- sdk_local_fallback_applied: localFallbackApplied,
3828
- sdk_local_fallback_reason: localFallbackReason,
3829
- guard_latency_ms: guardLatencyMs,
3830
- model_latency_ms: modelLatencyMs,
3831
- total_pipeline_latency_ms: totalPipelineLatencyMs,
3832
- guard_event_id: guardEventId,
3833
- client_event_id: canonicalClientEventId,
3834
- transparency,
3835
- ...buildSdkTimingMetadata({
5001
+ metadata: mergeTelemetryContexts(
5002
+ telemetryMetadata,
5003
+ {
5004
+ transformed_input: maskedText,
5005
+ transformed_output: wrappedCompletion.transformedOutput,
5006
+ output_masked: wrappedCompletion.outputMasked,
5007
+ shadow_mode: isShadowMode,
5008
+ simulated_decision: verdict.simulated_decision ?? null,
5009
+ simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
5010
+ response_streamed: false,
5011
+ sdk_local_fallback_applied: localFallbackApplied,
5012
+ sdk_local_fallback_reason: localFallbackReason,
5013
+ guard_latency_ms: guardLatencyMs,
5014
+ model_latency_ms: modelLatencyMs,
5015
+ total_pipeline_latency_ms: totalPipelineLatencyMs,
5016
+ guard_event_id: guardEventId,
5017
+ client_event_id: canonicalClientEventId,
5018
+ transparency
5019
+ },
5020
+ buildSdkTimingMetadata({
3836
5021
  sdkConfigFetchMs,
3837
5022
  sdkLocalScanMs,
3838
5023
  sdkGuardMs: guardLatencyMs,
3839
5024
  sdkConfigVersion: capabilityConfig.version
3840
5025
  })
3841
- },
5026
+ ),
3842
5027
  client_capabilities: this.buildClientCapabilities(
3843
5028
  "openai",
3844
5029
  false,
@@ -3855,17 +5040,21 @@ var AgentID = class {
3855
5040
  );
3856
5041
  }
3857
5042
  }
3858
- if (!capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig) && shouldDeanonymize) {
3859
- const deanon = this.pii.deanonymize(adapter.extractOutput(res), mapping);
5043
+ if (!isShadowMode && maskedText) {
5044
+ const output = adapter.extractOutput(res);
5045
+ const maskedOutput = this.wrapCompletion(output, {
5046
+ piiMapping: mapping,
5047
+ deanonymizeForClient: false
5048
+ }).transformedOutput;
3860
5049
  try {
3861
5050
  if (Array.isArray(res?.choices)) {
3862
5051
  for (const choice of res.choices) {
3863
5052
  const typedChoice = choice;
3864
5053
  if (typedChoice?.message && typeof typedChoice.message.content === "string") {
3865
- typedChoice.message.content = deanon;
5054
+ typedChoice.message.content = maskedOutput;
3866
5055
  }
3867
5056
  if (typedChoice?.delta && typeof typedChoice.delta.content === "string") {
3868
- typedChoice.delta.content = deanon;
5057
+ typedChoice.delta.content = maskedOutput;
3869
5058
  }
3870
5059
  }
3871
5060
  }
@@ -3890,6 +5079,155 @@ var AgentID = class {
3890
5079
  });
3891
5080
  }
3892
5081
  };
5082
+ function mergeWorkflowTrailRequestOptions(base, override) {
5083
+ const apiKey = firstNonEmptyString(override?.apiKey, base?.apiKey);
5084
+ return apiKey ? { apiKey } : void 0;
5085
+ }
5086
+ function appendWorkflowErrorMetadata(metadata, error) {
5087
+ const nextMetadata = { ...metadata ?? {} };
5088
+ if (error instanceof Error) {
5089
+ if (typeof nextMetadata.error_name !== "string") {
5090
+ nextMetadata.error_name = error.name;
5091
+ }
5092
+ if (typeof nextMetadata.error_message !== "string" && error.message.trim().length > 0) {
5093
+ nextMetadata.error_message = error.message.trim();
5094
+ }
5095
+ return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
5096
+ }
5097
+ if (typeof nextMetadata.error_message !== "string" && typeof error !== "undefined") {
5098
+ const errorMessage = String(error).trim();
5099
+ if (errorMessage.length > 0) {
5100
+ nextMetadata.error_message = errorMessage;
5101
+ }
5102
+ }
5103
+ return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
5104
+ }
5105
+ var AgentIDWorkflowStep = class {
5106
+ constructor(params) {
5107
+ this.trail = params.trail;
5108
+ this.workflowStepId = params.workflowStepId;
5109
+ this.startEventId = params.startEventId;
5110
+ this.telemetry = params.telemetry;
5111
+ this.startedAtMs = params.startedAtMs;
5112
+ }
5113
+ resolveStepTelemetry(telemetry) {
5114
+ return mergeTelemetryContexts(
5115
+ this.telemetry,
5116
+ createAgentIdTelemetryContext({
5117
+ workflow_step_id: this.workflowStepId,
5118
+ parent_event_id: this.startEventId
5119
+ }),
5120
+ telemetry
5121
+ );
5122
+ }
5123
+ async log(params = {}, options) {
5124
+ return this.trail.logStep(
5125
+ {
5126
+ ...params,
5127
+ telemetry: this.resolveStepTelemetry(params.telemetry)
5128
+ },
5129
+ options
5130
+ );
5131
+ }
5132
+ async complete(params = {}, options) {
5133
+ return this.log(
5134
+ {
5135
+ ...params,
5136
+ latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
5137
+ event_status: params.event_status ?? "completed"
5138
+ },
5139
+ options
5140
+ );
5141
+ }
5142
+ async fail(error, params = {}, options) {
5143
+ return this.log(
5144
+ {
5145
+ ...params,
5146
+ latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
5147
+ metadata: appendWorkflowErrorMetadata(params.metadata, error),
5148
+ event_type: params.event_type ?? "error",
5149
+ event_status: params.event_status ?? "failed",
5150
+ severity: params.severity ?? "error"
5151
+ },
5152
+ options
5153
+ );
5154
+ }
5155
+ };
5156
+ var AgentIDWorkflowTrail = class {
5157
+ constructor(options) {
5158
+ this.agent = options.agent;
5159
+ this.systemId = options.system_id;
5160
+ this.userId = options.user_id;
5161
+ this.requestIdentity = options.request_identity;
5162
+ this.telemetry = createAgentIdTelemetryContext(options.telemetry);
5163
+ this.clientCapabilities = options.client_capabilities;
5164
+ this.requestOptions = options.requestOptions;
5165
+ }
5166
+ async logStep(params = {}, options) {
5167
+ const payload = this.agent.buildOperationLogParams({
5168
+ ...params,
5169
+ system_id: this.systemId,
5170
+ user_id: this.userId,
5171
+ request_identity: this.requestIdentity,
5172
+ telemetry: mergeTelemetryContexts(this.telemetry, params.telemetry),
5173
+ client_capabilities: params.client_capabilities ?? this.clientCapabilities
5174
+ });
5175
+ await this.agent.log(
5176
+ payload,
5177
+ mergeWorkflowTrailRequestOptions(this.requestOptions, options)
5178
+ );
5179
+ return payload;
5180
+ }
5181
+ async startStep(params = {}, options) {
5182
+ const startedAtMs = Date.now();
5183
+ const requestedTelemetry = createAgentIdTelemetryContext(params.telemetry);
5184
+ const workflowStepId = firstNonEmptyString(requestedTelemetry?.workflow_step_id, requestedTelemetry?.workflowStepId) ?? createAgentIdCorrelationId();
5185
+ const startTelemetry = mergeTelemetryContexts(
5186
+ requestedTelemetry,
5187
+ createAgentIdTelemetryContext({
5188
+ workflow_step_id: workflowStepId
5189
+ })
5190
+ );
5191
+ const startPayload = await this.logStep(
5192
+ {
5193
+ ...params,
5194
+ telemetry: startTelemetry,
5195
+ event_type: params.event_type ?? "start",
5196
+ event_status: params.event_status ?? "started"
5197
+ },
5198
+ options
5199
+ );
5200
+ return new AgentIDWorkflowStep({
5201
+ trail: this,
5202
+ workflowStepId,
5203
+ startEventId: startPayload.event_id ?? createEventId2(),
5204
+ telemetry: startTelemetry,
5205
+ startedAtMs
5206
+ });
5207
+ }
5208
+ async runStep(params, run, hooks, options) {
5209
+ const step = await this.startStep(params, options);
5210
+ try {
5211
+ const result = await run();
5212
+ const completeParams = {
5213
+ ...hooks?.complete ?? {},
5214
+ ...hooks?.onComplete?.(result) ?? {}
5215
+ };
5216
+ await step.complete(completeParams, options);
5217
+ return result;
5218
+ } catch (error) {
5219
+ const failParams = {
5220
+ ...hooks?.fail ?? {},
5221
+ ...hooks?.onError?.(error) ?? {}
5222
+ };
5223
+ await step.fail(error, failParams, options);
5224
+ throw error;
5225
+ }
5226
+ }
5227
+ };
5228
+ function createAgentIdWorkflowTrail(options) {
5229
+ return new AgentIDWorkflowTrail(options);
5230
+ }
3893
5231
 
3894
5232
  export {
3895
5233
  OpenAIAdapter,
@@ -3897,7 +5235,13 @@ export {
3897
5235
  scanWithRegex,
3898
5236
  InjectionScanner,
3899
5237
  getInjectionScanner,
5238
+ createAgentIdCorrelationId,
5239
+ createAgentIdTelemetryContext,
5240
+ createAgentIdOperationLog,
3900
5241
  SecurityBlockError,
3901
5242
  DependencyError,
3902
- AgentID
5243
+ AgentID,
5244
+ AgentIDWorkflowStep,
5245
+ AgentIDWorkflowTrail,
5246
+ createAgentIdWorkflowTrail
3903
5247
  };