@diogonzafe/tokenwatch 0.8.0 → 0.10.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,4 +1,4 @@
1
- import { I as IExporter, U as UsageEntry } from './index-CFBI-1ab.cjs';
1
+ import { I as IExporter, U as UsageEntry } from './index-B5OF0YCl.cjs';
2
2
 
3
3
  interface OTelAttributes {
4
4
  [key: string]: string | number | boolean | undefined;
@@ -1,4 +1,4 @@
1
- import { I as IExporter, U as UsageEntry } from './index-CFBI-1ab.js';
1
+ import { I as IExporter, U as UsageEntry } from './index-B5OF0YCl.js';
2
2
 
3
3
  interface OTelAttributes {
4
4
  [key: string]: string | number | boolean | undefined;
@@ -65,6 +65,10 @@ interface TrackerConfig {
65
65
  anomalyDetection?: AnomalyDetectionConfig;
66
66
  /** Custom exporter called after every tracked call (e.g. OTelExporter) */
67
67
  exporter?: IExporter;
68
+ /** TokenWatch Cloud API key — mirrors every tracked call to the cloud dashboard (fire-and-forget) */
69
+ cloudApiKey?: string;
70
+ /** Override the cloud ingest endpoint (default: https://api.tokenwatch.dev/v1/ingest) */
71
+ cloudEndpoint?: string;
68
72
  }
69
73
  interface UsageEntry {
70
74
  model: string;
@@ -86,6 +90,8 @@ interface UsageEntry {
86
90
  feature?: string;
87
91
  /** Application identifier — set once in TrackerConfig.appId and stamped on every entry */
88
92
  appId?: string;
93
+ /** Arbitrary key-value tags for custom dimensions (e.g. tenantId, region, plan) */
94
+ metadata?: Record<string, string>;
89
95
  timestamp: string;
90
96
  }
91
97
  interface ModelStats {
@@ -133,6 +139,11 @@ interface Report {
133
139
  byUser: Record<string, UserStats>;
134
140
  byFeature: Record<string, FeatureStats>;
135
141
  byApp: Record<string, AppStats>;
142
+ /** Grouped by each custom metadata key → value → stats */
143
+ byMetadata: Record<string, Record<string, {
144
+ costUSD: number;
145
+ calls: number;
146
+ }>>;
136
147
  period: {
137
148
  from: string;
138
149
  to: string;
@@ -188,6 +199,8 @@ interface TrackingMeta {
188
199
  __feature?: string;
189
200
  /** Override the tracker-level appId for this specific call */
190
201
  __appId?: string;
202
+ /** Arbitrary key-value tags for custom dimensions — appear in report.byMetadata */
203
+ __metadata?: Record<string, string>;
191
204
  }
192
205
 
193
206
  export type { AnomalyDetectionConfig as A, BudgetConfig as B, CostForecast as C, FeatureStats as F, IExporter as I, LazyTracker as L, ModelPrice as M, PriceMap as P, Report as R, SessionStats as S, TrackerConfig as T, UsageEntry as U, Tracker as a, TrackingMeta as b, ForecastOptions as c, IStorage as d, ModelStats as e, PricesFile as f, ReportOptions as g, UserStats as h };
@@ -65,6 +65,10 @@ interface TrackerConfig {
65
65
  anomalyDetection?: AnomalyDetectionConfig;
66
66
  /** Custom exporter called after every tracked call (e.g. OTelExporter) */
67
67
  exporter?: IExporter;
68
+ /** TokenWatch Cloud API key — mirrors every tracked call to the cloud dashboard (fire-and-forget) */
69
+ cloudApiKey?: string;
70
+ /** Override the cloud ingest endpoint (default: https://api.tokenwatch.dev/v1/ingest) */
71
+ cloudEndpoint?: string;
68
72
  }
69
73
  interface UsageEntry {
70
74
  model: string;
@@ -86,6 +90,8 @@ interface UsageEntry {
86
90
  feature?: string;
87
91
  /** Application identifier — set once in TrackerConfig.appId and stamped on every entry */
88
92
  appId?: string;
93
+ /** Arbitrary key-value tags for custom dimensions (e.g. tenantId, region, plan) */
94
+ metadata?: Record<string, string>;
89
95
  timestamp: string;
90
96
  }
91
97
  interface ModelStats {
@@ -133,6 +139,11 @@ interface Report {
133
139
  byUser: Record<string, UserStats>;
134
140
  byFeature: Record<string, FeatureStats>;
135
141
  byApp: Record<string, AppStats>;
142
+ /** Grouped by each custom metadata key → value → stats */
143
+ byMetadata: Record<string, Record<string, {
144
+ costUSD: number;
145
+ calls: number;
146
+ }>>;
136
147
  period: {
137
148
  from: string;
138
149
  to: string;
@@ -188,6 +199,8 @@ interface TrackingMeta {
188
199
  __feature?: string;
189
200
  /** Override the tracker-level appId for this specific call */
190
201
  __appId?: string;
202
+ /** Arbitrary key-value tags for custom dimensions — appear in report.byMetadata */
203
+ __metadata?: Record<string, string>;
191
204
  }
192
205
 
193
206
  export type { AnomalyDetectionConfig as A, BudgetConfig as B, CostForecast as C, FeatureStats as F, IExporter as I, LazyTracker as L, ModelPrice as M, PriceMap as P, Report as R, SessionStats as S, TrackerConfig as T, UsageEntry as U, Tracker as a, TrackingMeta as b, ForecastOptions as c, IStorage as d, ModelStats as e, PricesFile as f, ReportOptions as g, UserStats as h };
package/dist/index.cjs CHANGED
@@ -64,6 +64,41 @@ function calculateCost(inputTokens, outputTokens, price, cachedTokens = 0, cache
64
64
  return regularInputCost + cachedReadCost + cacheCreationCost + outputCost;
65
65
  }
66
66
 
67
+ // src/exporters/cloud.ts
68
+ var DEFAULT_ENDPOINT = "https://api.tokenwatch.dev/v1/ingest";
69
+ var CloudExporter = class {
70
+ constructor(apiKey, endpoint) {
71
+ this.apiKey = apiKey;
72
+ this.endpoint = endpoint ?? DEFAULT_ENDPOINT;
73
+ }
74
+ apiKey;
75
+ endpoint;
76
+ export(entry) {
77
+ fetch(this.endpoint, {
78
+ method: "POST",
79
+ headers: {
80
+ "Content-Type": "application/json",
81
+ Authorization: `Bearer ${this.apiKey}`
82
+ },
83
+ body: JSON.stringify({
84
+ model: entry.model,
85
+ inputTokens: entry.inputTokens,
86
+ outputTokens: entry.outputTokens,
87
+ reasoningTokens: entry.reasoningTokens ?? 0,
88
+ cachedTokens: entry.cachedTokens ?? 0,
89
+ cacheCreationTokens: entry.cacheCreationTokens ?? 0,
90
+ costUSD: entry.costUSD,
91
+ sessionId: entry.sessionId,
92
+ userId: entry.userId,
93
+ feature: entry.feature,
94
+ metadata: entry.metadata,
95
+ timestamp: entry.timestamp
96
+ })
97
+ }).catch(() => {
98
+ });
99
+ }
100
+ };
101
+
67
102
  // src/core/suggestions.ts
68
103
  var PROVIDER_PREFIXES = ["gpt-", "claude-", "gemini-", "deepseek-"];
69
104
  function getProviderPrefix(model) {
@@ -155,6 +190,7 @@ var SqliteStorage = class {
155
190
  user_id TEXT,
156
191
  feature TEXT,
157
192
  app_id TEXT,
193
+ metadata TEXT,
158
194
  timestamp TEXT NOT NULL
159
195
  )
160
196
  `);
@@ -174,13 +210,16 @@ var SqliteStorage = class {
174
210
  if (!cols.includes("app_id")) {
175
211
  this.db.exec(`ALTER TABLE usage ADD COLUMN app_id TEXT`);
176
212
  }
213
+ if (!cols.includes("metadata")) {
214
+ this.db.exec(`ALTER TABLE usage ADD COLUMN metadata TEXT`);
215
+ }
177
216
  }
178
217
  record(entry) {
179
218
  this.db.prepare(
180
219
  `INSERT INTO usage
181
220
  (model, input_tokens, output_tokens, reasoning_tokens, cached_tokens, cache_creation_tokens,
182
- cost_usd, session_id, user_id, feature, app_id, timestamp)
183
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
221
+ cost_usd, session_id, user_id, feature, app_id, metadata, timestamp)
222
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
184
223
  ).run(
185
224
  entry.model,
186
225
  entry.inputTokens,
@@ -193,6 +232,7 @@ var SqliteStorage = class {
193
232
  entry.userId ?? null,
194
233
  entry.feature ?? null,
195
234
  entry.appId ?? null,
235
+ entry.metadata != null ? JSON.stringify(entry.metadata) : null,
196
236
  entry.timestamp
197
237
  );
198
238
  }
@@ -210,6 +250,7 @@ var SqliteStorage = class {
210
250
  ...r.user_id != null && { userId: r.user_id },
211
251
  ...r.feature != null && { feature: r.feature },
212
252
  ...r.app_id != null && { appId: r.app_id },
253
+ ...r.metadata != null && { metadata: JSON.parse(r.metadata) },
213
254
  timestamp: r.timestamp
214
255
  }));
215
256
  }
@@ -1725,7 +1766,9 @@ var TrackerConfigSchema = import_zod.z.object({
1725
1766
  mode: import_zod.z.enum(["once", "always"]).optional().default("once")
1726
1767
  }).optional(),
1727
1768
  exporter: import_zod.z.custom((v) => v !== null && typeof v === "object" && typeof v.export === "function").optional(),
1728
- appId: import_zod.z.string().optional()
1769
+ appId: import_zod.z.string().optional(),
1770
+ cloudApiKey: import_zod.z.string().optional(),
1771
+ cloudEndpoint: import_zod.z.string().url().optional()
1729
1772
  });
1730
1773
  function createTracker(config = {}) {
1731
1774
  const parsed = TrackerConfigSchema.safeParse(config);
@@ -1745,9 +1788,12 @@ ${issues}`);
1745
1788
  suggestions,
1746
1789
  anomalyDetection,
1747
1790
  exporter,
1748
- appId
1791
+ appId,
1792
+ cloudApiKey,
1793
+ cloudEndpoint
1749
1794
  } = parsed.data;
1750
1795
  const storage = typeof storageOption === "object" ? storageOption : createStorage(storageOption);
1796
+ const cloudExporter = cloudApiKey ? new CloudExporter(cloudApiKey, cloudEndpoint) : null;
1751
1797
  let remotePrices;
1752
1798
  let pricesUpdatedAt = bundledUpdatedAt;
1753
1799
  if (syncPrices) {
@@ -1808,6 +1854,9 @@ ${issues}`);
1808
1854
  Promise.resolve(exporter.export(full)).catch(() => {
1809
1855
  });
1810
1856
  }
1857
+ if (cloudExporter) {
1858
+ cloudExporter.export(full);
1859
+ }
1811
1860
  maybeFireAlerts(full);
1812
1861
  if (anomalyDetection) maybeDetectAnomaly(full);
1813
1862
  if (suggestions) {
@@ -1889,6 +1938,7 @@ ${issues}`);
1889
1938
  const byUser = {};
1890
1939
  const byFeature = {};
1891
1940
  const byApp = {};
1941
+ const byMetadata = {};
1892
1942
  let totalInput = 0;
1893
1943
  let totalOutput = 0;
1894
1944
  let totalCost = 0;
@@ -1930,6 +1980,14 @@ ${issues}`);
1930
1980
  a.costUSD += e.costUSD;
1931
1981
  a.calls += 1;
1932
1982
  }
1983
+ if (e.metadata) {
1984
+ for (const [key, val] of Object.entries(e.metadata)) {
1985
+ const group = byMetadata[key] ??= {};
1986
+ const slot = group[val] ??= { costUSD: 0, calls: 0 };
1987
+ slot.costUSD += e.costUSD;
1988
+ slot.calls += 1;
1989
+ }
1990
+ }
1933
1991
  }
1934
1992
  if (options && entries.length > 0) {
1935
1993
  periodFrom = entries[0]?.timestamp ?? periodFrom;
@@ -1942,6 +2000,7 @@ ${issues}`);
1942
2000
  byUser,
1943
2001
  byFeature,
1944
2002
  byApp,
2003
+ byMetadata,
1945
2004
  period: { from: periodFrom, to: lastTimestamp },
1946
2005
  ...pricesUpdatedAt ? { pricesUpdatedAt } : {}
1947
2006
  };
@@ -2046,7 +2105,7 @@ ${issues}`);
2046
2105
  }
2047
2106
  async function exportCSV() {
2048
2107
  const entries = await Promise.resolve(storage.getAll());
2049
- const header = "timestamp,model,inputTokens,outputTokens,reasoningTokens,cachedTokens,cacheCreationTokens,costUSD,sessionId,userId,feature,appId";
2108
+ const header = "timestamp,model,inputTokens,outputTokens,reasoningTokens,cachedTokens,cacheCreationTokens,costUSD,sessionId,userId,feature,appId,metadata";
2050
2109
  const rows = entries.map(
2051
2110
  (e) => [
2052
2111
  csvEscape(e.timestamp),
@@ -2060,7 +2119,8 @@ ${issues}`);
2060
2119
  csvEscape(e.sessionId ?? ""),
2061
2120
  csvEscape(e.userId ?? ""),
2062
2121
  csvEscape(e.feature ?? ""),
2063
- csvEscape(e.appId ?? "")
2122
+ csvEscape(e.appId ?? ""),
2123
+ csvEscape(e.metadata ? JSON.stringify(e.metadata) : "")
2064
2124
  ].join(",")
2065
2125
  );
2066
2126
  return [header, ...rows].join("\n");
@@ -2132,6 +2192,7 @@ function emptyReport() {
2132
2192
  byUser: {},
2133
2193
  byFeature: {},
2134
2194
  byApp: {},
2195
+ byMetadata: {},
2135
2196
  period: { from: now, to: now }
2136
2197
  };
2137
2198
  }
@@ -2188,12 +2249,13 @@ function createLazyTracker() {
2188
2249
 
2189
2250
  // src/providers/openai.ts
2190
2251
  function extractMeta(params) {
2191
- const { __sessionId, __userId, __feature, ...cleaned } = params;
2252
+ const { __sessionId, __userId, __feature, __metadata, ...cleaned } = params;
2192
2253
  return {
2193
2254
  cleaned,
2194
2255
  sessionId: typeof __sessionId === "string" ? __sessionId : void 0,
2195
2256
  userId: typeof __userId === "string" ? __userId : void 0,
2196
- feature: typeof __feature === "string" ? __feature : void 0
2257
+ feature: typeof __feature === "string" ? __feature : void 0,
2258
+ metadata: __metadata != null && typeof __metadata === "object" ? __metadata : void 0
2197
2259
  };
2198
2260
  }
2199
2261
  function extractUsage(usage) {
@@ -2208,7 +2270,7 @@ function extractUsage(usage) {
2208
2270
  cachedTokens
2209
2271
  };
2210
2272
  }
2211
- function trackWithMeta(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens = 0) {
2273
+ function trackWithMeta(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens = 0, metadata) {
2212
2274
  tracker.track({
2213
2275
  model,
2214
2276
  inputTokens,
@@ -2217,10 +2279,11 @@ function trackWithMeta(tracker, model, inputTokens, outputTokens, reasoningToken
2217
2279
  ...cachedTokens > 0 && { cachedTokens },
2218
2280
  ...sessionId !== void 0 && { sessionId },
2219
2281
  ...userId !== void 0 && { userId },
2220
- ...feature !== void 0 && { feature }
2282
+ ...feature !== void 0 && { feature },
2283
+ ...metadata !== void 0 && { metadata }
2221
2284
  });
2222
2285
  }
2223
- async function* wrapStream(stream, model, sessionId, userId, feature, tracker) {
2286
+ async function* wrapStream(stream, model, sessionId, userId, feature, tracker, metadata) {
2224
2287
  let lastChunk;
2225
2288
  for await (const chunk of stream) {
2226
2289
  lastChunk = chunk;
@@ -2232,7 +2295,7 @@ async function* wrapStream(stream, model, sessionId, userId, feature, tracker) {
2232
2295
  `[tokenwatch] No usage data in stream for model "${model}". Cost recorded as $0. Pass stream_options: { include_usage: true } to get accurate costs.`
2233
2296
  );
2234
2297
  }
2235
- trackWithMeta(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens);
2298
+ trackWithMeta(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens, metadata);
2236
2299
  }
2237
2300
  function wrapOpenAI(client, tracker) {
2238
2301
  const proxiedCompletions = new Proxy(client.chat.completions, {
@@ -2240,7 +2303,7 @@ function wrapOpenAI(client, tracker) {
2240
2303
  if (prop !== "create")
2241
2304
  return target[prop];
2242
2305
  return async function(params) {
2243
- const { cleaned, sessionId, userId, feature } = extractMeta(params);
2306
+ const { cleaned, sessionId, userId, feature, metadata } = extractMeta(params);
2244
2307
  const model = typeof cleaned["model"] === "string" ? cleaned["model"] : "unknown";
2245
2308
  const result = await target.create(cleaned);
2246
2309
  if (result && typeof result === "object" && Symbol.asyncIterator in result) {
@@ -2250,7 +2313,8 @@ function wrapOpenAI(client, tracker) {
2250
2313
  sessionId,
2251
2314
  userId,
2252
2315
  feature,
2253
- tracker
2316
+ tracker,
2317
+ metadata
2254
2318
  );
2255
2319
  }
2256
2320
  const completion = result;
@@ -2264,7 +2328,8 @@ function wrapOpenAI(client, tracker) {
2264
2328
  sessionId,
2265
2329
  userId,
2266
2330
  feature,
2267
- cachedTokens
2331
+ cachedTokens,
2332
+ metadata
2268
2333
  );
2269
2334
  return result;
2270
2335
  };
@@ -2281,12 +2346,12 @@ function wrapOpenAI(client, tracker) {
2281
2346
  if (prop !== "create")
2282
2347
  return target[prop];
2283
2348
  return async function(params) {
2284
- const { cleaned, sessionId, userId, feature } = extractMeta(params);
2349
+ const { cleaned, sessionId, userId, feature, metadata } = extractMeta(params);
2285
2350
  const model = typeof cleaned["model"] === "string" ? cleaned["model"] : "unknown";
2286
2351
  const result = await target.create(cleaned);
2287
2352
  const embedding = result;
2288
2353
  const inputTokens = embedding.usage?.total_tokens ?? 0;
2289
- trackWithMeta(tracker, embedding.model ?? model, inputTokens, 0, 0, sessionId, userId, feature);
2354
+ trackWithMeta(tracker, embedding.model ?? model, inputTokens, 0, 0, sessionId, userId, feature, 0, metadata);
2290
2355
  return result;
2291
2356
  };
2292
2357
  }
@@ -2302,12 +2367,13 @@ function wrapOpenAI(client, tracker) {
2302
2367
 
2303
2368
  // src/providers/anthropic.ts
2304
2369
  function extractMeta2(params) {
2305
- const { __sessionId, __userId, __feature, ...cleaned } = params;
2370
+ const { __sessionId, __userId, __feature, __metadata, ...cleaned } = params;
2306
2371
  return {
2307
2372
  cleaned,
2308
2373
  sessionId: typeof __sessionId === "string" ? __sessionId : void 0,
2309
2374
  userId: typeof __userId === "string" ? __userId : void 0,
2310
- feature: typeof __feature === "string" ? __feature : void 0
2375
+ feature: typeof __feature === "string" ? __feature : void 0,
2376
+ metadata: __metadata != null && typeof __metadata === "object" ? __metadata : void 0
2311
2377
  };
2312
2378
  }
2313
2379
  function extractUsage2(usage) {
@@ -2324,7 +2390,7 @@ function extractThinkingTokenApprox(content) {
2324
2390
  const chars = content.filter((b) => b.type === "thinking").reduce((sum, b) => sum + (b.thinking?.length ?? 0), 0);
2325
2391
  return chars > 0 ? Math.round(chars / 4) : 0;
2326
2392
  }
2327
- function trackWithMeta2(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens = 0, cacheCreationTokens = 0) {
2393
+ function trackWithMeta2(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens = 0, cacheCreationTokens = 0, metadata) {
2328
2394
  tracker.track({
2329
2395
  model,
2330
2396
  inputTokens,
@@ -2334,10 +2400,11 @@ function trackWithMeta2(tracker, model, inputTokens, outputTokens, reasoningToke
2334
2400
  ...cacheCreationTokens > 0 && { cacheCreationTokens },
2335
2401
  ...sessionId !== void 0 && { sessionId },
2336
2402
  ...userId !== void 0 && { userId },
2337
- ...feature !== void 0 && { feature }
2403
+ ...feature !== void 0 && { feature },
2404
+ ...metadata !== void 0 && { metadata }
2338
2405
  });
2339
2406
  }
2340
- async function* wrapStream2(stream, model, sessionId, userId, feature, tracker) {
2407
+ async function* wrapStream2(stream, model, sessionId, userId, feature, tracker, metadata) {
2341
2408
  let inputTokens = 0;
2342
2409
  let outputTokens = 0;
2343
2410
  let cachedTokens = 0;
@@ -2365,7 +2432,7 @@ async function* wrapStream2(stream, model, sessionId, userId, feature, tracker)
2365
2432
  }
2366
2433
  }
2367
2434
  const reasoningTokens = thinkingCharCount > 0 ? Math.round(thinkingCharCount / 4) : 0;
2368
- trackWithMeta2(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens, cacheCreationTokens);
2435
+ trackWithMeta2(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens, cacheCreationTokens, metadata);
2369
2436
  }
2370
2437
  function wrapAnthropic(client, tracker) {
2371
2438
  const proxiedMessages = new Proxy(client.messages, {
@@ -2373,7 +2440,7 @@ function wrapAnthropic(client, tracker) {
2373
2440
  if (prop !== "create")
2374
2441
  return target[prop];
2375
2442
  return async function(params) {
2376
- const { cleaned, sessionId, userId, feature } = extractMeta2(params);
2443
+ const { cleaned, sessionId, userId, feature, metadata } = extractMeta2(params);
2377
2444
  const model = typeof cleaned["model"] === "string" ? cleaned["model"] : "unknown";
2378
2445
  const result = await target.create(cleaned);
2379
2446
  if (result && typeof result === "object" && Symbol.asyncIterator in result) {
@@ -2383,7 +2450,8 @@ function wrapAnthropic(client, tracker) {
2383
2450
  sessionId,
2384
2451
  userId,
2385
2452
  feature,
2386
- tracker
2453
+ tracker,
2454
+ metadata
2387
2455
  );
2388
2456
  }
2389
2457
  const message = result;
@@ -2399,7 +2467,8 @@ function wrapAnthropic(client, tracker) {
2399
2467
  userId,
2400
2468
  feature,
2401
2469
  cachedTokens,
2402
- cacheCreationTokens
2470
+ cacheCreationTokens,
2471
+ metadata
2403
2472
  );
2404
2473
  return result;
2405
2474
  };
@@ -2420,10 +2489,11 @@ function wrapGemini(client, tracker) {
2420
2489
  if (prop !== "getGenerativeModel")
2421
2490
  return target[prop];
2422
2491
  return function(modelParams) {
2423
- const { __sessionId, __userId, __feature, ...cleanedParams } = modelParams;
2492
+ const { __sessionId, __userId, __feature, __metadata, ...cleanedParams } = modelParams;
2424
2493
  const feature = typeof __feature === "string" ? __feature : void 0;
2425
2494
  const sessionId = typeof __sessionId === "string" ? __sessionId : void 0;
2426
2495
  const userId = typeof __userId === "string" ? __userId : void 0;
2496
+ const metadata = __metadata != null && typeof __metadata === "object" ? __metadata : void 0;
2427
2497
  const modelInstance = target.getGenerativeModel(cleanedParams);
2428
2498
  const modelId = modelParams.model;
2429
2499
  return new Proxy(modelInstance, {
@@ -2438,7 +2508,8 @@ function wrapGemini(client, tracker) {
2438
2508
  outputTokens: meta?.candidatesTokenCount ?? 0,
2439
2509
  ...sessionId !== void 0 && { sessionId },
2440
2510
  ...userId !== void 0 && { userId },
2441
- ...feature !== void 0 && { feature }
2511
+ ...feature !== void 0 && { feature },
2512
+ ...metadata !== void 0 && { metadata }
2442
2513
  });
2443
2514
  return result;
2444
2515
  };
@@ -2454,7 +2525,8 @@ function wrapGemini(client, tracker) {
2454
2525
  outputTokens: meta?.candidatesTokenCount ?? 0,
2455
2526
  ...sessionId !== void 0 && { sessionId },
2456
2527
  ...userId !== void 0 && { userId },
2457
- ...feature !== void 0 && { feature }
2528
+ ...feature !== void 0 && { feature },
2529
+ ...metadata !== void 0 && { metadata }
2458
2530
  });
2459
2531
  }).catch(() => {
2460
2532
  });