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
package/dist/index.js
CHANGED
|
@@ -21,27 +21,106 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AgentID: () => AgentID,
|
|
24
|
+
AgentIDWorkflowStep: () => AgentIDWorkflowStep,
|
|
25
|
+
AgentIDWorkflowTrail: () => AgentIDWorkflowTrail,
|
|
24
26
|
DependencyError: () => DependencyError,
|
|
25
27
|
InjectionScanner: () => InjectionScanner,
|
|
26
28
|
OpenAIAdapter: () => OpenAIAdapter,
|
|
27
29
|
PIIManager: () => PIIManager,
|
|
28
30
|
SecurityBlockError: () => SecurityBlockError,
|
|
31
|
+
createAgentIdCorrelationId: () => createAgentIdCorrelationId,
|
|
32
|
+
createAgentIdOperationLog: () => createAgentIdOperationLog,
|
|
33
|
+
createAgentIdTelemetryContext: () => createAgentIdTelemetryContext,
|
|
34
|
+
createAgentIdWorkflowTrail: () => createAgentIdWorkflowTrail,
|
|
29
35
|
getInjectionScanner: () => getInjectionScanner,
|
|
36
|
+
protectMessageHistory: () => protectMessageHistory,
|
|
30
37
|
scanWithRegex: () => scanWithRegex
|
|
31
38
|
});
|
|
32
39
|
module.exports = __toCommonJS(index_exports);
|
|
33
40
|
|
|
34
41
|
// src/adapters.ts
|
|
42
|
+
function getLastUserMessage(req) {
|
|
43
|
+
const messages = req?.messages;
|
|
44
|
+
if (!Array.isArray(messages)) return null;
|
|
45
|
+
let lastUser = null;
|
|
46
|
+
for (const msg of messages) {
|
|
47
|
+
if (msg && typeof msg === "object" && msg.role === "user") {
|
|
48
|
+
lastUser = msg;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return lastUser;
|
|
52
|
+
}
|
|
53
|
+
function normalizeFilename(value, fallback) {
|
|
54
|
+
if (typeof value !== "string") {
|
|
55
|
+
return fallback;
|
|
56
|
+
}
|
|
57
|
+
const trimmed = value.trim();
|
|
58
|
+
return trimmed.length > 0 ? trimmed : fallback;
|
|
59
|
+
}
|
|
60
|
+
function parseDataUrl(value) {
|
|
61
|
+
if (!value.startsWith("data:")) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const commaIndex = value.indexOf(",");
|
|
65
|
+
if (commaIndex === -1) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const header = value.slice(5, commaIndex);
|
|
69
|
+
if (!/;base64/i.test(header)) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const mimeType = header.split(";")[0]?.trim().toLowerCase() || null;
|
|
73
|
+
return { mimeType };
|
|
74
|
+
}
|
|
75
|
+
function inferAttachmentExtension(mimeType) {
|
|
76
|
+
switch (mimeType) {
|
|
77
|
+
case "application/pdf":
|
|
78
|
+
return "pdf";
|
|
79
|
+
case "image/png":
|
|
80
|
+
return "png";
|
|
81
|
+
case "image/jpeg":
|
|
82
|
+
return "jpg";
|
|
83
|
+
case "image/webp":
|
|
84
|
+
return "webp";
|
|
85
|
+
case "image/gif":
|
|
86
|
+
return "gif";
|
|
87
|
+
case "text/plain":
|
|
88
|
+
return "txt";
|
|
89
|
+
default:
|
|
90
|
+
return "bin";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function defaultFilenameForMimeType(mimeType) {
|
|
94
|
+
return `attachment.${inferAttachmentExtension(mimeType)}`;
|
|
95
|
+
}
|
|
96
|
+
function normalizeFileAttachment(part) {
|
|
97
|
+
const file = part?.file;
|
|
98
|
+
const rawContent = typeof file?.file_data === "string" && file.file_data.trim().length > 0 ? file.file_data.trim() : null;
|
|
99
|
+
if (!rawContent) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const detectedMimeType = parseDataUrl(rawContent)?.mimeType ?? null;
|
|
103
|
+
return {
|
|
104
|
+
filename: normalizeFilename(file?.filename, defaultFilenameForMimeType(detectedMimeType)),
|
|
105
|
+
...detectedMimeType ? { mime_type: detectedMimeType } : {},
|
|
106
|
+
content_base64: rawContent
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function normalizeImageAttachment(part) {
|
|
110
|
+
const imageUrl = typeof part?.image_url?.url === "string" && part.image_url.url.trim().length > 0 ? part.image_url.url.trim() : null;
|
|
111
|
+
if (!imageUrl || !imageUrl.startsWith("data:")) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
const detectedMimeType = parseDataUrl(imageUrl)?.mimeType ?? "image/png";
|
|
115
|
+
return {
|
|
116
|
+
filename: defaultFilenameForMimeType(detectedMimeType),
|
|
117
|
+
mime_type: detectedMimeType,
|
|
118
|
+
content_base64: imageUrl
|
|
119
|
+
};
|
|
120
|
+
}
|
|
35
121
|
var OpenAIAdapter = class {
|
|
36
122
|
extractInput(req) {
|
|
37
|
-
const
|
|
38
|
-
if (!Array.isArray(messages)) return null;
|
|
39
|
-
let lastUser = null;
|
|
40
|
-
for (const msg of messages) {
|
|
41
|
-
if (msg && typeof msg === "object" && msg.role === "user") {
|
|
42
|
-
lastUser = msg;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
123
|
+
const lastUser = getLastUserMessage(req);
|
|
45
124
|
if (!lastUser) return null;
|
|
46
125
|
const content = lastUser.content;
|
|
47
126
|
if (typeof content === "string") return content;
|
|
@@ -56,6 +135,34 @@ var OpenAIAdapter = class {
|
|
|
56
135
|
}
|
|
57
136
|
return null;
|
|
58
137
|
}
|
|
138
|
+
extractAttachments(req) {
|
|
139
|
+
const lastUser = getLastUserMessage(req);
|
|
140
|
+
if (!lastUser) return [];
|
|
141
|
+
const content = lastUser?.content;
|
|
142
|
+
if (!Array.isArray(content)) {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
const attachments = [];
|
|
146
|
+
for (const part of content) {
|
|
147
|
+
if (!part || typeof part !== "object") {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (part.type === "file") {
|
|
151
|
+
const attachment = normalizeFileAttachment(part);
|
|
152
|
+
if (attachment) {
|
|
153
|
+
attachments.push(attachment);
|
|
154
|
+
}
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (part.type === "image_url") {
|
|
158
|
+
const attachment = normalizeImageAttachment(part);
|
|
159
|
+
if (attachment) {
|
|
160
|
+
attachments.push(attachment);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return attachments;
|
|
165
|
+
}
|
|
59
166
|
getModelName(req, res) {
|
|
60
167
|
const model = res?.model ?? req?.model ?? "unknown";
|
|
61
168
|
return String(model);
|
|
@@ -75,7 +182,7 @@ var OpenAIAdapter = class {
|
|
|
75
182
|
|
|
76
183
|
// src/sdk-version.ts
|
|
77
184
|
var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
|
|
78
|
-
var AGENTID_SDK_VERSION_HEADER = "js-0.1.
|
|
185
|
+
var AGENTID_SDK_VERSION_HEADER = "js-0.1.40".trim().length > 0 ? "js-0.1.40" : FALLBACK_SDK_VERSION;
|
|
79
186
|
|
|
80
187
|
// src/pii-national-identifiers.ts
|
|
81
188
|
var MAX_CANDIDATES_PER_RULE = 256;
|
|
@@ -939,8 +1046,173 @@ function detectNationalIdentifiers(text, options = {}) {
|
|
|
939
1046
|
return results;
|
|
940
1047
|
}
|
|
941
1048
|
|
|
1049
|
+
// src/secret-patterns.ts
|
|
1050
|
+
var SDK_SECRET_PATTERN_DEFINITIONS = [
|
|
1051
|
+
{
|
|
1052
|
+
id: "openai_api_key",
|
|
1053
|
+
placeholderType: "OPENAI_API_KEY",
|
|
1054
|
+
patternSource: "\\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\\b",
|
|
1055
|
+
flags: "iu",
|
|
1056
|
+
prefilterTerms: ["sk-", "proj-", "openai"]
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
id: "aws_access_key",
|
|
1060
|
+
placeholderType: "AWS_ACCESS_KEY",
|
|
1061
|
+
patternSource: "\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b",
|
|
1062
|
+
flags: "iu",
|
|
1063
|
+
prefilterTerms: ["akia", "asia", "aws"]
|
|
1064
|
+
},
|
|
1065
|
+
{
|
|
1066
|
+
id: "github_token",
|
|
1067
|
+
placeholderType: "GITHUB_TOKEN",
|
|
1068
|
+
patternSource: "\\b(?:gh[pousr]_[A-Za-z0-9]{24,255}|github_pat_[A-Za-z0-9_]{20,255})\\b",
|
|
1069
|
+
flags: "iu",
|
|
1070
|
+
prefilterTerms: ["ghp_", "gho_", "ghu_", "ghs_", "ghr_", "github_pat_"]
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
id: "slack_token",
|
|
1074
|
+
placeholderType: "SLACK_TOKEN",
|
|
1075
|
+
patternSource: "\\bxox(?:a|b|p|r|s)-[A-Za-z0-9-]{10,200}\\b",
|
|
1076
|
+
flags: "iu",
|
|
1077
|
+
prefilterTerms: ["xoxa-", "xoxb-", "xoxp-", "xoxr-", "xoxs-", "slack"]
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
id: "slack_webhook_url",
|
|
1081
|
+
placeholderType: "SLACK_WEBHOOK_URL",
|
|
1082
|
+
patternSource: "https:\\/\\/hooks\\.slack\\.com\\/services\\/[A-Za-z0-9/_-]{20,}",
|
|
1083
|
+
flags: "iu",
|
|
1084
|
+
prefilterTerms: ["hooks.slack.com/services", "slack"]
|
|
1085
|
+
},
|
|
1086
|
+
{
|
|
1087
|
+
id: "discord_webhook_url",
|
|
1088
|
+
placeholderType: "DISCORD_WEBHOOK_URL",
|
|
1089
|
+
patternSource: "https:\\/\\/discord(?:app)?\\.com\\/api\\/webhooks\\/\\d+\\/[A-Za-z0-9_-]{16,}",
|
|
1090
|
+
flags: "iu",
|
|
1091
|
+
prefilterTerms: ["discord.com/api/webhooks", "discordapp.com/api/webhooks", "discord"]
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
id: "stripe_secret_key",
|
|
1095
|
+
placeholderType: "STRIPE_SECRET_KEY",
|
|
1096
|
+
patternSource: "\\b(?:sk|pk|ak|rk)_(?:live|test)_[A-Za-z0-9]+\\b",
|
|
1097
|
+
flags: "iu",
|
|
1098
|
+
prefilterTerms: [
|
|
1099
|
+
"sk_live_",
|
|
1100
|
+
"pk_live_",
|
|
1101
|
+
"sk_test_",
|
|
1102
|
+
"pk_test_",
|
|
1103
|
+
"ak_live_",
|
|
1104
|
+
"ak_test_",
|
|
1105
|
+
"rk_live_",
|
|
1106
|
+
"rk_test_",
|
|
1107
|
+
"stripe"
|
|
1108
|
+
]
|
|
1109
|
+
},
|
|
1110
|
+
{
|
|
1111
|
+
id: "google_api_key",
|
|
1112
|
+
placeholderType: "GOOGLE_API_KEY",
|
|
1113
|
+
patternSource: "\\bAIza[0-9A-Za-z_-]{35}\\b",
|
|
1114
|
+
flags: "iu",
|
|
1115
|
+
prefilterTerms: ["aiza", "google"]
|
|
1116
|
+
},
|
|
1117
|
+
{
|
|
1118
|
+
id: "anthropic_api_key",
|
|
1119
|
+
placeholderType: "ANTHROPIC_API_KEY",
|
|
1120
|
+
patternSource: "\\bsk-ant-(?:api\\d{2}-)?[A-Za-z0-9_-]{20,}\\b",
|
|
1121
|
+
flags: "iu",
|
|
1122
|
+
prefilterTerms: ["sk-ant-", "anthropic"]
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
id: "evm_private_key",
|
|
1126
|
+
placeholderType: "EVM_PRIVATE_KEY",
|
|
1127
|
+
patternSource: "\\b0x[a-fA-F0-9]{64}\\b",
|
|
1128
|
+
flags: "iu",
|
|
1129
|
+
prefilterTerms: ["0x", "ethereum", "evm", "private key"]
|
|
1130
|
+
},
|
|
1131
|
+
{
|
|
1132
|
+
id: "jwt_token",
|
|
1133
|
+
placeholderType: "JWT_TOKEN",
|
|
1134
|
+
patternSource: "\\beyJ[A-Za-z0-9_-]{6,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\b",
|
|
1135
|
+
flags: "iu",
|
|
1136
|
+
prefilterTerms: ["eyj", "jwt", "bearer"]
|
|
1137
|
+
},
|
|
1138
|
+
{
|
|
1139
|
+
id: "bearer_token",
|
|
1140
|
+
placeholderType: "BEARER_TOKEN",
|
|
1141
|
+
patternSource: "\\bauthorization\\b\\s*[:=]\\s*bearer\\s+[A-Za-z0-9._~+\\/-]{16,}|\\bbearer\\s+[A-Za-z0-9._~+\\/-]{24,}",
|
|
1142
|
+
flags: "iu",
|
|
1143
|
+
prefilterTerms: ["authorization", "bearer"]
|
|
1144
|
+
},
|
|
1145
|
+
{
|
|
1146
|
+
id: "api_key_header",
|
|
1147
|
+
placeholderType: "API_KEY_HEADER",
|
|
1148
|
+
patternSource: "\\bx[-_]?api[-_]?key\\b\\s*[:=]\\s*[A-Za-z0-9._~+\\/-]{16,}",
|
|
1149
|
+
flags: "iu",
|
|
1150
|
+
prefilterTerms: ["x-api-key", "api-key", "x_api_key", "api_key"]
|
|
1151
|
+
},
|
|
1152
|
+
{
|
|
1153
|
+
id: "credential_assignment",
|
|
1154
|
+
placeholderType: "CREDENTIAL_ASSIGNMENT",
|
|
1155
|
+
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,})`,
|
|
1156
|
+
flags: "iu",
|
|
1157
|
+
prefilterTerms: [
|
|
1158
|
+
"api key",
|
|
1159
|
+
"apikey",
|
|
1160
|
+
"api_key",
|
|
1161
|
+
"access token",
|
|
1162
|
+
"access_token",
|
|
1163
|
+
"auth token",
|
|
1164
|
+
"client secret",
|
|
1165
|
+
"private key"
|
|
1166
|
+
]
|
|
1167
|
+
},
|
|
1168
|
+
{
|
|
1169
|
+
id: "password_assignment",
|
|
1170
|
+
placeholderType: "PASSWORD_ASSIGNMENT",
|
|
1171
|
+
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,})`,
|
|
1172
|
+
flags: "iu",
|
|
1173
|
+
prefilterTerms: ["password", "passwd", "pwd", "heslo"]
|
|
1174
|
+
},
|
|
1175
|
+
{
|
|
1176
|
+
id: "private_key_material",
|
|
1177
|
+
placeholderType: "PRIVATE_KEY_MATERIAL",
|
|
1178
|
+
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)-----|$)",
|
|
1179
|
+
flags: "iu",
|
|
1180
|
+
prefilterTerms: ["begin private key", "begin pgp private key block", "private key"]
|
|
1181
|
+
},
|
|
1182
|
+
{
|
|
1183
|
+
id: "azure_connection_string",
|
|
1184
|
+
placeholderType: "AZURE_CONNECTION_STRING",
|
|
1185
|
+
patternSource: "\\bDefaultEndpointsProtocol=https;AccountName=[A-Za-z0-9.-]{3,};AccountKey=[A-Za-z0-9+/=]{20,}(?:;EndpointSuffix=[A-Za-z0-9.-]+)?\\b",
|
|
1186
|
+
flags: "iu",
|
|
1187
|
+
prefilterTerms: ["defaultendpointsprotocol", "accountname", "accountkey", "azure"]
|
|
1188
|
+
},
|
|
1189
|
+
{
|
|
1190
|
+
id: "azure_sas_token",
|
|
1191
|
+
placeholderType: "AZURE_SAS_TOKEN",
|
|
1192
|
+
patternSource: "\\bsv=[^\\s&]{2,}&[^\\s]{0,200}\\bsig=[A-Za-z0-9%/+_-]{16,}",
|
|
1193
|
+
flags: "iu",
|
|
1194
|
+
prefilterTerms: ["sv=", "sig=", "accountkey", "azure"]
|
|
1195
|
+
}
|
|
1196
|
+
];
|
|
1197
|
+
function ensureGlobalFlag(flags) {
|
|
1198
|
+
const normalized = new Set(flags.split(""));
|
|
1199
|
+
normalized.add("g");
|
|
1200
|
+
return [...normalized].join("");
|
|
1201
|
+
}
|
|
1202
|
+
var COMPILED_SDK_SECRET_PATTERNS = SDK_SECRET_PATTERN_DEFINITIONS.map((definition) => ({
|
|
1203
|
+
...definition,
|
|
1204
|
+
scanRegex: new RegExp(definition.patternSource, ensureGlobalFlag(definition.flags)),
|
|
1205
|
+
prefilterTermsLower: definition.prefilterTerms.map((term) => term.toLowerCase())
|
|
1206
|
+
}));
|
|
1207
|
+
function getSdkSecretDetectionMatchers() {
|
|
1208
|
+
return COMPILED_SDK_SECRET_PATTERNS;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
942
1211
|
// src/pii.ts
|
|
943
1212
|
var defaultScanDeadlineMs = 100;
|
|
1213
|
+
var sdkSecretMatchers = getSdkSecretDetectionMatchers();
|
|
1214
|
+
var DISCORD_WEBHOOK_TOKEN_RE = /https:\/\/discord(?:app)?\.com\/api\/webhooks\/\d+\/([A-Za-z0-9_-]{16,})/giu;
|
|
1215
|
+
var BASIC_AUTH_PASSWORD_RE = /\/\/[^:\s/?#@]+:([^@\s/?#]+)@/giu;
|
|
944
1216
|
function countDigits2(value) {
|
|
945
1217
|
let count = 0;
|
|
946
1218
|
for (const ch of value) {
|
|
@@ -965,15 +1237,32 @@ function luhnCheck(value) {
|
|
|
965
1237
|
return sum % 10 === 0;
|
|
966
1238
|
}
|
|
967
1239
|
function normalizeDetections(text, detections) {
|
|
968
|
-
const sorted = detections.filter((d) => d.start >= 0 && d.end > d.start && d.end <= text.length).sort(
|
|
1240
|
+
const sorted = detections.filter((d) => d.start >= 0 && d.end > d.start && d.end <= text.length).sort(
|
|
1241
|
+
(a, b) => detectionPriority(b.type) - detectionPriority(a.type) || a.start - b.start || b.end - b.start - (a.end - a.start)
|
|
1242
|
+
);
|
|
969
1243
|
const kept = [];
|
|
970
|
-
let cursor = 0;
|
|
971
1244
|
for (const d of sorted) {
|
|
972
|
-
if (
|
|
1245
|
+
if (kept.some((candidate) => rangesOverlap(candidate, d))) continue;
|
|
973
1246
|
kept.push(d);
|
|
974
|
-
cursor = d.end;
|
|
975
1247
|
}
|
|
976
|
-
return kept;
|
|
1248
|
+
return kept.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
1249
|
+
}
|
|
1250
|
+
function rangesOverlap(left, right) {
|
|
1251
|
+
return left.start < right.end && right.start < left.end;
|
|
1252
|
+
}
|
|
1253
|
+
function detectionPriority(type) {
|
|
1254
|
+
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(
|
|
1255
|
+
type
|
|
1256
|
+
)) {
|
|
1257
|
+
return 100;
|
|
1258
|
+
}
|
|
1259
|
+
if (/^(?:CREDENTIAL_ASSIGNMENT|PASSWORD_ASSIGNMENT|PRIVATE_KEY_MATERIAL|ENV_SECRET_ASSIGNMENT)$/u.test(type)) {
|
|
1260
|
+
return 80;
|
|
1261
|
+
}
|
|
1262
|
+
if (type === "PERSON_NAME" || type === "PERSON") {
|
|
1263
|
+
return 10;
|
|
1264
|
+
}
|
|
1265
|
+
return 50;
|
|
977
1266
|
}
|
|
978
1267
|
var PHONE_CONTEXT_KEYWORDS = [
|
|
979
1268
|
"tel",
|
|
@@ -983,6 +1272,8 @@ var PHONE_CONTEXT_KEYWORDS = [
|
|
|
983
1272
|
"call",
|
|
984
1273
|
"contact",
|
|
985
1274
|
"number",
|
|
1275
|
+
"cislo",
|
|
1276
|
+
"\u010D\xEDslo",
|
|
986
1277
|
"hotline",
|
|
987
1278
|
"support",
|
|
988
1279
|
"infoline",
|
|
@@ -1008,6 +1299,59 @@ var PHONE_CONTEXT_RE = new RegExp(
|
|
|
1008
1299
|
"iu"
|
|
1009
1300
|
);
|
|
1010
1301
|
var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
|
|
1302
|
+
"name",
|
|
1303
|
+
"names",
|
|
1304
|
+
"namen",
|
|
1305
|
+
"firstname",
|
|
1306
|
+
"lastname",
|
|
1307
|
+
"first",
|
|
1308
|
+
"last",
|
|
1309
|
+
"forename",
|
|
1310
|
+
"surname",
|
|
1311
|
+
"family",
|
|
1312
|
+
"given",
|
|
1313
|
+
"jmeno",
|
|
1314
|
+
"jake",
|
|
1315
|
+
"jaky",
|
|
1316
|
+
"jaka",
|
|
1317
|
+
"jsem",
|
|
1318
|
+
"jsme",
|
|
1319
|
+
"napsal",
|
|
1320
|
+
"napsali",
|
|
1321
|
+
"napsala",
|
|
1322
|
+
"napsane",
|
|
1323
|
+
"pouzil",
|
|
1324
|
+
"pouzili",
|
|
1325
|
+
"prijmeni",
|
|
1326
|
+
"vorname",
|
|
1327
|
+
"nachname",
|
|
1328
|
+
"familienname",
|
|
1329
|
+
"what",
|
|
1330
|
+
"which",
|
|
1331
|
+
"whose",
|
|
1332
|
+
"did",
|
|
1333
|
+
"we",
|
|
1334
|
+
"write",
|
|
1335
|
+
"wrote",
|
|
1336
|
+
"written",
|
|
1337
|
+
"type",
|
|
1338
|
+
"typed",
|
|
1339
|
+
"use",
|
|
1340
|
+
"used",
|
|
1341
|
+
"wie",
|
|
1342
|
+
"welchen",
|
|
1343
|
+
"welche",
|
|
1344
|
+
"welches",
|
|
1345
|
+
"haben",
|
|
1346
|
+
"wir",
|
|
1347
|
+
"geschrieben",
|
|
1348
|
+
"getippt",
|
|
1349
|
+
"quel",
|
|
1350
|
+
"quelle",
|
|
1351
|
+
"nom",
|
|
1352
|
+
"que",
|
|
1353
|
+
"cual",
|
|
1354
|
+
"nombre",
|
|
1011
1355
|
"write",
|
|
1012
1356
|
"code",
|
|
1013
1357
|
"script",
|
|
@@ -1034,6 +1378,52 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
|
|
|
1034
1378
|
"security",
|
|
1035
1379
|
"instructions",
|
|
1036
1380
|
"instruction",
|
|
1381
|
+
"google",
|
|
1382
|
+
"form",
|
|
1383
|
+
"forms",
|
|
1384
|
+
"engineering",
|
|
1385
|
+
"leadership",
|
|
1386
|
+
"weekly",
|
|
1387
|
+
"daily",
|
|
1388
|
+
"monthly",
|
|
1389
|
+
"quarterly",
|
|
1390
|
+
"sync",
|
|
1391
|
+
"office",
|
|
1392
|
+
"updates",
|
|
1393
|
+
"update",
|
|
1394
|
+
"meeting",
|
|
1395
|
+
"meetings",
|
|
1396
|
+
"agenda",
|
|
1397
|
+
"minutes",
|
|
1398
|
+
"subject",
|
|
1399
|
+
"calendar",
|
|
1400
|
+
"roadmap",
|
|
1401
|
+
"platform",
|
|
1402
|
+
"product",
|
|
1403
|
+
"design",
|
|
1404
|
+
"operations",
|
|
1405
|
+
"business",
|
|
1406
|
+
"newsletter",
|
|
1407
|
+
"report",
|
|
1408
|
+
"reports",
|
|
1409
|
+
"amazon",
|
|
1410
|
+
"web",
|
|
1411
|
+
"services",
|
|
1412
|
+
"aws",
|
|
1413
|
+
"velka",
|
|
1414
|
+
"transformace",
|
|
1415
|
+
"project",
|
|
1416
|
+
"projekt",
|
|
1417
|
+
"program",
|
|
1418
|
+
"initiative",
|
|
1419
|
+
"iniciativa",
|
|
1420
|
+
"migration",
|
|
1421
|
+
"migrace",
|
|
1422
|
+
"test",
|
|
1423
|
+
"uuid",
|
|
1424
|
+
"fixture",
|
|
1425
|
+
"data",
|
|
1426
|
+
"firma",
|
|
1037
1427
|
"rules",
|
|
1038
1428
|
"rule",
|
|
1039
1429
|
"json",
|
|
@@ -1046,10 +1436,22 @@ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
|
|
|
1046
1436
|
"agentid",
|
|
1047
1437
|
"risk",
|
|
1048
1438
|
"score",
|
|
1049
|
-
"summary"
|
|
1439
|
+
"summary",
|
|
1440
|
+
"hi",
|
|
1441
|
+
"hello",
|
|
1442
|
+
"hey",
|
|
1443
|
+
"dear",
|
|
1444
|
+
"team",
|
|
1445
|
+
"ahoj",
|
|
1446
|
+
"dobry",
|
|
1447
|
+
"dobryden",
|
|
1448
|
+
"zdravim"
|
|
1050
1449
|
]);
|
|
1051
1450
|
var TECHNICAL_CONTEXT_WORD_REGEX = /\b(?:curl|http|https|import|python|javascript|typescript|sql|nosql|mongo|database|query|script|code|os\.system|eval|exec|node|npm|api|endpoint|regex|json|xml|yaml|bash|powershell)\b/i;
|
|
1052
1451
|
var TECHNICAL_CONTEXT_SYMBOL_REGEX = /:\/\/|`|\{|\}|\[|\]|\(|\)|;|\$|=>|::|\/\//;
|
|
1452
|
+
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;
|
|
1453
|
+
var NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX = /(?:[:=]|=>|-|\b(?:is|was|je|jsou|jmenuje|called|named|ist|sind|lautet|est|es)\b)\s*$/iu;
|
|
1454
|
+
var BIRTH_NUMBER_CONTEXT_RE = /\b(?:rodn[eé]\s*(?:č[ií]slo|cislo)|r\.?\s*c\.?|birth\s+number)\b[^0-9]{0,80}(\d{6}(?:\/?\d{3,4})?)\b/giu;
|
|
1053
1455
|
function hasPhoneContext(text, matchStartIndex, windowSize = 50) {
|
|
1054
1456
|
const start = Math.max(0, matchStartIndex - windowSize);
|
|
1055
1457
|
const windowLower = text.slice(start, matchStartIndex).toLowerCase();
|
|
@@ -1066,6 +1468,16 @@ function buildContextWindow(source, index, length) {
|
|
|
1066
1468
|
function isTechnicalContext(contextWindow) {
|
|
1067
1469
|
return TECHNICAL_CONTEXT_WORD_REGEX.test(contextWindow) || TECHNICAL_CONTEXT_SYMBOL_REGEX.test(contextWindow);
|
|
1068
1470
|
}
|
|
1471
|
+
function isNameLabelQuestionContext(contextWindow) {
|
|
1472
|
+
const normalized = normalizePersonWord(contextWindow);
|
|
1473
|
+
if (!normalized.trim()) {
|
|
1474
|
+
return false;
|
|
1475
|
+
}
|
|
1476
|
+
if (!NAME_LABEL_QUESTION_CONTEXT_REGEX.test(normalized)) {
|
|
1477
|
+
return false;
|
|
1478
|
+
}
|
|
1479
|
+
return !NAME_VALUE_ASSIGNMENT_BEFORE_CANDIDATE_REGEX.test(normalized.slice(-32));
|
|
1480
|
+
}
|
|
1069
1481
|
function isLikelyPersonNameCandidate(candidate, contextWindow) {
|
|
1070
1482
|
const words = candidate.trim().split(/\s+/);
|
|
1071
1483
|
if (words.length !== 2) {
|
|
@@ -1074,6 +1486,9 @@ function isLikelyPersonNameCandidate(candidate, contextWindow) {
|
|
|
1074
1486
|
if (isTechnicalContext(contextWindow)) {
|
|
1075
1487
|
return false;
|
|
1076
1488
|
}
|
|
1489
|
+
if (isNameLabelQuestionContext(contextWindow)) {
|
|
1490
|
+
return false;
|
|
1491
|
+
}
|
|
1077
1492
|
for (const rawWord of words) {
|
|
1078
1493
|
const normalized = normalizePersonWord(rawWord);
|
|
1079
1494
|
if (normalized.length < 2) {
|
|
@@ -1094,63 +1509,135 @@ var PIIManager = class {
|
|
|
1094
1509
|
*
|
|
1095
1510
|
* Zero-dependency fallback with strict checksum validation for CEE national IDs.
|
|
1096
1511
|
*/
|
|
1097
|
-
anonymize(text) {
|
|
1512
|
+
anonymize(text, options) {
|
|
1098
1513
|
if (!text) return { maskedText: text, mapping: {} };
|
|
1099
1514
|
try {
|
|
1100
1515
|
const detections = [];
|
|
1101
|
-
const
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
if (m.index == null) continue;
|
|
1109
|
-
detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
|
|
1110
|
-
}
|
|
1111
|
-
const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
|
|
1112
|
-
for (const m of text.matchAll(ccRe)) {
|
|
1113
|
-
if (m.index == null) continue;
|
|
1114
|
-
const digits = countDigits2(m[0]);
|
|
1115
|
-
if (digits < 12 || digits > 19) continue;
|
|
1116
|
-
if (!luhnCheck(m[0])) continue;
|
|
1117
|
-
detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
|
|
1516
|
+
const loweredText = text.toLowerCase();
|
|
1517
|
+
const resolvedOptions = {
|
|
1518
|
+
pii: options?.pii !== false,
|
|
1519
|
+
secrets: options?.secrets !== false
|
|
1520
|
+
};
|
|
1521
|
+
if (!resolvedOptions.pii && !resolvedOptions.secrets) {
|
|
1522
|
+
return { maskedText: text, mapping: {} };
|
|
1118
1523
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
if (digits < 9 || digits > 15) continue;
|
|
1125
|
-
const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
|
|
1126
|
-
if (!isStrongInternational) {
|
|
1127
|
-
const hasContext = hasPhoneContext(text, m.index);
|
|
1128
|
-
if (!hasContext) continue;
|
|
1524
|
+
if (resolvedOptions.pii) {
|
|
1525
|
+
const emailRe = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
|
|
1526
|
+
for (const m of text.matchAll(emailRe)) {
|
|
1527
|
+
if (m.index == null) continue;
|
|
1528
|
+
detections.push({ start: m.index, end: m.index + m[0].length, type: "EMAIL", text: m[0] });
|
|
1129
1529
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
if (m.index == null) continue;
|
|
1135
|
-
const candidate = m[0];
|
|
1136
|
-
const contextWindow = buildContextWindow(text, m.index, candidate.length);
|
|
1137
|
-
if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
|
|
1138
|
-
continue;
|
|
1530
|
+
const ibanRe = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/gi;
|
|
1531
|
+
for (const m of text.matchAll(ibanRe)) {
|
|
1532
|
+
if (m.index == null) continue;
|
|
1533
|
+
detections.push({ start: m.index, end: m.index + m[0].length, type: "IBAN", text: m[0] });
|
|
1139
1534
|
}
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1535
|
+
const ccRe = /(?:\b\d[\d -]{10,22}\d\b)/g;
|
|
1536
|
+
for (const m of text.matchAll(ccRe)) {
|
|
1537
|
+
if (m.index == null) continue;
|
|
1538
|
+
const digits = countDigits2(m[0]);
|
|
1539
|
+
if (digits < 12 || digits > 19) continue;
|
|
1540
|
+
if (!luhnCheck(m[0])) continue;
|
|
1541
|
+
detections.push({ start: m.index, end: m.index + m[0].length, type: "CREDIT_CARD", text: m[0] });
|
|
1542
|
+
}
|
|
1543
|
+
const phoneRe = /(?<!\d)(?:\+?\d[\d\s().-]{7,}\d)(?!\d)/g;
|
|
1544
|
+
for (const m of text.matchAll(phoneRe)) {
|
|
1545
|
+
if (m.index == null) continue;
|
|
1546
|
+
const candidate = m[0];
|
|
1547
|
+
const digits = countDigits2(candidate);
|
|
1548
|
+
if (digits < 9 || digits > 15) continue;
|
|
1549
|
+
const isStrongInternational = candidate.startsWith("+") || candidate.startsWith("00");
|
|
1550
|
+
if (!isStrongInternational) {
|
|
1551
|
+
const hasContext = hasPhoneContext(text, m.index);
|
|
1552
|
+
if (!hasContext) continue;
|
|
1553
|
+
}
|
|
1554
|
+
detections.push({ start: m.index, end: m.index + m[0].length, type: "PHONE", text: m[0] });
|
|
1555
|
+
}
|
|
1556
|
+
const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
|
|
1557
|
+
for (const m of text.matchAll(personRe)) {
|
|
1558
|
+
if (m.index == null) continue;
|
|
1559
|
+
const candidate = m[0];
|
|
1560
|
+
const contextWindow = buildContextWindow(text, m.index, candidate.length);
|
|
1561
|
+
if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
|
|
1562
|
+
continue;
|
|
1563
|
+
}
|
|
1564
|
+
detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
|
|
1565
|
+
}
|
|
1566
|
+
BIRTH_NUMBER_CONTEXT_RE.lastIndex = 0;
|
|
1567
|
+
for (const match of text.matchAll(BIRTH_NUMBER_CONTEXT_RE)) {
|
|
1568
|
+
if (match.index == null) continue;
|
|
1569
|
+
const value = match[1] ?? "";
|
|
1570
|
+
if (!/^\d{6}(?:\/?\d{3,4})?$/.test(value)) continue;
|
|
1571
|
+
const localIndex = match[0].lastIndexOf(value);
|
|
1572
|
+
const start = match.index + Math.max(0, localIndex);
|
|
1573
|
+
detections.push({
|
|
1574
|
+
start,
|
|
1575
|
+
end: start + value.length,
|
|
1576
|
+
type: "BIRTH_NUMBER",
|
|
1577
|
+
text: value
|
|
1578
|
+
});
|
|
1579
|
+
}
|
|
1580
|
+
const nationalIdMatches = detectNationalIdentifiers(text, {
|
|
1581
|
+
deadlineMs: defaultScanDeadlineMs,
|
|
1582
|
+
allowContextBirthNumberFallback: false
|
|
1153
1583
|
});
|
|
1584
|
+
for (const match of nationalIdMatches) {
|
|
1585
|
+
if (match.start < 0 || match.end <= match.start) continue;
|
|
1586
|
+
detections.push({
|
|
1587
|
+
start: match.start,
|
|
1588
|
+
end: match.end,
|
|
1589
|
+
type: "NATIONAL_ID",
|
|
1590
|
+
text: text.slice(match.start, match.end)
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
if (resolvedOptions.secrets) {
|
|
1595
|
+
BASIC_AUTH_PASSWORD_RE.lastIndex = 0;
|
|
1596
|
+
for (const match of text.matchAll(BASIC_AUTH_PASSWORD_RE)) {
|
|
1597
|
+
if (match.index == null) continue;
|
|
1598
|
+
const password = match[1] ?? "";
|
|
1599
|
+
if (!password) continue;
|
|
1600
|
+
const localIndex = match[0].lastIndexOf(password);
|
|
1601
|
+
const start = match.index + Math.max(0, localIndex);
|
|
1602
|
+
detections.push({
|
|
1603
|
+
start,
|
|
1604
|
+
end: start + password.length,
|
|
1605
|
+
type: "BASIC_AUTH_PASSWORD",
|
|
1606
|
+
text: password
|
|
1607
|
+
});
|
|
1608
|
+
}
|
|
1609
|
+
DISCORD_WEBHOOK_TOKEN_RE.lastIndex = 0;
|
|
1610
|
+
for (const match of text.matchAll(DISCORD_WEBHOOK_TOKEN_RE)) {
|
|
1611
|
+
if (match.index == null) continue;
|
|
1612
|
+
const token = match[1] ?? "";
|
|
1613
|
+
if (!token) continue;
|
|
1614
|
+
const localIndex = match[0].lastIndexOf(token);
|
|
1615
|
+
const start = match.index + Math.max(0, localIndex);
|
|
1616
|
+
detections.push({
|
|
1617
|
+
start,
|
|
1618
|
+
end: start + token.length,
|
|
1619
|
+
type: "DISCORD_WEBHOOK_TOKEN",
|
|
1620
|
+
text: token
|
|
1621
|
+
});
|
|
1622
|
+
}
|
|
1623
|
+
for (const matcher of sdkSecretMatchers) {
|
|
1624
|
+
if (matcher.id === "discord_webhook_url") {
|
|
1625
|
+
continue;
|
|
1626
|
+
}
|
|
1627
|
+
if (matcher.prefilterTermsLower.length > 0 && !matcher.prefilterTermsLower.some((term) => loweredText.includes(term))) {
|
|
1628
|
+
continue;
|
|
1629
|
+
}
|
|
1630
|
+
matcher.scanRegex.lastIndex = 0;
|
|
1631
|
+
for (const match of text.matchAll(matcher.scanRegex)) {
|
|
1632
|
+
if (match.index == null) continue;
|
|
1633
|
+
detections.push({
|
|
1634
|
+
start: match.index,
|
|
1635
|
+
end: match.index + match[0].length,
|
|
1636
|
+
type: matcher.placeholderType,
|
|
1637
|
+
text: match[0]
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1154
1641
|
}
|
|
1155
1642
|
const kept = normalizeDetections(text, detections);
|
|
1156
1643
|
if (!kept.length) return { maskedText: text, mapping: {} };
|
|
@@ -1195,7 +1682,9 @@ var DEFAULT_FAIL_OPEN_CONFIG = {
|
|
|
1195
1682
|
block_on_heuristic: false,
|
|
1196
1683
|
inject_transparency_metadata: false,
|
|
1197
1684
|
block_pii_leakage: false,
|
|
1198
|
-
enable_sdk_pii_masking:
|
|
1685
|
+
enable_sdk_pii_masking: true,
|
|
1686
|
+
block_secret_leakage: false,
|
|
1687
|
+
enable_sdk_secret_masking: true,
|
|
1199
1688
|
block_db_access: false,
|
|
1200
1689
|
block_code_execution: false,
|
|
1201
1690
|
block_toxicity: false
|
|
@@ -1237,11 +1726,11 @@ function detectCapabilityViolation(text, config) {
|
|
|
1237
1726
|
}
|
|
1238
1727
|
return null;
|
|
1239
1728
|
}
|
|
1240
|
-
function redactPiiStrict(pii, text) {
|
|
1729
|
+
function redactPiiStrict(pii, text, options) {
|
|
1241
1730
|
if (!text) {
|
|
1242
1731
|
return { redactedText: text, changed: false };
|
|
1243
1732
|
}
|
|
1244
|
-
const masked = pii.anonymize(text);
|
|
1733
|
+
const masked = pii.anonymize(text, options);
|
|
1245
1734
|
let redactedText = masked.maskedText;
|
|
1246
1735
|
const placeholders = Object.keys(masked.mapping).sort((a, b) => b.length - a.length);
|
|
1247
1736
|
for (const placeholder of placeholders) {
|
|
@@ -1270,7 +1759,7 @@ var LocalSecurityEnforcer = class {
|
|
|
1270
1759
|
`AgentID: Security policy blocked (${violationType})`
|
|
1271
1760
|
);
|
|
1272
1761
|
}
|
|
1273
|
-
if (!config.block_pii_leakage) {
|
|
1762
|
+
if (!config.block_pii_leakage && !config.block_secret_leakage) {
|
|
1274
1763
|
return {
|
|
1275
1764
|
sanitizedInput: input,
|
|
1276
1765
|
events: []
|
|
@@ -1280,10 +1769,13 @@ var LocalSecurityEnforcer = class {
|
|
|
1280
1769
|
throw new SecurityPolicyViolationError(
|
|
1281
1770
|
"PII_LEAKAGE_STRICT",
|
|
1282
1771
|
"BLOCKED",
|
|
1283
|
-
"AgentID: Streaming is not supported when
|
|
1772
|
+
"AgentID: Streaming is not supported when strict masking/blocking mode is enabled. Please disable streaming or adjust security settings."
|
|
1284
1773
|
);
|
|
1285
1774
|
}
|
|
1286
|
-
const strictRedaction = redactPiiStrict(this.pii, input
|
|
1775
|
+
const strictRedaction = redactPiiStrict(this.pii, input, {
|
|
1776
|
+
pii: config.block_pii_leakage,
|
|
1777
|
+
secrets: config.block_secret_leakage
|
|
1778
|
+
});
|
|
1287
1779
|
return {
|
|
1288
1780
|
sanitizedInput: strictRedaction.redactedText,
|
|
1289
1781
|
events: strictRedaction.changed ? [
|
|
@@ -1409,6 +1901,16 @@ function normalizeCapabilityConfig(payload) {
|
|
|
1409
1901
|
"enable_sdk_pii_masking",
|
|
1410
1902
|
false
|
|
1411
1903
|
),
|
|
1904
|
+
block_secret_leakage: readOptionalBooleanField(
|
|
1905
|
+
body,
|
|
1906
|
+
"block_secret_leakage",
|
|
1907
|
+
false
|
|
1908
|
+
),
|
|
1909
|
+
enable_sdk_secret_masking: readOptionalBooleanField(
|
|
1910
|
+
body,
|
|
1911
|
+
"enable_sdk_secret_masking",
|
|
1912
|
+
false
|
|
1913
|
+
),
|
|
1412
1914
|
block_db_access: readBooleanField(body, "block_db_access", "block_db"),
|
|
1413
1915
|
block_code_execution: readBooleanField(
|
|
1414
1916
|
body,
|
|
@@ -2069,14 +2571,14 @@ async function reportSecurityEvent(options) {
|
|
|
2069
2571
|
const inputValue = options.storePii ? snippet : snippetHash;
|
|
2070
2572
|
const eventId = createEventId(options.eventId ?? options.clientEventId);
|
|
2071
2573
|
const metadata = {
|
|
2574
|
+
...options.telemetryMetadata ?? {},
|
|
2072
2575
|
source: options.source,
|
|
2073
2576
|
detector: options.detector,
|
|
2074
2577
|
trigger_rule: options.triggerRule,
|
|
2075
2578
|
language: options.language,
|
|
2076
2579
|
ai_scan_status: options.aiStatus ?? null,
|
|
2077
2580
|
reason: options.reason ?? null,
|
|
2078
|
-
client_event_id: eventId
|
|
2079
|
-
...options.telemetryMetadata ?? {}
|
|
2581
|
+
client_event_id: eventId
|
|
2080
2582
|
};
|
|
2081
2583
|
if (options.storePii) {
|
|
2082
2584
|
metadata.snippet = snippet;
|
|
@@ -2248,9 +2750,18 @@ var INGEST_MAX_ATTEMPTS = 3;
|
|
|
2248
2750
|
var INGEST_RETRY_DELAYS_MS = [250, 500];
|
|
2249
2751
|
var GUARD_VERDICT_CACHE_TTL_MS = 0;
|
|
2250
2752
|
var MAX_INGEST_TEXT_CHARS = 32e3;
|
|
2753
|
+
var OPENAI_TELEMETRY_FIELD = "agentid_telemetry";
|
|
2251
2754
|
function normalizeBaseUrl3(baseUrl) {
|
|
2252
2755
|
return baseUrl.replace(/\/+$/, "");
|
|
2253
2756
|
}
|
|
2757
|
+
function firstNonEmptyString(...values) {
|
|
2758
|
+
for (const value of values) {
|
|
2759
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
2760
|
+
return value.trim();
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
return void 0;
|
|
2764
|
+
}
|
|
2254
2765
|
function isAbortSignalLike(value) {
|
|
2255
2766
|
if (!value || typeof value !== "object") return false;
|
|
2256
2767
|
const candidate = value;
|
|
@@ -2412,6 +2923,424 @@ function createCorrelationId(seed) {
|
|
|
2412
2923
|
}
|
|
2413
2924
|
return createPseudoUuidV42();
|
|
2414
2925
|
}
|
|
2926
|
+
function getObjectString(value, ...keys) {
|
|
2927
|
+
for (const key of keys) {
|
|
2928
|
+
const candidate = value?.[key];
|
|
2929
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
2930
|
+
return candidate.trim();
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
return void 0;
|
|
2934
|
+
}
|
|
2935
|
+
function getObjectNumber(value, ...keys) {
|
|
2936
|
+
for (const key of keys) {
|
|
2937
|
+
const candidate = value?.[key];
|
|
2938
|
+
if (typeof candidate === "number" && Number.isFinite(candidate)) {
|
|
2939
|
+
return candidate;
|
|
2940
|
+
}
|
|
2941
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
2942
|
+
const parsed = Number(candidate);
|
|
2943
|
+
if (Number.isFinite(parsed)) {
|
|
2944
|
+
return parsed;
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
return void 0;
|
|
2949
|
+
}
|
|
2950
|
+
function normalizeTelemetryString(value) {
|
|
2951
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
2952
|
+
}
|
|
2953
|
+
function normalizeTelemetryCategory(value) {
|
|
2954
|
+
const normalized = normalizeTelemetryString(value);
|
|
2955
|
+
if (!normalized) return void 0;
|
|
2956
|
+
return normalized.toLowerCase().replace(/[\s-]+/g, "_");
|
|
2957
|
+
}
|
|
2958
|
+
function toSnakeToken(value) {
|
|
2959
|
+
return value.trim().replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_").toLowerCase();
|
|
2960
|
+
}
|
|
2961
|
+
function hasUsageSignals(value) {
|
|
2962
|
+
if (!value) return false;
|
|
2963
|
+
for (const entry of Object.values(value)) {
|
|
2964
|
+
if (typeof entry === "number" && Number.isFinite(entry) && entry > 0) {
|
|
2965
|
+
return true;
|
|
2966
|
+
}
|
|
2967
|
+
if (typeof entry === "string" && entry.trim().length > 0) {
|
|
2968
|
+
const parsed = Number(entry);
|
|
2969
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
2970
|
+
return true;
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
return false;
|
|
2975
|
+
}
|
|
2976
|
+
function truncatePromptPreflightPreview(value, maxChars = 280) {
|
|
2977
|
+
const normalized = value.trim();
|
|
2978
|
+
if (normalized.length <= maxChars) {
|
|
2979
|
+
return normalized;
|
|
2980
|
+
}
|
|
2981
|
+
return `${normalized.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
|
|
2982
|
+
}
|
|
2983
|
+
function formatPromptPreflightReason(reason) {
|
|
2984
|
+
const normalized = normalizeTelemetryString(reason);
|
|
2985
|
+
if (!normalized) {
|
|
2986
|
+
return void 0;
|
|
2987
|
+
}
|
|
2988
|
+
return normalized.replace(/[_-]+/g, " ");
|
|
2989
|
+
}
|
|
2990
|
+
function summarizePromptPreflightResult(params) {
|
|
2991
|
+
const reason = formatPromptPreflightReason(
|
|
2992
|
+
params.localFallbackApplied ? params.localFallbackReason ?? void 0 : params.verdict.reason
|
|
2993
|
+
) ?? "policy evaluation";
|
|
2994
|
+
if (!params.verdict.allowed && !params.localFallbackApplied) {
|
|
2995
|
+
return `Blocked the prompt before model execution because ${reason}.`;
|
|
2996
|
+
}
|
|
2997
|
+
if (params.localFallbackApplied) {
|
|
2998
|
+
return `Guard preflight degraded, so the SDK applied local fallback checks before model execution (${reason}).`;
|
|
2999
|
+
}
|
|
3000
|
+
if (params.verdict.shadow_mode && params.verdict.shadow_blocked) {
|
|
3001
|
+
return "Evaluated the prompt in shadow mode before model execution; shadow policy would have blocked it.";
|
|
3002
|
+
}
|
|
3003
|
+
if (params.verdict.simulated_decision === "masked" || params.verdict.detected_pii) {
|
|
3004
|
+
return "Evaluated the prompt before model execution and masked sensitive content where needed.";
|
|
3005
|
+
}
|
|
3006
|
+
return "Evaluated the prompt and attachments against guardrails before model execution.";
|
|
3007
|
+
}
|
|
3008
|
+
function buildPromptPreflightTelemetry(params) {
|
|
3009
|
+
const baseTelemetry = createAgentIdTelemetryContext(params.telemetry);
|
|
3010
|
+
const baseStepName = firstNonEmptyString(
|
|
3011
|
+
baseTelemetry?.workflow_step_name,
|
|
3012
|
+
baseTelemetry?.workflowStepName
|
|
3013
|
+
);
|
|
3014
|
+
const stepName = baseStepName ? `${toSnakeToken(baseStepName)}_preflight` : "prompt_preflight";
|
|
3015
|
+
const summary = summarizePromptPreflightResult({
|
|
3016
|
+
verdict: params.verdict,
|
|
3017
|
+
localFallbackApplied: params.local_fallback_applied,
|
|
3018
|
+
localFallbackReason: params.local_fallback_reason
|
|
3019
|
+
});
|
|
3020
|
+
return mergeTelemetryContexts(baseTelemetry, {
|
|
3021
|
+
workflow_step_id: createAgentIdCorrelationId(),
|
|
3022
|
+
workflow_step_name: stepName,
|
|
3023
|
+
event_title: "Prompt Preflight Evaluated",
|
|
3024
|
+
event_category: "guard",
|
|
3025
|
+
event_subtype: "prompt_preflight_evaluated",
|
|
3026
|
+
event_status: !params.verdict.allowed && !params.local_fallback_applied ? "blocked" : "completed",
|
|
3027
|
+
step_summary: summary,
|
|
3028
|
+
input_preview: truncatePromptPreflightPreview(params.input),
|
|
3029
|
+
output_preview: summary,
|
|
3030
|
+
runtime_surface: params.runtime_surface ?? "openai_sdk_guard",
|
|
3031
|
+
guard_event_id: params.guard_event_id ?? void 0,
|
|
3032
|
+
guard_latency_ms: params.guard_latency_ms ?? void 0,
|
|
3033
|
+
preflight_for_client_event_id: params.preflight_for_client_event_id,
|
|
3034
|
+
preflight_logged_via_sdk: true,
|
|
3035
|
+
lifecycle_status: "preflight_only"
|
|
3036
|
+
});
|
|
3037
|
+
}
|
|
3038
|
+
function inferOperationCategory(telemetry, eventType) {
|
|
3039
|
+
const explicitCategory = normalizeTelemetryCategory(
|
|
3040
|
+
telemetry?.event_category ?? telemetry?.eventCategory
|
|
3041
|
+
);
|
|
3042
|
+
if (explicitCategory === "ai" || explicitCategory === "llm" || explicitCategory === "inference") {
|
|
3043
|
+
return "ai";
|
|
3044
|
+
}
|
|
3045
|
+
if (explicitCategory === "guard" || explicitCategory === "security") {
|
|
3046
|
+
return "guard";
|
|
3047
|
+
}
|
|
3048
|
+
if (explicitCategory === "tool") return "tool";
|
|
3049
|
+
if (explicitCategory === "delivery" || explicitCategory === "send") return "delivery";
|
|
3050
|
+
if (explicitCategory === "inbox" || explicitCategory === "reply") return "inbox";
|
|
3051
|
+
if (explicitCategory === "workflow" || explicitCategory === "agent") return "workflow";
|
|
3052
|
+
if (explicitCategory === "compliance" || explicitCategory === "transparency") {
|
|
3053
|
+
return "compliance";
|
|
3054
|
+
}
|
|
3055
|
+
if (explicitCategory === "operational" || explicitCategory === "ops") {
|
|
3056
|
+
return "operational";
|
|
3057
|
+
}
|
|
3058
|
+
const haystack = [
|
|
3059
|
+
eventType,
|
|
3060
|
+
telemetry?.event_subtype,
|
|
3061
|
+
telemetry?.eventSubtype,
|
|
3062
|
+
telemetry?.tool_name,
|
|
3063
|
+
telemetry?.toolName,
|
|
3064
|
+
telemetry?.tool_target_type,
|
|
3065
|
+
telemetry?.toolTargetType,
|
|
3066
|
+
telemetry?.workflow_name,
|
|
3067
|
+
telemetry?.workflowName,
|
|
3068
|
+
telemetry?.workflow_step_name,
|
|
3069
|
+
telemetry?.workflowStepName,
|
|
3070
|
+
getObjectString(telemetry, "operation_family", "domain")
|
|
3071
|
+
].filter((entry) => typeof entry === "string" && entry.trim().length > 0).join(" ").replace(/[_./-]+/g, " ").toLowerCase();
|
|
3072
|
+
if (/\b(llm|ai|inference|completion|summary|classification|draft)\b/.test(haystack)) {
|
|
3073
|
+
return "ai";
|
|
3074
|
+
}
|
|
3075
|
+
if (/\b(guard|security|policy|pii|prompt[_ ]?injection|review)\b/.test(haystack)) {
|
|
3076
|
+
return "guard";
|
|
3077
|
+
}
|
|
3078
|
+
if (/\b(reply|inbox|inbound|received|bounce|opened|followup)\b/.test(haystack)) {
|
|
3079
|
+
return "inbox";
|
|
3080
|
+
}
|
|
3081
|
+
if (/\b(email|mail|send|delivery|delivered|slack|sms|webhook|notification)\b/.test(haystack)) {
|
|
3082
|
+
return "delivery";
|
|
3083
|
+
}
|
|
3084
|
+
if (/\b(workflow|step|run|agent)\b/.test(haystack)) {
|
|
3085
|
+
return "workflow";
|
|
3086
|
+
}
|
|
3087
|
+
if (/\b(compliance|transparency|audit|evidence)\b/.test(haystack)) {
|
|
3088
|
+
return "compliance";
|
|
3089
|
+
}
|
|
3090
|
+
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(
|
|
3091
|
+
haystack
|
|
3092
|
+
)) {
|
|
3093
|
+
return "tool";
|
|
3094
|
+
}
|
|
3095
|
+
return "operational";
|
|
3096
|
+
}
|
|
3097
|
+
function inferOperationStatus(params) {
|
|
3098
|
+
const explicitStatus = normalizeTelemetryString(params.eventStatus)?.toLowerCase();
|
|
3099
|
+
if (explicitStatus === "started" || explicitStatus === "completed" || explicitStatus === "failed") {
|
|
3100
|
+
return explicitStatus;
|
|
3101
|
+
}
|
|
3102
|
+
if (explicitStatus === "blocked" || explicitStatus === "skipped") {
|
|
3103
|
+
return explicitStatus;
|
|
3104
|
+
}
|
|
3105
|
+
const normalizedEventType = normalizeTelemetryString(params.eventType)?.toLowerCase();
|
|
3106
|
+
if (normalizedEventType === "start") return "started";
|
|
3107
|
+
if (normalizedEventType === "error") return "failed";
|
|
3108
|
+
if (normalizedEventType === "security_block") return "blocked";
|
|
3109
|
+
if (normalizedEventType === "human_override") return "completed";
|
|
3110
|
+
if (normalizedEventType === "complete") return "completed";
|
|
3111
|
+
return params.severity === "error" ? "failed" : "completed";
|
|
3112
|
+
}
|
|
3113
|
+
function deriveOperationEventType(params) {
|
|
3114
|
+
const explicit = normalizeTelemetryString(params.explicitEventType);
|
|
3115
|
+
if (explicit) {
|
|
3116
|
+
return explicit;
|
|
3117
|
+
}
|
|
3118
|
+
if (params.status === "started") return "start";
|
|
3119
|
+
if (params.status === "failed") return "error";
|
|
3120
|
+
if (params.status === "blocked") {
|
|
3121
|
+
return params.category === "guard" ? "security_block" : "error";
|
|
3122
|
+
}
|
|
3123
|
+
return "complete";
|
|
3124
|
+
}
|
|
3125
|
+
function deriveSubtypeBase(telemetry) {
|
|
3126
|
+
const toolName = normalizeTelemetryString(telemetry?.tool_name ?? telemetry?.toolName);
|
|
3127
|
+
if (toolName) {
|
|
3128
|
+
const tokens = toSnakeToken(toolName).split("_").filter(Boolean);
|
|
3129
|
+
if (tokens.length > 1 && ["workflow", "agent", "operation", "ops", "hr", "finance", "compliance"].includes(tokens[0])) {
|
|
3130
|
+
return tokens.slice(1).join("_");
|
|
3131
|
+
}
|
|
3132
|
+
return tokens.join("_");
|
|
3133
|
+
}
|
|
3134
|
+
const workflowName = normalizeTelemetryString(
|
|
3135
|
+
telemetry?.workflow_step_name ?? telemetry?.workflowStepName ?? telemetry?.workflow_name ?? telemetry?.workflowName
|
|
3136
|
+
);
|
|
3137
|
+
if (workflowName) {
|
|
3138
|
+
return toSnakeToken(workflowName);
|
|
3139
|
+
}
|
|
3140
|
+
return void 0;
|
|
3141
|
+
}
|
|
3142
|
+
function deriveOperationSubtype(params) {
|
|
3143
|
+
const explicitSubtype = normalizeTelemetryString(params.explicitSubtype);
|
|
3144
|
+
if (explicitSubtype) {
|
|
3145
|
+
return toSnakeToken(explicitSubtype);
|
|
3146
|
+
}
|
|
3147
|
+
const base = deriveSubtypeBase(params.telemetry);
|
|
3148
|
+
const suffix = params.status === "started" ? "started" : params.status === "failed" ? "failed" : params.status === "blocked" ? "blocked" : params.status === "skipped" ? "skipped" : "completed";
|
|
3149
|
+
if (base) {
|
|
3150
|
+
return `${base}_${suffix}`;
|
|
3151
|
+
}
|
|
3152
|
+
if (params.eventType === "start") return `${params.category}_started`;
|
|
3153
|
+
if (params.eventType === "error") return `${params.category}_failed`;
|
|
3154
|
+
if (params.eventType === "security_block") return `${params.category}_blocked`;
|
|
3155
|
+
return `${params.category}_completed`;
|
|
3156
|
+
}
|
|
3157
|
+
function inferOperationSeverity(params) {
|
|
3158
|
+
if (params.explicitSeverity) {
|
|
3159
|
+
return params.explicitSeverity;
|
|
3160
|
+
}
|
|
3161
|
+
if (params.status === "failed" || params.status === "blocked") {
|
|
3162
|
+
return "error";
|
|
3163
|
+
}
|
|
3164
|
+
if (params.status === "skipped") {
|
|
3165
|
+
return "warning";
|
|
3166
|
+
}
|
|
3167
|
+
return "info";
|
|
3168
|
+
}
|
|
3169
|
+
function createAgentIdCorrelationId(seed) {
|
|
3170
|
+
return createCorrelationId(seed);
|
|
3171
|
+
}
|
|
3172
|
+
function createAgentIdTelemetryContext(value) {
|
|
3173
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3174
|
+
return void 0;
|
|
3175
|
+
}
|
|
3176
|
+
const raw = { ...value };
|
|
3177
|
+
const normalized = {};
|
|
3178
|
+
const assignString = (key, ...aliases) => {
|
|
3179
|
+
const next = getObjectString(raw, key, ...aliases);
|
|
3180
|
+
if (next) {
|
|
3181
|
+
normalized[key] = next;
|
|
3182
|
+
}
|
|
3183
|
+
};
|
|
3184
|
+
const assignNumber = (key, ...aliases) => {
|
|
3185
|
+
const next = getObjectNumber(raw, key, ...aliases);
|
|
3186
|
+
if (typeof next === "number") {
|
|
3187
|
+
normalized[key] = next;
|
|
3188
|
+
}
|
|
3189
|
+
};
|
|
3190
|
+
assignString("workflow_id", "workflowId");
|
|
3191
|
+
assignString("workflow_run_id", "workflowRunId");
|
|
3192
|
+
assignString("workflow_step_id", "workflowStepId");
|
|
3193
|
+
assignString("workflow_name", "workflowName");
|
|
3194
|
+
assignString("workflow_step_name", "workflowStepName");
|
|
3195
|
+
assignNumber("workflow_step_index", "workflowStepIndex");
|
|
3196
|
+
assignString("parent_event_id", "parentEventId");
|
|
3197
|
+
assignString("tool_name", "toolName");
|
|
3198
|
+
assignString("tool_target", "toolTarget");
|
|
3199
|
+
assignString("tool_target_type", "toolTargetType");
|
|
3200
|
+
assignString("event_title", "eventTitle");
|
|
3201
|
+
assignString("event_status", "eventStatus");
|
|
3202
|
+
assignString("event_category", "eventCategory");
|
|
3203
|
+
assignString("event_subtype", "eventSubtype");
|
|
3204
|
+
const consumedKeys = /* @__PURE__ */ new Set([
|
|
3205
|
+
"workflow_id",
|
|
3206
|
+
"workflowId",
|
|
3207
|
+
"workflow_run_id",
|
|
3208
|
+
"workflowRunId",
|
|
3209
|
+
"workflow_step_id",
|
|
3210
|
+
"workflowStepId",
|
|
3211
|
+
"workflow_name",
|
|
3212
|
+
"workflowName",
|
|
3213
|
+
"workflow_step_name",
|
|
3214
|
+
"workflowStepName",
|
|
3215
|
+
"workflow_step_index",
|
|
3216
|
+
"workflowStepIndex",
|
|
3217
|
+
"parent_event_id",
|
|
3218
|
+
"parentEventId",
|
|
3219
|
+
"tool_name",
|
|
3220
|
+
"toolName",
|
|
3221
|
+
"tool_target",
|
|
3222
|
+
"toolTarget",
|
|
3223
|
+
"tool_target_type",
|
|
3224
|
+
"toolTargetType",
|
|
3225
|
+
"event_title",
|
|
3226
|
+
"eventTitle",
|
|
3227
|
+
"event_status",
|
|
3228
|
+
"eventStatus",
|
|
3229
|
+
"event_category",
|
|
3230
|
+
"eventCategory",
|
|
3231
|
+
"event_subtype",
|
|
3232
|
+
"eventSubtype"
|
|
3233
|
+
]);
|
|
3234
|
+
for (const [key, entry] of Object.entries(raw)) {
|
|
3235
|
+
if (consumedKeys.has(key) || entry === void 0) {
|
|
3236
|
+
continue;
|
|
3237
|
+
}
|
|
3238
|
+
if (typeof entry === "string") {
|
|
3239
|
+
if (entry.trim().length > 0) {
|
|
3240
|
+
normalized[key] = entry.trim();
|
|
3241
|
+
}
|
|
3242
|
+
continue;
|
|
3243
|
+
}
|
|
3244
|
+
normalized[key] = entry;
|
|
3245
|
+
}
|
|
3246
|
+
if (typeof normalized.workflow_id !== "string" && typeof normalized.workflow_run_id === "string") {
|
|
3247
|
+
normalized.workflow_id = normalized.workflow_run_id;
|
|
3248
|
+
}
|
|
3249
|
+
return Object.keys(normalized).length > 0 ? normalized : void 0;
|
|
3250
|
+
}
|
|
3251
|
+
function createAgentIdOperationLog(params) {
|
|
3252
|
+
const telemetry = createAgentIdTelemetryContext(params.telemetry);
|
|
3253
|
+
const category = inferOperationCategory(
|
|
3254
|
+
createAgentIdTelemetryContext({
|
|
3255
|
+
...telemetry ?? {},
|
|
3256
|
+
event_category: params.event_category ?? telemetry?.event_category
|
|
3257
|
+
}),
|
|
3258
|
+
params.event_type
|
|
3259
|
+
);
|
|
3260
|
+
const status = inferOperationStatus({
|
|
3261
|
+
eventStatus: normalizeTelemetryString(params.event_status) ?? normalizeTelemetryString(telemetry?.event_status ?? telemetry?.eventStatus),
|
|
3262
|
+
eventType: params.event_type,
|
|
3263
|
+
severity: params.severity
|
|
3264
|
+
});
|
|
3265
|
+
const eventType = deriveOperationEventType({
|
|
3266
|
+
explicitEventType: params.event_type,
|
|
3267
|
+
status,
|
|
3268
|
+
category
|
|
3269
|
+
});
|
|
3270
|
+
const subtype = deriveOperationSubtype({
|
|
3271
|
+
explicitSubtype: normalizeTelemetryString(params.event_subtype) ?? normalizeTelemetryString(telemetry?.event_subtype ?? telemetry?.eventSubtype),
|
|
3272
|
+
telemetry,
|
|
3273
|
+
category,
|
|
3274
|
+
status,
|
|
3275
|
+
eventType
|
|
3276
|
+
});
|
|
3277
|
+
const severity = inferOperationSeverity({
|
|
3278
|
+
explicitSeverity: params.severity,
|
|
3279
|
+
status
|
|
3280
|
+
});
|
|
3281
|
+
const usage = params.usage;
|
|
3282
|
+
const clientEventId = normalizeTelemetryString(params.client_event_id) ?? normalizeTelemetryString(telemetry?.client_event_id);
|
|
3283
|
+
const modelUsed = category === "ai" || hasUsageSignals(usage) || typeof params.model === "string" && params.model.trim().length > 0 && params.model.trim().toLowerCase() !== "not_applicable";
|
|
3284
|
+
const metadata = {
|
|
3285
|
+
...params.metadata ?? {},
|
|
3286
|
+
...telemetry ?? {},
|
|
3287
|
+
event_category: category,
|
|
3288
|
+
event_subtype: subtype,
|
|
3289
|
+
event_status: status,
|
|
3290
|
+
status,
|
|
3291
|
+
model_used: modelUsed,
|
|
3292
|
+
spend_bearing: category === "ai" && hasUsageSignals(usage)
|
|
3293
|
+
};
|
|
3294
|
+
if (clientEventId && typeof metadata.client_event_id !== "string") {
|
|
3295
|
+
metadata.client_event_id = clientEventId;
|
|
3296
|
+
}
|
|
3297
|
+
return {
|
|
3298
|
+
event_id: normalizeTelemetryString(params.event_id) ?? createEventId2(),
|
|
3299
|
+
system_id: params.system_id,
|
|
3300
|
+
user_id: params.user_id,
|
|
3301
|
+
request_identity: params.request_identity,
|
|
3302
|
+
input: params.input ?? "",
|
|
3303
|
+
output: params.output ?? "",
|
|
3304
|
+
model: normalizeTelemetryString(params.model) ?? "not_applicable",
|
|
3305
|
+
usage,
|
|
3306
|
+
tokens: params.tokens,
|
|
3307
|
+
latency: params.latency,
|
|
3308
|
+
metadata,
|
|
3309
|
+
event_type: eventType,
|
|
3310
|
+
severity,
|
|
3311
|
+
timestamp: params.timestamp,
|
|
3312
|
+
client_capabilities: params.client_capabilities
|
|
3313
|
+
};
|
|
3314
|
+
}
|
|
3315
|
+
function asTelemetryContext(value) {
|
|
3316
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3317
|
+
return void 0;
|
|
3318
|
+
}
|
|
3319
|
+
return createAgentIdTelemetryContext(value);
|
|
3320
|
+
}
|
|
3321
|
+
function mergeTelemetryContexts(...contexts) {
|
|
3322
|
+
const merged = {};
|
|
3323
|
+
let hasValues = false;
|
|
3324
|
+
for (const context of contexts) {
|
|
3325
|
+
if (!context) {
|
|
3326
|
+
continue;
|
|
3327
|
+
}
|
|
3328
|
+
Object.assign(merged, createAgentIdTelemetryContext(context));
|
|
3329
|
+
hasValues = true;
|
|
3330
|
+
}
|
|
3331
|
+
return hasValues ? createAgentIdTelemetryContext(merged) : void 0;
|
|
3332
|
+
}
|
|
3333
|
+
function extractRequestTelemetryContext(requestBody) {
|
|
3334
|
+
return asTelemetryContext(requestBody[OPENAI_TELEMETRY_FIELD]);
|
|
3335
|
+
}
|
|
3336
|
+
function stripRequestTelemetryContext(requestBody) {
|
|
3337
|
+
if (!Object.prototype.hasOwnProperty.call(requestBody, OPENAI_TELEMETRY_FIELD)) {
|
|
3338
|
+
return requestBody;
|
|
3339
|
+
}
|
|
3340
|
+
const nextRequestBody = { ...requestBody };
|
|
3341
|
+
delete nextRequestBody[OPENAI_TELEMETRY_FIELD];
|
|
3342
|
+
return nextRequestBody;
|
|
3343
|
+
}
|
|
2415
3344
|
async function waitForRetry(attemptIndex) {
|
|
2416
3345
|
const delay = GUARD_RETRY_DELAYS_MS[attemptIndex];
|
|
2417
3346
|
if (!delay) return;
|
|
@@ -2591,6 +3520,61 @@ function createStreamingPlaceholderRewriter(piiManager, mapping) {
|
|
|
2591
3520
|
}
|
|
2592
3521
|
};
|
|
2593
3522
|
}
|
|
3523
|
+
var TYPED_PLACEHOLDER_RE = /<[A-Z][A-Z0-9_]*_\d+>/g;
|
|
3524
|
+
function derivePlaceholderMappingFromTransform(source, transformed) {
|
|
3525
|
+
if (!source || !transformed || source === transformed) {
|
|
3526
|
+
return {};
|
|
3527
|
+
}
|
|
3528
|
+
const placeholders = [...transformed.matchAll(TYPED_PLACEHOLDER_RE)].map((match) => ({
|
|
3529
|
+
token: match[0],
|
|
3530
|
+
start: match.index ?? 0,
|
|
3531
|
+
end: (match.index ?? 0) + match[0].length
|
|
3532
|
+
}));
|
|
3533
|
+
if (placeholders.length === 0) {
|
|
3534
|
+
return {};
|
|
3535
|
+
}
|
|
3536
|
+
const mapping = {};
|
|
3537
|
+
let sourceCursor = 0;
|
|
3538
|
+
let transformedCursor = 0;
|
|
3539
|
+
for (const placeholder of placeholders) {
|
|
3540
|
+
const literalBefore = transformed.slice(transformedCursor, placeholder.start);
|
|
3541
|
+
if (literalBefore) {
|
|
3542
|
+
const literalIndex = source.indexOf(literalBefore, sourceCursor);
|
|
3543
|
+
if (literalIndex < 0) {
|
|
3544
|
+
return {};
|
|
3545
|
+
}
|
|
3546
|
+
sourceCursor = literalIndex + literalBefore.length;
|
|
3547
|
+
}
|
|
3548
|
+
const nextPlaceholderStart = placeholders.find((candidate) => candidate.start > placeholder.start)?.start ?? transformed.length;
|
|
3549
|
+
const literalAfter = transformed.slice(placeholder.end, nextPlaceholderStart);
|
|
3550
|
+
const nextLiteralIndex = literalAfter ? source.indexOf(literalAfter, sourceCursor) : nextPlaceholderStart >= transformed.length ? source.length : sourceCursor;
|
|
3551
|
+
if (nextLiteralIndex < sourceCursor) {
|
|
3552
|
+
return {};
|
|
3553
|
+
}
|
|
3554
|
+
const originalValue = source.slice(sourceCursor, nextLiteralIndex);
|
|
3555
|
+
if (originalValue.length > 0 && typeof mapping[placeholder.token] !== "string") {
|
|
3556
|
+
mapping[placeholder.token] = originalValue;
|
|
3557
|
+
}
|
|
3558
|
+
sourceCursor = nextLiteralIndex;
|
|
3559
|
+
transformedCursor = placeholder.end;
|
|
3560
|
+
}
|
|
3561
|
+
return mapping;
|
|
3562
|
+
}
|
|
3563
|
+
function mergePiiMappings(primary, fallback) {
|
|
3564
|
+
const merged = { ...primary };
|
|
3565
|
+
for (const [placeholder, value] of Object.entries(fallback)) {
|
|
3566
|
+
if (typeof merged[placeholder] !== "string" && typeof value === "string") {
|
|
3567
|
+
merged[placeholder] = value;
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
return merged;
|
|
3571
|
+
}
|
|
3572
|
+
function textContainsMappingPlaceholder(text, mapping) {
|
|
3573
|
+
if (!text || !mapping) {
|
|
3574
|
+
return false;
|
|
3575
|
+
}
|
|
3576
|
+
return Object.keys(mapping).some((placeholder) => placeholder.length > 0 && text.includes(placeholder));
|
|
3577
|
+
}
|
|
2594
3578
|
var SecurityBlockError = class extends Error {
|
|
2595
3579
|
constructor(reason = "guard_denied") {
|
|
2596
3580
|
super(`AgentID: Security Blocked (${reason})`);
|
|
@@ -2615,6 +3599,7 @@ var AgentID = class {
|
|
|
2615
3599
|
this.apiKey = resolveConfiguredApiKey(config.apiKey);
|
|
2616
3600
|
this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
|
|
2617
3601
|
this.configuredPiiMasking = typeof config.piiMasking === "boolean" ? config.piiMasking : null;
|
|
3602
|
+
this.configuredSecretMasking = typeof config.secretMasking === "boolean" ? config.secretMasking : null;
|
|
2618
3603
|
this.checkInjection = config.checkInjection !== false;
|
|
2619
3604
|
this.clientFastFail = config.clientFastFail === true || config.client_fast_fail === true;
|
|
2620
3605
|
this.aiScanEnabled = config.aiScanEnabled !== false;
|
|
@@ -2636,6 +3621,9 @@ var AgentID = class {
|
|
|
2636
3621
|
get piiMasking() {
|
|
2637
3622
|
return this.configuredPiiMasking ?? void 0;
|
|
2638
3623
|
}
|
|
3624
|
+
get secretMasking() {
|
|
3625
|
+
return this.configuredSecretMasking ?? void 0;
|
|
3626
|
+
}
|
|
2639
3627
|
resolveEffectivePiiMasking(config) {
|
|
2640
3628
|
if (config?.enable_sdk_pii_masking === true) {
|
|
2641
3629
|
return true;
|
|
@@ -2645,12 +3633,24 @@ var AgentID = class {
|
|
|
2645
3633
|
}
|
|
2646
3634
|
return false;
|
|
2647
3635
|
}
|
|
3636
|
+
resolveEffectiveSecretMasking(config) {
|
|
3637
|
+
if (config?.enable_sdk_secret_masking === true || config?.enable_sdk_pii_masking === true) {
|
|
3638
|
+
return true;
|
|
3639
|
+
}
|
|
3640
|
+
if (this.configuredSecretMasking !== null) {
|
|
3641
|
+
return this.configuredSecretMasking;
|
|
3642
|
+
}
|
|
3643
|
+
return false;
|
|
3644
|
+
}
|
|
2648
3645
|
getEffectivePiiMasking(options) {
|
|
2649
3646
|
return this.resolveEffectivePiiMasking(this.getCachedCapabilityConfig(options));
|
|
2650
3647
|
}
|
|
2651
3648
|
getEffectivePiiMaskingForConfig(capabilityConfig) {
|
|
2652
3649
|
return this.resolveEffectivePiiMasking(capabilityConfig);
|
|
2653
3650
|
}
|
|
3651
|
+
getEffectiveSecretMaskingForConfig(capabilityConfig) {
|
|
3652
|
+
return this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3653
|
+
}
|
|
2654
3654
|
buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig) {
|
|
2655
3655
|
return {
|
|
2656
3656
|
capabilities: {
|
|
@@ -2658,6 +3658,9 @@ var AgentID = class {
|
|
|
2658
3658
|
pii_masking_enabled: this.resolveEffectivePiiMasking(
|
|
2659
3659
|
capabilityConfig ?? this.getCachedCapabilityConfig()
|
|
2660
3660
|
),
|
|
3661
|
+
secret_masking_enabled: this.resolveEffectiveSecretMasking(
|
|
3662
|
+
capabilityConfig ?? this.getCachedCapabilityConfig()
|
|
3663
|
+
),
|
|
2661
3664
|
framework
|
|
2662
3665
|
}
|
|
2663
3666
|
};
|
|
@@ -2750,6 +3753,23 @@ var AgentID = class {
|
|
|
2750
3753
|
const config = await this.getCapabilityConfig(false, options);
|
|
2751
3754
|
return config.strict_security_mode || config.failure_mode === "fail_close";
|
|
2752
3755
|
}
|
|
3756
|
+
buildFailOpenGuardVerdict(reason, input, options) {
|
|
3757
|
+
const capabilityConfig = this.getCachedCapabilityConfig(options);
|
|
3758
|
+
const shouldMaskPii = capabilityConfig.block_pii_leakage || this.resolveEffectivePiiMasking(capabilityConfig);
|
|
3759
|
+
const shouldMaskSecrets = capabilityConfig.block_secret_leakage === true || this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3760
|
+
const response = { allowed: true, reason };
|
|
3761
|
+
if (input && (shouldMaskPii || shouldMaskSecrets)) {
|
|
3762
|
+
const masked = this.pii.anonymize(input, {
|
|
3763
|
+
pii: shouldMaskPii,
|
|
3764
|
+
secrets: shouldMaskSecrets
|
|
3765
|
+
});
|
|
3766
|
+
if (masked.maskedText !== input) {
|
|
3767
|
+
response.transformed_input = masked.maskedText;
|
|
3768
|
+
response.detected_pii = Object.keys(masked.mapping).length > 0;
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
return response;
|
|
3772
|
+
}
|
|
2753
3773
|
maybeRaiseStrictIngestDependencyError(params) {
|
|
2754
3774
|
if (params.result.ok) {
|
|
2755
3775
|
return;
|
|
@@ -2797,10 +3817,13 @@ var AgentID = class {
|
|
|
2797
3817
|
systemId: params.systemId,
|
|
2798
3818
|
eventId: params.clientEventId,
|
|
2799
3819
|
clientEventId: params.clientEventId,
|
|
2800
|
-
telemetryMetadata:
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
3820
|
+
telemetryMetadata: mergeTelemetryContexts(
|
|
3821
|
+
params.telemetryMetadata,
|
|
3822
|
+
buildSdkTimingMetadata({
|
|
3823
|
+
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
3824
|
+
sdkConfigVersion: params.capabilityConfig.version
|
|
3825
|
+
})
|
|
3826
|
+
)
|
|
2804
3827
|
});
|
|
2805
3828
|
}
|
|
2806
3829
|
try {
|
|
@@ -2817,7 +3840,8 @@ var AgentID = class {
|
|
|
2817
3840
|
actionTaken: event.actionTaken,
|
|
2818
3841
|
apiKey: params.apiKey,
|
|
2819
3842
|
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
2820
|
-
sdkLocalScanMs
|
|
3843
|
+
sdkLocalScanMs,
|
|
3844
|
+
telemetryMetadata: params.telemetryMetadata
|
|
2821
3845
|
});
|
|
2822
3846
|
}
|
|
2823
3847
|
return {
|
|
@@ -2832,7 +3856,8 @@ var AgentID = class {
|
|
|
2832
3856
|
actionTaken: error.actionTaken,
|
|
2833
3857
|
apiKey: params.apiKey,
|
|
2834
3858
|
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
2835
|
-
sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
|
|
3859
|
+
sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt),
|
|
3860
|
+
telemetryMetadata: params.telemetryMetadata
|
|
2836
3861
|
});
|
|
2837
3862
|
}
|
|
2838
3863
|
throw error;
|
|
@@ -2846,7 +3871,7 @@ var AgentID = class {
|
|
|
2846
3871
|
);
|
|
2847
3872
|
let sanitizedInput = params.input;
|
|
2848
3873
|
let sdkLocalScanMs = 0;
|
|
2849
|
-
if (this.configuredPiiMasking === null) {
|
|
3874
|
+
if (this.configuredPiiMasking === null || this.configuredSecretMasking === null) {
|
|
2850
3875
|
const refreshed = await this.refreshCapabilityConfigBeforeClientControl({
|
|
2851
3876
|
capabilityConfig,
|
|
2852
3877
|
sdkConfigFetchMs,
|
|
@@ -2857,8 +3882,12 @@ var AgentID = class {
|
|
|
2857
3882
|
}
|
|
2858
3883
|
if (!this.clientFastFail) {
|
|
2859
3884
|
const effectivePiiMasking2 = this.resolveEffectivePiiMasking(capabilityConfig);
|
|
2860
|
-
|
|
2861
|
-
|
|
3885
|
+
const effectiveSecretMasking2 = this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3886
|
+
if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2 || !capabilityConfig.block_secret_leakage && effectiveSecretMasking2) {
|
|
3887
|
+
const masked = this.pii.anonymize(sanitizedInput, {
|
|
3888
|
+
pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking2,
|
|
3889
|
+
secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking2
|
|
3890
|
+
});
|
|
2862
3891
|
return {
|
|
2863
3892
|
sanitizedInput: masked.maskedText,
|
|
2864
3893
|
capabilityConfig,
|
|
@@ -2890,13 +3919,18 @@ var AgentID = class {
|
|
|
2890
3919
|
apiKey: effectiveApiKey,
|
|
2891
3920
|
clientEventId: params.clientEventId,
|
|
2892
3921
|
sdkConfigFetchMs,
|
|
3922
|
+
telemetryMetadata: params.telemetryMetadata,
|
|
2893
3923
|
runPromptInjectionCheck: !params.skipInjectionScan
|
|
2894
3924
|
});
|
|
2895
3925
|
sanitizedInput = enforced.sanitizedInput;
|
|
2896
3926
|
sdkLocalScanMs = enforced.sdkLocalScanMs;
|
|
2897
3927
|
const effectivePiiMasking = this.resolveEffectivePiiMasking(capabilityConfig);
|
|
2898
|
-
|
|
2899
|
-
|
|
3928
|
+
const effectiveSecretMasking = this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3929
|
+
if (!capabilityConfig.block_pii_leakage && effectivePiiMasking || !capabilityConfig.block_secret_leakage && effectiveSecretMasking) {
|
|
3930
|
+
const masked = this.pii.anonymize(sanitizedInput, {
|
|
3931
|
+
pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking,
|
|
3932
|
+
secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking
|
|
3933
|
+
});
|
|
2900
3934
|
return {
|
|
2901
3935
|
sanitizedInput: masked.maskedText,
|
|
2902
3936
|
capabilityConfig,
|
|
@@ -2932,6 +3966,7 @@ var AgentID = class {
|
|
|
2932
3966
|
apiKey: effectiveApiKey,
|
|
2933
3967
|
clientEventId: params.clientEventId,
|
|
2934
3968
|
sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
|
|
3969
|
+
telemetryMetadata: params.telemetryMetadata,
|
|
2935
3970
|
runPromptInjectionCheck: true
|
|
2936
3971
|
});
|
|
2937
3972
|
return {
|
|
@@ -2975,12 +4010,43 @@ var AgentID = class {
|
|
|
2975
4010
|
})
|
|
2976
4011
|
});
|
|
2977
4012
|
}
|
|
2978
|
-
withMaskedOpenAIRequest(req, maskedText) {
|
|
4013
|
+
withMaskedOpenAIRequest(req, maskedText, options) {
|
|
2979
4014
|
const messages = Array.isArray(req?.messages) ? req.messages : null;
|
|
2980
4015
|
if (!messages) {
|
|
2981
4016
|
return req;
|
|
2982
4017
|
}
|
|
2983
|
-
const newMessages =
|
|
4018
|
+
const newMessages = messages.map((message2) => {
|
|
4019
|
+
if (!message2 || typeof message2 !== "object") {
|
|
4020
|
+
return message2;
|
|
4021
|
+
}
|
|
4022
|
+
const typedMessage = message2;
|
|
4023
|
+
const currentContent2 = typedMessage.content;
|
|
4024
|
+
if (typeof currentContent2 === "string") {
|
|
4025
|
+
return {
|
|
4026
|
+
...typedMessage,
|
|
4027
|
+
content: this.pii.anonymize(currentContent2, options).maskedText
|
|
4028
|
+
};
|
|
4029
|
+
}
|
|
4030
|
+
if (Array.isArray(currentContent2)) {
|
|
4031
|
+
return {
|
|
4032
|
+
...typedMessage,
|
|
4033
|
+
content: currentContent2.map((part) => {
|
|
4034
|
+
if (!part || typeof part !== "object") {
|
|
4035
|
+
return part;
|
|
4036
|
+
}
|
|
4037
|
+
const typedPart = part;
|
|
4038
|
+
if (typeof typedPart.text !== "string") {
|
|
4039
|
+
return part;
|
|
4040
|
+
}
|
|
4041
|
+
return {
|
|
4042
|
+
...typedPart,
|
|
4043
|
+
text: this.pii.anonymize(typedPart.text, options).maskedText
|
|
4044
|
+
};
|
|
4045
|
+
})
|
|
4046
|
+
};
|
|
4047
|
+
}
|
|
4048
|
+
return message2;
|
|
4049
|
+
});
|
|
2984
4050
|
let lastUserIdx = null;
|
|
2985
4051
|
for (let i = 0; i < newMessages.length; i += 1) {
|
|
2986
4052
|
const msg = newMessages[i];
|
|
@@ -2995,9 +4061,30 @@ var AgentID = class {
|
|
|
2995
4061
|
if (!message || typeof message !== "object") {
|
|
2996
4062
|
return req;
|
|
2997
4063
|
}
|
|
4064
|
+
const currentContent = message.content;
|
|
4065
|
+
let nextContent = maskedText;
|
|
4066
|
+
if (Array.isArray(currentContent)) {
|
|
4067
|
+
let textReplaced = false;
|
|
4068
|
+
const preservedParts = [];
|
|
4069
|
+
for (const part of currentContent) {
|
|
4070
|
+
if (!part || typeof part !== "object" || part.type !== "text" || typeof part.text !== "string") {
|
|
4071
|
+
preservedParts.push(part);
|
|
4072
|
+
continue;
|
|
4073
|
+
}
|
|
4074
|
+
if (textReplaced) {
|
|
4075
|
+
continue;
|
|
4076
|
+
}
|
|
4077
|
+
textReplaced = true;
|
|
4078
|
+
preservedParts.push({
|
|
4079
|
+
...part,
|
|
4080
|
+
text: maskedText
|
|
4081
|
+
});
|
|
4082
|
+
}
|
|
4083
|
+
nextContent = textReplaced ? preservedParts : [{ type: "text", text: maskedText }, ...currentContent];
|
|
4084
|
+
}
|
|
2998
4085
|
newMessages[lastUserIdx] = {
|
|
2999
4086
|
...message,
|
|
3000
|
-
content:
|
|
4087
|
+
content: nextContent
|
|
3001
4088
|
};
|
|
3002
4089
|
if (!req || typeof req !== "object") {
|
|
3003
4090
|
return req;
|
|
@@ -3016,6 +4103,7 @@ var AgentID = class {
|
|
|
3016
4103
|
event_type: "security_policy_violation",
|
|
3017
4104
|
severity: "high",
|
|
3018
4105
|
metadata: {
|
|
4106
|
+
...params.telemetryMetadata ?? {},
|
|
3019
4107
|
event_type: "security_policy_violation",
|
|
3020
4108
|
severity: "high",
|
|
3021
4109
|
system_id: params.systemId,
|
|
@@ -3043,6 +4131,7 @@ var AgentID = class {
|
|
|
3043
4131
|
event_type: "security_alert",
|
|
3044
4132
|
severity: "warning",
|
|
3045
4133
|
metadata: {
|
|
4134
|
+
...params.guardParams.metadata ?? {},
|
|
3046
4135
|
source: "guard",
|
|
3047
4136
|
status: params.status,
|
|
3048
4137
|
guard_reason: params.reason,
|
|
@@ -3171,7 +4260,13 @@ var AgentID = class {
|
|
|
3171
4260
|
guardParams: params,
|
|
3172
4261
|
apiKey: effectiveApiKey
|
|
3173
4262
|
});
|
|
3174
|
-
return withGuardLatency(
|
|
4263
|
+
return withGuardLatency(
|
|
4264
|
+
this.buildFailOpenGuardVerdict(
|
|
4265
|
+
"system_failure_fail_open",
|
|
4266
|
+
params.input,
|
|
4267
|
+
{ apiKey: effectiveApiKey }
|
|
4268
|
+
)
|
|
4269
|
+
);
|
|
3175
4270
|
}
|
|
3176
4271
|
this.cacheGuardVerdict(guardCacheKey, verdict);
|
|
3177
4272
|
return withGuardLatency(verdict);
|
|
@@ -3206,7 +4301,11 @@ var AgentID = class {
|
|
|
3206
4301
|
if (effectiveStrictMode) {
|
|
3207
4302
|
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
3208
4303
|
}
|
|
3209
|
-
return withGuardLatency(
|
|
4304
|
+
return withGuardLatency(
|
|
4305
|
+
this.buildFailOpenGuardVerdict("timeout_fallback", params.input, {
|
|
4306
|
+
apiKey: effectiveApiKey
|
|
4307
|
+
})
|
|
4308
|
+
);
|
|
3210
4309
|
}
|
|
3211
4310
|
console.warn(
|
|
3212
4311
|
effectiveStrictMode ? "[AgentID] Guard check failed (Strict mode active):" : "[AgentID] Guard check failed (Fail-Open active):",
|
|
@@ -3221,7 +4320,11 @@ var AgentID = class {
|
|
|
3221
4320
|
if (effectiveStrictMode) {
|
|
3222
4321
|
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
3223
4322
|
}
|
|
3224
|
-
return withGuardLatency(
|
|
4323
|
+
return withGuardLatency(
|
|
4324
|
+
this.buildFailOpenGuardVerdict("guard_unreachable", params.input, {
|
|
4325
|
+
apiKey: effectiveApiKey
|
|
4326
|
+
})
|
|
4327
|
+
);
|
|
3225
4328
|
} finally {
|
|
3226
4329
|
clearTimeout(timeoutId);
|
|
3227
4330
|
}
|
|
@@ -3230,13 +4333,23 @@ var AgentID = class {
|
|
|
3230
4333
|
if (effectiveStrictMode) {
|
|
3231
4334
|
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
3232
4335
|
}
|
|
3233
|
-
return withGuardLatency(
|
|
4336
|
+
return withGuardLatency(
|
|
4337
|
+
this.buildFailOpenGuardVerdict("timeout_fallback", params.input, {
|
|
4338
|
+
apiKey: effectiveApiKey
|
|
4339
|
+
})
|
|
4340
|
+
);
|
|
3234
4341
|
}
|
|
3235
4342
|
if (typeof lastStatusCode === "number" && lastStatusCode >= 500) {
|
|
3236
4343
|
if (effectiveStrictMode) {
|
|
3237
4344
|
return withGuardLatency({ allowed: false, reason: "server_error" });
|
|
3238
4345
|
}
|
|
3239
|
-
return withGuardLatency(
|
|
4346
|
+
return withGuardLatency(
|
|
4347
|
+
this.buildFailOpenGuardVerdict(
|
|
4348
|
+
"system_failure_fail_open",
|
|
4349
|
+
params.input,
|
|
4350
|
+
{ apiKey: effectiveApiKey }
|
|
4351
|
+
)
|
|
4352
|
+
);
|
|
3240
4353
|
}
|
|
3241
4354
|
console.warn(
|
|
3242
4355
|
effectiveStrictMode ? "[AgentID] Guard check failed (Strict mode active):" : "[AgentID] Guard check failed (Fail-Open active):",
|
|
@@ -3245,7 +4358,11 @@ var AgentID = class {
|
|
|
3245
4358
|
if (effectiveStrictMode) {
|
|
3246
4359
|
return withGuardLatency({ allowed: false, reason: "network_error_strict_mode" });
|
|
3247
4360
|
}
|
|
3248
|
-
return withGuardLatency(
|
|
4361
|
+
return withGuardLatency(
|
|
4362
|
+
this.buildFailOpenGuardVerdict("guard_unreachable", params.input, {
|
|
4363
|
+
apiKey: effectiveApiKey
|
|
4364
|
+
})
|
|
4365
|
+
);
|
|
3249
4366
|
}
|
|
3250
4367
|
async sendIngest(params, options, internal) {
|
|
3251
4368
|
const ingestStartedAt = Date.now();
|
|
@@ -3485,21 +4602,29 @@ var AgentID = class {
|
|
|
3485
4602
|
wrapCompletion(completion, options) {
|
|
3486
4603
|
if (typeof completion === "string") {
|
|
3487
4604
|
const masked = this.pii.anonymize(completion);
|
|
4605
|
+
const placeholderOutputMasked = textContainsMappingPlaceholder(
|
|
4606
|
+
completion,
|
|
4607
|
+
options?.piiMapping
|
|
4608
|
+
);
|
|
3488
4609
|
return {
|
|
3489
4610
|
mode: "static",
|
|
3490
4611
|
rawOutput: completion,
|
|
3491
4612
|
transformedOutput: masked.maskedText,
|
|
3492
|
-
outputMasked: masked.maskedText !== completion
|
|
4613
|
+
outputMasked: masked.maskedText !== completion || placeholderOutputMasked
|
|
3493
4614
|
};
|
|
3494
4615
|
}
|
|
3495
4616
|
if (!isAsyncIterable(completion)) {
|
|
3496
4617
|
const asText = String(completion ?? "");
|
|
3497
4618
|
const masked = this.pii.anonymize(asText);
|
|
4619
|
+
const placeholderOutputMasked = textContainsMappingPlaceholder(
|
|
4620
|
+
asText,
|
|
4621
|
+
options?.piiMapping
|
|
4622
|
+
);
|
|
3498
4623
|
return {
|
|
3499
4624
|
mode: "static",
|
|
3500
4625
|
rawOutput: asText,
|
|
3501
4626
|
transformedOutput: masked.maskedText,
|
|
3502
|
-
outputMasked: masked.maskedText !== asText
|
|
4627
|
+
outputMasked: masked.maskedText !== asText || placeholderOutputMasked
|
|
3503
4628
|
};
|
|
3504
4629
|
}
|
|
3505
4630
|
const source = completion;
|
|
@@ -3509,8 +4634,10 @@ var AgentID = class {
|
|
|
3509
4634
|
const isOpenAIStreamFinishChunk = this.isOpenAIStreamFinishChunk.bind(this);
|
|
3510
4635
|
const rewriteOpenAIStreamChunkForClient = this.rewriteOpenAIStreamChunkForClient.bind(this);
|
|
3511
4636
|
const createSyntheticOpenAIStreamChunk = this.createSyntheticOpenAIStreamChunk.bind(this);
|
|
4637
|
+
const setOpenAIStreamChunkText = this.setOpenAIStreamChunkText.bind(this);
|
|
3512
4638
|
const piiManager = this.pii;
|
|
3513
4639
|
const streamRewriter = options?.deanonymizeForClient === true && options.piiMapping ? createStreamingPlaceholderRewriter(piiManager, options.piiMapping) : null;
|
|
4640
|
+
const maskForClient = options?.maskForClient === true && streamRewriter === null;
|
|
3514
4641
|
let lastUsage;
|
|
3515
4642
|
let resolveDone = null;
|
|
3516
4643
|
let rejectDone = null;
|
|
@@ -3523,12 +4650,17 @@ var AgentID = class {
|
|
|
3523
4650
|
try {
|
|
3524
4651
|
let finishChunkFlushed = false;
|
|
3525
4652
|
let lastChunkTemplate;
|
|
4653
|
+
let clientRawText = "";
|
|
4654
|
+
let clientMaskFlushed = false;
|
|
3526
4655
|
for await (const chunk of source) {
|
|
3527
4656
|
const chunkText = extractStreamChunkText(chunk);
|
|
3528
|
-
const isFinishChunk = streamRewriter ? isOpenAIStreamFinishChunk(chunk) : false;
|
|
4657
|
+
const isFinishChunk = streamRewriter || maskForClient ? isOpenAIStreamFinishChunk(chunk) : false;
|
|
3529
4658
|
if (chunkText) {
|
|
3530
4659
|
await collector.push(chunkText);
|
|
3531
4660
|
lastChunkTemplate = chunk;
|
|
4661
|
+
if (maskForClient) {
|
|
4662
|
+
clientRawText += chunkText;
|
|
4663
|
+
}
|
|
3532
4664
|
}
|
|
3533
4665
|
const chunkUsage = extractStreamChunkUsage(chunk);
|
|
3534
4666
|
if (chunkUsage) {
|
|
@@ -3548,6 +4680,28 @@ var AgentID = class {
|
|
|
3548
4680
|
}
|
|
3549
4681
|
continue;
|
|
3550
4682
|
}
|
|
4683
|
+
if (maskForClient) {
|
|
4684
|
+
if (isFinishChunk) {
|
|
4685
|
+
const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
|
|
4686
|
+
clientMaskFlushed = true;
|
|
4687
|
+
if (maskedClientText.length > 0) {
|
|
4688
|
+
yield createSyntheticOpenAIStreamChunk(
|
|
4689
|
+
maskedClientText,
|
|
4690
|
+
lastChunkTemplate ?? chunk
|
|
4691
|
+
);
|
|
4692
|
+
}
|
|
4693
|
+
if (chunkText) {
|
|
4694
|
+
setOpenAIStreamChunkText(chunk, "");
|
|
4695
|
+
}
|
|
4696
|
+
yield chunk;
|
|
4697
|
+
finishChunkFlushed = true;
|
|
4698
|
+
continue;
|
|
4699
|
+
}
|
|
4700
|
+
if (!chunkText) {
|
|
4701
|
+
yield chunk;
|
|
4702
|
+
}
|
|
4703
|
+
continue;
|
|
4704
|
+
}
|
|
3551
4705
|
yield chunk;
|
|
3552
4706
|
}
|
|
3553
4707
|
if (streamRewriter && !finishChunkFlushed) {
|
|
@@ -3559,14 +4713,27 @@ var AgentID = class {
|
|
|
3559
4713
|
);
|
|
3560
4714
|
}
|
|
3561
4715
|
}
|
|
4716
|
+
if (maskForClient && !clientMaskFlushed) {
|
|
4717
|
+
const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
|
|
4718
|
+
if (maskedClientText.length > 0) {
|
|
4719
|
+
yield createSyntheticOpenAIStreamChunk(
|
|
4720
|
+
maskedClientText,
|
|
4721
|
+
lastChunkTemplate
|
|
4722
|
+
);
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
3562
4725
|
await collector.close();
|
|
3563
4726
|
const rawOutput = await collector.result;
|
|
3564
4727
|
const masked = piiManager.anonymize(rawOutput);
|
|
4728
|
+
const placeholderOutputMasked = textContainsMappingPlaceholder(
|
|
4729
|
+
rawOutput,
|
|
4730
|
+
options?.piiMapping
|
|
4731
|
+
);
|
|
3565
4732
|
resolveDone?.({
|
|
3566
4733
|
mode: "static",
|
|
3567
4734
|
rawOutput,
|
|
3568
4735
|
transformedOutput: masked.maskedText,
|
|
3569
|
-
outputMasked: masked.maskedText !== rawOutput,
|
|
4736
|
+
outputMasked: masked.maskedText !== rawOutput || placeholderOutputMasked,
|
|
3570
4737
|
usage: lastUsage
|
|
3571
4738
|
});
|
|
3572
4739
|
} catch (error) {
|
|
@@ -3601,6 +4768,37 @@ var AgentID = class {
|
|
|
3601
4768
|
);
|
|
3602
4769
|
}
|
|
3603
4770
|
}
|
|
4771
|
+
buildOperationLogParams(params) {
|
|
4772
|
+
return createAgentIdOperationLog(params);
|
|
4773
|
+
}
|
|
4774
|
+
async logOperation(params, options) {
|
|
4775
|
+
return this.log(this.buildOperationLogParams(params), options);
|
|
4776
|
+
}
|
|
4777
|
+
async logPromptPreflightStep(params, options) {
|
|
4778
|
+
const telemetry = buildPromptPreflightTelemetry(params);
|
|
4779
|
+
const summary = firstNonEmptyString(telemetry?.step_summary, telemetry?.stepSummary) ?? summarizePromptPreflightResult({
|
|
4780
|
+
verdict: params.verdict,
|
|
4781
|
+
localFallbackApplied: params.local_fallback_applied,
|
|
4782
|
+
localFallbackReason: params.local_fallback_reason
|
|
4783
|
+
});
|
|
4784
|
+
await this.logOperation(
|
|
4785
|
+
{
|
|
4786
|
+
system_id: params.system_id,
|
|
4787
|
+
user_id: params.user_id,
|
|
4788
|
+
request_identity: params.request_identity,
|
|
4789
|
+
input: params.input,
|
|
4790
|
+
output: summary,
|
|
4791
|
+
model: "not_applicable",
|
|
4792
|
+
latency: params.guard_latency_ms ?? void 0,
|
|
4793
|
+
telemetry,
|
|
4794
|
+
client_capabilities: params.client_capabilities
|
|
4795
|
+
},
|
|
4796
|
+
options
|
|
4797
|
+
);
|
|
4798
|
+
}
|
|
4799
|
+
operation(params, options) {
|
|
4800
|
+
return this.logOperation(params, options);
|
|
4801
|
+
}
|
|
3604
4802
|
/**
|
|
3605
4803
|
* Analytics alias for telemetry logging.
|
|
3606
4804
|
*/
|
|
@@ -3645,49 +4843,62 @@ var AgentID = class {
|
|
|
3645
4843
|
if (typeof originalCreate !== "function") return originalCreate;
|
|
3646
4844
|
return async (...args) => {
|
|
3647
4845
|
const normalizedCreateArgs = normalizeOpenAICreateArgs(args);
|
|
3648
|
-
const
|
|
4846
|
+
const rawReq = normalizedCreateArgs?.[0] ?? {};
|
|
4847
|
+
const requestTelemetry = extractRequestTelemetryContext(rawReq);
|
|
4848
|
+
const telemetryMetadata = mergeTelemetryContexts(
|
|
4849
|
+
options.telemetry,
|
|
4850
|
+
requestTelemetry
|
|
4851
|
+
);
|
|
4852
|
+
const providerReq = stripRequestTelemetryContext(rawReq);
|
|
3649
4853
|
const pipelineStartedAt = Date.now();
|
|
3650
|
-
const requestLevelApiKey = options.resolveApiKey?.(
|
|
4854
|
+
const requestLevelApiKey = options.resolveApiKey?.(rawReq) ?? options.apiKey ?? options.api_key;
|
|
3651
4855
|
const effectiveApiKey = this.resolveApiKey(requestLevelApiKey);
|
|
3652
4856
|
const requestOptions = { apiKey: effectiveApiKey };
|
|
3653
|
-
const clientEventId = this.resolveClientEventId(
|
|
4857
|
+
const clientEventId = this.resolveClientEventId(rawReq);
|
|
3654
4858
|
const effectiveStrictMode = await this.resolveEffectiveStrictMode(requestOptions);
|
|
3655
|
-
const stream = adapter.isStream(
|
|
4859
|
+
const stream = adapter.isStream(providerReq);
|
|
3656
4860
|
let capabilityConfig = this.getCachedCapabilityConfig(requestOptions);
|
|
3657
|
-
const userText = adapter.extractInput(
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
let
|
|
4861
|
+
const userText = adapter.extractInput(providerReq);
|
|
4862
|
+
const requestAttachments = adapter.extractAttachments(providerReq);
|
|
4863
|
+
const hasGuardContent = userText !== null || requestAttachments.length > 0;
|
|
4864
|
+
let maskedText = userText ?? "";
|
|
4865
|
+
let maskedReq = providerReq;
|
|
4866
|
+
let createArgs = providerReq === rawReq ? normalizedCreateArgs : [{ ...providerReq }, ...normalizedCreateArgs.slice(1)];
|
|
3661
4867
|
let mapping = {};
|
|
3662
|
-
let shouldDeanonymize = false;
|
|
3663
4868
|
let sdkConfigFetchMs = 0;
|
|
3664
4869
|
let sdkLocalScanMs = 0;
|
|
3665
|
-
|
|
4870
|
+
let providerMaskingOptions;
|
|
4871
|
+
if (hasGuardContent) {
|
|
3666
4872
|
const prepared = await this.prepareInputForDispatch({
|
|
3667
|
-
input: userText,
|
|
4873
|
+
input: userText ?? "",
|
|
3668
4874
|
systemId,
|
|
3669
4875
|
stream,
|
|
3670
|
-
clientEventId
|
|
4876
|
+
clientEventId,
|
|
4877
|
+
telemetryMetadata
|
|
3671
4878
|
}, requestOptions);
|
|
3672
4879
|
capabilityConfig = prepared.capabilityConfig;
|
|
4880
|
+
providerMaskingOptions = {
|
|
4881
|
+
pii: !capabilityConfig.block_pii_leakage && this.resolveEffectivePiiMasking(capabilityConfig),
|
|
4882
|
+
secrets: !capabilityConfig.block_secret_leakage && this.resolveEffectiveSecretMasking(capabilityConfig)
|
|
4883
|
+
};
|
|
3673
4884
|
maskedText = prepared.sanitizedInput;
|
|
3674
4885
|
mapping = prepared.piiMapping ?? {};
|
|
3675
|
-
shouldDeanonymize = prepared.shouldDeanonymize === true;
|
|
3676
4886
|
sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
|
|
3677
4887
|
sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
|
|
3678
|
-
if (maskedText !== userText) {
|
|
4888
|
+
if (maskedText !== (userText ?? "")) {
|
|
3679
4889
|
maskedReq = this.withMaskedOpenAIRequest(
|
|
3680
|
-
|
|
3681
|
-
maskedText
|
|
4890
|
+
providerReq,
|
|
4891
|
+
maskedText,
|
|
4892
|
+
providerMaskingOptions
|
|
3682
4893
|
);
|
|
3683
|
-
const nextCreateArgs = [...
|
|
4894
|
+
const nextCreateArgs = [...createArgs];
|
|
3684
4895
|
nextCreateArgs[0] = maskedReq;
|
|
3685
4896
|
createArgs = nextCreateArgs;
|
|
3686
4897
|
}
|
|
3687
4898
|
}
|
|
3688
|
-
if (!
|
|
4899
|
+
if (!hasGuardContent) {
|
|
3689
4900
|
throw new Error(
|
|
3690
|
-
"AgentID: No user message found. Security guard requires
|
|
4901
|
+
"AgentID: No user message or supported inline attachment found. Security guard requires prompt content."
|
|
3691
4902
|
);
|
|
3692
4903
|
}
|
|
3693
4904
|
const verdict = await this.guard({
|
|
@@ -3698,6 +4909,8 @@ var AgentID = class {
|
|
|
3698
4909
|
client_event_id: clientEventId,
|
|
3699
4910
|
expected_languages: expectedLanguages,
|
|
3700
4911
|
request_identity: options.request_identity,
|
|
4912
|
+
metadata: telemetryMetadata,
|
|
4913
|
+
attachments: requestAttachments,
|
|
3701
4914
|
client_capabilities: this.buildClientCapabilities(
|
|
3702
4915
|
"openai",
|
|
3703
4916
|
false,
|
|
@@ -3719,22 +4932,44 @@ var AgentID = class {
|
|
|
3719
4932
|
apiKey: effectiveApiKey,
|
|
3720
4933
|
clientEventId,
|
|
3721
4934
|
sdkConfigFetchMs,
|
|
4935
|
+
telemetryMetadata,
|
|
3722
4936
|
runPromptInjectionCheck: true
|
|
3723
4937
|
});
|
|
3724
4938
|
maskedText = fallback.sanitizedInput;
|
|
3725
4939
|
sdkLocalScanMs = fallback.sdkLocalScanMs;
|
|
3726
4940
|
}
|
|
3727
4941
|
} else {
|
|
4942
|
+
await this.logPromptPreflightStep(
|
|
4943
|
+
{
|
|
4944
|
+
system_id: systemId,
|
|
4945
|
+
user_id: options.user_id,
|
|
4946
|
+
request_identity: options.request_identity,
|
|
4947
|
+
input: maskedText,
|
|
4948
|
+
telemetry: telemetryMetadata,
|
|
4949
|
+
verdict,
|
|
4950
|
+
guard_event_id: verdict.guard_event_id ?? null,
|
|
4951
|
+
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),
|
|
4952
|
+
preflight_for_client_event_id: typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId,
|
|
4953
|
+
client_capabilities: this.buildClientCapabilities(
|
|
4954
|
+
"openai",
|
|
4955
|
+
false,
|
|
4956
|
+
capabilityConfig
|
|
4957
|
+
),
|
|
4958
|
+
runtime_surface: "openai_sdk_guard"
|
|
4959
|
+
},
|
|
4960
|
+
requestOptions
|
|
4961
|
+
);
|
|
3728
4962
|
throw new SecurityBlockError(verdict.reason ?? "guard_denied");
|
|
3729
4963
|
}
|
|
3730
4964
|
}
|
|
3731
|
-
const currentRequestInput = adapter.extractInput(maskedReq);
|
|
3732
|
-
if (maskedText !== currentRequestInput) {
|
|
4965
|
+
const currentRequestInput = adapter.extractInput(maskedReq) ?? "";
|
|
4966
|
+
if (maskedText !== currentRequestInput || providerMaskingOptions?.pii === true || providerMaskingOptions?.secrets === true) {
|
|
3733
4967
|
maskedReq = this.withMaskedOpenAIRequest(
|
|
3734
|
-
|
|
3735
|
-
maskedText
|
|
4968
|
+
providerReq,
|
|
4969
|
+
maskedText,
|
|
4970
|
+
providerMaskingOptions
|
|
3736
4971
|
);
|
|
3737
|
-
const nextCreateArgs = [...
|
|
4972
|
+
const nextCreateArgs = [...createArgs];
|
|
3738
4973
|
nextCreateArgs[0] = maskedReq;
|
|
3739
4974
|
createArgs = nextCreateArgs;
|
|
3740
4975
|
}
|
|
@@ -3745,15 +4980,45 @@ var AgentID = class {
|
|
|
3745
4980
|
const isShadowMode = verdict.shadow_mode === true;
|
|
3746
4981
|
const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
|
|
3747
4982
|
if (transformedInput !== maskedText) {
|
|
4983
|
+
const serverDerivedMapping = derivePlaceholderMappingFromTransform(
|
|
4984
|
+
maskedText,
|
|
4985
|
+
transformedInput
|
|
4986
|
+
);
|
|
4987
|
+
if (Object.keys(serverDerivedMapping).length > 0) {
|
|
4988
|
+
mapping = mergePiiMappings(mapping, serverDerivedMapping);
|
|
4989
|
+
}
|
|
3748
4990
|
maskedText = transformedInput;
|
|
3749
4991
|
maskedReq = this.withMaskedOpenAIRequest(
|
|
3750
|
-
|
|
3751
|
-
transformedInput
|
|
4992
|
+
providerReq,
|
|
4993
|
+
transformedInput,
|
|
4994
|
+
providerMaskingOptions
|
|
3752
4995
|
);
|
|
3753
|
-
const nextCreateArgs = [...
|
|
4996
|
+
const nextCreateArgs = [...createArgs];
|
|
3754
4997
|
nextCreateArgs[0] = maskedReq;
|
|
3755
4998
|
createArgs = nextCreateArgs;
|
|
3756
4999
|
}
|
|
5000
|
+
await this.logPromptPreflightStep(
|
|
5001
|
+
{
|
|
5002
|
+
system_id: systemId,
|
|
5003
|
+
user_id: options.user_id,
|
|
5004
|
+
request_identity: options.request_identity,
|
|
5005
|
+
input: maskedText,
|
|
5006
|
+
telemetry: telemetryMetadata,
|
|
5007
|
+
verdict,
|
|
5008
|
+
guard_event_id: guardEventId,
|
|
5009
|
+
guard_latency_ms: guardLatencyMs,
|
|
5010
|
+
preflight_for_client_event_id: canonicalClientEventId,
|
|
5011
|
+
client_capabilities: this.buildClientCapabilities(
|
|
5012
|
+
"openai",
|
|
5013
|
+
false,
|
|
5014
|
+
capabilityConfig
|
|
5015
|
+
),
|
|
5016
|
+
local_fallback_applied: localFallbackApplied,
|
|
5017
|
+
local_fallback_reason: localFallbackReason,
|
|
5018
|
+
runtime_surface: "openai_sdk_guard"
|
|
5019
|
+
},
|
|
5020
|
+
requestOptions
|
|
5021
|
+
);
|
|
3757
5022
|
if (stream) {
|
|
3758
5023
|
const modelStartedAt2 = Date.now();
|
|
3759
5024
|
const streamResponse = await originalCreate.apply(compTarget, createArgs);
|
|
@@ -3765,14 +5030,15 @@ var AgentID = class {
|
|
|
3765
5030
|
})(),
|
|
3766
5031
|
{
|
|
3767
5032
|
piiMapping: mapping,
|
|
3768
|
-
deanonymizeForClient:
|
|
5033
|
+
deanonymizeForClient: false,
|
|
5034
|
+
maskForClient: !isShadowMode
|
|
3769
5035
|
}
|
|
3770
5036
|
);
|
|
3771
5037
|
if (maskedText && wrappedCompletion.mode === "stream") {
|
|
3772
5038
|
void wrappedCompletion.done.then(async (result) => {
|
|
3773
5039
|
const modelLatencyMs2 = Math.max(0, Date.now() - modelStartedAt2);
|
|
3774
5040
|
const totalPipelineLatencyMs2 = Math.max(0, Date.now() - pipelineStartedAt);
|
|
3775
|
-
const outputForLog =
|
|
5041
|
+
const outputForLog = result.transformedOutput;
|
|
3776
5042
|
const ingestResult = await this.sendIngest({
|
|
3777
5043
|
event_id: canonicalClientEventId,
|
|
3778
5044
|
system_id: systemId,
|
|
@@ -3784,29 +5050,32 @@ var AgentID = class {
|
|
|
3784
5050
|
usage: result.usage,
|
|
3785
5051
|
latency: modelLatencyMs2,
|
|
3786
5052
|
event_type: "complete",
|
|
3787
|
-
metadata:
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
5053
|
+
metadata: mergeTelemetryContexts(
|
|
5054
|
+
telemetryMetadata,
|
|
5055
|
+
{
|
|
5056
|
+
transformed_input: maskedText,
|
|
5057
|
+
transformed_output: result.transformedOutput,
|
|
5058
|
+
output_masked: result.outputMasked,
|
|
5059
|
+
shadow_mode: isShadowMode,
|
|
5060
|
+
simulated_decision: verdict.simulated_decision ?? null,
|
|
5061
|
+
simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
|
|
5062
|
+
response_streamed: true,
|
|
5063
|
+
sdk_local_fallback_applied: localFallbackApplied,
|
|
5064
|
+
sdk_local_fallback_reason: localFallbackReason,
|
|
5065
|
+
guard_latency_ms: guardLatencyMs,
|
|
5066
|
+
model_latency_ms: modelLatencyMs2,
|
|
5067
|
+
total_pipeline_latency_ms: totalPipelineLatencyMs2,
|
|
5068
|
+
guard_event_id: guardEventId,
|
|
5069
|
+
client_event_id: canonicalClientEventId,
|
|
5070
|
+
transparency
|
|
5071
|
+
},
|
|
5072
|
+
buildSdkTimingMetadata({
|
|
3804
5073
|
sdkConfigFetchMs,
|
|
3805
5074
|
sdkLocalScanMs,
|
|
3806
5075
|
sdkGuardMs: guardLatencyMs,
|
|
3807
5076
|
sdkConfigVersion: capabilityConfig.version
|
|
3808
5077
|
})
|
|
3809
|
-
|
|
5078
|
+
),
|
|
3810
5079
|
client_capabilities: this.buildClientCapabilities(
|
|
3811
5080
|
"openai",
|
|
3812
5081
|
false,
|
|
@@ -3837,10 +5106,13 @@ var AgentID = class {
|
|
|
3837
5106
|
const totalPipelineLatencyMs = Math.max(0, Date.now() - pipelineStartedAt);
|
|
3838
5107
|
if (maskedText) {
|
|
3839
5108
|
const output = adapter.extractOutput(res);
|
|
3840
|
-
const wrappedCompletion = this.wrapCompletion(output
|
|
5109
|
+
const wrappedCompletion = this.wrapCompletion(output, {
|
|
5110
|
+
piiMapping: mapping,
|
|
5111
|
+
deanonymizeForClient: false
|
|
5112
|
+
});
|
|
3841
5113
|
const model = adapter.getModelName(maskedReq, res);
|
|
3842
5114
|
const usage = adapter.getTokenUsage(res);
|
|
3843
|
-
const outputForLog =
|
|
5115
|
+
const outputForLog = wrappedCompletion.transformedOutput;
|
|
3844
5116
|
const ingestResult = await this.sendIngest({
|
|
3845
5117
|
event_id: canonicalClientEventId,
|
|
3846
5118
|
system_id: systemId,
|
|
@@ -3852,29 +5124,32 @@ var AgentID = class {
|
|
|
3852
5124
|
usage,
|
|
3853
5125
|
latency: modelLatencyMs,
|
|
3854
5126
|
event_type: "complete",
|
|
3855
|
-
metadata:
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
5127
|
+
metadata: mergeTelemetryContexts(
|
|
5128
|
+
telemetryMetadata,
|
|
5129
|
+
{
|
|
5130
|
+
transformed_input: maskedText,
|
|
5131
|
+
transformed_output: wrappedCompletion.transformedOutput,
|
|
5132
|
+
output_masked: wrappedCompletion.outputMasked,
|
|
5133
|
+
shadow_mode: isShadowMode,
|
|
5134
|
+
simulated_decision: verdict.simulated_decision ?? null,
|
|
5135
|
+
simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
|
|
5136
|
+
response_streamed: false,
|
|
5137
|
+
sdk_local_fallback_applied: localFallbackApplied,
|
|
5138
|
+
sdk_local_fallback_reason: localFallbackReason,
|
|
5139
|
+
guard_latency_ms: guardLatencyMs,
|
|
5140
|
+
model_latency_ms: modelLatencyMs,
|
|
5141
|
+
total_pipeline_latency_ms: totalPipelineLatencyMs,
|
|
5142
|
+
guard_event_id: guardEventId,
|
|
5143
|
+
client_event_id: canonicalClientEventId,
|
|
5144
|
+
transparency
|
|
5145
|
+
},
|
|
5146
|
+
buildSdkTimingMetadata({
|
|
3872
5147
|
sdkConfigFetchMs,
|
|
3873
5148
|
sdkLocalScanMs,
|
|
3874
5149
|
sdkGuardMs: guardLatencyMs,
|
|
3875
5150
|
sdkConfigVersion: capabilityConfig.version
|
|
3876
5151
|
})
|
|
3877
|
-
|
|
5152
|
+
),
|
|
3878
5153
|
client_capabilities: this.buildClientCapabilities(
|
|
3879
5154
|
"openai",
|
|
3880
5155
|
false,
|
|
@@ -3891,17 +5166,21 @@ var AgentID = class {
|
|
|
3891
5166
|
);
|
|
3892
5167
|
}
|
|
3893
5168
|
}
|
|
3894
|
-
if (!
|
|
3895
|
-
const
|
|
5169
|
+
if (!isShadowMode && maskedText) {
|
|
5170
|
+
const output = adapter.extractOutput(res);
|
|
5171
|
+
const maskedOutput = this.wrapCompletion(output, {
|
|
5172
|
+
piiMapping: mapping,
|
|
5173
|
+
deanonymizeForClient: false
|
|
5174
|
+
}).transformedOutput;
|
|
3896
5175
|
try {
|
|
3897
5176
|
if (Array.isArray(res?.choices)) {
|
|
3898
5177
|
for (const choice of res.choices) {
|
|
3899
5178
|
const typedChoice = choice;
|
|
3900
5179
|
if (typedChoice?.message && typeof typedChoice.message.content === "string") {
|
|
3901
|
-
typedChoice.message.content =
|
|
5180
|
+
typedChoice.message.content = maskedOutput;
|
|
3902
5181
|
}
|
|
3903
5182
|
if (typedChoice?.delta && typeof typedChoice.delta.content === "string") {
|
|
3904
|
-
typedChoice.delta.content =
|
|
5183
|
+
typedChoice.delta.content = maskedOutput;
|
|
3905
5184
|
}
|
|
3906
5185
|
}
|
|
3907
5186
|
}
|
|
@@ -3926,14 +5205,222 @@ var AgentID = class {
|
|
|
3926
5205
|
});
|
|
3927
5206
|
}
|
|
3928
5207
|
};
|
|
5208
|
+
function mergeWorkflowTrailRequestOptions(base, override) {
|
|
5209
|
+
const apiKey = firstNonEmptyString(override?.apiKey, base?.apiKey);
|
|
5210
|
+
return apiKey ? { apiKey } : void 0;
|
|
5211
|
+
}
|
|
5212
|
+
function appendWorkflowErrorMetadata(metadata, error) {
|
|
5213
|
+
const nextMetadata = { ...metadata ?? {} };
|
|
5214
|
+
if (error instanceof Error) {
|
|
5215
|
+
if (typeof nextMetadata.error_name !== "string") {
|
|
5216
|
+
nextMetadata.error_name = error.name;
|
|
5217
|
+
}
|
|
5218
|
+
if (typeof nextMetadata.error_message !== "string" && error.message.trim().length > 0) {
|
|
5219
|
+
nextMetadata.error_message = error.message.trim();
|
|
5220
|
+
}
|
|
5221
|
+
return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
|
|
5222
|
+
}
|
|
5223
|
+
if (typeof nextMetadata.error_message !== "string" && typeof error !== "undefined") {
|
|
5224
|
+
const errorMessage = String(error).trim();
|
|
5225
|
+
if (errorMessage.length > 0) {
|
|
5226
|
+
nextMetadata.error_message = errorMessage;
|
|
5227
|
+
}
|
|
5228
|
+
}
|
|
5229
|
+
return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
|
|
5230
|
+
}
|
|
5231
|
+
var AgentIDWorkflowStep = class {
|
|
5232
|
+
constructor(params) {
|
|
5233
|
+
this.trail = params.trail;
|
|
5234
|
+
this.workflowStepId = params.workflowStepId;
|
|
5235
|
+
this.startEventId = params.startEventId;
|
|
5236
|
+
this.telemetry = params.telemetry;
|
|
5237
|
+
this.startedAtMs = params.startedAtMs;
|
|
5238
|
+
}
|
|
5239
|
+
resolveStepTelemetry(telemetry) {
|
|
5240
|
+
return mergeTelemetryContexts(
|
|
5241
|
+
this.telemetry,
|
|
5242
|
+
createAgentIdTelemetryContext({
|
|
5243
|
+
workflow_step_id: this.workflowStepId,
|
|
5244
|
+
parent_event_id: this.startEventId
|
|
5245
|
+
}),
|
|
5246
|
+
telemetry
|
|
5247
|
+
);
|
|
5248
|
+
}
|
|
5249
|
+
async log(params = {}, options) {
|
|
5250
|
+
return this.trail.logStep(
|
|
5251
|
+
{
|
|
5252
|
+
...params,
|
|
5253
|
+
telemetry: this.resolveStepTelemetry(params.telemetry)
|
|
5254
|
+
},
|
|
5255
|
+
options
|
|
5256
|
+
);
|
|
5257
|
+
}
|
|
5258
|
+
async complete(params = {}, options) {
|
|
5259
|
+
return this.log(
|
|
5260
|
+
{
|
|
5261
|
+
...params,
|
|
5262
|
+
latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
|
|
5263
|
+
event_status: params.event_status ?? "completed"
|
|
5264
|
+
},
|
|
5265
|
+
options
|
|
5266
|
+
);
|
|
5267
|
+
}
|
|
5268
|
+
async fail(error, params = {}, options) {
|
|
5269
|
+
return this.log(
|
|
5270
|
+
{
|
|
5271
|
+
...params,
|
|
5272
|
+
latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
|
|
5273
|
+
metadata: appendWorkflowErrorMetadata(params.metadata, error),
|
|
5274
|
+
event_type: params.event_type ?? "error",
|
|
5275
|
+
event_status: params.event_status ?? "failed",
|
|
5276
|
+
severity: params.severity ?? "error"
|
|
5277
|
+
},
|
|
5278
|
+
options
|
|
5279
|
+
);
|
|
5280
|
+
}
|
|
5281
|
+
};
|
|
5282
|
+
var AgentIDWorkflowTrail = class {
|
|
5283
|
+
constructor(options) {
|
|
5284
|
+
this.agent = options.agent;
|
|
5285
|
+
this.systemId = options.system_id;
|
|
5286
|
+
this.userId = options.user_id;
|
|
5287
|
+
this.requestIdentity = options.request_identity;
|
|
5288
|
+
this.telemetry = createAgentIdTelemetryContext(options.telemetry);
|
|
5289
|
+
this.clientCapabilities = options.client_capabilities;
|
|
5290
|
+
this.requestOptions = options.requestOptions;
|
|
5291
|
+
}
|
|
5292
|
+
async logStep(params = {}, options) {
|
|
5293
|
+
const payload = this.agent.buildOperationLogParams({
|
|
5294
|
+
...params,
|
|
5295
|
+
system_id: this.systemId,
|
|
5296
|
+
user_id: this.userId,
|
|
5297
|
+
request_identity: this.requestIdentity,
|
|
5298
|
+
telemetry: mergeTelemetryContexts(this.telemetry, params.telemetry),
|
|
5299
|
+
client_capabilities: params.client_capabilities ?? this.clientCapabilities
|
|
5300
|
+
});
|
|
5301
|
+
await this.agent.log(
|
|
5302
|
+
payload,
|
|
5303
|
+
mergeWorkflowTrailRequestOptions(this.requestOptions, options)
|
|
5304
|
+
);
|
|
5305
|
+
return payload;
|
|
5306
|
+
}
|
|
5307
|
+
async startStep(params = {}, options) {
|
|
5308
|
+
const startedAtMs = Date.now();
|
|
5309
|
+
const requestedTelemetry = createAgentIdTelemetryContext(params.telemetry);
|
|
5310
|
+
const workflowStepId = firstNonEmptyString(requestedTelemetry?.workflow_step_id, requestedTelemetry?.workflowStepId) ?? createAgentIdCorrelationId();
|
|
5311
|
+
const startTelemetry = mergeTelemetryContexts(
|
|
5312
|
+
requestedTelemetry,
|
|
5313
|
+
createAgentIdTelemetryContext({
|
|
5314
|
+
workflow_step_id: workflowStepId
|
|
5315
|
+
})
|
|
5316
|
+
);
|
|
5317
|
+
const startPayload = await this.logStep(
|
|
5318
|
+
{
|
|
5319
|
+
...params,
|
|
5320
|
+
telemetry: startTelemetry,
|
|
5321
|
+
event_type: params.event_type ?? "start",
|
|
5322
|
+
event_status: params.event_status ?? "started"
|
|
5323
|
+
},
|
|
5324
|
+
options
|
|
5325
|
+
);
|
|
5326
|
+
return new AgentIDWorkflowStep({
|
|
5327
|
+
trail: this,
|
|
5328
|
+
workflowStepId,
|
|
5329
|
+
startEventId: startPayload.event_id ?? createEventId2(),
|
|
5330
|
+
telemetry: startTelemetry,
|
|
5331
|
+
startedAtMs
|
|
5332
|
+
});
|
|
5333
|
+
}
|
|
5334
|
+
async runStep(params, run, hooks, options) {
|
|
5335
|
+
const step = await this.startStep(params, options);
|
|
5336
|
+
try {
|
|
5337
|
+
const result = await run();
|
|
5338
|
+
const completeParams = {
|
|
5339
|
+
...hooks?.complete ?? {},
|
|
5340
|
+
...hooks?.onComplete?.(result) ?? {}
|
|
5341
|
+
};
|
|
5342
|
+
await step.complete(completeParams, options);
|
|
5343
|
+
return result;
|
|
5344
|
+
} catch (error) {
|
|
5345
|
+
const failParams = {
|
|
5346
|
+
...hooks?.fail ?? {},
|
|
5347
|
+
...hooks?.onError?.(error) ?? {}
|
|
5348
|
+
};
|
|
5349
|
+
await step.fail(error, failParams, options);
|
|
5350
|
+
throw error;
|
|
5351
|
+
}
|
|
5352
|
+
}
|
|
5353
|
+
};
|
|
5354
|
+
function createAgentIdWorkflowTrail(options) {
|
|
5355
|
+
return new AgentIDWorkflowTrail(options);
|
|
5356
|
+
}
|
|
5357
|
+
|
|
5358
|
+
// src/message-history.ts
|
|
5359
|
+
function isPlainRecord(value) {
|
|
5360
|
+
if (!value || typeof value !== "object") return false;
|
|
5361
|
+
const proto = Object.getPrototypeOf(value);
|
|
5362
|
+
return proto === Object.prototype || proto === null;
|
|
5363
|
+
}
|
|
5364
|
+
function protectMessageHistory(messages, options = { pii: true, secrets: true }) {
|
|
5365
|
+
const piiManager = new PIIManager();
|
|
5366
|
+
let textPartsCount = 0;
|
|
5367
|
+
let transformedTextPartsCount = 0;
|
|
5368
|
+
const protectString = (value) => {
|
|
5369
|
+
textPartsCount += 1;
|
|
5370
|
+
const masked = piiManager.anonymize(value, options).maskedText;
|
|
5371
|
+
if (masked !== value) {
|
|
5372
|
+
transformedTextPartsCount += 1;
|
|
5373
|
+
}
|
|
5374
|
+
return masked;
|
|
5375
|
+
};
|
|
5376
|
+
const visit = (value, key) => {
|
|
5377
|
+
if (typeof value === "string") {
|
|
5378
|
+
return key === "content" || key === "text" ? protectString(value) : value;
|
|
5379
|
+
}
|
|
5380
|
+
if (Array.isArray(value)) {
|
|
5381
|
+
let changed = false;
|
|
5382
|
+
const next = value.map((item) => {
|
|
5383
|
+
const protectedItem = visit(item);
|
|
5384
|
+
if (protectedItem !== item) changed = true;
|
|
5385
|
+
return protectedItem;
|
|
5386
|
+
});
|
|
5387
|
+
return changed ? next : value;
|
|
5388
|
+
}
|
|
5389
|
+
if (isPlainRecord(value)) {
|
|
5390
|
+
let changed = false;
|
|
5391
|
+
const next = {};
|
|
5392
|
+
for (const [entryKey, entryValue] of Object.entries(value)) {
|
|
5393
|
+
const protectedValue = visit(entryValue, entryKey);
|
|
5394
|
+
next[entryKey] = protectedValue;
|
|
5395
|
+
if (protectedValue !== entryValue) changed = true;
|
|
5396
|
+
}
|
|
5397
|
+
return changed ? next : value;
|
|
5398
|
+
}
|
|
5399
|
+
return value;
|
|
5400
|
+
};
|
|
5401
|
+
const protectedMessages = visit(messages);
|
|
5402
|
+
return {
|
|
5403
|
+
messages: protectedMessages,
|
|
5404
|
+
transformed: protectedMessages !== messages,
|
|
5405
|
+
textPartsCount,
|
|
5406
|
+
transformedTextPartsCount
|
|
5407
|
+
};
|
|
5408
|
+
}
|
|
3929
5409
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3930
5410
|
0 && (module.exports = {
|
|
3931
5411
|
AgentID,
|
|
5412
|
+
AgentIDWorkflowStep,
|
|
5413
|
+
AgentIDWorkflowTrail,
|
|
3932
5414
|
DependencyError,
|
|
3933
5415
|
InjectionScanner,
|
|
3934
5416
|
OpenAIAdapter,
|
|
3935
5417
|
PIIManager,
|
|
3936
5418
|
SecurityBlockError,
|
|
5419
|
+
createAgentIdCorrelationId,
|
|
5420
|
+
createAgentIdOperationLog,
|
|
5421
|
+
createAgentIdTelemetryContext,
|
|
5422
|
+
createAgentIdWorkflowTrail,
|
|
3937
5423
|
getInjectionScanner,
|
|
5424
|
+
protectMessageHistory,
|
|
3938
5425
|
scanWithRegex
|
|
3939
5426
|
});
|