@revenium/anthropic 1.0.9 → 1.1.1
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/CHANGELOG.md +12 -0
- package/README.md +62 -10
- package/dist/cjs/config.js +39 -36
- package/dist/cjs/constants.js +6 -0
- package/dist/cjs/tracking.js +21 -3
- package/dist/cjs/utils/prompt-extraction.js +158 -0
- package/dist/cjs/utils/trace-fields.js +36 -0
- package/dist/cjs/utils/validation.js +105 -69
- package/dist/cjs/wrapper.js +79 -0
- package/dist/esm/config.js +41 -38
- package/dist/esm/constants.js +6 -0
- package/dist/esm/tracking.js +21 -3
- package/dist/esm/utils/prompt-extraction.js +154 -0
- package/dist/esm/utils/trace-fields.js +35 -0
- package/dist/esm/utils/validation.js +106 -70
- package/dist/esm/wrapper.js +79 -0
- package/dist/types/config.d.ts +1 -1
- package/dist/types/constants.d.ts +6 -0
- package/dist/types/types.d.ts +38 -8
- package/dist/types/utils/prompt-extraction.d.ts +10 -0
- package/dist/types/utils/trace-fields.d.ts +1 -0
- package/dist/types/utils/validation.d.ts +1 -1
- package/examples/advanced.ts +4 -4
- package/examples/getting_started.ts +2 -2
- package/examples/metadata.ts +3 -3
- package/examples/prompt-capture-example.ts +105 -0
- package/package.json +1 -1
package/dist/esm/config.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { validateReveniumConfig } from
|
|
2
|
-
import { DEFAULT_CONFIG, ENV_VARS, LOGGING_CONFIG } from
|
|
1
|
+
import { validateReveniumConfig } from "./utils/validation.js";
|
|
2
|
+
import { DEFAULT_CONFIG, ENV_VARS, LOGGING_CONFIG } from "./constants.js";
|
|
3
3
|
/**
|
|
4
4
|
* Simple console logger implementation for Anthropic middleware
|
|
5
5
|
*/
|
|
6
6
|
class ConsoleLogger {
|
|
7
7
|
isDebugEnabled() {
|
|
8
|
-
return process.env[ENV_VARS.DEBUG] ===
|
|
8
|
+
return process.env[ENV_VARS.DEBUG] === "true";
|
|
9
9
|
}
|
|
10
10
|
formatMessage(level, message, context) {
|
|
11
11
|
const timestamp = new Date().toISOString();
|
|
12
|
-
const prefix = `[${LOGGING_CONFIG.MIDDLEWARE_NAME}${level ===
|
|
13
|
-
const contextStr = context ? ` ${JSON.stringify(context)}` :
|
|
12
|
+
const prefix = `[${LOGGING_CONFIG.MIDDLEWARE_NAME}${level === "DEBUG" ? " Debug" : ""}]`;
|
|
13
|
+
const contextStr = context ? ` ${JSON.stringify(context)}` : "";
|
|
14
14
|
return `${timestamp} ${prefix} ${message}${contextStr}`;
|
|
15
15
|
}
|
|
16
16
|
debug(message, context) {
|
|
17
17
|
if (this.isDebugEnabled()) {
|
|
18
|
-
console.debug(this.formatMessage(
|
|
18
|
+
console.debug(this.formatMessage("DEBUG", message, context));
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
info(message, context) {
|
|
22
|
-
console.info(this.formatMessage(
|
|
22
|
+
console.info(this.formatMessage("INFO", message, context));
|
|
23
23
|
}
|
|
24
24
|
warn(message, context) {
|
|
25
|
-
console.warn(this.formatMessage(
|
|
25
|
+
console.warn(this.formatMessage("WARN", message, context));
|
|
26
26
|
}
|
|
27
27
|
error(message, context) {
|
|
28
|
-
console.error(this.formatMessage(
|
|
28
|
+
console.error(this.formatMessage("ERROR", message, context));
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
@@ -40,13 +40,14 @@ function loadConfigFromEnvironment() {
|
|
|
40
40
|
reveniumApiKey: process.env[ENV_VARS.REVENIUM_API_KEY],
|
|
41
41
|
reveniumBaseUrl: process.env[ENV_VARS.REVENIUM_BASE_URL],
|
|
42
42
|
anthropicApiKey: process.env[ENV_VARS.ANTHROPIC_API_KEY],
|
|
43
|
-
debug: process.env[ENV_VARS.DEBUG] ===
|
|
43
|
+
debug: process.env[ENV_VARS.DEBUG] === "true",
|
|
44
44
|
logLevel: process.env[ENV_VARS.LOG_LEVEL],
|
|
45
45
|
apiTimeout: process.env[ENV_VARS.API_TIMEOUT],
|
|
46
46
|
failSilent: process.env[ENV_VARS.FAIL_SILENT],
|
|
47
47
|
maxRetries: process.env[ENV_VARS.MAX_RETRIES],
|
|
48
48
|
printSummary: process.env[ENV_VARS.PRINT_SUMMARY],
|
|
49
|
-
teamId: process.env[ENV_VARS.TEAM_ID]
|
|
49
|
+
teamId: process.env[ENV_VARS.TEAM_ID],
|
|
50
|
+
capturePrompts: process.env[ENV_VARS.CAPTURE_PROMPTS],
|
|
50
51
|
};
|
|
51
52
|
return env;
|
|
52
53
|
}
|
|
@@ -57,11 +58,11 @@ function parsePrintSummary(value) {
|
|
|
57
58
|
if (!value)
|
|
58
59
|
return undefined;
|
|
59
60
|
const lowerValue = value.toLowerCase();
|
|
60
|
-
if (lowerValue ===
|
|
61
|
-
return
|
|
62
|
-
if (lowerValue ===
|
|
63
|
-
return
|
|
64
|
-
if (lowerValue ===
|
|
61
|
+
if (lowerValue === "true" || lowerValue === "human")
|
|
62
|
+
return "human";
|
|
63
|
+
if (lowerValue === "json")
|
|
64
|
+
return "json";
|
|
65
|
+
if (lowerValue === "false")
|
|
65
66
|
return false;
|
|
66
67
|
return undefined;
|
|
67
68
|
}
|
|
@@ -73,9 +74,10 @@ function createConfigFromEnvironment(env) {
|
|
|
73
74
|
return null;
|
|
74
75
|
}
|
|
75
76
|
const apiTimeout = env.apiTimeout ? parseInt(env.apiTimeout, 10) : undefined;
|
|
76
|
-
const failSilent = env.failSilent !==
|
|
77
|
+
const failSilent = env.failSilent !== "false"; // Default to true
|
|
77
78
|
const maxRetries = env.maxRetries ? parseInt(env.maxRetries, 10) : undefined;
|
|
78
79
|
const printSummary = parsePrintSummary(env.printSummary);
|
|
80
|
+
const capturePrompts = env.capturePrompts === "true";
|
|
79
81
|
return {
|
|
80
82
|
reveniumApiKey: env.reveniumApiKey,
|
|
81
83
|
reveniumBaseUrl: env.reveniumBaseUrl || DEFAULT_CONFIG.REVENIUM_BASE_URL,
|
|
@@ -84,7 +86,8 @@ function createConfigFromEnvironment(env) {
|
|
|
84
86
|
failSilent,
|
|
85
87
|
maxRetries,
|
|
86
88
|
printSummary,
|
|
87
|
-
teamId: env.teamId?.trim()
|
|
89
|
+
teamId: env.teamId?.trim(),
|
|
90
|
+
capturePrompts,
|
|
88
91
|
};
|
|
89
92
|
}
|
|
90
93
|
/**
|
|
@@ -94,18 +97,18 @@ export function validateConfig(config) {
|
|
|
94
97
|
const validation = validateReveniumConfig(config);
|
|
95
98
|
if (!validation.isValid) {
|
|
96
99
|
// Log detailed validation errors
|
|
97
|
-
getLogger().error(
|
|
100
|
+
getLogger().error("Configuration validation failed", {
|
|
98
101
|
errors: validation.errors,
|
|
99
102
|
warnings: validation.warnings,
|
|
100
|
-
suggestions: validation.suggestions
|
|
103
|
+
suggestions: validation.suggestions,
|
|
101
104
|
});
|
|
102
105
|
// Create detailed error message
|
|
103
|
-
let errorMessage =
|
|
106
|
+
let errorMessage = "Configuration validation failed:\n";
|
|
104
107
|
validation.errors.forEach((error, index) => {
|
|
105
108
|
errorMessage += ` ${index + 1}. ${error}\n`;
|
|
106
109
|
});
|
|
107
110
|
if (validation.suggestions && validation.suggestions.length > 0) {
|
|
108
|
-
errorMessage +=
|
|
111
|
+
errorMessage += "\nSuggestions:\n";
|
|
109
112
|
validation.suggestions.forEach((suggestion) => {
|
|
110
113
|
errorMessage += ` • ${suggestion}\n`;
|
|
111
114
|
});
|
|
@@ -114,8 +117,8 @@ export function validateConfig(config) {
|
|
|
114
117
|
}
|
|
115
118
|
// Log warnings if any
|
|
116
119
|
if (validation.warnings && validation.warnings.length > 0) {
|
|
117
|
-
getLogger().warn(
|
|
118
|
-
warnings: validation.warnings
|
|
120
|
+
getLogger().warn("Configuration warnings", {
|
|
121
|
+
warnings: validation.warnings,
|
|
119
122
|
});
|
|
120
123
|
}
|
|
121
124
|
}
|
|
@@ -138,18 +141,18 @@ export function setConfig(config) {
|
|
|
138
141
|
const validation = validateReveniumConfig(config);
|
|
139
142
|
if (!validation.isValid) {
|
|
140
143
|
// Log detailed validation errors
|
|
141
|
-
getLogger().error(
|
|
144
|
+
getLogger().error("Configuration validation failed", {
|
|
142
145
|
errors: validation.errors,
|
|
143
146
|
warnings: validation.warnings,
|
|
144
|
-
suggestions: validation.suggestions
|
|
147
|
+
suggestions: validation.suggestions,
|
|
145
148
|
});
|
|
146
149
|
// Create detailed error message
|
|
147
|
-
let errorMessage =
|
|
150
|
+
let errorMessage = "Configuration validation failed:\n";
|
|
148
151
|
validation.errors.forEach((error, index) => {
|
|
149
152
|
errorMessage += ` ${index + 1}. ${error}\n`;
|
|
150
153
|
});
|
|
151
154
|
if (validation.suggestions && validation.suggestions.length > 0) {
|
|
152
|
-
errorMessage +=
|
|
155
|
+
errorMessage += "\nSuggestions:\n";
|
|
153
156
|
validation.suggestions.forEach((suggestion) => {
|
|
154
157
|
errorMessage += ` • ${suggestion}\n`;
|
|
155
158
|
});
|
|
@@ -158,16 +161,16 @@ export function setConfig(config) {
|
|
|
158
161
|
}
|
|
159
162
|
// Log warnings if any
|
|
160
163
|
if (validation.warnings && validation.warnings.length > 0) {
|
|
161
|
-
getLogger().warn(
|
|
162
|
-
warnings: validation.warnings
|
|
164
|
+
getLogger().warn("Configuration warnings", {
|
|
165
|
+
warnings: validation.warnings,
|
|
163
166
|
});
|
|
164
167
|
}
|
|
165
168
|
// Use the normalized config from validation (with defaults applied and fields trimmed)
|
|
166
169
|
globalConfig = validation.config;
|
|
167
|
-
globalLogger.debug(
|
|
170
|
+
globalLogger.debug("Revenium configuration updated", {
|
|
168
171
|
baseUrl: globalConfig.reveniumBaseUrl,
|
|
169
172
|
hasApiKey: !!globalConfig.reveniumApiKey,
|
|
170
|
-
hasAnthropicKey: !!globalConfig.anthropicApiKey
|
|
173
|
+
hasAnthropicKey: !!globalConfig.anthropicApiKey,
|
|
171
174
|
});
|
|
172
175
|
}
|
|
173
176
|
/**
|
|
@@ -181,7 +184,7 @@ export function getLogger() {
|
|
|
181
184
|
*/
|
|
182
185
|
export function setLogger(logger) {
|
|
183
186
|
globalLogger = logger;
|
|
184
|
-
globalLogger.debug(
|
|
187
|
+
globalLogger.debug("Custom logger set for Revenium middleware");
|
|
185
188
|
}
|
|
186
189
|
/**
|
|
187
190
|
* Initialize configuration from environment variables
|
|
@@ -192,12 +195,12 @@ export function initializeConfig() {
|
|
|
192
195
|
if (config) {
|
|
193
196
|
try {
|
|
194
197
|
setConfig(config);
|
|
195
|
-
globalLogger.debug(
|
|
198
|
+
globalLogger.debug("Revenium middleware initialized from environment variables");
|
|
196
199
|
return true;
|
|
197
200
|
}
|
|
198
201
|
catch (error) {
|
|
199
|
-
globalLogger.error(
|
|
200
|
-
error: error instanceof Error ? error.message : String(error)
|
|
202
|
+
globalLogger.error("Failed to initialize Revenium configuration", {
|
|
203
|
+
error: error instanceof Error ? error.message : String(error),
|
|
201
204
|
});
|
|
202
205
|
return false;
|
|
203
206
|
}
|
|
@@ -218,14 +221,14 @@ export function getConfigStatus() {
|
|
|
218
221
|
hasConfig: false,
|
|
219
222
|
hasApiKey: false,
|
|
220
223
|
hasAnthropicKey: false,
|
|
221
|
-
baseUrl:
|
|
224
|
+
baseUrl: "",
|
|
222
225
|
};
|
|
223
226
|
}
|
|
224
227
|
return {
|
|
225
228
|
hasConfig: true,
|
|
226
229
|
hasApiKey: !!globalConfig.reveniumApiKey,
|
|
227
230
|
hasAnthropicKey: !!globalConfig.anthropicApiKey,
|
|
228
|
-
baseUrl: globalConfig.reveniumBaseUrl
|
|
231
|
+
baseUrl: globalConfig.reveniumBaseUrl,
|
|
229
232
|
};
|
|
230
233
|
}
|
|
231
234
|
/**
|
package/dist/esm/constants.js
CHANGED
|
@@ -22,6 +22,10 @@ export const DEFAULT_CONFIG = {
|
|
|
22
22
|
MAX_RETRY_ATTEMPTS: 10,
|
|
23
23
|
/** Warning threshold for low API timeout */
|
|
24
24
|
LOW_TIMEOUT_WARNING_THRESHOLD: 3000,
|
|
25
|
+
/** Default prompt capture behavior */
|
|
26
|
+
CAPTURE_PROMPTS: false,
|
|
27
|
+
/** Maximum size for each prompt field in characters (50KB) */
|
|
28
|
+
MAX_PROMPT_SIZE: 50000,
|
|
25
29
|
};
|
|
26
30
|
/**
|
|
27
31
|
* Circuit breaker configuration constants
|
|
@@ -113,6 +117,8 @@ export const ENV_VARS = {
|
|
|
113
117
|
PRINT_SUMMARY: "REVENIUM_PRINT_SUMMARY",
|
|
114
118
|
/** Team ID for cost metrics retrieval */
|
|
115
119
|
TEAM_ID: "REVENIUM_TEAM_ID",
|
|
120
|
+
/** Prompt capture mode */
|
|
121
|
+
CAPTURE_PROMPTS: "REVENIUM_CAPTURE_PROMPTS",
|
|
116
122
|
};
|
|
117
123
|
/**
|
|
118
124
|
* Summary printer configuration
|
package/dist/esm/tracking.js
CHANGED
|
@@ -8,6 +8,7 @@ import { withRetry, ReveniumApiError, createErrorContext, handleError, } from ".
|
|
|
8
8
|
import { DEFAULT_CONFIG, API_ENDPOINTS, LOGGING_CONFIG, ANTHROPIC_PATTERNS, } from "./constants.js";
|
|
9
9
|
import { getEnvironment, getRegion, getCredentialAlias, getTraceType, getTraceName, detectOperationSubtype, getParentTransactionId, getTransactionName, getRetryNumber, } from "./utils/trace-fields.js";
|
|
10
10
|
import { printUsageSummary } from "./utils/summary-printer.js";
|
|
11
|
+
import { extractPrompts } from "./utils/prompt-extraction.js";
|
|
11
12
|
// Global logger
|
|
12
13
|
const logger = getLogger();
|
|
13
14
|
if (typeof process !== "undefined") {
|
|
@@ -143,7 +144,9 @@ async function buildReveniumPayload(data) {
|
|
|
143
144
|
"taskType",
|
|
144
145
|
"agent",
|
|
145
146
|
"organizationId",
|
|
147
|
+
"organizationName",
|
|
146
148
|
"productId",
|
|
149
|
+
"productName",
|
|
147
150
|
"subscriber",
|
|
148
151
|
"subscriptionId",
|
|
149
152
|
"traceId",
|
|
@@ -167,6 +170,10 @@ async function buildReveniumPayload(data) {
|
|
|
167
170
|
const transactionName = getTransactionName();
|
|
168
171
|
const retryNumber = getRetryNumber();
|
|
169
172
|
const operationSubtype = detectOperationSubtype(data.requestBody);
|
|
173
|
+
let promptData = null;
|
|
174
|
+
if (data.requestBody && data.response) {
|
|
175
|
+
promptData = extractPrompts(data.requestBody, data.response, data.metadata);
|
|
176
|
+
}
|
|
170
177
|
return {
|
|
171
178
|
stopReason: getStopReason(data.stopReason),
|
|
172
179
|
costType: "AI",
|
|
@@ -189,10 +196,12 @@ async function buildReveniumPayload(data) {
|
|
|
189
196
|
middlewareSource: "nodejs",
|
|
190
197
|
...(data.metadata?.taskType && { taskType: data.metadata.taskType }),
|
|
191
198
|
...(data.metadata?.agent && { agent: data.metadata.agent }),
|
|
192
|
-
...(data.metadata?.organizationId && {
|
|
193
|
-
|
|
199
|
+
...((data.metadata?.organizationName || data.metadata?.organizationId) && {
|
|
200
|
+
organizationName: data.metadata.organizationName || data.metadata.organizationId,
|
|
201
|
+
}),
|
|
202
|
+
...((data.metadata?.productName || data.metadata?.productId) && {
|
|
203
|
+
productName: data.metadata.productName || data.metadata.productId,
|
|
194
204
|
}),
|
|
195
|
-
...(data.metadata?.productId && { productId: data.metadata.productId }),
|
|
196
205
|
...(data.metadata?.subscriber && { subscriber: data.metadata.subscriber }),
|
|
197
206
|
...(data.metadata?.subscriptionId && {
|
|
198
207
|
subscriptionId: data.metadata.subscriptionId,
|
|
@@ -210,6 +219,15 @@ async function buildReveniumPayload(data) {
|
|
|
210
219
|
...(transactionName && { transactionName }),
|
|
211
220
|
...(retryNumber !== undefined && { retryNumber }),
|
|
212
221
|
...(operationSubtype && { operationSubtype }),
|
|
222
|
+
...(data.hasVisionContent !== undefined && {
|
|
223
|
+
hasVisionContent: data.hasVisionContent,
|
|
224
|
+
}),
|
|
225
|
+
...(promptData && {
|
|
226
|
+
systemPrompt: promptData.systemPrompt,
|
|
227
|
+
inputMessages: promptData.inputMessages,
|
|
228
|
+
outputResponse: promptData.outputResponse,
|
|
229
|
+
promptsTruncated: promptData.promptsTruncated,
|
|
230
|
+
}),
|
|
213
231
|
...customFields,
|
|
214
232
|
};
|
|
215
233
|
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { DEFAULT_CONFIG } from "../constants.js";
|
|
2
|
+
import { getConfig } from "../config.js";
|
|
3
|
+
function sanitizeCredentials(text) {
|
|
4
|
+
const patterns = [
|
|
5
|
+
{
|
|
6
|
+
regex: /sk-proj-[a-zA-Z0-9_-]{48,}/g,
|
|
7
|
+
replacement: "sk-proj-***REDACTED***",
|
|
8
|
+
},
|
|
9
|
+
{ regex: /sk-[a-zA-Z0-9_-]{20,}/g, replacement: "sk-***REDACTED***" },
|
|
10
|
+
{
|
|
11
|
+
regex: /Bearer\s+[a-zA-Z0-9_\-\.]+/gi,
|
|
12
|
+
replacement: "Bearer ***REDACTED***",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
regex: /api[_-]?key["\s:=]+[a-zA-Z0-9_\-\.\+\/=]{20,}/gi,
|
|
16
|
+
replacement: "api_key: ***REDACTED***",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
regex: /token["\s:=]+[a-zA-Z0-9_\-\.]{20,}/gi,
|
|
20
|
+
replacement: "token: ***REDACTED***",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
regex: /password["\s:=]+[^\s"']{8,}/gi,
|
|
24
|
+
replacement: "password: ***REDACTED***",
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
let sanitized = text;
|
|
28
|
+
for (const pattern of patterns) {
|
|
29
|
+
sanitized = sanitized.replace(pattern.regex, pattern.replacement);
|
|
30
|
+
}
|
|
31
|
+
return sanitized;
|
|
32
|
+
}
|
|
33
|
+
function truncateString(str, maxLength) {
|
|
34
|
+
const sanitized = sanitizeCredentials(str);
|
|
35
|
+
if (sanitized.length <= maxLength) {
|
|
36
|
+
return { value: sanitized, truncated: false };
|
|
37
|
+
}
|
|
38
|
+
return { value: sanitized.substring(0, maxLength), truncated: true };
|
|
39
|
+
}
|
|
40
|
+
function extractSystemPrompt(params) {
|
|
41
|
+
if (!params.system) {
|
|
42
|
+
return "";
|
|
43
|
+
}
|
|
44
|
+
if (typeof params.system === "string") {
|
|
45
|
+
return params.system;
|
|
46
|
+
}
|
|
47
|
+
if (Array.isArray(params.system)) {
|
|
48
|
+
return params.system
|
|
49
|
+
.map((block) => {
|
|
50
|
+
if (block.type === "text") {
|
|
51
|
+
return block.text;
|
|
52
|
+
}
|
|
53
|
+
if (block.type === "image") {
|
|
54
|
+
return "[IMAGE]";
|
|
55
|
+
}
|
|
56
|
+
return "";
|
|
57
|
+
})
|
|
58
|
+
.filter(Boolean)
|
|
59
|
+
.join("\n");
|
|
60
|
+
}
|
|
61
|
+
return "";
|
|
62
|
+
}
|
|
63
|
+
function extractInputMessages(params) {
|
|
64
|
+
if (!params.messages || params.messages.length === 0) {
|
|
65
|
+
return "";
|
|
66
|
+
}
|
|
67
|
+
return params.messages
|
|
68
|
+
.map((message) => {
|
|
69
|
+
const role = message.role;
|
|
70
|
+
let content = "";
|
|
71
|
+
if (typeof message.content === "string") {
|
|
72
|
+
content = message.content;
|
|
73
|
+
}
|
|
74
|
+
else if (Array.isArray(message.content)) {
|
|
75
|
+
content = message.content
|
|
76
|
+
.map((block) => {
|
|
77
|
+
if (block.type === "text") {
|
|
78
|
+
return block.text;
|
|
79
|
+
}
|
|
80
|
+
if (block.type === "image") {
|
|
81
|
+
return "[IMAGE]";
|
|
82
|
+
}
|
|
83
|
+
if (block.type === "tool_use") {
|
|
84
|
+
const toolName = block.name || "unknown";
|
|
85
|
+
return `[TOOL_USE: ${toolName}]`;
|
|
86
|
+
}
|
|
87
|
+
if (block.type === "tool_result") {
|
|
88
|
+
return "[TOOL_RESULT]";
|
|
89
|
+
}
|
|
90
|
+
return "";
|
|
91
|
+
})
|
|
92
|
+
.filter(Boolean)
|
|
93
|
+
.join("\n");
|
|
94
|
+
}
|
|
95
|
+
return `[${role}]\n${content}`;
|
|
96
|
+
})
|
|
97
|
+
.join("\n\n");
|
|
98
|
+
}
|
|
99
|
+
function extractOutputResponse(response) {
|
|
100
|
+
if (!response.content || response.content.length === 0) {
|
|
101
|
+
return "";
|
|
102
|
+
}
|
|
103
|
+
return response.content
|
|
104
|
+
.map((block) => {
|
|
105
|
+
if (block.type === "text") {
|
|
106
|
+
return block.text;
|
|
107
|
+
}
|
|
108
|
+
if (block.type === "tool_use") {
|
|
109
|
+
return `[TOOL_USE: ${block.name}]`;
|
|
110
|
+
}
|
|
111
|
+
return "";
|
|
112
|
+
})
|
|
113
|
+
.filter(Boolean)
|
|
114
|
+
.join("\n");
|
|
115
|
+
}
|
|
116
|
+
export function shouldCapturePrompts(metadata) {
|
|
117
|
+
if (metadata?.capturePrompts !== undefined) {
|
|
118
|
+
return metadata.capturePrompts;
|
|
119
|
+
}
|
|
120
|
+
const config = getConfig();
|
|
121
|
+
if (config?.capturePrompts !== undefined) {
|
|
122
|
+
return config.capturePrompts;
|
|
123
|
+
}
|
|
124
|
+
return DEFAULT_CONFIG.CAPTURE_PROMPTS;
|
|
125
|
+
}
|
|
126
|
+
export function extractPrompts(params, response, metadata) {
|
|
127
|
+
if (!shouldCapturePrompts(metadata)) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
const maxSize = DEFAULT_CONFIG.MAX_PROMPT_SIZE;
|
|
131
|
+
let anyTruncated = false;
|
|
132
|
+
const systemPromptRaw = extractSystemPrompt(params);
|
|
133
|
+
const systemPromptResult = truncateString(systemPromptRaw, maxSize);
|
|
134
|
+
anyTruncated = anyTruncated || systemPromptResult.truncated;
|
|
135
|
+
const inputMessagesRaw = extractInputMessages(params);
|
|
136
|
+
const inputMessagesResult = truncateString(inputMessagesRaw, maxSize);
|
|
137
|
+
anyTruncated = anyTruncated || inputMessagesResult.truncated;
|
|
138
|
+
const outputResponseRaw = extractOutputResponse(response);
|
|
139
|
+
const outputResponseResult = truncateString(outputResponseRaw, maxSize);
|
|
140
|
+
anyTruncated = anyTruncated || outputResponseResult.truncated;
|
|
141
|
+
const hasAnyContent = systemPromptResult.value ||
|
|
142
|
+
inputMessagesResult.value ||
|
|
143
|
+
outputResponseResult.value;
|
|
144
|
+
if (!hasAnyContent) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
systemPrompt: systemPromptResult.value || undefined,
|
|
149
|
+
inputMessages: inputMessagesResult.value || undefined,
|
|
150
|
+
outputResponse: outputResponseResult.value || undefined,
|
|
151
|
+
promptsTruncated: anyTruncated,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=prompt-extraction.js.map
|
|
@@ -89,6 +89,41 @@ export function detectOperationSubtype(requestBody) {
|
|
|
89
89
|
}
|
|
90
90
|
return null;
|
|
91
91
|
}
|
|
92
|
+
export function detectVisionContent(params) {
|
|
93
|
+
if (!params) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
if (params.messages && Array.isArray(params.messages)) {
|
|
98
|
+
for (const message of params.messages) {
|
|
99
|
+
if (!message || typeof message !== "object" || !message.content) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (Array.isArray(message.content)) {
|
|
103
|
+
for (const block of message.content) {
|
|
104
|
+
if (block && typeof block === "object" && block.type === "image") {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (params.system && Array.isArray(params.system)) {
|
|
112
|
+
for (const block of params.system) {
|
|
113
|
+
if (block && typeof block === "object" && block.type === "image") {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
logger.debug("Error detecting vision content, defaulting to false", {
|
|
122
|
+
error: error instanceof Error ? error.message : String(error),
|
|
123
|
+
});
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
92
127
|
export function getParentTransactionId() {
|
|
93
128
|
return process.env.REVENIUM_PARENT_TRANSACTION_ID || null;
|
|
94
129
|
}
|