@revenium/perplexity 1.0.18 → 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,7 +187,7 @@ const streamingExample = async () => {
187
187
  streamingExample();
188
188
  ```
189
189
 
190
- #### Metadata Example
190
+ #### METADATA Example
191
191
 
192
192
  Create `examples/metadata-perplexity.js`:
193
193
 
@@ -200,34 +200,38 @@ const metadataExample = async () => {
200
200
  const middleware = new PerplexityReveniumMiddleware();
201
201
  const model = middleware.getGenerativeModel("sonar-pro");
202
202
  const result = await model.createChatCompletion({
203
- messages: [
204
- {
205
- role: "user",
206
- content: "Analyze this quarterly report",
207
- },
208
- ],
203
+ model: "sonar-pro",
204
+ messages: [{ role: "user", content: "What is the capital of France?" }],
209
205
  usageMetadata: {
210
- // User tracking
211
- traceId: "conv-28a7e9d4",
212
- taskType: "document-analysis",
213
- subscriberEmail: "user@example.com",
214
- subscriberId: "user-123",
215
- subscriberCredentialName: "api-key-1",
216
-
217
- // Business context
218
- organizationId: "acme-corp",
219
- subscriptionId: "premium-plan",
220
- productId: "business-intelligence",
221
- agent: "analysis-assistant",
222
- responseQualityScore: 0.95,
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",
223
230
  },
224
231
  });
225
-
226
- console.log("*** METADATA RESPONSE ***");
227
- console.log("Response:", result.choices[0]?.message?.content);
228
- console.log("✅ Metadata tracking with metering successful!");
232
+ console.log("[BASIC REQUEST]", result.choices[0].message);
229
233
  } catch (error) {
230
- console.error("❌ Perplexity metadata example failed:", error);
234
+ console.error("❌ Perplexity streaming example failed:", error);
231
235
  process.exit(1);
232
236
  }
233
237
  };
@@ -261,6 +265,7 @@ npm run test-perplexity-stream
261
265
 
262
266
  # Test metadata
263
267
  npm run test-perplexity-metadata
268
+
264
269
  ```
265
270
 
266
271
  ---
@@ -303,6 +308,7 @@ npm run e-basic # Basic chat completion
303
308
  npm run e-streaming # Streaming response
304
309
  npm run e-enhanced # Enhanced request
305
310
  npm run e-chat-completions # Chat completions
311
+ npm run e-metadata # Metadata request
306
312
 
307
313
  # Playground examples
308
314
  # Required build first
@@ -311,6 +317,7 @@ npm run build
311
317
  npm run p-basic
312
318
  npm run p-streaming
313
319
  npm run p-enhanced
320
+ npm run p-metadata
314
321
  ```
315
322
 
316
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.18",
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
  }