@revenium/perplexity 2.0.9 → 2.1.0
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/.env.example +4 -0
- package/CHANGELOG.md +25 -0
- package/README.md +66 -0
- package/dist/cjs/core/config/loader.js +6 -1
- package/dist/cjs/core/config/loader.js.map +1 -1
- package/dist/cjs/core/middleware/interfaces.js +38 -1
- package/dist/cjs/core/middleware/interfaces.js.map +1 -1
- package/dist/cjs/core/middleware/streaming-wrapper.js +67 -2
- package/dist/cjs/core/middleware/streaming-wrapper.js.map +1 -1
- package/dist/cjs/core/tracking/payload-builder.js +8 -0
- package/dist/cjs/core/tracking/payload-builder.js.map +1 -1
- package/dist/cjs/core/tracking/usage-tracker.js +8 -5
- package/dist/cjs/core/tracking/usage-tracker.js.map +1 -1
- package/dist/cjs/utils/prompt-extraction.js +194 -0
- package/dist/cjs/utils/prompt-extraction.js.map +1 -0
- package/dist/esm/core/config/loader.js +6 -1
- package/dist/esm/core/config/loader.js.map +1 -1
- package/dist/esm/core/middleware/interfaces.js +38 -1
- package/dist/esm/core/middleware/interfaces.js.map +1 -1
- package/dist/esm/core/middleware/streaming-wrapper.js +67 -2
- package/dist/esm/core/middleware/streaming-wrapper.js.map +1 -1
- package/dist/esm/core/tracking/payload-builder.js +8 -0
- package/dist/esm/core/tracking/payload-builder.js.map +1 -1
- package/dist/esm/core/tracking/usage-tracker.js +8 -5
- package/dist/esm/core/tracking/usage-tracker.js.map +1 -1
- package/dist/esm/utils/prompt-extraction.js +188 -0
- package/dist/esm/utils/prompt-extraction.js.map +1 -0
- package/dist/types/core/config/loader.d.ts.map +1 -1
- package/dist/types/core/middleware/interfaces.d.ts.map +1 -1
- package/dist/types/core/middleware/streaming-wrapper.d.ts +9 -1
- package/dist/types/core/middleware/streaming-wrapper.d.ts.map +1 -1
- package/dist/types/core/tracking/payload-builder.d.ts.map +1 -1
- package/dist/types/core/tracking/usage-tracker.d.ts +8 -0
- package/dist/types/core/tracking/usage-tracker.d.ts.map +1 -1
- package/dist/types/types/function-parameters.d.ts +7 -0
- package/dist/types/types/function-parameters.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +11 -0
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/utils/prompt-extraction.d.ts +29 -0
- package/dist/types/utils/prompt-extraction.d.ts.map +1 -0
- package/examples/prompt-capture.ts +108 -0
- package/package.json +2 -1
package/.env.example
CHANGED
|
@@ -19,5 +19,9 @@ REVENIUM_RETRY_NUMBER=0
|
|
|
19
19
|
# Debug Configuration (Optional)
|
|
20
20
|
REVENIUM_DEBUG=false
|
|
21
21
|
|
|
22
|
+
# Prompt Capture Configuration (Optional)
|
|
23
|
+
# REVENIUM_CAPTURE_PROMPTS=false
|
|
24
|
+
# REVENIUM_MAX_PROMPT_SIZE=50000
|
|
25
|
+
|
|
22
26
|
# AWS Region Detection (Optional - auto-detected if not set)
|
|
23
27
|
AWS_REGION=us-east-1
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.1.0] - 2026-01-21
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Prompt capture functionality with automatic credential sanitization
|
|
13
|
+
- New prompt capture fields in ReveniumPayload: systemPrompt, inputMessages, outputResponse, promptsTruncated
|
|
14
|
+
- Configuration options: capturePrompts (boolean), maxPromptSize (number, default: 50000)
|
|
15
|
+
- Environment variables: REVENIUM_CAPTURE_PROMPTS, REVENIUM_MAX_PROMPT_SIZE
|
|
16
|
+
- Per-call override via usageMetadata.capturePrompts
|
|
17
|
+
- Comprehensive credential sanitization with 13 patterns:
|
|
18
|
+
- Perplexity API keys (pplx-\*)
|
|
19
|
+
- OpenAI keys (sk-_, sk-proj-_, sk-ant-\*)
|
|
20
|
+
- AWS access keys (AKIA\*)
|
|
21
|
+
- GitHub tokens (ghp*\*, ghs*\*)
|
|
22
|
+
- JWT tokens (eyJ*.eyJ*.\*)
|
|
23
|
+
- Bearer tokens
|
|
24
|
+
- Generic API keys, tokens, passwords, secrets
|
|
25
|
+
- Automatic truncation of prompts exceeding maxPromptSize with truncation flag
|
|
26
|
+
|
|
27
|
+
### Security
|
|
28
|
+
|
|
29
|
+
- All captured prompts are automatically sanitized to remove sensitive credentials
|
|
30
|
+
- Credential patterns are redacted before transmission to Revenium API
|
|
31
|
+
- Prompt capture is opt-in (disabled by default) for privacy
|
|
32
|
+
|
|
8
33
|
## [2.0.9] - 2026-01-06
|
|
9
34
|
|
|
10
35
|
### Added
|
package/README.md
CHANGED
|
@@ -287,6 +287,72 @@ REVENIUM_RETRY_NUMBER=0
|
|
|
287
287
|
|
|
288
288
|
For a complete example, see [`.env.example`](https://github.com/revenium/revenium-middleware-perplexity-node/blob/HEAD/.env.example).
|
|
289
289
|
|
|
290
|
+
## Prompt Capture
|
|
291
|
+
|
|
292
|
+
The middleware can capture prompts and responses for analysis. This feature is **disabled by default** for privacy.
|
|
293
|
+
|
|
294
|
+
### Configuration
|
|
295
|
+
|
|
296
|
+
Enable prompt capture using environment variables, programmatic configuration, or per-call metadata:
|
|
297
|
+
|
|
298
|
+
**Environment Variables:**
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
export REVENIUM_CAPTURE_PROMPTS=true
|
|
302
|
+
export REVENIUM_MAX_PROMPT_SIZE=50000
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Programmatic Configuration:**
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
import { Initialize } from "@revenium/perplexity";
|
|
309
|
+
|
|
310
|
+
Initialize({
|
|
311
|
+
reveniumApiKey: "hak_your_key",
|
|
312
|
+
reveniumBaseUrl: "https://api.revenium.ai",
|
|
313
|
+
perplexityApiKey: "pplx_your_key",
|
|
314
|
+
capturePrompts: true,
|
|
315
|
+
maxPromptSize: 50000,
|
|
316
|
+
});
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**Per-Call Override:**
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
const response = await client.chat.completions.create(
|
|
323
|
+
{
|
|
324
|
+
model: "llama-3.1-sonar-small-128k-online",
|
|
325
|
+
messages: [{ role: "user", content: "Hello" }],
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
usageMetadata: { capturePrompts: true },
|
|
329
|
+
},
|
|
330
|
+
);
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Configuration Priority
|
|
334
|
+
|
|
335
|
+
The middleware uses the following priority order (highest to lowest):
|
|
336
|
+
|
|
337
|
+
1. Per-call `usageMetadata.capturePrompts`
|
|
338
|
+
2. Programmatic `config.capturePrompts`
|
|
339
|
+
3. Environment variable `REVENIUM_CAPTURE_PROMPTS`
|
|
340
|
+
4. Default: `false`
|
|
341
|
+
|
|
342
|
+
### Security
|
|
343
|
+
|
|
344
|
+
All captured prompts are automatically sanitized to remove sensitive credentials:
|
|
345
|
+
|
|
346
|
+
- Perplexity API keys (pplx-\*)
|
|
347
|
+
- OpenAI keys (sk-\*, sk-proj-\*, sk-ant-\*)
|
|
348
|
+
- AWS access keys (AKIA\*)
|
|
349
|
+
- GitHub tokens (ghp*\*, ghs*\*)
|
|
350
|
+
- JWT tokens
|
|
351
|
+
- Bearer tokens
|
|
352
|
+
- Generic API keys, tokens, passwords, secrets
|
|
353
|
+
|
|
354
|
+
Prompts exceeding `maxPromptSize` (default: 50000 characters) are automatically truncated with a flag indicating truncation.
|
|
355
|
+
|
|
290
356
|
## Terminal Cost/Metrics Summary
|
|
291
357
|
|
|
292
358
|
The middleware can print a cost and metrics summary to your terminal after each API request. This is useful for development and debugging.
|
|
@@ -47,11 +47,12 @@ function loadConfigFromEnv() {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
const teamId = process.env.REVENIUM_TEAM_ID;
|
|
50
|
+
const capturePromptsEnv = process.env.REVENIUM_CAPTURE_PROMPTS;
|
|
50
51
|
if (!reveniumApiKey)
|
|
51
52
|
return null;
|
|
52
53
|
if (!perplexityApiKey)
|
|
53
54
|
return null;
|
|
54
|
-
|
|
55
|
+
const config = {
|
|
55
56
|
reveniumApiKey,
|
|
56
57
|
reveniumBaseUrl,
|
|
57
58
|
perplexityApiKey,
|
|
@@ -60,5 +61,9 @@ function loadConfigFromEnv() {
|
|
|
60
61
|
printSummary,
|
|
61
62
|
teamId,
|
|
62
63
|
};
|
|
64
|
+
if (capturePromptsEnv !== undefined) {
|
|
65
|
+
config.capturePrompts = capturePromptsEnv.toLowerCase() === "true";
|
|
66
|
+
}
|
|
67
|
+
return config;
|
|
63
68
|
}
|
|
64
69
|
//# sourceMappingURL=loader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../../src/core/config/loader.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAoBH,
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../../src/core/config/loader.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAoBH,8CAkDC;AAnED,mCAA8C;AAE9C;;GAEG;AACH,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAC5D,MAAM,2BAA2B,GAAG,2BAA2B,CAAC;AAEhE;;GAEG;AACH,IAAI,aAAa,GAAG,KAAK,CAAC;AAE1B;;;GAGG;AACH,SAAgB,iBAAiB;IAC/B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAA,eAAU,GAAE,CAAC;QACb,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,MAAM,cAAc,GAClB,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACxE,MAAM,eAAe,GACnB,OAAO,CAAC,GAAG,CAAC,0BAA0B;QACtC,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAC7B,yBAAyB,CAAC;IAC5B,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IACxD,MAAM,iBAAiB,GACrB,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,2BAA2B,CAAC;IACrE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM,CAAC;IAEpD,IAAI,YAAY,GAA2C,SAAS,CAAC;IACrE,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IAC3D,IAAI,eAAe,EAAE,CAAC;QACpB,IAAI,eAAe,KAAK,MAAM,EAAE,CAAC;YAC/B,YAAY,GAAG,IAAI,CAAC;QACtB,CAAC;aAAM,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;YACvC,YAAY,GAAG,KAAK,CAAC;QACvB,CAAC;aAAM,IAAI,eAAe,KAAK,OAAO,IAAI,eAAe,KAAK,MAAM,EAAE,CAAC;YACrE,YAAY,GAAG,eAAe,CAAC;QACjC,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;IAE/D,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,CAAC,gBAAgB;QAAE,OAAO,IAAI,CAAC;IAEnC,MAAM,MAAM,GAAQ;QAClB,cAAc;QACd,eAAe;QACf,gBAAgB;QAChB,iBAAiB;QACjB,KAAK;QACL,YAAY;QACZ,MAAM;KACP,CAAC;IAEF,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,CAAC,cAAc,GAAG,iBAAiB,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;IACrE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -8,6 +8,7 @@ const config_1 = require("../config");
|
|
|
8
8
|
const transaction_id_js_1 = require("../../utils/transaction-id.js");
|
|
9
9
|
const index_js_1 = require("../tracking/index.js");
|
|
10
10
|
const streaming_wrapper_js_1 = require("./streaming-wrapper.js");
|
|
11
|
+
const prompt_extraction_js_1 = require("../../utils/prompt-extraction.js");
|
|
11
12
|
const logger = (0, config_1.getLogger)();
|
|
12
13
|
/**
|
|
13
14
|
* Chat interface - provides access to chat completions
|
|
@@ -48,6 +49,9 @@ class CompletionsInterface {
|
|
|
48
49
|
if ("usage" in response && response.usage) {
|
|
49
50
|
// Extract cost if available (Perplexity-specific)
|
|
50
51
|
const usage = response.usage;
|
|
52
|
+
const responseContent = "choices" in response
|
|
53
|
+
? response.choices[0]?.message?.content || undefined
|
|
54
|
+
: undefined;
|
|
51
55
|
(0, index_js_1.trackUsageAsync)({
|
|
52
56
|
requestId: ("id" in response ? response.id : null) || transactionId,
|
|
53
57
|
model: params.model,
|
|
@@ -61,12 +65,31 @@ class CompletionsInterface {
|
|
|
61
65
|
usageMetadata: metadata,
|
|
62
66
|
isStreamed: false,
|
|
63
67
|
cost: usage.cost,
|
|
68
|
+
responseFormat: params.response_format,
|
|
69
|
+
messages: params.messages,
|
|
70
|
+
responseContent: responseContent
|
|
71
|
+
? (0, prompt_extraction_js_1.sanitizeCredentials)(responseContent)
|
|
72
|
+
: undefined,
|
|
64
73
|
});
|
|
65
74
|
}
|
|
66
75
|
return response;
|
|
67
76
|
}
|
|
68
77
|
catch (error) {
|
|
69
78
|
logger.error(`[Revenium] Error in chat completion: ${error.message}`);
|
|
79
|
+
const endTime = Date.now();
|
|
80
|
+
const duration = endTime - startTime.getTime();
|
|
81
|
+
(0, index_js_1.trackUsageAsync)({
|
|
82
|
+
requestId: transactionId,
|
|
83
|
+
model: params.model,
|
|
84
|
+
promptTokens: 0,
|
|
85
|
+
completionTokens: 0,
|
|
86
|
+
totalTokens: 0,
|
|
87
|
+
duration,
|
|
88
|
+
finishReason: "error",
|
|
89
|
+
usageMetadata: metadata,
|
|
90
|
+
isStreamed: false,
|
|
91
|
+
messages: params.messages,
|
|
92
|
+
});
|
|
70
93
|
throw error;
|
|
71
94
|
}
|
|
72
95
|
}
|
|
@@ -82,10 +105,24 @@ class CompletionsInterface {
|
|
|
82
105
|
...params,
|
|
83
106
|
stream: true,
|
|
84
107
|
});
|
|
85
|
-
return new streaming_wrapper_js_1.StreamingWrapper(stream, params.model, startTime, transactionId, metadata, this.config);
|
|
108
|
+
return new streaming_wrapper_js_1.StreamingWrapper(stream, params.model, startTime, transactionId, metadata, this.config, params.response_format, params.messages);
|
|
86
109
|
}
|
|
87
110
|
catch (error) {
|
|
88
111
|
logger.error(`[Revenium] Error in streaming chat completion: ${error.message}`);
|
|
112
|
+
const endTime = Date.now();
|
|
113
|
+
const duration = endTime - startTime.getTime();
|
|
114
|
+
(0, index_js_1.trackUsageAsync)({
|
|
115
|
+
requestId: transactionId,
|
|
116
|
+
model: params.model,
|
|
117
|
+
promptTokens: 0,
|
|
118
|
+
completionTokens: 0,
|
|
119
|
+
totalTokens: 0,
|
|
120
|
+
duration,
|
|
121
|
+
finishReason: "error",
|
|
122
|
+
usageMetadata: metadata,
|
|
123
|
+
isStreamed: true,
|
|
124
|
+
messages: params.messages,
|
|
125
|
+
});
|
|
89
126
|
throw error;
|
|
90
127
|
}
|
|
91
128
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../../../src/core/middleware/interfaces.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAIH,sCAAsC;AACtC,qEAAsE;AACtE,mDAAuD;AACvD,iEAA0D;
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../../../src/core/middleware/interfaces.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,18 +6,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.StreamingWrapper = void 0;
|
|
7
7
|
const config_1 = require("../config");
|
|
8
8
|
const tracking_1 = require("../tracking");
|
|
9
|
+
const prompt_extraction_js_1 = require("../../utils/prompt-extraction.js");
|
|
9
10
|
const logger = (0, config_1.getLogger)();
|
|
10
11
|
/**
|
|
11
12
|
* Wrapper for streaming responses that tracks usage
|
|
12
13
|
*/
|
|
13
14
|
class StreamingWrapper {
|
|
14
|
-
constructor(stream, model, startTime, transactionId, metadata, config) {
|
|
15
|
+
constructor(stream, model, startTime, transactionId, metadata, config, responseFormat, messages) {
|
|
16
|
+
this.accumulatedContent = "";
|
|
15
17
|
this.stream = stream;
|
|
16
18
|
this.model = model;
|
|
17
19
|
this.startTime = startTime;
|
|
18
20
|
this.transactionId = transactionId;
|
|
19
21
|
this.metadata = metadata;
|
|
20
22
|
this.config = config || {};
|
|
23
|
+
this.responseFormat = responseFormat;
|
|
24
|
+
this.messages = messages || [];
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
23
27
|
* Iterate over stream chunks
|
|
@@ -30,6 +34,7 @@ class StreamingWrapper {
|
|
|
30
34
|
let costData = undefined;
|
|
31
35
|
let firstChunkTime = null;
|
|
32
36
|
let timeToFirstToken = 0;
|
|
37
|
+
let completed = false;
|
|
33
38
|
try {
|
|
34
39
|
for await (const chunk of this.stream) {
|
|
35
40
|
// Capture time of first chunk
|
|
@@ -39,6 +44,14 @@ class StreamingWrapper {
|
|
|
39
44
|
firstChunkTime.getTime() - this.startTime.getTime();
|
|
40
45
|
}
|
|
41
46
|
lastChunk = chunk;
|
|
47
|
+
if (chunk.choices?.[0]?.delta?.content &&
|
|
48
|
+
(0, prompt_extraction_js_1.shouldCapturePrompts)(this.metadata)) {
|
|
49
|
+
const maxSize = (0, prompt_extraction_js_1.getMaxPromptSize)();
|
|
50
|
+
const remaining = maxSize - this.accumulatedContent.length;
|
|
51
|
+
if (remaining > 0) {
|
|
52
|
+
this.accumulatedContent += chunk.choices[0].delta.content.slice(0, remaining);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
42
55
|
// Track usage if available in chunk
|
|
43
56
|
if (chunk.usage) {
|
|
44
57
|
inputTokens = chunk.usage.prompt_tokens || 0;
|
|
@@ -51,6 +64,7 @@ class StreamingWrapper {
|
|
|
51
64
|
}
|
|
52
65
|
yield chunk;
|
|
53
66
|
}
|
|
67
|
+
completed = true;
|
|
54
68
|
// Send metering data when stream completes (fire-and-forget)
|
|
55
69
|
const endTime = Date.now();
|
|
56
70
|
const duration = endTime - this.startTime.getTime();
|
|
@@ -67,13 +81,64 @@ class StreamingWrapper {
|
|
|
67
81
|
isStreamed: true,
|
|
68
82
|
timeToFirstToken,
|
|
69
83
|
cost: costData,
|
|
84
|
+
responseFormat: this.responseFormat,
|
|
85
|
+
messages: this.messages,
|
|
86
|
+
responseContent: this.accumulatedContent
|
|
87
|
+
? (0, prompt_extraction_js_1.sanitizeCredentials)(this.accumulatedContent)
|
|
88
|
+
: undefined,
|
|
70
89
|
});
|
|
71
90
|
}
|
|
72
91
|
catch (error) {
|
|
73
|
-
|
|
92
|
+
completed = true;
|
|
74
93
|
logger.error("[Revenium] Error in stream processing:", error.message);
|
|
94
|
+
const endTime = Date.now();
|
|
95
|
+
const duration = endTime - this.startTime.getTime();
|
|
96
|
+
(0, tracking_1.trackUsageAsync)({
|
|
97
|
+
requestId: this.transactionId,
|
|
98
|
+
model: this.model,
|
|
99
|
+
promptTokens: inputTokens,
|
|
100
|
+
completionTokens: outputTokens,
|
|
101
|
+
totalTokens,
|
|
102
|
+
duration,
|
|
103
|
+
finishReason: "error",
|
|
104
|
+
usageMetadata: this.metadata,
|
|
105
|
+
isStreamed: true,
|
|
106
|
+
messages: this.messages,
|
|
107
|
+
responseContent: this.accumulatedContent
|
|
108
|
+
? (0, prompt_extraction_js_1.sanitizeCredentials)(this.accumulatedContent)
|
|
109
|
+
: undefined,
|
|
110
|
+
});
|
|
75
111
|
throw error;
|
|
76
112
|
}
|
|
113
|
+
finally {
|
|
114
|
+
if (!completed) {
|
|
115
|
+
const endTime = Date.now();
|
|
116
|
+
const duration = endTime - this.startTime.getTime();
|
|
117
|
+
(0, tracking_1.trackUsageAsync)({
|
|
118
|
+
requestId: this.transactionId,
|
|
119
|
+
model: this.model,
|
|
120
|
+
promptTokens: inputTokens,
|
|
121
|
+
completionTokens: outputTokens,
|
|
122
|
+
totalTokens,
|
|
123
|
+
duration,
|
|
124
|
+
finishReason: "cancelled",
|
|
125
|
+
usageMetadata: this.metadata,
|
|
126
|
+
isStreamed: true,
|
|
127
|
+
timeToFirstToken,
|
|
128
|
+
cost: costData,
|
|
129
|
+
responseFormat: this.responseFormat,
|
|
130
|
+
messages: this.messages,
|
|
131
|
+
responseContent: this.accumulatedContent
|
|
132
|
+
? (0, prompt_extraction_js_1.sanitizeCredentials)(this.accumulatedContent)
|
|
133
|
+
: undefined,
|
|
134
|
+
});
|
|
135
|
+
logger.debug("[Revenium] Streaming cancelled", {
|
|
136
|
+
requestId: this.transactionId,
|
|
137
|
+
model: this.model,
|
|
138
|
+
duration,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
77
142
|
}
|
|
78
143
|
}
|
|
79
144
|
exports.StreamingWrapper = StreamingWrapper;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming-wrapper.js","sourceRoot":"","sources":["../../../../src/core/middleware/streaming-wrapper.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAGH,sCAAsC;AACtC,0CAA8C;
|
|
1
|
+
{"version":3,"file":"streaming-wrapper.js","sourceRoot":"","sources":["../../../../src/core/middleware/streaming-wrapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,7 @@ const stop_reason_mapper_js_1 = require("../../utils/stop-reason-mapper.js");
|
|
|
13
13
|
const metadata_builder_js_1 = require("../../utils/metadata-builder.js");
|
|
14
14
|
const index_js_2 = require("../providers/index.js");
|
|
15
15
|
const trace_fields_js_1 = require("../../utils/trace-fields.js");
|
|
16
|
+
const prompt_extraction_js_1 = require("../../utils/prompt-extraction.js");
|
|
16
17
|
// Global logger
|
|
17
18
|
const logger = (0, index_js_1.getLogger)();
|
|
18
19
|
/**
|
|
@@ -96,6 +97,7 @@ async function buildPayload(operationType, response, request, startTime, duratio
|
|
|
96
97
|
...costFields,
|
|
97
98
|
};
|
|
98
99
|
// Chat-specific fields
|
|
100
|
+
const promptData = (0, prompt_extraction_js_1.extractPrompts)(request, response, request.usageMetadata);
|
|
99
101
|
return {
|
|
100
102
|
...commonPayload,
|
|
101
103
|
operationType: "CHAT",
|
|
@@ -109,6 +111,12 @@ async function buildPayload(operationType, response, request, startTime, duratio
|
|
|
109
111
|
isStreamed: Boolean(request.stream),
|
|
110
112
|
// Time to first token (for streaming requests)
|
|
111
113
|
timeToFirstToken: timeToFirstToken,
|
|
114
|
+
...(promptData && {
|
|
115
|
+
systemPrompt: promptData.systemPrompt,
|
|
116
|
+
inputMessages: promptData.inputMessages,
|
|
117
|
+
outputResponse: promptData.outputResponse,
|
|
118
|
+
promptsTruncated: promptData.promptsTruncated,
|
|
119
|
+
}),
|
|
112
120
|
};
|
|
113
121
|
}
|
|
114
122
|
//# sourceMappingURL=payload-builder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload-builder.js","sourceRoot":"","sources":["../../../../src/core/tracking/payload-builder.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;
|
|
1
|
+
{"version":3,"file":"payload-builder.js","sourceRoot":"","sources":["../../../../src/core/tracking/payload-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,19 +48,22 @@ function trackUsageAsync(trackingData) {
|
|
|
48
48
|
{
|
|
49
49
|
index: 0,
|
|
50
50
|
finish_reason: trackingData.finishReason,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
...(trackingData.responseContent && {
|
|
52
|
+
message: {
|
|
53
|
+
role: "assistant",
|
|
54
|
+
content: trackingData.responseContent,
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
55
57
|
},
|
|
56
58
|
],
|
|
57
59
|
};
|
|
58
60
|
// Build DTO request object from tracking data
|
|
59
61
|
const dtoRequest = {
|
|
60
62
|
model: trackingData.model,
|
|
61
|
-
messages: [],
|
|
63
|
+
messages: trackingData.messages || [],
|
|
62
64
|
usageMetadata: trackingData.usageMetadata,
|
|
63
65
|
stream: trackingData.isStreamed,
|
|
66
|
+
response_format: trackingData.responseFormat,
|
|
64
67
|
};
|
|
65
68
|
const startTime = Date.now() - trackingData.duration;
|
|
66
69
|
sendReveniumMetrics(dtoResponse, dtoRequest, startTime, trackingData.duration, trackingData.providerInfo, trackingData.timeToFirstToken)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-tracker.js","sourceRoot":"","sources":["../../../../src/core/tracking/usage-tracker.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAoBH,kDA6BC;AAMD,
|
|
1
|
+
{"version":3,"file":"usage-tracker.js","sourceRoot":"","sources":["../../../../src/core/tracking/usage-tracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMaxPromptSize = getMaxPromptSize;
|
|
4
|
+
exports.sanitizeCredentials = sanitizeCredentials;
|
|
5
|
+
exports.shouldCapturePrompts = shouldCapturePrompts;
|
|
6
|
+
exports.extractPrompts = extractPrompts;
|
|
7
|
+
const index_js_1 = require("../core/config/index.js");
|
|
8
|
+
const DEFAULT_MAX_PROMPT_SIZE = 50000;
|
|
9
|
+
const CAPTURE_PROMPTS_DEFAULT = false;
|
|
10
|
+
function getMaxPromptSize() {
|
|
11
|
+
const config = (0, index_js_1.getConfig)();
|
|
12
|
+
if (config?.maxPromptSize && config.maxPromptSize > 0) {
|
|
13
|
+
return config.maxPromptSize;
|
|
14
|
+
}
|
|
15
|
+
const envValue = process.env.REVENIUM_MAX_PROMPT_SIZE;
|
|
16
|
+
if (envValue) {
|
|
17
|
+
const parsed = parseInt(envValue, 10);
|
|
18
|
+
if (!isNaN(parsed) && parsed > 0) {
|
|
19
|
+
return parsed;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return DEFAULT_MAX_PROMPT_SIZE;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Sanitizes common credential patterns from text.
|
|
26
|
+
*
|
|
27
|
+
* Redacts the following credential types:
|
|
28
|
+
* - OpenAI keys: sk-*, sk-proj-*, sk-ant-* (20+ chars)
|
|
29
|
+
* - Perplexity keys: pplx-* (20+ chars)
|
|
30
|
+
* - AWS access keys: AKIA* (20 chars)
|
|
31
|
+
* - GitHub tokens: ghp_*, ghs_* (36+ chars)
|
|
32
|
+
* - JWT tokens: eyJ*.eyJ*.*
|
|
33
|
+
* - Bearer tokens
|
|
34
|
+
* - Generic API keys, tokens, passwords, secrets (8-20+ chars)
|
|
35
|
+
*
|
|
36
|
+
* LIMITATIONS:
|
|
37
|
+
* - Shorter credentials may pass through unsanitized
|
|
38
|
+
* - Length constraints balance security with false positive prevention
|
|
39
|
+
*/
|
|
40
|
+
function sanitizeCredentials(text) {
|
|
41
|
+
const patterns = [
|
|
42
|
+
{
|
|
43
|
+
regex: /pplx-[a-zA-Z0-9_-]{20,}/g,
|
|
44
|
+
replacement: "pplx-***REDACTED***",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
regex: /sk-proj-[a-zA-Z0-9_-]{48,}/g,
|
|
48
|
+
replacement: "sk-proj-***REDACTED***",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
regex: /sk-ant-[a-zA-Z0-9_-]{20,}/g,
|
|
52
|
+
replacement: "sk-ant-***REDACTED***",
|
|
53
|
+
},
|
|
54
|
+
{ regex: /sk-[a-zA-Z0-9_-]{20,}/g, replacement: "sk-***REDACTED***" },
|
|
55
|
+
{
|
|
56
|
+
regex: /AKIA[A-Z0-9]{16}/g,
|
|
57
|
+
replacement: "AKIA***REDACTED***",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
regex: /ghp_[a-zA-Z0-9]{36,}/g,
|
|
61
|
+
replacement: "ghp_***REDACTED***",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
regex: /ghs_[a-zA-Z0-9]{36,}/g,
|
|
65
|
+
replacement: "ghs_***REDACTED***",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
regex: /eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+/g,
|
|
69
|
+
replacement: "***REDACTED_JWT***",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
regex: /Bearer\s+[a-zA-Z0-9_\-.+\/=]+/gi,
|
|
73
|
+
replacement: "Bearer ***REDACTED***",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
regex: /api[_-]?key["'\s:=]+[a-zA-Z0-9_\-.+\/=]{20,}/gi,
|
|
77
|
+
replacement: "api_key: ***REDACTED***",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
regex: /token["'\s:=]+[a-zA-Z0-9_\-.+\/=]{20,}/gi,
|
|
81
|
+
replacement: "token: ***REDACTED***",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
regex: /password["'\s:=]+["']?([^"'\s]{8,})["']?/gi,
|
|
85
|
+
replacement: "password: ***REDACTED***",
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
regex: /secret["'\s:=]+["']?([^"'\s]{8,})["']?/gi,
|
|
89
|
+
replacement: "secret: ***REDACTED***",
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
let sanitized = text;
|
|
93
|
+
for (const pattern of patterns) {
|
|
94
|
+
sanitized = sanitized.replace(pattern.regex, pattern.replacement);
|
|
95
|
+
}
|
|
96
|
+
return sanitized;
|
|
97
|
+
}
|
|
98
|
+
function truncateString(str, maxLength) {
|
|
99
|
+
if (!str || str.length === 0) {
|
|
100
|
+
return { value: "", truncated: false };
|
|
101
|
+
}
|
|
102
|
+
const sanitized = sanitizeCredentials(str);
|
|
103
|
+
if (sanitized.length <= maxLength) {
|
|
104
|
+
return { value: sanitized, truncated: false };
|
|
105
|
+
}
|
|
106
|
+
return { value: sanitized.substring(0, maxLength), truncated: true };
|
|
107
|
+
}
|
|
108
|
+
function extractSystemPrompt(params) {
|
|
109
|
+
if (!params.messages || !Array.isArray(params.messages)) {
|
|
110
|
+
return "";
|
|
111
|
+
}
|
|
112
|
+
const systemMessages = params.messages
|
|
113
|
+
.filter((msg) => msg.role === "system")
|
|
114
|
+
.map((msg) => msg.content)
|
|
115
|
+
.filter(Boolean);
|
|
116
|
+
return systemMessages.join("\n\n");
|
|
117
|
+
}
|
|
118
|
+
function extractInputMessages(params) {
|
|
119
|
+
if (!params.messages || !Array.isArray(params.messages)) {
|
|
120
|
+
return "";
|
|
121
|
+
}
|
|
122
|
+
return params.messages
|
|
123
|
+
.filter((msg) => msg.role !== "system")
|
|
124
|
+
.map((message) => `[${message.role}]\n${message.content}`)
|
|
125
|
+
.join("\n\n");
|
|
126
|
+
}
|
|
127
|
+
function extractOutputResponse(response) {
|
|
128
|
+
if (!response.choices || response.choices.length === 0) {
|
|
129
|
+
return "";
|
|
130
|
+
}
|
|
131
|
+
const choice = response.choices[0];
|
|
132
|
+
const parts = [];
|
|
133
|
+
if (choice.message?.content) {
|
|
134
|
+
parts.push(choice.message.content);
|
|
135
|
+
}
|
|
136
|
+
if (choice.delta?.content) {
|
|
137
|
+
parts.push(choice.delta.content);
|
|
138
|
+
}
|
|
139
|
+
const message = choice.message;
|
|
140
|
+
if (message?.tool_calls && Array.isArray(message.tool_calls)) {
|
|
141
|
+
message.tool_calls.forEach((toolCall) => {
|
|
142
|
+
if (toolCall.function?.name) {
|
|
143
|
+
parts.push(`[TOOL_USE: ${toolCall.function.name}]`);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (message?.function_call?.name) {
|
|
148
|
+
parts.push(`[FUNCTION_CALL: ${message.function_call.name}]`);
|
|
149
|
+
}
|
|
150
|
+
return parts.join("\n");
|
|
151
|
+
}
|
|
152
|
+
function shouldCapturePrompts(metadata) {
|
|
153
|
+
if (metadata?.capturePrompts !== undefined) {
|
|
154
|
+
return metadata.capturePrompts;
|
|
155
|
+
}
|
|
156
|
+
const config = (0, index_js_1.getConfig)();
|
|
157
|
+
if (config?.capturePrompts !== undefined) {
|
|
158
|
+
return config.capturePrompts;
|
|
159
|
+
}
|
|
160
|
+
const envValue = process.env.REVENIUM_CAPTURE_PROMPTS;
|
|
161
|
+
if (envValue !== undefined) {
|
|
162
|
+
return envValue.toLowerCase() === "true";
|
|
163
|
+
}
|
|
164
|
+
return CAPTURE_PROMPTS_DEFAULT;
|
|
165
|
+
}
|
|
166
|
+
function extractPrompts(params, response, metadata) {
|
|
167
|
+
if (!shouldCapturePrompts(metadata)) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
const maxSize = getMaxPromptSize();
|
|
171
|
+
let anyTruncated = false;
|
|
172
|
+
const systemPromptRaw = extractSystemPrompt(params);
|
|
173
|
+
const systemPromptResult = truncateString(systemPromptRaw, maxSize);
|
|
174
|
+
anyTruncated = anyTruncated || systemPromptResult.truncated;
|
|
175
|
+
const inputMessagesRaw = extractInputMessages(params);
|
|
176
|
+
const inputMessagesResult = truncateString(inputMessagesRaw, maxSize);
|
|
177
|
+
anyTruncated = anyTruncated || inputMessagesResult.truncated;
|
|
178
|
+
const outputResponseRaw = extractOutputResponse(response);
|
|
179
|
+
const outputResponseResult = truncateString(outputResponseRaw, maxSize);
|
|
180
|
+
anyTruncated = anyTruncated || outputResponseResult.truncated;
|
|
181
|
+
const hasAnyContent = systemPromptResult.value ||
|
|
182
|
+
inputMessagesResult.value ||
|
|
183
|
+
outputResponseResult.value;
|
|
184
|
+
if (!hasAnyContent) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
systemPrompt: systemPromptResult.value || undefined,
|
|
189
|
+
inputMessages: inputMessagesResult.value || undefined,
|
|
190
|
+
outputResponse: outputResponseResult.value || undefined,
|
|
191
|
+
promptsTruncated: anyTruncated,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=prompt-extraction.js.map
|