@revenium/perplexity 1.0.22 → 1.0.25

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 (87) hide show
  1. package/README.md +391 -154
  2. package/dist/interfaces/meteringResponse.d.ts +28 -27
  3. package/dist/interfaces/meteringResponse.js +2 -2
  4. package/dist/models/Metering.js +23 -20
  5. package/dist/v1/perplexityV1.service.js +166 -0
  6. package/dist/v2/perplexityV2.service.js +178 -0
  7. package/examples/v1/basic.ts +50 -0
  8. package/examples/v1/chat.ts +40 -0
  9. package/examples/v1/metadata.ts +49 -0
  10. package/examples/v1/streaming.ts +44 -0
  11. package/examples/v2/basic.ts +49 -0
  12. package/examples/v2/chat.ts +60 -0
  13. package/examples/v2/metadata.ts +71 -0
  14. package/examples/v2/streaming.ts +61 -0
  15. package/package.json +26 -11
  16. package/playground/v1/basic.js +50 -0
  17. package/playground/v1/chat.js +46 -0
  18. package/playground/v1/metadata.js +50 -0
  19. package/playground/v1/streaming.js +44 -0
  20. package/playground/v2/basic.js +49 -0
  21. package/playground/v2/chat.js +72 -0
  22. package/playground/v2/metadata.js +76 -0
  23. package/playground/v2/streaming.js +67 -0
  24. package/src/index.ts +14 -1
  25. package/src/interfaces/chatCompletionRequest.ts +7 -2
  26. package/src/interfaces/meteringResponse.ts +1 -0
  27. package/src/interfaces/perplexityResponse.ts +63 -0
  28. package/src/interfaces/perplexityStreaming.ts +56 -0
  29. package/src/models/Metering.ts +9 -2
  30. package/src/utils/constants/perplexityModels.ts +71 -0
  31. package/src/v1/perplexityV1.controller.ts +164 -0
  32. package/src/v1/perplexityV1.service.ts +230 -0
  33. package/src/v2/perplexityV2.controller.ts +219 -0
  34. package/src/v2/perplexityV2.service.ts +260 -0
  35. package/dist/index.js +0 -19
  36. package/dist/interfaces/chatCompletionRequest.d.ts +0 -9
  37. package/dist/interfaces/chatCompletionRequest.js +0 -2
  38. package/dist/interfaces/credential.d.ts +0 -4
  39. package/dist/interfaces/credential.js +0 -2
  40. package/dist/interfaces/meteringRequest.d.ts +0 -13
  41. package/dist/interfaces/meteringRequest.js +0 -2
  42. package/dist/interfaces/operation.d.ts +0 -4
  43. package/dist/interfaces/operation.js +0 -8
  44. package/dist/interfaces/subscriber.d.ts +0 -8
  45. package/dist/interfaces/subscriber.js +0 -2
  46. package/dist/interfaces/tokenCounts.d.ts +0 -7
  47. package/dist/interfaces/tokenCounts.js +0 -2
  48. package/dist/interfaces/usageMetadata.d.ts +0 -27
  49. package/dist/interfaces/usageMetadata.js +0 -2
  50. package/dist/middleware.d.ts +0 -22
  51. package/dist/middleware.js +0 -129
  52. package/dist/models/Logger.js +0 -35
  53. package/dist/models/Metering.d.ts +0 -9
  54. package/dist/utils/calculateDurationMs.d.ts +0 -1
  55. package/dist/utils/calculateDurationMs.js +0 -6
  56. package/dist/utils/constants/constants.d.ts +0 -6
  57. package/dist/utils/constants/constants.js +0 -11
  58. package/dist/utils/constants/logLevels.d.ts +0 -1
  59. package/dist/utils/constants/logLevels.js +0 -4
  60. package/dist/utils/constants/messages.d.ts +0 -5
  61. package/dist/utils/constants/messages.js +0 -8
  62. package/dist/utils/constants/models.d.ts +0 -1
  63. package/dist/utils/constants/models.js +0 -21
  64. package/dist/utils/extractTokenCount.d.ts +0 -2
  65. package/dist/utils/extractTokenCount.js +0 -28
  66. package/dist/utils/formatTimeStamp.d.ts +0 -1
  67. package/dist/utils/formatTimeStamp.js +0 -6
  68. package/dist/utils/generateTransactionId.d.ts +0 -1
  69. package/dist/utils/generateTransactionId.js +0 -7
  70. package/dist/utils/index.d.ts +0 -6
  71. package/dist/utils/index.js +0 -23
  72. package/dist/utils/loadEnv.d.ts +0 -1
  73. package/dist/utils/loadEnv.js +0 -7
  74. package/dist/utils/safeExtract.d.ts +0 -29
  75. package/dist/utils/safeExtract.js +0 -67
  76. package/examples/basic.ts +0 -17
  77. package/examples/chat-completions.ts +0 -22
  78. package/examples/enhanced.ts +0 -20
  79. package/examples/metadata.ts +0 -43
  80. package/examples/streaming.ts +0 -24
  81. package/playground/basic.js +0 -17
  82. package/playground/chat-completions.js +0 -22
  83. package/playground/enhanced.js +0 -20
  84. package/playground/metadata.js +0 -43
  85. package/playground/streaming.js +0 -24
  86. package/src/middleware.ts +0 -157
  87. /package/src/utils/{formatTimeStamp.ts → formatTimestamp.ts} +0 -0
@@ -1,27 +1,28 @@
1
- import { ISubscriber } from "./subscriber";
2
- export interface IMeteringResponse {
3
- stopReason: string;
4
- costType: string;
5
- isStreamed: boolean;
6
- taskType: string;
7
- agent: string;
8
- operationType: string;
9
- inputTokenCount: number;
10
- outputTokenCount: number;
11
- reasoningTokenCount: number;
12
- cacheCreationTokenCount: number;
13
- cacheReadTokenCount: number;
14
- totalTokenCount: number;
15
- organizationId: string;
16
- productId: string;
17
- subscriber: ISubscriber;
18
- model: string;
19
- transactionId: string;
20
- responseTime: string;
21
- requestDuration: number;
22
- provider: string;
23
- requestTime: string;
24
- completionStartTime: string;
25
- timeToFirstToken: number;
26
- middleware_source: string;
27
- }
1
+ import { ISubscriber } from "./subscriber";
2
+ export interface IMeteringResponse {
3
+ stopReason: string;
4
+ costType: string;
5
+ isStreamed: boolean;
6
+ taskType: string;
7
+ agent: string;
8
+ operationType: string;
9
+ inputTokenCount: number;
10
+ outputTokenCount: number;
11
+ reasoningTokenCount: number;
12
+ cacheCreationTokenCount: number;
13
+ cacheReadTokenCount: number;
14
+ totalTokenCount: number;
15
+ organizationId: string;
16
+ productId: string;
17
+ subscriber: ISubscriber;
18
+ model: string;
19
+ transactionId: string;
20
+ responseTime: string;
21
+ requestDuration: number;
22
+ provider: string;
23
+ requestTime: string;
24
+ completionStartTime: string;
25
+ timeToFirstToken: number;
26
+ middleware_source: string;
27
+ traceId?: string;
28
+ }
@@ -1,2 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Metering = void 0;
4
4
  const utils_1 = require("../utils");
5
5
  const calculateDurationMs_1 = require("../utils/calculateDurationMs");
6
- const formatTimeStamp_1 = require("../utils/formatTimeStamp");
6
+ const formatTimestamp_1 = require("../utils/formatTimestamp");
7
7
  const generateTransactionId_1 = require("../utils/generateTransactionId");
8
8
  const Logger_1 = require("./Logger");
9
9
  class Metering {
@@ -12,6 +12,8 @@ class Metering {
12
12
  this.apiKey = "";
13
13
  this.sendMeteringData = async (metering) => {
14
14
  try {
15
+ // Log the metering data being sent for debugging
16
+ Logger_1.logger.info("Sending metering data to Revenium:", JSON.stringify(metering, null, 2));
15
17
  const response = await fetch(`${this.endpoint}/v2/ai/completions`, {
16
18
  method: "POST",
17
19
  headers: {
@@ -36,27 +38,27 @@ class Metering {
36
38
  this.endpoint = clientEndpoint;
37
39
  }
38
40
  createMetering(metering, isStreamed) {
39
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
41
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
40
42
  const usageMetadata = metering.usageMetadata;
41
43
  const agent = "perplexity";
42
44
  return {
43
45
  stopReason: (_a = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.stopReason) !== null && _a !== void 0 ? _a : metering.stopReason,
44
46
  costType: utils_1.COST_TYPE,
45
47
  isStreamed,
46
- taskType: utils_1.COST_TYPE,
47
- agent: (_b = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.agent) !== null && _b !== void 0 ? _b : agent,
48
- operationType: (_c = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.operationType) !== null && _c !== void 0 ? _c : metering.operationType.toString(),
49
- inputTokenCount: (_d = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.inputTokenCount) !== null && _d !== void 0 ? _d : metering.tokenCounts.inputTokens,
50
- outputTokenCount: (_e = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.outputTokenCount) !== null && _e !== void 0 ? _e : metering.tokenCounts.outputTokens,
51
- reasoningTokenCount: (_g = (_f = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.reasoningTokenCount) !== null && _f !== void 0 ? _f : metering.tokenCounts.reasoningTokens) !== null && _g !== void 0 ? _g : 0,
52
- cacheCreationTokenCount: (_j = (_h = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.cacheCreationTokenCount) !== null && _h !== void 0 ? _h : metering.tokenCounts.cachedTokens) !== null && _j !== void 0 ? _j : 0,
53
- cacheReadTokenCount: (_k = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.cacheReadTokenCount) !== null && _k !== void 0 ? _k : 0,
54
- totalTokenCount: (_l = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.totalTokenCount) !== null && _l !== void 0 ? _l : metering.tokenCounts.totalTokens,
55
- organizationId: (_m = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.organizationId) !== null && _m !== void 0 ? _m : `my-customer-name-${(0, generateTransactionId_1.generateTransactionId)()}`,
56
- productId: (_o = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.productId) !== null && _o !== void 0 ? _o : utils_1.PRODUCT_ID_FREE,
48
+ taskType: (_b = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.taskType) !== null && _b !== void 0 ? _b : utils_1.COST_TYPE,
49
+ agent: (_c = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.agent) !== null && _c !== void 0 ? _c : agent,
50
+ operationType: (_d = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.operationType) !== null && _d !== void 0 ? _d : metering.operationType.toString(),
51
+ inputTokenCount: (_e = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.inputTokenCount) !== null && _e !== void 0 ? _e : metering.tokenCounts.inputTokens,
52
+ outputTokenCount: (_f = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.outputTokenCount) !== null && _f !== void 0 ? _f : metering.tokenCounts.outputTokens,
53
+ reasoningTokenCount: (_h = (_g = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.reasoningTokenCount) !== null && _g !== void 0 ? _g : metering.tokenCounts.reasoningTokens) !== null && _h !== void 0 ? _h : 0,
54
+ cacheCreationTokenCount: (_k = (_j = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.cacheCreationTokenCount) !== null && _j !== void 0 ? _j : metering.tokenCounts.cachedTokens) !== null && _k !== void 0 ? _k : 0,
55
+ cacheReadTokenCount: (_l = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.cacheReadTokenCount) !== null && _l !== void 0 ? _l : 0,
56
+ totalTokenCount: (_m = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.totalTokenCount) !== null && _m !== void 0 ? _m : metering.tokenCounts.totalTokens,
57
+ organizationId: (_o = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.organizationId) !== null && _o !== void 0 ? _o : `my-customer-name-${(0, generateTransactionId_1.generateTransactionId)()}`,
58
+ productId: (_p = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.productId) !== null && _p !== void 0 ? _p : utils_1.PRODUCT_ID_FREE,
57
59
  subscriber: {
58
- id: (_p = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.subscriberId) !== null && _p !== void 0 ? _p : `user-${(0, generateTransactionId_1.generateTransactionId)()}`,
59
- email: (_q = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.subscriberEmail) !== null && _q !== void 0 ? _q : `user-@${agent.toLowerCase()}.ai`,
60
+ id: (_q = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.subscriberId) !== null && _q !== void 0 ? _q : `user-${(0, generateTransactionId_1.generateTransactionId)()}`,
61
+ email: (_r = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.subscriberEmail) !== null && _r !== void 0 ? _r : `user-@${agent.toLowerCase()}.ai`,
60
62
  credential: (usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.subscriberCredentialName) &&
61
63
  (usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.subscriberCredential)
62
64
  ? {
@@ -66,14 +68,15 @@ class Metering {
66
68
  : utils_1.CURRENT_CREDENTIAL,
67
69
  },
68
70
  model: metering.modelName,
69
- transactionId: (_r = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.transactionId) !== null && _r !== void 0 ? _r : (0, generateTransactionId_1.generateTransactionId)(),
70
- responseTime: (0, formatTimeStamp_1.formatTimestamp)(metering.endTime),
71
+ transactionId: (_s = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.transactionId) !== null && _s !== void 0 ? _s : (0, generateTransactionId_1.generateTransactionId)(),
72
+ responseTime: (0, formatTimestamp_1.formatTimestamp)(metering.endTime),
71
73
  requestDuration: (0, calculateDurationMs_1.calculateDurationMs)(metering.startTime, metering.endTime),
72
74
  provider: agent,
73
- requestTime: (_t = (_s = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.requestTime) === null || _s === void 0 ? void 0 : _s.toString()) !== null && _t !== void 0 ? _t : (0, formatTimeStamp_1.formatTimestamp)(metering.startTime),
74
- completionStartTime: (_v = (_u = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.completionStartTime) === null || _u === void 0 ? void 0 : _u.toString()) !== null && _v !== void 0 ? _v : (0, formatTimeStamp_1.formatTimestamp)(metering.endTime),
75
- timeToFirstToken: (_w = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.timeToFirstToken) !== null && _w !== void 0 ? _w : 0,
75
+ requestTime: (_u = (_t = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.requestTime) === null || _t === void 0 ? void 0 : _t.toString()) !== null && _u !== void 0 ? _u : (0, formatTimestamp_1.formatTimestamp)(metering.startTime),
76
+ completionStartTime: (_w = (_v = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.completionStartTime) === null || _v === void 0 ? void 0 : _v.toString()) !== null && _w !== void 0 ? _w : (0, formatTimestamp_1.formatTimestamp)(metering.endTime),
77
+ timeToFirstToken: (_x = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.timeToFirstToken) !== null && _x !== void 0 ? _x : 0,
76
78
  middleware_source: utils_1.MIDDLEWARE_SOURCE,
79
+ traceId: usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.traceId,
77
80
  };
78
81
  }
79
82
  }
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PerplexityV1Service = void 0;
7
+ const openai_1 = __importDefault(require("openai"));
8
+ const Logger_1 = require("../models/Logger");
9
+ const Metering_1 = require("../models/Metering");
10
+ const generateTransactionId_1 = require("../utils/generateTransactionId");
11
+ const operation_1 = require("../interfaces/operation");
12
+ const utils_1 = require("../utils");
13
+ class PerplexityV1Service {
14
+ constructor() {
15
+ this.working = true;
16
+ this.client = new openai_1.default({
17
+ apiKey: utils_1.PERPLEXITY_API_KEY,
18
+ baseURL: utils_1.PERPLEXITY_API_BASE_URL,
19
+ });
20
+ Logger_1.logger.info(utils_1.PERPLEXITY_CLIENT_INITIALIZED_MESSAGE);
21
+ }
22
+ async createChatCompletion(params, model) {
23
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
24
+ const transactionId = (0, generateTransactionId_1.generateTransactionId)();
25
+ const startTime = new Date();
26
+ try {
27
+ const { usageMetadata, ...openaiParams } = params;
28
+ const requestParams = {
29
+ ...openaiParams,
30
+ model,
31
+ };
32
+ const result = (await this.client.chat.completions.create({
33
+ ...requestParams,
34
+ stream: false,
35
+ }));
36
+ // Build V1 response format
37
+ const perplexityResponse = {
38
+ responses: [
39
+ {
40
+ text: ((_b = (_a = result.choices[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content) || "",
41
+ role: "assistant",
42
+ finishReason: (_c = result.choices[0]) === null || _c === void 0 ? void 0 : _c.finish_reason,
43
+ },
44
+ ],
45
+ usageMetadata: {
46
+ inputTokenCount: ((_d = result.usage) === null || _d === void 0 ? void 0 : _d.prompt_tokens) || 0,
47
+ outputTokenCount: ((_e = result.usage) === null || _e === void 0 ? void 0 : _e.completion_tokens) || 0,
48
+ totalTokenCount: ((_f = result.usage) === null || _f === void 0 ? void 0 : _f.total_tokens) || 0,
49
+ },
50
+ modelVersion: result.model,
51
+ transactionId,
52
+ };
53
+ // Send metering data (using current middleware logic)
54
+ if (this.working) {
55
+ const tokenCounts = {
56
+ inputTokens: ((_g = result.usage) === null || _g === void 0 ? void 0 : _g.prompt_tokens) || 0,
57
+ outputTokens: ((_h = result.usage) === null || _h === void 0 ? void 0 : _h.completion_tokens) || 0,
58
+ totalTokens: ((_j = result.usage) === null || _j === void 0 ? void 0 : _j.total_tokens) || 0,
59
+ };
60
+ const endTime = new Date();
61
+ Logger_1.logger.info("Metering is working.");
62
+ const metering = new Metering_1.Metering(utils_1.REVENIUM_METERING_API_KEY !== null && utils_1.REVENIUM_METERING_API_KEY !== void 0 ? utils_1.REVENIUM_METERING_API_KEY : "", utils_1.REVENIUM_METERING_BASE_URL !== null && utils_1.REVENIUM_METERING_BASE_URL !== void 0 ? utils_1.REVENIUM_METERING_BASE_URL : "");
63
+ // Combine user metadata with transaction ID
64
+ const combinedMetadata = {
65
+ ...usageMetadata,
66
+ transactionId,
67
+ };
68
+ const getMetering = metering.createMetering({
69
+ modelName: model,
70
+ endTime,
71
+ startTime,
72
+ operationType: operation_1.IOperationType.CHAT,
73
+ stopReason: "END",
74
+ tokenCounts,
75
+ usageMetadata: combinedMetadata,
76
+ }, false);
77
+ await metering.sendMeteringData(getMetering);
78
+ }
79
+ else {
80
+ Logger_1.logger.warning("Metering is not working. Check your configuration.");
81
+ }
82
+ return perplexityResponse;
83
+ }
84
+ catch (error) {
85
+ Logger_1.logger.error("Error in Perplexity V1 chat completion:", error);
86
+ throw error;
87
+ }
88
+ }
89
+ async createStreamingCompletion(params, model) {
90
+ const transactionId = (0, generateTransactionId_1.generateTransactionId)();
91
+ const startTime = new Date();
92
+ try {
93
+ const { usageMetadata, ...openaiParams } = params;
94
+ const requestParams = {
95
+ ...openaiParams,
96
+ model,
97
+ };
98
+ const stream = await this.client.chat.completions.create({
99
+ ...requestParams,
100
+ stream: true,
101
+ });
102
+ const wrappedStream = this.wrapStream(stream, transactionId, model, startTime, usageMetadata);
103
+ return {
104
+ stream: wrappedStream,
105
+ usageMetadata: {
106
+ inputTokenCount: 0, // Will be updated when stream completes
107
+ outputTokenCount: 0,
108
+ totalTokenCount: 0,
109
+ },
110
+ modelVersion: model,
111
+ transactionId,
112
+ };
113
+ }
114
+ catch (error) {
115
+ Logger_1.logger.error("Error in Perplexity V1 streaming:", error);
116
+ throw error;
117
+ }
118
+ }
119
+ async *wrapStream(stream, transactionId, model, startTime, usageMetadata) {
120
+ let lastChunk = null;
121
+ try {
122
+ for await (const chunk of stream) {
123
+ lastChunk = chunk;
124
+ yield chunk;
125
+ }
126
+ // Send metering data when stream completes (using current middleware logic)
127
+ if (this.working) {
128
+ // For streaming, we'll use the last chunk's usage data if available
129
+ const tokenCounts = {
130
+ inputTokens: 0, // Will be updated if lastChunk has usage data
131
+ outputTokens: 0,
132
+ totalTokens: 0,
133
+ };
134
+ const endTime = new Date();
135
+ Logger_1.logger.info("Metering is working.");
136
+ const metering = new Metering_1.Metering(utils_1.REVENIUM_METERING_API_KEY !== null && utils_1.REVENIUM_METERING_API_KEY !== void 0 ? utils_1.REVENIUM_METERING_API_KEY : "", utils_1.REVENIUM_METERING_BASE_URL !== null && utils_1.REVENIUM_METERING_BASE_URL !== void 0 ? utils_1.REVENIUM_METERING_BASE_URL : "");
137
+ // Combine user metadata with transaction ID
138
+ const combinedMetadata = {
139
+ ...usageMetadata,
140
+ transactionId,
141
+ };
142
+ const getMetering = metering.createMetering({
143
+ modelName: model,
144
+ endTime,
145
+ startTime,
146
+ operationType: operation_1.IOperationType.CHAT,
147
+ stopReason: "END",
148
+ tokenCounts,
149
+ usageMetadata: combinedMetadata,
150
+ }, true);
151
+ await metering.sendMeteringData(getMetering);
152
+ }
153
+ else {
154
+ Logger_1.logger.warning("Metering is not working. Check your configuration.");
155
+ }
156
+ }
157
+ catch (error) {
158
+ Logger_1.logger.error("Error in Perplexity V1 stream processing:", error);
159
+ throw error;
160
+ }
161
+ }
162
+ setWorking(working) {
163
+ this.working = working;
164
+ }
165
+ }
166
+ exports.PerplexityV1Service = PerplexityV1Service;
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PerplexityV2Service = void 0;
7
+ const openai_1 = __importDefault(require("openai"));
8
+ const Logger_1 = require("../models/Logger");
9
+ const Metering_1 = require("../models/Metering");
10
+ const generateTransactionId_1 = require("../utils/generateTransactionId");
11
+ const operation_1 = require("../interfaces/operation");
12
+ const utils_1 = require("../utils");
13
+ class PerplexityV2Service {
14
+ constructor() {
15
+ this.working = true;
16
+ this.client = new openai_1.default({
17
+ apiKey: utils_1.PERPLEXITY_API_KEY,
18
+ baseURL: utils_1.PERPLEXITY_API_BASE_URL,
19
+ });
20
+ Logger_1.logger.info(`${utils_1.PERPLEXITY_CLIENT_INITIALIZED_MESSAGE} (V2)`);
21
+ }
22
+ async createChatCompletion(params, model) {
23
+ var _a, _b, _c;
24
+ const transactionId = (0, generateTransactionId_1.generateTransactionId)();
25
+ const startTime = Date.now();
26
+ try {
27
+ const { usageMetadata, ...openaiParams } = params;
28
+ const requestParams = {
29
+ ...openaiParams,
30
+ model,
31
+ };
32
+ const result = (await this.client.chat.completions.create({
33
+ ...requestParams,
34
+ stream: false,
35
+ }));
36
+ const endTime = Date.now();
37
+ const processingTime = endTime - startTime;
38
+ // Build V2 enhanced response format (following OpenAI Responses API)
39
+ const perplexityV2Response = {
40
+ id: result.id,
41
+ object: "chat.completion",
42
+ created: result.created,
43
+ model: result.model,
44
+ choices: result.choices,
45
+ usage: {
46
+ prompt_tokens: ((_a = result.usage) === null || _a === void 0 ? void 0 : _a.prompt_tokens) || 0,
47
+ completion_tokens: ((_b = result.usage) === null || _b === void 0 ? void 0 : _b.completion_tokens) || 0,
48
+ total_tokens: ((_c = result.usage) === null || _c === void 0 ? void 0 : _c.total_tokens) || 0,
49
+ },
50
+ metadata: {
51
+ transactionId,
52
+ processingTime,
53
+ version: "v2",
54
+ },
55
+ };
56
+ // Send metering data (modernized approach)
57
+ await this.sendMeteringData(transactionId, model, operation_1.IOperationType.CHAT, {
58
+ inputTokenCount: perplexityV2Response.usage.prompt_tokens,
59
+ outputTokenCount: perplexityV2Response.usage.completion_tokens,
60
+ totalTokenCount: perplexityV2Response.usage.total_tokens,
61
+ }, processingTime, usageMetadata);
62
+ return perplexityV2Response;
63
+ }
64
+ catch (error) {
65
+ Logger_1.logger.error("Error in Perplexity V2 chat completion:", error);
66
+ throw error;
67
+ }
68
+ }
69
+ async createStreamingCompletion(params, model) {
70
+ const transactionId = (0, generateTransactionId_1.generateTransactionId)();
71
+ const startTime = Date.now();
72
+ try {
73
+ const { usageMetadata, ...openaiParams } = params;
74
+ const requestParams = {
75
+ ...openaiParams,
76
+ model,
77
+ };
78
+ const stream = await this.client.chat.completions.create({
79
+ ...requestParams,
80
+ stream: true,
81
+ });
82
+ const wrappedStream = this.wrapStreamV2(stream, transactionId, model, startTime, usageMetadata);
83
+ return {
84
+ id: transactionId,
85
+ object: "chat.completion.chunk",
86
+ stream: wrappedStream,
87
+ metadata: {
88
+ transactionId,
89
+ startTime,
90
+ version: "v2",
91
+ },
92
+ };
93
+ }
94
+ catch (error) {
95
+ Logger_1.logger.error("Error in Perplexity V2 streaming:", error);
96
+ throw error;
97
+ }
98
+ }
99
+ async *wrapStreamV2(stream, transactionId, model, startTime, usageMetadata) {
100
+ let lastChunk = null;
101
+ try {
102
+ for await (const chunk of stream) {
103
+ lastChunk = chunk;
104
+ // Transform to V2 format (following OpenAI Responses API)
105
+ const v2Chunk = {
106
+ id: chunk.id,
107
+ object: "chat.completion.chunk",
108
+ created: chunk.created,
109
+ model: chunk.model,
110
+ choices: chunk.choices,
111
+ usage: chunk.usage
112
+ ? {
113
+ prompt_tokens: chunk.usage.prompt_tokens || 0,
114
+ completion_tokens: chunk.usage.completion_tokens || 0,
115
+ total_tokens: chunk.usage.total_tokens || 0,
116
+ }
117
+ : undefined,
118
+ };
119
+ yield v2Chunk;
120
+ }
121
+ // Send metering data when stream completes
122
+ const endTime = Date.now();
123
+ const processingTime = endTime - startTime;
124
+ if (lastChunk === null || lastChunk === void 0 ? void 0 : lastChunk.usage) {
125
+ await this.sendMeteringData(transactionId, model, operation_1.IOperationType.CHAT, {
126
+ inputTokenCount: lastChunk.usage.prompt_tokens || 0,
127
+ outputTokenCount: lastChunk.usage.completion_tokens || 0,
128
+ totalTokenCount: lastChunk.usage.total_tokens || 0,
129
+ }, processingTime, usageMetadata);
130
+ }
131
+ }
132
+ catch (error) {
133
+ Logger_1.logger.error("Error in Perplexity V2 stream processing:", error);
134
+ throw error;
135
+ }
136
+ }
137
+ async sendMeteringData(transactionId, model, operationType, usageData, processingTime, customMetadata) {
138
+ if (!this.working) {
139
+ Logger_1.logger.warning("Metering is not working. Check your configuration.");
140
+ return;
141
+ }
142
+ try {
143
+ const startTime = new Date(Date.now() - processingTime);
144
+ const endTime = new Date();
145
+ const metering = new Metering_1.Metering(utils_1.REVENIUM_METERING_API_KEY !== null && utils_1.REVENIUM_METERING_API_KEY !== void 0 ? utils_1.REVENIUM_METERING_API_KEY : "", utils_1.REVENIUM_METERING_BASE_URL !== null && utils_1.REVENIUM_METERING_BASE_URL !== void 0 ? utils_1.REVENIUM_METERING_BASE_URL : "");
146
+ // Convert IUsageMetadata to ITokenCounts for metering
147
+ const tokenCounts = {
148
+ inputTokens: usageData.inputTokenCount || 0,
149
+ outputTokens: usageData.outputTokenCount || 0,
150
+ totalTokens: usageData.totalTokenCount || 0,
151
+ };
152
+ // Combine custom metadata with transaction ID (token counts are handled separately)
153
+ const combinedMetadata = {
154
+ ...customMetadata,
155
+ transactionId,
156
+ };
157
+ // Use the same approach as V1 but with V2 enhancements
158
+ const meteringData = metering.createMetering({
159
+ modelName: model,
160
+ endTime,
161
+ startTime,
162
+ operationType,
163
+ stopReason: "END",
164
+ tokenCounts,
165
+ usageMetadata: combinedMetadata,
166
+ }, false);
167
+ await metering.sendMeteringData(meteringData);
168
+ Logger_1.logger.info("V2 Metering data sent successfully.");
169
+ }
170
+ catch (error) {
171
+ Logger_1.logger.error("Error sending V2 metering data:", error);
172
+ }
173
+ }
174
+ setWorking(working) {
175
+ this.working = working;
176
+ }
177
+ }
178
+ exports.PerplexityV2Service = PerplexityV2Service;
@@ -0,0 +1,50 @@
1
+ import { PerplexityV1Controller } from "../../src/index";
2
+
3
+ const basicV1Example = async () => {
4
+ console.log("=".repeat(50));
5
+ console.log(
6
+ "šŸ”„ Perplexity V1 Basic Example (Compatible with current middleware)"
7
+ );
8
+ console.log("=".repeat(50));
9
+
10
+ try {
11
+ const controller = new PerplexityV1Controller();
12
+
13
+ // Basic chat completion
14
+ const result = await controller.createChat([
15
+ "What is artificial intelligence and how does it work?",
16
+ ]);
17
+
18
+ console.log("šŸ“ Response:");
19
+ console.log(result.responses[0].text);
20
+
21
+ console.log("\nšŸ“Š Usage Metadata:");
22
+ console.log(`Input tokens: ${result.usageMetadata.inputTokenCount}`);
23
+ console.log(`Output tokens: ${result.usageMetadata.outputTokenCount}`);
24
+ console.log(`Total tokens: ${result.usageMetadata.totalTokenCount}`);
25
+
26
+ console.log("\nšŸ”§ Model Info:");
27
+ console.log(`Model: ${result.modelVersion}`);
28
+ console.log(`Transaction ID: ${result.transactionId}`);
29
+
30
+ // Test model capabilities
31
+ console.log("\nšŸŽÆ Model Capabilities:");
32
+ const models = controller.getAvailableModels();
33
+ console.log(`Available models: ${models.slice(0, 3).join(", ")}...`);
34
+
35
+ const supportsChat = controller.supportsCapability("sonar-pro", "chat");
36
+ const supportsStreaming = controller.supportsCapability(
37
+ "sonar-pro",
38
+ "streaming"
39
+ );
40
+ const supportsOnline = controller.supportsCapability("sonar-pro", "online");
41
+
42
+ console.log(
43
+ `Sonar-pro capabilities: chat=${supportsChat}, streaming=${supportsStreaming}, online=${supportsOnline}`
44
+ );
45
+ } catch (error) {
46
+ console.error("āŒ Error:", error);
47
+ }
48
+ };
49
+
50
+ basicV1Example();
@@ -0,0 +1,40 @@
1
+ import { PerplexityV1Controller } from "../../src/index";
2
+
3
+ const chatV1Example = async () => {
4
+ console.log("=".repeat(50));
5
+ console.log("šŸ’¬ Perplexity V1 Multi-turn Chat Example");
6
+ console.log("=".repeat(50));
7
+
8
+ try {
9
+ const controller = new PerplexityV1Controller();
10
+
11
+ // Multi-turn conversation using message objects
12
+ const messages = [
13
+ { role: "user", content: "What are the benefits of renewable energy?" },
14
+ { role: "assistant", content: "Renewable energy offers several key benefits including environmental sustainability, reduced greenhouse gas emissions, and long-term cost savings." },
15
+ { role: "user", content: "Can you elaborate on the cost savings aspect?" }
16
+ ];
17
+
18
+ const result = await controller.createChat(messages, "sonar-pro");
19
+
20
+ console.log("šŸ“ Multi-turn Chat Response:");
21
+ console.log(result.responses[0].text);
22
+
23
+ console.log("\nšŸ“Š Usage Statistics:");
24
+ console.log(`Input tokens: ${result.usageMetadata.inputTokenCount}`);
25
+ console.log(`Output tokens: ${result.usageMetadata.outputTokenCount}`);
26
+ console.log(`Total tokens: ${result.usageMetadata.totalTokenCount}`);
27
+
28
+ console.log("\nšŸ”§ Model Information:");
29
+ const modelInfo = controller.getModelInfo("sonar-pro");
30
+ console.log(`Model: ${modelInfo.model}`);
31
+ console.log(`Version: ${modelInfo.version}`);
32
+ console.log(`Context Window: ${modelInfo.contextWindow} tokens`);
33
+ console.log(`Capabilities:`, modelInfo.capabilities);
34
+
35
+ } catch (error) {
36
+ console.error("āŒ Error:", error);
37
+ }
38
+ };
39
+
40
+ chatV1Example();
@@ -0,0 +1,49 @@
1
+ import { PerplexityV1Controller, IUsageMetadata } from "../../src/index";
2
+
3
+ const metadataV1Example = async () => {
4
+ console.log("=".repeat(50));
5
+ console.log("šŸ“Š Perplexity V1 Custom Metadata Example");
6
+ console.log("=".repeat(50));
7
+
8
+ try {
9
+ const controller = new PerplexityV1Controller();
10
+
11
+ // Custom metadata for tracking
12
+ const customMetadata: IUsageMetadata = {
13
+ traceId: "trace-12345",
14
+ taskType: "research-query",
15
+ subscriberEmail: "user@example.com",
16
+ subscriberId: "user-456",
17
+ organizationId: "org-789",
18
+ agent: "perplexity-v1-demo",
19
+ };
20
+
21
+ const result = await controller.createChat([
22
+ "Explain quantum computing in simple terms"
23
+ ], "sonar-pro", customMetadata);
24
+
25
+ console.log("šŸ“ Response:");
26
+ console.log(result.responses[0].text);
27
+
28
+ console.log("\nšŸ“Š Usage Metadata:");
29
+ console.log(`Input tokens: ${result.usageMetadata.inputTokenCount}`);
30
+ console.log(`Output tokens: ${result.usageMetadata.outputTokenCount}`);
31
+ console.log(`Total tokens: ${result.usageMetadata.totalTokenCount}`);
32
+
33
+ console.log("\nšŸ·ļø Custom Metadata Sent:");
34
+ console.log(`Trace ID: ${customMetadata.traceId}`);
35
+ console.log(`Task Type: ${customMetadata.taskType}`);
36
+ console.log(`Subscriber: ${customMetadata.subscriberEmail}`);
37
+ console.log(`Organization: ${customMetadata.organizationId}`);
38
+ console.log(`Agent: ${customMetadata.agent}`);
39
+
40
+ console.log("\nšŸ”§ Transaction Info:");
41
+ console.log(`Model: ${result.modelVersion}`);
42
+ console.log(`Transaction ID: ${result.transactionId}`);
43
+
44
+ } catch (error) {
45
+ console.error("āŒ Error:", error);
46
+ }
47
+ };
48
+
49
+ metadataV1Example();