@revenium/anthropic 1.0.4 → 1.0.6

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 CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.0.6] - 2025-10-24
6
+
7
+ ### Added
8
+ - Comprehensive metadata fields table in README with practical use cases for all 11 fields
9
+ - New `getting_started.ts` example showing complete metadata integration
10
+
11
+ ### Changed
12
+ - Streamlined Getting Started tutorial with clearer step-by-step instructions
13
+ - Improved documentation with direct links to example files
14
+
15
+ ## [1.0.5] - 2025-10-23
16
+
17
+ ### Changed
18
+ - Improved .env.example with realistic key format examples (hak_, sk-ant-)
19
+
5
20
  ## [1.0.4] - 2025-10-21
6
21
 
7
22
  ### Changed
@@ -45,6 +60,8 @@ All notable changes to this project will be documented in this file.
45
60
  - Configurable retry logic
46
61
  - Debug logging support
47
62
 
63
+ [1.0.6]: https://github.com/revenium/revenium-middleware-anthropic-node/releases/tag/v1.0.6
64
+ [1.0.5]: https://github.com/revenium/revenium-middleware-anthropic-node/releases/tag/v1.0.5
48
65
  [1.0.4]: https://github.com/revenium/revenium-middleware-anthropic-node/releases/tag/v1.0.4
49
66
  [1.0.3]: https://github.com/revenium/revenium-middleware-anthropic-node/releases/tag/v1.0.3
50
67
  [1.0.2]: https://github.com/revenium/revenium-middleware-anthropic-node/releases/tag/v1.0.2
package/README.md CHANGED
@@ -7,8 +7,6 @@
7
7
 
8
8
  Automatically track and meter your Anthropic Claude API usage with Revenium. This middleware provides seamless integration with **Anthropic Claude SDK**, requiring minimal code changes and featuring native TypeScript support.
9
9
 
10
- > **Note - Package Renamed**: This package has been renamed from `revenium-middleware-anthropic-node` to `@revenium/anthropic` for better organization and simpler naming. Please update your dependencies accordingly.
11
-
12
10
  ## Features
13
11
 
14
12
  - **Seamless Integration**: Drop-in replacement with zero code changes required
@@ -21,134 +19,60 @@ Automatically track and meter your Anthropic Claude API usage with Revenium. Thi
21
19
  - **Fire-and-forget**: Never blocks your application flow
22
20
  - **Analytics**: Detailed usage analytics and reporting
23
21
 
24
- ## Package Migration
25
-
26
- This package has been renamed from `revenium-middleware-anthropic-node` to `@revenium/anthropic` for better organization and simpler naming.
27
-
28
- ### Migration Steps
29
-
30
- If you're upgrading from the old package:
31
-
32
- ```bash
33
- # Uninstall the old package
34
- npm uninstall revenium-middleware-anthropic-node
35
-
36
- # Install the new package
37
- npm install @revenium/anthropic
38
- ```
39
-
40
- **Update your imports:**
41
-
42
- ```typescript
43
- // Old import
44
- import "revenium-middleware-anthropic-node";
45
-
46
- // New import
47
- import "@revenium/anthropic";
48
- ```
49
-
50
- All functionality remains exactly the same - only the package name has changed.
51
-
52
22
  ## Getting Started
53
23
 
54
- ### Quick Start
55
-
56
- ```bash
57
- npm install @revenium/anthropic @anthropic-ai/sdk
58
- ```
59
-
60
- For complete setup instructions, TypeScript patterns, and usage examples, see [examples/README.md](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/README.md).
61
-
62
- ### Step-by-Step Guide
63
-
64
- The following guide walks you through creating a new project from scratch:
65
-
66
- ### Step 1: Create Your Project
24
+ ### 1. Create Project Directory
67
25
 
68
26
  ```bash
69
- # Create project directory
27
+ # Create and navigate to project directory
70
28
  mkdir my-anthropic-project
71
29
  cd my-anthropic-project
72
30
 
73
- # Initialize Node.js project
31
+ # Initialize npm project
74
32
  npm init -y
75
- ```
76
-
77
- ### Step 2: Install Dependencies
78
-
79
- ```bash
80
- # Install Revenium middleware and Anthropic SDK
81
- npm install @revenium/anthropic @anthropic-ai/sdk@^0.55.1 dotenv
82
33
 
83
- # For TypeScript projects (optional)
84
- npm install -D typescript tsx @types/node
34
+ # Install dependencies
35
+ npm install @revenium/anthropic @anthropic-ai/sdk dotenv tsx
36
+ npm install --save-dev typescript @types/node
85
37
  ```
86
38
 
87
- ### Step 3: Setup Environment Variables
39
+ ### 2. Configure Environment Variables
88
40
 
89
- Create a `.env` file in your project root:
41
+ Create a `.env` file:
90
42
 
91
43
  ```bash
92
- # Create .env file
93
- echo. > .env # On Windows (CMD)
94
- touch .env # On Mac/Linux
95
- # OR PowerShell
96
- New-Item -Path .env -ItemType File
44
+ REVENIUM_METERING_API_KEY="hak_your_revenium_key"
45
+ ANTHROPIC_API_KEY="sk-ant-your_anthropic_key"
97
46
  ```
98
47
 
99
- Copy and paste the following into `.env`:
48
+ > **Note**: `REVENIUM_METERING_BASE_URL` defaults to `https://api.revenium.io` and doesn't need to be set unless using a different environment.
100
49
 
101
- ```env
102
- # Anthropic Configuration
103
- ANTHROPIC_API_KEY=sk-ant-your_anthropic_api_key_here
50
+ ### 3. Run Your First Example
104
51
 
105
- # Revenium Configuration
106
- REVENIUM_METERING_API_KEY=hak_your_revenium_api_key_here
107
- REVENIUM_METERING_BASE_URL=https://api.revenium.io/meter
52
+ Run the [getting started example](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/getting_started.ts):
108
53
 
109
- # Optional: Enable debug logging
110
- REVENIUM_DEBUG=true
54
+ ```bash
55
+ npx tsx node_modules/@revenium/anthropic/examples/getting_started.ts
111
56
  ```
112
57
 
113
- **NOTE**: Replace each `your_..._here` with your actual values.
114
-
115
- ### Step 4: Protect Your API Keys
116
-
117
- **CRITICAL**: Create a `.gitignore` file to prevent committing sensitive data like API keys.
118
-
119
- **Recommended**: Use the industry-standard [GitHub Node.gitignore](https://github.com/github/gitignore/blob/main/Node.gitignore)
58
+ Or with debug logging:
120
59
 
121
60
  ```bash
122
- # Download GitHub's standard Node.gitignore
123
- curl -o .gitignore https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
124
- ```
61
+ # Linux/macOS
62
+ REVENIUM_DEBUG=true npx tsx node_modules/@revenium/anthropic/examples/getting_started.ts
125
63
 
126
- **IMPORTANT**: Ensure these patterns are included to protect your environment variables:
127
-
128
- ```gitignore
129
- # Environment variables - CRITICAL for API key protection
130
- .env
131
- .env.*
132
- !.env.example
64
+ # Windows (PowerShell)
65
+ $env:REVENIUM_DEBUG="true"; npx tsx node_modules/@revenium/anthropic/examples/getting_started.ts
133
66
  ```
134
67
 
135
- Never commit `.env` files containing your API keys to version control.
136
-
137
- ### Step 5: Follow the Examples
138
-
139
- See [examples/README.md](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/README.md) for complete examples and setup instructions.
140
-
141
- **Cloned from GitHub?** Run examples with:
142
-
143
- ```bash
144
- npm install
145
- npm run example:basic
146
- npm run example:advanced
147
- ```
68
+ **For more examples and TypeScript patterns, see [examples/README.md](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/README.md).**
148
69
 
149
- **Browse online:** [`examples/` directory](https://github.com/revenium/revenium-middleware-anthropic-node/tree/HEAD/examples)
70
+ ## Requirements
150
71
 
151
- ---
72
+ - Node.js 18+
73
+ - TypeScript 5.0+ (for TypeScript projects)
74
+ - Anthropic SDK (@anthropic-ai/sdk) v0.20.0+
75
+ - Revenium API key
152
76
 
153
77
  ## What Gets Tracked
154
78
 
@@ -168,166 +92,63 @@ The middleware automatically captures:
168
92
 
169
93
  The middleware supports three initialization patterns:
170
94
 
171
- #### Option A: Automatic Initialization (Simplest)
95
+ **Automatic (Recommended)** - Simply import the middleware and it auto-initializes:
172
96
 
173
97
  ```typescript
174
- // Simply import - auto-initializes with graceful fallback
175
98
  import "@revenium/anthropic";
176
99
  import Anthropic from "@anthropic-ai/sdk";
177
100
 
178
- // If env vars are set, tracking works automatically
179
101
  const anthropic = new Anthropic();
102
+ // Tracking works automatically if env vars are set
180
103
  ```
181
104
 
182
- #### Option B: Explicit Initialization (More Control)
105
+ **Explicit** - Call `initialize()` for error handling control
183
106
 
184
- ```typescript
185
- import { initialize } from "@revenium/anthropic";
186
- import Anthropic from "@anthropic-ai/sdk";
107
+ **Manual** - Use `configure()` to set all options programmatically
187
108
 
188
- try {
189
- initialize();
190
- // Middleware initialized successfully
191
- } catch (error) {
192
- // Handle initialization error appropriately
193
- throw new Error(`Initialization failed: ${error.message}`);
194
- }
195
-
196
- const anthropic = new Anthropic();
197
- ```
198
-
199
- #### Option C: Manual Configuration (Full Control)
200
-
201
- ```typescript
202
- import { configure } from "@revenium/anthropic";
203
- import Anthropic from "@anthropic-ai/sdk";
204
-
205
- configure({
206
- reveniumApiKey: "hak_your_api_key_here",
207
- reveniumBaseUrl: "https://api.revenium.io/meter",
208
- anthropicApiKey: "sk-ant-your_key_here",
209
- apiTimeout: 5000,
210
- failSilent: true,
211
- maxRetries: 3,
212
- });
213
-
214
- const anthropic = new Anthropic();
215
- ```
109
+ For detailed examples of all initialization patterns, see [examples/](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/README.md).
216
110
 
217
111
  ### Streaming Responses
218
112
 
219
- ```typescript
220
- import "@revenium/anthropic";
221
- import Anthropic from "@anthropic-ai/sdk";
222
-
223
- const anthropic = new Anthropic();
113
+ Streaming is fully supported with real-time token tracking and time-to-first-token metrics. The middleware automatically tracks streaming responses without any additional configuration.
224
114
 
225
- const stream = await anthropic.messages.create({
226
- model: "claude-3-5-sonnet-latest",
227
- max_tokens: 1000,
228
- messages: [{ role: "user", content: "Write a story about AI" }],
229
- stream: true,
230
- usageMetadata: {
231
- subscriber: {
232
- id: "user-123",
233
- email: "user@example.com",
234
- },
235
- organizationId: "story-org",
236
- taskType: "creative-writing",
237
- agent: "story-writer",
238
- },
239
- });
240
-
241
- for await (const event of stream) {
242
- if (
243
- event.type === "content_block_delta" &&
244
- event.delta.type === "text_delta"
245
- ) {
246
- process.stdout.write(event.delta.text);
247
- }
248
- }
249
- ```
115
+ See [examples/advanced-features.ts](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/advanced-features.ts) for working streaming examples.
250
116
 
251
117
  ### Custom Metadata Tracking
252
118
 
253
- Add business context to your AI usage:
254
-
255
- ```typescript
256
- // Custom metadata for enhanced tracking (following project structure)
257
- const customMetadata = {
258
- subscriber: {
259
- id: "user-789",
260
- email: "user@company.com",
261
- credential: {
262
- name: "premium-user",
263
- value: "tier-1",
264
- },
265
- },
266
- organizationId: "org-456",
267
- productId: "premium-plan",
268
- taskType: "CUSTOMER_SUPPORT",
269
- agent: "CustomerSupportBot",
270
- traceId: "user-session-123",
271
- responseQualityScore: 9.2,
272
- };
273
-
274
- const response = await anthropic.messages.create({
275
- model: "claude-3-5-sonnet-latest",
276
- max_tokens: 1024,
277
- messages: [{ role: "user", content: "Help me with my account" }],
278
- usageMetadata: customMetadata,
279
- });
280
- ```
281
-
282
- ### Usage Metadata Interface
283
-
284
- All metadata fields are optional:
285
-
286
- ```typescript
287
- interface UsageMetadata {
288
- traceId?: string; // Session or conversation ID
289
- taskType?: string; // Type of AI task (e.g., "chat", "analysis")
290
- organizationId?: string; // Organization/company ID
291
- subscriptionId?: string; // Billing plan ID
292
- productId?: string; // Your product/feature ID
293
- agent?: string; // AI agent identifier
294
- responseQualityScore?: number; // Quality score (0-1)
295
- subscriber?: {
296
- id?: string; // User ID from your system
297
- email?: string; // User's email address
298
- credential?: {
299
- name?: string; // Credential name
300
- value?: string; // Credential value
301
- };
302
- };
303
- }
304
- ```
119
+ Add business context to track usage by organization, user, task type, or custom fields. Pass a `usageMetadata` object with any of these optional fields:
120
+
121
+ | Field | Description | Use Case |
122
+ |-------|-------------|----------|
123
+ | `traceId` | Unique identifier for session or conversation tracking | Link multiple API calls together for debugging, user session analytics, or distributed tracing across services |
124
+ | `taskType` | Type of AI task being performed | Categorize usage by workload (e.g., "chat", "code-generation", "doc-summary") for cost analysis and optimization |
125
+ | `subscriber.id` | Unique user identifier | Track individual user consumption for billing, rate limiting, or user analytics |
126
+ | `subscriber.email` | User email address | Identify users for support, compliance, or usage reports |
127
+ | `subscriber.credential.name` | Authentication credential name | Track which API key or service account made the request |
128
+ | `subscriber.credential.value` | Authentication credential value | Associate usage with specific credentials for security auditing |
129
+ | `organizationId` | Organization or company identifier | Multi-tenant cost allocation, usage quotas per organization |
130
+ | `subscriptionId` | Subscription plan identifier | Track usage against subscription limits, identify plan upgrade opportunities |
131
+ | `productId` | Your product or feature identifier | Attribute AI costs to specific features in your application (e.g., "chatbot", "email-assistant") |
132
+ | `agent` | AI agent or bot identifier | Distinguish between multiple AI agents or automation workflows in your system |
133
+ | `responseQualityScore` | Custom quality rating (0.0-1.0) | Track user satisfaction or automated quality metrics for model performance analysis |
134
+
135
+ **Resources:**
136
+ - [API Reference](https://revenium.readme.io/reference/meter_ai_completion) - Complete metadata field documentation
305
137
 
306
138
  ## Configuration Options
307
139
 
308
140
  ### Environment Variables
309
141
 
310
- | Variable | Required | Default | Description |
311
- | ---------------------------- | -------- | ------------------------------- | --------------------------------- |
312
- | `REVENIUM_METERING_API_KEY` | Yes | - | Your Revenium API key |
313
- | `ANTHROPIC_API_KEY` | Yes | - | Anthropic Claude API key |
314
- | `REVENIUM_METERING_BASE_URL` | No | `https://api.revenium.io/meter` | Revenium metering API base URL |
315
- | `REVENIUM_DEBUG` | No | `false` | Enable debug logging (true/false) |
142
+ | Variable | Required | Default | Description |
143
+ | ---------------------------- | -------- | -------------------------- | --------------------------------- |
144
+ | `REVENIUM_METERING_API_KEY` | Yes | - | Your Revenium API key |
145
+ | `ANTHROPIC_API_KEY` | Yes | - | Anthropic Claude API key |
146
+ | `REVENIUM_METERING_BASE_URL` | No | `https://api.revenium.io` | Revenium metering API base URL |
147
+ | `REVENIUM_DEBUG` | No | `false` | Enable debug logging (true/false) |
316
148
 
317
149
  ### Manual Configuration
318
150
 
319
- ```typescript
320
- import { configure } from "@revenium/anthropic";
321
-
322
- configure({
323
- reveniumApiKey: "hak_your_api_key",
324
- reveniumBaseUrl: "https://api.revenium.io/meter",
325
- anthropicApiKey: "sk-ant-your_key",
326
- apiTimeout: 5000,
327
- failSilent: true,
328
- maxRetries: 3,
329
- });
330
- ```
151
+ For programmatic configuration instead of environment variables, use the `configure()` function. See the initialization options above and [examples/](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/README.md) for details.
331
152
 
332
153
  ## Troubleshooting
333
154
 
@@ -370,6 +191,14 @@ npm install
370
191
  npm run build
371
192
  ```
372
193
 
194
+ ### OpenRouter Users
195
+
196
+ **Note:** Revenium's automatic token cost calculation uses AI model names from the providers themselves (e.g., `claude-sonnet-4-20250514`).
197
+
198
+ If you are using a service like OpenRouter that changes model names (from `claude-sonnet-4-20250514` to `anthropic/claude-sonnet-4`), automatic cost calculations may not work properly in Revenium (though all other processing will work normally).
199
+
200
+ Supporting OpenRouter AI model names is something we're working on for the future. If this is critical for your use case, please use the 'provide feedback' button in the Help Center to let us know.
201
+
373
202
  ### Debug Mode
374
203
 
375
204
  Enable detailed logging to troubleshoot issues:
@@ -411,13 +240,6 @@ All examples are in the `examples/` directory of the installed package. For deta
411
240
 
412
241
  The middleware never blocks your application - if Revenium tracking fails, your Anthropic requests continue normally.
413
242
 
414
- ## Requirements
415
-
416
- - Node.js 16+
417
- - Anthropic SDK (@anthropic-ai/sdk) v0.20.0+
418
- - TypeScript 5.0+ (for TypeScript projects)
419
- - Revenium API key
420
-
421
243
  ## Documentation
422
244
 
423
245
  For detailed documentation, visit [docs.revenium.io](https://docs.revenium.io)
@@ -445,7 +267,7 @@ For issues, feature requests, or contributions:
445
267
  - **GitHub Repository**: [revenium/revenium-middleware-anthropic-node](https://github.com/revenium/revenium-middleware-anthropic-node)
446
268
  - **Issues**: [Report bugs or request features](https://github.com/revenium/revenium-middleware-anthropic-node/issues)
447
269
  - **Documentation**: [docs.revenium.io](https://docs.revenium.io)
448
- - **Contact**: Reach out to the Revenium team for additional support
270
+ - **Email**: support@revenium.io
449
271
 
450
272
  ## Development
451
273
 
@@ -10,7 +10,7 @@ exports.ANTHROPIC_PATTERNS = exports.API_ENDPOINTS = exports.ENV_VARS = exports.
10
10
  */
11
11
  exports.DEFAULT_CONFIG = {
12
12
  /** Default Revenium API base URL */
13
- REVENIUM_BASE_URL: 'https://api.revenium.io/meter',
13
+ REVENIUM_BASE_URL: 'https://api.revenium.io',
14
14
  /** Default API timeout in milliseconds */
15
15
  API_TIMEOUT: 5000,
16
16
  /** Default maximum retries for failed API calls */
@@ -118,7 +118,7 @@ exports.ENV_VARS = {
118
118
  */
119
119
  exports.API_ENDPOINTS = {
120
120
  /** Revenium AI completions endpoint */
121
- AI_COMPLETIONS: '/v2/ai/completions',
121
+ AI_COMPLETIONS: '/meter/v2/ai/completions',
122
122
  };
123
123
  /**
124
124
  * Anthropic model patterns
@@ -142,6 +142,7 @@ function buildReveniumPayload(data) {
142
142
  completionStartTime: completionStartTime,
143
143
  timeToFirstToken: data.timeToFirstToken || 0,
144
144
  traceId: data.metadata?.traceId,
145
+ responseQualityScore: data.metadata?.responseQualityScore, // Fixed: Now sending to Revenium
145
146
  middlewareSource: "nodejs",
146
147
  };
147
148
  }
@@ -68,7 +68,6 @@
68
68
  * credential: { name: 'api-key', value: 'sk-...' }
69
69
  * },
70
70
  * traceId: 'analysis-session-789',
71
- * taskId: 'task-001',
72
71
  * taskType: 'data-analysis',
73
72
  * organizationId: 'enterprise-client',
74
73
  * subscriptionId: 'premium-plan',
@@ -60,8 +60,7 @@ function validateUsageMetadata(metadata) {
60
60
  const validated = {};
61
61
  // Validate string fields
62
62
  const stringFields = [
63
- 'traceId', 'taskId', 'taskType', 'subscriberEmail', 'subscriberId',
64
- 'subscriberCredentialName', 'subscriberCredential', 'organizationId',
63
+ 'traceId', 'taskType', 'organizationId',
65
64
  'subscriptionId', 'productId', 'agent'
66
65
  ];
67
66
  for (const field of stringFields) {
@@ -161,7 +160,7 @@ function validateReveniumConfig(config) {
161
160
  }
162
161
  catch {
163
162
  errors.push('reveniumBaseUrl must be a valid URL');
164
- suggestions.push('Use format: https://api.revenium.io/meter');
163
+ suggestions.push('Use format: https://api.revenium.io');
165
164
  }
166
165
  }
167
166
  // Validate optional Anthropic API key
@@ -61,8 +61,10 @@ function getMessagesPrototype() {
61
61
  * Patch Anthropic SDK by modifying prototype methods
62
62
  */
63
63
  function patchAnthropic() {
64
- if (patchingContext.isPatched)
64
+ if (patchingContext.isPatched) {
65
+ logger.debug('Anthropic SDK already patched, skipping duplicate initialization');
65
66
  return;
67
+ }
66
68
  try {
67
69
  // Access the Messages class prototype using sophisticated prototype access
68
70
  const messagesPrototype = getMessagesPrototype();
@@ -7,7 +7,7 @@
7
7
  */
8
8
  export const DEFAULT_CONFIG = {
9
9
  /** Default Revenium API base URL */
10
- REVENIUM_BASE_URL: 'https://api.revenium.io/meter',
10
+ REVENIUM_BASE_URL: 'https://api.revenium.io',
11
11
  /** Default API timeout in milliseconds */
12
12
  API_TIMEOUT: 5000,
13
13
  /** Default maximum retries for failed API calls */
@@ -115,7 +115,7 @@ export const ENV_VARS = {
115
115
  */
116
116
  export const API_ENDPOINTS = {
117
117
  /** Revenium AI completions endpoint */
118
- AI_COMPLETIONS: '/v2/ai/completions',
118
+ AI_COMPLETIONS: '/meter/v2/ai/completions',
119
119
  };
120
120
  /**
121
121
  * Anthropic model patterns
@@ -133,6 +133,7 @@ function buildReveniumPayload(data) {
133
133
  completionStartTime: completionStartTime,
134
134
  timeToFirstToken: data.timeToFirstToken || 0,
135
135
  traceId: data.metadata?.traceId,
136
+ responseQualityScore: data.metadata?.responseQualityScore, // Fixed: Now sending to Revenium
136
137
  middlewareSource: "nodejs",
137
138
  };
138
139
  }
@@ -67,7 +67,6 @@
67
67
  * credential: { name: 'api-key', value: 'sk-...' }
68
68
  * },
69
69
  * traceId: 'analysis-session-789',
70
- * taskId: 'task-001',
71
70
  * taskType: 'data-analysis',
72
71
  * organizationId: 'enterprise-client',
73
72
  * subscriptionId: 'premium-plan',
@@ -49,8 +49,7 @@ export function validateUsageMetadata(metadata) {
49
49
  const validated = {};
50
50
  // Validate string fields
51
51
  const stringFields = [
52
- 'traceId', 'taskId', 'taskType', 'subscriberEmail', 'subscriberId',
53
- 'subscriberCredentialName', 'subscriberCredential', 'organizationId',
52
+ 'traceId', 'taskType', 'organizationId',
54
53
  'subscriptionId', 'productId', 'agent'
55
54
  ];
56
55
  for (const field of stringFields) {
@@ -150,7 +149,7 @@ export function validateReveniumConfig(config) {
150
149
  }
151
150
  catch {
152
151
  errors.push('reveniumBaseUrl must be a valid URL');
153
- suggestions.push('Use format: https://api.revenium.io/meter');
152
+ suggestions.push('Use format: https://api.revenium.io');
154
153
  }
155
154
  }
156
155
  // Validate optional Anthropic API key
@@ -53,8 +53,10 @@ function getMessagesPrototype() {
53
53
  * Patch Anthropic SDK by modifying prototype methods
54
54
  */
55
55
  export function patchAnthropic() {
56
- if (patchingContext.isPatched)
56
+ if (patchingContext.isPatched) {
57
+ logger.debug('Anthropic SDK already patched, skipping duplicate initialization');
57
58
  return;
59
+ }
58
60
  try {
59
61
  // Access the Messages class prototype using sophisticated prototype access
60
62
  const messagesPrototype = getMessagesPrototype();
@@ -7,7 +7,7 @@
7
7
  */
8
8
  export declare const DEFAULT_CONFIG: {
9
9
  /** Default Revenium API base URL */
10
- readonly REVENIUM_BASE_URL: "https://api.revenium.io/meter";
10
+ readonly REVENIUM_BASE_URL: "https://api.revenium.io";
11
11
  /** Default API timeout in milliseconds */
12
12
  readonly API_TIMEOUT: 5000;
13
13
  /** Default maximum retries for failed API calls */
@@ -115,7 +115,7 @@ export declare const ENV_VARS: {
115
115
  */
116
116
  export declare const API_ENDPOINTS: {
117
117
  /** Revenium AI completions endpoint */
118
- readonly AI_COMPLETIONS: "/v2/ai/completions";
118
+ readonly AI_COMPLETIONS: "/meter/v2/ai/completions";
119
119
  };
120
120
  /**
121
121
  * Anthropic model patterns
@@ -67,7 +67,6 @@
67
67
  * credential: { name: 'api-key', value: 'sk-...' }
68
68
  * },
69
69
  * traceId: 'analysis-session-789',
70
- * taskId: 'task-001',
71
70
  * taskType: 'data-analysis',
72
71
  * organizationId: 'enterprise-client',
73
72
  * subscriptionId: 'premium-plan',
@@ -52,7 +52,7 @@ export interface Subscriber {
52
52
  * ```typescript
53
53
  * const config: ReveniumConfig = {
54
54
  * reveniumApiKey: 'hak_1234567890abcdef',
55
- * reveniumBaseUrl: 'https://api.revenium.io/meter/v2',
55
+ * reveniumBaseUrl: 'https://api.revenium.io',
56
56
  * anthropicApiKey: 'sk-ant-1234567890abcdef',
57
57
  * apiTimeout: 8000,
58
58
  * failSilent: true,
@@ -98,8 +98,6 @@ export interface UsageMetadata {
98
98
  subscriber?: Subscriber;
99
99
  /** Unique identifier for conversation/session tracking across multiple requests */
100
100
  traceId?: string;
101
- /** Identifier for specific AI task grouping within a trace */
102
- taskId?: string;
103
101
  /** Classification of AI operation (e.g., 'customer-support', 'content-generation', 'code-review') */
104
102
  taskType?: string;
105
103
  /** Customer organization identifier for multi-tenant applications */
@@ -290,6 +288,8 @@ export interface ReveniumPayload {
290
288
  timeToFirstToken: number;
291
289
  /** Optional trace identifier for request correlation */
292
290
  traceId?: string;
291
+ /** Quality score of the AI response (0.0-1.0) for performance tracking */
292
+ responseQualityScore?: number;
293
293
  /** Source identifier for the middleware */
294
294
  middlewareSource: string;
295
295
  }
@@ -0,0 +1,18 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Read(//Users/daithi/git/rev/git/revenium-middleware-anthropic-node/**)",
5
+ "Bash(npm init:*)",
6
+ "Bash(npm install:*)",
7
+ "Bash(cp:*)",
8
+ "Bash(npx tsx:*)",
9
+ "WebFetch(domain:revenium.readme.io)",
10
+ "Bash(tee:*)",
11
+ "Bash(npm run clean:*)",
12
+ "Bash(npm run build:*)",
13
+ "Bash(node -e \"require(''@revenium/anthropic''); console.log(''✅ Option A (Auto-init) - Import works'')\")"
14
+ ],
15
+ "deny": [],
16
+ "ask": []
17
+ }
18
+ }
@@ -2,16 +2,27 @@
2
2
 
3
3
  **TypeScript-first** examples demonstrating automatic Revenium usage tracking with the Anthropic SDK.
4
4
 
5
- ## Quick Start
5
+ ## Getting Started - Step by Step
6
6
 
7
- ### 1. Install Dependencies
7
+ ### 1. Create Your Project
8
+
9
+ ```bash
10
+ # Create project directory
11
+ mkdir my-anthropic-project
12
+ cd my-anthropic-project
13
+
14
+ # Initialize Node.js project
15
+ npm init -y
16
+ ```
17
+
18
+ ### 2. Install Dependencies
8
19
 
9
20
  ```bash
10
21
  npm install @revenium/anthropic @anthropic-ai/sdk dotenv
11
22
  npm install -D typescript tsx @types/node # For TypeScript
12
23
  ```
13
24
 
14
- ### 2. Environment Setup
25
+ ### 3. Environment Setup
15
26
 
16
27
  Create a `.env` file in your project root:
17
28
 
@@ -21,11 +32,11 @@ REVENIUM_METERING_API_KEY=hak_your_revenium_api_key
21
32
  ANTHROPIC_API_KEY=sk-ant-your_anthropic_api_key
22
33
 
23
34
  # Optional
24
- REVENIUM_METERING_BASE_URL=https://api.revenium.io/meter
35
+ REVENIUM_METERING_BASE_URL=https://api.revenium.io
25
36
  REVENIUM_DEBUG=false
26
37
  ```
27
38
 
28
- ### 3. Run Examples
39
+ ### 4. Run Examples
29
40
 
30
41
  **If you cloned from GitHub:**
31
42
 
@@ -59,6 +70,7 @@ Demonstrates the three ways to initialize the Revenium middleware:
59
70
  - **Manual configuration** - Use `configure()` for custom settings
60
71
 
61
72
  **Key Features:**
73
+
62
74
  - TypeScript module augmentation for native `usageMetadata` support
63
75
  - Full type safety with IntelliSense
64
76
  - Interface validation using `satisfies` operator
@@ -76,8 +88,9 @@ Demonstrates advanced Anthropic SDK features with automatic tracking:
76
88
  - **Error handling** - Comprehensive error handling patterns
77
89
 
78
90
  **Key Features:**
91
+
79
92
  - Type-safe event handling and stream processing
80
- - Advanced metadata patterns with interface extensions
93
+ - Advanced metadata patterns with custom fields support
81
94
  - Generic functions with type constraints
82
95
  - Custom logger integration
83
96
 
@@ -130,6 +143,7 @@ import Anthropic from "@anthropic-ai/sdk";
130
143
  **Problem:** `REVENIUM_METERING_API_KEY` or `ANTHROPIC_API_KEY` not found
131
144
 
132
145
  **Solutions:**
146
+
133
147
  - Ensure `.env` file is in project root
134
148
  - Check variable names match exactly
135
149
  - Verify you're importing `dotenv/config` before the middleware
@@ -152,14 +166,6 @@ import Anthropic from "@anthropic-ai/sdk";
152
166
  }
153
167
  ```
154
168
 
155
- ### IntelliSense Not Working
156
-
157
- **Solutions:**
158
- 1. Restart TypeScript language server in your IDE
159
- 2. Ensure `@revenium/anthropic` is imported at the top
160
- 3. Verify `@anthropic-ai/sdk` types are installed
161
- 4. Check TypeScript version is 4.5 or higher
162
-
163
169
  ### Debug Mode
164
170
 
165
171
  Enable detailed logging to troubleshoot issues:
@@ -7,7 +7,7 @@
7
7
  * • Manual tracking for custom scenarios with full type safety
8
8
  * • Comprehensive error handling with typed error responses
9
9
  * • Generic functions with type constraints
10
- * • Advanced metadata patterns with interface extensions
10
+ * • Advanced metadata patterns with custom fields support
11
11
  * • Type-safe event handling and stream processing
12
12
  *
13
13
  * All features leverage TypeScript's type system for maximum safety and IntelliSense.
@@ -30,29 +30,11 @@ import type {
30
30
 
31
31
  import { trackUsageAsync, getStatus, setLogger } from "@revenium/anthropic";
32
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
33
  /**
52
34
  * Streaming event types with full type safety
53
35
  */
54
36
  type StreamEvent =
55
- | { type: "start"; timestamp: Date; metadata: AdvancedUsageMetadata }
37
+ | { type: "start"; timestamp: Date; metadata: UsageMetadata }
56
38
  | { type: "content"; content: string; timestamp: Date }
57
39
  | { type: "complete"; totalTokens: number; duration: number; timestamp: Date }
58
40
  | { type: "error"; error: string; timestamp: Date };
@@ -113,7 +95,7 @@ async function demonstrateAdvancedFeatures(): Promise<void> {
113
95
  );
114
96
 
115
97
  // Create strongly typed metadata with satisfies operator
116
- const advancedMetadata: AdvancedUsageMetadata = {
98
+ const advancedMetadata: UsageMetadata = {
117
99
  subscriber: {
118
100
  id: "artist-456",
119
101
  email: "artist@creative-studio.com",
@@ -126,12 +108,8 @@ async function demonstrateAdvancedFeatures(): Promise<void> {
126
108
  productId: "story-generator-pro",
127
109
  taskType: "creative-writing",
128
110
  agent: "storyteller-v2",
129
- // Advanced metadata extensions
130
- sessionId: `session_${Date.now()}`,
131
- userRole: "user",
132
- feature: "generation",
133
- priority: "normal",
134
- } satisfies AdvancedUsageMetadata;
111
+ traceId: `session_${Date.now()}`,
112
+ } satisfies UsageMetadata;
135
113
 
136
114
  // Type-safe streaming with event tracking
137
115
  const streamEvents: StreamEvent[] = [];
@@ -258,16 +236,13 @@ async function demonstrateAdvancedFeatures(): Promise<void> {
258
236
  "\nExample 3: Educational content with different metadata pattern..."
259
237
  );
260
238
 
261
- const educationalMetadata: AdvancedUsageMetadata = {
239
+ const educationalMetadata: UsageMetadata = {
262
240
  subscriber: { id: "student-789" },
263
241
  organizationId: "green-tech-edu",
264
242
  productId: "sustainability-tutor",
265
243
  taskType: "educational-query",
266
- sessionId: `edu_session_${Date.now()}`,
267
- userRole: "guest",
268
- feature: "analysis",
269
- priority: "low",
270
- } satisfies AdvancedUsageMetadata;
244
+ traceId: `edu_session_${Date.now()}`,
245
+ } satisfies UsageMetadata;
271
246
 
272
247
  const stream2 = await anthropic.messages.create({
273
248
  model: "claude-3-5-sonnet-latest",
@@ -308,7 +283,7 @@ async function demonstrateAdvancedFeatures(): Promise<void> {
308
283
  console.log("Example 4: Weather tool with advanced TypeScript patterns...");
309
284
 
310
285
  // Create tool-specific metadata with type safety
311
- const toolMetadata: AdvancedUsageMetadata = {
286
+ const toolMetadata: UsageMetadata = {
312
287
  subscriber: {
313
288
  id: "weather-user-456",
314
289
  email: "user@weather-app.com",
@@ -317,11 +292,8 @@ async function demonstrateAdvancedFeatures(): Promise<void> {
317
292
  productId: "smart-weather-assistant",
318
293
  taskType: "tool-usage",
319
294
  agent: "weather-bot-v3",
320
- sessionId: `weather_${Date.now()}`,
321
- userRole: "user",
322
- feature: "chat",
323
- priority: "normal",
324
- } satisfies AdvancedUsageMetadata;
295
+ traceId: `weather_${Date.now()}`,
296
+ } satisfies UsageMetadata;
325
297
 
326
298
  const toolStream = await anthropic.messages.create({
327
299
  model: "claude-3-5-sonnet-latest",
@@ -391,7 +363,6 @@ async function demonstrateAdvancedFeatures(): Promise<void> {
391
363
  console.log(" • Type-safe metadata with satisfies operator");
392
364
  console.log(" • Strongly typed event handling and streaming");
393
365
  console.log(" • Custom logger implementation with typed interfaces");
394
- console.log(" • Advanced metadata patterns with interface extensions");
395
366
  console.log(" • Comprehensive error handling with typed responses");
396
367
  console.log(" • Generic functions with type constraints");
397
368
  console.log(" • Full IntelliSense support throughout\n");
@@ -461,9 +432,7 @@ function checkEnvironment(): void {
461
432
  console.error(" REVENIUM_METERING_API_KEY=hak_your_api_key");
462
433
  console.error(" ANTHROPIC_API_KEY=sk-ant-your_anthropic_key");
463
434
  console.error("\nOptional (uses defaults if not set):");
464
- console.error(
465
- " REVENIUM_METERING_BASE_URL=https://api.revenium.io/meter/v2"
466
- );
435
+ console.error(" REVENIUM_METERING_BASE_URL=https://api.revenium.io");
467
436
  console.error(" REVENIUM_DEBUG=true # For detailed logging");
468
437
  process.exit(1);
469
438
  }
@@ -480,7 +449,6 @@ if (require.main === module) {
480
449
  );
481
450
  console.log("\nTypeScript Features Demonstrated:");
482
451
  console.log(" • Type-safe streaming with event handling");
483
- console.log(" • Advanced metadata patterns with interface extensions");
484
452
  console.log(" • Custom logger implementation with typed interfaces");
485
453
  console.log(" • Manual tracking with full type safety");
486
454
  console.log(" • Comprehensive error handling with typed responses");
@@ -23,7 +23,7 @@ import "dotenv/config";
23
23
  import "@revenium/anthropic";
24
24
  import Anthropic from "@anthropic-ai/sdk";
25
25
 
26
- // Import types for full TypeScript support
26
+ // Import types and functions for full TypeScript support
27
27
  import type {
28
28
  UsageMetadata,
29
29
  ReveniumConfig,
@@ -31,6 +31,9 @@ import type {
31
31
  MiddlewareStatus,
32
32
  } from "@revenium/anthropic";
33
33
 
34
+ // Import initialization and configuration functions
35
+ import { initialize, getStatus, configure, getConfig } from "@revenium/anthropic";
36
+
34
37
  async function demonstrateBasicUsage() {
35
38
  console.log("Revenium Anthropic Middleware - Basic Usage Examples\n");
36
39
 
@@ -42,16 +45,14 @@ async function demonstrateBasicUsage() {
42
45
  "Just import the middleware - it auto-configures from environment variables\n"
43
46
  );
44
47
 
45
- // Simply import the middleware - auto-initialization happens automatically
46
- await import("@revenium/anthropic");
47
-
48
+ // The middleware was already imported at the top of the file - auto-initialization happens automatically
48
49
  const anthropic = new Anthropic();
49
50
 
50
51
  try {
51
52
  // Example 1: Basic request without metadata (still tracked automatically)
52
53
  console.log("Example 1: Basic request without metadata...");
53
54
  const basicResponse = await anthropic.messages.create({
54
- model: "claude-sonnet-4-20250514",
55
+ model: "claude-3-5-sonnet-latest",
55
56
  max_tokens: 50,
56
57
  messages: [
57
58
  { role: "user", content: "What is the capital of France? Be concise." },
@@ -72,7 +73,7 @@ async function demonstrateBasicUsage() {
72
73
  // Example 2: Request with rich metadata for enhanced tracking
73
74
  console.log("Example 2: Request with rich metadata...");
74
75
  const metadataResponse = await anthropic.messages.create({
75
- model: "claude-sonnet-4-20250514",
76
+ model: "claude-3-5-sonnet-latest",
76
77
  max_tokens: 80,
77
78
  messages: [
78
79
  { role: "user", content: "Explain quantum computing in one sentence." },
@@ -130,9 +131,6 @@ async function demonstrateExplicitInitialization() {
130
131
  );
131
132
 
132
133
  try {
133
- // Import initialization functions
134
- const { initialize, getStatus } = await import("@revenium/anthropic");
135
-
136
134
  // Explicitly initialize with clear error feedback
137
135
  initialize();
138
136
  console.log("✓ Explicit initialization successful!");
@@ -148,7 +146,7 @@ async function demonstrateExplicitInitialization() {
148
146
  // Now use Anthropic with guaranteed tracking
149
147
  const anthropic = new Anthropic();
150
148
  const response = await anthropic.messages.create({
151
- model: "claude-sonnet-4-20250514",
149
+ model: "claude-3-5-sonnet-latest",
152
150
  max_tokens: 60,
153
151
  messages: [
154
152
  {
@@ -190,17 +188,13 @@ async function demonstrateManualConfiguration() {
190
188
  console.log("Option C: Manual Configuration (Full Control)");
191
189
 
192
190
  try {
193
- // Import configuration function
194
- const { configure, getConfig } = await import("@revenium/anthropic");
195
-
196
191
  // Manual configuration with all options
197
192
  configure({
198
193
  // Required: Revenium API configuration
199
194
  reveniumApiKey:
200
195
  process.env.REVENIUM_METERING_API_KEY || "hak_your_api_key_here",
201
196
  reveniumBaseUrl:
202
- process.env.REVENIUM_METERING_BASE_URL ||
203
- "https://api.revenium.io/meter",
197
+ process.env.REVENIUM_METERING_BASE_URL || "https://api.revenium.io",
204
198
 
205
199
  // Optional: Anthropic API key (can also be set in Anthropic client)
206
200
  anthropicApiKey: process.env.ANTHROPIC_API_KEY,
@@ -228,7 +222,7 @@ async function demonstrateManualConfiguration() {
228
222
  });
229
223
 
230
224
  const response = await anthropic.messages.create({
231
- model: "claude-sonnet-4-20250514",
225
+ model: "claude-3-5-sonnet-latest",
232
226
  max_tokens: 80,
233
227
  messages: [
234
228
  {
@@ -285,9 +279,7 @@ function checkEnvironment() {
285
279
  console.error(" REVENIUM_METERING_API_KEY=hak_your_api_key");
286
280
  console.error(" ANTHROPIC_API_KEY=sk-ant-your_anthropic_key");
287
281
  console.error("\nOptional (uses defaults if not set):");
288
- console.error(
289
- " REVENIUM_METERING_BASE_URL=https://api.revenium.io/meter"
290
- );
282
+ console.error(" REVENIUM_METERING_BASE_URL=https://api.revenium.io");
291
283
  console.error(" REVENIUM_DEBUG=true # For detailed logging");
292
284
  process.exit(1);
293
285
  }
@@ -0,0 +1,50 @@
1
+ import 'dotenv/config';
2
+ import '@revenium/anthropic';
3
+ import Anthropic from '@anthropic-ai/sdk';
4
+
5
+ async function main() {
6
+ // Create Anthropic client
7
+ const anthropic = new Anthropic();
8
+
9
+ // Chat completion with metadata
10
+ const response = await anthropic.messages.create({
11
+ model: 'claude-3-5-sonnet-latest',
12
+ max_tokens: 2000,
13
+ messages: [
14
+ { role: 'user', content: 'Please verify you are ready to assist me.' }
15
+ ],
16
+
17
+ /* Optional metadata for advanced reporting, lineage tracking, and cost allocation
18
+ usageMetadata: {
19
+ // User identification
20
+ subscriber: {
21
+ id: 'user-123',
22
+ email: 'user@example.com',
23
+ credential: {
24
+ name: 'api-key-prod',
25
+ value: 'key-abc-123'
26
+ }
27
+ },
28
+
29
+ // Organization & billing
30
+ organizationId: 'my-customers-name',
31
+ subscriptionId: 'plan-enterprise-2024',
32
+
33
+ // Product & task tracking
34
+ productId: 'my-product',
35
+ taskType: 'doc-summary',
36
+ agent: 'customer-support',
37
+
38
+ // Session tracking
39
+ traceId: 'session-' + Date.now(),
40
+
41
+ // Quality metrics
42
+ responseQualityScore: 0.95
43
+ }
44
+ */
45
+ });
46
+
47
+ console.log('Response:', response.content[0]?.text);
48
+ }
49
+
50
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revenium/anthropic",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
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",