@revenium/anthropic 1.0.8 → 1.0.9
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 +34 -1
- package/README.md +156 -49
- package/dist/cjs/config.js +55 -7
- package/dist/cjs/constants.js +39 -24
- package/dist/cjs/tracking.js +82 -20
- package/dist/cjs/types/anthropic-augmentation.js +0 -62
- package/dist/cjs/utils/summary-printer.js +189 -0
- package/dist/cjs/utils/trace-fields.js +117 -0
- package/dist/cjs/utils/validation.js +55 -23
- package/dist/cjs/wrapper.js +49 -41
- package/dist/esm/config.js +55 -7
- package/dist/esm/constants.js +38 -23
- package/dist/esm/tracking.js +82 -20
- package/dist/esm/types/anthropic-augmentation.js +0 -62
- package/dist/esm/utils/summary-printer.js +186 -0
- package/dist/esm/utils/trace-fields.js +106 -0
- package/dist/esm/utils/validation.js +56 -24
- package/dist/esm/wrapper.js +55 -47
- package/dist/types/config.d.ts +1 -0
- package/dist/types/constants.d.ts +15 -0
- package/dist/types/types/anthropic-augmentation.d.ts +0 -92
- package/dist/types/types.d.ts +28 -196
- package/dist/types/utils/summary-printer.d.ts +3 -0
- package/dist/types/utils/trace-fields.d.ts +10 -0
- package/examples/advanced.ts +128 -0
- package/examples/basic.ts +132 -0
- package/examples/getting_started.ts +6 -6
- package/examples/metadata.ts +58 -0
- package/package.json +4 -6
- package/examples/advanced-features.ts +0 -469
- package/examples/basic-usage.ts +0 -314
package/dist/esm/wrapper.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Anthropic SDK wrapper with type safety and structured error handling
|
|
3
3
|
*/
|
|
4
|
-
import Anthropic from
|
|
5
|
-
import { getLogger, getConfig } from
|
|
6
|
-
import { trackUsageAsync, extractUsageFromResponse, extractUsageFromStream } from
|
|
7
|
-
import { validateAnthropicMessageParams, validateUsageMetadata } from
|
|
8
|
-
import { AnthropicPatchingError, RequestProcessingError, StreamProcessingError, createErrorContext, handleError } from
|
|
9
|
-
import { randomUUID } from
|
|
4
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
5
|
+
import { getLogger, getConfig } from "./config.js";
|
|
6
|
+
import { trackUsageAsync, extractUsageFromResponse, extractUsageFromStream, } from "./tracking.js";
|
|
7
|
+
import { validateAnthropicMessageParams, validateUsageMetadata, } from "./utils/validation.js";
|
|
8
|
+
import { AnthropicPatchingError, RequestProcessingError, StreamProcessingError, createErrorContext, handleError, } from "./utils/error-handling.js";
|
|
9
|
+
import { randomUUID } from "crypto";
|
|
10
10
|
// Global logger
|
|
11
11
|
const logger = getLogger();
|
|
12
12
|
/**
|
|
@@ -15,7 +15,7 @@ const logger = getLogger();
|
|
|
15
15
|
const patchingContext = {
|
|
16
16
|
originalMethods: {},
|
|
17
17
|
isPatched: false,
|
|
18
|
-
patchedInstances: new WeakSet()
|
|
18
|
+
patchedInstances: new WeakSet(),
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
21
|
* Get the Messages prototype using sophisticated prototype access
|
|
@@ -38,8 +38,8 @@ function getMessagesPrototype() {
|
|
|
38
38
|
const config = getConfig();
|
|
39
39
|
const apiKey = config?.anthropicApiKey ?? process.env.ANTHROPIC_API_KEY;
|
|
40
40
|
if (!apiKey) {
|
|
41
|
-
throw new AnthropicPatchingError(
|
|
42
|
-
|
|
41
|
+
throw new AnthropicPatchingError("Unable to access Anthropic Messages prototype: No API key available and direct prototype access failed. " +
|
|
42
|
+
"Provide ANTHROPIC_API_KEY environment variable or pass anthropicApiKey in config.");
|
|
43
43
|
}
|
|
44
44
|
const minimalInstance = new Anthropic({ apiKey });
|
|
45
45
|
const messagesPrototype = Object.getPrototypeOf(minimalInstance.messages);
|
|
@@ -57,19 +57,19 @@ function getMessagesPrototype() {
|
|
|
57
57
|
*/
|
|
58
58
|
export function patchAnthropic() {
|
|
59
59
|
if (patchingContext.isPatched) {
|
|
60
|
-
logger.debug(
|
|
60
|
+
logger.debug("Anthropic SDK already patched, skipping duplicate initialization");
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
63
|
try {
|
|
64
64
|
// Access the Messages class prototype using sophisticated prototype access
|
|
65
65
|
const messagesPrototype = getMessagesPrototype();
|
|
66
66
|
if (!messagesPrototype)
|
|
67
|
-
throw new AnthropicPatchingError(
|
|
67
|
+
throw new AnthropicPatchingError("Unable to access Anthropic Messages prototype");
|
|
68
68
|
// Store original methods
|
|
69
69
|
patchingContext.originalMethods.create = messagesPrototype?.create;
|
|
70
70
|
patchingContext.originalMethods.stream = messagesPrototype?.stream;
|
|
71
71
|
if (!patchingContext.originalMethods?.create) {
|
|
72
|
-
throw new AnthropicPatchingError(
|
|
72
|
+
throw new AnthropicPatchingError("Unable to find original create method");
|
|
73
73
|
}
|
|
74
74
|
// Patch the create method
|
|
75
75
|
const patchedCreateFunction = function (params, options) {
|
|
@@ -83,11 +83,11 @@ export function patchAnthropic() {
|
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
patchingContext.isPatched = true;
|
|
86
|
-
logger.info(
|
|
86
|
+
logger.info("Anthropic SDK patched successfully");
|
|
87
87
|
}
|
|
88
88
|
catch (error) {
|
|
89
89
|
const errorContext = createErrorContext()
|
|
90
|
-
.with(
|
|
90
|
+
.with("patchingAttempt", true)
|
|
91
91
|
.build();
|
|
92
92
|
handleError(error, logger, errorContext);
|
|
93
93
|
if (error instanceof AnthropicPatchingError)
|
|
@@ -112,11 +112,11 @@ export function unpatchAnthropic() {
|
|
|
112
112
|
}
|
|
113
113
|
patchingContext.isPatched = false;
|
|
114
114
|
patchingContext.originalMethods = {};
|
|
115
|
-
logger.info(
|
|
115
|
+
logger.info("Anthropic SDK unpatched successfully");
|
|
116
116
|
}
|
|
117
117
|
catch (error) {
|
|
118
118
|
const errorContext = createErrorContext()
|
|
119
|
-
.with(
|
|
119
|
+
.with("unpatchingAttempt", true)
|
|
120
120
|
.build();
|
|
121
121
|
handleError(error, logger, errorContext);
|
|
122
122
|
throw new AnthropicPatchingError(`Failed to unpatch Anthropic SDK: ${error instanceof Error ? error.message : String(error)}`, errorContext);
|
|
@@ -132,7 +132,7 @@ export function isAnthropicPatched() {
|
|
|
132
132
|
* Handle streaming response by collecting chunks and extracting usage data
|
|
133
133
|
*/
|
|
134
134
|
async function handleStreamingResponse(stream, context) {
|
|
135
|
-
const { requestId, model, metadata, requestTime, startTime } = context;
|
|
135
|
+
const { requestId, model, metadata, requestTime, startTime, requestBody } = context;
|
|
136
136
|
// Create a new async generator that collects chunks and tracks usage
|
|
137
137
|
async function* trackingStream() {
|
|
138
138
|
const chunks = [];
|
|
@@ -140,7 +140,7 @@ async function handleStreamingResponse(stream, context) {
|
|
|
140
140
|
try {
|
|
141
141
|
for await (const chunk of stream) {
|
|
142
142
|
// Track first token time
|
|
143
|
-
if (!firstTokenTime && chunk.type ===
|
|
143
|
+
if (!firstTokenTime && chunk.type === "content_block_delta") {
|
|
144
144
|
firstTokenTime = Date.now();
|
|
145
145
|
}
|
|
146
146
|
chunks.push(chunk);
|
|
@@ -150,12 +150,14 @@ async function handleStreamingResponse(stream, context) {
|
|
|
150
150
|
const endTime = Date.now();
|
|
151
151
|
const responseTime = new Date();
|
|
152
152
|
const duration = endTime - startTime;
|
|
153
|
-
const timeToFirstToken = firstTokenTime
|
|
154
|
-
|
|
153
|
+
const timeToFirstToken = firstTokenTime
|
|
154
|
+
? firstTokenTime - startTime
|
|
155
|
+
: undefined;
|
|
156
|
+
logger.debug("Stream completed, extracting usage", {
|
|
155
157
|
requestId,
|
|
156
158
|
chunkCount: chunks.length,
|
|
157
159
|
duration,
|
|
158
|
-
timeToFirstToken
|
|
160
|
+
timeToFirstToken,
|
|
159
161
|
});
|
|
160
162
|
const usage = extractUsageFromStream(chunks);
|
|
161
163
|
// Create tracking data
|
|
@@ -172,22 +174,23 @@ async function handleStreamingResponse(stream, context) {
|
|
|
172
174
|
metadata,
|
|
173
175
|
requestTime,
|
|
174
176
|
responseTime,
|
|
175
|
-
timeToFirstToken
|
|
177
|
+
timeToFirstToken,
|
|
178
|
+
requestBody: requestBody,
|
|
176
179
|
};
|
|
177
180
|
// Track usage asynchronously
|
|
178
181
|
trackUsageAsync(trackingData);
|
|
179
|
-
logger.debug(
|
|
182
|
+
logger.debug("Anthropic streaming request completed successfully", {
|
|
180
183
|
requestId,
|
|
181
184
|
model,
|
|
182
185
|
inputTokens: usage.inputTokens,
|
|
183
186
|
outputTokens: usage.outputTokens,
|
|
184
|
-
duration
|
|
187
|
+
duration,
|
|
185
188
|
});
|
|
186
189
|
}
|
|
187
190
|
catch (error) {
|
|
188
|
-
logger.error(
|
|
191
|
+
logger.error("Error processing streaming response", {
|
|
189
192
|
requestId,
|
|
190
|
-
error: error instanceof Error ? error.message : String(error)
|
|
193
|
+
error: error instanceof Error ? error.message : String(error),
|
|
191
194
|
});
|
|
192
195
|
throw error;
|
|
193
196
|
}
|
|
@@ -201,19 +204,19 @@ async function patchedCreateMethod(params, options) {
|
|
|
201
204
|
const requestId = randomUUID();
|
|
202
205
|
const startTime = Date.now();
|
|
203
206
|
const requestTime = new Date();
|
|
204
|
-
logger.debug(
|
|
207
|
+
logger.debug("Intercepted Anthropic messages.create call", {
|
|
205
208
|
requestId,
|
|
206
209
|
model: params.model,
|
|
207
210
|
hasMetadata: !!params.usageMetadata,
|
|
208
|
-
isStreaming: !!params.stream
|
|
211
|
+
isStreaming: !!params.stream,
|
|
209
212
|
});
|
|
210
213
|
// Validate parameters
|
|
211
214
|
const validation = validateAnthropicMessageParams(params);
|
|
212
215
|
if (!validation.isValid) {
|
|
213
|
-
logger.warn(
|
|
216
|
+
logger.warn("Invalid Anthropic parameters detected", {
|
|
214
217
|
requestId,
|
|
215
218
|
errors: validation.errors,
|
|
216
|
-
warnings: validation.warnings
|
|
219
|
+
warnings: validation.warnings,
|
|
217
220
|
});
|
|
218
221
|
}
|
|
219
222
|
// Extract and validate metadata
|
|
@@ -224,7 +227,7 @@ async function patchedCreateMethod(params, options) {
|
|
|
224
227
|
// Call original method
|
|
225
228
|
const originalCreate = patchingContext.originalMethods.create;
|
|
226
229
|
if (!originalCreate)
|
|
227
|
-
throw new RequestProcessingError(
|
|
230
|
+
throw new RequestProcessingError("Original create method not available");
|
|
228
231
|
const response = await originalCreate.call(this, cleanParams, options);
|
|
229
232
|
// Check if this is a streaming response
|
|
230
233
|
const isStreaming = !!params.stream;
|
|
@@ -247,16 +250,17 @@ async function patchedCreateMethod(params, options) {
|
|
|
247
250
|
stopReason: usage.stopReason,
|
|
248
251
|
metadata,
|
|
249
252
|
requestTime,
|
|
250
|
-
responseTime
|
|
253
|
+
responseTime,
|
|
254
|
+
requestBody: params,
|
|
251
255
|
};
|
|
252
256
|
// Track usage asynchronously
|
|
253
257
|
trackUsageAsync(trackingData);
|
|
254
|
-
logger.debug(
|
|
258
|
+
logger.debug("Anthropic request completed successfully", {
|
|
255
259
|
requestId,
|
|
256
260
|
model: params.model,
|
|
257
261
|
inputTokens: usage.inputTokens,
|
|
258
262
|
outputTokens: usage.outputTokens,
|
|
259
|
-
duration
|
|
263
|
+
duration,
|
|
260
264
|
});
|
|
261
265
|
return response;
|
|
262
266
|
}
|
|
@@ -266,7 +270,8 @@ async function patchedCreateMethod(params, options) {
|
|
|
266
270
|
model: params.model,
|
|
267
271
|
metadata,
|
|
268
272
|
requestTime,
|
|
269
|
-
startTime
|
|
273
|
+
startTime,
|
|
274
|
+
requestBody: params,
|
|
270
275
|
});
|
|
271
276
|
}
|
|
272
277
|
catch (error) {
|
|
@@ -291,18 +296,18 @@ async function* patchedStreamMethod(params, options) {
|
|
|
291
296
|
const responseTime = new Date();
|
|
292
297
|
const chunks = [];
|
|
293
298
|
let firstTokenTime;
|
|
294
|
-
logger.debug(
|
|
299
|
+
logger.debug("Intercepted Anthropic messages.stream call", {
|
|
295
300
|
requestId,
|
|
296
301
|
model: params.model,
|
|
297
|
-
hasMetadata: !!params.usageMetadata
|
|
302
|
+
hasMetadata: !!params.usageMetadata,
|
|
298
303
|
});
|
|
299
304
|
// Validate parameters
|
|
300
305
|
const validation = validateAnthropicMessageParams(params);
|
|
301
306
|
if (!validation.isValid) {
|
|
302
|
-
logger.warn(
|
|
307
|
+
logger.warn("Invalid Anthropic streaming parameters detected", {
|
|
303
308
|
requestId,
|
|
304
309
|
errors: validation.errors,
|
|
305
|
-
warnings: validation.warnings
|
|
310
|
+
warnings: validation.warnings,
|
|
306
311
|
});
|
|
307
312
|
}
|
|
308
313
|
// Extract and validate metadata
|
|
@@ -313,12 +318,12 @@ async function* patchedStreamMethod(params, options) {
|
|
|
313
318
|
// Call original stream method
|
|
314
319
|
const originalStream = patchingContext.originalMethods?.stream;
|
|
315
320
|
if (!originalStream) {
|
|
316
|
-
throw new StreamProcessingError(
|
|
321
|
+
throw new StreamProcessingError("Original stream method not available");
|
|
317
322
|
}
|
|
318
323
|
const stream = originalStream.call(this, cleanParams, options);
|
|
319
324
|
for await (const chunk of stream) {
|
|
320
325
|
// Track first token time
|
|
321
|
-
if (!firstTokenTime && chunk.type ===
|
|
326
|
+
if (!firstTokenTime && chunk.type === "content_block_delta") {
|
|
322
327
|
firstTokenTime = Date.now();
|
|
323
328
|
}
|
|
324
329
|
chunks.push(chunk);
|
|
@@ -326,7 +331,9 @@ async function* patchedStreamMethod(params, options) {
|
|
|
326
331
|
}
|
|
327
332
|
const endTime = Date.now();
|
|
328
333
|
const duration = endTime - startTime;
|
|
329
|
-
const timeToFirstToken = firstTokenTime
|
|
334
|
+
const timeToFirstToken = firstTokenTime
|
|
335
|
+
? firstTokenTime - startTime
|
|
336
|
+
: undefined;
|
|
330
337
|
// Extract usage information from all chunks
|
|
331
338
|
const usage = extractUsageFromStream(chunks);
|
|
332
339
|
// Create tracking data
|
|
@@ -343,18 +350,19 @@ async function* patchedStreamMethod(params, options) {
|
|
|
343
350
|
metadata,
|
|
344
351
|
requestTime,
|
|
345
352
|
responseTime,
|
|
346
|
-
timeToFirstToken
|
|
353
|
+
timeToFirstToken,
|
|
354
|
+
requestBody: params,
|
|
347
355
|
};
|
|
348
356
|
// Track usage asynchronously
|
|
349
357
|
trackUsageAsync(trackingData);
|
|
350
|
-
logger.debug(
|
|
358
|
+
logger.debug("Anthropic streaming request completed successfully", {
|
|
351
359
|
requestId,
|
|
352
360
|
model: params.model,
|
|
353
361
|
inputTokens: usage.inputTokens,
|
|
354
362
|
outputTokens: usage.outputTokens,
|
|
355
363
|
duration,
|
|
356
364
|
timeToFirstToken,
|
|
357
|
-
chunkCount: chunks.length
|
|
365
|
+
chunkCount: chunks.length,
|
|
358
366
|
});
|
|
359
367
|
}
|
|
360
368
|
catch (error) {
|
|
@@ -364,8 +372,8 @@ async function* patchedStreamMethod(params, options) {
|
|
|
364
372
|
.withRequestId(requestId)
|
|
365
373
|
.withModel(params.model)
|
|
366
374
|
.withDuration(duration)
|
|
367
|
-
.with(
|
|
368
|
-
.with(
|
|
375
|
+
.with("isStreaming", true)
|
|
376
|
+
.with("chunkCount", chunks.length)
|
|
369
377
|
.build();
|
|
370
378
|
handleError(error, logger, errorContext);
|
|
371
379
|
throw error;
|
package/dist/types/config.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare function validateConfig(config: ReveniumConfig): void;
|
|
|
13
13
|
export declare function getConfig(): ReveniumConfig | null;
|
|
14
14
|
/**
|
|
15
15
|
* Set the global configuration
|
|
16
|
+
* Uses the normalized config from validation (with defaults applied and fields trimmed)
|
|
16
17
|
*/
|
|
17
18
|
export declare function setConfig(config: ReveniumConfig): void;
|
|
18
19
|
/**
|
|
@@ -109,6 +109,21 @@ export declare const ENV_VARS: {
|
|
|
109
109
|
readonly FAIL_SILENT: "REVENIUM_FAIL_SILENT";
|
|
110
110
|
/** Maximum retries */
|
|
111
111
|
readonly MAX_RETRIES: "REVENIUM_MAX_RETRIES";
|
|
112
|
+
/** Print summary mode (true/false/human/json) */
|
|
113
|
+
readonly PRINT_SUMMARY: "REVENIUM_PRINT_SUMMARY";
|
|
114
|
+
/** Team ID for cost metrics retrieval */
|
|
115
|
+
readonly TEAM_ID: "REVENIUM_TEAM_ID";
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Summary printer configuration
|
|
119
|
+
*/
|
|
120
|
+
export declare const SUMMARY_PRINTER_CONFIG: {
|
|
121
|
+
/** Maximum number of retries when fetching cost metrics */
|
|
122
|
+
readonly MAX_RETRIES: 3;
|
|
123
|
+
/** Delay between retries in milliseconds */
|
|
124
|
+
readonly RETRY_DELAY: 2000;
|
|
125
|
+
/** Fetch timeout in milliseconds (prevents hung requests from keeping Node process alive) */
|
|
126
|
+
readonly FETCH_TIMEOUT: 10000;
|
|
112
127
|
};
|
|
113
128
|
/**
|
|
114
129
|
* API endpoints
|
|
@@ -18,68 +18,6 @@
|
|
|
18
18
|
* - **Automatic Validation**: TypeScript validates the structure at compile time
|
|
19
19
|
* - **Better Developer Experience**: Auto-completion and error detection
|
|
20
20
|
*
|
|
21
|
-
* ## Usage Examples:
|
|
22
|
-
*
|
|
23
|
-
* ### Basic Usage:
|
|
24
|
-
* ```typescript
|
|
25
|
-
* import '@revenium/anthropic';
|
|
26
|
-
* import Anthropic from '@anthropic-ai/sdk';
|
|
27
|
-
*
|
|
28
|
-
* const anthropic = new Anthropic();
|
|
29
|
-
*
|
|
30
|
-
* const response = await anthropic.messages.create({
|
|
31
|
-
* model: 'claude-3-5-sonnet-latest',
|
|
32
|
-
* max_tokens: 1024,
|
|
33
|
-
* messages: [{ role: 'user', content: 'Hello!' }],
|
|
34
|
-
* usageMetadata: { // TypeScript recognizes this natively
|
|
35
|
-
* subscriber: { id: 'user-123', email: 'user@example.com' },
|
|
36
|
-
* organizationId: 'my-company',
|
|
37
|
-
* taskType: 'customer-support',
|
|
38
|
-
* traceId: 'session-abc-123'
|
|
39
|
-
* }
|
|
40
|
-
* });
|
|
41
|
-
* ```
|
|
42
|
-
*
|
|
43
|
-
* ### Streaming Usage:
|
|
44
|
-
* ```typescript
|
|
45
|
-
* const stream = await anthropic.messages.stream({
|
|
46
|
-
* model: 'claude-3-5-sonnet-latest',
|
|
47
|
-
* max_tokens: 1024,
|
|
48
|
-
* messages: [{ role: 'user', content: 'Generate a report' }],
|
|
49
|
-
* usageMetadata: {
|
|
50
|
-
* taskType: 'content-generation',
|
|
51
|
-
* productId: 'report-generator',
|
|
52
|
-
* responseQualityScore: 0.95
|
|
53
|
-
* }
|
|
54
|
-
* });
|
|
55
|
-
* ```
|
|
56
|
-
*
|
|
57
|
-
* ### Advanced Usage with All Fields:
|
|
58
|
-
* ```typescript
|
|
59
|
-
* const response = await anthropic.messages.create({
|
|
60
|
-
* model: 'claude-3-5-sonnet-latest',
|
|
61
|
-
* max_tokens: 2048,
|
|
62
|
-
* messages: [{ role: 'user', content: 'Complex analysis task' }],
|
|
63
|
-
* usageMetadata: {
|
|
64
|
-
* subscriber: {
|
|
65
|
-
* id: 'user-456',
|
|
66
|
-
* email: 'analyst@company.com',
|
|
67
|
-
* credential: { name: 'api-key', value: 'sk-...' }
|
|
68
|
-
* },
|
|
69
|
-
* traceId: 'analysis-session-789',
|
|
70
|
-
* taskType: 'data-analysis',
|
|
71
|
-
* organizationId: 'enterprise-client',
|
|
72
|
-
* subscriptionId: 'premium-plan',
|
|
73
|
-
* productId: 'analytics-suite',
|
|
74
|
-
* agent: 'data-analyst-bot',
|
|
75
|
-
* responseQualityScore: 0.98,
|
|
76
|
-
* customField: 'custom-value' // Extensible with custom fields
|
|
77
|
-
* }
|
|
78
|
-
* });
|
|
79
|
-
* ```
|
|
80
|
-
*
|
|
81
|
-
* @public
|
|
82
|
-
* @since 1.1.0
|
|
83
21
|
*/
|
|
84
22
|
import { UsageMetadata } from "../types";
|
|
85
23
|
export {};
|
|
@@ -109,36 +47,6 @@ declare module "@anthropic-ai/sdk/resources/messages" {
|
|
|
109
47
|
* - **Multi-tenancy**: Organize usage by organizationId
|
|
110
48
|
* - **Quality Monitoring**: Track response quality scores
|
|
111
49
|
* - **Custom Analytics**: Add custom fields for specific business needs
|
|
112
|
-
*
|
|
113
|
-
* @example Basic user tracking
|
|
114
|
-
* ```typescript
|
|
115
|
-
* usageMetadata: {
|
|
116
|
-
* subscriber: { id: 'user-123', email: 'user@example.com' },
|
|
117
|
-
* organizationId: 'my-company'
|
|
118
|
-
* }
|
|
119
|
-
* ```
|
|
120
|
-
*
|
|
121
|
-
* @example Session and task tracking
|
|
122
|
-
* ```typescript
|
|
123
|
-
* usageMetadata: {
|
|
124
|
-
* traceId: 'session-abc-123',
|
|
125
|
-
* taskType: 'customer-support',
|
|
126
|
-
* productId: 'help-desk'
|
|
127
|
-
* }
|
|
128
|
-
* ```
|
|
129
|
-
*
|
|
130
|
-
* @example Advanced analytics
|
|
131
|
-
* ```typescript
|
|
132
|
-
* usageMetadata: {
|
|
133
|
-
* subscriber: { id: 'user-456' },
|
|
134
|
-
* taskType: 'content-generation',
|
|
135
|
-
* responseQualityScore: 0.95,
|
|
136
|
-
* customMetric: 'high-priority'
|
|
137
|
-
* }
|
|
138
|
-
* ```
|
|
139
|
-
*
|
|
140
|
-
* @public
|
|
141
|
-
* @since 1.1.0
|
|
142
50
|
*/
|
|
143
51
|
usageMetadata?: UsageMetadata;
|
|
144
52
|
}
|