@diogonzafe/tokenwatch 0.10.0 → 0.10.1

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.
Files changed (2) hide show
  1. package/README.md +41 -1
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -86,7 +86,12 @@ const res = await openai.chat.completions.create({
86
86
  // Optional — removed before sending to the API
87
87
  __sessionId: 'session_abc',
88
88
  __userId: 'user_123',
89
- __feature: 'chat', // tag calls by product feature → report.byFeature
89
+ __feature: 'chat', // tag calls by product feature → report.byFeature
90
+ __metadata: { // arbitrary custom dimensions → report.byMetadata
91
+ tenantId: 'acme-corp',
92
+ region: 'eu-west',
93
+ plan: 'enterprise',
94
+ },
90
95
  })
91
96
  // res is identical to the original OpenAI response — zero difference
92
97
  ```
@@ -291,6 +296,37 @@ The handler extracts `promptTokens` / `completionTokens` from `llmOutput.tokenUs
291
296
 
292
297
  ---
293
298
 
299
+ ## Custom Metadata
300
+
301
+ Tag any call with arbitrary key-value dimensions using `__metadata`. Works with all provider wrappers (OpenAI, Anthropic, Gemini, DeepSeek):
302
+
303
+ ```ts
304
+ await openai.chat.completions.create({
305
+ model: 'gpt-4o',
306
+ messages: [...],
307
+ __metadata: {
308
+ tenantId: 'acme-corp', // group by tenant
309
+ region: 'eu-west', // group by region
310
+ plan: 'enterprise', // group by plan tier
311
+ experiment: 'prompt-v3', // A/B test tracking
312
+ },
313
+ })
314
+ ```
315
+
316
+ Custom dimensions appear in `report.byMetadata`, grouped by key → value → stats:
317
+
318
+ ```ts
319
+ const report = await tracker.getReport()
320
+
321
+ report.byMetadata['tenantId']['acme-corp'] // { costUSD: 1.20, calls: 94 }
322
+ report.byMetadata['region']['eu-west'] // { costUSD: 0.52, calls: 38 }
323
+ report.byMetadata['plan']['enterprise'] // { costUSD: 0.87, calls: 61 }
324
+ ```
325
+
326
+ Metadata is persisted in every storage backend and exported in CSV (as a JSON column). The `tokenwatch dashboard` automatically shows a collapsible table per key when metadata is present.
327
+
328
+ ---
329
+
294
330
  ## Reports
295
331
 
296
332
  All report methods are async:
@@ -307,6 +343,10 @@ const report = await tracker.getReport()
307
343
  // bySession: { 'session_abc': { costUSD: 0.045, calls: 4 } },
308
344
  // byUser: { 'user_123': { costUSD: 0.087, calls: 7 } },
309
345
  // byFeature: { 'chat': { costUSD: 0.062, calls: 5 }, 'rag': { costUSD: 0.025, calls: 3 } },
346
+ // byMetadata: {
347
+ // 'tenantId': { 'acme-corp': { costUSD: 0.072, calls: 9 } },
348
+ // 'region': { 'eu-west': { costUSD: 0.052, calls: 6 }, 'us-east': { costUSD: 0.035, calls: 5 } },
349
+ // },
310
350
  // period: { from: '2026-04-16T10:00:00Z', to: '2026-04-16T11:00:00Z' },
311
351
  // pricesUpdatedAt: '2026-04-22' // date of the price data in use
312
352
  // }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diogonzafe/tokenwatch",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "Transparent wrapper to track LLM API costs in real-time by session, user and model",
5
5
  "author": "diogonzafe",
6
6
  "license": "MIT",