@revenium/perplexity 1.0.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.
Files changed (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +367 -0
  3. package/dist/index.d.ts +8 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +40 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/models/Exception/ApiResponseError.d.ts +6 -0
  8. package/dist/models/Exception/ApiResponseError.d.ts.map +1 -0
  9. package/dist/models/Exception/ApiResponseError.js +13 -0
  10. package/dist/models/Exception/ApiResponseError.js.map +1 -0
  11. package/dist/models/Exception/ConfigurationError.d.ts +4 -0
  12. package/dist/models/Exception/ConfigurationError.d.ts.map +1 -0
  13. package/dist/models/Exception/ConfigurationError.js +11 -0
  14. package/dist/models/Exception/ConfigurationError.js.map +1 -0
  15. package/dist/models/Exception/MeteringError.d.ts +5 -0
  16. package/dist/models/Exception/MeteringError.d.ts.map +1 -0
  17. package/dist/models/Exception/MeteringError.js +12 -0
  18. package/dist/models/Exception/MeteringError.js.map +1 -0
  19. package/dist/models/Exception/MiddlewareActivationError.d.ts +4 -0
  20. package/dist/models/Exception/MiddlewareActivationError.d.ts.map +1 -0
  21. package/dist/models/Exception/MiddlewareActivationError.js +11 -0
  22. package/dist/models/Exception/MiddlewareActivationError.js.map +1 -0
  23. package/dist/models/Exception/StreamTrackingError.d.ts +4 -0
  24. package/dist/models/Exception/StreamTrackingError.d.ts.map +1 -0
  25. package/dist/models/Exception/StreamTrackingError.js +11 -0
  26. package/dist/models/Exception/StreamTrackingError.js.map +1 -0
  27. package/dist/models/Exception/TokenCountingError.d.ts +4 -0
  28. package/dist/models/Exception/TokenCountingError.d.ts.map +1 -0
  29. package/dist/models/Exception/TokenCountingError.js +11 -0
  30. package/dist/models/Exception/TokenCountingError.js.map +1 -0
  31. package/dist/models/Exception/index.d.ts +7 -0
  32. package/dist/models/Exception/index.d.ts.map +1 -0
  33. package/dist/models/Exception/index.js +23 -0
  34. package/dist/models/Exception/index.js.map +1 -0
  35. package/dist/models/Logger.d.ts +10 -0
  36. package/dist/models/Logger.d.ts.map +1 -0
  37. package/dist/models/Logger.js +36 -0
  38. package/dist/models/Logger.js.map +1 -0
  39. package/dist/models/index.d.ts +3 -0
  40. package/dist/models/index.d.ts.map +1 -0
  41. package/dist/models/index.js +19 -0
  42. package/dist/models/index.js.map +1 -0
  43. package/dist/perplexity-ai/client.d.ts +31 -0
  44. package/dist/perplexity-ai/client.d.ts.map +1 -0
  45. package/dist/perplexity-ai/client.js +75 -0
  46. package/dist/perplexity-ai/client.js.map +1 -0
  47. package/dist/perplexity-ai/index.d.ts +3 -0
  48. package/dist/perplexity-ai/index.d.ts.map +1 -0
  49. package/dist/perplexity-ai/index.js +19 -0
  50. package/dist/perplexity-ai/index.js.map +1 -0
  51. package/dist/perplexity-ai/middleware.d.ts +2 -0
  52. package/dist/perplexity-ai/middleware.d.ts.map +1 -0
  53. package/dist/perplexity-ai/middleware.js +163 -0
  54. package/dist/perplexity-ai/middleware.js.map +1 -0
  55. package/dist/types/context.d.ts +9 -0
  56. package/dist/types/context.d.ts.map +1 -0
  57. package/dist/types/context.js +3 -0
  58. package/dist/types/context.js.map +1 -0
  59. package/dist/types/index.d.ts +12 -0
  60. package/dist/types/index.d.ts.map +1 -0
  61. package/dist/types/index.js +28 -0
  62. package/dist/types/index.js.map +1 -0
  63. package/dist/types/metering.d.ts +28 -0
  64. package/dist/types/metering.d.ts.map +1 -0
  65. package/dist/types/metering.js +3 -0
  66. package/dist/types/metering.js.map +1 -0
  67. package/dist/types/modelInfo.d.ts +6 -0
  68. package/dist/types/modelInfo.d.ts.map +1 -0
  69. package/dist/types/modelInfo.js +3 -0
  70. package/dist/types/modelInfo.js.map +1 -0
  71. package/dist/types/operation.d.ts +5 -0
  72. package/dist/types/operation.d.ts.map +1 -0
  73. package/dist/types/operation.js +9 -0
  74. package/dist/types/operation.js.map +1 -0
  75. package/dist/types/perplexityConfig.d.ts +5 -0
  76. package/dist/types/perplexityConfig.d.ts.map +1 -0
  77. package/dist/types/perplexityConfig.js +3 -0
  78. package/dist/types/perplexityConfig.js.map +1 -0
  79. package/dist/types/provider.d.ts +4 -0
  80. package/dist/types/provider.d.ts.map +1 -0
  81. package/dist/types/provider.js +8 -0
  82. package/dist/types/provider.js.map +1 -0
  83. package/dist/types/reveniumConfig.d.ts +6 -0
  84. package/dist/types/reveniumConfig.d.ts.map +1 -0
  85. package/dist/types/reveniumConfig.js +3 -0
  86. package/dist/types/reveniumConfig.js.map +1 -0
  87. package/dist/types/streamTracker.d.ts +9 -0
  88. package/dist/types/streamTracker.d.ts.map +1 -0
  89. package/dist/types/streamTracker.js +3 -0
  90. package/dist/types/streamTracker.js.map +1 -0
  91. package/dist/types/subscriber.d.ts +9 -0
  92. package/dist/types/subscriber.d.ts.map +1 -0
  93. package/dist/types/subscriber.js +3 -0
  94. package/dist/types/subscriber.js.map +1 -0
  95. package/dist/types/tokenCounts.d.ts +6 -0
  96. package/dist/types/tokenCounts.d.ts.map +1 -0
  97. package/dist/types/tokenCounts.js +3 -0
  98. package/dist/types/tokenCounts.js.map +1 -0
  99. package/dist/types/usageData.d.ts +16 -0
  100. package/dist/types/usageData.d.ts.map +1 -0
  101. package/dist/types/usageData.js +3 -0
  102. package/dist/types/usageData.js.map +1 -0
  103. package/dist/types/usageMetadata.d.ts +14 -0
  104. package/dist/types/usageMetadata.d.ts.map +1 -0
  105. package/dist/types/usageMetadata.js +3 -0
  106. package/dist/types/usageMetadata.js.map +1 -0
  107. package/dist/utils/activeMiddleware.d.ts +2 -0
  108. package/dist/utils/activeMiddleware.d.ts.map +1 -0
  109. package/dist/utils/activeMiddleware.js +24 -0
  110. package/dist/utils/activeMiddleware.js.map +1 -0
  111. package/dist/utils/askConsole.d.ts +2 -0
  112. package/dist/utils/askConsole.d.ts.map +1 -0
  113. package/dist/utils/askConsole.js +20 -0
  114. package/dist/utils/askConsole.js.map +1 -0
  115. package/dist/utils/calculateDurationMs.d.ts +2 -0
  116. package/dist/utils/calculateDurationMs.d.ts.map +1 -0
  117. package/dist/utils/calculateDurationMs.js +7 -0
  118. package/dist/utils/calculateDurationMs.js.map +1 -0
  119. package/dist/utils/constants/constants.d.ts +9 -0
  120. package/dist/utils/constants/constants.d.ts.map +1 -0
  121. package/dist/utils/constants/constants.js +19 -0
  122. package/dist/utils/constants/constants.js.map +1 -0
  123. package/dist/utils/constants/messages.d.ts +19 -0
  124. package/dist/utils/constants/messages.d.ts.map +1 -0
  125. package/dist/utils/constants/messages.js +22 -0
  126. package/dist/utils/constants/messages.js.map +1 -0
  127. package/dist/utils/createMeteringRequest.d.ts +3 -0
  128. package/dist/utils/createMeteringRequest.d.ts.map +1 -0
  129. package/dist/utils/createMeteringRequest.js +10 -0
  130. package/dist/utils/createMeteringRequest.js.map +1 -0
  131. package/dist/utils/createPerplexityMetadata.d.ts +3 -0
  132. package/dist/utils/createPerplexityMetadata.d.ts.map +1 -0
  133. package/dist/utils/createPerplexityMetadata.js +12 -0
  134. package/dist/utils/createPerplexityMetadata.js.map +1 -0
  135. package/dist/utils/extractModelName.d.ts +2 -0
  136. package/dist/utils/extractModelName.d.ts.map +1 -0
  137. package/dist/utils/extractModelName.js +15 -0
  138. package/dist/utils/extractModelName.js.map +1 -0
  139. package/dist/utils/extractPerplexityTokenCounts.d.ts +3 -0
  140. package/dist/utils/extractPerplexityTokenCounts.d.ts.map +1 -0
  141. package/dist/utils/extractPerplexityTokenCounts.js +17 -0
  142. package/dist/utils/extractPerplexityTokenCounts.js.map +1 -0
  143. package/dist/utils/extractStopReason.d.ts +2 -0
  144. package/dist/utils/extractStopReason.d.ts.map +1 -0
  145. package/dist/utils/extractStopReason.js +14 -0
  146. package/dist/utils/extractStopReason.js.map +1 -0
  147. package/dist/utils/extractUsageMetadata.d.ts +3 -0
  148. package/dist/utils/extractUsageMetadata.d.ts.map +1 -0
  149. package/dist/utils/extractUsageMetadata.js +15 -0
  150. package/dist/utils/extractUsageMetadata.js.map +1 -0
  151. package/dist/utils/formatTimestamp.d.ts +2 -0
  152. package/dist/utils/formatTimestamp.d.ts.map +1 -0
  153. package/dist/utils/formatTimestamp.js +7 -0
  154. package/dist/utils/formatTimestamp.js.map +1 -0
  155. package/dist/utils/generateTransactionId.d.ts +2 -0
  156. package/dist/utils/generateTransactionId.d.ts.map +1 -0
  157. package/dist/utils/generateTransactionId.js +8 -0
  158. package/dist/utils/generateTransactionId.js.map +1 -0
  159. package/dist/utils/getEnv.d.ts +4 -0
  160. package/dist/utils/getEnv.d.ts.map +1 -0
  161. package/dist/utils/getEnv.js +16 -0
  162. package/dist/utils/getEnv.js.map +1 -0
  163. package/dist/utils/index.d.ts +13 -0
  164. package/dist/utils/index.d.ts.map +1 -0
  165. package/dist/utils/index.js +29 -0
  166. package/dist/utils/index.js.map +1 -0
  167. package/dist/utils/safeExtract.d.ts +2 -0
  168. package/dist/utils/safeExtract.d.ts.map +1 -0
  169. package/dist/utils/safeExtract.js +22 -0
  170. package/dist/utils/safeExtract.js.map +1 -0
  171. package/dist/utils/sendMeteringData.d.ts +3 -0
  172. package/dist/utils/sendMeteringData.d.ts.map +1 -0
  173. package/dist/utils/sendMeteringData.js +35 -0
  174. package/dist/utils/sendMeteringData.js.map +1 -0
  175. package/dist/utils/verifyLogVerbose.d.ts +2 -0
  176. package/dist/utils/verifyLogVerbose.d.ts.map +1 -0
  177. package/dist/utils/verifyLogVerbose.js +10 -0
  178. package/dist/utils/verifyLogVerbose.js.map +1 -0
  179. package/examples/README.md +316 -0
  180. package/examples/basic-client-example.ts +36 -0
  181. package/examples/metadata-example.ts +92 -0
  182. package/examples/multiple-models-example.ts +65 -0
  183. package/examples/openai-client-example.ts +76 -0
  184. package/examples/perplexity_basic_example.ts +24 -0
  185. package/examples/perplexity_middleware_example.ts +222 -0
  186. package/examples/run-all-examples.ts +118 -0
  187. package/examples/simple-test.ts +278 -0
  188. package/examples/streaming-example.ts +46 -0
  189. package/package.json +54 -0
  190. package/src/index.ts +38 -0
  191. package/src/models/Exception/ApiResponseError.ts +6 -0
  192. package/src/models/Exception/ConfigurationError.ts +6 -0
  193. package/src/models/Exception/MeteringError.ts +6 -0
  194. package/src/models/Exception/MiddlewareActivationError.ts +6 -0
  195. package/src/models/Exception/StreamTrackingError.ts +6 -0
  196. package/src/models/Exception/TokenCountingError.ts +6 -0
  197. package/src/models/Exception/index.ts +6 -0
  198. package/src/models/Logger.ts +38 -0
  199. package/src/models/index.ts +2 -0
  200. package/src/perplexity-ai/client.ts +97 -0
  201. package/src/perplexity-ai/index.ts +2 -0
  202. package/src/perplexity-ai/middleware.ts +259 -0
  203. package/src/types/context.ts +9 -0
  204. package/src/types/index.ts +11 -0
  205. package/src/types/metering.ts +28 -0
  206. package/src/types/modelInfo.ts +5 -0
  207. package/src/types/operation.ts +4 -0
  208. package/src/types/perplexityConfig.ts +4 -0
  209. package/src/types/provider.ts +3 -0
  210. package/src/types/reveniumConfig.ts +5 -0
  211. package/src/types/streamTracker.ts +9 -0
  212. package/src/types/subscriber.ts +8 -0
  213. package/src/types/tokenCounts.ts +5 -0
  214. package/src/types/usageData.ts +16 -0
  215. package/src/types/usageMetadata.ts +13 -0
  216. package/src/utils/activeMiddleware.ts +34 -0
  217. package/src/utils/askConsole.ts +15 -0
  218. package/src/utils/calculateDurationMs.ts +3 -0
  219. package/src/utils/constants/constants.ts +17 -0
  220. package/src/utils/constants/messages.ts +35 -0
  221. package/src/utils/createMeteringRequest.ts +16 -0
  222. package/src/utils/createPerplexityMetadata.ts +11 -0
  223. package/src/utils/extractModelName.ts +14 -0
  224. package/src/utils/extractPerplexityTokenCounts.ts +16 -0
  225. package/src/utils/extractStopReason.ts +13 -0
  226. package/src/utils/extractUsageMetadata.ts +15 -0
  227. package/src/utils/formatTimestamp.ts +3 -0
  228. package/src/utils/generateTransactionId.ts +5 -0
  229. package/src/utils/getEnv.ts +16 -0
  230. package/src/utils/index.ts +12 -0
  231. package/src/utils/safeExtract.ts +18 -0
  232. package/src/utils/sendMeteringData.ts +46 -0
  233. package/src/utils/verifyLogVerbose.ts +7 -0
  234. package/tsconfig.json +23 -0
@@ -0,0 +1,278 @@
1
+ import { config } from "dotenv";
2
+ import "../src/index"; // Import middleware to activate automatic tracking
3
+
4
+ config();
5
+
6
+ async function perplexityBasicExample(): Promise<boolean> {
7
+ console.log("\n🤖 Perplexity AI - Basic Example");
8
+ console.log("=".repeat(50));
9
+
10
+ const perplexityApiKey = process.env.PERPLEXITY_API_KEY;
11
+ const reveniumKey = process.env.REVENIUM_METERING_API_KEY;
12
+
13
+ if (!perplexityApiKey) {
14
+ console.log("❌ PERPLEXITY_API_KEY not found");
15
+ console.log(" Set: export PERPLEXITY_API_KEY=your-perplexity-api-key");
16
+ return false;
17
+ }
18
+
19
+ if (!reveniumKey) {
20
+ console.log("⚠️ REVENIUM_METERING_API_KEY not found - metering will fail");
21
+ console.log(" Set: export REVENIUM_METERING_API_KEY=your-revenium-key");
22
+ }
23
+
24
+ console.log(`✅ Perplexity API Key: ${perplexityApiKey.substring(0, 10)}...`);
25
+ if (reveniumKey) {
26
+ console.log(`✅ Revenium Key: ${reveniumKey.substring(0, 10)}...`);
27
+ }
28
+
29
+ try {
30
+ const response = await fetch("https://api.perplexity.ai/chat/completions", {
31
+ method: "POST",
32
+ headers: {
33
+ Authorization: `Bearer ${perplexityApiKey}`,
34
+ "Content-Type": "application/json",
35
+ },
36
+ body: JSON.stringify({
37
+ model: "perplexity-online",
38
+ messages: [
39
+ {
40
+ role: "user",
41
+ content:
42
+ "What is the meaning of life, the universe and everything?",
43
+ },
44
+ ],
45
+ }),
46
+ });
47
+
48
+ if (!response.ok) {
49
+ throw new Error(`HTTP error! status: ${response.status}`);
50
+ }
51
+
52
+ const result = await response.json();
53
+ console.log(
54
+ `✅ Response: ${result.choices[0].message.content.substring(0, 100)}...`
55
+ );
56
+ console.log("✅ Response received successfully");
57
+ console.log("📊 Token usage will be tracked by the middleware");
58
+ console.log("🎉 Zero-config integration successful!");
59
+ console.log(" Your usage is automatically tracked in Revenium");
60
+ return true;
61
+ } catch (error) {
62
+ console.log(`❌ Perplexity test failed: ${error}`);
63
+ console.error(error);
64
+ return false;
65
+ }
66
+ }
67
+
68
+ async function perplexityEnhancedExample(): Promise<boolean> {
69
+ console.log("\n📊 Perplexity AI - Enhanced Tracking Example");
70
+ console.log("=".repeat(50));
71
+
72
+ const perplexityApiKey = process.env.PERPLEXITY_API_KEY;
73
+ if (!perplexityApiKey) {
74
+ console.log("❌ PERPLEXITY_API_KEY not found");
75
+ return false;
76
+ }
77
+
78
+ try {
79
+ const response = await fetch("https://api.perplexity.ai/chat/completions", {
80
+ method: "POST",
81
+ headers: {
82
+ Authorization: `Bearer ${perplexityApiKey}`,
83
+ "Content-Type": "application/json",
84
+ },
85
+ body: JSON.stringify({
86
+ model: "perplexity-online",
87
+ messages: [
88
+ {
89
+ role: "user",
90
+ content: "Analyze this quarterly report for key insights",
91
+ },
92
+ ],
93
+ usageMetadata: {
94
+ traceId: "conv-28a7e9d4",
95
+ taskType: "document-analysis",
96
+ subscriberEmail: "user@example.com",
97
+ subscriberId: "user-12345",
98
+ organizationId: "acme-corp",
99
+ subscriptionId: "premium-plan",
100
+ productId: "business-intelligence",
101
+ agent: "report-analyzer-v2",
102
+ },
103
+ }),
104
+ });
105
+
106
+ if (!response.ok) {
107
+ throw new Error(`HTTP error! status: ${response.status}`);
108
+ }
109
+
110
+ const result = await response.json();
111
+ console.log(
112
+ `✅ Enhanced response: ${result.choices[0].message.content.substring(
113
+ 0,
114
+ 100
115
+ )}...`
116
+ );
117
+ console.log("🎯 Enhanced tracking with metadata successful!");
118
+ return true;
119
+ } catch (error) {
120
+ console.log(`❌ Perplexity enhanced test failed: ${error}`);
121
+ console.error(error);
122
+ return false;
123
+ }
124
+ }
125
+
126
+ async function perplexityStreamingExample(): Promise<boolean> {
127
+ console.log("\n🌊 Perplexity AI - Streaming Example");
128
+ console.log("=".repeat(50));
129
+
130
+ const perplexityApiKey = process.env.PERPLEXITY_API_KEY;
131
+ if (!perplexityApiKey) {
132
+ console.log("❌ PERPLEXITY_API_KEY not found");
133
+ return false;
134
+ }
135
+
136
+ try {
137
+ const response = await fetch("https://api.perplexity.ai/chat/completions", {
138
+ method: "POST",
139
+ headers: {
140
+ Authorization: `Bearer ${perplexityApiKey}`,
141
+ "Content-Type": "application/json",
142
+ },
143
+ body: JSON.stringify({
144
+ model: "perplexity-online",
145
+ messages: [
146
+ {
147
+ role: "user",
148
+ content: "Write a creative story about AI",
149
+ },
150
+ ],
151
+ stream: true,
152
+ usageMetadata: {
153
+ organizationId: "creative-studio",
154
+ taskType: "creative-writing",
155
+ },
156
+ }),
157
+ });
158
+
159
+ if (!response.ok) {
160
+ throw new Error(`HTTP error! status: ${response.status}`);
161
+ }
162
+
163
+ if (!response.body) {
164
+ throw new Error("No response body for streaming");
165
+ }
166
+
167
+ const reader = response.body.getReader();
168
+ const decoder = new TextDecoder();
169
+ let streamedContent = "";
170
+
171
+ while (true) {
172
+ const { done, value } = await reader.read();
173
+ if (done) break;
174
+
175
+ const chunk = decoder.decode(value);
176
+ const lines = chunk.split("\n");
177
+
178
+ for (const line of lines) {
179
+ if (line.startsWith("data: ")) {
180
+ const data = line.slice(6);
181
+ if (data === "[DONE]") break;
182
+
183
+ try {
184
+ const parsed = JSON.parse(data);
185
+ if (parsed.choices[0]?.delta?.content) {
186
+ const content = parsed.choices[0].delta.content;
187
+ streamedContent += content;
188
+ process.stdout.write(content);
189
+ }
190
+ } catch (e) {
191
+ // Ignore parsing errors for incomplete chunks
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+ console.log("\n✅ Streaming completed successfully");
198
+ console.log("📊 Streaming usage will be tracked by the middleware");
199
+ return true;
200
+ } catch (error) {
201
+ console.log(`❌ Perplexity streaming test failed: ${error}`);
202
+ console.error(error);
203
+ return false;
204
+ }
205
+ }
206
+
207
+ async function perplexityDifferentModelExample(): Promise<boolean> {
208
+ console.log("\n🔧 Perplexity AI - Different Model Example");
209
+ console.log("=".repeat(50));
210
+
211
+ const perplexityApiKey = process.env.PERPLEXITY_API_KEY;
212
+ if (!perplexityApiKey) {
213
+ console.log("❌ PERPLEXITY_API_KEY not found");
214
+ return false;
215
+ }
216
+
217
+ try {
218
+ const response = await fetch("https://api.perplexity.ai/chat/completions", {
219
+ method: "POST",
220
+ headers: {
221
+ Authorization: `Bearer ${perplexityApiKey}`,
222
+ "Content-Type": "application/json",
223
+ },
224
+ body: JSON.stringify({
225
+ model: "llama-3.1-8b-online",
226
+ messages: [
227
+ {
228
+ role: "user",
229
+ content: "Explain quantum computing in simple terms",
230
+ },
231
+ ],
232
+ }),
233
+ });
234
+
235
+ if (!response.ok) {
236
+ throw new Error(`HTTP error! status: ${response.status}`);
237
+ }
238
+
239
+ const result = await response.json();
240
+ console.log(
241
+ `✅ Llama response: ${result.choices[0].message.content.substring(
242
+ 0,
243
+ 100
244
+ )}...`
245
+ );
246
+ console.log("✅ Different model test successful!");
247
+ return true;
248
+ } catch (error) {
249
+ console.log(`❌ Perplexity different model test failed: ${error}`);
250
+ console.error(error);
251
+ return false;
252
+ }
253
+ }
254
+
255
+ async function main(): Promise<void> {
256
+ console.log("🚀 Starting Revenium Perplexity AI Middleware Tests");
257
+ console.log("=".repeat(60));
258
+
259
+ let successCount = 0;
260
+ const totalTests: number = 4;
261
+
262
+ // Run Perplexity AI tests
263
+ if (await perplexityBasicExample()) successCount++;
264
+ if (await perplexityEnhancedExample()) successCount++;
265
+ if (await perplexityStreamingExample()) successCount++;
266
+ if (await perplexityDifferentModelExample()) successCount++;
267
+
268
+ console.log("\n" + "=".repeat(60));
269
+ console.log(`📊 Test Results: ${successCount}/${totalTests} tests passed`);
270
+
271
+ if (successCount === totalTests) {
272
+ console.log("🎉 All tests passed! Middleware is working correctly.");
273
+ } else {
274
+ console.log("⚠️ Some tests failed. Check the logs above for details.");
275
+ }
276
+ }
277
+
278
+ main().catch(console.error);
@@ -0,0 +1,46 @@
1
+ import { config } from "dotenv";
2
+ import { createPerplexityClient } from "../src/perplexity-ai";
3
+
4
+ config();
5
+
6
+ async function streamingExample() {
7
+ console.log("\n🌊 Perplexity AI - Streaming Example");
8
+ console.log("=".repeat(50));
9
+
10
+ try {
11
+ // Create client instance
12
+ const client = createPerplexityClient();
13
+
14
+ // Create streaming chat completion
15
+ const stream = await client.createStreamingChatCompletion({
16
+ model: "sonar-pro",
17
+ messages: [
18
+ {
19
+ role: "user",
20
+ content: "Write a creative story about AI and the future of technology",
21
+ },
22
+ ],
23
+ });
24
+
25
+ console.log("📝 Streaming response:");
26
+ console.log("-".repeat(30));
27
+
28
+ let fullContent = "";
29
+ for await (const chunk of stream) {
30
+ const content = chunk.choices[0]?.delta?.content;
31
+ if (content) {
32
+ fullContent += content;
33
+ process.stdout.write(content);
34
+ }
35
+ }
36
+
37
+ console.log("\n\n✅ Streaming completed successfully");
38
+ console.log("📊 Streaming usage automatically tracked by middleware");
39
+ console.log("🎉 Streaming example successful!");
40
+
41
+ } catch (error) {
42
+ console.error("❌ Error:", error);
43
+ }
44
+ }
45
+
46
+ streamingExample().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@revenium/perplexity",
3
+ "version": "1.0.0",
4
+ "description": "NodeJS middleware for perplexity's AI API",
5
+ "homepage": "https://github.com/revenium/revenium-middleware-perplexity-node#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/revenium/revenium-middleware-perplexity-node/issues"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/revenium/revenium-middleware-perplexity-node.git"
12
+ },
13
+ "license": "ISC",
14
+ "author": "",
15
+ "type": "commonjs",
16
+ "main": "dist/index.js",
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "dev": "tsc --watch",
20
+ "clean": "rimraf dist",
21
+ "prebuild": "npm run clean",
22
+ "simple-test": "npx ts-node examples/simple-test.ts",
23
+ "perplexity-basic-example": "npx ts-node examples/perplexity_basic_example.ts",
24
+ "perplexity-middleware-example": "npx ts-node examples/perplexity_middleware_example.ts",
25
+ "basic-client-example": "npx ts-node examples/basic-client-example.ts",
26
+ "streaming-example": "npx ts-node examples/streaming-example.ts",
27
+ "multiple-models-example": "npx ts-node examples/multiple-models-example.ts",
28
+ "openai-client-example": "npx ts-node examples/openai-client-example.ts",
29
+ "metadata-example": "npx ts-node examples/metadata-example.ts",
30
+ "run-all-examples": "npx ts-node examples/run-all-examples.ts"
31
+ },
32
+ "keywords": [
33
+ "revenium",
34
+ "middleware",
35
+ "perplexity",
36
+ "ai",
37
+ "chat",
38
+ "completion",
39
+ "metering",
40
+ "monitoring",
41
+ "typescript"
42
+ ],
43
+ "dependencies": {
44
+ "axios": "^1.11.0",
45
+ "dotenv": "^17.2.1",
46
+ "openai": "^5.15.0",
47
+ "uuid": "^11.1.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^24.3.0",
51
+ "rimraf": "^6.0.1",
52
+ "typescript": "^5.9.2"
53
+ }
54
+ }
package/src/index.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { config } from "dotenv";
2
+ import { Logger } from "./models";
3
+ import { activeMiddleware } from "./utils/activeMiddleware";
4
+ import { verifyLogVerbose } from "./utils/verifyLogVerbose";
5
+
6
+ // Import the Perplexity middleware to activate it
7
+ import "./perplexity-ai/middleware";
8
+
9
+ config();
10
+
11
+ const verboseStartup:boolean =
12
+ process.env.REVENIUM_VERBOSE_STARTUP?.toLowerCase() === "true";
13
+
14
+ verifyLogVerbose(
15
+ verboseStartup,
16
+ "Revenium Perplexity middleware initialization starting"
17
+ );
18
+
19
+ // Activate middleware for Perplexity AI
20
+ let activeSDKs: string[] = [];
21
+ activeMiddleware(verboseStartup, activeSDKs, "perplexity-ai");
22
+
23
+ // Export all utilities, types, and models
24
+ export * from "./utils";
25
+ export * from "./types";
26
+ export * from "./models";
27
+
28
+ // Export Perplexity client and middleware
29
+ export * from "./perplexity-ai";
30
+
31
+ // Log the active SDKs
32
+ Logger.info(
33
+ "Revenium Perplexity middleware activated for: %s",
34
+ activeSDKs.length > 0 ? activeSDKs.join(", ") : "none"
35
+ );
36
+
37
+ export const version:string = "0.1.0";
38
+ export const activeSDKList:string[] = activeSDKs;
@@ -0,0 +1,6 @@
1
+ export class ApiResponseError extends Error {
2
+ constructor(message: string, public statusCode?: number, public response?: any) {
3
+ super(message);
4
+ this.name = 'ApiResponseError';
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ export class ConfigurationError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = 'ConfigurationError';
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ export class MeteringError extends Error {
2
+ constructor(message: string, public originalError?: Error) {
3
+ super(message);
4
+ this.name = 'MeteringError';
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ export class MiddlewareActivationError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = 'MiddlewareActivationError';
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ export class StreamTrackingError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = 'StreamTrackingError';
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ export class TokenCountingError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = 'TokenCountingError';
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./ApiResponseError";
2
+ export * from "./ConfigurationError";
3
+ export * from "./MeteringError";
4
+ export * from "./MiddlewareActivationError";
5
+ export * from "./StreamTrackingError";
6
+ export * from "./TokenCountingError";
@@ -0,0 +1,38 @@
1
+ import { LOG_LEVELS } from "../utils/constants/constants";
2
+
3
+ export class Logger {
4
+ private static logLevel: string = process.env.REVENIUM_LOG_LEVEL || "INFO";
5
+
6
+ static debug(message: string, data?: any): void {
7
+ if (this.shouldLog(LOG_LEVELS[0])) {
8
+ console.log(`${LOG_LEVELS[0]} ${message}`, data || "");
9
+ }
10
+ }
11
+
12
+ static info(message: string, data?: any): void {
13
+ if (this.shouldLog(LOG_LEVELS[1])) {
14
+ console.log(`${LOG_LEVELS[1]} ${message}`, data || "");
15
+ }
16
+ }
17
+
18
+ static warning(message: string, data?: any): void {
19
+ if (this.shouldLog(LOG_LEVELS[2])) {
20
+ console.warn(`${LOG_LEVELS[2]} ${message}`, data || "");
21
+ }
22
+ }
23
+
24
+ static error(message: string, data?: any): void {
25
+ if (this.shouldLog(LOG_LEVELS[3])) {
26
+ console.error(`${LOG_LEVELS[3]} ${message}`, data || "");
27
+ }
28
+ }
29
+
30
+ private static shouldLog(level: string): boolean {
31
+ const levels = LOG_LEVELS;
32
+ const currentLevel = levels.indexOf(this.logLevel.toUpperCase());
33
+ const messageLevel = levels.indexOf(level);
34
+ return messageLevel >= currentLevel;
35
+ }
36
+ }
37
+
38
+ export const logger = Logger;
@@ -0,0 +1,2 @@
1
+ export * from "./Logger";
2
+ export * from "./Exception";
@@ -0,0 +1,97 @@
1
+ import { OpenAI } from "openai";
2
+ import type { ChatCompletionMessageParam } from "openai/resources/chat/completions";
3
+ import { Logger } from "../models";
4
+ import {
5
+ PERPLEXITY_CHAT_COMPLETION_FAILED_MESSAGE,
6
+ PERPLEXITY_CLIENT_INITIALIZED_MESSAGE,
7
+ PERPLEXITY_GET_MODELS_FAILED_MESSAGE,
8
+ PERPLEXITY_REQUIRED_API_KEY_MESSAGE,
9
+ PERPLEXITY_STREAMING_CHAT_COMPLETION_FAILED_MESSAGE,
10
+ } from "../utils/constants/messages";
11
+
12
+ // Import middleware to activate automatic tracking
13
+ import "./middleware";
14
+ import { CURRENT_PERPLEXITY_BASE_URL } from "../utils/constants/constants";
15
+
16
+ //Perplexity AI Client with middleware integration
17
+ export class PerplexityClient {
18
+ private client: OpenAI;
19
+
20
+ constructor(apiKey?: string) {
21
+ const perplexityApiKey = apiKey || process.env.PERPLEXITY_API_KEY;
22
+
23
+ if (!perplexityApiKey) {
24
+ throw new Error(PERPLEXITY_REQUIRED_API_KEY_MESSAGE);
25
+ }
26
+
27
+ this.client = new OpenAI({
28
+ apiKey: perplexityApiKey,
29
+ baseURL: CURRENT_PERPLEXITY_BASE_URL,
30
+ });
31
+
32
+ Logger.info(PERPLEXITY_CLIENT_INITIALIZED_MESSAGE);
33
+ }
34
+
35
+ //Create a chat completion
36
+ async createChatCompletion(params: {
37
+ model: string;
38
+ messages: ChatCompletionMessageParam[];
39
+ stream?: false;
40
+ usageMetadata?: any;
41
+ [key: string]: any;
42
+ }) {
43
+ try {
44
+ // Remove usageMetadata from params as it's not part of OpenAI API
45
+ const { usageMetadata, ...openaiParams } = params;
46
+ const response = await this.client.chat.completions.create(openaiParams);
47
+ return response;
48
+ } catch (error) {
49
+ Logger.error(PERPLEXITY_CHAT_COMPLETION_FAILED_MESSAGE, { error });
50
+ throw error;
51
+ }
52
+ }
53
+
54
+ //Create a streaming chat completion
55
+ async createStreamingChatCompletion(params: {
56
+ model: string;
57
+ messages: ChatCompletionMessageParam[];
58
+ usageMetadata?: any;
59
+ [key: string]: any;
60
+ }) {
61
+ try {
62
+ // Remove usageMetadata from params as it's not part of OpenAI API
63
+ const { usageMetadata, ...openaiParams } = params;
64
+ const stream = await this.client.chat.completions.create({
65
+ ...openaiParams,
66
+ stream: true,
67
+ });
68
+ return stream;
69
+ } catch (error) {
70
+ Logger.error(PERPLEXITY_STREAMING_CHAT_COMPLETION_FAILED_MESSAGE, {
71
+ error,
72
+ });
73
+ throw error;
74
+ }
75
+ }
76
+
77
+ //Get available models
78
+ async getModels() {
79
+ try {
80
+ const models = await this.client.models.list();
81
+ return models;
82
+ } catch (error) {
83
+ Logger.error(PERPLEXITY_GET_MODELS_FAILED_MESSAGE, { error });
84
+ throw error;
85
+ }
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Create a Perplexity client instance
91
+ */
92
+ export function createPerplexityClient(apiKey?: string): PerplexityClient {
93
+ return new PerplexityClient(apiKey);
94
+ }
95
+
96
+ // Export the OpenAI client for advanced usage
97
+ export { OpenAI };
@@ -0,0 +1,2 @@
1
+ export * from "./middleware";
2
+ export * from "./client";