agentid-sdk 0.1.37 → 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.37".trim().length > 0 ? "js-0.1.37" : 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,6 +3579,9 @@ 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) {
2607
3586
  if (config?.enable_sdk_pii_masking === true) {
2608
3587
  return true;
@@ -2612,12 +3591,24 @@ var AgentID = class {
2612
3591
  }
2613
3592
  return false;
2614
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;
3602
+ }
2615
3603
  getEffectivePiiMasking(options) {
2616
3604
  return this.resolveEffectivePiiMasking(this.getCachedCapabilityConfig(options));
2617
3605
  }
2618
3606
  getEffectivePiiMaskingForConfig(capabilityConfig) {
2619
3607
  return this.resolveEffectivePiiMasking(capabilityConfig);
2620
3608
  }
3609
+ getEffectiveSecretMaskingForConfig(capabilityConfig) {
3610
+ return this.resolveEffectiveSecretMasking(capabilityConfig);
3611
+ }
2621
3612
  buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig) {
2622
3613
  return {
2623
3614
  capabilities: {
@@ -2625,6 +3616,9 @@ var AgentID = class {
2625
3616
  pii_masking_enabled: this.resolveEffectivePiiMasking(
2626
3617
  capabilityConfig ?? this.getCachedCapabilityConfig()
2627
3618
  ),
3619
+ secret_masking_enabled: this.resolveEffectiveSecretMasking(
3620
+ capabilityConfig ?? this.getCachedCapabilityConfig()
3621
+ ),
2628
3622
  framework
2629
3623
  }
2630
3624
  };
@@ -2764,10 +3758,13 @@ var AgentID = class {
2764
3758
  systemId: params.systemId,
2765
3759
  eventId: params.clientEventId,
2766
3760
  clientEventId: params.clientEventId,
2767
- telemetryMetadata: buildSdkTimingMetadata({
2768
- sdkConfigFetchMs: params.sdkConfigFetchMs,
2769
- sdkConfigVersion: params.capabilityConfig.version
2770
- })
3761
+ telemetryMetadata: mergeTelemetryContexts(
3762
+ params.telemetryMetadata,
3763
+ buildSdkTimingMetadata({
3764
+ sdkConfigFetchMs: params.sdkConfigFetchMs,
3765
+ sdkConfigVersion: params.capabilityConfig.version
3766
+ })
3767
+ )
2771
3768
  });
2772
3769
  }
2773
3770
  try {
@@ -2784,7 +3781,8 @@ var AgentID = class {
2784
3781
  actionTaken: event.actionTaken,
2785
3782
  apiKey: params.apiKey,
2786
3783
  sdkConfigFetchMs: params.sdkConfigFetchMs,
2787
- sdkLocalScanMs
3784
+ sdkLocalScanMs,
3785
+ telemetryMetadata: params.telemetryMetadata
2788
3786
  });
2789
3787
  }
2790
3788
  return {
@@ -2799,7 +3797,8 @@ var AgentID = class {
2799
3797
  actionTaken: error.actionTaken,
2800
3798
  apiKey: params.apiKey,
2801
3799
  sdkConfigFetchMs: params.sdkConfigFetchMs,
2802
- sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
3800
+ sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt),
3801
+ telemetryMetadata: params.telemetryMetadata
2803
3802
  });
2804
3803
  }
2805
3804
  throw error;
@@ -2813,7 +3812,7 @@ var AgentID = class {
2813
3812
  );
2814
3813
  let sanitizedInput = params.input;
2815
3814
  let sdkLocalScanMs = 0;
2816
- if (this.configuredPiiMasking === null) {
3815
+ if (this.configuredPiiMasking === null || this.configuredSecretMasking === null) {
2817
3816
  const refreshed = await this.refreshCapabilityConfigBeforeClientControl({
2818
3817
  capabilityConfig,
2819
3818
  sdkConfigFetchMs,
@@ -2824,8 +3823,12 @@ var AgentID = class {
2824
3823
  }
2825
3824
  if (!this.clientFastFail) {
2826
3825
  const effectivePiiMasking2 = this.resolveEffectivePiiMasking(capabilityConfig);
2827
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2) {
2828
- 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
+ });
2829
3832
  return {
2830
3833
  sanitizedInput: masked.maskedText,
2831
3834
  capabilityConfig,
@@ -2857,13 +3860,18 @@ var AgentID = class {
2857
3860
  apiKey: effectiveApiKey,
2858
3861
  clientEventId: params.clientEventId,
2859
3862
  sdkConfigFetchMs,
3863
+ telemetryMetadata: params.telemetryMetadata,
2860
3864
  runPromptInjectionCheck: !params.skipInjectionScan
2861
3865
  });
2862
3866
  sanitizedInput = enforced.sanitizedInput;
2863
3867
  sdkLocalScanMs = enforced.sdkLocalScanMs;
2864
3868
  const effectivePiiMasking = this.resolveEffectivePiiMasking(capabilityConfig);
2865
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking) {
2866
- 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
+ });
2867
3875
  return {
2868
3876
  sanitizedInput: masked.maskedText,
2869
3877
  capabilityConfig,
@@ -2899,6 +3907,7 @@ var AgentID = class {
2899
3907
  apiKey: effectiveApiKey,
2900
3908
  clientEventId: params.clientEventId,
2901
3909
  sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
3910
+ telemetryMetadata: params.telemetryMetadata,
2902
3911
  runPromptInjectionCheck: true
2903
3912
  });
2904
3913
  return {
@@ -2962,9 +3971,30 @@ var AgentID = class {
2962
3971
  if (!message || typeof message !== "object") {
2963
3972
  return req;
2964
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
+ }
2965
3995
  newMessages[lastUserIdx] = {
2966
3996
  ...message,
2967
- content: maskedText
3997
+ content: nextContent
2968
3998
  };
2969
3999
  if (!req || typeof req !== "object") {
2970
4000
  return req;
@@ -2983,6 +4013,7 @@ var AgentID = class {
2983
4013
  event_type: "security_policy_violation",
2984
4014
  severity: "high",
2985
4015
  metadata: {
4016
+ ...params.telemetryMetadata ?? {},
2986
4017
  event_type: "security_policy_violation",
2987
4018
  severity: "high",
2988
4019
  system_id: params.systemId,
@@ -3010,6 +4041,7 @@ var AgentID = class {
3010
4041
  event_type: "security_alert",
3011
4042
  severity: "warning",
3012
4043
  metadata: {
4044
+ ...params.guardParams.metadata ?? {},
3013
4045
  source: "guard",
3014
4046
  status: params.status,
3015
4047
  guard_reason: params.reason,
@@ -3452,21 +4484,29 @@ var AgentID = class {
3452
4484
  wrapCompletion(completion, options) {
3453
4485
  if (typeof completion === "string") {
3454
4486
  const masked = this.pii.anonymize(completion);
4487
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4488
+ completion,
4489
+ options?.piiMapping
4490
+ );
3455
4491
  return {
3456
4492
  mode: "static",
3457
4493
  rawOutput: completion,
3458
4494
  transformedOutput: masked.maskedText,
3459
- outputMasked: masked.maskedText !== completion
4495
+ outputMasked: masked.maskedText !== completion || placeholderOutputMasked
3460
4496
  };
3461
4497
  }
3462
4498
  if (!isAsyncIterable(completion)) {
3463
4499
  const asText = String(completion ?? "");
3464
4500
  const masked = this.pii.anonymize(asText);
4501
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4502
+ asText,
4503
+ options?.piiMapping
4504
+ );
3465
4505
  return {
3466
4506
  mode: "static",
3467
4507
  rawOutput: asText,
3468
4508
  transformedOutput: masked.maskedText,
3469
- outputMasked: masked.maskedText !== asText
4509
+ outputMasked: masked.maskedText !== asText || placeholderOutputMasked
3470
4510
  };
3471
4511
  }
3472
4512
  const source = completion;
@@ -3476,8 +4516,10 @@ var AgentID = class {
3476
4516
  const isOpenAIStreamFinishChunk = this.isOpenAIStreamFinishChunk.bind(this);
3477
4517
  const rewriteOpenAIStreamChunkForClient = this.rewriteOpenAIStreamChunkForClient.bind(this);
3478
4518
  const createSyntheticOpenAIStreamChunk = this.createSyntheticOpenAIStreamChunk.bind(this);
4519
+ const setOpenAIStreamChunkText = this.setOpenAIStreamChunkText.bind(this);
3479
4520
  const piiManager = this.pii;
3480
4521
  const streamRewriter = options?.deanonymizeForClient === true && options.piiMapping ? createStreamingPlaceholderRewriter(piiManager, options.piiMapping) : null;
4522
+ const maskForClient = options?.maskForClient === true && streamRewriter === null;
3481
4523
  let lastUsage;
3482
4524
  let resolveDone = null;
3483
4525
  let rejectDone = null;
@@ -3490,12 +4532,17 @@ var AgentID = class {
3490
4532
  try {
3491
4533
  let finishChunkFlushed = false;
3492
4534
  let lastChunkTemplate;
4535
+ let clientRawText = "";
4536
+ let clientMaskFlushed = false;
3493
4537
  for await (const chunk of source) {
3494
4538
  const chunkText = extractStreamChunkText(chunk);
3495
- const isFinishChunk = streamRewriter ? isOpenAIStreamFinishChunk(chunk) : false;
4539
+ const isFinishChunk = streamRewriter || maskForClient ? isOpenAIStreamFinishChunk(chunk) : false;
3496
4540
  if (chunkText) {
3497
4541
  await collector.push(chunkText);
3498
4542
  lastChunkTemplate = chunk;
4543
+ if (maskForClient) {
4544
+ clientRawText += chunkText;
4545
+ }
3499
4546
  }
3500
4547
  const chunkUsage = extractStreamChunkUsage(chunk);
3501
4548
  if (chunkUsage) {
@@ -3515,6 +4562,28 @@ var AgentID = class {
3515
4562
  }
3516
4563
  continue;
3517
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
+ }
3518
4587
  yield chunk;
3519
4588
  }
3520
4589
  if (streamRewriter && !finishChunkFlushed) {
@@ -3526,14 +4595,27 @@ var AgentID = class {
3526
4595
  );
3527
4596
  }
3528
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
+ }
3529
4607
  await collector.close();
3530
4608
  const rawOutput = await collector.result;
3531
4609
  const masked = piiManager.anonymize(rawOutput);
4610
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4611
+ rawOutput,
4612
+ options?.piiMapping
4613
+ );
3532
4614
  resolveDone?.({
3533
4615
  mode: "static",
3534
4616
  rawOutput,
3535
4617
  transformedOutput: masked.maskedText,
3536
- outputMasked: masked.maskedText !== rawOutput,
4618
+ outputMasked: masked.maskedText !== rawOutput || placeholderOutputMasked,
3537
4619
  usage: lastUsage
3538
4620
  });
3539
4621
  } catch (error) {
@@ -3568,6 +4650,37 @@ var AgentID = class {
3568
4650
  );
3569
4651
  }
3570
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
+ }
3571
4684
  /**
3572
4685
  * Analytics alias for telemetry logging.
3573
4686
  */
@@ -3612,49 +4725,56 @@ var AgentID = class {
3612
4725
  if (typeof originalCreate !== "function") return originalCreate;
3613
4726
  return async (...args) => {
3614
4727
  const normalizedCreateArgs = normalizeOpenAICreateArgs(args);
3615
- 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);
3616
4735
  const pipelineStartedAt = Date.now();
3617
- const requestLevelApiKey = options.resolveApiKey?.(req) ?? options.apiKey ?? options.api_key;
4736
+ const requestLevelApiKey = options.resolveApiKey?.(rawReq) ?? options.apiKey ?? options.api_key;
3618
4737
  const effectiveApiKey = this.resolveApiKey(requestLevelApiKey);
3619
4738
  const requestOptions = { apiKey: effectiveApiKey };
3620
- const clientEventId = this.resolveClientEventId(req);
4739
+ const clientEventId = this.resolveClientEventId(rawReq);
3621
4740
  const effectiveStrictMode = await this.resolveEffectiveStrictMode(requestOptions);
3622
- const stream = adapter.isStream(req);
4741
+ const stream = adapter.isStream(providerReq);
3623
4742
  let capabilityConfig = this.getCachedCapabilityConfig(requestOptions);
3624
- const userText = adapter.extractInput(req);
3625
- let maskedText = userText;
3626
- let maskedReq = req;
3627
- 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)];
3628
4749
  let mapping = {};
3629
- let shouldDeanonymize = false;
3630
4750
  let sdkConfigFetchMs = 0;
3631
4751
  let sdkLocalScanMs = 0;
3632
- if (userText) {
4752
+ if (hasGuardContent) {
3633
4753
  const prepared = await this.prepareInputForDispatch({
3634
- input: userText,
4754
+ input: userText ?? "",
3635
4755
  systemId,
3636
4756
  stream,
3637
- clientEventId
4757
+ clientEventId,
4758
+ telemetryMetadata
3638
4759
  }, requestOptions);
3639
4760
  capabilityConfig = prepared.capabilityConfig;
3640
4761
  maskedText = prepared.sanitizedInput;
3641
4762
  mapping = prepared.piiMapping ?? {};
3642
- shouldDeanonymize = prepared.shouldDeanonymize === true;
3643
4763
  sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
3644
4764
  sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
3645
- if (maskedText !== userText) {
4765
+ if (maskedText !== (userText ?? "")) {
3646
4766
  maskedReq = this.withMaskedOpenAIRequest(
3647
- req,
4767
+ providerReq,
3648
4768
  maskedText
3649
4769
  );
3650
- const nextCreateArgs = [...normalizedCreateArgs];
4770
+ const nextCreateArgs = [...createArgs];
3651
4771
  nextCreateArgs[0] = maskedReq;
3652
4772
  createArgs = nextCreateArgs;
3653
4773
  }
3654
4774
  }
3655
- if (!maskedText) {
4775
+ if (!hasGuardContent) {
3656
4776
  throw new Error(
3657
- "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."
3658
4778
  );
3659
4779
  }
3660
4780
  const verdict = await this.guard({
@@ -3665,6 +4785,8 @@ var AgentID = class {
3665
4785
  client_event_id: clientEventId,
3666
4786
  expected_languages: expectedLanguages,
3667
4787
  request_identity: options.request_identity,
4788
+ metadata: telemetryMetadata,
4789
+ attachments: requestAttachments,
3668
4790
  client_capabilities: this.buildClientCapabilities(
3669
4791
  "openai",
3670
4792
  false,
@@ -3686,22 +4808,43 @@ var AgentID = class {
3686
4808
  apiKey: effectiveApiKey,
3687
4809
  clientEventId,
3688
4810
  sdkConfigFetchMs,
4811
+ telemetryMetadata,
3689
4812
  runPromptInjectionCheck: true
3690
4813
  });
3691
4814
  maskedText = fallback.sanitizedInput;
3692
4815
  sdkLocalScanMs = fallback.sdkLocalScanMs;
3693
4816
  }
3694
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
+ );
3695
4838
  throw new SecurityBlockError(verdict.reason ?? "guard_denied");
3696
4839
  }
3697
4840
  }
3698
- const currentRequestInput = adapter.extractInput(maskedReq);
4841
+ const currentRequestInput = adapter.extractInput(maskedReq) ?? "";
3699
4842
  if (maskedText !== currentRequestInput) {
3700
4843
  maskedReq = this.withMaskedOpenAIRequest(
3701
- req,
4844
+ providerReq,
3702
4845
  maskedText
3703
4846
  );
3704
- const nextCreateArgs = [...normalizedCreateArgs];
4847
+ const nextCreateArgs = [...createArgs];
3705
4848
  nextCreateArgs[0] = maskedReq;
3706
4849
  createArgs = nextCreateArgs;
3707
4850
  }
@@ -3712,15 +4855,44 @@ var AgentID = class {
3712
4855
  const isShadowMode = verdict.shadow_mode === true;
3713
4856
  const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
3714
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
+ }
3715
4865
  maskedText = transformedInput;
3716
4866
  maskedReq = this.withMaskedOpenAIRequest(
3717
- req,
4867
+ providerReq,
3718
4868
  transformedInput
3719
4869
  );
3720
- const nextCreateArgs = [...normalizedCreateArgs];
4870
+ const nextCreateArgs = [...createArgs];
3721
4871
  nextCreateArgs[0] = maskedReq;
3722
4872
  createArgs = nextCreateArgs;
3723
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
+ );
3724
4896
  if (stream) {
3725
4897
  const modelStartedAt2 = Date.now();
3726
4898
  const streamResponse = await originalCreate.apply(compTarget, createArgs);
@@ -3732,7 +4904,8 @@ var AgentID = class {
3732
4904
  })(),
3733
4905
  {
3734
4906
  piiMapping: mapping,
3735
- deanonymizeForClient: shouldDeanonymize
4907
+ deanonymizeForClient: false,
4908
+ maskForClient: !isShadowMode
3736
4909
  }
3737
4910
  );
3738
4911
  if (maskedText && wrappedCompletion.mode === "stream") {
@@ -3751,29 +4924,32 @@ var AgentID = class {
3751
4924
  usage: result.usage,
3752
4925
  latency: modelLatencyMs2,
3753
4926
  event_type: "complete",
3754
- metadata: {
3755
- transformed_input: maskedText,
3756
- transformed_output: result.transformedOutput,
3757
- output_masked: result.outputMasked,
3758
- shadow_mode: isShadowMode,
3759
- simulated_decision: verdict.simulated_decision ?? null,
3760
- simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
3761
- response_streamed: true,
3762
- sdk_local_fallback_applied: localFallbackApplied,
3763
- sdk_local_fallback_reason: localFallbackReason,
3764
- guard_latency_ms: guardLatencyMs,
3765
- model_latency_ms: modelLatencyMs2,
3766
- total_pipeline_latency_ms: totalPipelineLatencyMs2,
3767
- guard_event_id: guardEventId,
3768
- client_event_id: canonicalClientEventId,
3769
- transparency,
3770
- ...buildSdkTimingMetadata({
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({
3771
4947
  sdkConfigFetchMs,
3772
4948
  sdkLocalScanMs,
3773
4949
  sdkGuardMs: guardLatencyMs,
3774
4950
  sdkConfigVersion: capabilityConfig.version
3775
4951
  })
3776
- },
4952
+ ),
3777
4953
  client_capabilities: this.buildClientCapabilities(
3778
4954
  "openai",
3779
4955
  false,
@@ -3804,7 +4980,10 @@ var AgentID = class {
3804
4980
  const totalPipelineLatencyMs = Math.max(0, Date.now() - pipelineStartedAt);
3805
4981
  if (maskedText) {
3806
4982
  const output = adapter.extractOutput(res);
3807
- const wrappedCompletion = this.wrapCompletion(output);
4983
+ const wrappedCompletion = this.wrapCompletion(output, {
4984
+ piiMapping: mapping,
4985
+ deanonymizeForClient: false
4986
+ });
3808
4987
  const model = adapter.getModelName(maskedReq, res);
3809
4988
  const usage = adapter.getTokenUsage(res);
3810
4989
  const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
@@ -3819,29 +4998,32 @@ var AgentID = class {
3819
4998
  usage,
3820
4999
  latency: modelLatencyMs,
3821
5000
  event_type: "complete",
3822
- metadata: {
3823
- transformed_input: maskedText,
3824
- transformed_output: wrappedCompletion.transformedOutput,
3825
- output_masked: wrappedCompletion.outputMasked,
3826
- shadow_mode: isShadowMode,
3827
- simulated_decision: verdict.simulated_decision ?? null,
3828
- simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
3829
- response_streamed: false,
3830
- sdk_local_fallback_applied: localFallbackApplied,
3831
- sdk_local_fallback_reason: localFallbackReason,
3832
- guard_latency_ms: guardLatencyMs,
3833
- model_latency_ms: modelLatencyMs,
3834
- total_pipeline_latency_ms: totalPipelineLatencyMs,
3835
- guard_event_id: guardEventId,
3836
- client_event_id: canonicalClientEventId,
3837
- transparency,
3838
- ...buildSdkTimingMetadata({
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({
3839
5021
  sdkConfigFetchMs,
3840
5022
  sdkLocalScanMs,
3841
5023
  sdkGuardMs: guardLatencyMs,
3842
5024
  sdkConfigVersion: capabilityConfig.version
3843
5025
  })
3844
- },
5026
+ ),
3845
5027
  client_capabilities: this.buildClientCapabilities(
3846
5028
  "openai",
3847
5029
  false,
@@ -3858,17 +5040,21 @@ var AgentID = class {
3858
5040
  );
3859
5041
  }
3860
5042
  }
3861
- if (!capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig) && shouldDeanonymize) {
3862
- 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;
3863
5049
  try {
3864
5050
  if (Array.isArray(res?.choices)) {
3865
5051
  for (const choice of res.choices) {
3866
5052
  const typedChoice = choice;
3867
5053
  if (typedChoice?.message && typeof typedChoice.message.content === "string") {
3868
- typedChoice.message.content = deanon;
5054
+ typedChoice.message.content = maskedOutput;
3869
5055
  }
3870
5056
  if (typedChoice?.delta && typeof typedChoice.delta.content === "string") {
3871
- typedChoice.delta.content = deanon;
5057
+ typedChoice.delta.content = maskedOutput;
3872
5058
  }
3873
5059
  }
3874
5060
  }
@@ -3893,6 +5079,155 @@ var AgentID = class {
3893
5079
  });
3894
5080
  }
3895
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
+ }
3896
5231
 
3897
5232
  export {
3898
5233
  OpenAIAdapter,
@@ -3900,7 +5235,13 @@ export {
3900
5235
  scanWithRegex,
3901
5236
  InjectionScanner,
3902
5237
  getInjectionScanner,
5238
+ createAgentIdCorrelationId,
5239
+ createAgentIdTelemetryContext,
5240
+ createAgentIdOperationLog,
3903
5241
  SecurityBlockError,
3904
5242
  DependencyError,
3905
- AgentID
5243
+ AgentID,
5244
+ AgentIDWorkflowStep,
5245
+ AgentIDWorkflowTrail,
5246
+ createAgentIdWorkflowTrail
3906
5247
  };