agentid-sdk 0.1.37 → 0.1.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +303 -57
- package/dist/agentid-BWlN5KCq.d.mts +400 -0
- package/dist/agentid-BWlN5KCq.d.ts +400 -0
- package/dist/{chunk-HWES3LI2.mjs → chunk-25SZBEYX.mjs} +1596 -169
- package/dist/index.d.mts +19 -3
- package/dist/index.d.ts +19 -3
- package/dist/index.js +1655 -168
- package/dist/index.mjs +66 -1
- package/dist/langchain.d.mts +15 -1
- package/dist/langchain.d.ts +15 -1
- package/dist/langchain.js +988 -71
- package/dist/langchain.mjs +451 -16
- package/dist/transparency-badge.d.mts +1 -1
- package/dist/transparency-badge.d.ts +1 -1
- package/package.json +9 -5
- package/dist/agentid-JQx2Iy7B.d.mts +0 -240
- package/dist/agentid-JQx2Iy7B.d.ts +0 -240
|
@@ -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
|
|
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|heslo)(?:\\b|["'])\\s*(?:(?::|=|=>)|(?:is|are|was|were|je)\\b)?\\s*(?:"[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,}"|'[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,}'|[A-Za-z0-9._~!@#$%^&*+=\\/-]{8,})`,
|
|
1128
|
+
flags: "iu",
|
|
1129
|
+
prefilterTerms: ["password", "passwd", "pwd", "heslo"]
|
|
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(
|
|
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 (
|
|
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",
|
|
@@ -946,6 +1228,8 @@ var PHONE_CONTEXT_KEYWORDS = [
|
|
|
946
1228
|
"call",
|
|
947
1229
|
"contact",
|
|
948
1230
|
"number",
|
|
1231
|
+
"cislo",
|
|
1232
|
+
"\u010D\xEDslo",
|
|
949
1233
|
"hotline",
|
|
950
1234
|
"support",
|
|
951
1235
|
"infoline",
|
|
@@ -971,6 +1255,59 @@ var PHONE_CONTEXT_RE = new RegExp(
|
|
|
971
1255
|
"iu"
|
|
972
1256
|
);
|
|
973
1257
|
var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
|
|
1258
|
+
"name",
|
|
1259
|
+
"names",
|
|
1260
|
+
"namen",
|
|
1261
|
+
"firstname",
|
|
1262
|
+
"lastname",
|
|
1263
|
+
"first",
|
|
1264
|
+
"last",
|
|
1265
|
+
"forename",
|
|
1266
|
+
"surname",
|
|
1267
|
+
"family",
|
|
1268
|
+
"given",
|
|
1269
|
+
"jmeno",
|
|
1270
|
+
"jake",
|
|
1271
|
+
"jaky",
|
|
1272
|
+
"jaka",
|
|
1273
|
+
"jsem",
|
|
1274
|
+
"jsme",
|
|
1275
|
+
"napsal",
|
|
1276
|
+
"napsali",
|
|
1277
|
+
"napsala",
|
|
1278
|
+
"napsane",
|
|
1279
|
+
"pouzil",
|
|
1280
|
+
"pouzili",
|
|
1281
|
+
"prijmeni",
|
|
1282
|
+
"vorname",
|
|
1283
|
+
"nachname",
|
|
1284
|
+
"familienname",
|
|
1285
|
+
"what",
|
|
1286
|
+
"which",
|
|
1287
|
+
"whose",
|
|
1288
|
+
"did",
|
|
1289
|
+
"we",
|
|
1290
|
+
"write",
|
|
1291
|
+
"wrote",
|
|
1292
|
+
"written",
|
|
1293
|
+
"type",
|
|
1294
|
+
"typed",
|
|
1295
|
+
"use",
|
|
1296
|
+
"used",
|
|
1297
|
+
"wie",
|
|
1298
|
+
"welchen",
|
|
1299
|
+
"welche",
|
|
1300
|
+
"welches",
|
|
1301
|
+
"haben",
|
|
1302
|
+
"wir",
|
|
1303
|
+
"geschrieben",
|
|
1304
|
+
"getippt",
|
|
1305
|
+
"quel",
|
|
1306
|
+
"quelle",
|
|
1307
|
+
"nom",
|
|
1308
|
+
"que",
|
|
1309
|
+
"cual",
|
|
1310
|
+
"nombre",
|
|
974
1311
|
"write",
|
|
975
1312
|
"code",
|
|
976
1313
|
"script",
|
|
@@ -997,6 +1334,52 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
|
|
|
997
1334
|
"security",
|
|
998
1335
|
"instructions",
|
|
999
1336
|
"instruction",
|
|
1337
|
+
"google",
|
|
1338
|
+
"form",
|
|
1339
|
+
"forms",
|
|
1340
|
+
"engineering",
|
|
1341
|
+
"leadership",
|
|
1342
|
+
"weekly",
|
|
1343
|
+
"daily",
|
|
1344
|
+
"monthly",
|
|
1345
|
+
"quarterly",
|
|
1346
|
+
"sync",
|
|
1347
|
+
"office",
|
|
1348
|
+
"updates",
|
|
1349
|
+
"update",
|
|
1350
|
+
"meeting",
|
|
1351
|
+
"meetings",
|
|
1352
|
+
"agenda",
|
|
1353
|
+
"minutes",
|
|
1354
|
+
"subject",
|
|
1355
|
+
"calendar",
|
|
1356
|
+
"roadmap",
|
|
1357
|
+
"platform",
|
|
1358
|
+
"product",
|
|
1359
|
+
"design",
|
|
1360
|
+
"operations",
|
|
1361
|
+
"business",
|
|
1362
|
+
"newsletter",
|
|
1363
|
+
"report",
|
|
1364
|
+
"reports",
|
|
1365
|
+
"amazon",
|
|
1366
|
+
"web",
|
|
1367
|
+
"services",
|
|
1368
|
+
"aws",
|
|
1369
|
+
"velka",
|
|
1370
|
+
"transformace",
|
|
1371
|
+
"project",
|
|
1372
|
+
"projekt",
|
|
1373
|
+
"program",
|
|
1374
|
+
"initiative",
|
|
1375
|
+
"iniciativa",
|
|
1376
|
+
"migration",
|
|
1377
|
+
"migrace",
|
|
1378
|
+
"test",
|
|
1379
|
+
"uuid",
|
|
1380
|
+
"fixture",
|
|
1381
|
+
"data",
|
|
1382
|
+
"firma",
|
|
1000
1383
|
"rules",
|
|
1001
1384
|
"rule",
|
|
1002
1385
|
"json",
|
|
@@ -1009,10 +1392,22 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
|
|
|
1009
1392
|
"agentid",
|
|
1010
1393
|
"risk",
|
|
1011
1394
|
"score",
|
|
1012
|
-
"summary"
|
|
1395
|
+
"summary",
|
|
1396
|
+
"hi",
|
|
1397
|
+
"hello",
|
|
1398
|
+
"hey",
|
|
1399
|
+
"dear",
|
|
1400
|
+
"team",
|
|
1401
|
+
"ahoj",
|
|
1402
|
+
"dobry",
|
|
1403
|
+
"dobryden",
|
|
1404
|
+
"zdravim"
|
|
1013
1405
|
]);
|
|
1014
1406
|
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
1407
|
var TECHNICAL_CONTEXT_SYMBOL_REGEX = /:\/\/|`|\{|\}|\[|\]|\(|\)|;|\$|=>|::|\/\//;
|
|
1408
|
+
var NAME_LABEL_QUESTION_CONTEXT_REGEX = /\b(?:jak(?:e|y|a|ou)|kter(?:e|y|a|ou)|co|what|which|whose|wie|welch(?:e|er|es|en|em)?|quel(?:le|s|les)?|que|cual(?:es)?|wat|welke|jaki|jakie|jaka)\b[\s\S]{0,80}\b(?:jmeno|prijmeni|name|names|namen|nom|nombre|nome|naam|imie|nazwisko|meno)\b[\s\S]{0,96}\b(?:napsal\p{L}*|napsan\p{L}*|psal\p{L}*|pouzil\p{L}*|pouzili\p{L}*|write|wrote|written|type|typed|enter(?:ed)?|use(?:d)?|say|said|geschrieben|getippt|eingetragen|ecrit|escrib\p{L}*|scritt\p{L}*)\b/iu;
|
|
1409
|
+
var NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX = /(?:[:=]|=>|-|\b(?:is|was|je|jsou|jmenuje|called|named|ist|sind|lautet|est|es)\b)\s*$/iu;
|
|
1410
|
+
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
1411
|
function hasPhoneContext(text, matchStartIndex, windowSize = 50) {
|
|
1017
1412
|
const start = Math.max(0, matchStartIndex - windowSize);
|
|
1018
1413
|
const windowLower = text.slice(start, matchStartIndex).toLowerCase();
|
|
@@ -1029,6 +1424,16 @@ function buildContextWindow(source, index, length) {
|
|
|
1029
1424
|
function isTechnicalContext(contextWindow) {
|
|
1030
1425
|
return TECHNICAL_CONTEXT_WORD_REGEX.test(contextWindow) || TECHNICAL_CONTEXT_SYMBOL_REGEX.test(contextWindow);
|
|
1031
1426
|
}
|
|
1427
|
+
function isNameLabelQuestionContext(contextWindow) {
|
|
1428
|
+
const normalized = normalizePersonWord(contextWindow);
|
|
1429
|
+
if (!normalized.trim()) {
|
|
1430
|
+
return false;
|
|
1431
|
+
}
|
|
1432
|
+
if (!NAME_LABEL_QUESTION_CONTEXT_REGEX.test(normalized)) {
|
|
1433
|
+
return false;
|
|
1434
|
+
}
|
|
1435
|
+
return !NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX.test(normalized.slice(-32));
|
|
1436
|
+
}
|
|
1032
1437
|
function isLikelyPersonNameCandidate(candidate, contextWindow) {
|
|
1033
1438
|
const words = candidate.trim().split(/\s+/);
|
|
1034
1439
|
if (words.length !== 2) {
|
|
@@ -1037,6 +1442,9 @@ function isLikelyPersonNameCandidate(candidate, contextWindow) {
|
|
|
1037
1442
|
if (isTechnicalContext(contextWindow)) {
|
|
1038
1443
|
return false;
|
|
1039
1444
|
}
|
|
1445
|
+
if (isNameLabelQuestionContext(contextWindow)) {
|
|
1446
|
+
return false;
|
|
1447
|
+
}
|
|
1040
1448
|
for (const rawWord of words) {
|
|
1041
1449
|
const normalized = normalizePersonWord(rawWord);
|
|
1042
1450
|
if (normalized.length < 2) {
|
|
@@ -1057,63 +1465,135 @@ var PIIManager = class {
|
|
|
1057
1465
|
*
|
|
1058
1466
|
* Zero-dependency fallback with strict checksum validation for CEE national IDs.
|
|
1059
1467
|
*/
|
|
1060
|
-
anonymize(text) {
|
|
1468
|
+
anonymize(text, options) {
|
|
1061
1469
|
if (!text) return { maskedText: text, mapping: {} };
|
|
1062
1470
|
try {
|
|
1063
1471
|
const detections = [];
|
|
1064
|
-
const
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
|
|
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] });
|
|
1472
|
+
const loweredText = text.toLowerCase();
|
|
1473
|
+
const resolvedOptions = {
|
|
1474
|
+
pii: options?.pii !== false,
|
|
1475
|
+
secrets: options?.secrets !== false
|
|
1476
|
+
};
|
|
1477
|
+
if (!resolvedOptions.pii && !resolvedOptions.secrets) {
|
|
1478
|
+
return { maskedText: text, mapping: {} };
|
|
1081
1479
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
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;
|
|
1480
|
+
if (resolvedOptions.pii) {
|
|
1481
|
+
const emailRe = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
|
|
1482
|
+
for (const m of text.matchAll(emailRe)) {
|
|
1483
|
+
if (m.index == null) continue;
|
|
1484
|
+
detections.push({ start: m.index, end: m.index + m[0].length, type: "EMAIL", text: m[0] });
|
|
1092
1485
|
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
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;
|
|
1486
|
+
const ibanRe = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/gi;
|
|
1487
|
+
for (const m of text.matchAll(ibanRe)) {
|
|
1488
|
+
if (m.index == null) continue;
|
|
1489
|
+
detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
|
|
1102
1490
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1491
|
+
const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
|
|
1492
|
+
for (const m of text.matchAll(ccRe)) {
|
|
1493
|
+
if (m.index == null) continue;
|
|
1494
|
+
const digits = countDigits2(m[0]);
|
|
1495
|
+
if (digits < 12 || digits > 19) continue;
|
|
1496
|
+
if (!luhnCheck(m[0])) continue;
|
|
1497
|
+
detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
|
|
1498
|
+
}
|
|
1499
|
+
const phoneRe = /(?<!\d)(?:\+?\d[\d\s().-]{7,}\d)(?!\d)/g;
|
|
1500
|
+
for (const m of text.matchAll(phoneRe)) {
|
|
1501
|
+
if (m.index == null) continue;
|
|
1502
|
+
const candidate = m[0];
|
|
1503
|
+
const digits = countDigits2(candidate);
|
|
1504
|
+
if (digits < 9 || digits > 15) continue;
|
|
1505
|
+
const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
|
|
1506
|
+
if (!isStrongInternational) {
|
|
1507
|
+
const hasContext = hasPhoneContext(text, m.index);
|
|
1508
|
+
if (!hasContext) continue;
|
|
1509
|
+
}
|
|
1510
|
+
detections.push({ start: m.index, end: m.index + m[0].length, type: "PHONE", text: m[0] });
|
|
1511
|
+
}
|
|
1512
|
+
const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
|
|
1513
|
+
for (const m of text.matchAll(personRe)) {
|
|
1514
|
+
if (m.index == null) continue;
|
|
1515
|
+
const candidate = m[0];
|
|
1516
|
+
const contextWindow = buildContextWindow(text, m.index, candidate.length);
|
|
1517
|
+
if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
|
|
1518
|
+
continue;
|
|
1519
|
+
}
|
|
1520
|
+
detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
|
|
1521
|
+
}
|
|
1522
|
+
BIRTH_NUMBER_CONTEXT_RE.lastIndex = 0;
|
|
1523
|
+
for (const match of text.matchAll(BIRTH_NUMBER_CONTEXT_RE)) {
|
|
1524
|
+
if (match.index == null) continue;
|
|
1525
|
+
const value = match[1] ?? "";
|
|
1526
|
+
if (!/^\d{6}(?:\/?\d{3,4})?$/.test(value)) continue;
|
|
1527
|
+
const localIndex = match[0].lastIndexOf(value);
|
|
1528
|
+
const start = match.index + Math.max(0, localIndex);
|
|
1529
|
+
detections.push({
|
|
1530
|
+
start,
|
|
1531
|
+
end: start + value.length,
|
|
1532
|
+
type: "BIRTH_NUMBER",
|
|
1533
|
+
text: value
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
const nationalIdMatches = detectNationalIdentifiers(text, {
|
|
1537
|
+
deadlineMs: defaultScanDeadlineMs,
|
|
1538
|
+
allowContextBirthNumberFallback: false
|
|
1116
1539
|
});
|
|
1540
|
+
for (const match of nationalIdMatches) {
|
|
1541
|
+
if (match.start < 0 || match.end <= match.start) continue;
|
|
1542
|
+
detections.push({
|
|
1543
|
+
start: match.start,
|
|
1544
|
+
end: match.end,
|
|
1545
|
+
type: "NATIONAL_ID",
|
|
1546
|
+
text: text.slice(match.start, match.end)
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
if (resolvedOptions.secrets) {
|
|
1551
|
+
BASIC_AUTH_PASSWORD_RE.lastIndex = 0;
|
|
1552
|
+
for (const match of text.matchAll(BASIC_AUTH_PASSWORD_RE)) {
|
|
1553
|
+
if (match.index == null) continue;
|
|
1554
|
+
const password = match[1] ?? "";
|
|
1555
|
+
if (!password) continue;
|
|
1556
|
+
const localIndex = match[0].lastIndexOf(password);
|
|
1557
|
+
const start = match.index + Math.max(0, localIndex);
|
|
1558
|
+
detections.push({
|
|
1559
|
+
start,
|
|
1560
|
+
end: start + password.length,
|
|
1561
|
+
type: "BASIC_AUTH_PASSWORD",
|
|
1562
|
+
text: password
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1565
|
+
DISCORD_WEBHOOK_TOKEN_RE.lastIndex = 0;
|
|
1566
|
+
for (const match of text.matchAll(DISCORD_WEBHOOK_TOKEN_RE)) {
|
|
1567
|
+
if (match.index == null) continue;
|
|
1568
|
+
const token = match[1] ?? "";
|
|
1569
|
+
if (!token) continue;
|
|
1570
|
+
const localIndex = match[0].lastIndexOf(token);
|
|
1571
|
+
const start = match.index + Math.max(0, localIndex);
|
|
1572
|
+
detections.push({
|
|
1573
|
+
start,
|
|
1574
|
+
end: start + token.length,
|
|
1575
|
+
type: "DISCORD_WEBHOOK_TOKEN",
|
|
1576
|
+
text: token
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
for (const matcher of sdkSecretMatchers) {
|
|
1580
|
+
if (matcher.id === "discord_webhook_url") {
|
|
1581
|
+
continue;
|
|
1582
|
+
}
|
|
1583
|
+
if (matcher.prefilterTermsLower.length > 0 && !matcher.prefilterTermsLower.some((term) => loweredText.includes(term))) {
|
|
1584
|
+
continue;
|
|
1585
|
+
}
|
|
1586
|
+
matcher.scanRegex.lastIndex = 0;
|
|
1587
|
+
for (const match of text.matchAll(matcher.scanRegex)) {
|
|
1588
|
+
if (match.index == null) continue;
|
|
1589
|
+
detections.push({
|
|
1590
|
+
start: match.index,
|
|
1591
|
+
end: match.index + match[0].length,
|
|
1592
|
+
type: matcher.placeholderType,
|
|
1593
|
+
text: match[0]
|
|
1594
|
+
});
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1117
1597
|
}
|
|
1118
1598
|
const kept = normalizeDetections(text, detections);
|
|
1119
1599
|
if (!kept.length) return { maskedText: text, mapping: {} };
|
|
@@ -1642,14 +2122,14 @@ async function reportSecurityEvent(options) {
|
|
|
1642
2122
|
const inputValue = options.storePii ? snippet : snippetHash;
|
|
1643
2123
|
const eventId = createEventId(options.eventId ?? options.clientEventId);
|
|
1644
2124
|
const metadata = {
|
|
2125
|
+
...options.telemetryMetadata ?? {},
|
|
1645
2126
|
source: options.source,
|
|
1646
2127
|
detector: options.detector,
|
|
1647
2128
|
trigger_rule: options.triggerRule,
|
|
1648
2129
|
language: options.language,
|
|
1649
2130
|
ai_scan_status: options.aiStatus ?? null,
|
|
1650
2131
|
reason: options.reason ?? null,
|
|
1651
|
-
client_event_id: eventId
|
|
1652
|
-
...options.telemetryMetadata ?? {}
|
|
2132
|
+
client_event_id: eventId
|
|
1653
2133
|
};
|
|
1654
2134
|
if (options.storePii) {
|
|
1655
2135
|
metadata.snippet = snippet;
|
|
@@ -1810,7 +2290,7 @@ function getInjectionScanner() {
|
|
|
1810
2290
|
|
|
1811
2291
|
// src/sdk-version.ts
|
|
1812
2292
|
var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
|
|
1813
|
-
var AGENTID_SDK_VERSION_HEADER = "js-0.1.
|
|
2293
|
+
var AGENTID_SDK_VERSION_HEADER = "js-0.1.40".trim().length > 0 ? "js-0.1.40" : FALLBACK_SDK_VERSION;
|
|
1814
2294
|
|
|
1815
2295
|
// src/local-security-enforcer.ts
|
|
1816
2296
|
var DEFAULT_FAIL_OPEN_CONFIG = {
|
|
@@ -1821,7 +2301,9 @@ var DEFAULT_FAIL_OPEN_CONFIG = {
|
|
|
1821
2301
|
block_on_heuristic: false,
|
|
1822
2302
|
inject_transparency_metadata: false,
|
|
1823
2303
|
block_pii_leakage: false,
|
|
1824
|
-
enable_sdk_pii_masking:
|
|
2304
|
+
enable_sdk_pii_masking: true,
|
|
2305
|
+
block_secret_leakage: false,
|
|
2306
|
+
enable_sdk_secret_masking: true,
|
|
1825
2307
|
block_db_access: false,
|
|
1826
2308
|
block_code_execution: false,
|
|
1827
2309
|
block_toxicity: false
|
|
@@ -1863,11 +2345,11 @@ function detectCapabilityViolation(text, config) {
|
|
|
1863
2345
|
}
|
|
1864
2346
|
return null;
|
|
1865
2347
|
}
|
|
1866
|
-
function redactPiiStrict(pii, text) {
|
|
2348
|
+
function redactPiiStrict(pii, text, options) {
|
|
1867
2349
|
if (!text) {
|
|
1868
2350
|
return { redactedText: text, changed: false };
|
|
1869
2351
|
}
|
|
1870
|
-
const masked = pii.anonymize(text);
|
|
2352
|
+
const masked = pii.anonymize(text, options);
|
|
1871
2353
|
let redactedText = masked.maskedText;
|
|
1872
2354
|
const placeholders = Object.keys(masked.mapping).sort((a, b) => b.length - a.length);
|
|
1873
2355
|
for (const placeholder of placeholders) {
|
|
@@ -1896,7 +2378,7 @@ var LocalSecurityEnforcer = class {
|
|
|
1896
2378
|
`AgentID: Security policy blocked (${violationType})`
|
|
1897
2379
|
);
|
|
1898
2380
|
}
|
|
1899
|
-
if (!config.block_pii_leakage) {
|
|
2381
|
+
if (!config.block_pii_leakage && !config.block_secret_leakage) {
|
|
1900
2382
|
return {
|
|
1901
2383
|
sanitizedInput: input,
|
|
1902
2384
|
events: []
|
|
@@ -1906,10 +2388,13 @@ var LocalSecurityEnforcer = class {
|
|
|
1906
2388
|
throw new SecurityPolicyViolationError(
|
|
1907
2389
|
"PII_LEAKAGE_STRICT",
|
|
1908
2390
|
"BLOCKED",
|
|
1909
|
-
"AgentID: Streaming is not supported when
|
|
2391
|
+
"AgentID: Streaming is not supported when strict masking/blocking mode is enabled. Please disable streaming or adjust security settings."
|
|
1910
2392
|
);
|
|
1911
2393
|
}
|
|
1912
|
-
const strictRedaction = redactPiiStrict(this.pii, input
|
|
2394
|
+
const strictRedaction = redactPiiStrict(this.pii, input, {
|
|
2395
|
+
pii: config.block_pii_leakage,
|
|
2396
|
+
secrets: config.block_secret_leakage
|
|
2397
|
+
});
|
|
1913
2398
|
return {
|
|
1914
2399
|
sanitizedInput: strictRedaction.redactedText,
|
|
1915
2400
|
events: strictRedaction.changed ? [
|
|
@@ -2035,6 +2520,16 @@ function normalizeCapabilityConfig(payload) {
|
|
|
2035
2520
|
"enable_sdk_pii_masking",
|
|
2036
2521
|
false
|
|
2037
2522
|
),
|
|
2523
|
+
block_secret_leakage: readOptionalBooleanField(
|
|
2524
|
+
body,
|
|
2525
|
+
"block_secret_leakage",
|
|
2526
|
+
false
|
|
2527
|
+
),
|
|
2528
|
+
enable_sdk_secret_masking: readOptionalBooleanField(
|
|
2529
|
+
body,
|
|
2530
|
+
"enable_sdk_secret_masking",
|
|
2531
|
+
false
|
|
2532
|
+
),
|
|
2038
2533
|
block_db_access: readBooleanField(body, "block_db_access", "block_db"),
|
|
2039
2534
|
block_code_execution: readBooleanField(
|
|
2040
2535
|
body,
|
|
@@ -2215,9 +2710,18 @@ var INGEST_MAX_ATTEMPTS = 3;
|
|
|
2215
2710
|
var INGEST_RETRY_DELAYS_MS = [250, 500];
|
|
2216
2711
|
var GUARD_VERDICT_CACHE_TTL_MS = 0;
|
|
2217
2712
|
var MAX_INGEST_TEXT_CHARS = 32e3;
|
|
2713
|
+
var OPENAI_TELEMETRY_FIELD = "agentid_telemetry";
|
|
2218
2714
|
function normalizeBaseUrl3(baseUrl) {
|
|
2219
2715
|
return baseUrl.replace(/\/+$/, "");
|
|
2220
2716
|
}
|
|
2717
|
+
function firstNonEmptyString(...values) {
|
|
2718
|
+
for (const value of values) {
|
|
2719
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
2720
|
+
return value.trim();
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
return void 0;
|
|
2724
|
+
}
|
|
2221
2725
|
function isAbortSignalLike(value) {
|
|
2222
2726
|
if (!value || typeof value !== "object") return false;
|
|
2223
2727
|
const candidate = value;
|
|
@@ -2379,6 +2883,424 @@ function createCorrelationId(seed) {
|
|
|
2379
2883
|
}
|
|
2380
2884
|
return createPseudoUuidV42();
|
|
2381
2885
|
}
|
|
2886
|
+
function getObjectString(value, ...keys) {
|
|
2887
|
+
for (const key of keys) {
|
|
2888
|
+
const candidate = value?.[key];
|
|
2889
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
2890
|
+
return candidate.trim();
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
return void 0;
|
|
2894
|
+
}
|
|
2895
|
+
function getObjectNumber(value, ...keys) {
|
|
2896
|
+
for (const key of keys) {
|
|
2897
|
+
const candidate = value?.[key];
|
|
2898
|
+
if (typeof candidate === "number" && Number.isFinite(candidate)) {
|
|
2899
|
+
return candidate;
|
|
2900
|
+
}
|
|
2901
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
2902
|
+
const parsed = Number(candidate);
|
|
2903
|
+
if (Number.isFinite(parsed)) {
|
|
2904
|
+
return parsed;
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
return void 0;
|
|
2909
|
+
}
|
|
2910
|
+
function normalizeTelemetryString(value) {
|
|
2911
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
2912
|
+
}
|
|
2913
|
+
function normalizeTelemetryCategory(value) {
|
|
2914
|
+
const normalized = normalizeTelemetryString(value);
|
|
2915
|
+
if (!normalized) return void 0;
|
|
2916
|
+
return normalized.toLowerCase().replace(/[\s-]+/g, "_");
|
|
2917
|
+
}
|
|
2918
|
+
function toSnakeToken(value) {
|
|
2919
|
+
return value.trim().replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_").toLowerCase();
|
|
2920
|
+
}
|
|
2921
|
+
function hasUsageSignals(value) {
|
|
2922
|
+
if (!value) return false;
|
|
2923
|
+
for (const entry of Object.values(value)) {
|
|
2924
|
+
if (typeof entry === "number" && Number.isFinite(entry) && entry > 0) {
|
|
2925
|
+
return true;
|
|
2926
|
+
}
|
|
2927
|
+
if (typeof entry === "string" && entry.trim().length > 0) {
|
|
2928
|
+
const parsed = Number(entry);
|
|
2929
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
2930
|
+
return true;
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
return false;
|
|
2935
|
+
}
|
|
2936
|
+
function truncatePromptPreflightPreview(value, maxChars = 280) {
|
|
2937
|
+
const normalized = value.trim();
|
|
2938
|
+
if (normalized.length <= maxChars) {
|
|
2939
|
+
return normalized;
|
|
2940
|
+
}
|
|
2941
|
+
return `${normalized.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
|
|
2942
|
+
}
|
|
2943
|
+
function formatPromptPreflightReason(reason) {
|
|
2944
|
+
const normalized = normalizeTelemetryString(reason);
|
|
2945
|
+
if (!normalized) {
|
|
2946
|
+
return void 0;
|
|
2947
|
+
}
|
|
2948
|
+
return normalized.replace(/[_-]+/g, " ");
|
|
2949
|
+
}
|
|
2950
|
+
function summarizePromptPreflightResult(params) {
|
|
2951
|
+
const reason = formatPromptPreflightReason(
|
|
2952
|
+
params.localFallbackApplied ? params.localFallbackReason ?? void 0 : params.verdict.reason
|
|
2953
|
+
) ?? "policy evaluation";
|
|
2954
|
+
if (!params.verdict.allowed && !params.localFallbackApplied) {
|
|
2955
|
+
return `Blocked the prompt before model execution because ${reason}.`;
|
|
2956
|
+
}
|
|
2957
|
+
if (params.localFallbackApplied) {
|
|
2958
|
+
return `Guard preflight degraded, so the SDK applied local fallback checks before model execution (${reason}).`;
|
|
2959
|
+
}
|
|
2960
|
+
if (params.verdict.shadow_mode && params.verdict.shadow_blocked) {
|
|
2961
|
+
return "Evaluated the prompt in shadow mode before model execution; shadow policy would have blocked it.";
|
|
2962
|
+
}
|
|
2963
|
+
if (params.verdict.simulated_decision === "masked" || params.verdict.detected_pii) {
|
|
2964
|
+
return "Evaluated the prompt before model execution and masked sensitive content where needed.";
|
|
2965
|
+
}
|
|
2966
|
+
return "Evaluated the prompt and attachments against guardrails before model execution.";
|
|
2967
|
+
}
|
|
2968
|
+
function buildPromptPreflightTelemetry(params) {
|
|
2969
|
+
const baseTelemetry = createAgentIdTelemetryContext(params.telemetry);
|
|
2970
|
+
const baseStepName = firstNonEmptyString(
|
|
2971
|
+
baseTelemetry?.workflow_step_name,
|
|
2972
|
+
baseTelemetry?.workflowStepName
|
|
2973
|
+
);
|
|
2974
|
+
const stepName = baseStepName ? `${toSnakeToken(baseStepName)}_preflight` : "prompt_preflight";
|
|
2975
|
+
const summary = summarizePromptPreflightResult({
|
|
2976
|
+
verdict: params.verdict,
|
|
2977
|
+
localFallbackApplied: params.local_fallback_applied,
|
|
2978
|
+
localFallbackReason: params.local_fallback_reason
|
|
2979
|
+
});
|
|
2980
|
+
return mergeTelemetryContexts(baseTelemetry, {
|
|
2981
|
+
workflow_step_id: createAgentIdCorrelationId(),
|
|
2982
|
+
workflow_step_name: stepName,
|
|
2983
|
+
event_title: "Prompt Preflight Evaluated",
|
|
2984
|
+
event_category: "guard",
|
|
2985
|
+
event_subtype: "prompt_preflight_evaluated",
|
|
2986
|
+
event_status: !params.verdict.allowed && !params.local_fallback_applied ? "blocked" : "completed",
|
|
2987
|
+
step_summary: summary,
|
|
2988
|
+
input_preview: truncatePromptPreflightPreview(params.input),
|
|
2989
|
+
output_preview: summary,
|
|
2990
|
+
runtime_surface: params.runtime_surface ?? "openai_sdk_guard",
|
|
2991
|
+
guard_event_id: params.guard_event_id ?? void 0,
|
|
2992
|
+
guard_latency_ms: params.guard_latency_ms ?? void 0,
|
|
2993
|
+
preflight_for_client_event_id: params.preflight_for_client_event_id,
|
|
2994
|
+
preflight_logged_via_sdk: true,
|
|
2995
|
+
lifecycle_status: "preflight_only"
|
|
2996
|
+
});
|
|
2997
|
+
}
|
|
2998
|
+
function inferOperationCategory(telemetry, eventType) {
|
|
2999
|
+
const explicitCategory = normalizeTelemetryCategory(
|
|
3000
|
+
telemetry?.event_category ?? telemetry?.eventCategory
|
|
3001
|
+
);
|
|
3002
|
+
if (explicitCategory === "ai" || explicitCategory === "llm" || explicitCategory === "inference") {
|
|
3003
|
+
return "ai";
|
|
3004
|
+
}
|
|
3005
|
+
if (explicitCategory === "guard" || explicitCategory === "security") {
|
|
3006
|
+
return "guard";
|
|
3007
|
+
}
|
|
3008
|
+
if (explicitCategory === "tool") return "tool";
|
|
3009
|
+
if (explicitCategory === "delivery" || explicitCategory === "send") return "delivery";
|
|
3010
|
+
if (explicitCategory === "inbox" || explicitCategory === "reply") return "inbox";
|
|
3011
|
+
if (explicitCategory === "workflow" || explicitCategory === "agent") return "workflow";
|
|
3012
|
+
if (explicitCategory === "compliance" || explicitCategory === "transparency") {
|
|
3013
|
+
return "compliance";
|
|
3014
|
+
}
|
|
3015
|
+
if (explicitCategory === "operational" || explicitCategory === "ops") {
|
|
3016
|
+
return "operational";
|
|
3017
|
+
}
|
|
3018
|
+
const haystack = [
|
|
3019
|
+
eventType,
|
|
3020
|
+
telemetry?.event_subtype,
|
|
3021
|
+
telemetry?.eventSubtype,
|
|
3022
|
+
telemetry?.tool_name,
|
|
3023
|
+
telemetry?.toolName,
|
|
3024
|
+
telemetry?.tool_target_type,
|
|
3025
|
+
telemetry?.toolTargetType,
|
|
3026
|
+
telemetry?.workflow_name,
|
|
3027
|
+
telemetry?.workflowName,
|
|
3028
|
+
telemetry?.workflow_step_name,
|
|
3029
|
+
telemetry?.workflowStepName,
|
|
3030
|
+
getObjectString(telemetry, "operation_family", "domain")
|
|
3031
|
+
].filter((entry) => typeof entry === "string" && entry.trim().length > 0).join(" ").replace(/[_./-]+/g, " ").toLowerCase();
|
|
3032
|
+
if (/\b(llm|ai|inference|completion|summary|classification|draft)\b/.test(haystack)) {
|
|
3033
|
+
return "ai";
|
|
3034
|
+
}
|
|
3035
|
+
if (/\b(guard|security|policy|pii|prompt[_ ]?injection|review)\b/.test(haystack)) {
|
|
3036
|
+
return "guard";
|
|
3037
|
+
}
|
|
3038
|
+
if (/\b(reply|inbox|inbound|received|bounce|opened|followup)\b/.test(haystack)) {
|
|
3039
|
+
return "inbox";
|
|
3040
|
+
}
|
|
3041
|
+
if (/\b(email|mail|send|delivery|delivered|slack|sms|webhook|notification)\b/.test(haystack)) {
|
|
3042
|
+
return "delivery";
|
|
3043
|
+
}
|
|
3044
|
+
if (/\b(workflow|step|run|agent)\b/.test(haystack)) {
|
|
3045
|
+
return "workflow";
|
|
3046
|
+
}
|
|
3047
|
+
if (/\b(compliance|transparency|audit|evidence)\b/.test(haystack)) {
|
|
3048
|
+
return "compliance";
|
|
3049
|
+
}
|
|
3050
|
+
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(
|
|
3051
|
+
haystack
|
|
3052
|
+
)) {
|
|
3053
|
+
return "tool";
|
|
3054
|
+
}
|
|
3055
|
+
return "operational";
|
|
3056
|
+
}
|
|
3057
|
+
function inferOperationStatus(params) {
|
|
3058
|
+
const explicitStatus = normalizeTelemetryString(params.eventStatus)?.toLowerCase();
|
|
3059
|
+
if (explicitStatus === "started" || explicitStatus === "completed" || explicitStatus === "failed") {
|
|
3060
|
+
return explicitStatus;
|
|
3061
|
+
}
|
|
3062
|
+
if (explicitStatus === "blocked" || explicitStatus === "skipped") {
|
|
3063
|
+
return explicitStatus;
|
|
3064
|
+
}
|
|
3065
|
+
const normalizedEventType = normalizeTelemetryString(params.eventType)?.toLowerCase();
|
|
3066
|
+
if (normalizedEventType === "start") return "started";
|
|
3067
|
+
if (normalizedEventType === "error") return "failed";
|
|
3068
|
+
if (normalizedEventType === "security_block") return "blocked";
|
|
3069
|
+
if (normalizedEventType === "human_override") return "completed";
|
|
3070
|
+
if (normalizedEventType === "complete") return "completed";
|
|
3071
|
+
return params.severity === "error" ? "failed" : "completed";
|
|
3072
|
+
}
|
|
3073
|
+
function deriveOperationEventType(params) {
|
|
3074
|
+
const explicit = normalizeTelemetryString(params.explicitEventType);
|
|
3075
|
+
if (explicit) {
|
|
3076
|
+
return explicit;
|
|
3077
|
+
}
|
|
3078
|
+
if (params.status === "started") return "start";
|
|
3079
|
+
if (params.status === "failed") return "error";
|
|
3080
|
+
if (params.status === "blocked") {
|
|
3081
|
+
return params.category === "guard" ? "security_block" : "error";
|
|
3082
|
+
}
|
|
3083
|
+
return "complete";
|
|
3084
|
+
}
|
|
3085
|
+
function deriveSubtypeBase(telemetry) {
|
|
3086
|
+
const toolName = normalizeTelemetryString(telemetry?.tool_name ?? telemetry?.toolName);
|
|
3087
|
+
if (toolName) {
|
|
3088
|
+
const tokens = toSnakeToken(toolName).split("_").filter(Boolean);
|
|
3089
|
+
if (tokens.length > 1 && ["workflow", "agent", "operation", "ops", "hr", "finance", "compliance"].includes(tokens[0])) {
|
|
3090
|
+
return tokens.slice(1).join("_");
|
|
3091
|
+
}
|
|
3092
|
+
return tokens.join("_");
|
|
3093
|
+
}
|
|
3094
|
+
const workflowName = normalizeTelemetryString(
|
|
3095
|
+
telemetry?.workflow_step_name ?? telemetry?.workflowStepName ?? telemetry?.workflow_name ?? telemetry?.workflowName
|
|
3096
|
+
);
|
|
3097
|
+
if (workflowName) {
|
|
3098
|
+
return toSnakeToken(workflowName);
|
|
3099
|
+
}
|
|
3100
|
+
return void 0;
|
|
3101
|
+
}
|
|
3102
|
+
function deriveOperationSubtype(params) {
|
|
3103
|
+
const explicitSubtype = normalizeTelemetryString(params.explicitSubtype);
|
|
3104
|
+
if (explicitSubtype) {
|
|
3105
|
+
return toSnakeToken(explicitSubtype);
|
|
3106
|
+
}
|
|
3107
|
+
const base = deriveSubtypeBase(params.telemetry);
|
|
3108
|
+
const suffix = params.status === "started" ? "started" : params.status === "failed" ? "failed" : params.status === "blocked" ? "blocked" : params.status === "skipped" ? "skipped" : "completed";
|
|
3109
|
+
if (base) {
|
|
3110
|
+
return `${base}_${suffix}`;
|
|
3111
|
+
}
|
|
3112
|
+
if (params.eventType === "start") return `${params.category}_started`;
|
|
3113
|
+
if (params.eventType === "error") return `${params.category}_failed`;
|
|
3114
|
+
if (params.eventType === "security_block") return `${params.category}_blocked`;
|
|
3115
|
+
return `${params.category}_completed`;
|
|
3116
|
+
}
|
|
3117
|
+
function inferOperationSeverity(params) {
|
|
3118
|
+
if (params.explicitSeverity) {
|
|
3119
|
+
return params.explicitSeverity;
|
|
3120
|
+
}
|
|
3121
|
+
if (params.status === "failed" || params.status === "blocked") {
|
|
3122
|
+
return "error";
|
|
3123
|
+
}
|
|
3124
|
+
if (params.status === "skipped") {
|
|
3125
|
+
return "warning";
|
|
3126
|
+
}
|
|
3127
|
+
return "info";
|
|
3128
|
+
}
|
|
3129
|
+
function createAgentIdCorrelationId(seed) {
|
|
3130
|
+
return createCorrelationId(seed);
|
|
3131
|
+
}
|
|
3132
|
+
function createAgentIdTelemetryContext(value) {
|
|
3133
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3134
|
+
return void 0;
|
|
3135
|
+
}
|
|
3136
|
+
const raw = { ...value };
|
|
3137
|
+
const normalized = {};
|
|
3138
|
+
const assignString = (key, ...aliases) => {
|
|
3139
|
+
const next = getObjectString(raw, key, ...aliases);
|
|
3140
|
+
if (next) {
|
|
3141
|
+
normalized[key] = next;
|
|
3142
|
+
}
|
|
3143
|
+
};
|
|
3144
|
+
const assignNumber = (key, ...aliases) => {
|
|
3145
|
+
const next = getObjectNumber(raw, key, ...aliases);
|
|
3146
|
+
if (typeof next === "number") {
|
|
3147
|
+
normalized[key] = next;
|
|
3148
|
+
}
|
|
3149
|
+
};
|
|
3150
|
+
assignString("workflow_id", "workflowId");
|
|
3151
|
+
assignString("workflow_run_id", "workflowRunId");
|
|
3152
|
+
assignString("workflow_step_id", "workflowStepId");
|
|
3153
|
+
assignString("workflow_name", "workflowName");
|
|
3154
|
+
assignString("workflow_step_name", "workflowStepName");
|
|
3155
|
+
assignNumber("workflow_step_index", "workflowStepIndex");
|
|
3156
|
+
assignString("parent_event_id", "parentEventId");
|
|
3157
|
+
assignString("tool_name", "toolName");
|
|
3158
|
+
assignString("tool_target", "toolTarget");
|
|
3159
|
+
assignString("tool_target_type", "toolTargetType");
|
|
3160
|
+
assignString("event_title", "eventTitle");
|
|
3161
|
+
assignString("event_status", "eventStatus");
|
|
3162
|
+
assignString("event_category", "eventCategory");
|
|
3163
|
+
assignString("event_subtype", "eventSubtype");
|
|
3164
|
+
const consumedKeys = /* @__PURE__ */ new Set([
|
|
3165
|
+
"workflow_id",
|
|
3166
|
+
"workflowId",
|
|
3167
|
+
"workflow_run_id",
|
|
3168
|
+
"workflowRunId",
|
|
3169
|
+
"workflow_step_id",
|
|
3170
|
+
"workflowStepId",
|
|
3171
|
+
"workflow_name",
|
|
3172
|
+
"workflowName",
|
|
3173
|
+
"workflow_step_name",
|
|
3174
|
+
"workflowStepName",
|
|
3175
|
+
"workflow_step_index",
|
|
3176
|
+
"workflowStepIndex",
|
|
3177
|
+
"parent_event_id",
|
|
3178
|
+
"parentEventId",
|
|
3179
|
+
"tool_name",
|
|
3180
|
+
"toolName",
|
|
3181
|
+
"tool_target",
|
|
3182
|
+
"toolTarget",
|
|
3183
|
+
"tool_target_type",
|
|
3184
|
+
"toolTargetType",
|
|
3185
|
+
"event_title",
|
|
3186
|
+
"eventTitle",
|
|
3187
|
+
"event_status",
|
|
3188
|
+
"eventStatus",
|
|
3189
|
+
"event_category",
|
|
3190
|
+
"eventCategory",
|
|
3191
|
+
"event_subtype",
|
|
3192
|
+
"eventSubtype"
|
|
3193
|
+
]);
|
|
3194
|
+
for (const [key, entry] of Object.entries(raw)) {
|
|
3195
|
+
if (consumedKeys.has(key) || entry === void 0) {
|
|
3196
|
+
continue;
|
|
3197
|
+
}
|
|
3198
|
+
if (typeof entry === "string") {
|
|
3199
|
+
if (entry.trim().length > 0) {
|
|
3200
|
+
normalized[key] = entry.trim();
|
|
3201
|
+
}
|
|
3202
|
+
continue;
|
|
3203
|
+
}
|
|
3204
|
+
normalized[key] = entry;
|
|
3205
|
+
}
|
|
3206
|
+
if (typeof normalized.workflow_id !== "string" && typeof normalized.workflow_run_id === "string") {
|
|
3207
|
+
normalized.workflow_id = normalized.workflow_run_id;
|
|
3208
|
+
}
|
|
3209
|
+
return Object.keys(normalized).length > 0 ? normalized : void 0;
|
|
3210
|
+
}
|
|
3211
|
+
function createAgentIdOperationLog(params) {
|
|
3212
|
+
const telemetry = createAgentIdTelemetryContext(params.telemetry);
|
|
3213
|
+
const category = inferOperationCategory(
|
|
3214
|
+
createAgentIdTelemetryContext({
|
|
3215
|
+
...telemetry ?? {},
|
|
3216
|
+
event_category: params.event_category ?? telemetry?.event_category
|
|
3217
|
+
}),
|
|
3218
|
+
params.event_type
|
|
3219
|
+
);
|
|
3220
|
+
const status = inferOperationStatus({
|
|
3221
|
+
eventStatus: normalizeTelemetryString(params.event_status) ?? normalizeTelemetryString(telemetry?.event_status ?? telemetry?.eventStatus),
|
|
3222
|
+
eventType: params.event_type,
|
|
3223
|
+
severity: params.severity
|
|
3224
|
+
});
|
|
3225
|
+
const eventType = deriveOperationEventType({
|
|
3226
|
+
explicitEventType: params.event_type,
|
|
3227
|
+
status,
|
|
3228
|
+
category
|
|
3229
|
+
});
|
|
3230
|
+
const subtype = deriveOperationSubtype({
|
|
3231
|
+
explicitSubtype: normalizeTelemetryString(params.event_subtype) ?? normalizeTelemetryString(telemetry?.event_subtype ?? telemetry?.eventSubtype),
|
|
3232
|
+
telemetry,
|
|
3233
|
+
category,
|
|
3234
|
+
status,
|
|
3235
|
+
eventType
|
|
3236
|
+
});
|
|
3237
|
+
const severity = inferOperationSeverity({
|
|
3238
|
+
explicitSeverity: params.severity,
|
|
3239
|
+
status
|
|
3240
|
+
});
|
|
3241
|
+
const usage = params.usage;
|
|
3242
|
+
const clientEventId = normalizeTelemetryString(params.client_event_id) ?? normalizeTelemetryString(telemetry?.client_event_id);
|
|
3243
|
+
const modelUsed = category === "ai" || hasUsageSignals(usage) || typeof params.model === "string" && params.model.trim().length > 0 && params.model.trim().toLowerCase() !== "not_applicable";
|
|
3244
|
+
const metadata = {
|
|
3245
|
+
...params.metadata ?? {},
|
|
3246
|
+
...telemetry ?? {},
|
|
3247
|
+
event_category: category,
|
|
3248
|
+
event_subtype: subtype,
|
|
3249
|
+
event_status: status,
|
|
3250
|
+
status,
|
|
3251
|
+
model_used: modelUsed,
|
|
3252
|
+
spend_bearing: category === "ai" && hasUsageSignals(usage)
|
|
3253
|
+
};
|
|
3254
|
+
if (clientEventId && typeof metadata.client_event_id !== "string") {
|
|
3255
|
+
metadata.client_event_id = clientEventId;
|
|
3256
|
+
}
|
|
3257
|
+
return {
|
|
3258
|
+
event_id: normalizeTelemetryString(params.event_id) ?? createEventId2(),
|
|
3259
|
+
system_id: params.system_id,
|
|
3260
|
+
user_id: params.user_id,
|
|
3261
|
+
request_identity: params.request_identity,
|
|
3262
|
+
input: params.input ?? "",
|
|
3263
|
+
output: params.output ?? "",
|
|
3264
|
+
model: normalizeTelemetryString(params.model) ?? "not_applicable",
|
|
3265
|
+
usage,
|
|
3266
|
+
tokens: params.tokens,
|
|
3267
|
+
latency: params.latency,
|
|
3268
|
+
metadata,
|
|
3269
|
+
event_type: eventType,
|
|
3270
|
+
severity,
|
|
3271
|
+
timestamp: params.timestamp,
|
|
3272
|
+
client_capabilities: params.client_capabilities
|
|
3273
|
+
};
|
|
3274
|
+
}
|
|
3275
|
+
function asTelemetryContext(value) {
|
|
3276
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3277
|
+
return void 0;
|
|
3278
|
+
}
|
|
3279
|
+
return createAgentIdTelemetryContext(value);
|
|
3280
|
+
}
|
|
3281
|
+
function mergeTelemetryContexts(...contexts) {
|
|
3282
|
+
const merged = {};
|
|
3283
|
+
let hasValues = false;
|
|
3284
|
+
for (const context of contexts) {
|
|
3285
|
+
if (!context) {
|
|
3286
|
+
continue;
|
|
3287
|
+
}
|
|
3288
|
+
Object.assign(merged, createAgentIdTelemetryContext(context));
|
|
3289
|
+
hasValues = true;
|
|
3290
|
+
}
|
|
3291
|
+
return hasValues ? createAgentIdTelemetryContext(merged) : void 0;
|
|
3292
|
+
}
|
|
3293
|
+
function extractRequestTelemetryContext(requestBody) {
|
|
3294
|
+
return asTelemetryContext(requestBody[OPENAI_TELEMETRY_FIELD]);
|
|
3295
|
+
}
|
|
3296
|
+
function stripRequestTelemetryContext(requestBody) {
|
|
3297
|
+
if (!Object.prototype.hasOwnProperty.call(requestBody, OPENAI_TELEMETRY_FIELD)) {
|
|
3298
|
+
return requestBody;
|
|
3299
|
+
}
|
|
3300
|
+
const nextRequestBody = { ...requestBody };
|
|
3301
|
+
delete nextRequestBody[OPENAI_TELEMETRY_FIELD];
|
|
3302
|
+
return nextRequestBody;
|
|
3303
|
+
}
|
|
2382
3304
|
async function waitForRetry(attemptIndex) {
|
|
2383
3305
|
const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
|
|
2384
3306
|
if (!delay) return;
|
|
@@ -2558,6 +3480,61 @@ function createStreamingPlaceholderRewriter(piiManager, mapping) {
|
|
|
2558
3480
|
}
|
|
2559
3481
|
};
|
|
2560
3482
|
}
|
|
3483
|
+
var TYPED_PLACEHOLDER_RE = /<[A-Z][A-Z0-9_]*_\d+>/g;
|
|
3484
|
+
function derivePlaceholderMappingFromTransform(source, transformed) {
|
|
3485
|
+
if (!source || !transformed || source === transformed) {
|
|
3486
|
+
return {};
|
|
3487
|
+
}
|
|
3488
|
+
const placeholders = [...transformed.matchAll(TYPED_PLACEHOLDER_RE)].map((match) => ({
|
|
3489
|
+
token: match[0],
|
|
3490
|
+
start: match.index ?? 0,
|
|
3491
|
+
end: (match.index ?? 0) + match[0].length
|
|
3492
|
+
}));
|
|
3493
|
+
if (placeholders.length === 0) {
|
|
3494
|
+
return {};
|
|
3495
|
+
}
|
|
3496
|
+
const mapping = {};
|
|
3497
|
+
let sourceCursor = 0;
|
|
3498
|
+
let transformedCursor = 0;
|
|
3499
|
+
for (const placeholder of placeholders) {
|
|
3500
|
+
const literalBefore = transformed.slice(transformedCursor, placeholder.start);
|
|
3501
|
+
if (literalBefore) {
|
|
3502
|
+
const literalIndex = source.indexOf(literalBefore, sourceCursor);
|
|
3503
|
+
if (literalIndex < 0) {
|
|
3504
|
+
return {};
|
|
3505
|
+
}
|
|
3506
|
+
sourceCursor = literalIndex + literalBefore.length;
|
|
3507
|
+
}
|
|
3508
|
+
const nextPlaceholderStart = placeholders.find((candidate) => candidate.start > placeholder.start)?.start ?? transformed.length;
|
|
3509
|
+
const literalAfter = transformed.slice(placeholder.end, nextPlaceholderStart);
|
|
3510
|
+
const nextLiteralIndex = literalAfter ? source.indexOf(literalAfter, sourceCursor) : nextPlaceholderStart >= transformed.length ? source.length : sourceCursor;
|
|
3511
|
+
if (nextLiteralIndex < sourceCursor) {
|
|
3512
|
+
return {};
|
|
3513
|
+
}
|
|
3514
|
+
const originalValue = source.slice(sourceCursor, nextLiteralIndex);
|
|
3515
|
+
if (originalValue.length > 0 && typeof mapping[placeholder.token] !== "string") {
|
|
3516
|
+
mapping[placeholder.token] = originalValue;
|
|
3517
|
+
}
|
|
3518
|
+
sourceCursor = nextLiteralIndex;
|
|
3519
|
+
transformedCursor = placeholder.end;
|
|
3520
|
+
}
|
|
3521
|
+
return mapping;
|
|
3522
|
+
}
|
|
3523
|
+
function mergePiiMappings(primary, fallback) {
|
|
3524
|
+
const merged = { ...primary };
|
|
3525
|
+
for (const [placeholder, value] of Object.entries(fallback)) {
|
|
3526
|
+
if (typeof merged[placeholder] !== "string" && typeof value === "string") {
|
|
3527
|
+
merged[placeholder] = value;
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
3530
|
+
return merged;
|
|
3531
|
+
}
|
|
3532
|
+
function textContainsMappingPlaceholder(text, mapping) {
|
|
3533
|
+
if (!text || !mapping) {
|
|
3534
|
+
return false;
|
|
3535
|
+
}
|
|
3536
|
+
return Object.keys(mapping).some((placeholder) => placeholder.length > 0 && text.includes(placeholder));
|
|
3537
|
+
}
|
|
2561
3538
|
var SecurityBlockError = class extends Error {
|
|
2562
3539
|
constructor(reason = "guard_denied") {
|
|
2563
3540
|
super(`AgentID: Security Blocked (${reason})`);
|
|
@@ -2582,6 +3559,7 @@ var AgentID = class {
|
|
|
2582
3559
|
this.apiKey = resolveConfiguredApiKey(config.apiKey);
|
|
2583
3560
|
this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
|
|
2584
3561
|
this.configuredPiiMasking = typeof config.piiMasking === "boolean" ? config.piiMasking : null;
|
|
3562
|
+
this.configuredSecretMasking = typeof config.secretMasking === "boolean" ? config.secretMasking : null;
|
|
2585
3563
|
this.checkInjection = config.checkInjection !== false;
|
|
2586
3564
|
this.clientFastFail = config.clientFastFail === true || config.client_fast_fail === true;
|
|
2587
3565
|
this.aiScanEnabled = config.aiScanEnabled !== false;
|
|
@@ -2603,6 +3581,9 @@ var AgentID = class {
|
|
|
2603
3581
|
get piiMasking() {
|
|
2604
3582
|
return this.configuredPiiMasking ?? void 0;
|
|
2605
3583
|
}
|
|
3584
|
+
get secretMasking() {
|
|
3585
|
+
return this.configuredSecretMasking ?? void 0;
|
|
3586
|
+
}
|
|
2606
3587
|
resolveEffectivePiiMasking(config) {
|
|
2607
3588
|
if (config?.enable_sdk_pii_masking === true) {
|
|
2608
3589
|
return true;
|
|
@@ -2612,12 +3593,24 @@ var AgentID = class {
|
|
|
2612
3593
|
}
|
|
2613
3594
|
return false;
|
|
2614
3595
|
}
|
|
3596
|
+
resolveEffectiveSecretMasking(config) {
|
|
3597
|
+
if (config?.enable_sdk_secret_masking === true || config?.enable_sdk_pii_masking === true) {
|
|
3598
|
+
return true;
|
|
3599
|
+
}
|
|
3600
|
+
if (this.configuredSecretMasking !== null) {
|
|
3601
|
+
return this.configuredSecretMasking;
|
|
3602
|
+
}
|
|
3603
|
+
return false;
|
|
3604
|
+
}
|
|
2615
3605
|
getEffectivePiiMasking(options) {
|
|
2616
3606
|
return this.resolveEffectivePiiMasking(this.getCachedCapabilityConfig(options));
|
|
2617
3607
|
}
|
|
2618
3608
|
getEffectivePiiMaskingForConfig(capabilityConfig) {
|
|
2619
3609
|
return this.resolveEffectivePiiMasking(capabilityConfig);
|
|
2620
3610
|
}
|
|
3611
|
+
getEffectiveSecretMaskingForConfig(capabilityConfig) {
|
|
3612
|
+
return this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3613
|
+
}
|
|
2621
3614
|
buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig) {
|
|
2622
3615
|
return {
|
|
2623
3616
|
capabilities: {
|
|
@@ -2625,6 +3618,9 @@ var AgentID = class {
|
|
|
2625
3618
|
pii_masking_enabled: this.resolveEffectivePiiMasking(
|
|
2626
3619
|
capabilityConfig ?? this.getCachedCapabilityConfig()
|
|
2627
3620
|
),
|
|
3621
|
+
secret_masking_enabled: this.resolveEffectiveSecretMasking(
|
|
3622
|
+
capabilityConfig ?? this.getCachedCapabilityConfig()
|
|
3623
|
+
),
|
|
2628
3624
|
framework
|
|
2629
3625
|
}
|
|
2630
3626
|
};
|
|
@@ -2717,6 +3713,23 @@ var AgentID = class {
|
|
|
2717
3713
|
const config = await this.getCapabilityConfig(false, options);
|
|
2718
3714
|
return config.strict_security_mode || config.failure_mode === "fail_close";
|
|
2719
3715
|
}
|
|
3716
|
+
buildFailOpenGuardVerdict(reason, input, options) {
|
|
3717
|
+
const capabilityConfig = this.getCachedCapabilityConfig(options);
|
|
3718
|
+
const shouldMaskPii = capabilityConfig.block_pii_leakage || this.resolveEffectivePiiMasking(capabilityConfig);
|
|
3719
|
+
const shouldMaskSecrets = capabilityConfig.block_secret_leakage === true || this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3720
|
+
const response = { allowed: true, reason };
|
|
3721
|
+
if (input && (shouldMaskPii || shouldMaskSecrets)) {
|
|
3722
|
+
const masked = this.pii.anonymize(input, {
|
|
3723
|
+
pii: shouldMaskPii,
|
|
3724
|
+
secrets: shouldMaskSecrets
|
|
3725
|
+
});
|
|
3726
|
+
if (masked.maskedText !== input) {
|
|
3727
|
+
response.transformed_input = masked.maskedText;
|
|
3728
|
+
response.detected_pii = Object.keys(masked.mapping).length > 0;
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
return response;
|
|
3732
|
+
}
|
|
2720
3733
|
maybeRaiseStrictIngestDependencyError(params) {
|
|
2721
3734
|
if (params.result.ok) {
|
|
2722
3735
|
return;
|
|
@@ -2764,10 +3777,13 @@ var AgentID = class {
|
|
|
2764
3777
|
systemId: params.systemId,
|
|
2765
3778
|
eventId: params.clientEventId,
|
|
2766
3779
|
clientEventId: params.clientEventId,
|
|
2767
|
-
telemetryMetadata:
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
3780
|
+
telemetryMetadata: mergeTelemetryContexts(
|
|
3781
|
+
params.telemetryMetadata,
|
|
3782
|
+
buildSdkTimingMetadata({
|
|
3783
|
+
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
3784
|
+
sdkConfigVersion: params.capabilityConfig.version
|
|
3785
|
+
})
|
|
3786
|
+
)
|
|
2771
3787
|
});
|
|
2772
3788
|
}
|
|
2773
3789
|
try {
|
|
@@ -2784,7 +3800,8 @@ var AgentID = class {
|
|
|
2784
3800
|
actionTaken: event.actionTaken,
|
|
2785
3801
|
apiKey: params.apiKey,
|
|
2786
3802
|
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
2787
|
-
sdkLocalScanMs
|
|
3803
|
+
sdkLocalScanMs,
|
|
3804
|
+
telemetryMetadata: params.telemetryMetadata
|
|
2788
3805
|
});
|
|
2789
3806
|
}
|
|
2790
3807
|
return {
|
|
@@ -2799,7 +3816,8 @@ var AgentID = class {
|
|
|
2799
3816
|
actionTaken: error.actionTaken,
|
|
2800
3817
|
apiKey: params.apiKey,
|
|
2801
3818
|
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
2802
|
-
sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
|
|
3819
|
+
sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt),
|
|
3820
|
+
telemetryMetadata: params.telemetryMetadata
|
|
2803
3821
|
});
|
|
2804
3822
|
}
|
|
2805
3823
|
throw error;
|
|
@@ -2813,7 +3831,7 @@ var AgentID = class {
|
|
|
2813
3831
|
);
|
|
2814
3832
|
let sanitizedInput = params.input;
|
|
2815
3833
|
let sdkLocalScanMs = 0;
|
|
2816
|
-
if (this.configuredPiiMasking === null) {
|
|
3834
|
+
if (this.configuredPiiMasking === null || this.configuredSecretMasking === null) {
|
|
2817
3835
|
const refreshed = await this.refreshCapabilityConfigBeforeClientControl({
|
|
2818
3836
|
capabilityConfig,
|
|
2819
3837
|
sdkConfigFetchMs,
|
|
@@ -2824,8 +3842,12 @@ var AgentID = class {
|
|
|
2824
3842
|
}
|
|
2825
3843
|
if (!this.clientFastFail) {
|
|
2826
3844
|
const effectivePiiMasking2 = this.resolveEffectivePiiMasking(capabilityConfig);
|
|
2827
|
-
|
|
2828
|
-
|
|
3845
|
+
const effectiveSecretMasking2 = this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3846
|
+
if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2 || !capabilityConfig.block_secret_leakage && effectiveSecretMasking2) {
|
|
3847
|
+
const masked = this.pii.anonymize(sanitizedInput, {
|
|
3848
|
+
pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking2,
|
|
3849
|
+
secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking2
|
|
3850
|
+
});
|
|
2829
3851
|
return {
|
|
2830
3852
|
sanitizedInput: masked.maskedText,
|
|
2831
3853
|
capabilityConfig,
|
|
@@ -2857,13 +3879,18 @@ var AgentID = class {
|
|
|
2857
3879
|
apiKey: effectiveApiKey,
|
|
2858
3880
|
clientEventId: params.clientEventId,
|
|
2859
3881
|
sdkConfigFetchMs,
|
|
3882
|
+
telemetryMetadata: params.telemetryMetadata,
|
|
2860
3883
|
runPromptInjectionCheck: !params.skipInjectionScan
|
|
2861
3884
|
});
|
|
2862
3885
|
sanitizedInput = enforced.sanitizedInput;
|
|
2863
3886
|
sdkLocalScanMs = enforced.sdkLocalScanMs;
|
|
2864
3887
|
const effectivePiiMasking = this.resolveEffectivePiiMasking(capabilityConfig);
|
|
2865
|
-
|
|
2866
|
-
|
|
3888
|
+
const effectiveSecretMasking = this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3889
|
+
if (!capabilityConfig.block_pii_leakage && effectivePiiMasking || !capabilityConfig.block_secret_leakage && effectiveSecretMasking) {
|
|
3890
|
+
const masked = this.pii.anonymize(sanitizedInput, {
|
|
3891
|
+
pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking,
|
|
3892
|
+
secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking
|
|
3893
|
+
});
|
|
2867
3894
|
return {
|
|
2868
3895
|
sanitizedInput: masked.maskedText,
|
|
2869
3896
|
capabilityConfig,
|
|
@@ -2899,6 +3926,7 @@ var AgentID = class {
|
|
|
2899
3926
|
apiKey: effectiveApiKey,
|
|
2900
3927
|
clientEventId: params.clientEventId,
|
|
2901
3928
|
sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
|
|
3929
|
+
telemetryMetadata: params.telemetryMetadata,
|
|
2902
3930
|
runPromptInjectionCheck: true
|
|
2903
3931
|
});
|
|
2904
3932
|
return {
|
|
@@ -2942,12 +3970,43 @@ var AgentID = class {
|
|
|
2942
3970
|
})
|
|
2943
3971
|
});
|
|
2944
3972
|
}
|
|
2945
|
-
withMaskedOpenAIRequest(req, maskedText) {
|
|
3973
|
+
withMaskedOpenAIRequest(req, maskedText, options) {
|
|
2946
3974
|
const messages = Array.isArray(req?.messages) ? req.messages : null;
|
|
2947
3975
|
if (!messages) {
|
|
2948
3976
|
return req;
|
|
2949
3977
|
}
|
|
2950
|
-
const newMessages =
|
|
3978
|
+
const newMessages = messages.map((message2) => {
|
|
3979
|
+
if (!message2 || typeof message2 !== "object") {
|
|
3980
|
+
return message2;
|
|
3981
|
+
}
|
|
3982
|
+
const typedMessage = message2;
|
|
3983
|
+
const currentContent2 = typedMessage.content;
|
|
3984
|
+
if (typeof currentContent2 === "string") {
|
|
3985
|
+
return {
|
|
3986
|
+
...typedMessage,
|
|
3987
|
+
content: this.pii.anonymize(currentContent2, options).maskedText
|
|
3988
|
+
};
|
|
3989
|
+
}
|
|
3990
|
+
if (Array.isArray(currentContent2)) {
|
|
3991
|
+
return {
|
|
3992
|
+
...typedMessage,
|
|
3993
|
+
content: currentContent2.map((part) => {
|
|
3994
|
+
if (!part || typeof part !== "object") {
|
|
3995
|
+
return part;
|
|
3996
|
+
}
|
|
3997
|
+
const typedPart = part;
|
|
3998
|
+
if (typeof typedPart.text !== "string") {
|
|
3999
|
+
return part;
|
|
4000
|
+
}
|
|
4001
|
+
return {
|
|
4002
|
+
...typedPart,
|
|
4003
|
+
text: this.pii.anonymize(typedPart.text, options).maskedText
|
|
4004
|
+
};
|
|
4005
|
+
})
|
|
4006
|
+
};
|
|
4007
|
+
}
|
|
4008
|
+
return message2;
|
|
4009
|
+
});
|
|
2951
4010
|
let lastUserIdx = null;
|
|
2952
4011
|
for (let i = 0; i < newMessages.length; i += 1) {
|
|
2953
4012
|
const msg = newMessages[i];
|
|
@@ -2962,9 +4021,30 @@ var AgentID = class {
|
|
|
2962
4021
|
if (!message || typeof message !== "object") {
|
|
2963
4022
|
return req;
|
|
2964
4023
|
}
|
|
4024
|
+
const currentContent = message.content;
|
|
4025
|
+
let nextContent = maskedText;
|
|
4026
|
+
if (Array.isArray(currentContent)) {
|
|
4027
|
+
let textReplaced = false;
|
|
4028
|
+
const preservedParts = [];
|
|
4029
|
+
for (const part of currentContent) {
|
|
4030
|
+
if (!part || typeof part !== "object" || part.type !== "text" || typeof part.text !== "string") {
|
|
4031
|
+
preservedParts.push(part);
|
|
4032
|
+
continue;
|
|
4033
|
+
}
|
|
4034
|
+
if (textReplaced) {
|
|
4035
|
+
continue;
|
|
4036
|
+
}
|
|
4037
|
+
textReplaced = true;
|
|
4038
|
+
preservedParts.push({
|
|
4039
|
+
...part,
|
|
4040
|
+
text: maskedText
|
|
4041
|
+
});
|
|
4042
|
+
}
|
|
4043
|
+
nextContent = textReplaced ? preservedParts : [{ type: "text", text: maskedText }, ...currentContent];
|
|
4044
|
+
}
|
|
2965
4045
|
newMessages[lastUserIdx] = {
|
|
2966
4046
|
...message,
|
|
2967
|
-
content:
|
|
4047
|
+
content: nextContent
|
|
2968
4048
|
};
|
|
2969
4049
|
if (!req || typeof req !== "object") {
|
|
2970
4050
|
return req;
|
|
@@ -2983,6 +4063,7 @@ var AgentID = class {
|
|
|
2983
4063
|
event_type: "security_policy_violation",
|
|
2984
4064
|
severity: "high",
|
|
2985
4065
|
metadata: {
|
|
4066
|
+
...params.telemetryMetadata ?? {},
|
|
2986
4067
|
event_type: "security_policy_violation",
|
|
2987
4068
|
severity: "high",
|
|
2988
4069
|
system_id: params.systemId,
|
|
@@ -3010,6 +4091,7 @@ var AgentID = class {
|
|
|
3010
4091
|
event_type: "security_alert",
|
|
3011
4092
|
severity: "warning",
|
|
3012
4093
|
metadata: {
|
|
4094
|
+
...params.guardParams.metadata ?? {},
|
|
3013
4095
|
source: "guard",
|
|
3014
4096
|
status: params.status,
|
|
3015
4097
|
guard_reason: params.reason,
|
|
@@ -3138,7 +4220,13 @@ var AgentID = class {
|
|
|
3138
4220
|
guardParams: params,
|
|
3139
4221
|
apiKey: effectiveApiKey
|
|
3140
4222
|
});
|
|
3141
|
-
return withGuardLatency(
|
|
4223
|
+
return withGuardLatency(
|
|
4224
|
+
this.buildFailOpenGuardVerdict(
|
|
4225
|
+
"system_failure_fail_open",
|
|
4226
|
+
params.input,
|
|
4227
|
+
{ apiKey: effectiveApiKey }
|
|
4228
|
+
)
|
|
4229
|
+
);
|
|
3142
4230
|
}
|
|
3143
4231
|
this.cacheGuardVerdict(guardCacheKey, verdict);
|
|
3144
4232
|
return withGuardLatency(verdict);
|
|
@@ -3173,7 +4261,11 @@ var AgentID = class {
|
|
|
3173
4261
|
if (effectiveStrictMode) {
|
|
3174
4262
|
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
3175
4263
|
}
|
|
3176
|
-
return withGuardLatency(
|
|
4264
|
+
return withGuardLatency(
|
|
4265
|
+
this.buildFailOpenGuardVerdict("timeout_fallback", params.input, {
|
|
4266
|
+
apiKey: effectiveApiKey
|
|
4267
|
+
})
|
|
4268
|
+
);
|
|
3177
4269
|
}
|
|
3178
4270
|
console.warn(
|
|
3179
4271
|
effectiveStrictMode ? "[AgentID] Guard check failed (Strict mode active):" : "[AgentID] Guard check failed (Fail-Open active):",
|
|
@@ -3188,7 +4280,11 @@ var AgentID = class {
|
|
|
3188
4280
|
if (effectiveStrictMode) {
|
|
3189
4281
|
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
3190
4282
|
}
|
|
3191
|
-
return withGuardLatency(
|
|
4283
|
+
return withGuardLatency(
|
|
4284
|
+
this.buildFailOpenGuardVerdict("guard_unreachable", params.input, {
|
|
4285
|
+
apiKey: effectiveApiKey
|
|
4286
|
+
})
|
|
4287
|
+
);
|
|
3192
4288
|
} finally {
|
|
3193
4289
|
clearTimeout(timeoutId);
|
|
3194
4290
|
}
|
|
@@ -3197,13 +4293,23 @@ var AgentID = class {
|
|
|
3197
4293
|
if (effectiveStrictMode) {
|
|
3198
4294
|
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
3199
4295
|
}
|
|
3200
|
-
return withGuardLatency(
|
|
4296
|
+
return withGuardLatency(
|
|
4297
|
+
this.buildFailOpenGuardVerdict("timeout_fallback", params.input, {
|
|
4298
|
+
apiKey: effectiveApiKey
|
|
4299
|
+
})
|
|
4300
|
+
);
|
|
3201
4301
|
}
|
|
3202
4302
|
if (typeof lastStatusCode === "number" && lastStatusCode >= 500) {
|
|
3203
4303
|
if (effectiveStrictMode) {
|
|
3204
4304
|
return withGuardLatency({ allowed: false, reason: "server_error" });
|
|
3205
4305
|
}
|
|
3206
|
-
return withGuardLatency(
|
|
4306
|
+
return withGuardLatency(
|
|
4307
|
+
this.buildFailOpenGuardVerdict(
|
|
4308
|
+
"system_failure_fail_open",
|
|
4309
|
+
params.input,
|
|
4310
|
+
{ apiKey: effectiveApiKey }
|
|
4311
|
+
)
|
|
4312
|
+
);
|
|
3207
4313
|
}
|
|
3208
4314
|
console.warn(
|
|
3209
4315
|
effectiveStrictMode ? "[AgentID] Guard check failed (Strict mode active):" : "[AgentID] Guard check failed (Fail-Open active):",
|
|
@@ -3212,7 +4318,11 @@ var AgentID = class {
|
|
|
3212
4318
|
if (effectiveStrictMode) {
|
|
3213
4319
|
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
3214
4320
|
}
|
|
3215
|
-
return withGuardLatency(
|
|
4321
|
+
return withGuardLatency(
|
|
4322
|
+
this.buildFailOpenGuardVerdict("guard_unreachable", params.input, {
|
|
4323
|
+
apiKey: effectiveApiKey
|
|
4324
|
+
})
|
|
4325
|
+
);
|
|
3216
4326
|
}
|
|
3217
4327
|
async sendIngest(params, options, internal) {
|
|
3218
4328
|
const ingestStartedAt = Date.now();
|
|
@@ -3452,21 +4562,29 @@ var AgentID = class {
|
|
|
3452
4562
|
wrapCompletion(completion, options) {
|
|
3453
4563
|
if (typeof completion === "string") {
|
|
3454
4564
|
const masked = this.pii.anonymize(completion);
|
|
4565
|
+
const placeholderOutputMasked = textContainsMappingPlaceholder(
|
|
4566
|
+
completion,
|
|
4567
|
+
options?.piiMapping
|
|
4568
|
+
);
|
|
3455
4569
|
return {
|
|
3456
4570
|
mode: "static",
|
|
3457
4571
|
rawOutput: completion,
|
|
3458
4572
|
transformedOutput: masked.maskedText,
|
|
3459
|
-
outputMasked: masked.maskedText !== completion
|
|
4573
|
+
outputMasked: masked.maskedText !== completion || placeholderOutputMasked
|
|
3460
4574
|
};
|
|
3461
4575
|
}
|
|
3462
4576
|
if (!isAsyncIterable(completion)) {
|
|
3463
4577
|
const asText = String(completion ?? "");
|
|
3464
4578
|
const masked = this.pii.anonymize(asText);
|
|
4579
|
+
const placeholderOutputMasked = textContainsMappingPlaceholder(
|
|
4580
|
+
asText,
|
|
4581
|
+
options?.piiMapping
|
|
4582
|
+
);
|
|
3465
4583
|
return {
|
|
3466
4584
|
mode: "static",
|
|
3467
4585
|
rawOutput: asText,
|
|
3468
4586
|
transformedOutput: masked.maskedText,
|
|
3469
|
-
outputMasked: masked.maskedText !== asText
|
|
4587
|
+
outputMasked: masked.maskedText !== asText || placeholderOutputMasked
|
|
3470
4588
|
};
|
|
3471
4589
|
}
|
|
3472
4590
|
const source = completion;
|
|
@@ -3476,8 +4594,10 @@ var AgentID = class {
|
|
|
3476
4594
|
const isOpenAIStreamFinishChunk = this.isOpenAIStreamFinishChunk.bind(this);
|
|
3477
4595
|
const rewriteOpenAIStreamChunkForClient = this.rewriteOpenAIStreamChunkForClient.bind(this);
|
|
3478
4596
|
const createSyntheticOpenAIStreamChunk = this.createSyntheticOpenAIStreamChunk.bind(this);
|
|
4597
|
+
const setOpenAIStreamChunkText = this.setOpenAIStreamChunkText.bind(this);
|
|
3479
4598
|
const piiManager = this.pii;
|
|
3480
4599
|
const streamRewriter = options?.deanonymizeForClient === true && options.piiMapping ? createStreamingPlaceholderRewriter(piiManager, options.piiMapping) : null;
|
|
4600
|
+
const maskForClient = options?.maskForClient === true && streamRewriter === null;
|
|
3481
4601
|
let lastUsage;
|
|
3482
4602
|
let resolveDone = null;
|
|
3483
4603
|
let rejectDone = null;
|
|
@@ -3490,12 +4610,17 @@ var AgentID = class {
|
|
|
3490
4610
|
try {
|
|
3491
4611
|
let finishChunkFlushed = false;
|
|
3492
4612
|
let lastChunkTemplate;
|
|
4613
|
+
let clientRawText = "";
|
|
4614
|
+
let clientMaskFlushed = false;
|
|
3493
4615
|
for await (const chunk of source) {
|
|
3494
4616
|
const chunkText = extractStreamChunkText(chunk);
|
|
3495
|
-
const isFinishChunk = streamRewriter ? isOpenAIStreamFinishChunk(chunk) : false;
|
|
4617
|
+
const isFinishChunk = streamRewriter || maskForClient ? isOpenAIStreamFinishChunk(chunk) : false;
|
|
3496
4618
|
if (chunkText) {
|
|
3497
4619
|
await collector.push(chunkText);
|
|
3498
4620
|
lastChunkTemplate = chunk;
|
|
4621
|
+
if (maskForClient) {
|
|
4622
|
+
clientRawText += chunkText;
|
|
4623
|
+
}
|
|
3499
4624
|
}
|
|
3500
4625
|
const chunkUsage = extractStreamChunkUsage(chunk);
|
|
3501
4626
|
if (chunkUsage) {
|
|
@@ -3515,6 +4640,28 @@ var AgentID = class {
|
|
|
3515
4640
|
}
|
|
3516
4641
|
continue;
|
|
3517
4642
|
}
|
|
4643
|
+
if (maskForClient) {
|
|
4644
|
+
if (isFinishChunk) {
|
|
4645
|
+
const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
|
|
4646
|
+
clientMaskFlushed = true;
|
|
4647
|
+
if (maskedClientText.length > 0) {
|
|
4648
|
+
yield createSyntheticOpenAIStreamChunk(
|
|
4649
|
+
maskedClientText,
|
|
4650
|
+
lastChunkTemplate ?? chunk
|
|
4651
|
+
);
|
|
4652
|
+
}
|
|
4653
|
+
if (chunkText) {
|
|
4654
|
+
setOpenAIStreamChunkText(chunk, "");
|
|
4655
|
+
}
|
|
4656
|
+
yield chunk;
|
|
4657
|
+
finishChunkFlushed = true;
|
|
4658
|
+
continue;
|
|
4659
|
+
}
|
|
4660
|
+
if (!chunkText) {
|
|
4661
|
+
yield chunk;
|
|
4662
|
+
}
|
|
4663
|
+
continue;
|
|
4664
|
+
}
|
|
3518
4665
|
yield chunk;
|
|
3519
4666
|
}
|
|
3520
4667
|
if (streamRewriter && !finishChunkFlushed) {
|
|
@@ -3526,14 +4673,27 @@ var AgentID = class {
|
|
|
3526
4673
|
);
|
|
3527
4674
|
}
|
|
3528
4675
|
}
|
|
4676
|
+
if (maskForClient && !clientMaskFlushed) {
|
|
4677
|
+
const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
|
|
4678
|
+
if (maskedClientText.length > 0) {
|
|
4679
|
+
yield createSyntheticOpenAIStreamChunk(
|
|
4680
|
+
maskedClientText,
|
|
4681
|
+
lastChunkTemplate
|
|
4682
|
+
);
|
|
4683
|
+
}
|
|
4684
|
+
}
|
|
3529
4685
|
await collector.close();
|
|
3530
4686
|
const rawOutput = await collector.result;
|
|
3531
4687
|
const masked = piiManager.anonymize(rawOutput);
|
|
4688
|
+
const placeholderOutputMasked = textContainsMappingPlaceholder(
|
|
4689
|
+
rawOutput,
|
|
4690
|
+
options?.piiMapping
|
|
4691
|
+
);
|
|
3532
4692
|
resolveDone?.({
|
|
3533
4693
|
mode: "static",
|
|
3534
4694
|
rawOutput,
|
|
3535
4695
|
transformedOutput: masked.maskedText,
|
|
3536
|
-
outputMasked: masked.maskedText !== rawOutput,
|
|
4696
|
+
outputMasked: masked.maskedText !== rawOutput || placeholderOutputMasked,
|
|
3537
4697
|
usage: lastUsage
|
|
3538
4698
|
});
|
|
3539
4699
|
} catch (error) {
|
|
@@ -3568,6 +4728,37 @@ var AgentID = class {
|
|
|
3568
4728
|
);
|
|
3569
4729
|
}
|
|
3570
4730
|
}
|
|
4731
|
+
buildOperationLogParams(params) {
|
|
4732
|
+
return createAgentIdOperationLog(params);
|
|
4733
|
+
}
|
|
4734
|
+
async logOperation(params, options) {
|
|
4735
|
+
return this.log(this.buildOperationLogParams(params), options);
|
|
4736
|
+
}
|
|
4737
|
+
async logPromptPreflightStep(params, options) {
|
|
4738
|
+
const telemetry = buildPromptPreflightTelemetry(params);
|
|
4739
|
+
const summary = firstNonEmptyString(telemetry?.step_summary, telemetry?.stepSummary) ?? summarizePromptPreflightResult({
|
|
4740
|
+
verdict: params.verdict,
|
|
4741
|
+
localFallbackApplied: params.local_fallback_applied,
|
|
4742
|
+
localFallbackReason: params.local_fallback_reason
|
|
4743
|
+
});
|
|
4744
|
+
await this.logOperation(
|
|
4745
|
+
{
|
|
4746
|
+
system_id: params.system_id,
|
|
4747
|
+
user_id: params.user_id,
|
|
4748
|
+
request_identity: params.request_identity,
|
|
4749
|
+
input: params.input,
|
|
4750
|
+
output: summary,
|
|
4751
|
+
model: "not_applicable",
|
|
4752
|
+
latency: params.guard_latency_ms ?? void 0,
|
|
4753
|
+
telemetry,
|
|
4754
|
+
client_capabilities: params.client_capabilities
|
|
4755
|
+
},
|
|
4756
|
+
options
|
|
4757
|
+
);
|
|
4758
|
+
}
|
|
4759
|
+
operation(params, options) {
|
|
4760
|
+
return this.logOperation(params, options);
|
|
4761
|
+
}
|
|
3571
4762
|
/**
|
|
3572
4763
|
* Analytics alias for telemetry logging.
|
|
3573
4764
|
*/
|
|
@@ -3612,49 +4803,62 @@ var AgentID = class {
|
|
|
3612
4803
|
if (typeof originalCreate !== "function") return originalCreate;
|
|
3613
4804
|
return async (...args) => {
|
|
3614
4805
|
const normalizedCreateArgs = normalizeOpenAICreateArgs(args);
|
|
3615
|
-
const
|
|
4806
|
+
const rawReq = normalizedCreateArgs?.[0] ?? {};
|
|
4807
|
+
const requestTelemetry = extractRequestTelemetryContext(rawReq);
|
|
4808
|
+
const telemetryMetadata = mergeTelemetryContexts(
|
|
4809
|
+
options.telemetry,
|
|
4810
|
+
requestTelemetry
|
|
4811
|
+
);
|
|
4812
|
+
const providerReq = stripRequestTelemetryContext(rawReq);
|
|
3616
4813
|
const pipelineStartedAt = Date.now();
|
|
3617
|
-
const requestLevelApiKey = options.resolveApiKey?.(
|
|
4814
|
+
const requestLevelApiKey = options.resolveApiKey?.(rawReq) ?? options.apiKey ?? options.api_key;
|
|
3618
4815
|
const effectiveApiKey = this.resolveApiKey(requestLevelApiKey);
|
|
3619
4816
|
const requestOptions = { apiKey: effectiveApiKey };
|
|
3620
|
-
const clientEventId = this.resolveClientEventId(
|
|
4817
|
+
const clientEventId = this.resolveClientEventId(rawReq);
|
|
3621
4818
|
const effectiveStrictMode = await this.resolveEffectiveStrictMode(requestOptions);
|
|
3622
|
-
const stream = adapter.isStream(
|
|
4819
|
+
const stream = adapter.isStream(providerReq);
|
|
3623
4820
|
let capabilityConfig = this.getCachedCapabilityConfig(requestOptions);
|
|
3624
|
-
const userText = adapter.extractInput(
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
let
|
|
4821
|
+
const userText = adapter.extractInput(providerReq);
|
|
4822
|
+
const requestAttachments = adapter.extractAttachments(providerReq);
|
|
4823
|
+
const hasGuardContent = userText !== null || requestAttachments.length > 0;
|
|
4824
|
+
let maskedText = userText ?? "";
|
|
4825
|
+
let maskedReq = providerReq;
|
|
4826
|
+
let createArgs = providerReq === rawReq ? normalizedCreateArgs : [{ ...providerReq }, ...normalizedCreateArgs.slice(1)];
|
|
3628
4827
|
let mapping = {};
|
|
3629
|
-
let shouldDeanonymize = false;
|
|
3630
4828
|
let sdkConfigFetchMs = 0;
|
|
3631
4829
|
let sdkLocalScanMs = 0;
|
|
3632
|
-
|
|
4830
|
+
let providerMaskingOptions;
|
|
4831
|
+
if (hasGuardContent) {
|
|
3633
4832
|
const prepared = await this.prepareInputForDispatch({
|
|
3634
|
-
input: userText,
|
|
4833
|
+
input: userText ?? "",
|
|
3635
4834
|
systemId,
|
|
3636
4835
|
stream,
|
|
3637
|
-
clientEventId
|
|
4836
|
+
clientEventId,
|
|
4837
|
+
telemetryMetadata
|
|
3638
4838
|
}, requestOptions);
|
|
3639
4839
|
capabilityConfig = prepared.capabilityConfig;
|
|
4840
|
+
providerMaskingOptions = {
|
|
4841
|
+
pii: !capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig),
|
|
4842
|
+
secrets: !capabilityConfig.block_secret_leakage && this.resolveEffectiveSecretMasking(capabilityConfig)
|
|
4843
|
+
};
|
|
3640
4844
|
maskedText = prepared.sanitizedInput;
|
|
3641
4845
|
mapping = prepared.piiMapping ?? {};
|
|
3642
|
-
shouldDeanonymize = prepared.shouldDeanonymize === true;
|
|
3643
4846
|
sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
|
|
3644
4847
|
sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
|
|
3645
|
-
if (maskedText !== userText) {
|
|
4848
|
+
if (maskedText !== (userText ?? "")) {
|
|
3646
4849
|
maskedReq = this.withMaskedOpenAIRequest(
|
|
3647
|
-
|
|
3648
|
-
maskedText
|
|
4850
|
+
providerReq,
|
|
4851
|
+
maskedText,
|
|
4852
|
+
providerMaskingOptions
|
|
3649
4853
|
);
|
|
3650
|
-
const nextCreateArgs = [...
|
|
4854
|
+
const nextCreateArgs = [...createArgs];
|
|
3651
4855
|
nextCreateArgs[0] = maskedReq;
|
|
3652
4856
|
createArgs = nextCreateArgs;
|
|
3653
4857
|
}
|
|
3654
4858
|
}
|
|
3655
|
-
if (!
|
|
4859
|
+
if (!hasGuardContent) {
|
|
3656
4860
|
throw new Error(
|
|
3657
|
-
"AgentID: No user message found. Security guard requires
|
|
4861
|
+
"AgentID: No user message or supported inline attachment found. Security guard requires prompt content."
|
|
3658
4862
|
);
|
|
3659
4863
|
}
|
|
3660
4864
|
const verdict = await this.guard({
|
|
@@ -3665,6 +4869,8 @@ var AgentID = class {
|
|
|
3665
4869
|
client_event_id: clientEventId,
|
|
3666
4870
|
expected_languages: expectedLanguages,
|
|
3667
4871
|
request_identity: options.request_identity,
|
|
4872
|
+
metadata: telemetryMetadata,
|
|
4873
|
+
attachments: requestAttachments,
|
|
3668
4874
|
client_capabilities: this.buildClientCapabilities(
|
|
3669
4875
|
"openai",
|
|
3670
4876
|
false,
|
|
@@ -3686,22 +4892,44 @@ var AgentID = class {
|
|
|
3686
4892
|
apiKey: effectiveApiKey,
|
|
3687
4893
|
clientEventId,
|
|
3688
4894
|
sdkConfigFetchMs,
|
|
4895
|
+
telemetryMetadata,
|
|
3689
4896
|
runPromptInjectionCheck: true
|
|
3690
4897
|
});
|
|
3691
4898
|
maskedText = fallback.sanitizedInput;
|
|
3692
4899
|
sdkLocalScanMs = fallback.sdkLocalScanMs;
|
|
3693
4900
|
}
|
|
3694
4901
|
} else {
|
|
4902
|
+
await this.logPromptPreflightStep(
|
|
4903
|
+
{
|
|
4904
|
+
system_id: systemId,
|
|
4905
|
+
user_id: options.user_id,
|
|
4906
|
+
request_identity: options.request_identity,
|
|
4907
|
+
input: maskedText,
|
|
4908
|
+
telemetry: telemetryMetadata,
|
|
4909
|
+
verdict,
|
|
4910
|
+
guard_event_id: verdict.guard_event_id ?? null,
|
|
4911
|
+
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),
|
|
4912
|
+
preflight_for_client_event_id: typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId,
|
|
4913
|
+
client_capabilities: this.buildClientCapabilities(
|
|
4914
|
+
"openai",
|
|
4915
|
+
false,
|
|
4916
|
+
capabilityConfig
|
|
4917
|
+
),
|
|
4918
|
+
runtime_surface: "openai_sdk_guard"
|
|
4919
|
+
},
|
|
4920
|
+
requestOptions
|
|
4921
|
+
);
|
|
3695
4922
|
throw new SecurityBlockError(verdict.reason ?? "guard_denied");
|
|
3696
4923
|
}
|
|
3697
4924
|
}
|
|
3698
|
-
const currentRequestInput = adapter.extractInput(maskedReq);
|
|
3699
|
-
if (maskedText !== currentRequestInput) {
|
|
4925
|
+
const currentRequestInput = adapter.extractInput(maskedReq) ?? "";
|
|
4926
|
+
if (maskedText !== currentRequestInput || providerMaskingOptions?.pii === true || providerMaskingOptions?.secrets === true) {
|
|
3700
4927
|
maskedReq = this.withMaskedOpenAIRequest(
|
|
3701
|
-
|
|
3702
|
-
maskedText
|
|
4928
|
+
providerReq,
|
|
4929
|
+
maskedText,
|
|
4930
|
+
providerMaskingOptions
|
|
3703
4931
|
);
|
|
3704
|
-
const nextCreateArgs = [...
|
|
4932
|
+
const nextCreateArgs = [...createArgs];
|
|
3705
4933
|
nextCreateArgs[0] = maskedReq;
|
|
3706
4934
|
createArgs = nextCreateArgs;
|
|
3707
4935
|
}
|
|
@@ -3712,15 +4940,45 @@ var AgentID = class {
|
|
|
3712
4940
|
const isShadowMode = verdict.shadow_mode === true;
|
|
3713
4941
|
const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
|
|
3714
4942
|
if (transformedInput !== maskedText) {
|
|
4943
|
+
const serverDerivedMapping = derivePlaceholderMappingFromTransform(
|
|
4944
|
+
maskedText,
|
|
4945
|
+
transformedInput
|
|
4946
|
+
);
|
|
4947
|
+
if (Object.keys(serverDerivedMapping).length > 0) {
|
|
4948
|
+
mapping = mergePiiMappings(mapping, serverDerivedMapping);
|
|
4949
|
+
}
|
|
3715
4950
|
maskedText = transformedInput;
|
|
3716
4951
|
maskedReq = this.withMaskedOpenAIRequest(
|
|
3717
|
-
|
|
3718
|
-
transformedInput
|
|
4952
|
+
providerReq,
|
|
4953
|
+
transformedInput,
|
|
4954
|
+
providerMaskingOptions
|
|
3719
4955
|
);
|
|
3720
|
-
const nextCreateArgs = [...
|
|
4956
|
+
const nextCreateArgs = [...createArgs];
|
|
3721
4957
|
nextCreateArgs[0] = maskedReq;
|
|
3722
4958
|
createArgs = nextCreateArgs;
|
|
3723
4959
|
}
|
|
4960
|
+
await this.logPromptPreflightStep(
|
|
4961
|
+
{
|
|
4962
|
+
system_id: systemId,
|
|
4963
|
+
user_id: options.user_id,
|
|
4964
|
+
request_identity: options.request_identity,
|
|
4965
|
+
input: maskedText,
|
|
4966
|
+
telemetry: telemetryMetadata,
|
|
4967
|
+
verdict,
|
|
4968
|
+
guard_event_id: guardEventId,
|
|
4969
|
+
guard_latency_ms: guardLatencyMs,
|
|
4970
|
+
preflight_for_client_event_id: canonicalClientEventId,
|
|
4971
|
+
client_capabilities: this.buildClientCapabilities(
|
|
4972
|
+
"openai",
|
|
4973
|
+
false,
|
|
4974
|
+
capabilityConfig
|
|
4975
|
+
),
|
|
4976
|
+
local_fallback_applied: localFallbackApplied,
|
|
4977
|
+
local_fallback_reason: localFallbackReason,
|
|
4978
|
+
runtime_surface: "openai_sdk_guard"
|
|
4979
|
+
},
|
|
4980
|
+
requestOptions
|
|
4981
|
+
);
|
|
3724
4982
|
if (stream) {
|
|
3725
4983
|
const modelStartedAt2 = Date.now();
|
|
3726
4984
|
const streamResponse = await originalCreate.apply(compTarget, createArgs);
|
|
@@ -3732,14 +4990,15 @@ var AgentID = class {
|
|
|
3732
4990
|
})(),
|
|
3733
4991
|
{
|
|
3734
4992
|
piiMapping: mapping,
|
|
3735
|
-
deanonymizeForClient:
|
|
4993
|
+
deanonymizeForClient: false,
|
|
4994
|
+
maskForClient: !isShadowMode
|
|
3736
4995
|
}
|
|
3737
4996
|
);
|
|
3738
4997
|
if (maskedText && wrappedCompletion.mode === "stream") {
|
|
3739
4998
|
void wrappedCompletion.done.then(async (result) => {
|
|
3740
4999
|
const modelLatencyMs2 = Math.max(0, Date.now() - modelStartedAt2);
|
|
3741
5000
|
const totalPipelineLatencyMs2 = Math.max(0, Date.now() - pipelineStartedAt);
|
|
3742
|
-
const outputForLog =
|
|
5001
|
+
const outputForLog = result.transformedOutput;
|
|
3743
5002
|
const ingestResult = await this.sendIngest({
|
|
3744
5003
|
event_id: canonicalClientEventId,
|
|
3745
5004
|
system_id: systemId,
|
|
@@ -3751,29 +5010,32 @@ var AgentID = class {
|
|
|
3751
5010
|
usage: result.usage,
|
|
3752
5011
|
latency: modelLatencyMs2,
|
|
3753
5012
|
event_type: "complete",
|
|
3754
|
-
metadata:
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
5013
|
+
metadata: mergeTelemetryContexts(
|
|
5014
|
+
telemetryMetadata,
|
|
5015
|
+
{
|
|
5016
|
+
transformed_input: maskedText,
|
|
5017
|
+
transformed_output: result.transformedOutput,
|
|
5018
|
+
output_masked: result.outputMasked,
|
|
5019
|
+
shadow_mode: isShadowMode,
|
|
5020
|
+
simulated_decision: verdict.simulated_decision ?? null,
|
|
5021
|
+
simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
|
|
5022
|
+
response_streamed: true,
|
|
5023
|
+
sdk_local_fallback_applied: localFallbackApplied,
|
|
5024
|
+
sdk_local_fallback_reason: localFallbackReason,
|
|
5025
|
+
guard_latency_ms: guardLatencyMs,
|
|
5026
|
+
model_latency_ms: modelLatencyMs2,
|
|
5027
|
+
total_pipeline_latency_ms: totalPipelineLatencyMs2,
|
|
5028
|
+
guard_event_id: guardEventId,
|
|
5029
|
+
client_event_id: canonicalClientEventId,
|
|
5030
|
+
transparency
|
|
5031
|
+
},
|
|
5032
|
+
buildSdkTimingMetadata({
|
|
3771
5033
|
sdkConfigFetchMs,
|
|
3772
5034
|
sdkLocalScanMs,
|
|
3773
5035
|
sdkGuardMs: guardLatencyMs,
|
|
3774
5036
|
sdkConfigVersion: capabilityConfig.version
|
|
3775
5037
|
})
|
|
3776
|
-
|
|
5038
|
+
),
|
|
3777
5039
|
client_capabilities: this.buildClientCapabilities(
|
|
3778
5040
|
"openai",
|
|
3779
5041
|
false,
|
|
@@ -3804,10 +5066,13 @@ var AgentID = class {
|
|
|
3804
5066
|
const totalPipelineLatencyMs = Math.max(0, Date.now() - pipelineStartedAt);
|
|
3805
5067
|
if (maskedText) {
|
|
3806
5068
|
const output = adapter.extractOutput(res);
|
|
3807
|
-
const wrappedCompletion = this.wrapCompletion(output
|
|
5069
|
+
const wrappedCompletion = this.wrapCompletion(output, {
|
|
5070
|
+
piiMapping: mapping,
|
|
5071
|
+
deanonymizeForClient: false
|
|
5072
|
+
});
|
|
3808
5073
|
const model = adapter.getModelName(maskedReq, res);
|
|
3809
5074
|
const usage = adapter.getTokenUsage(res);
|
|
3810
|
-
const outputForLog =
|
|
5075
|
+
const outputForLog = wrappedCompletion.transformedOutput;
|
|
3811
5076
|
const ingestResult = await this.sendIngest({
|
|
3812
5077
|
event_id: canonicalClientEventId,
|
|
3813
5078
|
system_id: systemId,
|
|
@@ -3819,29 +5084,32 @@ var AgentID = class {
|
|
|
3819
5084
|
usage,
|
|
3820
5085
|
latency: modelLatencyMs,
|
|
3821
5086
|
event_type: "complete",
|
|
3822
|
-
metadata:
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
5087
|
+
metadata: mergeTelemetryContexts(
|
|
5088
|
+
telemetryMetadata,
|
|
5089
|
+
{
|
|
5090
|
+
transformed_input: maskedText,
|
|
5091
|
+
transformed_output: wrappedCompletion.transformedOutput,
|
|
5092
|
+
output_masked: wrappedCompletion.outputMasked,
|
|
5093
|
+
shadow_mode: isShadowMode,
|
|
5094
|
+
simulated_decision: verdict.simulated_decision ?? null,
|
|
5095
|
+
simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
|
|
5096
|
+
response_streamed: false,
|
|
5097
|
+
sdk_local_fallback_applied: localFallbackApplied,
|
|
5098
|
+
sdk_local_fallback_reason: localFallbackReason,
|
|
5099
|
+
guard_latency_ms: guardLatencyMs,
|
|
5100
|
+
model_latency_ms: modelLatencyMs,
|
|
5101
|
+
total_pipeline_latency_ms: totalPipelineLatencyMs,
|
|
5102
|
+
guard_event_id: guardEventId,
|
|
5103
|
+
client_event_id: canonicalClientEventId,
|
|
5104
|
+
transparency
|
|
5105
|
+
},
|
|
5106
|
+
buildSdkTimingMetadata({
|
|
3839
5107
|
sdkConfigFetchMs,
|
|
3840
5108
|
sdkLocalScanMs,
|
|
3841
5109
|
sdkGuardMs: guardLatencyMs,
|
|
3842
5110
|
sdkConfigVersion: capabilityConfig.version
|
|
3843
5111
|
})
|
|
3844
|
-
|
|
5112
|
+
),
|
|
3845
5113
|
client_capabilities: this.buildClientCapabilities(
|
|
3846
5114
|
"openai",
|
|
3847
5115
|
false,
|
|
@@ -3858,17 +5126,21 @@ var AgentID = class {
|
|
|
3858
5126
|
);
|
|
3859
5127
|
}
|
|
3860
5128
|
}
|
|
3861
|
-
if (!
|
|
3862
|
-
const
|
|
5129
|
+
if (!isShadowMode && maskedText) {
|
|
5130
|
+
const output = adapter.extractOutput(res);
|
|
5131
|
+
const maskedOutput = this.wrapCompletion(output, {
|
|
5132
|
+
piiMapping: mapping,
|
|
5133
|
+
deanonymizeForClient: false
|
|
5134
|
+
}).transformedOutput;
|
|
3863
5135
|
try {
|
|
3864
5136
|
if (Array.isArray(res?.choices)) {
|
|
3865
5137
|
for (const choice of res.choices) {
|
|
3866
5138
|
const typedChoice = choice;
|
|
3867
5139
|
if (typedChoice?.message && typeof typedChoice.message.content === "string") {
|
|
3868
|
-
typedChoice.message.content =
|
|
5140
|
+
typedChoice.message.content = maskedOutput;
|
|
3869
5141
|
}
|
|
3870
5142
|
if (typedChoice?.delta && typeof typedChoice.delta.content === "string") {
|
|
3871
|
-
typedChoice.delta.content =
|
|
5143
|
+
typedChoice.delta.content = maskedOutput;
|
|
3872
5144
|
}
|
|
3873
5145
|
}
|
|
3874
5146
|
}
|
|
@@ -3893,6 +5165,155 @@ var AgentID = class {
|
|
|
3893
5165
|
});
|
|
3894
5166
|
}
|
|
3895
5167
|
};
|
|
5168
|
+
function mergeWorkflowTrailRequestOptions(base, override) {
|
|
5169
|
+
const apiKey = firstNonEmptyString(override?.apiKey, base?.apiKey);
|
|
5170
|
+
return apiKey ? { apiKey } : void 0;
|
|
5171
|
+
}
|
|
5172
|
+
function appendWorkflowErrorMetadata(metadata, error) {
|
|
5173
|
+
const nextMetadata = { ...metadata ?? {} };
|
|
5174
|
+
if (error instanceof Error) {
|
|
5175
|
+
if (typeof nextMetadata.error_name !== "string") {
|
|
5176
|
+
nextMetadata.error_name = error.name;
|
|
5177
|
+
}
|
|
5178
|
+
if (typeof nextMetadata.error_message !== "string" && error.message.trim().length > 0) {
|
|
5179
|
+
nextMetadata.error_message = error.message.trim();
|
|
5180
|
+
}
|
|
5181
|
+
return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
|
|
5182
|
+
}
|
|
5183
|
+
if (typeof nextMetadata.error_message !== "string" && typeof error !== "undefined") {
|
|
5184
|
+
const errorMessage = String(error).trim();
|
|
5185
|
+
if (errorMessage.length > 0) {
|
|
5186
|
+
nextMetadata.error_message = errorMessage;
|
|
5187
|
+
}
|
|
5188
|
+
}
|
|
5189
|
+
return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
|
|
5190
|
+
}
|
|
5191
|
+
var AgentIDWorkflowStep = class {
|
|
5192
|
+
constructor(params) {
|
|
5193
|
+
this.trail = params.trail;
|
|
5194
|
+
this.workflowStepId = params.workflowStepId;
|
|
5195
|
+
this.startEventId = params.startEventId;
|
|
5196
|
+
this.telemetry = params.telemetry;
|
|
5197
|
+
this.startedAtMs = params.startedAtMs;
|
|
5198
|
+
}
|
|
5199
|
+
resolveStepTelemetry(telemetry) {
|
|
5200
|
+
return mergeTelemetryContexts(
|
|
5201
|
+
this.telemetry,
|
|
5202
|
+
createAgentIdTelemetryContext({
|
|
5203
|
+
workflow_step_id: this.workflowStepId,
|
|
5204
|
+
parent_event_id: this.startEventId
|
|
5205
|
+
}),
|
|
5206
|
+
telemetry
|
|
5207
|
+
);
|
|
5208
|
+
}
|
|
5209
|
+
async log(params = {}, options) {
|
|
5210
|
+
return this.trail.logStep(
|
|
5211
|
+
{
|
|
5212
|
+
...params,
|
|
5213
|
+
telemetry: this.resolveStepTelemetry(params.telemetry)
|
|
5214
|
+
},
|
|
5215
|
+
options
|
|
5216
|
+
);
|
|
5217
|
+
}
|
|
5218
|
+
async complete(params = {}, options) {
|
|
5219
|
+
return this.log(
|
|
5220
|
+
{
|
|
5221
|
+
...params,
|
|
5222
|
+
latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
|
|
5223
|
+
event_status: params.event_status ?? "completed"
|
|
5224
|
+
},
|
|
5225
|
+
options
|
|
5226
|
+
);
|
|
5227
|
+
}
|
|
5228
|
+
async fail(error, params = {}, options) {
|
|
5229
|
+
return this.log(
|
|
5230
|
+
{
|
|
5231
|
+
...params,
|
|
5232
|
+
latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
|
|
5233
|
+
metadata: appendWorkflowErrorMetadata(params.metadata, error),
|
|
5234
|
+
event_type: params.event_type ?? "error",
|
|
5235
|
+
event_status: params.event_status ?? "failed",
|
|
5236
|
+
severity: params.severity ?? "error"
|
|
5237
|
+
},
|
|
5238
|
+
options
|
|
5239
|
+
);
|
|
5240
|
+
}
|
|
5241
|
+
};
|
|
5242
|
+
var AgentIDWorkflowTrail = class {
|
|
5243
|
+
constructor(options) {
|
|
5244
|
+
this.agent = options.agent;
|
|
5245
|
+
this.systemId = options.system_id;
|
|
5246
|
+
this.userId = options.user_id;
|
|
5247
|
+
this.requestIdentity = options.request_identity;
|
|
5248
|
+
this.telemetry = createAgentIdTelemetryContext(options.telemetry);
|
|
5249
|
+
this.clientCapabilities = options.client_capabilities;
|
|
5250
|
+
this.requestOptions = options.requestOptions;
|
|
5251
|
+
}
|
|
5252
|
+
async logStep(params = {}, options) {
|
|
5253
|
+
const payload = this.agent.buildOperationLogParams({
|
|
5254
|
+
...params,
|
|
5255
|
+
system_id: this.systemId,
|
|
5256
|
+
user_id: this.userId,
|
|
5257
|
+
request_identity: this.requestIdentity,
|
|
5258
|
+
telemetry: mergeTelemetryContexts(this.telemetry, params.telemetry),
|
|
5259
|
+
client_capabilities: params.client_capabilities ?? this.clientCapabilities
|
|
5260
|
+
});
|
|
5261
|
+
await this.agent.log(
|
|
5262
|
+
payload,
|
|
5263
|
+
mergeWorkflowTrailRequestOptions(this.requestOptions, options)
|
|
5264
|
+
);
|
|
5265
|
+
return payload;
|
|
5266
|
+
}
|
|
5267
|
+
async startStep(params = {}, options) {
|
|
5268
|
+
const startedAtMs = Date.now();
|
|
5269
|
+
const requestedTelemetry = createAgentIdTelemetryContext(params.telemetry);
|
|
5270
|
+
const workflowStepId = firstNonEmptyString(requestedTelemetry?.workflow_step_id, requestedTelemetry?.workflowStepId) ?? createAgentIdCorrelationId();
|
|
5271
|
+
const startTelemetry = mergeTelemetryContexts(
|
|
5272
|
+
requestedTelemetry,
|
|
5273
|
+
createAgentIdTelemetryContext({
|
|
5274
|
+
workflow_step_id: workflowStepId
|
|
5275
|
+
})
|
|
5276
|
+
);
|
|
5277
|
+
const startPayload = await this.logStep(
|
|
5278
|
+
{
|
|
5279
|
+
...params,
|
|
5280
|
+
telemetry: startTelemetry,
|
|
5281
|
+
event_type: params.event_type ?? "start",
|
|
5282
|
+
event_status: params.event_status ?? "started"
|
|
5283
|
+
},
|
|
5284
|
+
options
|
|
5285
|
+
);
|
|
5286
|
+
return new AgentIDWorkflowStep({
|
|
5287
|
+
trail: this,
|
|
5288
|
+
workflowStepId,
|
|
5289
|
+
startEventId: startPayload.event_id ?? createEventId2(),
|
|
5290
|
+
telemetry: startTelemetry,
|
|
5291
|
+
startedAtMs
|
|
5292
|
+
});
|
|
5293
|
+
}
|
|
5294
|
+
async runStep(params, run, hooks, options) {
|
|
5295
|
+
const step = await this.startStep(params, options);
|
|
5296
|
+
try {
|
|
5297
|
+
const result = await run();
|
|
5298
|
+
const completeParams = {
|
|
5299
|
+
...hooks?.complete ?? {},
|
|
5300
|
+
...hooks?.onComplete?.(result) ?? {}
|
|
5301
|
+
};
|
|
5302
|
+
await step.complete(completeParams, options);
|
|
5303
|
+
return result;
|
|
5304
|
+
} catch (error) {
|
|
5305
|
+
const failParams = {
|
|
5306
|
+
...hooks?.fail ?? {},
|
|
5307
|
+
...hooks?.onError?.(error) ?? {}
|
|
5308
|
+
};
|
|
5309
|
+
await step.fail(error, failParams, options);
|
|
5310
|
+
throw error;
|
|
5311
|
+
}
|
|
5312
|
+
}
|
|
5313
|
+
};
|
|
5314
|
+
function createAgentIdWorkflowTrail(options) {
|
|
5315
|
+
return new AgentIDWorkflowTrail(options);
|
|
5316
|
+
}
|
|
3896
5317
|
|
|
3897
5318
|
export {
|
|
3898
5319
|
OpenAIAdapter,
|
|
@@ -3900,7 +5321,13 @@ export {
|
|
|
3900
5321
|
scanWithRegex,
|
|
3901
5322
|
InjectionScanner,
|
|
3902
5323
|
getInjectionScanner,
|
|
5324
|
+
createAgentIdCorrelationId,
|
|
5325
|
+
createAgentIdTelemetryContext,
|
|
5326
|
+
createAgentIdOperationLog,
|
|
3903
5327
|
SecurityBlockError,
|
|
3904
5328
|
DependencyError,
|
|
3905
|
-
AgentID
|
|
5329
|
+
AgentID,
|
|
5330
|
+
AgentIDWorkflowStep,
|
|
5331
|
+
AgentIDWorkflowTrail,
|
|
5332
|
+
createAgentIdWorkflowTrail
|
|
3906
5333
|
};
|