@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.
Files changed (255) hide show
  1. package/.env.example +2 -2
  2. package/README.md +448 -566
  3. package/examples/basic.ts +17 -0
  4. package/examples/chat-completions.ts +22 -0
  5. package/examples/enhanced.ts +20 -0
  6. package/examples/streaming.ts +24 -0
  7. package/package.json +45 -61
  8. package/playground/basic.js +7 -17
  9. package/playground/enhanced.js +9 -22
  10. package/playground/streaming.js +10 -26
  11. package/src/index.ts +1 -35
  12. package/src/interfaces/chatCompletionRequest.ts +9 -0
  13. package/src/interfaces/credential.ts +4 -0
  14. package/src/interfaces/meteringRequest.ts +14 -0
  15. package/src/{types/metering.ts → interfaces/meteringResponse.ts} +3 -3
  16. package/src/interfaces/operation.ts +4 -0
  17. package/src/{types → interfaces}/subscriber.ts +1 -1
  18. package/src/interfaces/tokenCounts.ts +7 -0
  19. package/src/{types → interfaces}/usageMetadata.ts +1 -1
  20. package/src/middleware.ts +151 -0
  21. package/src/models/Logger.ts +5 -5
  22. package/src/models/Metering.ts +86 -0
  23. package/src/utils/calculateDurationMs.ts +1 -1
  24. package/src/utils/constants/constants.ts +9 -16
  25. package/src/utils/constants/logLevels.ts +1 -0
  26. package/src/utils/constants/messages.ts +8 -32
  27. package/src/utils/constants/models.ts +20 -0
  28. package/src/utils/extractTokenCount.ts +26 -0
  29. package/src/utils/generateTransactionId.ts +1 -1
  30. package/src/utils/index.ts +39 -12
  31. package/src/utils/loadEnv.ts +8 -0
  32. package/src/utils/safeExtract.ts +60 -11
  33. package/tsconfig.json +10 -18
  34. package/dist/index.d.ts +0 -8
  35. package/dist/index.d.ts.map +0 -1
  36. package/dist/index.js +0 -40
  37. package/dist/index.js.map +0 -1
  38. package/dist/models/Exception/ApiResponseError.d.ts +0 -6
  39. package/dist/models/Exception/ApiResponseError.d.ts.map +0 -1
  40. package/dist/models/Exception/ApiResponseError.js +0 -13
  41. package/dist/models/Exception/ApiResponseError.js.map +0 -1
  42. package/dist/models/Exception/ConfigurationError.d.ts +0 -4
  43. package/dist/models/Exception/ConfigurationError.d.ts.map +0 -1
  44. package/dist/models/Exception/ConfigurationError.js +0 -11
  45. package/dist/models/Exception/ConfigurationError.js.map +0 -1
  46. package/dist/models/Exception/MeteringError.d.ts +0 -5
  47. package/dist/models/Exception/MeteringError.d.ts.map +0 -1
  48. package/dist/models/Exception/MeteringError.js +0 -12
  49. package/dist/models/Exception/MeteringError.js.map +0 -1
  50. package/dist/models/Exception/MiddlewareActivationError.d.ts +0 -4
  51. package/dist/models/Exception/MiddlewareActivationError.d.ts.map +0 -1
  52. package/dist/models/Exception/MiddlewareActivationError.js +0 -11
  53. package/dist/models/Exception/MiddlewareActivationError.js.map +0 -1
  54. package/dist/models/Exception/StreamTrackingError.d.ts +0 -4
  55. package/dist/models/Exception/StreamTrackingError.d.ts.map +0 -1
  56. package/dist/models/Exception/StreamTrackingError.js +0 -11
  57. package/dist/models/Exception/StreamTrackingError.js.map +0 -1
  58. package/dist/models/Exception/TokenCountingError.d.ts +0 -4
  59. package/dist/models/Exception/TokenCountingError.d.ts.map +0 -1
  60. package/dist/models/Exception/TokenCountingError.js +0 -11
  61. package/dist/models/Exception/TokenCountingError.js.map +0 -1
  62. package/dist/models/Exception/index.d.ts +0 -7
  63. package/dist/models/Exception/index.d.ts.map +0 -1
  64. package/dist/models/Exception/index.js +0 -23
  65. package/dist/models/Exception/index.js.map +0 -1
  66. package/dist/models/Logger.d.ts +0 -10
  67. package/dist/models/Logger.d.ts.map +0 -1
  68. package/dist/models/Logger.js +0 -36
  69. package/dist/models/Logger.js.map +0 -1
  70. package/dist/models/index.d.ts +0 -3
  71. package/dist/models/index.d.ts.map +0 -1
  72. package/dist/models/index.js +0 -19
  73. package/dist/models/index.js.map +0 -1
  74. package/dist/perplexity-ai/client.d.ts +0 -31
  75. package/dist/perplexity-ai/client.d.ts.map +0 -1
  76. package/dist/perplexity-ai/client.js +0 -75
  77. package/dist/perplexity-ai/client.js.map +0 -1
  78. package/dist/perplexity-ai/index.d.ts +0 -3
  79. package/dist/perplexity-ai/index.d.ts.map +0 -1
  80. package/dist/perplexity-ai/index.js +0 -19
  81. package/dist/perplexity-ai/index.js.map +0 -1
  82. package/dist/perplexity-ai/middleware.d.ts +0 -2
  83. package/dist/perplexity-ai/middleware.d.ts.map +0 -1
  84. package/dist/perplexity-ai/middleware.js +0 -195
  85. package/dist/perplexity-ai/middleware.js.map +0 -1
  86. package/dist/types/context.d.ts +0 -9
  87. package/dist/types/context.d.ts.map +0 -1
  88. package/dist/types/context.js +0 -3
  89. package/dist/types/context.js.map +0 -1
  90. package/dist/types/index.d.ts +0 -12
  91. package/dist/types/index.d.ts.map +0 -1
  92. package/dist/types/index.js +0 -28
  93. package/dist/types/index.js.map +0 -1
  94. package/dist/types/metering.d.ts +0 -28
  95. package/dist/types/metering.d.ts.map +0 -1
  96. package/dist/types/metering.js +0 -3
  97. package/dist/types/metering.js.map +0 -1
  98. package/dist/types/modelInfo.d.ts +0 -6
  99. package/dist/types/modelInfo.d.ts.map +0 -1
  100. package/dist/types/modelInfo.js +0 -3
  101. package/dist/types/modelInfo.js.map +0 -1
  102. package/dist/types/operation.d.ts +0 -5
  103. package/dist/types/operation.d.ts.map +0 -1
  104. package/dist/types/operation.js +0 -9
  105. package/dist/types/operation.js.map +0 -1
  106. package/dist/types/perplexityConfig.d.ts +0 -5
  107. package/dist/types/perplexityConfig.d.ts.map +0 -1
  108. package/dist/types/perplexityConfig.js +0 -3
  109. package/dist/types/perplexityConfig.js.map +0 -1
  110. package/dist/types/provider.d.ts +0 -4
  111. package/dist/types/provider.d.ts.map +0 -1
  112. package/dist/types/provider.js +0 -8
  113. package/dist/types/provider.js.map +0 -1
  114. package/dist/types/reveniumConfig.d.ts +0 -6
  115. package/dist/types/reveniumConfig.d.ts.map +0 -1
  116. package/dist/types/reveniumConfig.js +0 -3
  117. package/dist/types/reveniumConfig.js.map +0 -1
  118. package/dist/types/streamTracker.d.ts +0 -9
  119. package/dist/types/streamTracker.d.ts.map +0 -1
  120. package/dist/types/streamTracker.js +0 -3
  121. package/dist/types/streamTracker.js.map +0 -1
  122. package/dist/types/subscriber.d.ts +0 -9
  123. package/dist/types/subscriber.d.ts.map +0 -1
  124. package/dist/types/subscriber.js +0 -3
  125. package/dist/types/subscriber.js.map +0 -1
  126. package/dist/types/tokenCounts.d.ts +0 -6
  127. package/dist/types/tokenCounts.d.ts.map +0 -1
  128. package/dist/types/tokenCounts.js +0 -3
  129. package/dist/types/tokenCounts.js.map +0 -1
  130. package/dist/types/usageData.d.ts +0 -16
  131. package/dist/types/usageData.d.ts.map +0 -1
  132. package/dist/types/usageData.js +0 -3
  133. package/dist/types/usageData.js.map +0 -1
  134. package/dist/types/usageMetadata.d.ts +0 -14
  135. package/dist/types/usageMetadata.d.ts.map +0 -1
  136. package/dist/types/usageMetadata.js +0 -3
  137. package/dist/types/usageMetadata.js.map +0 -1
  138. package/dist/utils/activeMiddleware.d.ts +0 -2
  139. package/dist/utils/activeMiddleware.d.ts.map +0 -1
  140. package/dist/utils/activeMiddleware.js +0 -24
  141. package/dist/utils/activeMiddleware.js.map +0 -1
  142. package/dist/utils/askConsole.d.ts +0 -2
  143. package/dist/utils/askConsole.d.ts.map +0 -1
  144. package/dist/utils/askConsole.js +0 -20
  145. package/dist/utils/askConsole.js.map +0 -1
  146. package/dist/utils/calculateDurationMs.d.ts +0 -2
  147. package/dist/utils/calculateDurationMs.d.ts.map +0 -1
  148. package/dist/utils/calculateDurationMs.js +0 -7
  149. package/dist/utils/calculateDurationMs.js.map +0 -1
  150. package/dist/utils/constants/constants.d.ts +0 -9
  151. package/dist/utils/constants/constants.d.ts.map +0 -1
  152. package/dist/utils/constants/constants.js +0 -19
  153. package/dist/utils/constants/constants.js.map +0 -1
  154. package/dist/utils/constants/messages.d.ts +0 -19
  155. package/dist/utils/constants/messages.d.ts.map +0 -1
  156. package/dist/utils/constants/messages.js +0 -22
  157. package/dist/utils/constants/messages.js.map +0 -1
  158. package/dist/utils/createMeteringRequest.d.ts +0 -3
  159. package/dist/utils/createMeteringRequest.d.ts.map +0 -1
  160. package/dist/utils/createMeteringRequest.js +0 -10
  161. package/dist/utils/createMeteringRequest.js.map +0 -1
  162. package/dist/utils/createPerplexityMetadata.d.ts +0 -3
  163. package/dist/utils/createPerplexityMetadata.d.ts.map +0 -1
  164. package/dist/utils/createPerplexityMetadata.js +0 -12
  165. package/dist/utils/createPerplexityMetadata.js.map +0 -1
  166. package/dist/utils/extractModelName.d.ts +0 -2
  167. package/dist/utils/extractModelName.d.ts.map +0 -1
  168. package/dist/utils/extractModelName.js +0 -15
  169. package/dist/utils/extractModelName.js.map +0 -1
  170. package/dist/utils/extractPerplexityTokenCounts.d.ts +0 -3
  171. package/dist/utils/extractPerplexityTokenCounts.d.ts.map +0 -1
  172. package/dist/utils/extractPerplexityTokenCounts.js +0 -17
  173. package/dist/utils/extractPerplexityTokenCounts.js.map +0 -1
  174. package/dist/utils/extractStopReason.d.ts +0 -2
  175. package/dist/utils/extractStopReason.d.ts.map +0 -1
  176. package/dist/utils/extractStopReason.js +0 -14
  177. package/dist/utils/extractStopReason.js.map +0 -1
  178. package/dist/utils/extractUsageMetadata.d.ts +0 -3
  179. package/dist/utils/extractUsageMetadata.d.ts.map +0 -1
  180. package/dist/utils/extractUsageMetadata.js +0 -15
  181. package/dist/utils/extractUsageMetadata.js.map +0 -1
  182. package/dist/utils/formatTimestamp.d.ts +0 -2
  183. package/dist/utils/formatTimestamp.d.ts.map +0 -1
  184. package/dist/utils/formatTimestamp.js +0 -7
  185. package/dist/utils/formatTimestamp.js.map +0 -1
  186. package/dist/utils/generateTransactionId.d.ts +0 -2
  187. package/dist/utils/generateTransactionId.d.ts.map +0 -1
  188. package/dist/utils/generateTransactionId.js +0 -8
  189. package/dist/utils/generateTransactionId.js.map +0 -1
  190. package/dist/utils/getEnv.d.ts +0 -4
  191. package/dist/utils/getEnv.d.ts.map +0 -1
  192. package/dist/utils/getEnv.js +0 -16
  193. package/dist/utils/getEnv.js.map +0 -1
  194. package/dist/utils/index.d.ts +0 -13
  195. package/dist/utils/index.d.ts.map +0 -1
  196. package/dist/utils/index.js +0 -29
  197. package/dist/utils/index.js.map +0 -1
  198. package/dist/utils/safeExtract.d.ts +0 -2
  199. package/dist/utils/safeExtract.d.ts.map +0 -1
  200. package/dist/utils/safeExtract.js +0 -22
  201. package/dist/utils/safeExtract.js.map +0 -1
  202. package/dist/utils/sendMeteringData.d.ts +0 -3
  203. package/dist/utils/sendMeteringData.d.ts.map +0 -1
  204. package/dist/utils/sendMeteringData.js +0 -35
  205. package/dist/utils/sendMeteringData.js.map +0 -1
  206. package/dist/utils/verifyLogVerbose.d.ts +0 -2
  207. package/dist/utils/verifyLogVerbose.d.ts.map +0 -1
  208. package/dist/utils/verifyLogVerbose.js +0 -10
  209. package/dist/utils/verifyLogVerbose.js.map +0 -1
  210. package/examples/basic-client-example.ts +0 -36
  211. package/examples/metadata-example.ts +0 -97
  212. package/examples/multiple-models-example.ts +0 -65
  213. package/examples/openai-client-example.ts +0 -76
  214. package/examples/perplexity_basic_example.ts +0 -24
  215. package/examples/perplexity_middleware_example.ts +0 -222
  216. package/examples/run-all-examples.ts +0 -118
  217. package/examples/simple-test.ts +0 -278
  218. package/examples/streaming-example.ts +0 -46
  219. package/playground/custom-config.js +0 -82
  220. package/playground/metadata.js +0 -94
  221. package/playground/multiple-models.js +0 -62
  222. package/playground/openai-client.js +0 -73
  223. package/src/models/Exception/ApiResponseError.ts +0 -6
  224. package/src/models/Exception/ConfigurationError.ts +0 -6
  225. package/src/models/Exception/MeteringError.ts +0 -6
  226. package/src/models/Exception/MiddlewareActivationError.ts +0 -6
  227. package/src/models/Exception/StreamTrackingError.ts +0 -6
  228. package/src/models/Exception/TokenCountingError.ts +0 -6
  229. package/src/models/Exception/index.ts +0 -6
  230. package/src/models/index.ts +0 -2
  231. package/src/perplexity-ai/client.ts +0 -100
  232. package/src/perplexity-ai/index.ts +0 -2
  233. package/src/perplexity-ai/middleware.ts +0 -297
  234. package/src/types/context.ts +0 -9
  235. package/src/types/index.ts +0 -11
  236. package/src/types/modelInfo.ts +0 -5
  237. package/src/types/operation.ts +0 -4
  238. package/src/types/perplexityConfig.ts +0 -4
  239. package/src/types/provider.ts +0 -3
  240. package/src/types/reveniumConfig.ts +0 -5
  241. package/src/types/streamTracker.ts +0 -9
  242. package/src/types/tokenCounts.ts +0 -5
  243. package/src/types/usageData.ts +0 -16
  244. package/src/utils/activeMiddleware.ts +0 -34
  245. package/src/utils/askConsole.ts +0 -15
  246. package/src/utils/createMeteringRequest.ts +0 -16
  247. package/src/utils/createPerplexityMetadata.ts +0 -11
  248. package/src/utils/extractModelName.ts +0 -14
  249. package/src/utils/extractPerplexityTokenCounts.ts +0 -16
  250. package/src/utils/extractStopReason.ts +0 -13
  251. package/src/utils/extractUsageMetadata.ts +0 -15
  252. package/src/utils/getEnv.ts +0 -16
  253. package/src/utils/sendMeteringData.ts +0 -46
  254. package/src/utils/verifyLogVerbose.ts +0 -7
  255. /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();
@@ -1,9 +0,0 @@
1
- import { UsageMetadata } from "./usageMetadata";
2
-
3
- export interface Context {
4
- transactionId: string;
5
- startTime: Date;
6
- model: string;
7
- operationType: string;
8
- usageMetadata?: UsageMetadata;
9
- }
@@ -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";
@@ -1,5 +0,0 @@
1
- export interface ModelInfo {
2
- name: string;
3
- provider: string;
4
- contextLength?: number;
5
- }
@@ -1,4 +0,0 @@
1
- export enum OperationType {
2
- CHAT = "chat",
3
- STREAMING = "streaming"
4
- }
@@ -1,4 +0,0 @@
1
- export interface PerplexityConfig {
2
- apiKey: string;
3
- baseUrl: string;
4
- }
@@ -1,3 +0,0 @@
1
- export enum Provider {
2
- PERPLEXITY = "Perplexity"
3
- }
@@ -1,5 +0,0 @@
1
- export interface ReveniumConfig {
2
- apiKey: string;
3
- baseUrl: string;
4
- logLevel: string;
5
- }
@@ -1,9 +0,0 @@
1
- import { UsageMetadata } from "./usageMetadata";
2
-
3
- export interface StreamTracker {
4
- transactionId: string;
5
- startTime: Date;
6
- firstTokenTime?: Date;
7
- isComplete: boolean;
8
- usageMetadata?: UsageMetadata;
9
- }
@@ -1,5 +0,0 @@
1
- export interface TokenCounts {
2
- inputTokens: number;
3
- outputTokens: number;
4
- totalTokens: number;
5
- }
@@ -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
- }
@@ -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,11 +0,0 @@
1
- import { UsageMetadata } from "../types";
2
-
3
- export function createPerplexityMetadata(metadata?: UsageMetadata): any {
4
- if (!metadata) {
5
- return {};
6
- }
7
-
8
- return {
9
- usageMetadata: metadata,
10
- };
11
- }
@@ -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
- }
@@ -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
- }
@@ -1,7 +0,0 @@
1
- import { Logger } from "../models";
2
-
3
- export function verifyLogVerbose(verbose: boolean, message: string): void {
4
- if (verbose) {
5
- Logger.info(message);
6
- }
7
- }