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