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.
package/dist/index.js CHANGED
@@ -21,27 +21,105 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AgentID: () => AgentID,
24
+ AgentIDWorkflowStep: () => AgentIDWorkflowStep,
25
+ AgentIDWorkflowTrail: () => AgentIDWorkflowTrail,
24
26
  DependencyError: () => DependencyError,
25
27
  InjectionScanner: () => InjectionScanner,
26
28
  OpenAIAdapter: () => OpenAIAdapter,
27
29
  PIIManager: () => PIIManager,
28
30
  SecurityBlockError: () => SecurityBlockError,
31
+ createAgentIdCorrelationId: () => createAgentIdCorrelationId,
32
+ createAgentIdOperationLog: () => createAgentIdOperationLog,
33
+ createAgentIdTelemetryContext: () => createAgentIdTelemetryContext,
34
+ createAgentIdWorkflowTrail: () => createAgentIdWorkflowTrail,
29
35
  getInjectionScanner: () => getInjectionScanner,
30
36
  scanWithRegex: () => scanWithRegex
31
37
  });
32
38
  module.exports = __toCommonJS(index_exports);
33
39
 
34
40
  // src/adapters.ts
41
+ function getLastUserMessage(req) {
42
+ const messages = req?.messages;
43
+ if (!Array.isArray(messages)) return null;
44
+ let lastUser = null;
45
+ for (const msg of messages) {
46
+ if (msg && typeof msg === "object" && msg.role === "user") {
47
+ lastUser = msg;
48
+ }
49
+ }
50
+ return lastUser;
51
+ }
52
+ function normalizeFilename(value, fallback) {
53
+ if (typeof value !== "string") {
54
+ return fallback;
55
+ }
56
+ const trimmed = value.trim();
57
+ return trimmed.length > 0 ? trimmed : fallback;
58
+ }
59
+ function parseDataUrl(value) {
60
+ if (!value.startsWith("data:")) {
61
+ return null;
62
+ }
63
+ const commaIndex = value.indexOf(",");
64
+ if (commaIndex === -1) {
65
+ return null;
66
+ }
67
+ const header = value.slice(5, commaIndex);
68
+ if (!/;base64/i.test(header)) {
69
+ return null;
70
+ }
71
+ const mimeType = header.split(";")[0]?.trim().toLowerCase() || null;
72
+ return { mimeType };
73
+ }
74
+ function inferAttachmentExtension(mimeType) {
75
+ switch (mimeType) {
76
+ case "application/pdf":
77
+ return "pdf";
78
+ case "image/png":
79
+ return "png";
80
+ case "image/jpeg":
81
+ return "jpg";
82
+ case "image/webp":
83
+ return "webp";
84
+ case "image/gif":
85
+ return "gif";
86
+ case "text/plain":
87
+ return "txt";
88
+ default:
89
+ return "bin";
90
+ }
91
+ }
92
+ function defaultFilenameForMimeType(mimeType) {
93
+ return `attachment.${inferAttachmentExtension(mimeType)}`;
94
+ }
95
+ function normalizeFileAttachment(part) {
96
+ const file = part?.file;
97
+ const rawContent = typeof file?.file_data === "string" && file.file_data.trim().length > 0 ? file.file_data.trim() : null;
98
+ if (!rawContent) {
99
+ return null;
100
+ }
101
+ const detectedMimeType = parseDataUrl(rawContent)?.mimeType ?? null;
102
+ return {
103
+ filename: normalizeFilename(file?.filename, defaultFilenameForMimeType(detectedMimeType)),
104
+ ...detectedMimeType ? { mime_type: detectedMimeType } : {},
105
+ content_base64: rawContent
106
+ };
107
+ }
108
+ function normalizeImageAttachment(part) {
109
+ const imageUrl = typeof part?.image_url?.url === "string" && part.image_url.url.trim().length > 0 ? part.image_url.url.trim() : null;
110
+ if (!imageUrl || !imageUrl.startsWith("data:")) {
111
+ return null;
112
+ }
113
+ const detectedMimeType = parseDataUrl(imageUrl)?.mimeType ?? "image/png";
114
+ return {
115
+ filename: defaultFilenameForMimeType(detectedMimeType),
116
+ mime_type: detectedMimeType,
117
+ content_base64: imageUrl
118
+ };
119
+ }
35
120
  var OpenAIAdapter = class {
36
121
  extractInput(req) {
37
- const messages = req?.messages;
38
- if (!Array.isArray(messages)) return null;
39
- let lastUser = null;
40
- for (const msg of messages) {
41
- if (msg && typeof msg === "object" && msg.role === "user") {
42
- lastUser = msg;
43
- }
44
- }
122
+ const lastUser = getLastUserMessage(req);
45
123
  if (!lastUser) return null;
46
124
  const content = lastUser.content;
47
125
  if (typeof content === "string") return content;
@@ -56,6 +134,34 @@ var OpenAIAdapter = class {
56
134
  }
57
135
  return null;
58
136
  }
137
+ extractAttachments(req) {
138
+ const lastUser = getLastUserMessage(req);
139
+ if (!lastUser) return [];
140
+ const content = lastUser?.content;
141
+ if (!Array.isArray(content)) {
142
+ return [];
143
+ }
144
+ const attachments = [];
145
+ for (const part of content) {
146
+ if (!part || typeof part !== "object") {
147
+ continue;
148
+ }
149
+ if (part.type === "file") {
150
+ const attachment = normalizeFileAttachment(part);
151
+ if (attachment) {
152
+ attachments.push(attachment);
153
+ }
154
+ continue;
155
+ }
156
+ if (part.type === "image_url") {
157
+ const attachment = normalizeImageAttachment(part);
158
+ if (attachment) {
159
+ attachments.push(attachment);
160
+ }
161
+ }
162
+ }
163
+ return attachments;
164
+ }
59
165
  getModelName(req, res) {
60
166
  const model = res?.model ?? req?.model ?? "unknown";
61
167
  return String(model);
@@ -75,7 +181,7 @@ var OpenAIAdapter = class {
75
181
 
76
182
  // src/sdk-version.ts
77
183
  var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
78
- var AGENTID_SDK_VERSION_HEADER = "js-0.1.37".trim().length > 0 ? "js-0.1.37" : FALLBACK_SDK_VERSION;
184
+ var AGENTID_SDK_VERSION_HEADER = "js-0.1.38".trim().length > 0 ? "js-0.1.38" : FALLBACK_SDK_VERSION;
79
185
 
80
186
  // src/pii-national-identifiers.ts
81
187
  var MAX_CANDIDATES_PER_RULE = 256;
@@ -939,8 +1045,173 @@ function detectNationalIdentifiers(text, options = {}) {
939
1045
  return results;
940
1046
  }
941
1047
 
1048
+ // src/secret-patterns.ts
1049
+ var SDK_SECRET_PATTERN_DEFINITIONS = [
1050
+ {
1051
+ id: "openai_api_key",
1052
+ placeholderType: "OPENAI_API_KEY",
1053
+ patternSource: "\\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\\b",
1054
+ flags: "iu",
1055
+ prefilterTerms: ["sk-", "proj-", "openai"]
1056
+ },
1057
+ {
1058
+ id: "aws_access_key",
1059
+ placeholderType: "AWS_ACCESS_KEY",
1060
+ patternSource: "\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b",
1061
+ flags: "iu",
1062
+ prefilterTerms: ["akia", "asia", "aws"]
1063
+ },
1064
+ {
1065
+ id: "github_token",
1066
+ placeholderType: "GITHUB_TOKEN",
1067
+ patternSource: "\\b(?:gh[pousr]_[A-Za-z0-9]{24,255}|github_pat_[A-Za-z0-9_]{20,255})\\b",
1068
+ flags: "iu",
1069
+ prefilterTerms: ["ghp_", "gho_", "ghu_", "ghs_", "ghr_", "github_pat_"]
1070
+ },
1071
+ {
1072
+ id: "slack_token",
1073
+ placeholderType: "SLACK_TOKEN",
1074
+ patternSource: "\\bxox(?:a|b|p|r|s)-[A-Za-z0-9-]{10,200}\\b",
1075
+ flags: "iu",
1076
+ prefilterTerms: ["xoxa-", "xoxb-", "xoxp-", "xoxr-", "xoxs-", "slack"]
1077
+ },
1078
+ {
1079
+ id: "slack_webhook_url",
1080
+ placeholderType: "SLACK_WEBHOOK_URL",
1081
+ patternSource: "https:\\/\\/hooks\\.slack\\.com\\/services\\/[A-Za-z0-9/_-]{20,}",
1082
+ flags: "iu",
1083
+ prefilterTerms: ["hooks.slack.com/services", "slack"]
1084
+ },
1085
+ {
1086
+ id: "discord_webhook_url",
1087
+ placeholderType: "DISCORD_WEBHOOK_URL",
1088
+ patternSource: "https:\\/\\/discord(?:app)?\\.com\\/api\\/webhooks\\/\\d+\\/[A-Za-z0-9_-]{16,}",
1089
+ flags: "iu",
1090
+ prefilterTerms: ["discord.com/api/webhooks", "discordapp.com/api/webhooks", "discord"]
1091
+ },
1092
+ {
1093
+ id: "stripe_secret_key",
1094
+ placeholderType: "STRIPE_SECRET_KEY",
1095
+ patternSource: "\\b(?:sk|pk|ak|rk)_(?:live|test)_[A-Za-z0-9]+\\b",
1096
+ flags: "iu",
1097
+ prefilterTerms: [
1098
+ "sk_live_",
1099
+ "pk_live_",
1100
+ "sk_test_",
1101
+ "pk_test_",
1102
+ "ak_live_",
1103
+ "ak_test_",
1104
+ "rk_live_",
1105
+ "rk_test_",
1106
+ "stripe"
1107
+ ]
1108
+ },
1109
+ {
1110
+ id: "google_api_key",
1111
+ placeholderType: "GOOGLE_API_KEY",
1112
+ patternSource: "\\bAIza[0-9A-Za-z_-]{35}\\b",
1113
+ flags: "iu",
1114
+ prefilterTerms: ["aiza", "google"]
1115
+ },
1116
+ {
1117
+ id: "anthropic_api_key",
1118
+ placeholderType: "ANTHROPIC_API_KEY",
1119
+ patternSource: "\\bsk-ant-(?:api\\d{2}-)?[A-Za-z0-9_-]{20,}\\b",
1120
+ flags: "iu",
1121
+ prefilterTerms: ["sk-ant-", "anthropic"]
1122
+ },
1123
+ {
1124
+ id: "evm_private_key",
1125
+ placeholderType: "EVM_PRIVATE_KEY",
1126
+ patternSource: "\\b0x[a-fA-F0-9]{64}\\b",
1127
+ flags: "iu",
1128
+ prefilterTerms: ["0x", "ethereum", "evm", "private key"]
1129
+ },
1130
+ {
1131
+ id: "jwt_token",
1132
+ placeholderType: "JWT_TOKEN",
1133
+ patternSource: "\\beyJ[A-Za-z0-9_-]{6,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\b",
1134
+ flags: "iu",
1135
+ prefilterTerms: ["eyj", "jwt", "bearer"]
1136
+ },
1137
+ {
1138
+ id: "bearer_token",
1139
+ placeholderType: "BEARER_TOKEN",
1140
+ patternSource: "\\bauthorization\\b\\s*[:=]\\s*bearer\\s+[A-Za-z0-9._~+\\/-]{16,}|\\bbearer\\s+[A-Za-z0-9._~+\\/-]{24,}",
1141
+ flags: "iu",
1142
+ prefilterTerms: ["authorization", "bearer"]
1143
+ },
1144
+ {
1145
+ id: "api_key_header",
1146
+ placeholderType: "API_KEY_HEADER",
1147
+ patternSource: "\\bx[-_]?api[-_]?key\\b\\s*[:=]\\s*[A-Za-z0-9._~+\\/-]{16,}",
1148
+ flags: "iu",
1149
+ prefilterTerms: ["x-api-key", "api-key", "x_api_key", "api_key"]
1150
+ },
1151
+ {
1152
+ id: "credential_assignment",
1153
+ placeholderType: "CREDENTIAL_ASSIGNMENT",
1154
+ 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,})`,
1155
+ flags: "iu",
1156
+ prefilterTerms: [
1157
+ "api key",
1158
+ "apikey",
1159
+ "api_key",
1160
+ "access token",
1161
+ "access_token",
1162
+ "auth token",
1163
+ "client secret",
1164
+ "private key"
1165
+ ]
1166
+ },
1167
+ {
1168
+ id: "password_assignment",
1169
+ placeholderType: "PASSWORD_ASSIGNMENT",
1170
+ 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,})`,
1171
+ flags: "iu",
1172
+ prefilterTerms: ["password", "passwd", "pwd"]
1173
+ },
1174
+ {
1175
+ id: "private_key_material",
1176
+ placeholderType: "PRIVATE_KEY_MATERIAL",
1177
+ 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)-----|$)",
1178
+ flags: "iu",
1179
+ prefilterTerms: ["begin private key", "begin pgp private key block", "private key"]
1180
+ },
1181
+ {
1182
+ id: "azure_connection_string",
1183
+ placeholderType: "AZURE_CONNECTION_STRING",
1184
+ patternSource: "\\bDefaultEndpointsProtocol=https;AccountName=[A-Za-z0-9.-]{3,};AccountKey=[A-Za-z0-9+/=]{20,}(?:;EndpointSuffix=[A-Za-z0-9.-]+)?\\b",
1185
+ flags: "iu",
1186
+ prefilterTerms: ["defaultendpointsprotocol", "accountname", "accountkey", "azure"]
1187
+ },
1188
+ {
1189
+ id: "azure_sas_token",
1190
+ placeholderType: "AZURE_SAS_TOKEN",
1191
+ patternSource: "\\bsv=[^\\s&]{2,}&[^\\s]{0,200}\\bsig=[A-Za-z0-9%/+_-]{16,}",
1192
+ flags: "iu",
1193
+ prefilterTerms: ["sv=", "sig=", "accountkey", "azure"]
1194
+ }
1195
+ ];
1196
+ function ensureGlobalFlag(flags) {
1197
+ const normalized = new Set(flags.split(""));
1198
+ normalized.add("g");
1199
+ return [...normalized].join("");
1200
+ }
1201
+ var COMPILED_SDK_SECRET_PATTERNS = SDK_SECRET_PATTERN_DEFINITIONS.map((definition) => ({
1202
+ ...definition,
1203
+ scanRegex: new RegExp(definition.patternSource, ensureGlobalFlag(definition.flags)),
1204
+ prefilterTermsLower: definition.prefilterTerms.map((term) => term.toLowerCase())
1205
+ }));
1206
+ function getSdkSecretDetectionMatchers() {
1207
+ return COMPILED_SDK_SECRET_PATTERNS;
1208
+ }
1209
+
942
1210
  // src/pii.ts
943
1211
  var defaultScanDeadlineMs = 100;
1212
+ var sdkSecretMatchers = getSdkSecretDetectionMatchers();
1213
+ var DISCORD_WEBHOOK_TOKEN_RE = /https:\/\/discord(?:app)?\.com\/api\/webhooks\/\d+\/([A-Za-z0-9_-]{16,})/giu;
1214
+ var BASIC_AUTH_PASSWORD_RE = /\/\/[^:\s/?#@]+:([^@\s/?#]+)@/giu;
944
1215
  function countDigits2(value) {
945
1216
  let count = 0;
946
1217
  for (const ch of value) {
@@ -965,15 +1236,32 @@ function luhnCheck(value) {
965
1236
  return sum % 10 === 0;
966
1237
  }
967
1238
  function normalizeDetections(text, detections) {
968
- const sorted = detections.filter((d) => d.start >= 0 && d.end > d.start && d.end <= text.length).sort((a, b) => a.start - b.start || b.end - b.start - (a.end - a.start));
1239
+ const sorted = detections.filter((d) => d.start >= 0 && d.end > d.start && d.end <= text.length).sort(
1240
+ (a, b) => detectionPriority(b.type) - detectionPriority(a.type) || a.start - b.start || b.end - b.start - (a.end - a.start)
1241
+ );
969
1242
  const kept = [];
970
- let cursor = 0;
971
1243
  for (const d of sorted) {
972
- if (d.start < cursor) continue;
1244
+ if (kept.some((candidate) => rangesOverlap(candidate, d))) continue;
973
1245
  kept.push(d);
974
- cursor = d.end;
975
1246
  }
976
- return kept;
1247
+ return kept.sort((a, b) => a.start - b.start || a.end - b.end);
1248
+ }
1249
+ function rangesOverlap(left, right) {
1250
+ return left.start < right.end && right.start < left.end;
1251
+ }
1252
+ function detectionPriority(type) {
1253
+ 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(
1254
+ type
1255
+ )) {
1256
+ return 100;
1257
+ }
1258
+ if (/^(?:CREDENTIAL_ASSIGNMENT|PASSWORD_ASSIGNMENT|PRIVATE_KEY_MATERIAL|ENV_SECRET_ASSIGNMENT)$/u.test(type)) {
1259
+ return 80;
1260
+ }
1261
+ if (type === "PERSON_NAME" || type === "PERSON") {
1262
+ return 10;
1263
+ }
1264
+ return 50;
977
1265
  }
978
1266
  var PHONE_CONTEXT_KEYWORDS = [
979
1267
  "tel",
@@ -1008,6 +1296,59 @@ var PHONE_CONTEXT_RE = new RegExp(
1008
1296
  "iu"
1009
1297
  );
1010
1298
  var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1299
+ "name",
1300
+ "names",
1301
+ "namen",
1302
+ "firstname",
1303
+ "lastname",
1304
+ "first",
1305
+ "last",
1306
+ "forename",
1307
+ "surname",
1308
+ "family",
1309
+ "given",
1310
+ "jmeno",
1311
+ "jake",
1312
+ "jaky",
1313
+ "jaka",
1314
+ "jsem",
1315
+ "jsme",
1316
+ "napsal",
1317
+ "napsali",
1318
+ "napsala",
1319
+ "napsane",
1320
+ "pouzil",
1321
+ "pouzili",
1322
+ "prijmeni",
1323
+ "vorname",
1324
+ "nachname",
1325
+ "familienname",
1326
+ "what",
1327
+ "which",
1328
+ "whose",
1329
+ "did",
1330
+ "we",
1331
+ "write",
1332
+ "wrote",
1333
+ "written",
1334
+ "type",
1335
+ "typed",
1336
+ "use",
1337
+ "used",
1338
+ "wie",
1339
+ "welchen",
1340
+ "welche",
1341
+ "welches",
1342
+ "haben",
1343
+ "wir",
1344
+ "geschrieben",
1345
+ "getippt",
1346
+ "quel",
1347
+ "quelle",
1348
+ "nom",
1349
+ "que",
1350
+ "cual",
1351
+ "nombre",
1011
1352
  "write",
1012
1353
  "code",
1013
1354
  "script",
@@ -1034,6 +1375,52 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1034
1375
  "security",
1035
1376
  "instructions",
1036
1377
  "instruction",
1378
+ "google",
1379
+ "form",
1380
+ "forms",
1381
+ "engineering",
1382
+ "leadership",
1383
+ "weekly",
1384
+ "daily",
1385
+ "monthly",
1386
+ "quarterly",
1387
+ "sync",
1388
+ "office",
1389
+ "updates",
1390
+ "update",
1391
+ "meeting",
1392
+ "meetings",
1393
+ "agenda",
1394
+ "minutes",
1395
+ "subject",
1396
+ "calendar",
1397
+ "roadmap",
1398
+ "platform",
1399
+ "product",
1400
+ "design",
1401
+ "operations",
1402
+ "business",
1403
+ "newsletter",
1404
+ "report",
1405
+ "reports",
1406
+ "amazon",
1407
+ "web",
1408
+ "services",
1409
+ "aws",
1410
+ "velka",
1411
+ "transformace",
1412
+ "project",
1413
+ "projekt",
1414
+ "program",
1415
+ "initiative",
1416
+ "iniciativa",
1417
+ "migration",
1418
+ "migrace",
1419
+ "test",
1420
+ "uuid",
1421
+ "fixture",
1422
+ "data",
1423
+ "firma",
1037
1424
  "rules",
1038
1425
  "rule",
1039
1426
  "json",
@@ -1046,10 +1433,22 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1046
1433
  "agentid",
1047
1434
  "risk",
1048
1435
  "score",
1049
- "summary"
1436
+ "summary",
1437
+ "hi",
1438
+ "hello",
1439
+ "hey",
1440
+ "dear",
1441
+ "team",
1442
+ "ahoj",
1443
+ "dobry",
1444
+ "dobryden",
1445
+ "zdravim"
1050
1446
  ]);
1051
1447
  var TECHNICAL_CONTEXT_WORD_REGEX = /\b(?:curl|http|https|import|python|javascript|typescript|sql|nosql|mongo|database|query|script|code|os\.system|eval|exec|node|npm|api|endpoint|regex|json|xml|yaml|bash|powershell)\b/i;
1052
1448
  var TECHNICAL_CONTEXT_SYMBOL_REGEX = /:\/\/|`|\{|\}|\[|\]|\(|\)|;|\$|=>|::|\/\//;
1449
+ 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;
1450
+ var NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX = /(?:[:=]|=>|-|\b(?:is|was|je|jsou|jmenuje|called|named|ist|sind|lautet|est|es)\b)\s*$/iu;
1451
+ var BIRTH_NUMBER_CONTEXT_RE = /\b(?:rodn[eé]\s*(?:č[ií]slo|cislo)|r\.?\s*c\.?|birth\s+number)\b[^0-9]{0,80}(\d{6}(?:\/?\d{3,4})?)\b/giu;
1053
1452
  function hasPhoneContext(text, matchStartIndex, windowSize = 50) {
1054
1453
  const start = Math.max(0, matchStartIndex - windowSize);
1055
1454
  const windowLower = text.slice(start, matchStartIndex).toLowerCase();
@@ -1066,6 +1465,16 @@ function buildContextWindow(source, index, length) {
1066
1465
  function isTechnicalContext(contextWindow) {
1067
1466
  return TECHNICAL_CONTEXT_WORD_REGEX.test(contextWindow) || TECHNICAL_CONTEXT_SYMBOL_REGEX.test(contextWindow);
1068
1467
  }
1468
+ function isNameLabelQuestionContext(contextWindow) {
1469
+ const normalized = normalizePersonWord(contextWindow);
1470
+ if (!normalized.trim()) {
1471
+ return false;
1472
+ }
1473
+ if (!NAME_LABEL_QUESTION_CONTEXT_REGEX.test(normalized)) {
1474
+ return false;
1475
+ }
1476
+ return !NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX.test(normalized.slice(-32));
1477
+ }
1069
1478
  function isLikelyPersonNameCandidate(candidate, contextWindow) {
1070
1479
  const words = candidate.trim().split(/\s+/);
1071
1480
  if (words.length !== 2) {
@@ -1074,6 +1483,9 @@ function isLikelyPersonNameCandidate(candidate, contextWindow) {
1074
1483
  if (isTechnicalContext(contextWindow)) {
1075
1484
  return false;
1076
1485
  }
1486
+ if (isNameLabelQuestionContext(contextWindow)) {
1487
+ return false;
1488
+ }
1077
1489
  for (const rawWord of words) {
1078
1490
  const normalized = normalizePersonWord(rawWord);
1079
1491
  if (normalized.length < 2) {
@@ -1094,63 +1506,135 @@ var PIIManager = class {
1094
1506
  *
1095
1507
  * Zero-dependency fallback with strict checksum validation for CEE national IDs.
1096
1508
  */
1097
- anonymize(text) {
1509
+ anonymize(text, options) {
1098
1510
  if (!text) return { maskedText: text, mapping: {} };
1099
1511
  try {
1100
1512
  const detections = [];
1101
- const emailRe = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
1102
- for (const m of text.matchAll(emailRe)) {
1103
- if (m.index == null) continue;
1104
- detections.push({ start: m.index, end: m.index + m[0].length, type: "EMAIL", text: m[0] });
1105
- }
1106
- const ibanRe = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/gi;
1107
- for (const m of text.matchAll(ibanRe)) {
1108
- if (m.index == null) continue;
1109
- detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
1110
- }
1111
- const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
1112
- for (const m of text.matchAll(ccRe)) {
1113
- if (m.index == null) continue;
1114
- const digits = countDigits2(m[0]);
1115
- if (digits < 12 || digits > 19) continue;
1116
- if (!luhnCheck(m[0])) continue;
1117
- detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
1513
+ const loweredText = text.toLowerCase();
1514
+ const resolvedOptions = {
1515
+ pii: options?.pii !== false,
1516
+ secrets: options?.secrets !== false
1517
+ };
1518
+ if (!resolvedOptions.pii && !resolvedOptions.secrets) {
1519
+ return { maskedText: text, mapping: {} };
1118
1520
  }
1119
- const phoneRe = /(?<!\d)(?:\+?\d[\d\s().-]{7,}\d)(?!\d)/g;
1120
- for (const m of text.matchAll(phoneRe)) {
1121
- if (m.index == null) continue;
1122
- const candidate = m[0];
1123
- const digits = countDigits2(candidate);
1124
- if (digits < 9 || digits > 15) continue;
1125
- const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
1126
- if (!isStrongInternational) {
1127
- const hasContext = hasPhoneContext(text, m.index);
1128
- if (!hasContext) continue;
1521
+ if (resolvedOptions.pii) {
1522
+ const emailRe = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
1523
+ for (const m of text.matchAll(emailRe)) {
1524
+ if (m.index == null) continue;
1525
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "EMAIL", text: m[0] });
1129
1526
  }
1130
- detections.push({ start: m.index, end: m.index + m[0].length, type: "PHONE", text: m[0] });
1131
- }
1132
- const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
1133
- for (const m of text.matchAll(personRe)) {
1134
- if (m.index == null) continue;
1135
- const candidate = m[0];
1136
- const contextWindow = buildContextWindow(text, m.index, candidate.length);
1137
- if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
1138
- continue;
1527
+ const ibanRe = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/gi;
1528
+ for (const m of text.matchAll(ibanRe)) {
1529
+ if (m.index == null) continue;
1530
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
1139
1531
  }
1140
- detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
1141
- }
1142
- const nationalIdMatches = detectNationalIdentifiers(text, {
1143
- deadlineMs: defaultScanDeadlineMs,
1144
- allowContextBirthNumberFallback: false
1145
- });
1146
- for (const match of nationalIdMatches) {
1147
- if (match.start < 0 || match.end <= match.start) continue;
1148
- detections.push({
1149
- start: match.start,
1150
- end: match.end,
1151
- type: "NATIONAL_ID",
1152
- text: text.slice(match.start, match.end)
1532
+ const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
1533
+ for (const m of text.matchAll(ccRe)) {
1534
+ if (m.index == null) continue;
1535
+ const digits = countDigits2(m[0]);
1536
+ if (digits < 12 || digits > 19) continue;
1537
+ if (!luhnCheck(m[0])) continue;
1538
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
1539
+ }
1540
+ const phoneRe = /(?<!\d)(?:\+?\d[\d\s().-]{7,}\d)(?!\d)/g;
1541
+ for (const m of text.matchAll(phoneRe)) {
1542
+ if (m.index == null) continue;
1543
+ const candidate = m[0];
1544
+ const digits = countDigits2(candidate);
1545
+ if (digits < 9 || digits > 15) continue;
1546
+ const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
1547
+ if (!isStrongInternational) {
1548
+ const hasContext = hasPhoneContext(text, m.index);
1549
+ if (!hasContext) continue;
1550
+ }
1551
+ detections.push({ start: m.index, end: m.index + m[0].length, type: "PHONE", text: m[0] });
1552
+ }
1553
+ const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
1554
+ for (const m of text.matchAll(personRe)) {
1555
+ if (m.index == null) continue;
1556
+ const candidate = m[0];
1557
+ const contextWindow = buildContextWindow(text, m.index, candidate.length);
1558
+ if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
1559
+ continue;
1560
+ }
1561
+ detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
1562
+ }
1563
+ BIRTH_NUMBER_CONTEXT_RE.lastIndex = 0;
1564
+ for (const match of text.matchAll(BIRTH_NUMBER_CONTEXT_RE)) {
1565
+ if (match.index == null) continue;
1566
+ const value = match[1] ?? "";
1567
+ if (!/^\d{6}(?:\/?\d{3,4})?$/.test(value)) continue;
1568
+ const localIndex = match[0].lastIndexOf(value);
1569
+ const start = match.index + Math.max(0, localIndex);
1570
+ detections.push({
1571
+ start,
1572
+ end: start + value.length,
1573
+ type: "BIRTH_NUMBER",
1574
+ text: value
1575
+ });
1576
+ }
1577
+ const nationalIdMatches = detectNationalIdentifiers(text, {
1578
+ deadlineMs: defaultScanDeadlineMs,
1579
+ allowContextBirthNumberFallback: false
1153
1580
  });
1581
+ for (const match of nationalIdMatches) {
1582
+ if (match.start < 0 || match.end <= match.start) continue;
1583
+ detections.push({
1584
+ start: match.start,
1585
+ end: match.end,
1586
+ type: "NATIONAL_ID",
1587
+ text: text.slice(match.start, match.end)
1588
+ });
1589
+ }
1590
+ }
1591
+ if (resolvedOptions.secrets) {
1592
+ BASIC_AUTH_PASSWORD_RE.lastIndex = 0;
1593
+ for (const match of text.matchAll(BASIC_AUTH_PASSWORD_RE)) {
1594
+ if (match.index == null) continue;
1595
+ const password = match[1] ?? "";
1596
+ if (!password) continue;
1597
+ const localIndex = match[0].lastIndexOf(password);
1598
+ const start = match.index + Math.max(0, localIndex);
1599
+ detections.push({
1600
+ start,
1601
+ end: start + password.length,
1602
+ type: "BASIC_AUTH_PASSWORD",
1603
+ text: password
1604
+ });
1605
+ }
1606
+ DISCORD_WEBHOOK_TOKEN_RE.lastIndex = 0;
1607
+ for (const match of text.matchAll(DISCORD_WEBHOOK_TOKEN_RE)) {
1608
+ if (match.index == null) continue;
1609
+ const token = match[1] ?? "";
1610
+ if (!token) continue;
1611
+ const localIndex = match[0].lastIndexOf(token);
1612
+ const start = match.index + Math.max(0, localIndex);
1613
+ detections.push({
1614
+ start,
1615
+ end: start + token.length,
1616
+ type: "DISCORD_WEBHOOK_TOKEN",
1617
+ text: token
1618
+ });
1619
+ }
1620
+ for (const matcher of sdkSecretMatchers) {
1621
+ if (matcher.id === "discord_webhook_url") {
1622
+ continue;
1623
+ }
1624
+ if (matcher.prefilterTermsLower.length > 0 && !matcher.prefilterTermsLower.some((term) => loweredText.includes(term))) {
1625
+ continue;
1626
+ }
1627
+ matcher.scanRegex.lastIndex = 0;
1628
+ for (const match of text.matchAll(matcher.scanRegex)) {
1629
+ if (match.index == null) continue;
1630
+ detections.push({
1631
+ start: match.index,
1632
+ end: match.index + match[0].length,
1633
+ type: matcher.placeholderType,
1634
+ text: match[0]
1635
+ });
1636
+ }
1637
+ }
1154
1638
  }
1155
1639
  const kept = normalizeDetections(text, detections);
1156
1640
  if (!kept.length) return { maskedText: text, mapping: {} };
@@ -1196,6 +1680,8 @@ var DEFAULT_FAIL_OPEN_CONFIG = {
1196
1680
  inject_transparency_metadata: false,
1197
1681
  block_pii_leakage: false,
1198
1682
  enable_sdk_pii_masking: false,
1683
+ block_secret_leakage: false,
1684
+ enable_sdk_secret_masking: false,
1199
1685
  block_db_access: false,
1200
1686
  block_code_execution: false,
1201
1687
  block_toxicity: false
@@ -1237,11 +1723,11 @@ function detectCapabilityViolation(text, config) {
1237
1723
  }
1238
1724
  return null;
1239
1725
  }
1240
- function redactPiiStrict(pii, text) {
1726
+ function redactPiiStrict(pii, text, options) {
1241
1727
  if (!text) {
1242
1728
  return { redactedText: text, changed: false };
1243
1729
  }
1244
- const masked = pii.anonymize(text);
1730
+ const masked = pii.anonymize(text, options);
1245
1731
  let redactedText = masked.maskedText;
1246
1732
  const placeholders = Object.keys(masked.mapping).sort((a, b) => b.length - a.length);
1247
1733
  for (const placeholder of placeholders) {
@@ -1270,7 +1756,7 @@ var LocalSecurityEnforcer = class {
1270
1756
  `AgentID: Security policy blocked (${violationType})`
1271
1757
  );
1272
1758
  }
1273
- if (!config.block_pii_leakage) {
1759
+ if (!config.block_pii_leakage && !config.block_secret_leakage) {
1274
1760
  return {
1275
1761
  sanitizedInput: input,
1276
1762
  events: []
@@ -1280,10 +1766,13 @@ var LocalSecurityEnforcer = class {
1280
1766
  throw new SecurityPolicyViolationError(
1281
1767
  "PII_LEAKAGE_STRICT",
1282
1768
  "BLOCKED",
1283
- "AgentID: Streaming is not supported when Strict PII Mode is enabled. Please disable streaming or adjust security settings."
1769
+ "AgentID: Streaming is not supported when strict masking/blocking mode is enabled. Please disable streaming or adjust security settings."
1284
1770
  );
1285
1771
  }
1286
- const strictRedaction = redactPiiStrict(this.pii, input);
1772
+ const strictRedaction = redactPiiStrict(this.pii, input, {
1773
+ pii: config.block_pii_leakage,
1774
+ secrets: config.block_secret_leakage
1775
+ });
1287
1776
  return {
1288
1777
  sanitizedInput: strictRedaction.redactedText,
1289
1778
  events: strictRedaction.changed ? [
@@ -1409,6 +1898,16 @@ function normalizeCapabilityConfig(payload) {
1409
1898
  "enable_sdk_pii_masking",
1410
1899
  false
1411
1900
  ),
1901
+ block_secret_leakage: readOptionalBooleanField(
1902
+ body,
1903
+ "block_secret_leakage",
1904
+ false
1905
+ ),
1906
+ enable_sdk_secret_masking: readOptionalBooleanField(
1907
+ body,
1908
+ "enable_sdk_secret_masking",
1909
+ false
1910
+ ),
1412
1911
  block_db_access: readBooleanField(body, "block_db_access", "block_db"),
1413
1912
  block_code_execution: readBooleanField(
1414
1913
  body,
@@ -2069,14 +2568,14 @@ async function reportSecurityEvent(options) {
2069
2568
  const inputValue = options.storePii ? snippet : snippetHash;
2070
2569
  const eventId = createEventId(options.eventId ?? options.clientEventId);
2071
2570
  const metadata = {
2571
+ ...options.telemetryMetadata ?? {},
2072
2572
  source: options.source,
2073
2573
  detector: options.detector,
2074
2574
  trigger_rule: options.triggerRule,
2075
2575
  language: options.language,
2076
2576
  ai_scan_status: options.aiStatus ?? null,
2077
2577
  reason: options.reason ?? null,
2078
- client_event_id: eventId,
2079
- ...options.telemetryMetadata ?? {}
2578
+ client_event_id: eventId
2080
2579
  };
2081
2580
  if (options.storePii) {
2082
2581
  metadata.snippet = snippet;
@@ -2248,9 +2747,18 @@ var INGEST_MAX_ATTEMPTS = 3;
2248
2747
  var INGEST_RETRY_DELAYS_MS = [250, 500];
2249
2748
  var GUARD_VERDICT_CACHE_TTL_MS = 0;
2250
2749
  var MAX_INGEST_TEXT_CHARS = 32e3;
2750
+ var OPENAI_TELEMETRY_FIELD = "agentid_telemetry";
2251
2751
  function normalizeBaseUrl3(baseUrl) {
2252
2752
  return baseUrl.replace(/\/+$/, "");
2253
2753
  }
2754
+ function firstNonEmptyString(...values) {
2755
+ for (const value of values) {
2756
+ if (typeof value === "string" && value.trim().length > 0) {
2757
+ return value.trim();
2758
+ }
2759
+ }
2760
+ return void 0;
2761
+ }
2254
2762
  function isAbortSignalLike(value) {
2255
2763
  if (!value || typeof value !== "object") return false;
2256
2764
  const candidate = value;
@@ -2412,6 +2920,424 @@ function createCorrelationId(seed) {
2412
2920
  }
2413
2921
  return createPseudoUuidV42();
2414
2922
  }
2923
+ function getObjectString(value, ...keys) {
2924
+ for (const key of keys) {
2925
+ const candidate = value?.[key];
2926
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
2927
+ return candidate.trim();
2928
+ }
2929
+ }
2930
+ return void 0;
2931
+ }
2932
+ function getObjectNumber(value, ...keys) {
2933
+ for (const key of keys) {
2934
+ const candidate = value?.[key];
2935
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
2936
+ return candidate;
2937
+ }
2938
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
2939
+ const parsed = Number(candidate);
2940
+ if (Number.isFinite(parsed)) {
2941
+ return parsed;
2942
+ }
2943
+ }
2944
+ }
2945
+ return void 0;
2946
+ }
2947
+ function normalizeTelemetryString(value) {
2948
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
2949
+ }
2950
+ function normalizeTelemetryCategory(value) {
2951
+ const normalized = normalizeTelemetryString(value);
2952
+ if (!normalized) return void 0;
2953
+ return normalized.toLowerCase().replace(/[\s-]+/g, "_");
2954
+ }
2955
+ function toSnakeToken(value) {
2956
+ return value.trim().replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_").toLowerCase();
2957
+ }
2958
+ function hasUsageSignals(value) {
2959
+ if (!value) return false;
2960
+ for (const entry of Object.values(value)) {
2961
+ if (typeof entry === "number" && Number.isFinite(entry) && entry > 0) {
2962
+ return true;
2963
+ }
2964
+ if (typeof entry === "string" && entry.trim().length > 0) {
2965
+ const parsed = Number(entry);
2966
+ if (Number.isFinite(parsed) && parsed > 0) {
2967
+ return true;
2968
+ }
2969
+ }
2970
+ }
2971
+ return false;
2972
+ }
2973
+ function truncatePromptPreflightPreview(value, maxChars = 280) {
2974
+ const normalized = value.trim();
2975
+ if (normalized.length <= maxChars) {
2976
+ return normalized;
2977
+ }
2978
+ return `${normalized.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
2979
+ }
2980
+ function formatPromptPreflightReason(reason) {
2981
+ const normalized = normalizeTelemetryString(reason);
2982
+ if (!normalized) {
2983
+ return void 0;
2984
+ }
2985
+ return normalized.replace(/[_-]+/g, " ");
2986
+ }
2987
+ function summarizePromptPreflightResult(params) {
2988
+ const reason = formatPromptPreflightReason(
2989
+ params.localFallbackApplied ? params.localFallbackReason ?? void 0 : params.verdict.reason
2990
+ ) ?? "policy evaluation";
2991
+ if (!params.verdict.allowed && !params.localFallbackApplied) {
2992
+ return `Blocked the prompt before model execution because ${reason}.`;
2993
+ }
2994
+ if (params.localFallbackApplied) {
2995
+ return `Guard preflight degraded, so the SDK applied local fallback checks before model execution (${reason}).`;
2996
+ }
2997
+ if (params.verdict.shadow_mode && params.verdict.shadow_blocked) {
2998
+ return "Evaluated the prompt in shadow mode before model execution; shadow policy would have blocked it.";
2999
+ }
3000
+ if (params.verdict.simulated_decision === "masked" || params.verdict.detected_pii) {
3001
+ return "Evaluated the prompt before model execution and masked sensitive content where needed.";
3002
+ }
3003
+ return "Evaluated the prompt and attachments against guardrails before model execution.";
3004
+ }
3005
+ function buildPromptPreflightTelemetry(params) {
3006
+ const baseTelemetry = createAgentIdTelemetryContext(params.telemetry);
3007
+ const baseStepName = firstNonEmptyString(
3008
+ baseTelemetry?.workflow_step_name,
3009
+ baseTelemetry?.workflowStepName
3010
+ );
3011
+ const stepName = baseStepName ? `${toSnakeToken(baseStepName)}_preflight` : "prompt_preflight";
3012
+ const summary = summarizePromptPreflightResult({
3013
+ verdict: params.verdict,
3014
+ localFallbackApplied: params.local_fallback_applied,
3015
+ localFallbackReason: params.local_fallback_reason
3016
+ });
3017
+ return mergeTelemetryContexts(baseTelemetry, {
3018
+ workflow_step_id: createAgentIdCorrelationId(),
3019
+ workflow_step_name: stepName,
3020
+ event_title: "Prompt Preflight Evaluated",
3021
+ event_category: "guard",
3022
+ event_subtype: "prompt_preflight_evaluated",
3023
+ event_status: !params.verdict.allowed && !params.local_fallback_applied ? "blocked" : "completed",
3024
+ step_summary: summary,
3025
+ input_preview: truncatePromptPreflightPreview(params.input),
3026
+ output_preview: summary,
3027
+ runtime_surface: params.runtime_surface ?? "openai_sdk_guard",
3028
+ guard_event_id: params.guard_event_id ?? void 0,
3029
+ guard_latency_ms: params.guard_latency_ms ?? void 0,
3030
+ preflight_for_client_event_id: params.preflight_for_client_event_id,
3031
+ preflight_logged_via_sdk: true,
3032
+ lifecycle_status: "preflight_only"
3033
+ });
3034
+ }
3035
+ function inferOperationCategory(telemetry, eventType) {
3036
+ const explicitCategory = normalizeTelemetryCategory(
3037
+ telemetry?.event_category ?? telemetry?.eventCategory
3038
+ );
3039
+ if (explicitCategory === "ai" || explicitCategory === "llm" || explicitCategory === "inference") {
3040
+ return "ai";
3041
+ }
3042
+ if (explicitCategory === "guard" || explicitCategory === "security") {
3043
+ return "guard";
3044
+ }
3045
+ if (explicitCategory === "tool") return "tool";
3046
+ if (explicitCategory === "delivery" || explicitCategory === "send") return "delivery";
3047
+ if (explicitCategory === "inbox" || explicitCategory === "reply") return "inbox";
3048
+ if (explicitCategory === "workflow" || explicitCategory === "agent") return "workflow";
3049
+ if (explicitCategory === "compliance" || explicitCategory === "transparency") {
3050
+ return "compliance";
3051
+ }
3052
+ if (explicitCategory === "operational" || explicitCategory === "ops") {
3053
+ return "operational";
3054
+ }
3055
+ const haystack = [
3056
+ eventType,
3057
+ telemetry?.event_subtype,
3058
+ telemetry?.eventSubtype,
3059
+ telemetry?.tool_name,
3060
+ telemetry?.toolName,
3061
+ telemetry?.tool_target_type,
3062
+ telemetry?.toolTargetType,
3063
+ telemetry?.workflow_name,
3064
+ telemetry?.workflowName,
3065
+ telemetry?.workflow_step_name,
3066
+ telemetry?.workflowStepName,
3067
+ getObjectString(telemetry, "operation_family", "domain")
3068
+ ].filter((entry) => typeof entry === "string" && entry.trim().length > 0).join(" ").replace(/[_./-]+/g, " ").toLowerCase();
3069
+ if (/\b(llm|ai|inference|completion|summary|classification|draft)\b/.test(haystack)) {
3070
+ return "ai";
3071
+ }
3072
+ if (/\b(guard|security|policy|pii|prompt[_ ]?injection|review)\b/.test(haystack)) {
3073
+ return "guard";
3074
+ }
3075
+ if (/\b(reply|inbox|inbound|received|bounce|opened|followup)\b/.test(haystack)) {
3076
+ return "inbox";
3077
+ }
3078
+ if (/\b(email|mail|send|delivery|delivered|slack|sms|webhook|notification)\b/.test(haystack)) {
3079
+ return "delivery";
3080
+ }
3081
+ if (/\b(workflow|step|run|agent)\b/.test(haystack)) {
3082
+ return "workflow";
3083
+ }
3084
+ if (/\b(compliance|transparency|audit|evidence)\b/.test(haystack)) {
3085
+ return "compliance";
3086
+ }
3087
+ 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(
3088
+ haystack
3089
+ )) {
3090
+ return "tool";
3091
+ }
3092
+ return "operational";
3093
+ }
3094
+ function inferOperationStatus(params) {
3095
+ const explicitStatus = normalizeTelemetryString(params.eventStatus)?.toLowerCase();
3096
+ if (explicitStatus === "started" || explicitStatus === "completed" || explicitStatus === "failed") {
3097
+ return explicitStatus;
3098
+ }
3099
+ if (explicitStatus === "blocked" || explicitStatus === "skipped") {
3100
+ return explicitStatus;
3101
+ }
3102
+ const normalizedEventType = normalizeTelemetryString(params.eventType)?.toLowerCase();
3103
+ if (normalizedEventType === "start") return "started";
3104
+ if (normalizedEventType === "error") return "failed";
3105
+ if (normalizedEventType === "security_block") return "blocked";
3106
+ if (normalizedEventType === "human_override") return "completed";
3107
+ if (normalizedEventType === "complete") return "completed";
3108
+ return params.severity === "error" ? "failed" : "completed";
3109
+ }
3110
+ function deriveOperationEventType(params) {
3111
+ const explicit = normalizeTelemetryString(params.explicitEventType);
3112
+ if (explicit) {
3113
+ return explicit;
3114
+ }
3115
+ if (params.status === "started") return "start";
3116
+ if (params.status === "failed") return "error";
3117
+ if (params.status === "blocked") {
3118
+ return params.category === "guard" ? "security_block" : "error";
3119
+ }
3120
+ return "complete";
3121
+ }
3122
+ function deriveSubtypeBase(telemetry) {
3123
+ const toolName = normalizeTelemetryString(telemetry?.tool_name ?? telemetry?.toolName);
3124
+ if (toolName) {
3125
+ const tokens = toSnakeToken(toolName).split("_").filter(Boolean);
3126
+ if (tokens.length > 1 && ["workflow", "agent", "operation", "ops", "hr", "finance", "compliance"].includes(tokens[0])) {
3127
+ return tokens.slice(1).join("_");
3128
+ }
3129
+ return tokens.join("_");
3130
+ }
3131
+ const workflowName = normalizeTelemetryString(
3132
+ telemetry?.workflow_step_name ?? telemetry?.workflowStepName ?? telemetry?.workflow_name ?? telemetry?.workflowName
3133
+ );
3134
+ if (workflowName) {
3135
+ return toSnakeToken(workflowName);
3136
+ }
3137
+ return void 0;
3138
+ }
3139
+ function deriveOperationSubtype(params) {
3140
+ const explicitSubtype = normalizeTelemetryString(params.explicitSubtype);
3141
+ if (explicitSubtype) {
3142
+ return toSnakeToken(explicitSubtype);
3143
+ }
3144
+ const base = deriveSubtypeBase(params.telemetry);
3145
+ const suffix = params.status === "started" ? "started" : params.status === "failed" ? "failed" : params.status === "blocked" ? "blocked" : params.status === "skipped" ? "skipped" : "completed";
3146
+ if (base) {
3147
+ return `${base}_${suffix}`;
3148
+ }
3149
+ if (params.eventType === "start") return `${params.category}_started`;
3150
+ if (params.eventType === "error") return `${params.category}_failed`;
3151
+ if (params.eventType === "security_block") return `${params.category}_blocked`;
3152
+ return `${params.category}_completed`;
3153
+ }
3154
+ function inferOperationSeverity(params) {
3155
+ if (params.explicitSeverity) {
3156
+ return params.explicitSeverity;
3157
+ }
3158
+ if (params.status === "failed" || params.status === "blocked") {
3159
+ return "error";
3160
+ }
3161
+ if (params.status === "skipped") {
3162
+ return "warning";
3163
+ }
3164
+ return "info";
3165
+ }
3166
+ function createAgentIdCorrelationId(seed) {
3167
+ return createCorrelationId(seed);
3168
+ }
3169
+ function createAgentIdTelemetryContext(value) {
3170
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
3171
+ return void 0;
3172
+ }
3173
+ const raw = { ...value };
3174
+ const normalized = {};
3175
+ const assignString = (key, ...aliases) => {
3176
+ const next = getObjectString(raw, key, ...aliases);
3177
+ if (next) {
3178
+ normalized[key] = next;
3179
+ }
3180
+ };
3181
+ const assignNumber = (key, ...aliases) => {
3182
+ const next = getObjectNumber(raw, key, ...aliases);
3183
+ if (typeof next === "number") {
3184
+ normalized[key] = next;
3185
+ }
3186
+ };
3187
+ assignString("workflow_id", "workflowId");
3188
+ assignString("workflow_run_id", "workflowRunId");
3189
+ assignString("workflow_step_id", "workflowStepId");
3190
+ assignString("workflow_name", "workflowName");
3191
+ assignString("workflow_step_name", "workflowStepName");
3192
+ assignNumber("workflow_step_index", "workflowStepIndex");
3193
+ assignString("parent_event_id", "parentEventId");
3194
+ assignString("tool_name", "toolName");
3195
+ assignString("tool_target", "toolTarget");
3196
+ assignString("tool_target_type", "toolTargetType");
3197
+ assignString("event_title", "eventTitle");
3198
+ assignString("event_status", "eventStatus");
3199
+ assignString("event_category", "eventCategory");
3200
+ assignString("event_subtype", "eventSubtype");
3201
+ const consumedKeys = /* @__PURE__ */ new Set([
3202
+ "workflow_id",
3203
+ "workflowId",
3204
+ "workflow_run_id",
3205
+ "workflowRunId",
3206
+ "workflow_step_id",
3207
+ "workflowStepId",
3208
+ "workflow_name",
3209
+ "workflowName",
3210
+ "workflow_step_name",
3211
+ "workflowStepName",
3212
+ "workflow_step_index",
3213
+ "workflowStepIndex",
3214
+ "parent_event_id",
3215
+ "parentEventId",
3216
+ "tool_name",
3217
+ "toolName",
3218
+ "tool_target",
3219
+ "toolTarget",
3220
+ "tool_target_type",
3221
+ "toolTargetType",
3222
+ "event_title",
3223
+ "eventTitle",
3224
+ "event_status",
3225
+ "eventStatus",
3226
+ "event_category",
3227
+ "eventCategory",
3228
+ "event_subtype",
3229
+ "eventSubtype"
3230
+ ]);
3231
+ for (const [key, entry] of Object.entries(raw)) {
3232
+ if (consumedKeys.has(key) || entry === void 0) {
3233
+ continue;
3234
+ }
3235
+ if (typeof entry === "string") {
3236
+ if (entry.trim().length > 0) {
3237
+ normalized[key] = entry.trim();
3238
+ }
3239
+ continue;
3240
+ }
3241
+ normalized[key] = entry;
3242
+ }
3243
+ if (typeof normalized.workflow_id !== "string" && typeof normalized.workflow_run_id === "string") {
3244
+ normalized.workflow_id = normalized.workflow_run_id;
3245
+ }
3246
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
3247
+ }
3248
+ function createAgentIdOperationLog(params) {
3249
+ const telemetry = createAgentIdTelemetryContext(params.telemetry);
3250
+ const category = inferOperationCategory(
3251
+ createAgentIdTelemetryContext({
3252
+ ...telemetry ?? {},
3253
+ event_category: params.event_category ?? telemetry?.event_category
3254
+ }),
3255
+ params.event_type
3256
+ );
3257
+ const status = inferOperationStatus({
3258
+ eventStatus: normalizeTelemetryString(params.event_status) ?? normalizeTelemetryString(telemetry?.event_status ?? telemetry?.eventStatus),
3259
+ eventType: params.event_type,
3260
+ severity: params.severity
3261
+ });
3262
+ const eventType = deriveOperationEventType({
3263
+ explicitEventType: params.event_type,
3264
+ status,
3265
+ category
3266
+ });
3267
+ const subtype = deriveOperationSubtype({
3268
+ explicitSubtype: normalizeTelemetryString(params.event_subtype) ?? normalizeTelemetryString(telemetry?.event_subtype ?? telemetry?.eventSubtype),
3269
+ telemetry,
3270
+ category,
3271
+ status,
3272
+ eventType
3273
+ });
3274
+ const severity = inferOperationSeverity({
3275
+ explicitSeverity: params.severity,
3276
+ status
3277
+ });
3278
+ const usage = params.usage;
3279
+ const clientEventId = normalizeTelemetryString(params.client_event_id) ?? normalizeTelemetryString(telemetry?.client_event_id);
3280
+ const modelUsed = category === "ai" || hasUsageSignals(usage) || typeof params.model === "string" && params.model.trim().length > 0 && params.model.trim().toLowerCase() !== "not_applicable";
3281
+ const metadata = {
3282
+ ...params.metadata ?? {},
3283
+ ...telemetry ?? {},
3284
+ event_category: category,
3285
+ event_subtype: subtype,
3286
+ event_status: status,
3287
+ status,
3288
+ model_used: modelUsed,
3289
+ spend_bearing: category === "ai" && hasUsageSignals(usage)
3290
+ };
3291
+ if (clientEventId && typeof metadata.client_event_id !== "string") {
3292
+ metadata.client_event_id = clientEventId;
3293
+ }
3294
+ return {
3295
+ event_id: normalizeTelemetryString(params.event_id) ?? createEventId2(),
3296
+ system_id: params.system_id,
3297
+ user_id: params.user_id,
3298
+ request_identity: params.request_identity,
3299
+ input: params.input ?? "",
3300
+ output: params.output ?? "",
3301
+ model: normalizeTelemetryString(params.model) ?? "not_applicable",
3302
+ usage,
3303
+ tokens: params.tokens,
3304
+ latency: params.latency,
3305
+ metadata,
3306
+ event_type: eventType,
3307
+ severity,
3308
+ timestamp: params.timestamp,
3309
+ client_capabilities: params.client_capabilities
3310
+ };
3311
+ }
3312
+ function asTelemetryContext(value) {
3313
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
3314
+ return void 0;
3315
+ }
3316
+ return createAgentIdTelemetryContext(value);
3317
+ }
3318
+ function mergeTelemetryContexts(...contexts) {
3319
+ const merged = {};
3320
+ let hasValues = false;
3321
+ for (const context of contexts) {
3322
+ if (!context) {
3323
+ continue;
3324
+ }
3325
+ Object.assign(merged, createAgentIdTelemetryContext(context));
3326
+ hasValues = true;
3327
+ }
3328
+ return hasValues ? createAgentIdTelemetryContext(merged) : void 0;
3329
+ }
3330
+ function extractRequestTelemetryContext(requestBody) {
3331
+ return asTelemetryContext(requestBody[OPENAI_TELEMETRY_FIELD]);
3332
+ }
3333
+ function stripRequestTelemetryContext(requestBody) {
3334
+ if (!Object.prototype.hasOwnProperty.call(requestBody, OPENAI_TELEMETRY_FIELD)) {
3335
+ return requestBody;
3336
+ }
3337
+ const nextRequestBody = { ...requestBody };
3338
+ delete nextRequestBody[OPENAI_TELEMETRY_FIELD];
3339
+ return nextRequestBody;
3340
+ }
2415
3341
  async function waitForRetry(attemptIndex) {
2416
3342
  const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
2417
3343
  if (!delay) return;
@@ -2591,6 +3517,61 @@ function createStreamingPlaceholderRewriter(piiManager, mapping) {
2591
3517
  }
2592
3518
  };
2593
3519
  }
3520
+ var TYPED_PLACEHOLDER_RE = /<[A-Z][A-Z0-9_]*_\d+>/g;
3521
+ function derivePlaceholderMappingFromTransform(source, transformed) {
3522
+ if (!source || !transformed || source === transformed) {
3523
+ return {};
3524
+ }
3525
+ const placeholders = [...transformed.matchAll(TYPED_PLACEHOLDER_RE)].map((match) => ({
3526
+ token: match[0],
3527
+ start: match.index ?? 0,
3528
+ end: (match.index ?? 0) + match[0].length
3529
+ }));
3530
+ if (placeholders.length === 0) {
3531
+ return {};
3532
+ }
3533
+ const mapping = {};
3534
+ let sourceCursor = 0;
3535
+ let transformedCursor = 0;
3536
+ for (const placeholder of placeholders) {
3537
+ const literalBefore = transformed.slice(transformedCursor, placeholder.start);
3538
+ if (literalBefore) {
3539
+ const literalIndex = source.indexOf(literalBefore, sourceCursor);
3540
+ if (literalIndex < 0) {
3541
+ return {};
3542
+ }
3543
+ sourceCursor = literalIndex + literalBefore.length;
3544
+ }
3545
+ const nextPlaceholderStart = placeholders.find((candidate) => candidate.start > placeholder.start)?.start ?? transformed.length;
3546
+ const literalAfter = transformed.slice(placeholder.end, nextPlaceholderStart);
3547
+ const nextLiteralIndex = literalAfter ? source.indexOf(literalAfter, sourceCursor) : nextPlaceholderStart >= transformed.length ? source.length : sourceCursor;
3548
+ if (nextLiteralIndex < sourceCursor) {
3549
+ return {};
3550
+ }
3551
+ const originalValue = source.slice(sourceCursor, nextLiteralIndex);
3552
+ if (originalValue.length > 0 && typeof mapping[placeholder.token] !== "string") {
3553
+ mapping[placeholder.token] = originalValue;
3554
+ }
3555
+ sourceCursor = nextLiteralIndex;
3556
+ transformedCursor = placeholder.end;
3557
+ }
3558
+ return mapping;
3559
+ }
3560
+ function mergePiiMappings(primary, fallback) {
3561
+ const merged = { ...primary };
3562
+ for (const [placeholder, value] of Object.entries(fallback)) {
3563
+ if (typeof merged[placeholder] !== "string" && typeof value === "string") {
3564
+ merged[placeholder] = value;
3565
+ }
3566
+ }
3567
+ return merged;
3568
+ }
3569
+ function textContainsMappingPlaceholder(text, mapping) {
3570
+ if (!text || !mapping) {
3571
+ return false;
3572
+ }
3573
+ return Object.keys(mapping).some((placeholder) => placeholder.length > 0 && text.includes(placeholder));
3574
+ }
2594
3575
  var SecurityBlockError = class extends Error {
2595
3576
  constructor(reason = "guard_denied") {
2596
3577
  super(`AgentID: Security Blocked (${reason})`);
@@ -2615,6 +3596,7 @@ var AgentID = class {
2615
3596
  this.apiKey = resolveConfiguredApiKey(config.apiKey);
2616
3597
  this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
2617
3598
  this.configuredPiiMasking = typeof config.piiMasking === "boolean" ? config.piiMasking : null;
3599
+ this.configuredSecretMasking = typeof config.secretMasking === "boolean" ? config.secretMasking : null;
2618
3600
  this.checkInjection = config.checkInjection !== false;
2619
3601
  this.clientFastFail = config.clientFastFail === true || config.client_fast_fail === true;
2620
3602
  this.aiScanEnabled = config.aiScanEnabled !== false;
@@ -2636,6 +3618,9 @@ var AgentID = class {
2636
3618
  get piiMasking() {
2637
3619
  return this.configuredPiiMasking ?? void 0;
2638
3620
  }
3621
+ get secretMasking() {
3622
+ return this.configuredSecretMasking ?? void 0;
3623
+ }
2639
3624
  resolveEffectivePiiMasking(config) {
2640
3625
  if (config?.enable_sdk_pii_masking === true) {
2641
3626
  return true;
@@ -2645,12 +3630,24 @@ var AgentID = class {
2645
3630
  }
2646
3631
  return false;
2647
3632
  }
3633
+ resolveEffectiveSecretMasking(config) {
3634
+ if (config?.enable_sdk_secret_masking === true || config?.enable_sdk_pii_masking === true) {
3635
+ return true;
3636
+ }
3637
+ if (this.configuredSecretMasking !== null) {
3638
+ return this.configuredSecretMasking;
3639
+ }
3640
+ return false;
3641
+ }
2648
3642
  getEffectivePiiMasking(options) {
2649
3643
  return this.resolveEffectivePiiMasking(this.getCachedCapabilityConfig(options));
2650
3644
  }
2651
3645
  getEffectivePiiMaskingForConfig(capabilityConfig) {
2652
3646
  return this.resolveEffectivePiiMasking(capabilityConfig);
2653
3647
  }
3648
+ getEffectiveSecretMaskingForConfig(capabilityConfig) {
3649
+ return this.resolveEffectiveSecretMasking(capabilityConfig);
3650
+ }
2654
3651
  buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig) {
2655
3652
  return {
2656
3653
  capabilities: {
@@ -2658,6 +3655,9 @@ var AgentID = class {
2658
3655
  pii_masking_enabled: this.resolveEffectivePiiMasking(
2659
3656
  capabilityConfig ?? this.getCachedCapabilityConfig()
2660
3657
  ),
3658
+ secret_masking_enabled: this.resolveEffectiveSecretMasking(
3659
+ capabilityConfig ?? this.getCachedCapabilityConfig()
3660
+ ),
2661
3661
  framework
2662
3662
  }
2663
3663
  };
@@ -2797,10 +3797,13 @@ var AgentID = class {
2797
3797
  systemId: params.systemId,
2798
3798
  eventId: params.clientEventId,
2799
3799
  clientEventId: params.clientEventId,
2800
- telemetryMetadata: buildSdkTimingMetadata({
2801
- sdkConfigFetchMs: params.sdkConfigFetchMs,
2802
- sdkConfigVersion: params.capabilityConfig.version
2803
- })
3800
+ telemetryMetadata: mergeTelemetryContexts(
3801
+ params.telemetryMetadata,
3802
+ buildSdkTimingMetadata({
3803
+ sdkConfigFetchMs: params.sdkConfigFetchMs,
3804
+ sdkConfigVersion: params.capabilityConfig.version
3805
+ })
3806
+ )
2804
3807
  });
2805
3808
  }
2806
3809
  try {
@@ -2817,7 +3820,8 @@ var AgentID = class {
2817
3820
  actionTaken: event.actionTaken,
2818
3821
  apiKey: params.apiKey,
2819
3822
  sdkConfigFetchMs: params.sdkConfigFetchMs,
2820
- sdkLocalScanMs
3823
+ sdkLocalScanMs,
3824
+ telemetryMetadata: params.telemetryMetadata
2821
3825
  });
2822
3826
  }
2823
3827
  return {
@@ -2832,7 +3836,8 @@ var AgentID = class {
2832
3836
  actionTaken: error.actionTaken,
2833
3837
  apiKey: params.apiKey,
2834
3838
  sdkConfigFetchMs: params.sdkConfigFetchMs,
2835
- sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
3839
+ sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt),
3840
+ telemetryMetadata: params.telemetryMetadata
2836
3841
  });
2837
3842
  }
2838
3843
  throw error;
@@ -2846,7 +3851,7 @@ var AgentID = class {
2846
3851
  );
2847
3852
  let sanitizedInput = params.input;
2848
3853
  let sdkLocalScanMs = 0;
2849
- if (this.configuredPiiMasking === null) {
3854
+ if (this.configuredPiiMasking === null || this.configuredSecretMasking === null) {
2850
3855
  const refreshed = await this.refreshCapabilityConfigBeforeClientControl({
2851
3856
  capabilityConfig,
2852
3857
  sdkConfigFetchMs,
@@ -2857,8 +3862,12 @@ var AgentID = class {
2857
3862
  }
2858
3863
  if (!this.clientFastFail) {
2859
3864
  const effectivePiiMasking2 = this.resolveEffectivePiiMasking(capabilityConfig);
2860
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2) {
2861
- const masked = this.pii.anonymize(sanitizedInput);
3865
+ const effectiveSecretMasking2 = this.resolveEffectiveSecretMasking(capabilityConfig);
3866
+ if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2 || !capabilityConfig.block_secret_leakage && effectiveSecretMasking2) {
3867
+ const masked = this.pii.anonymize(sanitizedInput, {
3868
+ pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking2,
3869
+ secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking2
3870
+ });
2862
3871
  return {
2863
3872
  sanitizedInput: masked.maskedText,
2864
3873
  capabilityConfig,
@@ -2890,13 +3899,18 @@ var AgentID = class {
2890
3899
  apiKey: effectiveApiKey,
2891
3900
  clientEventId: params.clientEventId,
2892
3901
  sdkConfigFetchMs,
3902
+ telemetryMetadata: params.telemetryMetadata,
2893
3903
  runPromptInjectionCheck: !params.skipInjectionScan
2894
3904
  });
2895
3905
  sanitizedInput = enforced.sanitizedInput;
2896
3906
  sdkLocalScanMs = enforced.sdkLocalScanMs;
2897
3907
  const effectivePiiMasking = this.resolveEffectivePiiMasking(capabilityConfig);
2898
- if (!capabilityConfig.block_pii_leakage && effectivePiiMasking) {
2899
- const masked = this.pii.anonymize(sanitizedInput);
3908
+ const effectiveSecretMasking = this.resolveEffectiveSecretMasking(capabilityConfig);
3909
+ if (!capabilityConfig.block_pii_leakage && effectivePiiMasking || !capabilityConfig.block_secret_leakage && effectiveSecretMasking) {
3910
+ const masked = this.pii.anonymize(sanitizedInput, {
3911
+ pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking,
3912
+ secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking
3913
+ });
2900
3914
  return {
2901
3915
  sanitizedInput: masked.maskedText,
2902
3916
  capabilityConfig,
@@ -2932,6 +3946,7 @@ var AgentID = class {
2932
3946
  apiKey: effectiveApiKey,
2933
3947
  clientEventId: params.clientEventId,
2934
3948
  sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
3949
+ telemetryMetadata: params.telemetryMetadata,
2935
3950
  runPromptInjectionCheck: true
2936
3951
  });
2937
3952
  return {
@@ -2995,9 +4010,30 @@ var AgentID = class {
2995
4010
  if (!message || typeof message !== "object") {
2996
4011
  return req;
2997
4012
  }
4013
+ const currentContent = message.content;
4014
+ let nextContent = maskedText;
4015
+ if (Array.isArray(currentContent)) {
4016
+ let textReplaced = false;
4017
+ const preservedParts = [];
4018
+ for (const part of currentContent) {
4019
+ if (!part || typeof part !== "object" || part.type !== "text" || typeof part.text !== "string") {
4020
+ preservedParts.push(part);
4021
+ continue;
4022
+ }
4023
+ if (textReplaced) {
4024
+ continue;
4025
+ }
4026
+ textReplaced = true;
4027
+ preservedParts.push({
4028
+ ...part,
4029
+ text: maskedText
4030
+ });
4031
+ }
4032
+ nextContent = textReplaced ? preservedParts : [{ type: "text", text: maskedText }, ...currentContent];
4033
+ }
2998
4034
  newMessages[lastUserIdx] = {
2999
4035
  ...message,
3000
- content: maskedText
4036
+ content: nextContent
3001
4037
  };
3002
4038
  if (!req || typeof req !== "object") {
3003
4039
  return req;
@@ -3016,6 +4052,7 @@ var AgentID = class {
3016
4052
  event_type: "security_policy_violation",
3017
4053
  severity: "high",
3018
4054
  metadata: {
4055
+ ...params.telemetryMetadata ?? {},
3019
4056
  event_type: "security_policy_violation",
3020
4057
  severity: "high",
3021
4058
  system_id: params.systemId,
@@ -3043,6 +4080,7 @@ var AgentID = class {
3043
4080
  event_type: "security_alert",
3044
4081
  severity: "warning",
3045
4082
  metadata: {
4083
+ ...params.guardParams.metadata ?? {},
3046
4084
  source: "guard",
3047
4085
  status: params.status,
3048
4086
  guard_reason: params.reason,
@@ -3485,21 +4523,29 @@ var AgentID = class {
3485
4523
  wrapCompletion(completion, options) {
3486
4524
  if (typeof completion === "string") {
3487
4525
  const masked = this.pii.anonymize(completion);
4526
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4527
+ completion,
4528
+ options?.piiMapping
4529
+ );
3488
4530
  return {
3489
4531
  mode: "static",
3490
4532
  rawOutput: completion,
3491
4533
  transformedOutput: masked.maskedText,
3492
- outputMasked: masked.maskedText !== completion
4534
+ outputMasked: masked.maskedText !== completion || placeholderOutputMasked
3493
4535
  };
3494
4536
  }
3495
4537
  if (!isAsyncIterable(completion)) {
3496
4538
  const asText = String(completion ?? "");
3497
4539
  const masked = this.pii.anonymize(asText);
4540
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4541
+ asText,
4542
+ options?.piiMapping
4543
+ );
3498
4544
  return {
3499
4545
  mode: "static",
3500
4546
  rawOutput: asText,
3501
4547
  transformedOutput: masked.maskedText,
3502
- outputMasked: masked.maskedText !== asText
4548
+ outputMasked: masked.maskedText !== asText || placeholderOutputMasked
3503
4549
  };
3504
4550
  }
3505
4551
  const source = completion;
@@ -3509,8 +4555,10 @@ var AgentID = class {
3509
4555
  const isOpenAIStreamFinishChunk = this.isOpenAIStreamFinishChunk.bind(this);
3510
4556
  const rewriteOpenAIStreamChunkForClient = this.rewriteOpenAIStreamChunkForClient.bind(this);
3511
4557
  const createSyntheticOpenAIStreamChunk = this.createSyntheticOpenAIStreamChunk.bind(this);
4558
+ const setOpenAIStreamChunkText = this.setOpenAIStreamChunkText.bind(this);
3512
4559
  const piiManager = this.pii;
3513
4560
  const streamRewriter = options?.deanonymizeForClient === true && options.piiMapping ? createStreamingPlaceholderRewriter(piiManager, options.piiMapping) : null;
4561
+ const maskForClient = options?.maskForClient === true && streamRewriter === null;
3514
4562
  let lastUsage;
3515
4563
  let resolveDone = null;
3516
4564
  let rejectDone = null;
@@ -3523,12 +4571,17 @@ var AgentID = class {
3523
4571
  try {
3524
4572
  let finishChunkFlushed = false;
3525
4573
  let lastChunkTemplate;
4574
+ let clientRawText = "";
4575
+ let clientMaskFlushed = false;
3526
4576
  for await (const chunk of source) {
3527
4577
  const chunkText = extractStreamChunkText(chunk);
3528
- const isFinishChunk = streamRewriter ? isOpenAIStreamFinishChunk(chunk) : false;
4578
+ const isFinishChunk = streamRewriter || maskForClient ? isOpenAIStreamFinishChunk(chunk) : false;
3529
4579
  if (chunkText) {
3530
4580
  await collector.push(chunkText);
3531
4581
  lastChunkTemplate = chunk;
4582
+ if (maskForClient) {
4583
+ clientRawText += chunkText;
4584
+ }
3532
4585
  }
3533
4586
  const chunkUsage = extractStreamChunkUsage(chunk);
3534
4587
  if (chunkUsage) {
@@ -3548,6 +4601,28 @@ var AgentID = class {
3548
4601
  }
3549
4602
  continue;
3550
4603
  }
4604
+ if (maskForClient) {
4605
+ if (isFinishChunk) {
4606
+ const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
4607
+ clientMaskFlushed = true;
4608
+ if (maskedClientText.length > 0) {
4609
+ yield createSyntheticOpenAIStreamChunk(
4610
+ maskedClientText,
4611
+ lastChunkTemplate ?? chunk
4612
+ );
4613
+ }
4614
+ if (chunkText) {
4615
+ setOpenAIStreamChunkText(chunk, "");
4616
+ }
4617
+ yield chunk;
4618
+ finishChunkFlushed = true;
4619
+ continue;
4620
+ }
4621
+ if (!chunkText) {
4622
+ yield chunk;
4623
+ }
4624
+ continue;
4625
+ }
3551
4626
  yield chunk;
3552
4627
  }
3553
4628
  if (streamRewriter && !finishChunkFlushed) {
@@ -3559,14 +4634,27 @@ var AgentID = class {
3559
4634
  );
3560
4635
  }
3561
4636
  }
4637
+ if (maskForClient && !clientMaskFlushed) {
4638
+ const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
4639
+ if (maskedClientText.length > 0) {
4640
+ yield createSyntheticOpenAIStreamChunk(
4641
+ maskedClientText,
4642
+ lastChunkTemplate
4643
+ );
4644
+ }
4645
+ }
3562
4646
  await collector.close();
3563
4647
  const rawOutput = await collector.result;
3564
4648
  const masked = piiManager.anonymize(rawOutput);
4649
+ const placeholderOutputMasked = textContainsMappingPlaceholder(
4650
+ rawOutput,
4651
+ options?.piiMapping
4652
+ );
3565
4653
  resolveDone?.({
3566
4654
  mode: "static",
3567
4655
  rawOutput,
3568
4656
  transformedOutput: masked.maskedText,
3569
- outputMasked: masked.maskedText !== rawOutput,
4657
+ outputMasked: masked.maskedText !== rawOutput || placeholderOutputMasked,
3570
4658
  usage: lastUsage
3571
4659
  });
3572
4660
  } catch (error) {
@@ -3601,6 +4689,37 @@ var AgentID = class {
3601
4689
  );
3602
4690
  }
3603
4691
  }
4692
+ buildOperationLogParams(params) {
4693
+ return createAgentIdOperationLog(params);
4694
+ }
4695
+ async logOperation(params, options) {
4696
+ return this.log(this.buildOperationLogParams(params), options);
4697
+ }
4698
+ async logPromptPreflightStep(params, options) {
4699
+ const telemetry = buildPromptPreflightTelemetry(params);
4700
+ const summary = firstNonEmptyString(telemetry?.step_summary, telemetry?.stepSummary) ?? summarizePromptPreflightResult({
4701
+ verdict: params.verdict,
4702
+ localFallbackApplied: params.local_fallback_applied,
4703
+ localFallbackReason: params.local_fallback_reason
4704
+ });
4705
+ await this.logOperation(
4706
+ {
4707
+ system_id: params.system_id,
4708
+ user_id: params.user_id,
4709
+ request_identity: params.request_identity,
4710
+ input: params.input,
4711
+ output: summary,
4712
+ model: "not_applicable",
4713
+ latency: params.guard_latency_ms ?? void 0,
4714
+ telemetry,
4715
+ client_capabilities: params.client_capabilities
4716
+ },
4717
+ options
4718
+ );
4719
+ }
4720
+ operation(params, options) {
4721
+ return this.logOperation(params, options);
4722
+ }
3604
4723
  /**
3605
4724
  * Analytics alias for telemetry logging.
3606
4725
  */
@@ -3645,49 +4764,56 @@ var AgentID = class {
3645
4764
  if (typeof originalCreate !== "function") return originalCreate;
3646
4765
  return async (...args) => {
3647
4766
  const normalizedCreateArgs = normalizeOpenAICreateArgs(args);
3648
- const req = normalizedCreateArgs?.[0] ?? {};
4767
+ const rawReq = normalizedCreateArgs?.[0] ?? {};
4768
+ const requestTelemetry = extractRequestTelemetryContext(rawReq);
4769
+ const telemetryMetadata = mergeTelemetryContexts(
4770
+ options.telemetry,
4771
+ requestTelemetry
4772
+ );
4773
+ const providerReq = stripRequestTelemetryContext(rawReq);
3649
4774
  const pipelineStartedAt = Date.now();
3650
- const requestLevelApiKey = options.resolveApiKey?.(req) ?? options.apiKey ?? options.api_key;
4775
+ const requestLevelApiKey = options.resolveApiKey?.(rawReq) ?? options.apiKey ?? options.api_key;
3651
4776
  const effectiveApiKey = this.resolveApiKey(requestLevelApiKey);
3652
4777
  const requestOptions = { apiKey: effectiveApiKey };
3653
- const clientEventId = this.resolveClientEventId(req);
4778
+ const clientEventId = this.resolveClientEventId(rawReq);
3654
4779
  const effectiveStrictMode = await this.resolveEffectiveStrictMode(requestOptions);
3655
- const stream = adapter.isStream(req);
4780
+ const stream = adapter.isStream(providerReq);
3656
4781
  let capabilityConfig = this.getCachedCapabilityConfig(requestOptions);
3657
- const userText = adapter.extractInput(req);
3658
- let maskedText = userText;
3659
- let maskedReq = req;
3660
- let createArgs = normalizedCreateArgs;
4782
+ const userText = adapter.extractInput(providerReq);
4783
+ const requestAttachments = adapter.extractAttachments(providerReq);
4784
+ const hasGuardContent = userText !== null || requestAttachments.length > 0;
4785
+ let maskedText = userText ?? "";
4786
+ let maskedReq = providerReq;
4787
+ let createArgs = providerReq === rawReq ? normalizedCreateArgs : [{ ...providerReq }, ...normalizedCreateArgs.slice(1)];
3661
4788
  let mapping = {};
3662
- let shouldDeanonymize = false;
3663
4789
  let sdkConfigFetchMs = 0;
3664
4790
  let sdkLocalScanMs = 0;
3665
- if (userText) {
4791
+ if (hasGuardContent) {
3666
4792
  const prepared = await this.prepareInputForDispatch({
3667
- input: userText,
4793
+ input: userText ?? "",
3668
4794
  systemId,
3669
4795
  stream,
3670
- clientEventId
4796
+ clientEventId,
4797
+ telemetryMetadata
3671
4798
  }, requestOptions);
3672
4799
  capabilityConfig = prepared.capabilityConfig;
3673
4800
  maskedText = prepared.sanitizedInput;
3674
4801
  mapping = prepared.piiMapping ?? {};
3675
- shouldDeanonymize = prepared.shouldDeanonymize === true;
3676
4802
  sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
3677
4803
  sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
3678
- if (maskedText !== userText) {
4804
+ if (maskedText !== (userText ?? "")) {
3679
4805
  maskedReq = this.withMaskedOpenAIRequest(
3680
- req,
4806
+ providerReq,
3681
4807
  maskedText
3682
4808
  );
3683
- const nextCreateArgs = [...normalizedCreateArgs];
4809
+ const nextCreateArgs = [...createArgs];
3684
4810
  nextCreateArgs[0] = maskedReq;
3685
4811
  createArgs = nextCreateArgs;
3686
4812
  }
3687
4813
  }
3688
- if (!maskedText) {
4814
+ if (!hasGuardContent) {
3689
4815
  throw new Error(
3690
- "AgentID: No user message found. Security guard requires string input."
4816
+ "AgentID: No user message or supported inline attachment found. Security guard requires prompt content."
3691
4817
  );
3692
4818
  }
3693
4819
  const verdict = await this.guard({
@@ -3698,6 +4824,8 @@ var AgentID = class {
3698
4824
  client_event_id: clientEventId,
3699
4825
  expected_languages: expectedLanguages,
3700
4826
  request_identity: options.request_identity,
4827
+ metadata: telemetryMetadata,
4828
+ attachments: requestAttachments,
3701
4829
  client_capabilities: this.buildClientCapabilities(
3702
4830
  "openai",
3703
4831
  false,
@@ -3719,22 +4847,43 @@ var AgentID = class {
3719
4847
  apiKey: effectiveApiKey,
3720
4848
  clientEventId,
3721
4849
  sdkConfigFetchMs,
4850
+ telemetryMetadata,
3722
4851
  runPromptInjectionCheck: true
3723
4852
  });
3724
4853
  maskedText = fallback.sanitizedInput;
3725
4854
  sdkLocalScanMs = fallback.sdkLocalScanMs;
3726
4855
  }
3727
4856
  } else {
4857
+ await this.logPromptPreflightStep(
4858
+ {
4859
+ system_id: systemId,
4860
+ user_id: options.user_id,
4861
+ request_identity: options.request_identity,
4862
+ input: maskedText,
4863
+ telemetry: telemetryMetadata,
4864
+ verdict,
4865
+ guard_event_id: verdict.guard_event_id ?? null,
4866
+ 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),
4867
+ preflight_for_client_event_id: typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId,
4868
+ client_capabilities: this.buildClientCapabilities(
4869
+ "openai",
4870
+ false,
4871
+ capabilityConfig
4872
+ ),
4873
+ runtime_surface: "openai_sdk_guard"
4874
+ },
4875
+ requestOptions
4876
+ );
3728
4877
  throw new SecurityBlockError(verdict.reason ?? "guard_denied");
3729
4878
  }
3730
4879
  }
3731
- const currentRequestInput = adapter.extractInput(maskedReq);
4880
+ const currentRequestInput = adapter.extractInput(maskedReq) ?? "";
3732
4881
  if (maskedText !== currentRequestInput) {
3733
4882
  maskedReq = this.withMaskedOpenAIRequest(
3734
- req,
4883
+ providerReq,
3735
4884
  maskedText
3736
4885
  );
3737
- const nextCreateArgs = [...normalizedCreateArgs];
4886
+ const nextCreateArgs = [...createArgs];
3738
4887
  nextCreateArgs[0] = maskedReq;
3739
4888
  createArgs = nextCreateArgs;
3740
4889
  }
@@ -3745,15 +4894,44 @@ var AgentID = class {
3745
4894
  const isShadowMode = verdict.shadow_mode === true;
3746
4895
  const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
3747
4896
  if (transformedInput !== maskedText) {
4897
+ const serverDerivedMapping = derivePlaceholderMappingFromTransform(
4898
+ maskedText,
4899
+ transformedInput
4900
+ );
4901
+ if (Object.keys(serverDerivedMapping).length > 0) {
4902
+ mapping = mergePiiMappings(mapping, serverDerivedMapping);
4903
+ }
3748
4904
  maskedText = transformedInput;
3749
4905
  maskedReq = this.withMaskedOpenAIRequest(
3750
- req,
4906
+ providerReq,
3751
4907
  transformedInput
3752
4908
  );
3753
- const nextCreateArgs = [...normalizedCreateArgs];
4909
+ const nextCreateArgs = [...createArgs];
3754
4910
  nextCreateArgs[0] = maskedReq;
3755
4911
  createArgs = nextCreateArgs;
3756
4912
  }
4913
+ await this.logPromptPreflightStep(
4914
+ {
4915
+ system_id: systemId,
4916
+ user_id: options.user_id,
4917
+ request_identity: options.request_identity,
4918
+ input: maskedText,
4919
+ telemetry: telemetryMetadata,
4920
+ verdict,
4921
+ guard_event_id: guardEventId,
4922
+ guard_latency_ms: guardLatencyMs,
4923
+ preflight_for_client_event_id: canonicalClientEventId,
4924
+ client_capabilities: this.buildClientCapabilities(
4925
+ "openai",
4926
+ false,
4927
+ capabilityConfig
4928
+ ),
4929
+ local_fallback_applied: localFallbackApplied,
4930
+ local_fallback_reason: localFallbackReason,
4931
+ runtime_surface: "openai_sdk_guard"
4932
+ },
4933
+ requestOptions
4934
+ );
3757
4935
  if (stream) {
3758
4936
  const modelStartedAt2 = Date.now();
3759
4937
  const streamResponse = await originalCreate.apply(compTarget, createArgs);
@@ -3765,7 +4943,8 @@ var AgentID = class {
3765
4943
  })(),
3766
4944
  {
3767
4945
  piiMapping: mapping,
3768
- deanonymizeForClient: shouldDeanonymize
4946
+ deanonymizeForClient: false,
4947
+ maskForClient: !isShadowMode
3769
4948
  }
3770
4949
  );
3771
4950
  if (maskedText && wrappedCompletion.mode === "stream") {
@@ -3784,29 +4963,32 @@ var AgentID = class {
3784
4963
  usage: result.usage,
3785
4964
  latency: modelLatencyMs2,
3786
4965
  event_type: "complete",
3787
- metadata: {
3788
- transformed_input: maskedText,
3789
- transformed_output: result.transformedOutput,
3790
- output_masked: result.outputMasked,
3791
- shadow_mode: isShadowMode,
3792
- simulated_decision: verdict.simulated_decision ?? null,
3793
- simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
3794
- response_streamed: true,
3795
- sdk_local_fallback_applied: localFallbackApplied,
3796
- sdk_local_fallback_reason: localFallbackReason,
3797
- guard_latency_ms: guardLatencyMs,
3798
- model_latency_ms: modelLatencyMs2,
3799
- total_pipeline_latency_ms: totalPipelineLatencyMs2,
3800
- guard_event_id: guardEventId,
3801
- client_event_id: canonicalClientEventId,
3802
- transparency,
3803
- ...buildSdkTimingMetadata({
4966
+ metadata: mergeTelemetryContexts(
4967
+ telemetryMetadata,
4968
+ {
4969
+ transformed_input: maskedText,
4970
+ transformed_output: result.transformedOutput,
4971
+ output_masked: result.outputMasked,
4972
+ shadow_mode: isShadowMode,
4973
+ simulated_decision: verdict.simulated_decision ?? null,
4974
+ simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
4975
+ response_streamed: true,
4976
+ sdk_local_fallback_applied: localFallbackApplied,
4977
+ sdk_local_fallback_reason: localFallbackReason,
4978
+ guard_latency_ms: guardLatencyMs,
4979
+ model_latency_ms: modelLatencyMs2,
4980
+ total_pipeline_latency_ms: totalPipelineLatencyMs2,
4981
+ guard_event_id: guardEventId,
4982
+ client_event_id: canonicalClientEventId,
4983
+ transparency
4984
+ },
4985
+ buildSdkTimingMetadata({
3804
4986
  sdkConfigFetchMs,
3805
4987
  sdkLocalScanMs,
3806
4988
  sdkGuardMs: guardLatencyMs,
3807
4989
  sdkConfigVersion: capabilityConfig.version
3808
4990
  })
3809
- },
4991
+ ),
3810
4992
  client_capabilities: this.buildClientCapabilities(
3811
4993
  "openai",
3812
4994
  false,
@@ -3837,7 +5019,10 @@ var AgentID = class {
3837
5019
  const totalPipelineLatencyMs = Math.max(0, Date.now() - pipelineStartedAt);
3838
5020
  if (maskedText) {
3839
5021
  const output = adapter.extractOutput(res);
3840
- const wrappedCompletion = this.wrapCompletion(output);
5022
+ const wrappedCompletion = this.wrapCompletion(output, {
5023
+ piiMapping: mapping,
5024
+ deanonymizeForClient: false
5025
+ });
3841
5026
  const model = adapter.getModelName(maskedReq, res);
3842
5027
  const usage = adapter.getTokenUsage(res);
3843
5028
  const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
@@ -3852,29 +5037,32 @@ var AgentID = class {
3852
5037
  usage,
3853
5038
  latency: modelLatencyMs,
3854
5039
  event_type: "complete",
3855
- metadata: {
3856
- transformed_input: maskedText,
3857
- transformed_output: wrappedCompletion.transformedOutput,
3858
- output_masked: wrappedCompletion.outputMasked,
3859
- shadow_mode: isShadowMode,
3860
- simulated_decision: verdict.simulated_decision ?? null,
3861
- simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
3862
- response_streamed: false,
3863
- sdk_local_fallback_applied: localFallbackApplied,
3864
- sdk_local_fallback_reason: localFallbackReason,
3865
- guard_latency_ms: guardLatencyMs,
3866
- model_latency_ms: modelLatencyMs,
3867
- total_pipeline_latency_ms: totalPipelineLatencyMs,
3868
- guard_event_id: guardEventId,
3869
- client_event_id: canonicalClientEventId,
3870
- transparency,
3871
- ...buildSdkTimingMetadata({
5040
+ metadata: mergeTelemetryContexts(
5041
+ telemetryMetadata,
5042
+ {
5043
+ transformed_input: maskedText,
5044
+ transformed_output: wrappedCompletion.transformedOutput,
5045
+ output_masked: wrappedCompletion.outputMasked,
5046
+ shadow_mode: isShadowMode,
5047
+ simulated_decision: verdict.simulated_decision ?? null,
5048
+ simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
5049
+ response_streamed: false,
5050
+ sdk_local_fallback_applied: localFallbackApplied,
5051
+ sdk_local_fallback_reason: localFallbackReason,
5052
+ guard_latency_ms: guardLatencyMs,
5053
+ model_latency_ms: modelLatencyMs,
5054
+ total_pipeline_latency_ms: totalPipelineLatencyMs,
5055
+ guard_event_id: guardEventId,
5056
+ client_event_id: canonicalClientEventId,
5057
+ transparency
5058
+ },
5059
+ buildSdkTimingMetadata({
3872
5060
  sdkConfigFetchMs,
3873
5061
  sdkLocalScanMs,
3874
5062
  sdkGuardMs: guardLatencyMs,
3875
5063
  sdkConfigVersion: capabilityConfig.version
3876
5064
  })
3877
- },
5065
+ ),
3878
5066
  client_capabilities: this.buildClientCapabilities(
3879
5067
  "openai",
3880
5068
  false,
@@ -3891,17 +5079,21 @@ var AgentID = class {
3891
5079
  );
3892
5080
  }
3893
5081
  }
3894
- if (!capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig) && shouldDeanonymize) {
3895
- const deanon = this.pii.deanonymize(adapter.extractOutput(res), mapping);
5082
+ if (!isShadowMode && maskedText) {
5083
+ const output = adapter.extractOutput(res);
5084
+ const maskedOutput = this.wrapCompletion(output, {
5085
+ piiMapping: mapping,
5086
+ deanonymizeForClient: false
5087
+ }).transformedOutput;
3896
5088
  try {
3897
5089
  if (Array.isArray(res?.choices)) {
3898
5090
  for (const choice of res.choices) {
3899
5091
  const typedChoice = choice;
3900
5092
  if (typedChoice?.message && typeof typedChoice.message.content === "string") {
3901
- typedChoice.message.content = deanon;
5093
+ typedChoice.message.content = maskedOutput;
3902
5094
  }
3903
5095
  if (typedChoice?.delta && typeof typedChoice.delta.content === "string") {
3904
- typedChoice.delta.content = deanon;
5096
+ typedChoice.delta.content = maskedOutput;
3905
5097
  }
3906
5098
  }
3907
5099
  }
@@ -3926,14 +5118,169 @@ var AgentID = class {
3926
5118
  });
3927
5119
  }
3928
5120
  };
5121
+ function mergeWorkflowTrailRequestOptions(base, override) {
5122
+ const apiKey = firstNonEmptyString(override?.apiKey, base?.apiKey);
5123
+ return apiKey ? { apiKey } : void 0;
5124
+ }
5125
+ function appendWorkflowErrorMetadata(metadata, error) {
5126
+ const nextMetadata = { ...metadata ?? {} };
5127
+ if (error instanceof Error) {
5128
+ if (typeof nextMetadata.error_name !== "string") {
5129
+ nextMetadata.error_name = error.name;
5130
+ }
5131
+ if (typeof nextMetadata.error_message !== "string" && error.message.trim().length > 0) {
5132
+ nextMetadata.error_message = error.message.trim();
5133
+ }
5134
+ return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
5135
+ }
5136
+ if (typeof nextMetadata.error_message !== "string" && typeof error !== "undefined") {
5137
+ const errorMessage = String(error).trim();
5138
+ if (errorMessage.length > 0) {
5139
+ nextMetadata.error_message = errorMessage;
5140
+ }
5141
+ }
5142
+ return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
5143
+ }
5144
+ var AgentIDWorkflowStep = class {
5145
+ constructor(params) {
5146
+ this.trail = params.trail;
5147
+ this.workflowStepId = params.workflowStepId;
5148
+ this.startEventId = params.startEventId;
5149
+ this.telemetry = params.telemetry;
5150
+ this.startedAtMs = params.startedAtMs;
5151
+ }
5152
+ resolveStepTelemetry(telemetry) {
5153
+ return mergeTelemetryContexts(
5154
+ this.telemetry,
5155
+ createAgentIdTelemetryContext({
5156
+ workflow_step_id: this.workflowStepId,
5157
+ parent_event_id: this.startEventId
5158
+ }),
5159
+ telemetry
5160
+ );
5161
+ }
5162
+ async log(params = {}, options) {
5163
+ return this.trail.logStep(
5164
+ {
5165
+ ...params,
5166
+ telemetry: this.resolveStepTelemetry(params.telemetry)
5167
+ },
5168
+ options
5169
+ );
5170
+ }
5171
+ async complete(params = {}, options) {
5172
+ return this.log(
5173
+ {
5174
+ ...params,
5175
+ latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
5176
+ event_status: params.event_status ?? "completed"
5177
+ },
5178
+ options
5179
+ );
5180
+ }
5181
+ async fail(error, params = {}, options) {
5182
+ return this.log(
5183
+ {
5184
+ ...params,
5185
+ latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
5186
+ metadata: appendWorkflowErrorMetadata(params.metadata, error),
5187
+ event_type: params.event_type ?? "error",
5188
+ event_status: params.event_status ?? "failed",
5189
+ severity: params.severity ?? "error"
5190
+ },
5191
+ options
5192
+ );
5193
+ }
5194
+ };
5195
+ var AgentIDWorkflowTrail = class {
5196
+ constructor(options) {
5197
+ this.agent = options.agent;
5198
+ this.systemId = options.system_id;
5199
+ this.userId = options.user_id;
5200
+ this.requestIdentity = options.request_identity;
5201
+ this.telemetry = createAgentIdTelemetryContext(options.telemetry);
5202
+ this.clientCapabilities = options.client_capabilities;
5203
+ this.requestOptions = options.requestOptions;
5204
+ }
5205
+ async logStep(params = {}, options) {
5206
+ const payload = this.agent.buildOperationLogParams({
5207
+ ...params,
5208
+ system_id: this.systemId,
5209
+ user_id: this.userId,
5210
+ request_identity: this.requestIdentity,
5211
+ telemetry: mergeTelemetryContexts(this.telemetry, params.telemetry),
5212
+ client_capabilities: params.client_capabilities ?? this.clientCapabilities
5213
+ });
5214
+ await this.agent.log(
5215
+ payload,
5216
+ mergeWorkflowTrailRequestOptions(this.requestOptions, options)
5217
+ );
5218
+ return payload;
5219
+ }
5220
+ async startStep(params = {}, options) {
5221
+ const startedAtMs = Date.now();
5222
+ const requestedTelemetry = createAgentIdTelemetryContext(params.telemetry);
5223
+ const workflowStepId = firstNonEmptyString(requestedTelemetry?.workflow_step_id, requestedTelemetry?.workflowStepId) ?? createAgentIdCorrelationId();
5224
+ const startTelemetry = mergeTelemetryContexts(
5225
+ requestedTelemetry,
5226
+ createAgentIdTelemetryContext({
5227
+ workflow_step_id: workflowStepId
5228
+ })
5229
+ );
5230
+ const startPayload = await this.logStep(
5231
+ {
5232
+ ...params,
5233
+ telemetry: startTelemetry,
5234
+ event_type: params.event_type ?? "start",
5235
+ event_status: params.event_status ?? "started"
5236
+ },
5237
+ options
5238
+ );
5239
+ return new AgentIDWorkflowStep({
5240
+ trail: this,
5241
+ workflowStepId,
5242
+ startEventId: startPayload.event_id ?? createEventId2(),
5243
+ telemetry: startTelemetry,
5244
+ startedAtMs
5245
+ });
5246
+ }
5247
+ async runStep(params, run, hooks, options) {
5248
+ const step = await this.startStep(params, options);
5249
+ try {
5250
+ const result = await run();
5251
+ const completeParams = {
5252
+ ...hooks?.complete ?? {},
5253
+ ...hooks?.onComplete?.(result) ?? {}
5254
+ };
5255
+ await step.complete(completeParams, options);
5256
+ return result;
5257
+ } catch (error) {
5258
+ const failParams = {
5259
+ ...hooks?.fail ?? {},
5260
+ ...hooks?.onError?.(error) ?? {}
5261
+ };
5262
+ await step.fail(error, failParams, options);
5263
+ throw error;
5264
+ }
5265
+ }
5266
+ };
5267
+ function createAgentIdWorkflowTrail(options) {
5268
+ return new AgentIDWorkflowTrail(options);
5269
+ }
3929
5270
  // Annotate the CommonJS export names for ESM import in node:
3930
5271
  0 && (module.exports = {
3931
5272
  AgentID,
5273
+ AgentIDWorkflowStep,
5274
+ AgentIDWorkflowTrail,
3932
5275
  DependencyError,
3933
5276
  InjectionScanner,
3934
5277
  OpenAIAdapter,
3935
5278
  PIIManager,
3936
5279
  SecurityBlockError,
5280
+ createAgentIdCorrelationId,
5281
+ createAgentIdOperationLog,
5282
+ createAgentIdTelemetryContext,
5283
+ createAgentIdWorkflowTrail,
3937
5284
  getInjectionScanner,
3938
5285
  scanWithRegex
3939
5286
  });