agentid-sdk 0.1.37 → 0.1.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +203 -48
- package/dist/agentid-CxVUF_eo.d.mts +399 -0
- package/dist/agentid-CxVUF_eo.d.ts +399 -0
- package/dist/{chunk-HWES3LI2.mjs → chunk-AIGMQSAV.mjs} +1495 -154
- package/dist/index.d.mts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +1500 -153
- 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,6 +3618,9 @@ var AgentID = class {
|
|
|
2636
3618
|
get piiMasking() {
|
|
2637
3619
|
return this.configuredPiiMasking ?? void 0;
|
|
2638
3620
|
}
|
|
3621
|
+
get secretMasking() {
|
|
3622
|
+
return this.configuredSecretMasking ?? void 0;
|
|
3623
|
+
}
|
|
2639
3624
|
resolveEffectivePiiMasking(config) {
|
|
2640
3625
|
if (config?.enable_sdk_pii_masking === true) {
|
|
2641
3626
|
return true;
|
|
@@ -2645,12 +3630,24 @@ var AgentID = class {
|
|
|
2645
3630
|
}
|
|
2646
3631
|
return false;
|
|
2647
3632
|
}
|
|
3633
|
+
resolveEffectiveSecretMasking(config) {
|
|
3634
|
+
if (config?.enable_sdk_secret_masking === true || config?.enable_sdk_pii_masking === true) {
|
|
3635
|
+
return true;
|
|
3636
|
+
}
|
|
3637
|
+
if (this.configuredSecretMasking !== null) {
|
|
3638
|
+
return this.configuredSecretMasking;
|
|
3639
|
+
}
|
|
3640
|
+
return false;
|
|
3641
|
+
}
|
|
2648
3642
|
getEffectivePiiMasking(options) {
|
|
2649
3643
|
return this.resolveEffectivePiiMasking(this.getCachedCapabilityConfig(options));
|
|
2650
3644
|
}
|
|
2651
3645
|
getEffectivePiiMaskingForConfig(capabilityConfig) {
|
|
2652
3646
|
return this.resolveEffectivePiiMasking(capabilityConfig);
|
|
2653
3647
|
}
|
|
3648
|
+
getEffectiveSecretMaskingForConfig(capabilityConfig) {
|
|
3649
|
+
return this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3650
|
+
}
|
|
2654
3651
|
buildClientCapabilities(framework = "js_sdk", hasFeedbackHandler = false, capabilityConfig) {
|
|
2655
3652
|
return {
|
|
2656
3653
|
capabilities: {
|
|
@@ -2658,6 +3655,9 @@ var AgentID = class {
|
|
|
2658
3655
|
pii_masking_enabled: this.resolveEffectivePiiMasking(
|
|
2659
3656
|
capabilityConfig ?? this.getCachedCapabilityConfig()
|
|
2660
3657
|
),
|
|
3658
|
+
secret_masking_enabled: this.resolveEffectiveSecretMasking(
|
|
3659
|
+
capabilityConfig ?? this.getCachedCapabilityConfig()
|
|
3660
|
+
),
|
|
2661
3661
|
framework
|
|
2662
3662
|
}
|
|
2663
3663
|
};
|
|
@@ -2797,10 +3797,13 @@ var AgentID = class {
|
|
|
2797
3797
|
systemId: params.systemId,
|
|
2798
3798
|
eventId: params.clientEventId,
|
|
2799
3799
|
clientEventId: params.clientEventId,
|
|
2800
|
-
telemetryMetadata:
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
3800
|
+
telemetryMetadata: mergeTelemetryContexts(
|
|
3801
|
+
params.telemetryMetadata,
|
|
3802
|
+
buildSdkTimingMetadata({
|
|
3803
|
+
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
3804
|
+
sdkConfigVersion: params.capabilityConfig.version
|
|
3805
|
+
})
|
|
3806
|
+
)
|
|
2804
3807
|
});
|
|
2805
3808
|
}
|
|
2806
3809
|
try {
|
|
@@ -2817,7 +3820,8 @@ var AgentID = class {
|
|
|
2817
3820
|
actionTaken: event.actionTaken,
|
|
2818
3821
|
apiKey: params.apiKey,
|
|
2819
3822
|
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
2820
|
-
sdkLocalScanMs
|
|
3823
|
+
sdkLocalScanMs,
|
|
3824
|
+
telemetryMetadata: params.telemetryMetadata
|
|
2821
3825
|
});
|
|
2822
3826
|
}
|
|
2823
3827
|
return {
|
|
@@ -2832,7 +3836,8 @@ var AgentID = class {
|
|
|
2832
3836
|
actionTaken: error.actionTaken,
|
|
2833
3837
|
apiKey: params.apiKey,
|
|
2834
3838
|
sdkConfigFetchMs: params.sdkConfigFetchMs,
|
|
2835
|
-
sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
|
|
3839
|
+
sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt),
|
|
3840
|
+
telemetryMetadata: params.telemetryMetadata
|
|
2836
3841
|
});
|
|
2837
3842
|
}
|
|
2838
3843
|
throw error;
|
|
@@ -2846,7 +3851,7 @@ var AgentID = class {
|
|
|
2846
3851
|
);
|
|
2847
3852
|
let sanitizedInput = params.input;
|
|
2848
3853
|
let sdkLocalScanMs = 0;
|
|
2849
|
-
if (this.configuredPiiMasking === null) {
|
|
3854
|
+
if (this.configuredPiiMasking === null || this.configuredSecretMasking === null) {
|
|
2850
3855
|
const refreshed = await this.refreshCapabilityConfigBeforeClientControl({
|
|
2851
3856
|
capabilityConfig,
|
|
2852
3857
|
sdkConfigFetchMs,
|
|
@@ -2857,8 +3862,12 @@ var AgentID = class {
|
|
|
2857
3862
|
}
|
|
2858
3863
|
if (!this.clientFastFail) {
|
|
2859
3864
|
const effectivePiiMasking2 = this.resolveEffectivePiiMasking(capabilityConfig);
|
|
2860
|
-
|
|
2861
|
-
|
|
3865
|
+
const effectiveSecretMasking2 = this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3866
|
+
if (!capabilityConfig.block_pii_leakage && effectivePiiMasking2 || !capabilityConfig.block_secret_leakage && effectiveSecretMasking2) {
|
|
3867
|
+
const masked = this.pii.anonymize(sanitizedInput, {
|
|
3868
|
+
pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking2,
|
|
3869
|
+
secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking2
|
|
3870
|
+
});
|
|
2862
3871
|
return {
|
|
2863
3872
|
sanitizedInput: masked.maskedText,
|
|
2864
3873
|
capabilityConfig,
|
|
@@ -2890,13 +3899,18 @@ var AgentID = class {
|
|
|
2890
3899
|
apiKey: effectiveApiKey,
|
|
2891
3900
|
clientEventId: params.clientEventId,
|
|
2892
3901
|
sdkConfigFetchMs,
|
|
3902
|
+
telemetryMetadata: params.telemetryMetadata,
|
|
2893
3903
|
runPromptInjectionCheck: !params.skipInjectionScan
|
|
2894
3904
|
});
|
|
2895
3905
|
sanitizedInput = enforced.sanitizedInput;
|
|
2896
3906
|
sdkLocalScanMs = enforced.sdkLocalScanMs;
|
|
2897
3907
|
const effectivePiiMasking = this.resolveEffectivePiiMasking(capabilityConfig);
|
|
2898
|
-
|
|
2899
|
-
|
|
3908
|
+
const effectiveSecretMasking = this.resolveEffectiveSecretMasking(capabilityConfig);
|
|
3909
|
+
if (!capabilityConfig.block_pii_leakage && effectivePiiMasking || !capabilityConfig.block_secret_leakage && effectiveSecretMasking) {
|
|
3910
|
+
const masked = this.pii.anonymize(sanitizedInput, {
|
|
3911
|
+
pii: !capabilityConfig.block_pii_leakage && effectivePiiMasking,
|
|
3912
|
+
secrets: !capabilityConfig.block_secret_leakage && effectiveSecretMasking
|
|
3913
|
+
});
|
|
2900
3914
|
return {
|
|
2901
3915
|
sanitizedInput: masked.maskedText,
|
|
2902
3916
|
capabilityConfig,
|
|
@@ -2932,6 +3946,7 @@ var AgentID = class {
|
|
|
2932
3946
|
apiKey: effectiveApiKey,
|
|
2933
3947
|
clientEventId: params.clientEventId,
|
|
2934
3948
|
sdkConfigFetchMs: refreshedConfig.sdkConfigFetchMs,
|
|
3949
|
+
telemetryMetadata: params.telemetryMetadata,
|
|
2935
3950
|
runPromptInjectionCheck: true
|
|
2936
3951
|
});
|
|
2937
3952
|
return {
|
|
@@ -2995,9 +4010,30 @@ var AgentID = class {
|
|
|
2995
4010
|
if (!message || typeof message !== "object") {
|
|
2996
4011
|
return req;
|
|
2997
4012
|
}
|
|
4013
|
+
const currentContent = message.content;
|
|
4014
|
+
let nextContent = maskedText;
|
|
4015
|
+
if (Array.isArray(currentContent)) {
|
|
4016
|
+
let textReplaced = false;
|
|
4017
|
+
const preservedParts = [];
|
|
4018
|
+
for (const part of currentContent) {
|
|
4019
|
+
if (!part || typeof part !== "object" || part.type !== "text" || typeof part.text !== "string") {
|
|
4020
|
+
preservedParts.push(part);
|
|
4021
|
+
continue;
|
|
4022
|
+
}
|
|
4023
|
+
if (textReplaced) {
|
|
4024
|
+
continue;
|
|
4025
|
+
}
|
|
4026
|
+
textReplaced = true;
|
|
4027
|
+
preservedParts.push({
|
|
4028
|
+
...part,
|
|
4029
|
+
text: maskedText
|
|
4030
|
+
});
|
|
4031
|
+
}
|
|
4032
|
+
nextContent = textReplaced ? preservedParts : [{ type: "text", text: maskedText }, ...currentContent];
|
|
4033
|
+
}
|
|
2998
4034
|
newMessages[lastUserIdx] = {
|
|
2999
4035
|
...message,
|
|
3000
|
-
content:
|
|
4036
|
+
content: nextContent
|
|
3001
4037
|
};
|
|
3002
4038
|
if (!req || typeof req !== "object") {
|
|
3003
4039
|
return req;
|
|
@@ -3016,6 +4052,7 @@ var AgentID = class {
|
|
|
3016
4052
|
event_type: "security_policy_violation",
|
|
3017
4053
|
severity: "high",
|
|
3018
4054
|
metadata: {
|
|
4055
|
+
...params.telemetryMetadata ?? {},
|
|
3019
4056
|
event_type: "security_policy_violation",
|
|
3020
4057
|
severity: "high",
|
|
3021
4058
|
system_id: params.systemId,
|
|
@@ -3043,6 +4080,7 @@ var AgentID = class {
|
|
|
3043
4080
|
event_type: "security_alert",
|
|
3044
4081
|
severity: "warning",
|
|
3045
4082
|
metadata: {
|
|
4083
|
+
...params.guardParams.metadata ?? {},
|
|
3046
4084
|
source: "guard",
|
|
3047
4085
|
status: params.status,
|
|
3048
4086
|
guard_reason: params.reason,
|
|
@@ -3485,21 +4523,29 @@ var AgentID = class {
|
|
|
3485
4523
|
wrapCompletion(completion, options) {
|
|
3486
4524
|
if (typeof completion === "string") {
|
|
3487
4525
|
const masked = this.pii.anonymize(completion);
|
|
4526
|
+
const placeholderOutputMasked = textContainsMappingPlaceholder(
|
|
4527
|
+
completion,
|
|
4528
|
+
options?.piiMapping
|
|
4529
|
+
);
|
|
3488
4530
|
return {
|
|
3489
4531
|
mode: "static",
|
|
3490
4532
|
rawOutput: completion,
|
|
3491
4533
|
transformedOutput: masked.maskedText,
|
|
3492
|
-
outputMasked: masked.maskedText !== completion
|
|
4534
|
+
outputMasked: masked.maskedText !== completion || placeholderOutputMasked
|
|
3493
4535
|
};
|
|
3494
4536
|
}
|
|
3495
4537
|
if (!isAsyncIterable(completion)) {
|
|
3496
4538
|
const asText = String(completion ?? "");
|
|
3497
4539
|
const masked = this.pii.anonymize(asText);
|
|
4540
|
+
const placeholderOutputMasked = textContainsMappingPlaceholder(
|
|
4541
|
+
asText,
|
|
4542
|
+
options?.piiMapping
|
|
4543
|
+
);
|
|
3498
4544
|
return {
|
|
3499
4545
|
mode: "static",
|
|
3500
4546
|
rawOutput: asText,
|
|
3501
4547
|
transformedOutput: masked.maskedText,
|
|
3502
|
-
outputMasked: masked.maskedText !== asText
|
|
4548
|
+
outputMasked: masked.maskedText !== asText || placeholderOutputMasked
|
|
3503
4549
|
};
|
|
3504
4550
|
}
|
|
3505
4551
|
const source = completion;
|
|
@@ -3509,8 +4555,10 @@ var AgentID = class {
|
|
|
3509
4555
|
const isOpenAIStreamFinishChunk = this.isOpenAIStreamFinishChunk.bind(this);
|
|
3510
4556
|
const rewriteOpenAIStreamChunkForClient = this.rewriteOpenAIStreamChunkForClient.bind(this);
|
|
3511
4557
|
const createSyntheticOpenAIStreamChunk = this.createSyntheticOpenAIStreamChunk.bind(this);
|
|
4558
|
+
const setOpenAIStreamChunkText = this.setOpenAIStreamChunkText.bind(this);
|
|
3512
4559
|
const piiManager = this.pii;
|
|
3513
4560
|
const streamRewriter = options?.deanonymizeForClient === true && options.piiMapping ? createStreamingPlaceholderRewriter(piiManager, options.piiMapping) : null;
|
|
4561
|
+
const maskForClient = options?.maskForClient === true && streamRewriter === null;
|
|
3514
4562
|
let lastUsage;
|
|
3515
4563
|
let resolveDone = null;
|
|
3516
4564
|
let rejectDone = null;
|
|
@@ -3523,12 +4571,17 @@ var AgentID = class {
|
|
|
3523
4571
|
try {
|
|
3524
4572
|
let finishChunkFlushed = false;
|
|
3525
4573
|
let lastChunkTemplate;
|
|
4574
|
+
let clientRawText = "";
|
|
4575
|
+
let clientMaskFlushed = false;
|
|
3526
4576
|
for await (const chunk of source) {
|
|
3527
4577
|
const chunkText = extractStreamChunkText(chunk);
|
|
3528
|
-
const isFinishChunk = streamRewriter ? isOpenAIStreamFinishChunk(chunk) : false;
|
|
4578
|
+
const isFinishChunk = streamRewriter || maskForClient ? isOpenAIStreamFinishChunk(chunk) : false;
|
|
3529
4579
|
if (chunkText) {
|
|
3530
4580
|
await collector.push(chunkText);
|
|
3531
4581
|
lastChunkTemplate = chunk;
|
|
4582
|
+
if (maskForClient) {
|
|
4583
|
+
clientRawText += chunkText;
|
|
4584
|
+
}
|
|
3532
4585
|
}
|
|
3533
4586
|
const chunkUsage = extractStreamChunkUsage(chunk);
|
|
3534
4587
|
if (chunkUsage) {
|
|
@@ -3548,6 +4601,28 @@ var AgentID = class {
|
|
|
3548
4601
|
}
|
|
3549
4602
|
continue;
|
|
3550
4603
|
}
|
|
4604
|
+
if (maskForClient) {
|
|
4605
|
+
if (isFinishChunk) {
|
|
4606
|
+
const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
|
|
4607
|
+
clientMaskFlushed = true;
|
|
4608
|
+
if (maskedClientText.length > 0) {
|
|
4609
|
+
yield createSyntheticOpenAIStreamChunk(
|
|
4610
|
+
maskedClientText,
|
|
4611
|
+
lastChunkTemplate ?? chunk
|
|
4612
|
+
);
|
|
4613
|
+
}
|
|
4614
|
+
if (chunkText) {
|
|
4615
|
+
setOpenAIStreamChunkText(chunk, "");
|
|
4616
|
+
}
|
|
4617
|
+
yield chunk;
|
|
4618
|
+
finishChunkFlushed = true;
|
|
4619
|
+
continue;
|
|
4620
|
+
}
|
|
4621
|
+
if (!chunkText) {
|
|
4622
|
+
yield chunk;
|
|
4623
|
+
}
|
|
4624
|
+
continue;
|
|
4625
|
+
}
|
|
3551
4626
|
yield chunk;
|
|
3552
4627
|
}
|
|
3553
4628
|
if (streamRewriter && !finishChunkFlushed) {
|
|
@@ -3559,14 +4634,27 @@ var AgentID = class {
|
|
|
3559
4634
|
);
|
|
3560
4635
|
}
|
|
3561
4636
|
}
|
|
4637
|
+
if (maskForClient && !clientMaskFlushed) {
|
|
4638
|
+
const maskedClientText = piiManager.anonymize(clientRawText).maskedText;
|
|
4639
|
+
if (maskedClientText.length > 0) {
|
|
4640
|
+
yield createSyntheticOpenAIStreamChunk(
|
|
4641
|
+
maskedClientText,
|
|
4642
|
+
lastChunkTemplate
|
|
4643
|
+
);
|
|
4644
|
+
}
|
|
4645
|
+
}
|
|
3562
4646
|
await collector.close();
|
|
3563
4647
|
const rawOutput = await collector.result;
|
|
3564
4648
|
const masked = piiManager.anonymize(rawOutput);
|
|
4649
|
+
const placeholderOutputMasked = textContainsMappingPlaceholder(
|
|
4650
|
+
rawOutput,
|
|
4651
|
+
options?.piiMapping
|
|
4652
|
+
);
|
|
3565
4653
|
resolveDone?.({
|
|
3566
4654
|
mode: "static",
|
|
3567
4655
|
rawOutput,
|
|
3568
4656
|
transformedOutput: masked.maskedText,
|
|
3569
|
-
outputMasked: masked.maskedText !== rawOutput,
|
|
4657
|
+
outputMasked: masked.maskedText !== rawOutput || placeholderOutputMasked,
|
|
3570
4658
|
usage: lastUsage
|
|
3571
4659
|
});
|
|
3572
4660
|
} catch (error) {
|
|
@@ -3601,6 +4689,37 @@ var AgentID = class {
|
|
|
3601
4689
|
);
|
|
3602
4690
|
}
|
|
3603
4691
|
}
|
|
4692
|
+
buildOperationLogParams(params) {
|
|
4693
|
+
return createAgentIdOperationLog(params);
|
|
4694
|
+
}
|
|
4695
|
+
async logOperation(params, options) {
|
|
4696
|
+
return this.log(this.buildOperationLogParams(params), options);
|
|
4697
|
+
}
|
|
4698
|
+
async logPromptPreflightStep(params, options) {
|
|
4699
|
+
const telemetry = buildPromptPreflightTelemetry(params);
|
|
4700
|
+
const summary = firstNonEmptyString(telemetry?.step_summary, telemetry?.stepSummary) ?? summarizePromptPreflightResult({
|
|
4701
|
+
verdict: params.verdict,
|
|
4702
|
+
localFallbackApplied: params.local_fallback_applied,
|
|
4703
|
+
localFallbackReason: params.local_fallback_reason
|
|
4704
|
+
});
|
|
4705
|
+
await this.logOperation(
|
|
4706
|
+
{
|
|
4707
|
+
system_id: params.system_id,
|
|
4708
|
+
user_id: params.user_id,
|
|
4709
|
+
request_identity: params.request_identity,
|
|
4710
|
+
input: params.input,
|
|
4711
|
+
output: summary,
|
|
4712
|
+
model: "not_applicable",
|
|
4713
|
+
latency: params.guard_latency_ms ?? void 0,
|
|
4714
|
+
telemetry,
|
|
4715
|
+
client_capabilities: params.client_capabilities
|
|
4716
|
+
},
|
|
4717
|
+
options
|
|
4718
|
+
);
|
|
4719
|
+
}
|
|
4720
|
+
operation(params, options) {
|
|
4721
|
+
return this.logOperation(params, options);
|
|
4722
|
+
}
|
|
3604
4723
|
/**
|
|
3605
4724
|
* Analytics alias for telemetry logging.
|
|
3606
4725
|
*/
|
|
@@ -3645,49 +4764,56 @@ var AgentID = class {
|
|
|
3645
4764
|
if (typeof originalCreate !== "function") return originalCreate;
|
|
3646
4765
|
return async (...args) => {
|
|
3647
4766
|
const normalizedCreateArgs = normalizeOpenAICreateArgs(args);
|
|
3648
|
-
const
|
|
4767
|
+
const rawReq = normalizedCreateArgs?.[0] ?? {};
|
|
4768
|
+
const requestTelemetry = extractRequestTelemetryContext(rawReq);
|
|
4769
|
+
const telemetryMetadata = mergeTelemetryContexts(
|
|
4770
|
+
options.telemetry,
|
|
4771
|
+
requestTelemetry
|
|
4772
|
+
);
|
|
4773
|
+
const providerReq = stripRequestTelemetryContext(rawReq);
|
|
3649
4774
|
const pipelineStartedAt = Date.now();
|
|
3650
|
-
const requestLevelApiKey = options.resolveApiKey?.(
|
|
4775
|
+
const requestLevelApiKey = options.resolveApiKey?.(rawReq) ?? options.apiKey ?? options.api_key;
|
|
3651
4776
|
const effectiveApiKey = this.resolveApiKey(requestLevelApiKey);
|
|
3652
4777
|
const requestOptions = { apiKey: effectiveApiKey };
|
|
3653
|
-
const clientEventId = this.resolveClientEventId(
|
|
4778
|
+
const clientEventId = this.resolveClientEventId(rawReq);
|
|
3654
4779
|
const effectiveStrictMode = await this.resolveEffectiveStrictMode(requestOptions);
|
|
3655
|
-
const stream = adapter.isStream(
|
|
4780
|
+
const stream = adapter.isStream(providerReq);
|
|
3656
4781
|
let capabilityConfig = this.getCachedCapabilityConfig(requestOptions);
|
|
3657
|
-
const userText = adapter.extractInput(
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
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)];
|
|
3661
4788
|
let mapping = {};
|
|
3662
|
-
let shouldDeanonymize = false;
|
|
3663
4789
|
let sdkConfigFetchMs = 0;
|
|
3664
4790
|
let sdkLocalScanMs = 0;
|
|
3665
|
-
if (
|
|
4791
|
+
if (hasGuardContent) {
|
|
3666
4792
|
const prepared = await this.prepareInputForDispatch({
|
|
3667
|
-
input: userText,
|
|
4793
|
+
input: userText ?? "",
|
|
3668
4794
|
systemId,
|
|
3669
4795
|
stream,
|
|
3670
|
-
clientEventId
|
|
4796
|
+
clientEventId,
|
|
4797
|
+
telemetryMetadata
|
|
3671
4798
|
}, requestOptions);
|
|
3672
4799
|
capabilityConfig = prepared.capabilityConfig;
|
|
3673
4800
|
maskedText = prepared.sanitizedInput;
|
|
3674
4801
|
mapping = prepared.piiMapping ?? {};
|
|
3675
|
-
shouldDeanonymize = prepared.shouldDeanonymize === true;
|
|
3676
4802
|
sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
|
|
3677
4803
|
sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
|
|
3678
|
-
if (maskedText !== userText) {
|
|
4804
|
+
if (maskedText !== (userText ?? "")) {
|
|
3679
4805
|
maskedReq = this.withMaskedOpenAIRequest(
|
|
3680
|
-
|
|
4806
|
+
providerReq,
|
|
3681
4807
|
maskedText
|
|
3682
4808
|
);
|
|
3683
|
-
const nextCreateArgs = [...
|
|
4809
|
+
const nextCreateArgs = [...createArgs];
|
|
3684
4810
|
nextCreateArgs[0] = maskedReq;
|
|
3685
4811
|
createArgs = nextCreateArgs;
|
|
3686
4812
|
}
|
|
3687
4813
|
}
|
|
3688
|
-
if (!
|
|
4814
|
+
if (!hasGuardContent) {
|
|
3689
4815
|
throw new Error(
|
|
3690
|
-
"AgentID: No user message found. Security guard requires
|
|
4816
|
+
"AgentID: No user message or supported inline attachment found. Security guard requires prompt content."
|
|
3691
4817
|
);
|
|
3692
4818
|
}
|
|
3693
4819
|
const verdict = await this.guard({
|
|
@@ -3698,6 +4824,8 @@ var AgentID = class {
|
|
|
3698
4824
|
client_event_id: clientEventId,
|
|
3699
4825
|
expected_languages: expectedLanguages,
|
|
3700
4826
|
request_identity: options.request_identity,
|
|
4827
|
+
metadata: telemetryMetadata,
|
|
4828
|
+
attachments: requestAttachments,
|
|
3701
4829
|
client_capabilities: this.buildClientCapabilities(
|
|
3702
4830
|
"openai",
|
|
3703
4831
|
false,
|
|
@@ -3719,22 +4847,43 @@ var AgentID = class {
|
|
|
3719
4847
|
apiKey: effectiveApiKey,
|
|
3720
4848
|
clientEventId,
|
|
3721
4849
|
sdkConfigFetchMs,
|
|
4850
|
+
telemetryMetadata,
|
|
3722
4851
|
runPromptInjectionCheck: true
|
|
3723
4852
|
});
|
|
3724
4853
|
maskedText = fallback.sanitizedInput;
|
|
3725
4854
|
sdkLocalScanMs = fallback.sdkLocalScanMs;
|
|
3726
4855
|
}
|
|
3727
4856
|
} else {
|
|
4857
|
+
await this.logPromptPreflightStep(
|
|
4858
|
+
{
|
|
4859
|
+
system_id: systemId,
|
|
4860
|
+
user_id: options.user_id,
|
|
4861
|
+
request_identity: options.request_identity,
|
|
4862
|
+
input: maskedText,
|
|
4863
|
+
telemetry: telemetryMetadata,
|
|
4864
|
+
verdict,
|
|
4865
|
+
guard_event_id: verdict.guard_event_id ?? null,
|
|
4866
|
+
guard_latency_ms: typeof verdict.guard_latency_ms === "number" && Number.isFinite(verdict.guard_latency_ms) ? Math.max(0, Math.trunc(verdict.guard_latency_ms)) : Math.max(0, Date.now() - pipelineStartedAt),
|
|
4867
|
+
preflight_for_client_event_id: typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId,
|
|
4868
|
+
client_capabilities: this.buildClientCapabilities(
|
|
4869
|
+
"openai",
|
|
4870
|
+
false,
|
|
4871
|
+
capabilityConfig
|
|
4872
|
+
),
|
|
4873
|
+
runtime_surface: "openai_sdk_guard"
|
|
4874
|
+
},
|
|
4875
|
+
requestOptions
|
|
4876
|
+
);
|
|
3728
4877
|
throw new SecurityBlockError(verdict.reason ?? "guard_denied");
|
|
3729
4878
|
}
|
|
3730
4879
|
}
|
|
3731
|
-
const currentRequestInput = adapter.extractInput(maskedReq);
|
|
4880
|
+
const currentRequestInput = adapter.extractInput(maskedReq) ?? "";
|
|
3732
4881
|
if (maskedText !== currentRequestInput) {
|
|
3733
4882
|
maskedReq = this.withMaskedOpenAIRequest(
|
|
3734
|
-
|
|
4883
|
+
providerReq,
|
|
3735
4884
|
maskedText
|
|
3736
4885
|
);
|
|
3737
|
-
const nextCreateArgs = [...
|
|
4886
|
+
const nextCreateArgs = [...createArgs];
|
|
3738
4887
|
nextCreateArgs[0] = maskedReq;
|
|
3739
4888
|
createArgs = nextCreateArgs;
|
|
3740
4889
|
}
|
|
@@ -3745,15 +4894,44 @@ var AgentID = class {
|
|
|
3745
4894
|
const isShadowMode = verdict.shadow_mode === true;
|
|
3746
4895
|
const transformedInput = isShadowMode ? maskedText : typeof verdict.transformed_input === "string" && verdict.transformed_input.length > 0 ? verdict.transformed_input : maskedText;
|
|
3747
4896
|
if (transformedInput !== maskedText) {
|
|
4897
|
+
const serverDerivedMapping = derivePlaceholderMappingFromTransform(
|
|
4898
|
+
maskedText,
|
|
4899
|
+
transformedInput
|
|
4900
|
+
);
|
|
4901
|
+
if (Object.keys(serverDerivedMapping).length > 0) {
|
|
4902
|
+
mapping = mergePiiMappings(mapping, serverDerivedMapping);
|
|
4903
|
+
}
|
|
3748
4904
|
maskedText = transformedInput;
|
|
3749
4905
|
maskedReq = this.withMaskedOpenAIRequest(
|
|
3750
|
-
|
|
4906
|
+
providerReq,
|
|
3751
4907
|
transformedInput
|
|
3752
4908
|
);
|
|
3753
|
-
const nextCreateArgs = [...
|
|
4909
|
+
const nextCreateArgs = [...createArgs];
|
|
3754
4910
|
nextCreateArgs[0] = maskedReq;
|
|
3755
4911
|
createArgs = nextCreateArgs;
|
|
3756
4912
|
}
|
|
4913
|
+
await this.logPromptPreflightStep(
|
|
4914
|
+
{
|
|
4915
|
+
system_id: systemId,
|
|
4916
|
+
user_id: options.user_id,
|
|
4917
|
+
request_identity: options.request_identity,
|
|
4918
|
+
input: maskedText,
|
|
4919
|
+
telemetry: telemetryMetadata,
|
|
4920
|
+
verdict,
|
|
4921
|
+
guard_event_id: guardEventId,
|
|
4922
|
+
guard_latency_ms: guardLatencyMs,
|
|
4923
|
+
preflight_for_client_event_id: canonicalClientEventId,
|
|
4924
|
+
client_capabilities: this.buildClientCapabilities(
|
|
4925
|
+
"openai",
|
|
4926
|
+
false,
|
|
4927
|
+
capabilityConfig
|
|
4928
|
+
),
|
|
4929
|
+
local_fallback_applied: localFallbackApplied,
|
|
4930
|
+
local_fallback_reason: localFallbackReason,
|
|
4931
|
+
runtime_surface: "openai_sdk_guard"
|
|
4932
|
+
},
|
|
4933
|
+
requestOptions
|
|
4934
|
+
);
|
|
3757
4935
|
if (stream) {
|
|
3758
4936
|
const modelStartedAt2 = Date.now();
|
|
3759
4937
|
const streamResponse = await originalCreate.apply(compTarget, createArgs);
|
|
@@ -3765,7 +4943,8 @@ var AgentID = class {
|
|
|
3765
4943
|
})(),
|
|
3766
4944
|
{
|
|
3767
4945
|
piiMapping: mapping,
|
|
3768
|
-
deanonymizeForClient:
|
|
4946
|
+
deanonymizeForClient: false,
|
|
4947
|
+
maskForClient: !isShadowMode
|
|
3769
4948
|
}
|
|
3770
4949
|
);
|
|
3771
4950
|
if (maskedText && wrappedCompletion.mode === "stream") {
|
|
@@ -3784,29 +4963,32 @@ var AgentID = class {
|
|
|
3784
4963
|
usage: result.usage,
|
|
3785
4964
|
latency: modelLatencyMs2,
|
|
3786
4965
|
event_type: "complete",
|
|
3787
|
-
metadata:
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
4966
|
+
metadata: mergeTelemetryContexts(
|
|
4967
|
+
telemetryMetadata,
|
|
4968
|
+
{
|
|
4969
|
+
transformed_input: maskedText,
|
|
4970
|
+
transformed_output: result.transformedOutput,
|
|
4971
|
+
output_masked: result.outputMasked,
|
|
4972
|
+
shadow_mode: isShadowMode,
|
|
4973
|
+
simulated_decision: verdict.simulated_decision ?? null,
|
|
4974
|
+
simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
|
|
4975
|
+
response_streamed: true,
|
|
4976
|
+
sdk_local_fallback_applied: localFallbackApplied,
|
|
4977
|
+
sdk_local_fallback_reason: localFallbackReason,
|
|
4978
|
+
guard_latency_ms: guardLatencyMs,
|
|
4979
|
+
model_latency_ms: modelLatencyMs2,
|
|
4980
|
+
total_pipeline_latency_ms: totalPipelineLatencyMs2,
|
|
4981
|
+
guard_event_id: guardEventId,
|
|
4982
|
+
client_event_id: canonicalClientEventId,
|
|
4983
|
+
transparency
|
|
4984
|
+
},
|
|
4985
|
+
buildSdkTimingMetadata({
|
|
3804
4986
|
sdkConfigFetchMs,
|
|
3805
4987
|
sdkLocalScanMs,
|
|
3806
4988
|
sdkGuardMs: guardLatencyMs,
|
|
3807
4989
|
sdkConfigVersion: capabilityConfig.version
|
|
3808
4990
|
})
|
|
3809
|
-
|
|
4991
|
+
),
|
|
3810
4992
|
client_capabilities: this.buildClientCapabilities(
|
|
3811
4993
|
"openai",
|
|
3812
4994
|
false,
|
|
@@ -3837,7 +5019,10 @@ var AgentID = class {
|
|
|
3837
5019
|
const totalPipelineLatencyMs = Math.max(0, Date.now() - pipelineStartedAt);
|
|
3838
5020
|
if (maskedText) {
|
|
3839
5021
|
const output = adapter.extractOutput(res);
|
|
3840
|
-
const wrappedCompletion = this.wrapCompletion(output
|
|
5022
|
+
const wrappedCompletion = this.wrapCompletion(output, {
|
|
5023
|
+
piiMapping: mapping,
|
|
5024
|
+
deanonymizeForClient: false
|
|
5025
|
+
});
|
|
3841
5026
|
const model = adapter.getModelName(maskedReq, res);
|
|
3842
5027
|
const usage = adapter.getTokenUsage(res);
|
|
3843
5028
|
const outputForLog = isShadowMode ? wrappedCompletion.rawOutput : wrappedCompletion.transformedOutput;
|
|
@@ -3852,29 +5037,32 @@ var AgentID = class {
|
|
|
3852
5037
|
usage,
|
|
3853
5038
|
latency: modelLatencyMs,
|
|
3854
5039
|
event_type: "complete",
|
|
3855
|
-
metadata:
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
5040
|
+
metadata: mergeTelemetryContexts(
|
|
5041
|
+
telemetryMetadata,
|
|
5042
|
+
{
|
|
5043
|
+
transformed_input: maskedText,
|
|
5044
|
+
transformed_output: wrappedCompletion.transformedOutput,
|
|
5045
|
+
output_masked: wrappedCompletion.outputMasked,
|
|
5046
|
+
shadow_mode: isShadowMode,
|
|
5047
|
+
simulated_decision: verdict.simulated_decision ?? null,
|
|
5048
|
+
simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
|
|
5049
|
+
response_streamed: false,
|
|
5050
|
+
sdk_local_fallback_applied: localFallbackApplied,
|
|
5051
|
+
sdk_local_fallback_reason: localFallbackReason,
|
|
5052
|
+
guard_latency_ms: guardLatencyMs,
|
|
5053
|
+
model_latency_ms: modelLatencyMs,
|
|
5054
|
+
total_pipeline_latency_ms: totalPipelineLatencyMs,
|
|
5055
|
+
guard_event_id: guardEventId,
|
|
5056
|
+
client_event_id: canonicalClientEventId,
|
|
5057
|
+
transparency
|
|
5058
|
+
},
|
|
5059
|
+
buildSdkTimingMetadata({
|
|
3872
5060
|
sdkConfigFetchMs,
|
|
3873
5061
|
sdkLocalScanMs,
|
|
3874
5062
|
sdkGuardMs: guardLatencyMs,
|
|
3875
5063
|
sdkConfigVersion: capabilityConfig.version
|
|
3876
5064
|
})
|
|
3877
|
-
|
|
5065
|
+
),
|
|
3878
5066
|
client_capabilities: this.buildClientCapabilities(
|
|
3879
5067
|
"openai",
|
|
3880
5068
|
false,
|
|
@@ -3891,17 +5079,21 @@ var AgentID = class {
|
|
|
3891
5079
|
);
|
|
3892
5080
|
}
|
|
3893
5081
|
}
|
|
3894
|
-
if (!
|
|
3895
|
-
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;
|
|
3896
5088
|
try {
|
|
3897
5089
|
if (Array.isArray(res?.choices)) {
|
|
3898
5090
|
for (const choice of res.choices) {
|
|
3899
5091
|
const typedChoice = choice;
|
|
3900
5092
|
if (typedChoice?.message && typeof typedChoice.message.content === "string") {
|
|
3901
|
-
typedChoice.message.content =
|
|
5093
|
+
typedChoice.message.content = maskedOutput;
|
|
3902
5094
|
}
|
|
3903
5095
|
if (typedChoice?.delta && typeof typedChoice.delta.content === "string") {
|
|
3904
|
-
typedChoice.delta.content =
|
|
5096
|
+
typedChoice.delta.content = maskedOutput;
|
|
3905
5097
|
}
|
|
3906
5098
|
}
|
|
3907
5099
|
}
|
|
@@ -3926,14 +5118,169 @@ var AgentID = class {
|
|
|
3926
5118
|
});
|
|
3927
5119
|
}
|
|
3928
5120
|
};
|
|
5121
|
+
function mergeWorkflowTrailRequestOptions(base, override) {
|
|
5122
|
+
const apiKey = firstNonEmptyString(override?.apiKey, base?.apiKey);
|
|
5123
|
+
return apiKey ? { apiKey } : void 0;
|
|
5124
|
+
}
|
|
5125
|
+
function appendWorkflowErrorMetadata(metadata, error) {
|
|
5126
|
+
const nextMetadata = { ...metadata ?? {} };
|
|
5127
|
+
if (error instanceof Error) {
|
|
5128
|
+
if (typeof nextMetadata.error_name !== "string") {
|
|
5129
|
+
nextMetadata.error_name = error.name;
|
|
5130
|
+
}
|
|
5131
|
+
if (typeof nextMetadata.error_message !== "string" && error.message.trim().length > 0) {
|
|
5132
|
+
nextMetadata.error_message = error.message.trim();
|
|
5133
|
+
}
|
|
5134
|
+
return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
|
|
5135
|
+
}
|
|
5136
|
+
if (typeof nextMetadata.error_message !== "string" && typeof error !== "undefined") {
|
|
5137
|
+
const errorMessage = String(error).trim();
|
|
5138
|
+
if (errorMessage.length > 0) {
|
|
5139
|
+
nextMetadata.error_message = errorMessage;
|
|
5140
|
+
}
|
|
5141
|
+
}
|
|
5142
|
+
return Object.keys(nextMetadata).length > 0 ? nextMetadata : void 0;
|
|
5143
|
+
}
|
|
5144
|
+
var AgentIDWorkflowStep = class {
|
|
5145
|
+
constructor(params) {
|
|
5146
|
+
this.trail = params.trail;
|
|
5147
|
+
this.workflowStepId = params.workflowStepId;
|
|
5148
|
+
this.startEventId = params.startEventId;
|
|
5149
|
+
this.telemetry = params.telemetry;
|
|
5150
|
+
this.startedAtMs = params.startedAtMs;
|
|
5151
|
+
}
|
|
5152
|
+
resolveStepTelemetry(telemetry) {
|
|
5153
|
+
return mergeTelemetryContexts(
|
|
5154
|
+
this.telemetry,
|
|
5155
|
+
createAgentIdTelemetryContext({
|
|
5156
|
+
workflow_step_id: this.workflowStepId,
|
|
5157
|
+
parent_event_id: this.startEventId
|
|
5158
|
+
}),
|
|
5159
|
+
telemetry
|
|
5160
|
+
);
|
|
5161
|
+
}
|
|
5162
|
+
async log(params = {}, options) {
|
|
5163
|
+
return this.trail.logStep(
|
|
5164
|
+
{
|
|
5165
|
+
...params,
|
|
5166
|
+
telemetry: this.resolveStepTelemetry(params.telemetry)
|
|
5167
|
+
},
|
|
5168
|
+
options
|
|
5169
|
+
);
|
|
5170
|
+
}
|
|
5171
|
+
async complete(params = {}, options) {
|
|
5172
|
+
return this.log(
|
|
5173
|
+
{
|
|
5174
|
+
...params,
|
|
5175
|
+
latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
|
|
5176
|
+
event_status: params.event_status ?? "completed"
|
|
5177
|
+
},
|
|
5178
|
+
options
|
|
5179
|
+
);
|
|
5180
|
+
}
|
|
5181
|
+
async fail(error, params = {}, options) {
|
|
5182
|
+
return this.log(
|
|
5183
|
+
{
|
|
5184
|
+
...params,
|
|
5185
|
+
latency: typeof params.latency === "number" ? params.latency : Math.max(0, Date.now() - this.startedAtMs),
|
|
5186
|
+
metadata: appendWorkflowErrorMetadata(params.metadata, error),
|
|
5187
|
+
event_type: params.event_type ?? "error",
|
|
5188
|
+
event_status: params.event_status ?? "failed",
|
|
5189
|
+
severity: params.severity ?? "error"
|
|
5190
|
+
},
|
|
5191
|
+
options
|
|
5192
|
+
);
|
|
5193
|
+
}
|
|
5194
|
+
};
|
|
5195
|
+
var AgentIDWorkflowTrail = class {
|
|
5196
|
+
constructor(options) {
|
|
5197
|
+
this.agent = options.agent;
|
|
5198
|
+
this.systemId = options.system_id;
|
|
5199
|
+
this.userId = options.user_id;
|
|
5200
|
+
this.requestIdentity = options.request_identity;
|
|
5201
|
+
this.telemetry = createAgentIdTelemetryContext(options.telemetry);
|
|
5202
|
+
this.clientCapabilities = options.client_capabilities;
|
|
5203
|
+
this.requestOptions = options.requestOptions;
|
|
5204
|
+
}
|
|
5205
|
+
async logStep(params = {}, options) {
|
|
5206
|
+
const payload = this.agent.buildOperationLogParams({
|
|
5207
|
+
...params,
|
|
5208
|
+
system_id: this.systemId,
|
|
5209
|
+
user_id: this.userId,
|
|
5210
|
+
request_identity: this.requestIdentity,
|
|
5211
|
+
telemetry: mergeTelemetryContexts(this.telemetry, params.telemetry),
|
|
5212
|
+
client_capabilities: params.client_capabilities ?? this.clientCapabilities
|
|
5213
|
+
});
|
|
5214
|
+
await this.agent.log(
|
|
5215
|
+
payload,
|
|
5216
|
+
mergeWorkflowTrailRequestOptions(this.requestOptions, options)
|
|
5217
|
+
);
|
|
5218
|
+
return payload;
|
|
5219
|
+
}
|
|
5220
|
+
async startStep(params = {}, options) {
|
|
5221
|
+
const startedAtMs = Date.now();
|
|
5222
|
+
const requestedTelemetry = createAgentIdTelemetryContext(params.telemetry);
|
|
5223
|
+
const workflowStepId = firstNonEmptyString(requestedTelemetry?.workflow_step_id, requestedTelemetry?.workflowStepId) ?? createAgentIdCorrelationId();
|
|
5224
|
+
const startTelemetry = mergeTelemetryContexts(
|
|
5225
|
+
requestedTelemetry,
|
|
5226
|
+
createAgentIdTelemetryContext({
|
|
5227
|
+
workflow_step_id: workflowStepId
|
|
5228
|
+
})
|
|
5229
|
+
);
|
|
5230
|
+
const startPayload = await this.logStep(
|
|
5231
|
+
{
|
|
5232
|
+
...params,
|
|
5233
|
+
telemetry: startTelemetry,
|
|
5234
|
+
event_type: params.event_type ?? "start",
|
|
5235
|
+
event_status: params.event_status ?? "started"
|
|
5236
|
+
},
|
|
5237
|
+
options
|
|
5238
|
+
);
|
|
5239
|
+
return new AgentIDWorkflowStep({
|
|
5240
|
+
trail: this,
|
|
5241
|
+
workflowStepId,
|
|
5242
|
+
startEventId: startPayload.event_id ?? createEventId2(),
|
|
5243
|
+
telemetry: startTelemetry,
|
|
5244
|
+
startedAtMs
|
|
5245
|
+
});
|
|
5246
|
+
}
|
|
5247
|
+
async runStep(params, run, hooks, options) {
|
|
5248
|
+
const step = await this.startStep(params, options);
|
|
5249
|
+
try {
|
|
5250
|
+
const result = await run();
|
|
5251
|
+
const completeParams = {
|
|
5252
|
+
...hooks?.complete ?? {},
|
|
5253
|
+
...hooks?.onComplete?.(result) ?? {}
|
|
5254
|
+
};
|
|
5255
|
+
await step.complete(completeParams, options);
|
|
5256
|
+
return result;
|
|
5257
|
+
} catch (error) {
|
|
5258
|
+
const failParams = {
|
|
5259
|
+
...hooks?.fail ?? {},
|
|
5260
|
+
...hooks?.onError?.(error) ?? {}
|
|
5261
|
+
};
|
|
5262
|
+
await step.fail(error, failParams, options);
|
|
5263
|
+
throw error;
|
|
5264
|
+
}
|
|
5265
|
+
}
|
|
5266
|
+
};
|
|
5267
|
+
function createAgentIdWorkflowTrail(options) {
|
|
5268
|
+
return new AgentIDWorkflowTrail(options);
|
|
5269
|
+
}
|
|
3929
5270
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3930
5271
|
0 && (module.exports = {
|
|
3931
5272
|
AgentID,
|
|
5273
|
+
AgentIDWorkflowStep,
|
|
5274
|
+
AgentIDWorkflowTrail,
|
|
3932
5275
|
DependencyError,
|
|
3933
5276
|
InjectionScanner,
|
|
3934
5277
|
OpenAIAdapter,
|
|
3935
5278
|
PIIManager,
|
|
3936
5279
|
SecurityBlockError,
|
|
5280
|
+
createAgentIdCorrelationId,
|
|
5281
|
+
createAgentIdOperationLog,
|
|
5282
|
+
createAgentIdTelemetryContext,
|
|
5283
|
+
createAgentIdWorkflowTrail,
|
|
3937
5284
|
getInjectionScanner,
|
|
3938
5285
|
scanWithRegex
|
|
3939
5286
|
});
|