@revenium/openai 1.0.12 → 1.0.13
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/.env.example +8 -8
- package/CHANGELOG.md +26 -0
- package/README.md +57 -351
- package/dist/cjs/core/config/loader.js +1 -1
- package/dist/cjs/core/config/manager.js +2 -1
- package/dist/cjs/core/config/manager.js.map +1 -1
- package/dist/cjs/core/providers/detector.js +3 -3
- package/dist/cjs/core/providers/detector.js.map +1 -1
- package/dist/cjs/core/tracking/api-client.js +1 -1
- package/dist/cjs/core/tracking/payload-builder.js +17 -12
- package/dist/cjs/core/tracking/payload-builder.js.map +1 -1
- package/dist/cjs/index.js +23 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/utils/metadata-builder.js +12 -5
- package/dist/cjs/utils/metadata-builder.js.map +1 -1
- package/dist/cjs/utils/stop-reason-mapper.js +4 -0
- package/dist/cjs/utils/stop-reason-mapper.js.map +1 -1
- package/dist/cjs/utils/url-builder.js +3 -3
- package/dist/esm/core/config/loader.js +1 -1
- package/dist/esm/core/config/manager.js +2 -1
- package/dist/esm/core/config/manager.js.map +1 -1
- package/dist/esm/core/providers/detector.js +3 -3
- package/dist/esm/core/providers/detector.js.map +1 -1
- package/dist/esm/core/tracking/api-client.js +1 -1
- package/dist/esm/core/tracking/payload-builder.js +17 -12
- package/dist/esm/core/tracking/payload-builder.js.map +1 -1
- package/dist/esm/index.js +22 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/utils/metadata-builder.js +12 -5
- package/dist/esm/utils/metadata-builder.js.map +1 -1
- package/dist/esm/utils/stop-reason-mapper.js +4 -0
- package/dist/esm/utils/stop-reason-mapper.js.map +1 -1
- package/dist/esm/utils/url-builder.js +3 -3
- package/dist/types/core/config/manager.d.ts.map +1 -1
- package/dist/types/core/tracking/payload-builder.d.ts.map +1 -1
- package/dist/types/index.d.ts +23 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +9 -13
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/types/openai-augmentation.d.ts +1 -2
- package/dist/types/types/openai-augmentation.d.ts.map +1 -1
- package/dist/types/utils/metadata-builder.d.ts +2 -1
- package/dist/types/utils/metadata-builder.d.ts.map +1 -1
- package/dist/types/utils/stop-reason-mapper.d.ts.map +1 -1
- package/dist/types/utils/url-builder.d.ts +3 -3
- package/examples/README.md +3 -41
- package/examples/azure-basic.ts +1 -1
- package/examples/azure-responses-basic.ts +3 -3
- package/examples/azure-responses-streaming.ts +3 -3
- package/examples/azure-streaming.ts +2 -2
- package/examples/getting_started.ts +1 -1
- package/examples/openai-basic.ts +2 -2
- package/examples/openai-function-calling.ts +2 -2
- package/examples/openai-responses-basic.ts +2 -2
- package/examples/openai-responses-streaming.ts +2 -2
- package/examples/openai-streaming.ts +1 -1
- package/examples/openai-vision.ts +2 -2
- package/package.json +1 -1
- package/src/core/config/loader.ts +1 -1
- package/src/core/config/manager.ts +2 -1
- package/src/core/providers/detector.ts +3 -3
- package/src/core/tracking/api-client.ts +1 -1
- package/src/core/tracking/payload-builder.ts +17 -12
- package/src/index.ts +27 -3
- package/src/types/index.ts +11 -14
- package/src/types/openai-augmentation.ts +1 -2
- package/src/utils/metadata-builder.ts +16 -7
- package/src/utils/stop-reason-mapper.ts +4 -0
- package/src/utils/url-builder.ts +3 -3
package/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Environment Variables:
|
|
8
8
|
* REVENIUM_METERING_API_KEY=hak_your_api_key
|
|
9
|
-
* REVENIUM_METERING_BASE_URL=https://api.revenium.
|
|
9
|
+
* REVENIUM_METERING_BASE_URL=https://api.revenium.ai (optional)
|
|
10
10
|
* OPENAI_API_KEY=sk_your_openai_key
|
|
11
11
|
*
|
|
12
12
|
* Simple Usage (auto-initialization):
|
|
@@ -77,7 +77,7 @@ export type {
|
|
|
77
77
|
* ```typescript
|
|
78
78
|
* const config: ReveniumConfig = {
|
|
79
79
|
* reveniumApiKey: 'hak_your_api_key',
|
|
80
|
-
* reveniumBaseUrl: 'https://api.revenium.
|
|
80
|
+
* reveniumBaseUrl: 'https://api.revenium.ai',
|
|
81
81
|
* debug: true
|
|
82
82
|
* };
|
|
83
83
|
* ```
|
|
@@ -212,7 +212,7 @@ export function initializeRevenium(config: ReveniumConfig): {
|
|
|
212
212
|
// Apply default base URL if not provided
|
|
213
213
|
const configWithDefaults = {
|
|
214
214
|
...config,
|
|
215
|
-
reveniumBaseUrl: config.reveniumBaseUrl || 'https://api.revenium.
|
|
215
|
+
reveniumBaseUrl: config.reveniumBaseUrl || 'https://api.revenium.ai',
|
|
216
216
|
};
|
|
217
217
|
|
|
218
218
|
validateConfig(configWithDefaults);
|
|
@@ -237,6 +237,30 @@ export function initializeRevenium(config: ReveniumConfig): {
|
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Configure Revenium middleware manually
|
|
242
|
+
* Alias for initializeRevenium() with a more intuitive name
|
|
243
|
+
*
|
|
244
|
+
* @param config - Revenium configuration object
|
|
245
|
+
* @returns Initialization result with success status and message
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* ```typescript
|
|
249
|
+
* import { configure } from '@revenium/openai';
|
|
250
|
+
*
|
|
251
|
+
* configure({
|
|
252
|
+
* reveniumApiKey: 'hak_your_api_key',
|
|
253
|
+
* reveniumBaseUrl: 'https://api.revenium.ai',
|
|
254
|
+
* });
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export function configure(config: ReveniumConfig): {
|
|
258
|
+
success: boolean;
|
|
259
|
+
message: string;
|
|
260
|
+
} {
|
|
261
|
+
return initializeRevenium(config);
|
|
262
|
+
}
|
|
263
|
+
|
|
240
264
|
/**
|
|
241
265
|
* Initialize Revenium middleware from environment variables
|
|
242
266
|
*/
|
package/src/types/index.ts
CHANGED
|
@@ -80,7 +80,7 @@ export interface Subscriber {
|
|
|
80
80
|
* productId: 'chat-assistant',
|
|
81
81
|
* taskType: 'customer-support',
|
|
82
82
|
* traceId: 'trace-789',
|
|
83
|
-
* responseQualityScore: 0.95,
|
|
83
|
+
* responseQualityScore: 0.95, // 0.0-1.0 scale per API spec
|
|
84
84
|
* agent: 'support-bot-v2'
|
|
85
85
|
* };
|
|
86
86
|
* ```
|
|
@@ -98,19 +98,14 @@ export interface UsageMetadata {
|
|
|
98
98
|
|
|
99
99
|
/** Task type classification (e.g., 'chat', 'summarization', 'translation') */
|
|
100
100
|
taskType?: string;
|
|
101
|
-
/** Unique task identifier for request correlation */
|
|
102
|
-
taskId?: string;
|
|
103
101
|
/** Distributed tracing identifier for request tracking across services */
|
|
104
102
|
traceId?: string;
|
|
105
103
|
|
|
106
|
-
/** Quality score for response evaluation (0.0
|
|
104
|
+
/** Quality score for response evaluation (0.0-1.0 scale per API spec) */
|
|
107
105
|
responseQualityScore?: number;
|
|
108
106
|
|
|
109
107
|
/** Agent or model variant identifier for A/B testing and performance tracking */
|
|
110
108
|
agent?: string;
|
|
111
|
-
|
|
112
|
-
/** Allow additional custom fields for extensibility */
|
|
113
|
-
[key: string]: unknown;
|
|
114
109
|
}
|
|
115
110
|
|
|
116
111
|
/**
|
|
@@ -214,7 +209,7 @@ export interface AzureConfig {
|
|
|
214
209
|
* ```typescript
|
|
215
210
|
* const config: ReveniumConfig = {
|
|
216
211
|
* reveniumApiKey: 'hak_your_revenium_api_key',
|
|
217
|
-
* reveniumBaseUrl: 'https://api.revenium.
|
|
212
|
+
* reveniumBaseUrl: 'https://api.revenium.ai',
|
|
218
213
|
* debug: true,
|
|
219
214
|
* openaiApiKey: process.env.OPENAI_API_KEY
|
|
220
215
|
* };
|
|
@@ -223,7 +218,7 @@ export interface AzureConfig {
|
|
|
223
218
|
export interface ReveniumConfig {
|
|
224
219
|
/** Revenium API key for authentication (required) */
|
|
225
220
|
reveniumApiKey: string;
|
|
226
|
-
/** Revenium API base URL (optional, defaults to https://api.revenium.
|
|
221
|
+
/** Revenium API base URL (optional, defaults to https://api.revenium.ai) */
|
|
227
222
|
reveniumBaseUrl?: string;
|
|
228
223
|
/** Enable debug logging (optional, defaults to false) */
|
|
229
224
|
debug?: boolean;
|
|
@@ -268,7 +263,7 @@ export interface Logger {
|
|
|
268
263
|
export interface ReveniumPayload {
|
|
269
264
|
// Core identification
|
|
270
265
|
transactionId: string;
|
|
271
|
-
operationType: 'CHAT' | 'EMBED';
|
|
266
|
+
operationType: 'CHAT' | 'GENERATE' | 'EMBED' | 'CLASSIFY' | 'SUMMARIZE' | 'TRANSLATE' | 'OTHER';
|
|
272
267
|
costType: 'AI';
|
|
273
268
|
|
|
274
269
|
// Model and provider info
|
|
@@ -287,14 +282,16 @@ export interface ReveniumPayload {
|
|
|
287
282
|
inputTokenCount: number;
|
|
288
283
|
outputTokenCount: number;
|
|
289
284
|
totalTokenCount: number;
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
285
|
+
// API Spec: https://revenium.readme.io/reference/meter_ai_completion
|
|
286
|
+
// "Leave null for models without reasoning capabilities" - NOT in required fields
|
|
287
|
+
reasoningTokenCount: number | undefined;
|
|
288
|
+
cacheCreationTokenCount: number | undefined; // Undefined when provider doesn't report
|
|
289
|
+
cacheReadTokenCount: number | undefined; // Undefined when provider doesn't report
|
|
293
290
|
|
|
294
291
|
// Chat-specific fields
|
|
295
292
|
stopReason: string;
|
|
296
293
|
isStreamed: boolean;
|
|
297
|
-
timeToFirstToken?: number;
|
|
294
|
+
timeToFirstToken?: number | undefined; // Undefined when not tracking TTFB
|
|
298
295
|
|
|
299
296
|
// Cost information (calculated by backend)
|
|
300
297
|
inputTokenCost?: number;
|
|
@@ -154,8 +154,7 @@ declare module 'openai/resources/embeddings' {
|
|
|
154
154
|
* },
|
|
155
155
|
* organizationId: 'my-company',
|
|
156
156
|
* productId: 'vector-search',
|
|
157
|
-
* taskType: 'document-indexing'
|
|
158
|
-
* taskId: 'batch-index-2024-01'
|
|
157
|
+
* taskType: 'document-indexing'
|
|
159
158
|
* }
|
|
160
159
|
* ```
|
|
161
160
|
*
|
|
@@ -37,7 +37,7 @@ const METADATA_FIELD_MAP: MetadataFieldConfig[] = [
|
|
|
37
37
|
{
|
|
38
38
|
source: 'responseQualityScore',
|
|
39
39
|
transform: (value: unknown) => {
|
|
40
|
-
// Ensure quality score is between 0 and 1
|
|
40
|
+
// Ensure quality score is between 0.0 and 1.0 (API spec requirement)
|
|
41
41
|
if (typeof value === 'number') return Math.max(0, Math.min(1, value));
|
|
42
42
|
return value;
|
|
43
43
|
},
|
|
@@ -111,8 +111,10 @@ export function validateMetadata(
|
|
|
111
111
|
// Check for common issues
|
|
112
112
|
if (usageMetadata.responseQualityScore) {
|
|
113
113
|
const score = usageMetadata.responseQualityScore;
|
|
114
|
+
// API Spec: https://revenium.readme.io/reference/meter_ai_completion (responseQualityScore)
|
|
115
|
+
// "typically on a 0.0-1.0 scale"
|
|
114
116
|
if (typeof score !== 'number' || score < 0 || score > 1) {
|
|
115
|
-
warnings.push('responseQualityScore should be a number between 0 and 1');
|
|
117
|
+
warnings.push('responseQualityScore should be a number between 0.0 and 1.0');
|
|
116
118
|
}
|
|
117
119
|
}
|
|
118
120
|
|
|
@@ -164,17 +166,23 @@ export function extractMetadata<T extends Record<string, unknown>>(
|
|
|
164
166
|
|
|
165
167
|
/**
|
|
166
168
|
* Create a metadata context for consistent logging
|
|
169
|
+
* Uses sanitization to protect PII (emails are masked)
|
|
167
170
|
*
|
|
168
171
|
* @param usageMetadata - Source metadata
|
|
169
|
-
* @returns Logging context object
|
|
172
|
+
* @returns Logging context object with sanitized PII
|
|
170
173
|
*/
|
|
171
174
|
export function createLoggingContext(usageMetadata?: UsageMetadata): Record<string, unknown> {
|
|
172
175
|
if (!usageMetadata) return {};
|
|
176
|
+
|
|
177
|
+
// Use sanitizer to protect PII in logs
|
|
178
|
+
const sanitized = sanitizeMetadataForLogging(usageMetadata);
|
|
179
|
+
const sanitizedSubscriber = sanitized.subscriber as { id?: string; email?: string; credential?: unknown };
|
|
180
|
+
|
|
173
181
|
return {
|
|
174
182
|
traceId: usageMetadata.traceId,
|
|
175
183
|
taskType: usageMetadata.taskType,
|
|
176
184
|
subscriberId: usageMetadata.subscriber?.id,
|
|
177
|
-
subscriberEmail:
|
|
185
|
+
subscriberEmail: sanitizedSubscriber?.email, // ← Now masked: us***@example.com
|
|
178
186
|
organizationId: usageMetadata.organizationId,
|
|
179
187
|
productId: usageMetadata.productId,
|
|
180
188
|
agent: usageMetadata.agent,
|
|
@@ -193,18 +201,19 @@ export function sanitizeMetadataForLogging(usageMetadata?: UsageMetadata): Recor
|
|
|
193
201
|
// Create a copy and handle nested subscriber object
|
|
194
202
|
const { subscriber, ...safeMetadata } = usageMetadata;
|
|
195
203
|
|
|
196
|
-
const result = { ...safeMetadata };
|
|
204
|
+
const result: Record<string, unknown> = { ...safeMetadata };
|
|
197
205
|
|
|
198
206
|
// Sanitize subscriber object if present
|
|
199
207
|
if (subscriber) {
|
|
200
|
-
const sanitizedSubscriber:
|
|
208
|
+
const sanitizedSubscriber: Record<string, unknown> = {};
|
|
201
209
|
|
|
202
210
|
if (subscriber.id) {
|
|
203
211
|
sanitizedSubscriber.id = subscriber.id;
|
|
204
212
|
}
|
|
205
213
|
|
|
206
214
|
if (subscriber.email) {
|
|
207
|
-
|
|
215
|
+
// Mask email: handles single-char emails (a@x.com → a***@x.com)
|
|
216
|
+
sanitizedSubscriber.email = subscriber.email.replace(/(.{1,2}).*(@.*)/, '$1***$2');
|
|
208
217
|
}
|
|
209
218
|
|
|
210
219
|
if (subscriber.credential) {
|
|
@@ -18,8 +18,12 @@ const STOP_REASON_MAP: Record<string, string> = {
|
|
|
18
18
|
timeout: 'TIMEOUT',
|
|
19
19
|
length: 'TOKEN_LIMIT',
|
|
20
20
|
max_tokens: 'TOKEN_LIMIT',
|
|
21
|
+
cost_limit: 'COST_LIMIT',
|
|
22
|
+
completion_limit: 'COMPLETION_LIMIT',
|
|
21
23
|
content_filter: 'ERROR',
|
|
22
24
|
error: 'ERROR',
|
|
25
|
+
cancelled: 'CANCELLED',
|
|
26
|
+
canceled: 'CANCELLED', // Handle both spellings
|
|
23
27
|
|
|
24
28
|
// Anthropic stop reasons (for consistency across middleware)
|
|
25
29
|
end_turn: 'END',
|
package/src/utils/url-builder.ts
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
* - If URL has neither → append /meter/v2 and endpoint
|
|
16
16
|
*
|
|
17
17
|
* Examples:
|
|
18
|
-
* - 'https://api.revenium.
|
|
19
|
-
* - 'https://api.revenium.
|
|
20
|
-
* - 'https://api.revenium.
|
|
18
|
+
* - 'https://api.revenium.ai' + '/ai/completions' → 'https://api.revenium.ai/meter/v2/ai/completions'
|
|
19
|
+
* - 'https://api.revenium.ai/meter' + '/ai/completions' → 'https://api.revenium.ai/meter/v2/ai/completions'
|
|
20
|
+
* - 'https://api.revenium.ai/meter/v2' + '/ai/completions' → 'https://api.revenium.ai/meter/v2/ai/completions'
|
|
21
21
|
*
|
|
22
22
|
* @param baseUrl - The base URL from configuration (may include /meter or /meter/v2)
|
|
23
23
|
* @param endpoint - The API endpoint to append (e.g., '/ai/completions')
|