@revenium/perplexity 1.0.10 → 1.0.14
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 +2 -2
- package/README.md +448 -566
- package/examples/basic.ts +17 -0
- package/examples/chat-completions.ts +22 -0
- package/examples/enhanced.ts +20 -0
- package/examples/streaming.ts +24 -0
- package/package.json +45 -61
- package/playground/basic.js +7 -17
- package/playground/enhanced.js +9 -22
- package/playground/streaming.js +10 -26
- package/src/index.ts +1 -35
- package/src/interfaces/chatCompletionRequest.ts +9 -0
- package/src/interfaces/credential.ts +4 -0
- package/src/interfaces/meteringRequest.ts +14 -0
- package/src/{types/metering.ts → interfaces/meteringResponse.ts} +3 -3
- package/src/interfaces/operation.ts +4 -0
- package/src/{types → interfaces}/subscriber.ts +1 -1
- package/src/interfaces/tokenCounts.ts +7 -0
- package/src/{types → interfaces}/usageMetadata.ts +1 -1
- package/src/middleware.ts +151 -0
- package/src/models/Logger.ts +5 -5
- package/src/models/Metering.ts +86 -0
- package/src/utils/calculateDurationMs.ts +1 -1
- package/src/utils/constants/constants.ts +9 -16
- package/src/utils/constants/logLevels.ts +1 -0
- package/src/utils/constants/messages.ts +8 -32
- package/src/utils/constants/models.ts +20 -0
- package/src/utils/extractTokenCount.ts +26 -0
- package/src/utils/generateTransactionId.ts +1 -1
- package/src/utils/index.ts +39 -12
- package/src/utils/loadEnv.ts +8 -0
- package/src/utils/safeExtract.ts +60 -11
- package/tsconfig.json +10 -18
- package/dist/index.d.ts +0 -8
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -40
- package/dist/index.js.map +0 -1
- package/dist/models/Exception/ApiResponseError.d.ts +0 -6
- package/dist/models/Exception/ApiResponseError.d.ts.map +0 -1
- package/dist/models/Exception/ApiResponseError.js +0 -13
- package/dist/models/Exception/ApiResponseError.js.map +0 -1
- package/dist/models/Exception/ConfigurationError.d.ts +0 -4
- package/dist/models/Exception/ConfigurationError.d.ts.map +0 -1
- package/dist/models/Exception/ConfigurationError.js +0 -11
- package/dist/models/Exception/ConfigurationError.js.map +0 -1
- package/dist/models/Exception/MeteringError.d.ts +0 -5
- package/dist/models/Exception/MeteringError.d.ts.map +0 -1
- package/dist/models/Exception/MeteringError.js +0 -12
- package/dist/models/Exception/MeteringError.js.map +0 -1
- package/dist/models/Exception/MiddlewareActivationError.d.ts +0 -4
- package/dist/models/Exception/MiddlewareActivationError.d.ts.map +0 -1
- package/dist/models/Exception/MiddlewareActivationError.js +0 -11
- package/dist/models/Exception/MiddlewareActivationError.js.map +0 -1
- package/dist/models/Exception/StreamTrackingError.d.ts +0 -4
- package/dist/models/Exception/StreamTrackingError.d.ts.map +0 -1
- package/dist/models/Exception/StreamTrackingError.js +0 -11
- package/dist/models/Exception/StreamTrackingError.js.map +0 -1
- package/dist/models/Exception/TokenCountingError.d.ts +0 -4
- package/dist/models/Exception/TokenCountingError.d.ts.map +0 -1
- package/dist/models/Exception/TokenCountingError.js +0 -11
- package/dist/models/Exception/TokenCountingError.js.map +0 -1
- package/dist/models/Exception/index.d.ts +0 -7
- package/dist/models/Exception/index.d.ts.map +0 -1
- package/dist/models/Exception/index.js +0 -23
- package/dist/models/Exception/index.js.map +0 -1
- package/dist/models/Logger.d.ts +0 -10
- package/dist/models/Logger.d.ts.map +0 -1
- package/dist/models/Logger.js +0 -36
- package/dist/models/Logger.js.map +0 -1
- package/dist/models/index.d.ts +0 -3
- package/dist/models/index.d.ts.map +0 -1
- package/dist/models/index.js +0 -19
- package/dist/models/index.js.map +0 -1
- package/dist/perplexity-ai/client.d.ts +0 -31
- package/dist/perplexity-ai/client.d.ts.map +0 -1
- package/dist/perplexity-ai/client.js +0 -75
- package/dist/perplexity-ai/client.js.map +0 -1
- package/dist/perplexity-ai/index.d.ts +0 -3
- package/dist/perplexity-ai/index.d.ts.map +0 -1
- package/dist/perplexity-ai/index.js +0 -19
- package/dist/perplexity-ai/index.js.map +0 -1
- package/dist/perplexity-ai/middleware.d.ts +0 -2
- package/dist/perplexity-ai/middleware.d.ts.map +0 -1
- package/dist/perplexity-ai/middleware.js +0 -195
- package/dist/perplexity-ai/middleware.js.map +0 -1
- package/dist/types/context.d.ts +0 -9
- package/dist/types/context.d.ts.map +0 -1
- package/dist/types/context.js +0 -3
- package/dist/types/context.js.map +0 -1
- package/dist/types/index.d.ts +0 -12
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -28
- package/dist/types/index.js.map +0 -1
- package/dist/types/metering.d.ts +0 -28
- package/dist/types/metering.d.ts.map +0 -1
- package/dist/types/metering.js +0 -3
- package/dist/types/metering.js.map +0 -1
- package/dist/types/modelInfo.d.ts +0 -6
- package/dist/types/modelInfo.d.ts.map +0 -1
- package/dist/types/modelInfo.js +0 -3
- package/dist/types/modelInfo.js.map +0 -1
- package/dist/types/operation.d.ts +0 -5
- package/dist/types/operation.d.ts.map +0 -1
- package/dist/types/operation.js +0 -9
- package/dist/types/operation.js.map +0 -1
- package/dist/types/perplexityConfig.d.ts +0 -5
- package/dist/types/perplexityConfig.d.ts.map +0 -1
- package/dist/types/perplexityConfig.js +0 -3
- package/dist/types/perplexityConfig.js.map +0 -1
- package/dist/types/provider.d.ts +0 -4
- package/dist/types/provider.d.ts.map +0 -1
- package/dist/types/provider.js +0 -8
- package/dist/types/provider.js.map +0 -1
- package/dist/types/reveniumConfig.d.ts +0 -6
- package/dist/types/reveniumConfig.d.ts.map +0 -1
- package/dist/types/reveniumConfig.js +0 -3
- package/dist/types/reveniumConfig.js.map +0 -1
- package/dist/types/streamTracker.d.ts +0 -9
- package/dist/types/streamTracker.d.ts.map +0 -1
- package/dist/types/streamTracker.js +0 -3
- package/dist/types/streamTracker.js.map +0 -1
- package/dist/types/subscriber.d.ts +0 -9
- package/dist/types/subscriber.d.ts.map +0 -1
- package/dist/types/subscriber.js +0 -3
- package/dist/types/subscriber.js.map +0 -1
- package/dist/types/tokenCounts.d.ts +0 -6
- package/dist/types/tokenCounts.d.ts.map +0 -1
- package/dist/types/tokenCounts.js +0 -3
- package/dist/types/tokenCounts.js.map +0 -1
- package/dist/types/usageData.d.ts +0 -16
- package/dist/types/usageData.d.ts.map +0 -1
- package/dist/types/usageData.js +0 -3
- package/dist/types/usageData.js.map +0 -1
- package/dist/types/usageMetadata.d.ts +0 -14
- package/dist/types/usageMetadata.d.ts.map +0 -1
- package/dist/types/usageMetadata.js +0 -3
- package/dist/types/usageMetadata.js.map +0 -1
- package/dist/utils/activeMiddleware.d.ts +0 -2
- package/dist/utils/activeMiddleware.d.ts.map +0 -1
- package/dist/utils/activeMiddleware.js +0 -24
- package/dist/utils/activeMiddleware.js.map +0 -1
- package/dist/utils/askConsole.d.ts +0 -2
- package/dist/utils/askConsole.d.ts.map +0 -1
- package/dist/utils/askConsole.js +0 -20
- package/dist/utils/askConsole.js.map +0 -1
- package/dist/utils/calculateDurationMs.d.ts +0 -2
- package/dist/utils/calculateDurationMs.d.ts.map +0 -1
- package/dist/utils/calculateDurationMs.js +0 -7
- package/dist/utils/calculateDurationMs.js.map +0 -1
- package/dist/utils/constants/constants.d.ts +0 -9
- package/dist/utils/constants/constants.d.ts.map +0 -1
- package/dist/utils/constants/constants.js +0 -19
- package/dist/utils/constants/constants.js.map +0 -1
- package/dist/utils/constants/messages.d.ts +0 -19
- package/dist/utils/constants/messages.d.ts.map +0 -1
- package/dist/utils/constants/messages.js +0 -22
- package/dist/utils/constants/messages.js.map +0 -1
- package/dist/utils/createMeteringRequest.d.ts +0 -3
- package/dist/utils/createMeteringRequest.d.ts.map +0 -1
- package/dist/utils/createMeteringRequest.js +0 -10
- package/dist/utils/createMeteringRequest.js.map +0 -1
- package/dist/utils/createPerplexityMetadata.d.ts +0 -3
- package/dist/utils/createPerplexityMetadata.d.ts.map +0 -1
- package/dist/utils/createPerplexityMetadata.js +0 -12
- package/dist/utils/createPerplexityMetadata.js.map +0 -1
- package/dist/utils/extractModelName.d.ts +0 -2
- package/dist/utils/extractModelName.d.ts.map +0 -1
- package/dist/utils/extractModelName.js +0 -15
- package/dist/utils/extractModelName.js.map +0 -1
- package/dist/utils/extractPerplexityTokenCounts.d.ts +0 -3
- package/dist/utils/extractPerplexityTokenCounts.d.ts.map +0 -1
- package/dist/utils/extractPerplexityTokenCounts.js +0 -17
- package/dist/utils/extractPerplexityTokenCounts.js.map +0 -1
- package/dist/utils/extractStopReason.d.ts +0 -2
- package/dist/utils/extractStopReason.d.ts.map +0 -1
- package/dist/utils/extractStopReason.js +0 -14
- package/dist/utils/extractStopReason.js.map +0 -1
- package/dist/utils/extractUsageMetadata.d.ts +0 -3
- package/dist/utils/extractUsageMetadata.d.ts.map +0 -1
- package/dist/utils/extractUsageMetadata.js +0 -15
- package/dist/utils/extractUsageMetadata.js.map +0 -1
- package/dist/utils/formatTimestamp.d.ts +0 -2
- package/dist/utils/formatTimestamp.d.ts.map +0 -1
- package/dist/utils/formatTimestamp.js +0 -7
- package/dist/utils/formatTimestamp.js.map +0 -1
- package/dist/utils/generateTransactionId.d.ts +0 -2
- package/dist/utils/generateTransactionId.d.ts.map +0 -1
- package/dist/utils/generateTransactionId.js +0 -8
- package/dist/utils/generateTransactionId.js.map +0 -1
- package/dist/utils/getEnv.d.ts +0 -4
- package/dist/utils/getEnv.d.ts.map +0 -1
- package/dist/utils/getEnv.js +0 -16
- package/dist/utils/getEnv.js.map +0 -1
- package/dist/utils/index.d.ts +0 -13
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -29
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/safeExtract.d.ts +0 -2
- package/dist/utils/safeExtract.d.ts.map +0 -1
- package/dist/utils/safeExtract.js +0 -22
- package/dist/utils/safeExtract.js.map +0 -1
- package/dist/utils/sendMeteringData.d.ts +0 -3
- package/dist/utils/sendMeteringData.d.ts.map +0 -1
- package/dist/utils/sendMeteringData.js +0 -35
- package/dist/utils/sendMeteringData.js.map +0 -1
- package/dist/utils/verifyLogVerbose.d.ts +0 -2
- package/dist/utils/verifyLogVerbose.d.ts.map +0 -1
- package/dist/utils/verifyLogVerbose.js +0 -10
- package/dist/utils/verifyLogVerbose.js.map +0 -1
- package/examples/basic-client-example.ts +0 -36
- package/examples/metadata-example.ts +0 -97
- package/examples/multiple-models-example.ts +0 -65
- package/examples/openai-client-example.ts +0 -76
- package/examples/perplexity_basic_example.ts +0 -24
- package/examples/perplexity_middleware_example.ts +0 -222
- package/examples/run-all-examples.ts +0 -118
- package/examples/simple-test.ts +0 -278
- package/examples/streaming-example.ts +0 -46
- package/playground/custom-config.js +0 -82
- package/playground/metadata.js +0 -94
- package/playground/multiple-models.js +0 -62
- package/playground/openai-client.js +0 -73
- package/src/models/Exception/ApiResponseError.ts +0 -6
- package/src/models/Exception/ConfigurationError.ts +0 -6
- package/src/models/Exception/MeteringError.ts +0 -6
- package/src/models/Exception/MiddlewareActivationError.ts +0 -6
- package/src/models/Exception/StreamTrackingError.ts +0 -6
- package/src/models/Exception/TokenCountingError.ts +0 -6
- package/src/models/Exception/index.ts +0 -6
- package/src/models/index.ts +0 -2
- package/src/perplexity-ai/client.ts +0 -100
- package/src/perplexity-ai/index.ts +0 -2
- package/src/perplexity-ai/middleware.ts +0 -297
- package/src/types/context.ts +0 -9
- package/src/types/index.ts +0 -11
- package/src/types/modelInfo.ts +0 -5
- package/src/types/operation.ts +0 -4
- package/src/types/perplexityConfig.ts +0 -4
- package/src/types/provider.ts +0 -3
- package/src/types/reveniumConfig.ts +0 -5
- package/src/types/streamTracker.ts +0 -9
- package/src/types/tokenCounts.ts +0 -5
- package/src/types/usageData.ts +0 -16
- package/src/utils/activeMiddleware.ts +0 -34
- package/src/utils/askConsole.ts +0 -15
- package/src/utils/createMeteringRequest.ts +0 -16
- package/src/utils/createPerplexityMetadata.ts +0 -11
- package/src/utils/extractModelName.ts +0 -14
- package/src/utils/extractPerplexityTokenCounts.ts +0 -16
- package/src/utils/extractStopReason.ts +0 -13
- package/src/utils/extractUsageMetadata.ts +0 -15
- package/src/utils/getEnv.ts +0 -16
- package/src/utils/sendMeteringData.ts +0 -46
- package/src/utils/verifyLogVerbose.ts +0 -7
- /package/src/utils/{formatTimestamp.ts → formatTimeStamp.ts} +0 -0
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
import { logger, Logger } from "../models";
|
|
2
|
-
import {
|
|
3
|
-
OperationType,
|
|
4
|
-
Provider,
|
|
5
|
-
UsageMetadata,
|
|
6
|
-
StreamTracker,
|
|
7
|
-
} from "../types";
|
|
8
|
-
import {
|
|
9
|
-
formatTimestamp,
|
|
10
|
-
calculateDurationMs,
|
|
11
|
-
extractPerplexityTokenCounts,
|
|
12
|
-
extractStopReason,
|
|
13
|
-
extractModelName,
|
|
14
|
-
extractUsageMetadata,
|
|
15
|
-
createMeteringRequest,
|
|
16
|
-
sendMeteringData,
|
|
17
|
-
generateTransactionId,
|
|
18
|
-
} from "../utils";
|
|
19
|
-
import { ConfigurationError, StreamTrackingError } from "../models";
|
|
20
|
-
import {
|
|
21
|
-
DEBUG_MIDDLEWARE_ALREADY_INITIALIZED_MESSAGE,
|
|
22
|
-
DEBUG_MIDDLEWARE_FAILED_TO_INITIALIZE_MESSAGE,
|
|
23
|
-
DEBUG_MIDDLEWARE_INITIALIZED_MESSAGE,
|
|
24
|
-
FAILED_TO_INITIALIZE_PERPLEXITY_MIDDLEWARE_MESSAGE,
|
|
25
|
-
DEBUG_MIDDLEWARE_INTERCEPTING_PERPLEXITY_REQUESTS_MESSAGE,
|
|
26
|
-
WARNING_REVENIUM_METERING_API_KEY_NOT_FOUND_MESSAGE,
|
|
27
|
-
FAILED_TO_PARSE_REQUEST_BODY_FOR_METADATA_EXTRACTION_MESSAGE,
|
|
28
|
-
DEBUG_MIDDLEWARE_PERPLEXITY_API_REQUEST_INTERCEPTED_MESSAGE,
|
|
29
|
-
ERROR_PERPLEXITY_API_REQUEST_FAILED_MESSAGE,
|
|
30
|
-
WARNING_FAILED_TO_SEND_METERING_DATA_MESSAGE,
|
|
31
|
-
DEBUG_MIDDLEWARE_PERPLEXITY_API_RESPONSE_METERING_COMPLETED_MESSAGE,
|
|
32
|
-
DEBUG_SKIPPING_METERING_DATA_SEND_MESSAGE,
|
|
33
|
-
ERROR_FAILED_TO_PROCESS_PERPLEXITY_RESPONSE_MESSAGE,
|
|
34
|
-
} from "../utils/constants/messages";
|
|
35
|
-
import {
|
|
36
|
-
CURRENT_PERPLEXITY_BASE_URL,
|
|
37
|
-
DEFAULT_PERPLEXITY_MODEL,
|
|
38
|
-
REVENIUM_METERING_BASE_URL,
|
|
39
|
-
} from "../utils/constants/constants";
|
|
40
|
-
import { Subscriber } from "../types/subscriber";
|
|
41
|
-
import {
|
|
42
|
-
getPerplexityBaseUrl,
|
|
43
|
-
getReveniumApiKey,
|
|
44
|
-
getReveniumBaseUrl,
|
|
45
|
-
} from "../utils/getEnv";
|
|
46
|
-
|
|
47
|
-
// Stream tracking storage
|
|
48
|
-
const streamTrackers: Map<string, StreamTracker> = new Map<
|
|
49
|
-
string,
|
|
50
|
-
StreamTracker
|
|
51
|
-
>();
|
|
52
|
-
|
|
53
|
-
// Track if middleware has been initialized to avoid double initialization
|
|
54
|
-
let middlewareInitialized: boolean = false;
|
|
55
|
-
|
|
56
|
-
//Initialize Perplexity AI middleware.
|
|
57
|
-
function initializePerplexityMiddleware(): void {
|
|
58
|
-
if (middlewareInitialized) {
|
|
59
|
-
console.log(DEBUG_MIDDLEWARE_ALREADY_INITIALIZED_MESSAGE);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Always initialize middleware, even without API key
|
|
64
|
-
if (!getReveniumApiKey()) {
|
|
65
|
-
Logger.warning(WARNING_REVENIUM_METERING_API_KEY_NOT_FOUND_MESSAGE);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
// Intercept HTTP requests to Perplexity API
|
|
70
|
-
interceptPerplexityHTTPRequests();
|
|
71
|
-
|
|
72
|
-
// Mark as initialized
|
|
73
|
-
middlewareInitialized = true;
|
|
74
|
-
console.log(DEBUG_MIDDLEWARE_INITIALIZED_MESSAGE);
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.error(DEBUG_MIDDLEWARE_FAILED_TO_INITIALIZE_MESSAGE, error);
|
|
77
|
-
throw new ConfigurationError(
|
|
78
|
-
`${FAILED_TO_INITIALIZE_PERPLEXITY_MIDDLEWARE_MESSAGE}: ${error}`
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
//Intercept HTTP requests to Perplexity API
|
|
84
|
-
function interceptPerplexityHTTPRequests(): void {
|
|
85
|
-
// Store original fetch function
|
|
86
|
-
const originalFetch = global.fetch;
|
|
87
|
-
|
|
88
|
-
// Override fetch to intercept Perplexity API calls
|
|
89
|
-
global.fetch = async function (
|
|
90
|
-
input: string | URL | Request,
|
|
91
|
-
init?: RequestInit
|
|
92
|
-
): Promise<Response> {
|
|
93
|
-
const url = typeof input === "string" ? input : input.toString();
|
|
94
|
-
console.log("🔍 [DEBUG] URL:", url);
|
|
95
|
-
|
|
96
|
-
// Check if this is a Perplexity API request
|
|
97
|
-
if (
|
|
98
|
-
url.includes(getPerplexityBaseUrl()) ||
|
|
99
|
-
url.includes("api.perplexity.ai")
|
|
100
|
-
) {
|
|
101
|
-
return await handlePerplexityRequest(url, init, originalFetch);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// For non-Perplexity requests, use original fetch
|
|
105
|
-
return originalFetch(input, init);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
console.log(DEBUG_MIDDLEWARE_INTERCEPTING_PERPLEXITY_REQUESTS_MESSAGE);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
//Handle Perplexity API requests
|
|
112
|
-
async function handlePerplexityRequest(
|
|
113
|
-
url: string,
|
|
114
|
-
init: RequestInit | undefined,
|
|
115
|
-
originalFetch: typeof fetch
|
|
116
|
-
): Promise<Response> {
|
|
117
|
-
const startTime = new Date();
|
|
118
|
-
const transactionId = generateTransactionId();
|
|
119
|
-
|
|
120
|
-
// Extract request body for metadata
|
|
121
|
-
let requestBody: any = {};
|
|
122
|
-
if (init?.body) {
|
|
123
|
-
try {
|
|
124
|
-
requestBody =
|
|
125
|
-
typeof init.body === "string" ? JSON.parse(init.body) : init.body;
|
|
126
|
-
} catch (error) {
|
|
127
|
-
Logger.warning(
|
|
128
|
-
FAILED_TO_PARSE_REQUEST_BODY_FOR_METADATA_EXTRACTION_MESSAGE
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Extract usage metadata
|
|
134
|
-
const usageMetadata = extractUsageMetadata(requestBody, null);
|
|
135
|
-
const model = requestBody.model || DEFAULT_PERPLEXITY_MODEL;
|
|
136
|
-
|
|
137
|
-
Logger.debug(DEBUG_MIDDLEWARE_PERPLEXITY_API_REQUEST_INTERCEPTED_MESSAGE, {
|
|
138
|
-
transactionId,
|
|
139
|
-
model,
|
|
140
|
-
url,
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
try {
|
|
144
|
-
// Make the original request
|
|
145
|
-
const response = await originalFetch(url, init);
|
|
146
|
-
|
|
147
|
-
// Clone the response so we can read it and still return it
|
|
148
|
-
const responseClone = response.clone();
|
|
149
|
-
|
|
150
|
-
// Process the response asynchronously (don't wait for it)
|
|
151
|
-
processPerplexityResponse(
|
|
152
|
-
responseClone,
|
|
153
|
-
transactionId,
|
|
154
|
-
model,
|
|
155
|
-
startTime,
|
|
156
|
-
usageMetadata
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
// Return the original response immediately
|
|
160
|
-
return response;
|
|
161
|
-
} catch (error) {
|
|
162
|
-
Logger.error(ERROR_PERPLEXITY_API_REQUEST_FAILED_MESSAGE, {
|
|
163
|
-
transactionId,
|
|
164
|
-
error,
|
|
165
|
-
});
|
|
166
|
-
throw error;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
//Process Perplexity API response
|
|
171
|
-
async function processPerplexityResponse(
|
|
172
|
-
response: Response,
|
|
173
|
-
transactionId: string,
|
|
174
|
-
model: string,
|
|
175
|
-
startTime: Date,
|
|
176
|
-
usageMetadata?: UsageMetadata,
|
|
177
|
-
subscriber?: Subscriber,
|
|
178
|
-
taskType?: string,
|
|
179
|
-
costType?: string,
|
|
180
|
-
operationType?: string,
|
|
181
|
-
organizationId?: string,
|
|
182
|
-
productId?: string,
|
|
183
|
-
isStreamed?: boolean
|
|
184
|
-
): Promise<void> {
|
|
185
|
-
try {
|
|
186
|
-
const endTime = new Date();
|
|
187
|
-
const duration = calculateDurationMs(startTime, endTime);
|
|
188
|
-
|
|
189
|
-
// Check if this is a streaming response
|
|
190
|
-
const contentType = response.headers.get("content-type") || "";
|
|
191
|
-
const isStreamingResponse =
|
|
192
|
-
contentType.includes("text/plain") ||
|
|
193
|
-
contentType.includes("text/event-stream");
|
|
194
|
-
|
|
195
|
-
let responseData: any;
|
|
196
|
-
let tokenCounts = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
197
|
-
let stopReason = "END";
|
|
198
|
-
|
|
199
|
-
if (isStreamingResponse) {
|
|
200
|
-
// For streaming responses, we can't easily parse the full response
|
|
201
|
-
// We'll extract what we can from the stream or use defaults
|
|
202
|
-
const responseText = await response.text();
|
|
203
|
-
|
|
204
|
-
// Try to extract token information from the last complete JSON chunk
|
|
205
|
-
const jsonChunks = responseText
|
|
206
|
-
.split("\n")
|
|
207
|
-
.filter((line) => line.startsWith("data: ") && line !== "data: [DONE]")
|
|
208
|
-
.map((line) => line.substring(6)); // Remove 'data: ' prefix
|
|
209
|
-
|
|
210
|
-
if (jsonChunks.length > 0) {
|
|
211
|
-
try {
|
|
212
|
-
// Parse the last chunk to get usage information
|
|
213
|
-
const lastChunk = JSON.parse(jsonChunks[jsonChunks.length - 1]);
|
|
214
|
-
if (lastChunk.usage) {
|
|
215
|
-
tokenCounts = extractPerplexityTokenCounts(lastChunk);
|
|
216
|
-
}
|
|
217
|
-
} catch (e) {
|
|
218
|
-
// If we can't parse, use defaults
|
|
219
|
-
Logger.warning(
|
|
220
|
-
"Could not parse streaming response for token counts, using defaults"
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
responseData = { usage: tokenCounts };
|
|
226
|
-
} else {
|
|
227
|
-
// Parse response body for non-streaming responses
|
|
228
|
-
responseData = await response.json();
|
|
229
|
-
tokenCounts = extractPerplexityTokenCounts(responseData);
|
|
230
|
-
stopReason = extractStopReason(responseData);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const modelName = extractModelName(responseData, model);
|
|
234
|
-
|
|
235
|
-
// Send metering data (only if API key is available)
|
|
236
|
-
if (getReveniumApiKey()) {
|
|
237
|
-
try {
|
|
238
|
-
await sendMeteringData(
|
|
239
|
-
{
|
|
240
|
-
stopReason: "END",
|
|
241
|
-
costType: costType || "AI",
|
|
242
|
-
isStreamed: isStreamed || true,
|
|
243
|
-
taskType: taskType || "chat",
|
|
244
|
-
agent: "perplexity-ai",
|
|
245
|
-
operationType: operationType || "CHAT",
|
|
246
|
-
inputTokenCount: tokenCounts.inputTokens,
|
|
247
|
-
outputTokenCount: tokenCounts.outputTokens,
|
|
248
|
-
reasoningTokenCount: 0,
|
|
249
|
-
cacheCreationTokenCount: 0,
|
|
250
|
-
cacheReadTokenCount: 0,
|
|
251
|
-
totalTokenCount: tokenCounts.totalTokens,
|
|
252
|
-
organizationId: organizationId || "my-customers-name",
|
|
253
|
-
productId: productId || "free-trial",
|
|
254
|
-
subscriber: subscriber || {
|
|
255
|
-
id: `user-${generateTransactionId()}`,
|
|
256
|
-
email: `user@perplexity.ai`,
|
|
257
|
-
credential: {
|
|
258
|
-
name: "keyname",
|
|
259
|
-
value: "keyValue",
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
model: modelName,
|
|
263
|
-
transactionId,
|
|
264
|
-
responseTime: formatTimestamp(endTime),
|
|
265
|
-
requestDuration: duration,
|
|
266
|
-
provider: Provider.PERPLEXITY,
|
|
267
|
-
requestTime: formatTimestamp(startTime),
|
|
268
|
-
completionStartTime: formatTimestamp(endTime),
|
|
269
|
-
timeToFirstToken: 0,
|
|
270
|
-
middleware_source: "node",
|
|
271
|
-
},
|
|
272
|
-
getReveniumApiKey(),
|
|
273
|
-
getReveniumBaseUrl()
|
|
274
|
-
);
|
|
275
|
-
} catch (error) {
|
|
276
|
-
Logger.warning(WARNING_FAILED_TO_SEND_METERING_DATA_MESSAGE, { error });
|
|
277
|
-
}
|
|
278
|
-
} else {
|
|
279
|
-
Logger.debug(DEBUG_SKIPPING_METERING_DATA_SEND_MESSAGE);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
Logger.debug(
|
|
283
|
-
DEBUG_MIDDLEWARE_PERPLEXITY_API_RESPONSE_METERING_COMPLETED_MESSAGE,
|
|
284
|
-
{
|
|
285
|
-
transactionId,
|
|
286
|
-
}
|
|
287
|
-
);
|
|
288
|
-
} catch (error) {
|
|
289
|
-
Logger.error(ERROR_FAILED_TO_PROCESS_PERPLEXITY_RESPONSE_MESSAGE, {
|
|
290
|
-
transactionId,
|
|
291
|
-
error,
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Initialize middleware when this module is imported
|
|
297
|
-
initializePerplexityMiddleware();
|
package/src/types/context.ts
DELETED
package/src/types/index.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export * from "./context";
|
|
2
|
-
export * from "./perplexityConfig";
|
|
3
|
-
export * from "./metering";
|
|
4
|
-
export * from "./modelInfo";
|
|
5
|
-
export * from "./operation";
|
|
6
|
-
export * from "./provider";
|
|
7
|
-
export * from "./reveniumConfig";
|
|
8
|
-
export * from "./streamTracker";
|
|
9
|
-
export * from "./tokenCounts";
|
|
10
|
-
export * from "./usageData";
|
|
11
|
-
export * from "./usageMetadata";
|
package/src/types/modelInfo.ts
DELETED
package/src/types/operation.ts
DELETED
package/src/types/provider.ts
DELETED
package/src/types/tokenCounts.ts
DELETED
package/src/types/usageData.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { TokenCounts } from "./tokenCounts";
|
|
2
|
-
import { UsageMetadata } from "./usageMetadata";
|
|
3
|
-
|
|
4
|
-
export interface UsageData {
|
|
5
|
-
transactionId: string;
|
|
6
|
-
model: string;
|
|
7
|
-
tokenCounts: TokenCounts;
|
|
8
|
-
stopReason: string;
|
|
9
|
-
startTime: string;
|
|
10
|
-
endTime: string;
|
|
11
|
-
duration: number;
|
|
12
|
-
operationType: string;
|
|
13
|
-
isStreaming: boolean;
|
|
14
|
-
streamId: string;
|
|
15
|
-
usageMetadata?: UsageMetadata;
|
|
16
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Logger } from "../models";
|
|
2
|
-
import { MiddlewareActivationError } from "../models";
|
|
3
|
-
import { verifyLogVerbose } from "./verifyLogVerbose";
|
|
4
|
-
|
|
5
|
-
export function activeMiddleware(
|
|
6
|
-
verboseStartup: boolean,
|
|
7
|
-
activeSDKs: string[],
|
|
8
|
-
sdkType: string
|
|
9
|
-
): void {
|
|
10
|
-
try {
|
|
11
|
-
verifyLogVerbose(
|
|
12
|
-
verboseStartup,
|
|
13
|
-
`Attempting to activate ${sdkType} middleware...`
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
// For Perplexity, we'll intercept HTTP requests to the Perplexity API
|
|
17
|
-
// This is a simpler approach since Perplexity doesn't have an official SDK
|
|
18
|
-
interceptPerplexityRequests();
|
|
19
|
-
|
|
20
|
-
activeSDKs.push(sdkType);
|
|
21
|
-
verifyLogVerbose(
|
|
22
|
-
verboseStartup,
|
|
23
|
-
`${sdkType} middleware activated successfully`
|
|
24
|
-
);
|
|
25
|
-
} catch (error) {
|
|
26
|
-
Logger.warning(`Failed to activate ${sdkType} middleware: ${error}`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function interceptPerplexityRequests(): void {
|
|
31
|
-
// This will be implemented in the main middleware file
|
|
32
|
-
// For now, we just log that we're ready to intercept
|
|
33
|
-
Logger.debug("Perplexity request interceptor ready");
|
|
34
|
-
}
|
package/src/utils/askConsole.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import readline from "readline";
|
|
2
|
-
|
|
3
|
-
export function askConsole(question: string): Promise<string> {
|
|
4
|
-
const rl = readline.createInterface({
|
|
5
|
-
input: process.stdin,
|
|
6
|
-
output: process.stdout,
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
return new Promise((resolve) => {
|
|
10
|
-
rl.question(question, (content) => {
|
|
11
|
-
rl.close();
|
|
12
|
-
resolve(content);
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MeteringRequest,
|
|
3
|
-
OperationType,
|
|
4
|
-
Provider,
|
|
5
|
-
UsageMetadata,
|
|
6
|
-
} from "../types";
|
|
7
|
-
import { formatTimestamp } from "./formatTimestamp";
|
|
8
|
-
|
|
9
|
-
export function createMeteringRequest(
|
|
10
|
-
request: MeteringRequest
|
|
11
|
-
): MeteringRequest {
|
|
12
|
-
return {
|
|
13
|
-
...request,
|
|
14
|
-
middleware_source: "node",
|
|
15
|
-
};
|
|
16
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { MODEL } from "./constants/constants";
|
|
2
|
-
import { safeExtract } from "./safeExtract";
|
|
3
|
-
|
|
4
|
-
export function extractModelName(response: any, defaultModel: string): string {
|
|
5
|
-
// Try to extract model name from response
|
|
6
|
-
const modelFromResponse = safeExtract(response, MODEL, "");
|
|
7
|
-
|
|
8
|
-
if (modelFromResponse) {
|
|
9
|
-
return modelFromResponse;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Fallback to default model
|
|
13
|
-
return defaultModel;
|
|
14
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { TokenCounts } from "../types";
|
|
2
|
-
import { SAFE_EXTRACT } from "./constants/constants";
|
|
3
|
-
import { safeExtract } from "./safeExtract";
|
|
4
|
-
|
|
5
|
-
export function extractPerplexityTokenCounts(response: any): TokenCounts {
|
|
6
|
-
// Extract token counts from Perplexity response
|
|
7
|
-
const inputTokens = safeExtract(response, SAFE_EXTRACT.INPUT_TOKENS, 0);
|
|
8
|
-
const outputTokens = safeExtract(response, SAFE_EXTRACT.OUTPUT_TOKENS, 0);
|
|
9
|
-
const totalTokens = safeExtract(response, SAFE_EXTRACT.TOTAL_TOKENS, 0);
|
|
10
|
-
|
|
11
|
-
return {
|
|
12
|
-
inputTokens,
|
|
13
|
-
outputTokens,
|
|
14
|
-
totalTokens: totalTokens || inputTokens + outputTokens,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { safeExtract } from "./safeExtract";
|
|
2
|
-
|
|
3
|
-
export function extractStopReason(response: any): string {
|
|
4
|
-
// Try to extract stop reason from Perplexity response
|
|
5
|
-
const stopReason = safeExtract(response, "choices.0.finish_reason", "");
|
|
6
|
-
|
|
7
|
-
if (stopReason) {
|
|
8
|
-
return stopReason;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// Fallback to a default reason
|
|
12
|
-
return "completed";
|
|
13
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { UsageMetadata } from '../types';
|
|
2
|
-
|
|
3
|
-
export function extractUsageMetadata(request: any, context: any): UsageMetadata | undefined {
|
|
4
|
-
// Check if usageMetadata is directly in the request
|
|
5
|
-
if (request && request.usageMetadata) {
|
|
6
|
-
return request.usageMetadata;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// Check if usageMetadata is in the context (for model-level metadata)
|
|
10
|
-
if (context && context._reveniumUsageMetadata) {
|
|
11
|
-
return context._reveniumUsageMetadata;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
package/src/utils/getEnv.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CURRENT_PERPLEXITY_BASE_URL,
|
|
3
|
-
REVENIUM_METERING_BASE_URL,
|
|
4
|
-
} from "./constants/constants";
|
|
5
|
-
|
|
6
|
-
export function getReveniumApiKey(): string {
|
|
7
|
-
return process.env.REVENIUM_METERING_API_KEY ?? "";
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function getReveniumBaseUrl(): string {
|
|
11
|
-
return process.env.REVENIUM_METERING_BASE_URL || REVENIUM_METERING_BASE_URL;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function getPerplexityBaseUrl(): string {
|
|
15
|
-
return process.env.PERPLEXITY_BASE_URL || CURRENT_PERPLEXITY_BASE_URL;
|
|
16
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import { MeteringRequest } from "../types";
|
|
3
|
-
import { MeteringError } from "../models";
|
|
4
|
-
import { STATUS_CODE, TIMEOUT_MS } from "./constants/constants";
|
|
5
|
-
|
|
6
|
-
export async function sendMeteringData(
|
|
7
|
-
meteringRequest: MeteringRequest,
|
|
8
|
-
apiKey: string,
|
|
9
|
-
baseUrl: string
|
|
10
|
-
): Promise<void> {
|
|
11
|
-
try {
|
|
12
|
-
const response = await axios.post(
|
|
13
|
-
`${baseUrl}/v2/ai/completions`,
|
|
14
|
-
meteringRequest,
|
|
15
|
-
{
|
|
16
|
-
headers: {
|
|
17
|
-
"Content-Type": "application/json",
|
|
18
|
-
Accept: "application/json",
|
|
19
|
-
"x-api-key": apiKey,
|
|
20
|
-
},
|
|
21
|
-
timeout: TIMEOUT_MS,
|
|
22
|
-
}
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
response.status !== STATUS_CODE.SUCCESS &&
|
|
27
|
-
response.status !== STATUS_CODE.CREATED
|
|
28
|
-
) {
|
|
29
|
-
throw new MeteringError(
|
|
30
|
-
`Failed to send metering data. Status: ${response.status}`,
|
|
31
|
-
new Error(`HTTP ${response.status}`)
|
|
32
|
-
);
|
|
33
|
-
} else {
|
|
34
|
-
console.log("🔍 [DEBUG] Metering data sent successfully");
|
|
35
|
-
}
|
|
36
|
-
} catch (error) {
|
|
37
|
-
if (error instanceof MeteringError) {
|
|
38
|
-
throw error;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
throw new MeteringError(
|
|
42
|
-
"Failed to send metering data to Revenium",
|
|
43
|
-
error as Error
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
File without changes
|