@revenium/anthropic 1.0.3 → 1.0.5

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