@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.
@@ -3,15 +3,6 @@
3
3
  */
4
4
  /**
5
5
  * Credential information for subscriber authentication
6
- *
7
- * @public
8
- * @example
9
- * ```typescript
10
- * const credential: Credential = {
11
- * name: 'api-key',
12
- * value: 'sk-1234567890abcdef'
13
- * };
14
- * ```
15
6
  */
16
7
  export interface Credential {
17
8
  /** The name/type of the credential (e.g., 'api-key', 'token', 'bearer') */
@@ -22,19 +13,6 @@ export interface Credential {
22
13
  /**
23
14
  * Subscriber information for Revenium API
24
15
  * All fields are optional to allow flexible usage
25
- *
26
- * @public
27
- * @example
28
- * ```typescript
29
- * const subscriber: Subscriber = {
30
- * id: 'user-123',
31
- * email: 'user@example.com',
32
- * credential: {
33
- * name: 'api-key',
34
- * value: 'sk-1234567890abcdef'
35
- * }
36
- * };
37
- * ```
38
16
  */
39
17
  export interface Subscriber {
40
18
  /** Unique identifier for the subscriber */
@@ -46,19 +24,6 @@ export interface Subscriber {
46
24
  }
47
25
  /**
48
26
  * Revenium configuration interface
49
- *
50
- * @public
51
- * @example
52
- * ```typescript
53
- * const config: ReveniumConfig = {
54
- * reveniumApiKey: 'hak_your_key_value_here',
55
- * reveniumBaseUrl: 'https://api.revenium.ai',
56
- * anthropicApiKey: 'sk-ant-your_api_key_here',
57
- * apiTimeout: 8000,
58
- * failSilent: true,
59
- * maxRetries: 3
60
- * };
61
- * ```
62
27
  */
63
28
  export interface ReveniumConfig {
64
29
  /** Revenium API key (starts with hak_) - required for tracking */
@@ -73,25 +38,18 @@ export interface ReveniumConfig {
73
38
  failSilent?: boolean;
74
39
  /** Maximum retries for failed Revenium API calls (default: 3) */
75
40
  maxRetries?: number;
41
+ /**
42
+ * Enable cost/metrics summary output to terminal after each API request.
43
+ * - true or 'human': Human-readable format with emojis
44
+ * - 'json': JSON format for automation
45
+ * - false: Disabled (default)
46
+ */
47
+ printSummary?: boolean | SummaryFormat;
48
+ /** Revenium team ID for fetching cost metrics from the API. If not provided, the summary will still be printed but without cost information. */
49
+ teamId?: string;
76
50
  }
77
51
  /**
78
52
  * Usage metadata for enhanced tracking and analytics
79
- *
80
- * @public
81
- * @example
82
- * ```typescript
83
- * const metadata: UsageMetadata = {
84
- * subscriber: {
85
- * id: 'user-123',
86
- * email: 'user@example.com'
87
- * },
88
- * traceId: 'trace-abc-123',
89
- * taskType: 'customer-support',
90
- * organizationId: 'org-456',
91
- * productId: 'chat-assistant',
92
- * responseQualityScore: 0.95
93
- * };
94
- * ```
95
53
  */
96
54
  export interface UsageMetadata {
97
55
  /** User identification information with nested structure for detailed tracking */
@@ -115,17 +73,6 @@ export interface UsageMetadata {
115
73
  }
116
74
  /**
117
75
  * Logger interface for consistent logging across the middleware
118
- *
119
- * @public
120
- * @example
121
- * ```typescript
122
- * const customLogger: Logger = {
123
- * debug: (msg, ctx) => console.debug(`[DEBUG] ${msg}`, ctx),
124
- * info: (msg, ctx) => console.info(`[INFO] ${msg}`, ctx),
125
- * warn: (msg, ctx) => console.warn(`[WARN] ${msg}`, ctx),
126
- * error: (msg, ctx) => console.error(`[ERROR] ${msg}`, ctx)
127
- * };
128
- * ```
129
76
  */
130
77
  export interface Logger {
131
78
  /** Log debug messages (only shown when debug mode is enabled) */
@@ -139,18 +86,6 @@ export interface Logger {
139
86
  }
140
87
  /**
141
88
  * Middleware status and health information
142
- *
143
- * @public
144
- * @example
145
- * ```typescript
146
- * const status: MiddlewareStatus = {
147
- * initialized: true,
148
- * patched: true,
149
- * hasConfig: true,
150
- * anthropicVersion: '0.55.1',
151
- * circuitBreakerState: 'CLOSED'
152
- * };
153
- * ```
154
89
  */
155
90
  export interface MiddlewareStatus {
156
91
  /** Whether the middleware has been successfully initialized */
@@ -166,22 +101,6 @@ export interface MiddlewareStatus {
166
101
  }
167
102
  /**
168
103
  * Tracking data structure for manual usage reporting to Revenium API
169
- *
170
- * @public
171
- * @example
172
- * ```typescript
173
- * const trackingData: TrackingData = {
174
- * requestId: 'req-123',
175
- * model: 'claude-3-5-sonnet-latest',
176
- * inputTokens: 150,
177
- * outputTokens: 75,
178
- * duration: 1250,
179
- * isStreamed: false,
180
- * stopReason: 'end_turn',
181
- * requestTime: new Date('2024-01-01T10:00:00Z'),
182
- * responseTime: new Date('2024-01-01T10:00:01Z')
183
- * };
184
- * ```
185
104
  */
186
105
  export interface TrackingData {
187
106
  /** Unique identifier for the API request */
@@ -210,32 +129,12 @@ export interface TrackingData {
210
129
  responseTime: Date;
211
130
  /** Time to first token in milliseconds (for streaming responses) */
212
131
  timeToFirstToken?: number;
132
+ /** Request body containing Anthropic message parameters */
133
+ requestBody?: AnthropicMessageParams;
213
134
  }
214
135
  /**
215
136
  * Internal payload structure for Revenium API
216
137
  * This interface represents the exact format expected by Revenium's tracking endpoint
217
- *
218
- * @internal
219
- * @example
220
- * ```typescript
221
- * const payload: ReveniumPayload = {
222
- * stopReason: 'end_turn',
223
- * costType: 'AI',
224
- * isStreamed: false,
225
- * operationType: 'CHAT',
226
- * inputTokenCount: 150,
227
- * outputTokenCount: 75,
228
- * reasoningTokenCount: 0,
229
- * cacheCreationTokenCount: 0,
230
- * cacheReadTokenCount: 0,
231
- * totalTokenCount: 225,
232
- * model: 'claude-3-5-sonnet-latest',
233
- * transactionId: 'txn-123',
234
- * responseTime: '2024-01-01T10:00:01.000Z',
235
- * requestDuration: 1250,
236
- * provider: 'anthropic'
237
- * };
238
- * ```
239
138
  */
240
139
  export interface ReveniumPayload {
241
140
  /** Reason why the AI completion stopped */
@@ -292,17 +191,22 @@ export interface ReveniumPayload {
292
191
  responseQualityScore?: number;
293
192
  /** Source identifier for the middleware */
294
193
  middlewareSource: string;
194
+ environment?: string;
195
+ operationSubtype?: string;
196
+ retryNumber?: number;
197
+ parentTransactionId?: string;
198
+ transactionName?: string;
199
+ region?: string;
200
+ credentialAlias?: string;
201
+ traceType?: string;
202
+ traceName?: string;
295
203
  }
296
204
  /**
297
205
  * Anthropic content block types for message validation
298
206
  * These interfaces match Anthropic's API specification for different content types
299
- *
300
- * @public
301
207
  */
302
208
  /**
303
209
  * Text content block for Anthropic messages
304
- *
305
- * @public
306
210
  */
307
211
  export interface AnthropicTextContent {
308
212
  /** Content type identifier */
@@ -312,8 +216,6 @@ export interface AnthropicTextContent {
312
216
  }
313
217
  /**
314
218
  * Image content block for Anthropic messages
315
- *
316
- * @public
317
219
  */
318
220
  export interface AnthropicImageContent {
319
221
  /** Content type identifier */
@@ -330,8 +232,6 @@ export interface AnthropicImageContent {
330
232
  }
331
233
  /**
332
234
  * Tool use content block for Anthropic messages
333
- *
334
- * @public
335
235
  */
336
236
  export interface AnthropicToolUseContent {
337
237
  /** Content type identifier */
@@ -345,8 +245,6 @@ export interface AnthropicToolUseContent {
345
245
  }
346
246
  /**
347
247
  * Tool result content block for Anthropic messages
348
- *
349
- * @public
350
248
  */
351
249
  export interface AnthropicToolResultContent {
352
250
  /** Content type identifier */
@@ -360,21 +258,10 @@ export interface AnthropicToolResultContent {
360
258
  }
361
259
  /**
362
260
  * Union type for all possible Anthropic content blocks
363
- *
364
- * @public
365
261
  */
366
262
  export type AnthropicContentBlock = AnthropicTextContent | AnthropicImageContent | AnthropicToolUseContent | AnthropicToolResultContent;
367
263
  /**
368
264
  * Anthropic message structure for validation
369
- *
370
- * @public
371
- * @example
372
- * ```typescript
373
- * const message: AnthropicMessage = {
374
- * role: 'user',
375
- * content: 'Hello, how can you help me today?'
376
- * };
377
- * ```
378
265
  */
379
266
  export interface AnthropicMessage {
380
267
  /** Role of the message sender */
@@ -384,25 +271,6 @@ export interface AnthropicMessage {
384
271
  }
385
272
  /**
386
273
  * Anthropic tool definition for function calling
387
- *
388
- * @public
389
- * @example
390
- * ```typescript
391
- * const tool: AnthropicTool = {
392
- * name: 'get_weather',
393
- * description: 'Get current weather for a location',
394
- * input_schema: {
395
- * type: 'object',
396
- * properties: {
397
- * location: {
398
- * type: 'string',
399
- * description: 'City name'
400
- * }
401
- * },
402
- * required: ['location']
403
- * }
404
- * };
405
- * ```
406
274
  */
407
275
  export interface AnthropicTool {
408
276
  /** Name of the tool function */
@@ -432,15 +300,6 @@ export interface AnthropicTool {
432
300
  }
433
301
  /**
434
302
  * Anthropic tool choice configuration for controlling tool usage
435
- *
436
- * @public
437
- * @example
438
- * ```typescript
439
- * const toolChoice: AnthropicToolChoice = {
440
- * type: 'tool',
441
- * name: 'get_weather'
442
- * };
443
- * ```
444
303
  */
445
304
  export interface AnthropicToolChoice {
446
305
  /** How the model should choose tools ('auto', 'any', or 'tool') */
@@ -451,20 +310,6 @@ export interface AnthropicToolChoice {
451
310
  /**
452
311
  * Anthropic message creation parameters
453
312
  * Complete interface for all parameters supported by Anthropic's messages API
454
- *
455
- * @public
456
- * @example
457
- * ```typescript
458
- * const params: AnthropicMessageParams = {
459
- * model: 'claude-3-5-sonnet-latest',
460
- * messages: [{ role: 'user', content: 'Hello!' }],
461
- * max_tokens: 1024,
462
- * temperature: 0.7,
463
- * usageMetadata: {
464
- * subscriber: { id: 'user-123' }
465
- * }
466
- * };
467
- * ```
468
313
  */
469
314
  export interface AnthropicMessageParams {
470
315
  /** AI model to use (e.g., 'claude-3-5-sonnet-latest') */
@@ -556,17 +401,6 @@ export interface AnthropicStreamChunk {
556
401
  }
557
402
  /**
558
403
  * Configuration validation result with detailed feedback
559
- *
560
- * @public
561
- * @example
562
- * ```typescript
563
- * const result: ConfigValidationResult = {
564
- * isValid: false,
565
- * errors: ['Missing reveniumApiKey'],
566
- * warnings: ['apiTimeout is very high'],
567
- * suggestions: ['Set REVENIUM_METERING_API_KEY environment variable']
568
- * };
569
- * ```
570
404
  */
571
405
  export interface ConfigValidationResult {
572
406
  /** Whether the configuration is valid and ready to use */
@@ -582,16 +416,6 @@ export interface ConfigValidationResult {
582
416
  }
583
417
  /**
584
418
  * Request validation result for API call validation
585
- *
586
- * @public
587
- * @example
588
- * ```typescript
589
- * const result: RequestValidationResult = {
590
- * isValid: true,
591
- * errors: [],
592
- * warnings: ['Large message count may impact performance']
593
- * };
594
- * ```
595
419
  */
596
420
  export interface RequestValidationResult {
597
421
  /** Whether the request parameters are valid */
@@ -643,5 +467,13 @@ export interface EnvironmentConfig {
643
467
  apiTimeout?: string;
644
468
  failSilent?: string;
645
469
  maxRetries?: string;
470
+ printSummary?: string;
471
+ teamId?: string;
646
472
  }
473
+ /**
474
+ * Summary output format options
475
+ * - 'human': Human-readable formatted output with emojis (default when enabled)
476
+ * - 'json': JSON formatted output for automation/parsing
477
+ */
478
+ export type SummaryFormat = "human" | "json";
647
479
  //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { ReveniumPayload } from "../types";
2
+ export declare function printUsageSummary(payload: ReveniumPayload): void;
3
+ //# sourceMappingURL=summary-printer.d.ts.map
@@ -0,0 +1,10 @@
1
+ export declare function getEnvironment(): string | null;
2
+ export declare function getRegion(): Promise<string | null>;
3
+ export declare function getCredentialAlias(): string | null;
4
+ export declare function getTraceType(): string | null;
5
+ export declare function getTraceName(): string | null;
6
+ export declare function detectOperationSubtype(requestBody?: any): string | null;
7
+ export declare function getParentTransactionId(): string | null;
8
+ export declare function getTransactionName(): string | null;
9
+ export declare function getRetryNumber(): number;
10
+ //# sourceMappingURL=trace-fields.d.ts.map
@@ -0,0 +1,128 @@
1
+ import "dotenv/config";
2
+ import "@revenium/anthropic";
3
+ import Anthropic from "@anthropic-ai/sdk";
4
+ import type { UsageMetadata, TrackingData } from "@revenium/anthropic";
5
+ import { trackUsageAsync, getStatus } from "@revenium/anthropic";
6
+
7
+ async function main() {
8
+ await streamingWithMetadata();
9
+ await toolUsage();
10
+ await manualTracking();
11
+ }
12
+
13
+ const streamingWithMetadata = async () => {
14
+ console.log("Revenium Anthropic Middleware - Streaming Example\n");
15
+ const anthropic = new Anthropic();
16
+
17
+ try {
18
+ const metadata: UsageMetadata = {
19
+ subscriber: { id: "user-123", email: "user@example.com" },
20
+ organizationId: "my-org",
21
+ productId: "my-product",
22
+ taskType: "streaming-demo",
23
+ traceId: `session_${Date.now()}`,
24
+ };
25
+
26
+ const stream = await anthropic.messages.create({
27
+ model: "claude-haiku-4-5",
28
+ max_tokens: 100,
29
+ messages: [{ role: "user", content: "Write a haiku about coding." }],
30
+ stream: true,
31
+ usageMetadata: metadata,
32
+ });
33
+
34
+ console.log("Response:");
35
+ for await (const event of stream) {
36
+ if (
37
+ event.type === "content_block_delta" &&
38
+ event.delta.type === "text_delta"
39
+ ) {
40
+ process.stdout.write(event.delta.text);
41
+ }
42
+ }
43
+ console.log("\n");
44
+ } catch (error) {
45
+ console.error("Error:", error);
46
+ }
47
+ };
48
+
49
+ const toolUsage = async () => {
50
+ console.log("Revenium Anthropic Middleware - Tool Usage Example\n");
51
+ const anthropic = new Anthropic();
52
+
53
+ try {
54
+ const response = await anthropic.messages.create({
55
+ model: "claude-haiku-4-5",
56
+ max_tokens: 200,
57
+ tools: [
58
+ {
59
+ name: "get_weather",
60
+ description: "Get weather for a location",
61
+ input_schema: {
62
+ type: "object",
63
+ properties: {
64
+ location: { type: "string", description: "City name" },
65
+ },
66
+ required: ["location"],
67
+ },
68
+ },
69
+ ],
70
+ messages: [{ role: "user", content: "What's the weather in Tokyo?" }],
71
+ usageMetadata: {
72
+ subscriber: { id: "tool-user" },
73
+ taskType: "tool-demo",
74
+ },
75
+ });
76
+
77
+ for (const block of response.content) {
78
+ if (block.type === "tool_use") {
79
+ console.log(`Tool called: ${block.name}`);
80
+ console.log(`Input: ${JSON.stringify(block.input)}\n`);
81
+ }
82
+ }
83
+ } catch (error) {
84
+ console.error("Error:", error);
85
+ }
86
+ };
87
+
88
+ const manualTracking = async () => {
89
+ console.log("Revenium Anthropic Middleware - Manual Tracking Example\n");
90
+
91
+ try {
92
+ const now = new Date();
93
+ const trackingData: TrackingData = {
94
+ requestId: `manual_${Date.now()}`,
95
+ model: "claude-haiku-4-5",
96
+ inputTokens: 25,
97
+ outputTokens: 150,
98
+ duration: 2500,
99
+ isStreamed: false,
100
+ requestTime: new Date(now.getTime() - 2500),
101
+ responseTime: now,
102
+ metadata: {
103
+ subscriber: { id: "manual-user" },
104
+ organizationId: "manual-org",
105
+ taskType: "manual-tracking",
106
+ },
107
+ };
108
+
109
+ trackUsageAsync(trackingData);
110
+ console.log("Manual tracking sent successfully");
111
+ console.log(
112
+ `Tracked: ${
113
+ trackingData.inputTokens + trackingData.outputTokens
114
+ } tokens\n`
115
+ );
116
+
117
+ const status = getStatus();
118
+ console.log("Middleware Status:", {
119
+ initialized: status.initialized,
120
+ patched: status.patched,
121
+ hasConfig: status.hasConfig,
122
+ });
123
+ } catch (error) {
124
+ console.error("Error:", error);
125
+ }
126
+ };
127
+
128
+ main().catch(console.error);
@@ -0,0 +1,132 @@
1
+ import "dotenv/config";
2
+ import "@revenium/anthropic";
3
+ import Anthropic from "@anthropic-ai/sdk";
4
+ import {
5
+ configure,
6
+ getConfig,
7
+ getStatus,
8
+ initialize,
9
+ } from "@revenium/anthropic";
10
+
11
+ async function main() {
12
+ await basicUsage();
13
+ await explicitInitialization();
14
+ await manualConfiguration();
15
+ }
16
+
17
+ const basicUsage = async () => {
18
+ console.log("Revenium Anthropic Middleware - Basic Example\n");
19
+ const anthropic = new Anthropic();
20
+ try {
21
+ const response = await anthropic.messages.create({
22
+ model: "claude-haiku-4-5",
23
+ max_tokens: 50,
24
+ messages: [
25
+ { role: "user", content: "What is the capital of France? Be concise." },
26
+ ],
27
+ });
28
+
29
+ const textResponse =
30
+ response.content[0].type === "text"
31
+ ? response.content[0].text
32
+ : "Non-text response";
33
+ console.log("RESPONSE: \n", textResponse);
34
+ console.log(
35
+ `Tokens: ${response.usage?.input_tokens} input + ${response.usage?.output_tokens} output\n`
36
+ );
37
+ } catch (error) {
38
+ console.error("Error: ", error);
39
+ }
40
+ };
41
+
42
+ const explicitInitialization = async () => {
43
+ console.log(
44
+ "Revenium Anthropic Middleware - Explicit Initialization Example\n"
45
+ );
46
+ try {
47
+ initialize();
48
+ const status = getStatus();
49
+ console.log("Middleware status:", {
50
+ initialized: status.initialized,
51
+ patched: status.patched,
52
+ hasConfig: status.hasConfig,
53
+ });
54
+
55
+ const anthropic = new Anthropic();
56
+ const response = await anthropic.messages.create({
57
+ model: "claude-haiku-4-5",
58
+ max_tokens: 50,
59
+ messages: [
60
+ {
61
+ role: "user",
62
+ content: "What are the benefits of explicit initialization?",
63
+ },
64
+ ],
65
+ });
66
+ const textResponse =
67
+ response.content[0].type === "text"
68
+ ? response.content[0].text
69
+ : "Non-text response";
70
+ console.log("RESPONSE: \n", textResponse);
71
+ console.log(
72
+ `Tokens: ${response.usage?.input_tokens} input + ${response.usage?.output_tokens} output\n`
73
+ );
74
+ } catch (error) {
75
+ console.error("Error: ", error);
76
+ }
77
+ };
78
+
79
+ const manualConfiguration = async () => {
80
+ console.log("Revenium Anthropic Middleware - Manual Configuration Example\n");
81
+ try {
82
+ // Manual configuration with all options
83
+ configure({
84
+ // Required: Revenium API configuration
85
+ reveniumApiKey:
86
+ process.env.REVENIUM_METERING_API_KEY || "hak_your_api_key_here",
87
+ reveniumBaseUrl:
88
+ process.env.REVENIUM_METERING_BASE_URL || "https://api.revenium.ai",
89
+
90
+ // Optional: Anthropic API key (can also be set in Anthropic client)
91
+ anthropicApiKey: process.env.ANTHROPIC_API_KEY,
92
+
93
+ // Optional: Performance and reliability settings
94
+ apiTimeout: 8000, // 8 second timeout (default: 5000)
95
+ maxRetries: 5, // 5 retry attempts (default: 3)
96
+ failSilent: false, // Throw errors instead of silent failure (default: true)
97
+ });
98
+
99
+ // Verify configuration
100
+ const config = getConfig();
101
+ console.log("Configuration:", {
102
+ hasReveniumKey: !!config?.reveniumApiKey,
103
+ baseUrl: config?.reveniumBaseUrl,
104
+ timeout: config?.apiTimeout,
105
+ maxRetries: config?.maxRetries,
106
+ });
107
+
108
+ const anthropic = new Anthropic({
109
+ apiKey: process.env.ANTHROPIC_API_KEY || "sk-ant-your_anthropic_key_here",
110
+ });
111
+ const response = await anthropic.messages.create({
112
+ model: "claude-haiku-4-5",
113
+ max_tokens: 50,
114
+ messages: [
115
+ {
116
+ role: "user",
117
+ content:
118
+ "What are the advantages of manual configuration in enterprise software?",
119
+ },
120
+ ],
121
+ });
122
+ const textResponse =
123
+ response.content[0].type === "text"
124
+ ? response.content[0].text
125
+ : "Non-text response";
126
+ console.log("RESPONSE: \n", textResponse);
127
+ } catch (error) {
128
+ console.error("Error: ", error);
129
+ }
130
+ };
131
+
132
+ main().catch(console.error);
@@ -1,6 +1,6 @@
1
- import 'dotenv/config';
2
- import '@revenium/anthropic';
3
- import Anthropic from '@anthropic-ai/sdk';
1
+ import "dotenv/config";
2
+ import "@revenium/anthropic";
3
+ import Anthropic from "@anthropic-ai/sdk";
4
4
 
5
5
  async function main() {
6
6
  // Create Anthropic client
@@ -8,10 +8,10 @@ async function main() {
8
8
 
9
9
  // Chat completion with metadata
10
10
  const response = await anthropic.messages.create({
11
- model: 'claude-haiku-4-5',
11
+ model: "claude-haiku-4-5",
12
12
  max_tokens: 2000,
13
13
  messages: [
14
- { role: 'user', content: 'Please verify you are ready to assist me.' }
14
+ { role: "user", content: "Please verify you are ready to assist me." },
15
15
  ],
16
16
 
17
17
  /* Optional metadata for advanced reporting, lineage tracking, and cost allocation
@@ -44,7 +44,7 @@ async function main() {
44
44
  */
45
45
  });
46
46
 
47
- console.log('Response:', response.content[0]?.text);
47
+ console.log("Response:", response.content[0]?.text);
48
48
  }
49
49
 
50
50
  main().catch(console.error);