@revenium/perplexity 1.0.19 → 1.0.20

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/README.md CHANGED
@@ -187,6 +187,58 @@ const streamingExample = async () => {
187
187
  streamingExample();
188
188
  ```
189
189
 
190
+ #### METADATA Example
191
+
192
+ Create `examples/metadata-perplexity.js`:
193
+
194
+ ```javascript
195
+ // examples/metadata-perplexity.js
196
+ import { PerplexityReveniumMiddleware } from "@revenium/perplexity";
197
+
198
+ const metadataExample = async () => {
199
+ try {
200
+ const middleware = new PerplexityReveniumMiddleware();
201
+ const model = middleware.getGenerativeModel("sonar-pro");
202
+ const result = await model.createChatCompletion({
203
+ model: "sonar-pro",
204
+ messages: [{ role: "user", content: "What is the capital of France?" }],
205
+ usageMetadata: {
206
+ taskType: "test",
207
+ subscriberEmail: "test@revenium.ai",
208
+ subscriberId: "123456",
209
+ subscriberCredentialName: "apiKey",
210
+ subscriberCredential: "keyValue",
211
+ organizationId: "123456",
212
+ subscriptionId: "123456",
213
+ productId: "free-trial",
214
+ agent: "perplexity",
215
+ responseQualityScore: 100,
216
+ transactionId: "123456",
217
+ timeToFirstToken: 1000,
218
+ requestTime: new Date(),
219
+ completionStartTime: new Date(),
220
+ operationType: "CHAT",
221
+ inputTokenCount: 10,
222
+ outputTokenCount: 10,
223
+ reasoningTokenCount: 20,
224
+ cacheCreationTokenCount: 0,
225
+ cacheReadTokenCount: 0,
226
+ totalTokenCount: 40,
227
+ responseTime: new Date(),
228
+ requestDuration: 1000,
229
+ stopReason: "END",
230
+ },
231
+ });
232
+ console.log("[BASIC REQUEST]", result.choices[0].message);
233
+ } catch (error) {
234
+ console.error("❌ Perplexity streaming example failed:", error);
235
+ process.exit(1);
236
+ }
237
+ };
238
+
239
+ metadataExample();
240
+ ```
241
+
190
242
  ### Step 8: Update package.json
191
243
 
192
244
  ```json
@@ -196,7 +248,8 @@ streamingExample();
196
248
  "type": "module",
197
249
  "scripts": {
198
250
  "test-perplexity": "node test-perplexity.js",
199
- "test-perplexity-stream": "node examples/streaming-perplexity.js"
251
+ "test-perplexity-stream": "node examples/streaming-perplexity.js",
252
+ "test-perplexity-metadata": "node examples/metadata-perplexity.js"
200
253
  },
201
254
  "dependencies": {
202
255
  "@revenium/perplexity": "^1.0.0"
@@ -210,6 +263,9 @@ streamingExample();
210
263
  # Test streaming
211
264
  npm run test-perplexity-stream
212
265
 
266
+ # Test metadata
267
+ npm run test-perplexity-metadata
268
+
213
269
  ```
214
270
 
215
271
  ---
@@ -252,6 +308,7 @@ npm run e-basic # Basic chat completion
252
308
  npm run e-streaming # Streaming response
253
309
  npm run e-enhanced # Enhanced request
254
310
  npm run e-chat-completions # Chat completions
311
+ npm run e-metadata # Metadata request
255
312
 
256
313
  # Playground examples
257
314
  # Required build first
@@ -260,6 +317,7 @@ npm run build
260
317
  npm run p-basic
261
318
  npm run p-streaming
262
319
  npm run p-enhanced
320
+ npm run p-metadata
263
321
  ```
264
322
 
265
323
  ---
@@ -0,0 +1,43 @@
1
+ import { PerplexityReveniumMiddleware } from "../src";
2
+
3
+ async function metadataRequest() {
4
+ console.log("=".repeat(50));
5
+ try {
6
+ const middleware = new PerplexityReveniumMiddleware();
7
+ const model = middleware.getGenerativeModel("sonar-pro");
8
+ const result = await model.createChatCompletion({
9
+ model: "sonar-pro",
10
+ messages: [{ role: "user", content: "What is the capital of France?" }],
11
+ usageMetadata: {
12
+ taskType: "test",
13
+ subscriberEmail: "test@revenium.ai",
14
+ subscriberId: "123456",
15
+ subscriberCredentialName: "apiKey",
16
+ subscriberCredential: "keyValue",
17
+ organizationId: "123456",
18
+ subscriptionId: "123456",
19
+ productId: "free-trial",
20
+ agent: "perplexity",
21
+ responseQualityScore: 100,
22
+ transactionId: "123456",
23
+ timeToFirstToken: 1000,
24
+ requestTime: new Date(),
25
+ completionStartTime: new Date(),
26
+ operationType: "CHAT",
27
+ inputTokenCount: 10,
28
+ outputTokenCount: 10,
29
+ reasoningTokenCount: 20,
30
+ cacheCreationTokenCount: 0,
31
+ cacheReadTokenCount: 0,
32
+ totalTokenCount: 40,
33
+ responseTime: new Date(),
34
+ requestDuration: 1000,
35
+ stopReason: "END",
36
+ },
37
+ });
38
+ console.log("[METADATA REQUEST]", result.choices[0].message);
39
+ } catch (error) {
40
+ console.log(error);
41
+ }
42
+ }
43
+ metadataRequest();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revenium/perplexity",
3
- "version": "1.0.19",
3
+ "version": "1.0.20",
4
4
  "description": "NodeJS middleware for perplexity's AI API",
5
5
  "homepage": "https://github.com/revenium/revenium-middleware-perplexity-node#readme",
6
6
  "bugs": {
@@ -20,7 +20,8 @@
20
20
  "e-basic": "npx ts-node examples/basic.ts",
21
21
  "e-streaming": "npx ts-node examples/streaming.ts",
22
22
  "e-chat-completions": "npx ts-node examples/chat-completions.ts",
23
- "e-enhanced": "npx ts-node examples/enhanced.ts"
23
+ "e-enhanced": "npx ts-node examples/enhanced.ts",
24
+ "e-metadata": "npx ts-node examples/metadata.ts"
24
25
  },
25
26
  "keywords": [
26
27
  "revenium",
@@ -0,0 +1,43 @@
1
+ import { PerplexityReveniumMiddleware } from "@revenium/perplexity";
2
+
3
+ async function metadataRequest() {
4
+ console.log("=".repeat(50));
5
+ try {
6
+ const middleware = new PerplexityReveniumMiddleware();
7
+ const model = middleware.getGenerativeModel("sonar-pro");
8
+ const result = await model.createChatCompletion({
9
+ model: "sonar-pro",
10
+ messages: [{ role: "user", content: "What is the capital of France?" }],
11
+ usageMetadata: {
12
+ taskType: "test",
13
+ subscriberEmail: "test@revenium.ai",
14
+ subscriberId: "123456",
15
+ subscriberCredentialName: "apiKey",
16
+ subscriberCredential: "keyValue",
17
+ organizationId: "123456",
18
+ subscriptionId: "123456",
19
+ productId: "free-trial",
20
+ agent: "perplexity",
21
+ responseQualityScore: 100,
22
+ transactionId: "123456",
23
+ timeToFirstToken: 1000,
24
+ requestTime: new Date(),
25
+ completionStartTime: new Date(),
26
+ operationType: "CHAT",
27
+ inputTokenCount: 10,
28
+ outputTokenCount: 10,
29
+ reasoningTokenCount: 20,
30
+ cacheCreationTokenCount: 0,
31
+ cacheReadTokenCount: 0,
32
+ totalTokenCount: 40,
33
+ responseTime: new Date(),
34
+ requestDuration: 1000,
35
+ stopReason: "END",
36
+ },
37
+ });
38
+ console.log("[METADATA REQUEST]", result.choices[0].message);
39
+ } catch (error) {
40
+ console.log(error);
41
+ }
42
+ }
43
+ metadataRequest();
@@ -1,9 +1,10 @@
1
1
  import { ChatCompletionMessageParam } from "openai/resources/index";
2
+ import { IUsageMetadata } from "./usageMetadata";
2
3
 
3
4
  export interface IChatCompletionRequest {
4
5
  model?: string;
5
6
  messages: ChatCompletionMessageParam[];
6
7
  stream?: boolean;
7
- usageMetadata?: any;
8
+ usageMetadata?: IUsageMetadata;
8
9
  [key: string]: any;
9
10
  }
@@ -10,4 +10,18 @@ export interface IUsageMetadata {
10
10
  productId?: string;
11
11
  agent?: string;
12
12
  responseQualityScore?: number;
13
+ transactionId?: string;
14
+ timeToFirstToken?: number;
15
+ requestTime?: Date;
16
+ completionStartTime?: Date;
17
+ operationType?: string;
18
+ inputTokenCount?: number;
19
+ outputTokenCount?: number;
20
+ reasoningTokenCount?: number;
21
+ cacheCreationTokenCount?: number;
22
+ cacheReadTokenCount?: number;
23
+ totalTokenCount?: number;
24
+ responseTime?: Date;
25
+ requestDuration?: number;
26
+ stopReason?: string;
13
27
  }
package/src/middleware.ts CHANGED
@@ -70,15 +70,18 @@ export class PerplexityReveniumMiddleware {
70
70
  REVENIUM_METERING_API_KEY ?? "",
71
71
  REVENIUM_METERING_BASE_URL ?? ""
72
72
  );
73
- const getMetering = metering.createMetering({
74
- modelName: this.modelName,
75
- endTime,
76
- startTime,
77
- operationType: IOperationType.CHAT,
78
- stopReason: "END",
79
- tokenCounts,
80
- usageMetadata,
81
- });
73
+ const getMetering = metering.createMetering(
74
+ {
75
+ modelName: this.modelName,
76
+ endTime,
77
+ startTime,
78
+ operationType: IOperationType.CHAT,
79
+ stopReason: "END",
80
+ tokenCounts,
81
+ usageMetadata,
82
+ },
83
+ true
84
+ );
82
85
  await metering.sendMeteringData(getMetering);
83
86
  return result;
84
87
  } catch (error) {
@@ -111,15 +114,18 @@ export class PerplexityReveniumMiddleware {
111
114
  REVENIUM_METERING_API_KEY ?? "",
112
115
  REVENIUM_METERING_BASE_URL ?? ""
113
116
  );
114
- const getMetering = metering.createMetering({
115
- modelName: this.modelName,
116
- endTime,
117
- startTime,
118
- operationType: IOperationType.CHAT,
119
- stopReason: "END",
120
- tokenCounts,
121
- usageMetadata,
122
- });
117
+ const getMetering = metering.createMetering(
118
+ {
119
+ modelName: this.modelName,
120
+ endTime,
121
+ startTime,
122
+ operationType: IOperationType.CHAT,
123
+ stopReason: "END",
124
+ tokenCounts,
125
+ usageMetadata,
126
+ },
127
+ false
128
+ );
123
129
  await metering.sendMeteringData(getMetering);
124
130
  return result;
125
131
  } catch (error) {
@@ -21,39 +21,67 @@ export class Metering {
21
21
  this.endpoint = clientEndpoint;
22
22
  }
23
23
 
24
- public createMetering(metering: IMeteringRequest): IMeteringResponse {
24
+ public createMetering(
25
+ metering: IMeteringRequest,
26
+ isStreamed: boolean
27
+ ): IMeteringResponse {
28
+ const usageMetadata = metering.usageMetadata;
25
29
  const agent: string = "perplexity";
26
30
  return {
27
- stopReason: metering.stopReason,
31
+ stopReason: usageMetadata?.stopReason ?? metering.stopReason,
28
32
  costType: COST_TYPE,
29
- isStreamed: false,
33
+ isStreamed,
30
34
  taskType: COST_TYPE,
31
- agent,
32
- operationType: metering.operationType.toString(),
33
- inputTokenCount: metering.tokenCounts.inputTokens,
34
- outputTokenCount: metering.tokenCounts.outputTokens,
35
- reasoningTokenCount: metering.tokenCounts.reasoningTokens || 0,
36
- cacheCreationTokenCount: metering.tokenCounts.cachedTokens || 0,
37
- cacheReadTokenCount: 0,
38
- totalTokenCount: metering.tokenCounts.totalTokens,
39
- organizationId: `my-customer-name-${generateTransactionId()}`,
40
- productId: PRODUCT_ID_FREE,
35
+ agent: usageMetadata?.agent ?? agent,
36
+ operationType:
37
+ usageMetadata?.operationType ?? metering.operationType.toString(),
38
+ inputTokenCount:
39
+ usageMetadata?.inputTokenCount ?? metering.tokenCounts.inputTokens,
40
+ outputTokenCount:
41
+ usageMetadata?.outputTokenCount ?? metering.tokenCounts.outputTokens,
42
+ reasoningTokenCount:
43
+ usageMetadata?.reasoningTokenCount ??
44
+ metering.tokenCounts.reasoningTokens ??
45
+ 0,
46
+ cacheCreationTokenCount:
47
+ usageMetadata?.cacheCreationTokenCount ??
48
+ metering.tokenCounts.cachedTokens ??
49
+ 0,
50
+ cacheReadTokenCount: usageMetadata?.cacheReadTokenCount ?? 0,
51
+ totalTokenCount:
52
+ usageMetadata?.totalTokenCount ?? metering.tokenCounts.totalTokens,
53
+ organizationId:
54
+ usageMetadata?.organizationId ??
55
+ `my-customer-name-${generateTransactionId()}`,
56
+ productId: usageMetadata?.productId ?? PRODUCT_ID_FREE,
41
57
  subscriber: {
42
- id: `user-${generateTransactionId()}`,
43
- email: `user-@${agent.toLowerCase()}.ai`,
44
- credential: CURRENT_CREDENTIAL,
58
+ id: usageMetadata?.subscriberId ?? `user-${generateTransactionId()}`,
59
+ email:
60
+ usageMetadata?.subscriberEmail ?? `user-@${agent.toLowerCase()}.ai`,
61
+ credential:
62
+ usageMetadata?.subscriberCredentialName &&
63
+ usageMetadata?.subscriberCredential
64
+ ? {
65
+ name: usageMetadata.subscriberCredentialName,
66
+ value: usageMetadata.subscriberCredential,
67
+ }
68
+ : CURRENT_CREDENTIAL,
45
69
  },
46
70
  model: metering.modelName,
47
- transactionId: generateTransactionId(),
71
+ transactionId: usageMetadata?.transactionId ?? generateTransactionId(),
48
72
  responseTime: formatTimestamp(metering.endTime),
49
73
  requestDuration: calculateDurationMs(
50
74
  metering.startTime,
51
75
  metering.endTime
52
76
  ),
53
77
  provider: agent,
54
- requestTime: formatTimestamp(metering.startTime),
55
- completionStartTime: formatTimestamp(metering.endTime),
56
- timeToFirstToken: 0,
78
+ requestTime:
79
+ usageMetadata?.requestTime?.toString() ??
80
+ formatTimestamp(metering.startTime),
81
+ completionStartTime:
82
+ usageMetadata?.completionStartTime?.toString() ??
83
+ formatTimestamp(metering.endTime),
84
+ timeToFirstToken: usageMetadata?.timeToFirstToken ?? 0,
57
85
  middleware_source: MIDDLEWARE_SOURCE,
58
86
  };
59
87
  }