@revenium/perplexity 2.0.4 → 2.0.6
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/CHANGELOG.md +113 -98
- package/LICENSE +21 -21
- package/README.md +292 -271
- package/SECURITY.md +34 -0
- package/dist/cjs/core/client/index.js +13 -0
- package/dist/cjs/core/client/index.js.map +1 -0
- package/dist/cjs/core/client/manager.js +88 -0
- package/dist/cjs/core/client/manager.js.map +1 -0
- package/dist/cjs/core/config/index.js +21 -0
- package/dist/cjs/core/config/index.js.map +1 -0
- package/dist/cjs/core/config/loader.js +48 -0
- package/dist/cjs/core/config/loader.js.map +1 -0
- package/dist/cjs/core/config/manager.js +77 -0
- package/dist/cjs/core/config/manager.js.map +1 -0
- package/dist/cjs/core/config/validator.js +47 -0
- package/dist/cjs/core/config/validator.js.map +1 -0
- package/dist/cjs/core/middleware/index.js +14 -0
- package/dist/cjs/core/middleware/index.js.map +1 -0
- package/dist/cjs/core/middleware/interfaces.js +94 -0
- package/dist/cjs/core/middleware/interfaces.js.map +1 -0
- package/dist/cjs/core/middleware/revenium-client.js +44 -0
- package/dist/cjs/core/middleware/revenium-client.js.map +1 -0
- package/dist/cjs/core/middleware/streaming-wrapper.js +80 -0
- package/dist/cjs/core/middleware/streaming-wrapper.js.map +1 -0
- package/dist/cjs/core/providers/detector.js +38 -0
- package/dist/cjs/core/providers/detector.js.map +1 -0
- package/dist/cjs/core/providers/index.js +14 -0
- package/dist/cjs/core/providers/index.js.map +1 -0
- package/dist/cjs/core/tracking/api-client.js +67 -0
- package/dist/cjs/core/tracking/api-client.js.map +1 -0
- package/dist/cjs/core/tracking/index.js +21 -0
- package/dist/cjs/core/tracking/index.js.map +1 -0
- package/dist/cjs/core/tracking/payload-builder.js +95 -0
- package/dist/cjs/core/tracking/payload-builder.js.map +1 -0
- package/dist/cjs/core/tracking/usage-tracker.js +83 -0
- package/dist/cjs/core/tracking/usage-tracker.js.map +1 -0
- package/dist/cjs/index.js +55 -59
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/function-parameters.js +14 -0
- package/dist/cjs/types/function-parameters.js.map +1 -0
- package/dist/cjs/types/index.js +20 -1
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/utils/constants.js +20 -0
- package/dist/cjs/utils/constants.js.map +1 -0
- package/dist/cjs/utils/error-handler.js +194 -0
- package/dist/cjs/utils/error-handler.js.map +1 -0
- package/dist/cjs/utils/metadata-builder.js +191 -0
- package/dist/cjs/utils/metadata-builder.js.map +1 -0
- package/dist/cjs/utils/stop-reason-mapper.js +74 -0
- package/dist/cjs/utils/stop-reason-mapper.js.map +1 -0
- package/dist/cjs/utils/transaction-id.js +19 -0
- package/dist/cjs/utils/transaction-id.js.map +1 -0
- package/dist/cjs/utils/url-builder.js +57 -0
- package/dist/cjs/utils/url-builder.js.map +1 -0
- package/dist/esm/core/client/index.js +5 -0
- package/dist/esm/core/client/index.js.map +1 -0
- package/dist/esm/core/client/manager.js +81 -0
- package/dist/esm/core/client/manager.js.map +1 -0
- package/dist/esm/core/config/index.js +11 -0
- package/dist/esm/core/config/index.js.map +1 -0
- package/dist/esm/core/config/loader.js +45 -0
- package/dist/esm/core/config/loader.js.map +1 -0
- package/dist/esm/core/config/manager.js +70 -0
- package/dist/esm/core/config/manager.js.map +1 -0
- package/dist/esm/core/config/validator.js +44 -0
- package/dist/esm/core/config/validator.js.map +1 -0
- package/dist/esm/core/middleware/index.js +7 -0
- package/dist/esm/core/middleware/index.js.map +1 -0
- package/dist/esm/core/middleware/interfaces.js +89 -0
- package/dist/esm/core/middleware/interfaces.js.map +1 -0
- package/dist/esm/core/middleware/revenium-client.js +37 -0
- package/dist/esm/core/middleware/revenium-client.js.map +1 -0
- package/dist/esm/core/middleware/streaming-wrapper.js +76 -0
- package/dist/esm/core/middleware/streaming-wrapper.js.map +1 -0
- package/dist/esm/core/providers/detector.js +34 -0
- package/dist/esm/core/providers/detector.js.map +1 -0
- package/dist/esm/core/providers/index.js +9 -0
- package/dist/esm/core/providers/index.js.map +1 -0
- package/dist/esm/core/tracking/api-client.js +64 -0
- package/dist/esm/core/tracking/api-client.js.map +1 -0
- package/dist/esm/core/tracking/index.js +13 -0
- package/dist/esm/core/tracking/index.js.map +1 -0
- package/dist/esm/core/tracking/payload-builder.js +92 -0
- package/dist/esm/core/tracking/payload-builder.js.map +1 -0
- package/dist/esm/core/tracking/usage-tracker.js +79 -0
- package/dist/esm/core/tracking/usage-tracker.js.map +1 -0
- package/dist/esm/index.js +42 -39
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/function-parameters.js +13 -0
- package/dist/esm/types/function-parameters.js.map +1 -0
- package/dist/esm/types/index.js +6 -2
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/utils/constants.js +17 -0
- package/dist/esm/utils/constants.js.map +1 -0
- package/dist/esm/utils/error-handler.js +182 -0
- package/dist/esm/utils/error-handler.js.map +1 -0
- package/dist/esm/utils/metadata-builder.js +183 -0
- package/dist/esm/utils/metadata-builder.js.map +1 -0
- package/dist/esm/utils/stop-reason-mapper.js +69 -0
- package/dist/esm/utils/stop-reason-mapper.js.map +1 -0
- package/dist/esm/utils/transaction-id.js +16 -0
- package/dist/esm/utils/transaction-id.js.map +1 -0
- package/dist/esm/utils/url-builder.js +53 -0
- package/dist/esm/utils/url-builder.js.map +1 -0
- package/dist/types/core/client/index.d.ts +5 -0
- package/dist/types/core/client/index.d.ts.map +1 -0
- package/dist/types/core/client/manager.d.ts +44 -0
- package/dist/types/core/client/manager.d.ts.map +1 -0
- package/dist/types/core/config/index.d.ts +10 -0
- package/dist/types/core/config/index.d.ts.map +1 -0
- package/dist/types/core/config/loader.d.ts +13 -0
- package/dist/types/core/config/loader.d.ts.map +1 -0
- package/dist/types/core/config/manager.d.ts +28 -0
- package/dist/types/core/config/manager.d.ts.map +1 -0
- package/dist/types/core/config/validator.d.ts +12 -0
- package/dist/types/core/config/validator.d.ts.map +1 -0
- package/dist/types/core/middleware/index.d.ts +7 -0
- package/dist/types/core/middleware/index.d.ts.map +1 -0
- package/dist/types/core/middleware/interfaces.d.ts +35 -0
- package/dist/types/core/middleware/interfaces.d.ts.map +1 -0
- package/dist/types/core/middleware/revenium-client.d.ts +25 -0
- package/dist/types/core/middleware/revenium-client.d.ts.map +1 -0
- package/dist/types/core/middleware/streaming-wrapper.d.ts +21 -0
- package/dist/types/core/middleware/streaming-wrapper.d.ts.map +1 -0
- package/dist/types/core/providers/detector.d.ts +24 -0
- package/dist/types/core/providers/detector.d.ts.map +1 -0
- package/dist/types/core/providers/index.d.ts +8 -0
- package/dist/types/core/providers/index.d.ts.map +1 -0
- package/dist/types/core/tracking/api-client.d.ts +17 -0
- package/dist/types/core/tracking/api-client.d.ts.map +1 -0
- package/dist/types/core/tracking/index.d.ts +11 -0
- package/dist/types/core/tracking/index.d.ts.map +1 -0
- package/dist/types/core/tracking/payload-builder.d.ts +24 -0
- package/dist/types/core/tracking/payload-builder.d.ts.map +1 -0
- package/dist/types/core/tracking/usage-tracker.d.ts +30 -0
- package/dist/types/core/tracking/usage-tracker.d.ts.map +1 -0
- package/dist/types/index.d.ts +50 -26
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types/function-parameters.d.ts +185 -0
- package/dist/types/types/function-parameters.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +108 -129
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/utils/constants.d.ts +9 -0
- package/dist/types/utils/constants.d.ts.map +1 -0
- package/dist/types/utils/error-handler.d.ts +95 -0
- package/dist/types/utils/error-handler.d.ts.map +1 -0
- package/dist/types/utils/metadata-builder.d.ts +65 -0
- package/dist/types/utils/metadata-builder.d.ts.map +1 -0
- package/dist/types/utils/stop-reason-mapper.d.ts +29 -0
- package/dist/types/utils/stop-reason-mapper.d.ts.map +1 -0
- package/dist/types/utils/transaction-id.d.ts +14 -0
- package/dist/types/utils/transaction-id.d.ts.map +1 -0
- package/dist/types/utils/url-builder.d.ts +22 -0
- package/dist/types/utils/url-builder.d.ts.map +1 -0
- package/examples/README.md +226 -322
- package/examples/advanced.ts +123 -0
- package/examples/basic.ts +45 -50
- package/examples/getting_started.ts +41 -64
- package/examples/metadata.ts +68 -65
- package/examples/stream.ts +53 -0
- package/package.json +72 -72
- package/dist/cjs/constants.js +0 -70
- package/dist/cjs/constants.js.map +0 -1
- package/dist/cjs/core/config/perplexity-config.js +0 -45
- package/dist/cjs/core/config/perplexity-config.js.map +0 -1
- package/dist/cjs/core/config/revenium-config.js +0 -80
- package/dist/cjs/core/config/revenium-config.js.map +0 -1
- package/dist/cjs/core/tracking/metering.js +0 -211
- package/dist/cjs/core/tracking/metering.js.map +0 -1
- package/dist/cjs/core/wrapper/perplexity-client.js +0 -187
- package/dist/cjs/core/wrapper/perplexity-client.js.map +0 -1
- package/dist/cjs/utils/logger.js +0 -23
- package/dist/cjs/utils/logger.js.map +0 -1
- package/dist/esm/constants.js +0 -67
- package/dist/esm/constants.js.map +0 -1
- package/dist/esm/core/config/perplexity-config.js +0 -40
- package/dist/esm/core/config/perplexity-config.js.map +0 -1
- package/dist/esm/core/config/revenium-config.js +0 -72
- package/dist/esm/core/config/revenium-config.js.map +0 -1
- package/dist/esm/core/tracking/metering.js +0 -206
- package/dist/esm/core/tracking/metering.js.map +0 -1
- package/dist/esm/core/wrapper/perplexity-client.js +0 -180
- package/dist/esm/core/wrapper/perplexity-client.js.map +0 -1
- package/dist/esm/utils/logger.js +0 -20
- package/dist/esm/utils/logger.js.map +0 -1
- package/dist/types/constants.d.ts +0 -67
- package/dist/types/constants.d.ts.map +0 -1
- package/dist/types/core/config/perplexity-config.d.ts +0 -24
- package/dist/types/core/config/perplexity-config.d.ts.map +0 -1
- package/dist/types/core/config/revenium-config.d.ts +0 -37
- package/dist/types/core/config/revenium-config.d.ts.map +0 -1
- package/dist/types/core/tracking/metering.d.ts +0 -31
- package/dist/types/core/tracking/metering.d.ts.map +0 -1
- package/dist/types/core/wrapper/perplexity-client.d.ts +0 -32
- package/dist/types/core/wrapper/perplexity-client.d.ts.map +0 -1
- package/dist/types/utils/logger.d.ts +0 -10
- package/dist/types/utils/logger.d.ts.map +0 -1
- package/examples/advanced-features.ts +0 -148
- package/examples/chat.ts +0 -73
- package/examples/streaming.ts +0 -50
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Error Handler Utilities
|
|
4
|
+
*
|
|
5
|
+
* Centralized error handling patterns to eliminate repetitive try/catch blocks
|
|
6
|
+
* and provide consistent error logging and recovery strategies.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.NetworkError = exports.ConfigurationError = exports.ValidationError = void 0;
|
|
10
|
+
exports.safeAsyncOperation = safeAsyncOperation;
|
|
11
|
+
exports.safeSyncOperation = safeSyncOperation;
|
|
12
|
+
exports.validateOrThrow = validateOrThrow;
|
|
13
|
+
exports.validateOrUndefined = validateOrUndefined;
|
|
14
|
+
exports.withRetry = withRetry;
|
|
15
|
+
exports.classifyError = classifyError;
|
|
16
|
+
const constants_js_1 = require("./constants.js");
|
|
17
|
+
/**
|
|
18
|
+
* Default error handling strategy
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_STRATEGY = {
|
|
21
|
+
logError: true,
|
|
22
|
+
rethrow: true,
|
|
23
|
+
messagePrefix: '',
|
|
24
|
+
fallbackValue: undefined,
|
|
25
|
+
transformError: (error) => (error instanceof Error ? error : new Error(String(error))),
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Safe async operation wrapper with comprehensive error handling
|
|
29
|
+
*
|
|
30
|
+
* @param operation - The async operation to execute
|
|
31
|
+
* @param context - Context information for logging
|
|
32
|
+
* @param strategy - Error handling strategy
|
|
33
|
+
* @param logger - Logger instance
|
|
34
|
+
* @returns Promise with result or fallback value
|
|
35
|
+
*/
|
|
36
|
+
async function safeAsyncOperation(operation, context, strategy = {}, logger) {
|
|
37
|
+
const config = { ...DEFAULT_STRATEGY, ...strategy };
|
|
38
|
+
try {
|
|
39
|
+
return await operation();
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
const transformedError = config.transformError(error);
|
|
43
|
+
if (config.logError && logger) {
|
|
44
|
+
logger.error(`${config.messagePrefix}${context}`, {
|
|
45
|
+
error: transformedError.message,
|
|
46
|
+
stack: transformedError.stack,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (config.rethrow)
|
|
50
|
+
throw transformedError;
|
|
51
|
+
return config.fallbackValue;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Safe sync operation wrapper
|
|
56
|
+
*
|
|
57
|
+
* @param operation - The sync operation to execute
|
|
58
|
+
* @param context - Context information for logging
|
|
59
|
+
* @param strategy - Error handling strategy
|
|
60
|
+
* @param logger - Logger instance
|
|
61
|
+
* @returns Result or fallback value
|
|
62
|
+
*/
|
|
63
|
+
function safeSyncOperation(operation, context, strategy = {}, logger) {
|
|
64
|
+
const config = { ...DEFAULT_STRATEGY, ...strategy };
|
|
65
|
+
try {
|
|
66
|
+
return operation();
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const transformedError = config.transformError(error);
|
|
70
|
+
if (config.logError && logger) {
|
|
71
|
+
logger.error(`${config.messagePrefix}${context}`, {
|
|
72
|
+
error: transformedError.message,
|
|
73
|
+
stack: transformedError.stack,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (config.rethrow)
|
|
77
|
+
throw transformedError;
|
|
78
|
+
return config.fallbackValue;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Validation wrapper that provides clear error messages
|
|
83
|
+
*
|
|
84
|
+
* @param value - Value to validate
|
|
85
|
+
* @param validator - Validation function
|
|
86
|
+
* @param errorMessage - Error message if validation fails
|
|
87
|
+
* @returns Validated value
|
|
88
|
+
*/
|
|
89
|
+
function validateOrThrow(value, validator, errorMessage) {
|
|
90
|
+
if (!validator(value))
|
|
91
|
+
throw new Error(errorMessage);
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validation wrapper that returns undefined on failure
|
|
96
|
+
*
|
|
97
|
+
* @param value - Value to validate
|
|
98
|
+
* @param validator - Validation function
|
|
99
|
+
* @param logger - Optional logger for warnings
|
|
100
|
+
* @param context - Context for logging
|
|
101
|
+
* @returns Validated value or undefined
|
|
102
|
+
*/
|
|
103
|
+
function validateOrUndefined(value, validator, logger, context) {
|
|
104
|
+
if (!validator(value)) {
|
|
105
|
+
if (logger && context) {
|
|
106
|
+
logger.warn(`Validation failed: ${context}`, { value });
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create a retry wrapper for operations that might fail temporarily
|
|
114
|
+
*
|
|
115
|
+
* @param operation - Operation to retry
|
|
116
|
+
* @param maxRetries - Maximum number of retries
|
|
117
|
+
* @param delayMs - Delay between retries in milliseconds
|
|
118
|
+
* @param logger - Logger for retry attempts
|
|
119
|
+
* @returns Promise with operation result
|
|
120
|
+
*/
|
|
121
|
+
async function withRetry(operation, maxRetries = 3, delayMs = 1000, logger) {
|
|
122
|
+
let lastError;
|
|
123
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
124
|
+
try {
|
|
125
|
+
return await operation();
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
129
|
+
if (attempt === maxRetries) {
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
if (logger) {
|
|
133
|
+
logger.warn(`Operation failed, retrying (${attempt}/${maxRetries})`, {
|
|
134
|
+
error: lastError.message,
|
|
135
|
+
nextRetryIn: delayMs,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// eslint-disable-next-line no-throw-literal
|
|
142
|
+
throw lastError;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Common error types for better error handling
|
|
146
|
+
*/
|
|
147
|
+
class ValidationError extends Error {
|
|
148
|
+
constructor(message, context) {
|
|
149
|
+
super(message);
|
|
150
|
+
this.context = context;
|
|
151
|
+
this.name = 'ValidationError';
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.ValidationError = ValidationError;
|
|
155
|
+
class ConfigurationError extends Error {
|
|
156
|
+
constructor(message, context) {
|
|
157
|
+
super(message);
|
|
158
|
+
this.context = context;
|
|
159
|
+
this.name = 'ConfigurationError';
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.ConfigurationError = ConfigurationError;
|
|
163
|
+
class NetworkError extends Error {
|
|
164
|
+
constructor(message, context) {
|
|
165
|
+
super(message);
|
|
166
|
+
this.context = context;
|
|
167
|
+
this.name = 'NetworkError';
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
exports.NetworkError = NetworkError;
|
|
171
|
+
/**
|
|
172
|
+
* Error classification utility
|
|
173
|
+
*/
|
|
174
|
+
function classifyError(error) {
|
|
175
|
+
if (error instanceof ValidationError) {
|
|
176
|
+
return { type: 'validation', message: error.message, isRetryable: false };
|
|
177
|
+
}
|
|
178
|
+
if (error instanceof ConfigurationError) {
|
|
179
|
+
return { type: 'configuration', message: error.message, isRetryable: false };
|
|
180
|
+
}
|
|
181
|
+
if (error instanceof NetworkError) {
|
|
182
|
+
return { type: 'network', message: error.message, isRetryable: true };
|
|
183
|
+
}
|
|
184
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
185
|
+
// Classify based on message patterns
|
|
186
|
+
if (constants_js_1.MESSAGE_PATTERNS_TYPE_NETWORK.some(pattern => message.includes(pattern))) {
|
|
187
|
+
return { type: 'network', message, isRetryable: true };
|
|
188
|
+
}
|
|
189
|
+
if (constants_js_1.ERROR_MESSAGE_PATTERNS_TYPE_CONFIG.some(pattern => message.includes(pattern))) {
|
|
190
|
+
return { type: 'configuration', message, isRetryable: false };
|
|
191
|
+
}
|
|
192
|
+
return { type: 'unknown', message, isRetryable: false };
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=error-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/utils/error-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Metadata Builder Utilities
|
|
4
|
+
*
|
|
5
|
+
* Centralized metadata handling to eliminate repetitive spreading
|
|
6
|
+
* and provide consistent metadata processing across the codebase.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.buildMetadataFields = buildMetadataFields;
|
|
10
|
+
exports.validateMetadata = validateMetadata;
|
|
11
|
+
exports.mergeMetadata = mergeMetadata;
|
|
12
|
+
exports.extractMetadata = extractMetadata;
|
|
13
|
+
exports.createLoggingContext = createLoggingContext;
|
|
14
|
+
exports.sanitizeMetadataForLogging = sanitizeMetadataForLogging;
|
|
15
|
+
/**
|
|
16
|
+
* Metadata mapping configuration
|
|
17
|
+
* Maps UsageMetadata fields to payload fields with optional transformations
|
|
18
|
+
* Subscriber object is passed through directly without transformation
|
|
19
|
+
*/
|
|
20
|
+
const METADATA_FIELD_MAP = [
|
|
21
|
+
{ source: 'traceId' },
|
|
22
|
+
{ source: 'taskType' },
|
|
23
|
+
{ source: 'agent' },
|
|
24
|
+
{ source: 'organizationId' },
|
|
25
|
+
{ source: 'productId' },
|
|
26
|
+
{ source: 'subscriber' }, // Pass through nested subscriber object directly
|
|
27
|
+
{ source: 'subscriptionId' },
|
|
28
|
+
{
|
|
29
|
+
source: 'responseQualityScore',
|
|
30
|
+
transform: (value) => {
|
|
31
|
+
// Ensure quality score is between 0.0 and 1.0 (API spec requirement)
|
|
32
|
+
if (typeof value === 'number')
|
|
33
|
+
return Math.max(0, Math.min(1, value));
|
|
34
|
+
return value;
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* Build metadata object for payload inclusion
|
|
40
|
+
*
|
|
41
|
+
* This function eliminates the repetitive spreading pattern and provides
|
|
42
|
+
* a clean, testable way to handle metadata transformation.
|
|
43
|
+
* Subscriber object is passed through directly without transformation.
|
|
44
|
+
*
|
|
45
|
+
* @param usageMetadata - Source metadata from request
|
|
46
|
+
* @returns Clean metadata object for payload
|
|
47
|
+
*/
|
|
48
|
+
function buildMetadataFields(usageMetadata) {
|
|
49
|
+
if (!usageMetadata)
|
|
50
|
+
return {};
|
|
51
|
+
const result = {};
|
|
52
|
+
// Process all metadata fields including nested subscriber object
|
|
53
|
+
for (const config of METADATA_FIELD_MAP) {
|
|
54
|
+
const value = usageMetadata[config.source];
|
|
55
|
+
// Skip undefined values (but allow null, empty strings, objects, etc.)
|
|
56
|
+
if (value === undefined)
|
|
57
|
+
continue;
|
|
58
|
+
// Apply transformation if configured
|
|
59
|
+
const transformedValue = config.transform ? config.transform(value) : value;
|
|
60
|
+
// Use target field name or default to source
|
|
61
|
+
const targetField = config.target || config.source;
|
|
62
|
+
result[targetField] = transformedValue;
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Validate metadata completeness for specific use cases
|
|
68
|
+
*
|
|
69
|
+
* @param usageMetadata - Metadata to validate
|
|
70
|
+
* @param requiredFields - List of required field names
|
|
71
|
+
* @returns Validation result
|
|
72
|
+
*/
|
|
73
|
+
function validateMetadata(usageMetadata, requiredFields = []) {
|
|
74
|
+
const missingFields = [];
|
|
75
|
+
const warnings = [];
|
|
76
|
+
if (!usageMetadata && requiredFields.length > 0) {
|
|
77
|
+
return {
|
|
78
|
+
isValid: false,
|
|
79
|
+
missingFields: requiredFields,
|
|
80
|
+
warnings: ['No metadata provided'],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (usageMetadata) {
|
|
84
|
+
// Check required fields
|
|
85
|
+
for (const field of requiredFields) {
|
|
86
|
+
if (!usageMetadata[field])
|
|
87
|
+
missingFields.push(String(field));
|
|
88
|
+
}
|
|
89
|
+
// Check for common issues
|
|
90
|
+
if (usageMetadata.responseQualityScore) {
|
|
91
|
+
const score = usageMetadata.responseQualityScore;
|
|
92
|
+
// API Spec: https://revenium.readme.io/reference/meter_ai_completion (responseQualityScore)
|
|
93
|
+
// "typically on a 0.0-1.0 scale"
|
|
94
|
+
if (typeof score !== 'number' || score < 0 || score > 1) {
|
|
95
|
+
warnings.push('responseQualityScore should be a number between 0.0 and 1.0');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (usageMetadata.subscriber?.email && !usageMetadata.subscriber.email.includes('@')) {
|
|
99
|
+
warnings.push('subscriber.email does not appear to be a valid email address');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
isValid: missingFields.length === 0,
|
|
104
|
+
missingFields,
|
|
105
|
+
warnings,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Merge multiple metadata sources with priority
|
|
110
|
+
*
|
|
111
|
+
* @param sources - Metadata sources in priority order (first wins)
|
|
112
|
+
* @returns Merged metadata object
|
|
113
|
+
*/
|
|
114
|
+
function mergeMetadata(...sources) {
|
|
115
|
+
const result = {};
|
|
116
|
+
// Process sources in reverse order so first source wins
|
|
117
|
+
for (const source of sources.reverse()) {
|
|
118
|
+
if (source)
|
|
119
|
+
Object.assign(result, source);
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Extract metadata from request parameters safely
|
|
125
|
+
*
|
|
126
|
+
* @param params - Request parameters that might contain usageMetadata
|
|
127
|
+
* @returns Extracted metadata and cleaned parameters
|
|
128
|
+
*/
|
|
129
|
+
function extractMetadata(params) {
|
|
130
|
+
const { usageMetadata, ...cleanParams } = params;
|
|
131
|
+
return {
|
|
132
|
+
metadata: usageMetadata,
|
|
133
|
+
cleanParams: cleanParams,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Create a metadata context for consistent logging
|
|
138
|
+
* Uses sanitization to protect PII (emails are masked)
|
|
139
|
+
*
|
|
140
|
+
* @param usageMetadata - Source metadata
|
|
141
|
+
* @returns Logging context object with sanitized PII
|
|
142
|
+
*/
|
|
143
|
+
function createLoggingContext(usageMetadata) {
|
|
144
|
+
if (!usageMetadata)
|
|
145
|
+
return {};
|
|
146
|
+
// Use sanitizer to protect PII in logs
|
|
147
|
+
const sanitized = sanitizeMetadataForLogging(usageMetadata);
|
|
148
|
+
const sanitizedSubscriber = sanitized.subscriber;
|
|
149
|
+
return {
|
|
150
|
+
traceId: usageMetadata.traceId,
|
|
151
|
+
taskType: usageMetadata.taskType,
|
|
152
|
+
subscriberId: usageMetadata.subscriber?.id,
|
|
153
|
+
subscriberEmail: sanitizedSubscriber?.email, // ← Now masked: us***@example.com
|
|
154
|
+
organizationId: usageMetadata.organizationId,
|
|
155
|
+
productId: usageMetadata.productId,
|
|
156
|
+
agent: usageMetadata.agent,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Sanitize metadata for logging (remove sensitive fields)
|
|
161
|
+
*
|
|
162
|
+
* @param usageMetadata - Source metadata
|
|
163
|
+
* @returns Sanitized metadata safe for logging
|
|
164
|
+
*/
|
|
165
|
+
function sanitizeMetadataForLogging(usageMetadata) {
|
|
166
|
+
if (!usageMetadata)
|
|
167
|
+
return {};
|
|
168
|
+
// Create a copy and handle nested subscriber object
|
|
169
|
+
const { subscriber, ...safeMetadata } = usageMetadata;
|
|
170
|
+
const result = { ...safeMetadata };
|
|
171
|
+
// Sanitize subscriber object if present
|
|
172
|
+
if (subscriber) {
|
|
173
|
+
const sanitizedSubscriber = {};
|
|
174
|
+
if (subscriber.id) {
|
|
175
|
+
sanitizedSubscriber.id = subscriber.id;
|
|
176
|
+
}
|
|
177
|
+
if (subscriber.email) {
|
|
178
|
+
// Mask email: handles single-char emails (a@x.com → a***@x.com)
|
|
179
|
+
sanitizedSubscriber.email = subscriber.email.replace(/(.{1,2}).*(@.*)/, '$1***$2');
|
|
180
|
+
}
|
|
181
|
+
if (subscriber.credential) {
|
|
182
|
+
sanitizedSubscriber.credential = {
|
|
183
|
+
name: subscriber.credential.name,
|
|
184
|
+
value: '[REDACTED]',
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
result.subscriber = sanitizedSubscriber;
|
|
188
|
+
}
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=metadata-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata-builder.js","sourceRoot":"","sources":["../../../src/utils/metadata-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stop Reason Mapper Utilities
|
|
4
|
+
*
|
|
5
|
+
* Centralized stop reason mapping logic using lookup tables
|
|
6
|
+
* instead of nested conditionals. Based on the good example
|
|
7
|
+
* from the anthropic-node middleware.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.mapStopReason = mapStopReason;
|
|
11
|
+
exports.getSupportedStopReasons = getSupportedStopReasons;
|
|
12
|
+
exports.isStopReasonSupported = isStopReasonSupported;
|
|
13
|
+
/**
|
|
14
|
+
* Stop reason mapping configuration
|
|
15
|
+
* Maps provider-specific stop reasons to Revenium's standardized set
|
|
16
|
+
*/
|
|
17
|
+
const STOP_REASON_MAP = {
|
|
18
|
+
// OpenAI/Azure OpenAI stop reasons
|
|
19
|
+
stop: 'END',
|
|
20
|
+
function_call: 'END_SEQUENCE',
|
|
21
|
+
tool_calls: 'END_SEQUENCE',
|
|
22
|
+
timeout: 'TIMEOUT',
|
|
23
|
+
length: 'TOKEN_LIMIT',
|
|
24
|
+
max_tokens: 'TOKEN_LIMIT',
|
|
25
|
+
cost_limit: 'COST_LIMIT',
|
|
26
|
+
completion_limit: 'COMPLETION_LIMIT',
|
|
27
|
+
content_filter: 'ERROR',
|
|
28
|
+
error: 'ERROR',
|
|
29
|
+
cancelled: 'CANCELLED',
|
|
30
|
+
canceled: 'CANCELLED', // Handle both spellings
|
|
31
|
+
// Anthropic stop reasons (for consistency across middleware)
|
|
32
|
+
end_turn: 'END',
|
|
33
|
+
stop_sequence: 'END_SEQUENCE',
|
|
34
|
+
tool_use: 'END_SEQUENCE',
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Default stop reason when mapping fails
|
|
38
|
+
*/
|
|
39
|
+
const DEFAULT_STOP_REASON = 'END';
|
|
40
|
+
/**
|
|
41
|
+
* Map provider stop reasons to Revenium stop reasons
|
|
42
|
+
*
|
|
43
|
+
* This replaces the nested if/switch logic with a clean lookup table approach.
|
|
44
|
+
* Based on the good example from the anthropic-node middleware.
|
|
45
|
+
*
|
|
46
|
+
* @param providerStopReason - Stop reason from the AI provider
|
|
47
|
+
* @param logger - Optional logger for warnings about unknown reasons
|
|
48
|
+
* @returns Standardized Revenium stop reason
|
|
49
|
+
*/
|
|
50
|
+
function mapStopReason(providerStopReason, logger) {
|
|
51
|
+
if (!providerStopReason)
|
|
52
|
+
return DEFAULT_STOP_REASON;
|
|
53
|
+
const normalizedReason = providerStopReason.toLowerCase();
|
|
54
|
+
const mappedReason = STOP_REASON_MAP[normalizedReason];
|
|
55
|
+
if (!mappedReason) {
|
|
56
|
+
// Log warning for unknown stop reasons to help with future mapping
|
|
57
|
+
logger?.warn(`Unknown stop reason: ${providerStopReason}, mapping to ${DEFAULT_STOP_REASON}`);
|
|
58
|
+
return DEFAULT_STOP_REASON;
|
|
59
|
+
}
|
|
60
|
+
return mappedReason;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get all supported stop reasons for documentation/testing
|
|
64
|
+
*/
|
|
65
|
+
function getSupportedStopReasons() {
|
|
66
|
+
return Object.keys(STOP_REASON_MAP);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if a stop reason is supported
|
|
70
|
+
*/
|
|
71
|
+
function isStopReasonSupported(reason) {
|
|
72
|
+
return reason.toLowerCase() in STOP_REASON_MAP;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=stop-reason-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop-reason-mapper.js","sourceRoot":"","sources":["../../../src/utils/stop-reason-mapper.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AA0CH,sCAeC;AAKD,0DAEC;AAKD,sDAEC;AArED;;;GAGG;AACH,MAAM,eAAe,GAA2B;IAC9C,mCAAmC;IACnC,IAAI,EAAE,KAAK;IACX,aAAa,EAAE,cAAc;IAC7B,UAAU,EAAE,cAAc;IAC1B,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,aAAa;IACrB,UAAU,EAAE,aAAa;IACzB,UAAU,EAAE,YAAY;IACxB,gBAAgB,EAAE,kBAAkB;IACpC,cAAc,EAAE,OAAO;IACvB,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,WAAW;IACtB,QAAQ,EAAE,WAAW,EAAG,wBAAwB;IAEhD,6DAA6D;IAC7D,QAAQ,EAAE,KAAK;IACf,aAAa,EAAE,cAAc;IAC7B,QAAQ,EAAE,cAAc;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAElC;;;;;;;;;GASG;AACH,SAAgB,aAAa,CAC3B,kBAA6C,EAC7C,MAA4D;IAE5D,IAAI,CAAC,kBAAkB;QAAE,OAAO,mBAAmB,CAAC;IACpD,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,WAAW,EAAE,CAAC;IAC1D,MAAM,YAAY,GAAG,eAAe,CAAC,gBAAgB,CAAC,CAAC;IAEvD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,mEAAmE;QACnE,MAAM,EAAE,IAAI,CAAC,wBAAwB,kBAAkB,gBAAgB,mBAAmB,EAAE,CAAC,CAAC;QAC9F,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,SAAgB,uBAAuB;IACrC,OAAO,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAgB,qBAAqB,CAAC,MAAc;IAClD,OAAO,MAAM,CAAC,WAAW,EAAE,IAAI,eAAe,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Transaction ID Generator
|
|
4
|
+
*
|
|
5
|
+
* Generates unique transaction IDs for tracking requests.
|
|
6
|
+
* Format: txn_{timestamp}_{random}
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.generateTransactionId = generateTransactionId;
|
|
10
|
+
/**
|
|
11
|
+
* Generate a unique transaction ID
|
|
12
|
+
*
|
|
13
|
+
* @returns A unique transaction ID in format: txn_{timestamp}_{random}
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
function generateTransactionId() {
|
|
17
|
+
return `txn_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=transaction-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-id.js","sourceRoot":"","sources":["../../../src/utils/transaction-id.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAQH,sDAEC;AARD;;;;;GAKG;AACH,SAAgB,qBAAqB;IACnC,OAAO,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* URL Builder Utilities
|
|
4
|
+
*
|
|
5
|
+
* Centralized URL construction logic to eliminate nested conditionals.
|
|
6
|
+
* Replaces the complex URL building logic from tracking.ts.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.buildReveniumUrl = buildReveniumUrl;
|
|
10
|
+
exports.isValidUrl = isValidUrl;
|
|
11
|
+
/**
|
|
12
|
+
* Build Revenium API URL with proper path handling
|
|
13
|
+
*
|
|
14
|
+
* @param baseUrl - The base URL from configuration (may include /meter or /meter/v2)
|
|
15
|
+
* @param endpoint - The API endpoint to append (e.g., '/ai/completions')
|
|
16
|
+
* @returns Complete URL for the API call
|
|
17
|
+
*/
|
|
18
|
+
function buildReveniumUrl(baseUrl, endpoint) {
|
|
19
|
+
// Normalize the base URL by removing trailing slashes
|
|
20
|
+
let normalizedBase = baseUrl.replace(/\/+$/, '');
|
|
21
|
+
// Check if /meter/v2 is already at the end
|
|
22
|
+
const hasMeterV2AtEnd = /\/meter\/v2$/i.test(normalizedBase);
|
|
23
|
+
if (hasMeterV2AtEnd) {
|
|
24
|
+
// Already has /meter/v2, just append endpoint
|
|
25
|
+
return `${normalizedBase}${endpoint}`;
|
|
26
|
+
}
|
|
27
|
+
// Check if /meter is at the end (but not /meter/v2)
|
|
28
|
+
const hasMeterAtEnd = /\/meter$/i.test(normalizedBase);
|
|
29
|
+
if (hasMeterAtEnd) {
|
|
30
|
+
// Has /meter but not /v2, append /v2 and endpoint
|
|
31
|
+
return `${normalizedBase}/v2${endpoint}`;
|
|
32
|
+
}
|
|
33
|
+
// Check if /v2 is at the end (without /meter)
|
|
34
|
+
const hasV2AtEnd = /\/v2$/i.test(normalizedBase);
|
|
35
|
+
if (hasV2AtEnd) {
|
|
36
|
+
// Has /v2 but not /meter, append endpoint as-is
|
|
37
|
+
return `${normalizedBase}${endpoint}`;
|
|
38
|
+
}
|
|
39
|
+
// Has neither /meter nor /v2, append /meter/v2 and endpoint
|
|
40
|
+
return `${normalizedBase}/meter/v2${endpoint}`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validate URL format
|
|
44
|
+
*
|
|
45
|
+
* @param url - URL to validate
|
|
46
|
+
* @returns true if valid, false otherwise
|
|
47
|
+
*/
|
|
48
|
+
function isValidUrl(url) {
|
|
49
|
+
try {
|
|
50
|
+
new URL(url);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=url-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-builder.js","sourceRoot":"","sources":["../../../src/utils/url-builder.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AASH,4CA2BC;AAQD,gCAOC;AAjDD;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAAC,OAAe,EAAE,QAAgB;IAChE,sDAAsD;IACtD,IAAI,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAEjD,2CAA2C;IAC3C,MAAM,eAAe,GAAG,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7D,IAAI,eAAe,EAAE,CAAC;QACpB,8CAA8C;QAC9C,OAAO,GAAG,cAAc,GAAG,QAAQ,EAAE,CAAC;IACxC,CAAC;IAED,oDAAoD;IACpD,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvD,IAAI,aAAa,EAAE,CAAC;QAClB,kDAAkD;QAClD,OAAO,GAAG,cAAc,MAAM,QAAQ,EAAE,CAAC;IAC3C,CAAC;IAED,8CAA8C;IAC9C,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACjD,IAAI,UAAU,EAAE,CAAC;QACf,gDAAgD;QAChD,OAAO,GAAG,cAAc,GAAG,QAAQ,EAAE,CAAC;IACxC,CAAC;IAED,4DAA4D;IAC5D,OAAO,GAAG,cAAc,YAAY,QAAQ,EAAE,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/client/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client Manager - singleton pattern
|
|
3
|
+
*
|
|
4
|
+
* Provides Initialize/GetClient pattern.
|
|
5
|
+
* Manages singleton instance of ReveniumPerplexity client.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import { ReveniumPerplexity } from "../middleware/revenium-client.js";
|
|
9
|
+
import { initializeConfig, getLogger } from "../config/manager.js";
|
|
10
|
+
/**
|
|
11
|
+
* Singleton instance of ReveniumPerplexity client
|
|
12
|
+
*/
|
|
13
|
+
let clientInstance = null;
|
|
14
|
+
const logger = getLogger();
|
|
15
|
+
/**
|
|
16
|
+
* Initialize Revenium Perplexity client from environment variables
|
|
17
|
+
*
|
|
18
|
+
* Loads configuration from environment:
|
|
19
|
+
* - REVENIUM_METERING_API_KEY (required)
|
|
20
|
+
* - PERPLEXITY_API_KEY (required)
|
|
21
|
+
* @throws {Error} If required environment variables are missing
|
|
22
|
+
*/
|
|
23
|
+
export function Initialize() {
|
|
24
|
+
logger.debug("Initializing Revenium Perplexity client");
|
|
25
|
+
const config = initializeConfig();
|
|
26
|
+
Configure(config);
|
|
27
|
+
logger.debug("Revenium Perplexity client initialized successfully");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Configure Revenium Perplexity client with custom configuration
|
|
31
|
+
*
|
|
32
|
+
* @param config - Configuration object
|
|
33
|
+
* @throws {Error} If required configuration fields are missing
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
36
|
+
export function Configure(config) {
|
|
37
|
+
logger.debug("Configuring Revenium Perplexity client");
|
|
38
|
+
if (!config.reveniumApiKey) {
|
|
39
|
+
throw new Error("reveniumApiKey is required in configuration");
|
|
40
|
+
}
|
|
41
|
+
if (!config.perplexityApiKey) {
|
|
42
|
+
throw new Error("perplexityApiKey is required in configuration");
|
|
43
|
+
}
|
|
44
|
+
const fullConfig = {
|
|
45
|
+
...config,
|
|
46
|
+
reveniumBaseUrl: config.reveniumBaseUrl || "https://api.revenium.ai",
|
|
47
|
+
perplexityBaseUrl: config.perplexityBaseUrl || "https://api.perplexity.ai",
|
|
48
|
+
debug: config.debug ?? false,
|
|
49
|
+
};
|
|
50
|
+
clientInstance = new ReveniumPerplexity(fullConfig);
|
|
51
|
+
if (fullConfig.debug) {
|
|
52
|
+
logger.debug("Revenium Perplexity client initialized successfully");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the singleton ReveniumPerplexity client instance
|
|
57
|
+
*
|
|
58
|
+
* @returns {ReveniumPerplexity} The client instance
|
|
59
|
+
* @throws {Error} If client has not been initialized
|
|
60
|
+
*
|
|
61
|
+
*/
|
|
62
|
+
export function GetClient() {
|
|
63
|
+
if (!clientInstance) {
|
|
64
|
+
throw new Error("Revenium Perplexity client not initialized. Call Initialize() or Configure() first.");
|
|
65
|
+
}
|
|
66
|
+
return clientInstance;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if client has been initialized
|
|
70
|
+
* @returns {boolean} True if client is initialized
|
|
71
|
+
*/
|
|
72
|
+
export function IsInitialized() {
|
|
73
|
+
return clientInstance !== null;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Reset the client instance (useful for testing)
|
|
77
|
+
*/
|
|
78
|
+
export function Reset() {
|
|
79
|
+
clientInstance = null;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../../src/core/client/manager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEnE;;GAEG;AACH,IAAI,cAAc,GAA8B,IAAI,CAAC;AACrD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;AAG3B;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAExD,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,SAAS,CAAC,MAAM,CAAC,CAAC;IAElB,MAAM,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,MAAsB;IAC9C,MAAM,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,UAAU,GAAmB;QACjC,GAAG,MAAM;QACT,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,yBAAyB;QACpE,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,IAAI,2BAA2B;QAC1E,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK;KAC7B,CAAC;IAEF,cAAc,GAAG,IAAI,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAEpD,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,qFAAqF,CACtF,CAAC;IACJ,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,cAAc,KAAK,IAAI,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK;IACnB,cAAc,GAAG,IAAI,CAAC;AACxB,CAAC"}
|