@revenium/anthropic 1.0.8 → 1.1.0

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.
@@ -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);
@@ -0,0 +1,58 @@
1
+ import "dotenv/config";
2
+ import "@revenium/anthropic";
3
+ import Anthropic from "@anthropic-ai/sdk";
4
+ import { UsageMetadata } from "@revenium/anthropic";
5
+
6
+ async function main() {
7
+ console.log("Revenium Anthropic Middleware - Metadata Example\n");
8
+ const anthropic = new Anthropic();
9
+ try {
10
+ const metadata: UsageMetadata = {
11
+ subscriber: {
12
+ id: "user-123",
13
+ email: "user@example.com",
14
+ credential: { name: "api-key", value: "key-123" },
15
+ },
16
+ traceId: "trace-123",
17
+ taskType: "task-123",
18
+ organizationId: "org-123",
19
+ subscriptionId: "sub-123",
20
+ productId: "prod-123",
21
+ agent: "agent-123",
22
+ responseQualityScore: 0.95,
23
+ };
24
+ const response = await anthropic.messages.create({
25
+ model: "claude-haiku-4-5",
26
+ max_tokens: 50,
27
+ messages: [
28
+ { role: "user", content: "What is the capital of France? Be concise." },
29
+ ],
30
+ usageMetadata: metadata,
31
+ tools: [
32
+ {
33
+ name: "get_weather",
34
+ description: "Get weather for a location",
35
+ input_schema: {
36
+ type: "object",
37
+ properties: {
38
+ location: { type: "string" },
39
+ },
40
+ },
41
+ },
42
+ ],
43
+ });
44
+
45
+ const textResponse =
46
+ response.content[0].type === "text"
47
+ ? response.content[0].text
48
+ : "Non-text response";
49
+ console.log("RESPONSE: \n", textResponse);
50
+ console.log(
51
+ `Tokens: ${response.usage?.input_tokens} input + ${response.usage?.output_tokens} output\n`
52
+ );
53
+ } catch (error) {
54
+ console.error("Error: ", error);
55
+ }
56
+ }
57
+
58
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revenium/anthropic",
3
- "version": "1.0.8",
3
+ "version": "1.1.0",
4
4
  "description": "Transparent TypeScript middleware for automatic Revenium usage tracking with Anthropic Claude AI",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -24,10 +24,9 @@
24
24
  "build:types": "tsc -p tsconfig.types.json",
25
25
  "fix-esm": "node scripts/fix-esm-imports.js",
26
26
  "dev": "tsc --watch",
27
- "test": "npm run build && echo 'Build successful - no automated tests configured'",
28
- "example": "npm run build && tsx examples/basic-usage.ts",
29
- "example:basic": "npm run build && tsx examples/basic-usage.ts",
30
- "example:advanced": "npm run build && tsx examples/advanced-features.ts",
27
+ "example": "npm run build && tsx examples/basic.ts",
28
+ "example:basic": "npm run build && tsx examples/basic.ts",
29
+ "example:advanced": "npm run build && tsx examples/advanced.ts",
31
30
  "clean": "rimraf dist",
32
31
  "prepublishOnly": "npm run clean && npm run build"
33
32
  },
@@ -75,7 +74,6 @@
75
74
  "examples/**/*",
76
75
  "!examples/.claude/**",
77
76
  "!examples/**/*.log",
78
- "!examples/**/*.sh",
79
77
  "README.md",
80
78
  "CHANGELOG.md",
81
79
  "LICENSE"
@@ -1,469 +0,0 @@
1
- /**
2
- * Revenium Anthropic Middleware - Advanced TypeScript Features Example
3
- *
4
- * This example demonstrates advanced TypeScript patterns and features:
5
- * • Streaming responses with type-safe real-time tracking
6
- * • Tool use (function calling) with strongly typed metadata
7
- * • Manual tracking for custom scenarios with full type safety
8
- * • Comprehensive error handling with typed error responses
9
- * • Generic functions with type constraints
10
- * • Advanced metadata patterns with custom fields support
11
- * • Type-safe event handling and stream processing
12
- *
13
- * All features leverage TypeScript's type system for maximum safety and IntelliSense.
14
- */
15
-
16
- // Load environment variables from .env file
17
- import "dotenv/config";
18
-
19
- // Import for module augmentation - enables native usageMetadata support
20
- import "@revenium/anthropic";
21
- import Anthropic from "@anthropic-ai/sdk";
22
-
23
- // Import types for advanced TypeScript patterns
24
- import type {
25
- UsageMetadata,
26
- TrackingData,
27
- MiddlewareStatus,
28
- Logger,
29
- } from "@revenium/anthropic";
30
-
31
- import { trackUsageAsync, getStatus, setLogger } from "@revenium/anthropic";
32
-
33
- /**
34
- * Streaming event types with full type safety
35
- */
36
- type StreamEvent =
37
- | { type: "start"; timestamp: Date; metadata: UsageMetadata }
38
- | { type: "content"; content: string; timestamp: Date }
39
- | { type: "complete"; totalTokens: number; duration: number; timestamp: Date }
40
- | { type: "error"; error: string; timestamp: Date };
41
-
42
- /**
43
- * Custom logger implementation for advanced scenarios
44
- */
45
- class AdvancedLogger implements Logger {
46
- private context: Record<string, unknown> = {};
47
-
48
- setContext(context: Record<string, unknown>): void {
49
- this.context = { ...this.context, ...context };
50
- }
51
-
52
- debug(message: string, data?: Record<string, unknown>): void {
53
- console.log(`[DEBUG] ${message}`, { ...this.context, ...data });
54
- }
55
-
56
- info(message: string, data?: Record<string, unknown>): void {
57
- console.log(`[INFO] ${message}`, { ...this.context, ...data });
58
- }
59
-
60
- warn(message: string, data?: Record<string, unknown>): void {
61
- console.warn(`[WARN] ${message}`, { ...this.context, ...data });
62
- }
63
-
64
- error(message: string, data?: Record<string, unknown>): void {
65
- console.error(`[ERROR] ${message}`, { ...this.context, ...data });
66
- }
67
- }
68
-
69
- async function demonstrateAdvancedFeatures(): Promise<void> {
70
- console.log("Revenium Anthropic Middleware - Advanced TypeScript Features\n");
71
-
72
- // Initialize custom logger with type safety
73
- const logger = new AdvancedLogger();
74
- logger.setContext({
75
- service: "advanced-features-demo",
76
- version: "1.0.0",
77
- environment: "development",
78
- });
79
- setLogger(logger);
80
-
81
- const anthropic = new Anthropic();
82
-
83
- try {
84
- // =============================================================================
85
- // ADVANCED TYPESCRIPT PATTERNS WITH STREAMING
86
- // =============================================================================
87
- console.log("Advanced TypeScript Streaming Patterns");
88
- console.log(
89
- "Type-safe streaming with event handling and metadata validation\n"
90
- );
91
-
92
- // Example 1: Type-safe streaming with advanced metadata
93
- console.log(
94
- "Example 1: Creative writing with advanced metadata patterns..."
95
- );
96
-
97
- // Create strongly typed metadata with satisfies operator
98
- const advancedMetadata: UsageMetadata = {
99
- subscriber: {
100
- id: "artist-456",
101
- email: "artist@creative-studio.com",
102
- credential: {
103
- name: "creative-api-key",
104
- value: "creative-key-789",
105
- },
106
- },
107
- organizationId: "creative-ai-studio",
108
- productId: "story-generator-pro",
109
- taskType: "creative-writing",
110
- agent: "storyteller-v2",
111
- traceId: `session_${Date.now()}`,
112
- } satisfies UsageMetadata;
113
-
114
- // Type-safe streaming with event tracking
115
- const streamEvents: StreamEvent[] = [];
116
- const startTime = new Date();
117
-
118
- streamEvents.push({
119
- type: "start",
120
- timestamp: startTime,
121
- metadata: advancedMetadata,
122
- });
123
-
124
- const stream1 = await anthropic.messages.create({
125
- model: "claude-haiku-4-5",
126
- max_tokens: 150,
127
- messages: [
128
- {
129
- role: "user",
130
- content: "Write a short story about a robot learning to paint.",
131
- },
132
- ],
133
- stream: true,
134
- usageMetadata: advancedMetadata, // Fully typed with module augmentation
135
- });
136
-
137
- console.log("Streaming response:");
138
- let content1 = "";
139
- let tokenCount = 0;
140
-
141
- for await (const event of stream1) {
142
- if (
143
- event.type === "content_block_delta" &&
144
- event.delta.type === "text_delta"
145
- ) {
146
- process.stdout.write(event.delta.text);
147
- content1 += event.delta.text;
148
- tokenCount++;
149
-
150
- // Add streaming event with type safety
151
- streamEvents.push({
152
- type: "content",
153
- content: event.delta.text,
154
- timestamp: new Date(),
155
- });
156
- }
157
- }
158
-
159
- // Complete streaming event tracking
160
- const endTime = new Date();
161
- streamEvents.push({
162
- type: "complete",
163
- totalTokens: tokenCount,
164
- duration: endTime.getTime() - startTime.getTime(),
165
- timestamp: endTime,
166
- });
167
-
168
- if (!content1.trim()) throw new Error("No content received from stream");
169
- console.log("\nStream 1 completed with type-safe event tracking");
170
- console.log(
171
- `Events captured: ${streamEvents.length}, Duration: ${
172
- endTime.getTime() - startTime.getTime()
173
- }ms\n`
174
- );
175
-
176
- // =============================================================================
177
- // ADVANCED MANUAL TRACKING WITH TYPE SAFETY
178
- // =============================================================================
179
- console.log("Advanced Manual Tracking with TypeScript");
180
- console.log(
181
- "Demonstrating manual tracking with full type safety and validation\n"
182
- );
183
-
184
- // Example 2: Manual tracking with type-safe data
185
- console.log("Example 2: Manual tracking with custom metrics...");
186
-
187
- const now = new Date();
188
- const trackingData: TrackingData = {
189
- requestId: `manual_${Date.now()}`,
190
- model: "claude-haiku-4-5",
191
- inputTokens: 25,
192
- outputTokens: 150,
193
- duration: 2500,
194
- isStreamed: false,
195
- requestTime: new Date(now.getTime() - 2500), // 2.5 seconds ago
196
- responseTime: now,
197
- metadata: {
198
- subscriber: { id: "manual-user-123" },
199
- organizationId: "manual-tracking-org",
200
- productId: "custom-analytics",
201
- taskType: "manual-analysis",
202
- } satisfies UsageMetadata,
203
- };
204
-
205
- // Type-safe manual tracking
206
- try {
207
- trackUsageAsync(trackingData); // Note: this function is synchronous
208
- console.log("Manual tracking completed successfully");
209
- console.log(
210
- `Tracked: ${
211
- trackingData.inputTokens + trackingData.outputTokens
212
- } tokens, ${trackingData.duration}ms duration\n`
213
- );
214
- } catch (error) {
215
- const errorMessage =
216
- error instanceof Error ? error.message : String(error);
217
- console.log(`Manual tracking failed: ${errorMessage}\n`);
218
- }
219
-
220
- // =============================================================================
221
- // SERVICE STATUS WITH TYPE SAFETY
222
- // =============================================================================
223
- console.log("Service Status and Health Check");
224
- console.log("Type-safe middleware status monitoring\n");
225
-
226
- const status: MiddlewareStatus = getStatus();
227
- console.log("Middleware Status:", {
228
- initialized: status.initialized,
229
- patched: status.patched,
230
- hasConfig: status.hasConfig,
231
- configValid: status.initialized && status.patched && status.hasConfig,
232
- });
233
-
234
- // Example 3: Educational content with different metadata pattern
235
- console.log(
236
- "\nExample 3: Educational content with different metadata pattern..."
237
- );
238
-
239
- const educationalMetadata: UsageMetadata = {
240
- subscriber: { id: "student-789" },
241
- organizationId: "green-tech-edu",
242
- productId: "sustainability-tutor",
243
- taskType: "educational-query",
244
- traceId: `edu_session_${Date.now()}`,
245
- } satisfies UsageMetadata;
246
-
247
- const stream2 = await anthropic.messages.create({
248
- model: "claude-haiku-4-5",
249
- max_tokens: 100,
250
- messages: [
251
- {
252
- role: "user",
253
- content: "Explain three benefits of renewable energy.",
254
- },
255
- ],
256
- stream: true,
257
- usageMetadata: educationalMetadata, // Fully typed
258
- });
259
-
260
- console.log("Educational response:");
261
- let content2 = "";
262
- for await (const event of stream2) {
263
- if (
264
- event.type === "content_block_delta" &&
265
- event.delta.type === "text_delta"
266
- ) {
267
- process.stdout.write(event.delta.text);
268
- content2 += event.delta.text;
269
- }
270
- }
271
-
272
- if (!content2.trim()) throw new Error("No content received from stream");
273
- console.log("\nStream 2 completed with educational metadata pattern\n");
274
-
275
- // =============================================================================
276
- // ADVANCED TOOL USE WITH TYPESCRIPT PATTERNS
277
- // =============================================================================
278
- console.log("Advanced Tool Use with TypeScript Patterns");
279
- console.log(
280
- "Tool usage with strongly typed metadata and comprehensive tracking\n"
281
- );
282
-
283
- console.log("Example 4: Weather tool with advanced TypeScript patterns...");
284
-
285
- // Create tool-specific metadata with type safety
286
- const toolMetadata: UsageMetadata = {
287
- subscriber: {
288
- id: "weather-user-456",
289
- email: "user@weather-app.com",
290
- },
291
- organizationId: "weather-services-inc",
292
- productId: "smart-weather-assistant",
293
- taskType: "tool-usage",
294
- agent: "weather-bot-v3",
295
- traceId: `weather_${Date.now()}`,
296
- } satisfies UsageMetadata;
297
-
298
- const toolStream = await anthropic.messages.create({
299
- model: "claude-haiku-4-5",
300
- max_tokens: 200,
301
- tools: [
302
- {
303
- name: "get_weather",
304
- description: "Get current weather for a location",
305
- input_schema: {
306
- type: "object",
307
- properties: {
308
- location: {
309
- type: "string",
310
- description: "City and state, e.g. San Francisco, CA",
311
- },
312
- units: {
313
- type: "string",
314
- enum: ["celsius", "fahrenheit"],
315
- description: "Temperature units",
316
- },
317
- },
318
- required: ["location"],
319
- },
320
- },
321
- ],
322
- messages: [
323
- {
324
- role: "user",
325
- content: "What's the weather like in New York? Use the weather tool.",
326
- },
327
- ],
328
- stream: true,
329
- usageMetadata: toolMetadata, // Using strongly typed metadata
330
- });
331
-
332
- console.log("Tool use streaming response:");
333
- let toolContent = "";
334
- for await (const event of toolStream) {
335
- if (
336
- event.type === "content_block_delta" &&
337
- event.delta.type === "text_delta"
338
- ) {
339
- process.stdout.write(event.delta.text);
340
- toolContent += event.delta.text;
341
- } else if (
342
- event.type === "content_block_start" &&
343
- event.content_block.type === "tool_use"
344
- ) {
345
- console.log(`\nTool called: ${event.content_block.name}`);
346
- }
347
- }
348
-
349
- if (!toolContent.trim())
350
- throw new Error("No content received from tool stream");
351
- console.log(
352
- "\nTool streaming completed with advanced TypeScript patterns\n"
353
- );
354
-
355
- // =============================================================================
356
- // SUMMARY AND TYPESCRIPT BENEFITS
357
- // =============================================================================
358
- console.log("Advanced TypeScript Features Summary");
359
- console.log("All examples completed successfully with full type safety!\n");
360
-
361
- console.log("TypeScript Benefits Demonstrated:");
362
- console.log(" • Module augmentation for native usageMetadata support");
363
- console.log(" • Type-safe metadata with satisfies operator");
364
- console.log(" • Strongly typed event handling and streaming");
365
- console.log(" • Custom logger implementation with typed interfaces");
366
- console.log(" • Comprehensive error handling with typed responses");
367
- console.log(" • Generic functions with type constraints");
368
- console.log(" • Full IntelliSense support throughout\n");
369
-
370
- console.log("Middleware Status Summary:");
371
- const finalStatus = getStatus();
372
- console.log(` • Initialized: ${finalStatus.initialized}`);
373
- console.log(` • Patched: ${finalStatus.patched}`);
374
- console.log(` • Has Config: ${finalStatus.hasConfig}`);
375
- console.log(
376
- ` • All Systems: ${
377
- finalStatus.initialized && finalStatus.patched && finalStatus.hasConfig
378
- ? "Operational"
379
- : "Check Configuration"
380
- }\n`
381
- );
382
-
383
- console.log("Next Steps:");
384
- console.log(" • Review comprehensive JSDoc in your IDE");
385
- console.log(
386
- " • Check the TypeScript-first examples/README.md for more patterns"
387
- );
388
- console.log(
389
- " • Implement custom metadata extensions for your use case\n"
390
- );
391
- } catch (error) {
392
- // Comprehensive TypeScript error handling
393
- const errorMessage = error instanceof Error ? error.message : String(error);
394
- console.error("Advanced TypeScript features demo failed:", errorMessage);
395
-
396
- // Type-safe error analysis
397
- if (error && typeof error === "object" && "status" in error) {
398
- const httpError = error as { status: number; message?: string };
399
- if (httpError.status >= 400) {
400
- console.error(
401
- `HTTP ${httpError.status} Error - API connectivity issue`
402
- );
403
- console.error("Check your API keys and network connectivity");
404
- }
405
- }
406
-
407
- // Log final status even on error
408
- const errorStatus = getStatus();
409
- console.error("Final Middleware Status:", {
410
- initialized: errorStatus.initialized,
411
- patched: errorStatus.patched,
412
- hasConfig: errorStatus.hasConfig,
413
- });
414
-
415
- throw error;
416
- }
417
- }
418
-
419
- /**
420
- * Type-safe environment validation
421
- */
422
- function checkEnvironment(): void {
423
- const required = ["REVENIUM_METERING_API_KEY", "ANTHROPIC_API_KEY"];
424
- const missing = required.filter((key) => !process.env[key]);
425
-
426
- if (missing.length > 0) {
427
- console.error(
428
- "Missing required environment variables for advanced TypeScript features:"
429
- );
430
- missing.forEach((key) => console.error(` • ${key}`));
431
- console.error("\nSet them in a .env file in the project root:");
432
- console.error(" REVENIUM_METERING_API_KEY=hak_your_api_key");
433
- console.error(" ANTHROPIC_API_KEY=sk-ant-your_anthropic_key");
434
- console.error("\nOptional (uses defaults if not set):");
435
- console.error(" REVENIUM_METERING_BASE_URL=https://api.revenium.ai");
436
- console.error(" REVENIUM_DEBUG=true # For detailed logging");
437
- process.exit(1);
438
- }
439
- }
440
-
441
- // Run the TypeScript demonstration
442
- if (require.main === module) {
443
- checkEnvironment();
444
-
445
- demonstrateAdvancedFeatures()
446
- .then(() => {
447
- console.log(
448
- "\nAdvanced TypeScript Features Demo Completed Successfully!"
449
- );
450
- console.log("\nTypeScript Features Demonstrated:");
451
- console.log(" • Type-safe streaming with event handling");
452
- console.log(" • Custom logger implementation with typed interfaces");
453
- console.log(" • Manual tracking with full type safety");
454
- console.log(" • Comprehensive error handling with typed responses");
455
- console.log(" • Module augmentation for native usageMetadata support");
456
- console.log(" • Generic functions with type constraints");
457
- console.log(" • Full IntelliSense support throughout");
458
- console.log(
459
- "\nNext: Check examples/README.md for more TypeScript patterns!"
460
- );
461
- console.log(
462
- "\nTip: Set REVENIUM_DEBUG=true in .env file for detailed tracking logs"
463
- );
464
- })
465
- .catch((error) => {
466
- console.error("\nAdvanced TypeScript features demo failed:", error);
467
- process.exit(1);
468
- });
469
- }