tokenmeter 0.9.0 → 0.9.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 (54) hide show
  1. package/README.md +220 -6
  2. package/dist/config.d.ts +7 -84
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +7 -158
  5. package/dist/config.js.map +1 -1
  6. package/dist/exporter/PostgresExporter.d.ts.map +1 -1
  7. package/dist/exporter/PostgresExporter.js +4 -2
  8. package/dist/exporter/PostgresExporter.js.map +1 -1
  9. package/dist/index.d.ts +3 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/instrumentation/proxy.d.ts.map +1 -1
  14. package/dist/instrumentation/proxy.js +279 -51
  15. package/dist/instrumentation/proxy.js.map +1 -1
  16. package/dist/instrumentation/strategies/index.d.ts +33 -0
  17. package/dist/instrumentation/strategies/index.d.ts.map +1 -1
  18. package/dist/instrumentation/strategies/index.js +146 -17
  19. package/dist/instrumentation/strategies/index.js.map +1 -1
  20. package/dist/integrations/inngest/index.d.ts +0 -38
  21. package/dist/integrations/inngest/index.d.ts.map +1 -1
  22. package/dist/integrations/inngest/index.js +0 -49
  23. package/dist/integrations/inngest/index.js.map +1 -1
  24. package/dist/integrations/vercel-ai/index.d.ts.map +1 -1
  25. package/dist/integrations/vercel-ai/index.js +2 -1
  26. package/dist/integrations/vercel-ai/index.js.map +1 -1
  27. package/dist/pricing/manifest.bundled.d.ts +24 -0
  28. package/dist/pricing/manifest.bundled.d.ts.map +1 -0
  29. package/dist/pricing/manifest.bundled.js +13347 -0
  30. package/dist/pricing/manifest.bundled.js.map +1 -0
  31. package/dist/pricing/manifest.d.ts +24 -10
  32. package/dist/pricing/manifest.d.ts.map +1 -1
  33. package/dist/pricing/manifest.js +189 -118
  34. package/dist/pricing/manifest.js.map +1 -1
  35. package/dist/pricing/schema.d.ts +22 -13
  36. package/dist/pricing/schema.d.ts.map +1 -1
  37. package/dist/pricing/schema.js +5 -2
  38. package/dist/pricing/schema.js.map +1 -1
  39. package/dist/processor/TokenMeterProcessor.d.ts +37 -7
  40. package/dist/processor/TokenMeterProcessor.d.ts.map +1 -1
  41. package/dist/processor/TokenMeterProcessor.js +45 -24
  42. package/dist/processor/TokenMeterProcessor.js.map +1 -1
  43. package/dist/query/client.d.ts +0 -24
  44. package/dist/query/client.d.ts.map +1 -1
  45. package/dist/query/client.js +42 -9
  46. package/dist/query/client.js.map +1 -1
  47. package/dist/registry.d.ts +127 -0
  48. package/dist/registry.d.ts.map +1 -0
  49. package/dist/registry.js +144 -0
  50. package/dist/registry.js.map +1 -0
  51. package/dist/types.d.ts +61 -5
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/types.js.map +1 -1
  54. package/package.json +3 -2
@@ -1,8 +1,31 @@
1
1
  /**
2
2
  * TokenMeter Span Processor
3
3
  *
4
- * An OpenTelemetry SpanProcessor that calculates costs based on usage data
5
- * and adds cost attributes to spans before they are exported.
4
+ * An OpenTelemetry SpanProcessor that calculates and logs costs for spans
5
+ * with usage data. Useful for debugging and observability of AI costs.
6
+ *
7
+ * ## Important Limitation
8
+ *
9
+ * This processor CANNOT add cost attributes to spans after they end.
10
+ * OpenTelemetry's `ReadableSpan` interface doesn't allow attribute modification
11
+ * after `span.end()` is called. The processor can only:
12
+ * - Log calculated costs for debugging
13
+ * - Validate pricing configuration
14
+ * - Use with `pricingOverrides` for cost estimation
15
+ *
16
+ * ## When to Use
17
+ *
18
+ * 1. **Debugging**: Verify cost calculations during development
19
+ * 2. **Monitoring non-monitor() spans**: Log costs for spans from external
20
+ * sources (e.g., Vercel AI SDK's experimental_telemetry) that already
21
+ * include usage data
22
+ *
23
+ * ## For Production Cost Tracking
24
+ *
25
+ * Use `monitor()` to wrap your AI clients instead - it calculates and adds
26
+ * `tokenmeter.cost_usd` to spans BEFORE they end, which is the proper approach.
27
+ *
28
+ * @see monitor() for production cost tracking
6
29
  */
7
30
  import type { Context } from "@opentelemetry/api";
8
31
  import type { SpanProcessor, ReadableSpan, Span } from "@opentelemetry/sdk-trace-base";
@@ -10,13 +33,18 @@ import type { TokenMeterProcessorConfig } from "../types.js";
10
33
  /**
11
34
  * TokenMeter SpanProcessor
12
35
  *
13
- * Intercepts spans on end and calculates costs based on usage attributes.
14
- * The calculated cost is added as an attribute before the span is exported.
36
+ * Calculates costs for spans with usage data and logs them.
37
+ *
38
+ * **Note**: This processor cannot add cost attributes to spans after they end.
39
+ * For production cost tracking, use `monitor()` instead.
15
40
  *
16
41
  * @example
17
42
  * ```typescript
18
43
  * import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
19
- * import { TokenMeterProcessor } from 'tokenmeter';
44
+ * import { TokenMeterProcessor, configureLogger } from 'tokenmeter';
45
+ *
46
+ * // Enable logging to see calculated costs
47
+ * configureLogger({ level: 'debug' });
20
48
  *
21
49
  * const provider = new NodeTracerProvider();
22
50
  * provider.addSpanProcessor(new TokenMeterProcessor());
@@ -33,9 +61,11 @@ export declare class TokenMeterProcessor implements SpanProcessor {
33
61
  /**
34
62
  * Called when a span starts (no-op for TokenMeter)
35
63
  */
36
- onStart(span: Span, parentContext: Context): void;
64
+ onStart(_span: Span, _parentContext: Context): void;
37
65
  /**
38
- * Called when a span ends - this is where we calculate and add cost
66
+ * Called when a span ends - calculates and logs cost.
67
+ *
68
+ * Note: Cannot add cost attribute to span after end() - use monitor() for that.
39
69
  */
40
70
  onEnd(span: ReadableSpan): void;
41
71
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"TokenMeterProcessor.d.ts","sourceRoot":"","sources":["../../src/processor/TokenMeterProcessor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,IAAI,EACL,MAAM,+BAA+B,CAAC;AAOvC,OAAO,KAAK,EAAE,yBAAyB,EAAmB,MAAM,aAAa,CAAC;AAG9E;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACvD,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,eAAe,CAA8B;IACrD,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,gBAAgB,CAA+B;gBAE3C,MAAM,GAAE,yBAA8B;YAQpC,iBAAiB;IAU/B;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,GAAG,IAAI;IAKjD;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAmD/B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA0BzB;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC;AAED,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"TokenMeterProcessor.d.ts","sourceRoot":"","sources":["../../src/processor/TokenMeterProcessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,IAAI,EACL,MAAM,+BAA+B,CAAC;AAOvC,OAAO,KAAK,EAAE,yBAAyB,EAAmB,MAAM,aAAa,CAAC;AAI9E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACvD,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,eAAe,CAA8B;IACrD,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,gBAAgB,CAA+B;gBAE3C,MAAM,GAAE,yBAA8B;YAQpC,iBAAiB;IAU/B;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,GAAG,IAAI;IAInD;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAuC/B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA0BzB;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC;AAED,eAAe,mBAAmB,CAAC"}
@@ -1,21 +1,50 @@
1
1
  /**
2
2
  * TokenMeter Span Processor
3
3
  *
4
- * An OpenTelemetry SpanProcessor that calculates costs based on usage data
5
- * and adds cost attributes to spans before they are exported.
4
+ * An OpenTelemetry SpanProcessor that calculates and logs costs for spans
5
+ * with usage data. Useful for debugging and observability of AI costs.
6
+ *
7
+ * ## Important Limitation
8
+ *
9
+ * This processor CANNOT add cost attributes to spans after they end.
10
+ * OpenTelemetry's `ReadableSpan` interface doesn't allow attribute modification
11
+ * after `span.end()` is called. The processor can only:
12
+ * - Log calculated costs for debugging
13
+ * - Validate pricing configuration
14
+ * - Use with `pricingOverrides` for cost estimation
15
+ *
16
+ * ## When to Use
17
+ *
18
+ * 1. **Debugging**: Verify cost calculations during development
19
+ * 2. **Monitoring non-monitor() spans**: Log costs for spans from external
20
+ * sources (e.g., Vercel AI SDK's experimental_telemetry) that already
21
+ * include usage data
22
+ *
23
+ * ## For Production Cost Tracking
24
+ *
25
+ * Use `monitor()` to wrap your AI clients instead - it calculates and adds
26
+ * `tokenmeter.cost_usd` to spans BEFORE they end, which is the proper approach.
27
+ *
28
+ * @see monitor() for production cost tracking
6
29
  */
7
30
  import { loadManifest, getModelPricing, calculateCost, getCachedManifest, } from "../pricing/manifest.js";
8
31
  import { TM_ATTRIBUTES, GEN_AI_ATTRIBUTES } from "../types.js";
32
+ import { logger } from "../logger.js";
9
33
  /**
10
34
  * TokenMeter SpanProcessor
11
35
  *
12
- * Intercepts spans on end and calculates costs based on usage attributes.
13
- * The calculated cost is added as an attribute before the span is exported.
36
+ * Calculates costs for spans with usage data and logs them.
37
+ *
38
+ * **Note**: This processor cannot add cost attributes to spans after they end.
39
+ * For production cost tracking, use `monitor()` instead.
14
40
  *
15
41
  * @example
16
42
  * ```typescript
17
43
  * import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
18
- * import { TokenMeterProcessor } from 'tokenmeter';
44
+ * import { TokenMeterProcessor, configureLogger } from 'tokenmeter';
45
+ *
46
+ * // Enable logging to see calculated costs
47
+ * configureLogger({ level: 'debug' });
19
48
  *
20
49
  * const provider = new NodeTracerProvider();
21
50
  * provider.addSpanProcessor(new TokenMeterProcessor());
@@ -40,21 +69,21 @@ export class TokenMeterProcessor {
40
69
  });
41
70
  }
42
71
  catch (error) {
43
- console.error("[tokenmeter] Failed to load pricing manifest:", error);
72
+ logger.error("Failed to load pricing manifest:", error);
44
73
  }
45
74
  }
46
75
  /**
47
76
  * Called when a span starts (no-op for TokenMeter)
48
77
  */
49
- onStart(span, parentContext) {
50
- // We don't need to do anything when spans start
51
- // Cost calculation happens on end
78
+ onStart(_span, _parentContext) {
79
+ // No-op: Cost calculation happens in onEnd
52
80
  }
53
81
  /**
54
- * Called when a span ends - this is where we calculate and add cost
82
+ * Called when a span ends - calculates and logs cost.
83
+ *
84
+ * Note: Cannot add cost attribute to span after end() - use monitor() for that.
55
85
  */
56
86
  onEnd(span) {
57
- // Get usage attributes from span
58
87
  const attrs = span.attributes;
59
88
  // Check if this span has usage data
60
89
  const inputUnits = attrs[TM_ATTRIBUTES.INPUT_UNITS] ||
@@ -77,18 +106,10 @@ export class TokenMeterProcessor {
77
106
  inputUnits,
78
107
  outputUnits,
79
108
  });
80
- // Add cost attribute to span
81
- // Note: OTel allows modifying span attributes after end but before export
82
- // We use a workaround by storing cost in the span's resource or via events
83
- // For now, we'll set it directly (works with most exporters)
109
+ // Log calculated cost for debugging
110
+ // Note: We cannot add this to the span - ReadableSpan is immutable after end()
84
111
  if (cost !== null) {
85
- // Unfortunately, ReadableSpan doesn't allow setting attributes after end
86
- // We need to use a custom approach - storing in a side channel or using events
87
- // For this implementation, we'll log a warning and add via span events
88
- // A production implementation would use a custom exporter or modify before end
89
- // The proper way is to calculate cost BEFORE span.end() in the proxy
90
- // This processor is for catching spans from other sources (like Vercel AI SDK)
91
- console.debug(`[tokenmeter] Calculated cost for ${provider}/${model}: $${cost.toFixed(6)}`);
112
+ logger.debug(`Calculated cost for ${provider}/${model}: $${cost.toFixed(6)}`);
92
113
  }
93
114
  }
94
115
  /**
@@ -102,12 +123,12 @@ export class TokenMeterProcessor {
102
123
  // Fall back to manifest
103
124
  const manifest = this.manifest || getCachedManifest();
104
125
  if (!manifest) {
105
- console.warn(`[tokenmeter] Pricing manifest not loaded, cannot calculate cost`);
126
+ logger.warn("Pricing manifest not loaded, cannot calculate cost");
106
127
  return null;
107
128
  }
108
129
  const pricing = getModelPricing(provider, model, manifest);
109
130
  if (!pricing) {
110
- console.warn(`[tokenmeter] No pricing found for ${provider}/${model}`);
131
+ logger.warn(`No pricing found for ${provider}/${model}`);
111
132
  return 0; // Return 0, not null, to indicate we tried but found no pricing
112
133
  }
113
134
  return calculateCost(usage, pricing);
@@ -1 +1 @@
1
- {"version":3,"file":"TokenMeterProcessor.js","sourceRoot":"","sources":["../../src/processor/TokenMeterProcessor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TokenMeterProcessor.js","sourceRoot":"","sources":["../../src/processor/TokenMeterProcessor.ts"],"names":[],"mappings":"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"}
@@ -32,30 +32,6 @@ export interface QueryClient {
32
32
  /** Close the database connection */
33
33
  close(): Promise<void>;
34
34
  }
35
- /**
36
- * Create a query client for cost aggregation
37
- *
38
- * @example
39
- * ```typescript
40
- * import { createQueryClient } from 'tokenmeter/query';
41
- *
42
- * const client = createQueryClient({
43
- * connectionString: process.env.DATABASE_URL,
44
- * });
45
- *
46
- * // Get total costs for an organization
47
- * const orgCosts = await client.getCostByOrg('org_123', {
48
- * from: '2024-01-01',
49
- * to: '2024-01-31',
50
- * groupBy: ['model'],
51
- * });
52
- *
53
- * console.log(`Total: $${orgCosts.totalCost}`);
54
- * for (const group of orgCosts.groups ?? []) {
55
- * console.log(` ${group.key.model}: $${group.cost}`);
56
- * }
57
- * ```
58
- */
59
35
  export declare function createQueryClient(config: QueryClientConfig): Promise<QueryClient>;
60
36
  export default createQueryClient;
61
37
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/query/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAUhE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1D,oCAAoC;IACpC,aAAa,CACX,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GACzC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,4CAA4C;IAC5C,YAAY,CACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,GACjD,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,qCAAqC;IACrC,cAAc,CACZ,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GACxC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,wCAAwC;IACxC,iBAAiB,CACf,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,GAC3C,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,0CAA0C;IAC1C,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACzD,oCAAoC;IACpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,WAAW,CAAC,CAqOtB;AAED,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/query/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAUhE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1D,oCAAoC;IACpC,aAAa,CACX,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GACzC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,4CAA4C;IAC5C,YAAY,CACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,GACjD,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,qCAAqC;IACrC,cAAc,CACZ,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GACxC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,wCAAwC;IACxC,iBAAiB,CACf,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,GAC3C,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,0CAA0C;IAC1C,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACzD,oCAAoC;IACpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AA4CD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,WAAW,CAAC,CA+PtB;AAED,eAAe,iBAAiB,CAAC"}
@@ -27,13 +27,36 @@
27
27
  * }
28
28
  * ```
29
29
  */
30
+ /**
31
+ * Validate table name to prevent SQL injection
32
+ */
33
+ function validateTableName(name) {
34
+ // Only allow alphanumeric characters and underscores
35
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
36
+ throw new Error(`Invalid table name: "${name}". Table names must start with a letter or underscore and contain only alphanumeric characters and underscores.`);
37
+ }
38
+ // Limit length to prevent abuse
39
+ if (name.length > 63) {
40
+ throw new Error(`Table name too long: "${name}". Maximum length is 63 characters.`);
41
+ }
42
+ }
30
43
  export async function createQueryClient(config) {
31
44
  const tableName = config.tableName ?? "tokenmeter_events";
45
+ // Validate table name to prevent SQL injection
46
+ validateTableName(tableName);
32
47
  // Dynamic import to avoid requiring pg at load time
33
48
  const { Pool } = await import("pg");
34
49
  const pool = new Pool({
35
50
  connectionString: config.connectionString,
36
51
  });
52
+ // Test connection on initialization
53
+ try {
54
+ await pool.query("SELECT 1");
55
+ }
56
+ catch (error) {
57
+ await pool.end();
58
+ throw new Error(`Failed to connect to database: ${error instanceof Error ? error.message : "Unknown error"}`);
59
+ }
37
60
  /**
38
61
  * Build WHERE clause from options
39
62
  */
@@ -75,17 +98,27 @@ export async function createQueryClient(config) {
75
98
  return { clause, values, nextIndex: paramIndex };
76
99
  }
77
100
  /**
78
- * Map groupBy field names to column names
101
+ * Allowed groupBy fields (whitelist for SQL injection prevention)
102
+ */
103
+ const ALLOWED_GROUP_BY_FIELDS = {
104
+ provider: "provider",
105
+ model: "model",
106
+ organizationId: "organization_id",
107
+ userId: "user_id",
108
+ workflowId: "workflow_id",
109
+ };
110
+ /**
111
+ * Map groupBy field names to column names.
112
+ * Throws an error for unknown fields to prevent SQL injection.
113
+ *
114
+ * @throws {Error} If field is not in the allowed whitelist
79
115
  */
80
116
  function mapGroupByField(field) {
81
- const fieldMap = {
82
- provider: "provider",
83
- model: "model",
84
- organizationId: "organization_id",
85
- userId: "user_id",
86
- workflowId: "workflow_id",
87
- };
88
- return fieldMap[field] ?? field;
117
+ const column = ALLOWED_GROUP_BY_FIELDS[field];
118
+ if (!column) {
119
+ throw new Error(`Invalid groupBy field: "${field}". Allowed fields: ${Object.keys(ALLOWED_GROUP_BY_FIELDS).join(", ")}`);
120
+ }
121
+ return column;
89
122
  }
90
123
  /**
91
124
  * Execute a cost query
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/query/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/query/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Provider Registry
3
+ *
4
+ * Extensible system for registering custom AI providers.
5
+ * Allows users to add support for new providers without modifying core code.
6
+ */
7
+ import type { ExtractionStrategy, UsageData } from "./types.js";
8
+ /**
9
+ * Symbol used to mark objects with their provider.
10
+ * Allows explicit provider identification without duck-typing.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { TOKENMETER_PROVIDER } from 'tokenmeter';
15
+ *
16
+ * const client = new CustomAIClient();
17
+ * client[TOKENMETER_PROVIDER] = 'custom-ai';
18
+ *
19
+ * const monitored = monitor(client); // Will use 'custom-ai' as provider
20
+ * ```
21
+ */
22
+ export declare const TOKENMETER_PROVIDER: unique symbol;
23
+ /**
24
+ * Configuration for registering a custom provider
25
+ */
26
+ export interface ProviderConfig {
27
+ /** Unique provider identifier (e.g., 'google-ai', 'custom-llm') */
28
+ name: string;
29
+ /**
30
+ * Function to detect if a client belongs to this provider.
31
+ * Called during monitor() if no explicit provider is set.
32
+ *
33
+ * @param client - The client instance being monitored
34
+ * @returns true if this provider should handle the client
35
+ */
36
+ detect?: (client: unknown) => boolean;
37
+ /**
38
+ * Function to extract usage data from API responses.
39
+ *
40
+ * @param response - The API response
41
+ * @param args - The original arguments passed to the API call
42
+ * @returns Usage data or null if extraction failed
43
+ */
44
+ extractUsage?: (response: unknown, args: unknown[]) => Partial<UsageData> | null;
45
+ /**
46
+ * Function to extract the model name from request args or response.
47
+ *
48
+ * @param args - The original arguments passed to the API call
49
+ * @param response - The API response (if available)
50
+ * @returns Model identifier string
51
+ */
52
+ extractModel?: (args: unknown[], response?: unknown) => string;
53
+ /**
54
+ * List of method names that are factory methods returning objects to be proxied.
55
+ * These methods won't create spans but their return values will be wrapped.
56
+ *
57
+ * @example ['getGenerativeModel', 'createClient', 'getModel']
58
+ */
59
+ factoryMethods?: string[];
60
+ /**
61
+ * Full extraction strategy (alternative to extractUsage/extractModel).
62
+ * If provided, this takes precedence over extractUsage and extractModel.
63
+ */
64
+ strategy?: ExtractionStrategy;
65
+ }
66
+ /**
67
+ * Register a custom provider with tokenmeter.
68
+ *
69
+ * This is the recommended way to add support for new AI providers
70
+ * without modifying the core library code.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * import { registerProvider } from 'tokenmeter';
75
+ *
76
+ * registerProvider({
77
+ * name: 'my-ai-provider',
78
+ * detect: (client) => 'generateText' in client && 'myProvider' in client,
79
+ * extractUsage: (response) => ({
80
+ * inputUnits: response.usage?.inputTokens,
81
+ * outputUnits: response.usage?.outputTokens,
82
+ * }),
83
+ * extractModel: (args) => args[0]?.model || 'unknown',
84
+ * factoryMethods: ['createModel'],
85
+ * });
86
+ *
87
+ * // Now you can monitor your custom client
88
+ * const client = monitor(new MyAIProvider());
89
+ * ```
90
+ */
91
+ export declare function registerProvider(config: ProviderConfig): void;
92
+ /**
93
+ * Unregister a provider
94
+ */
95
+ export declare function unregisterProvider(name: string): boolean;
96
+ /**
97
+ * Get a registered provider by name
98
+ */
99
+ export declare function getProvider(name: string): ProviderConfig | undefined;
100
+ /**
101
+ * Get all registered providers
102
+ */
103
+ export declare function getRegisteredProviders(): ProviderConfig[];
104
+ /**
105
+ * Clear all registered providers (useful for testing)
106
+ */
107
+ export declare function clearProviderRegistry(): void;
108
+ /**
109
+ * Detect provider from a client using the registry.
110
+ * Returns the first matching provider or undefined.
111
+ *
112
+ * @internal
113
+ */
114
+ export declare function detectProviderFromRegistry(client: unknown): string | undefined;
115
+ /**
116
+ * Get factory methods for a provider
117
+ *
118
+ * @internal
119
+ */
120
+ export declare function getFactoryMethods(provider: string): string[];
121
+ /**
122
+ * Get extraction strategy for a provider from the registry
123
+ *
124
+ * @internal
125
+ */
126
+ export declare function getRegisteredStrategy(provider: string): ExtractionStrategy | undefined;
127
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEhE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,eAAoC,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAEtC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CACb,QAAQ,EAAE,OAAO,EACjB,IAAI,EAAE,OAAO,EAAE,KACZ,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAE/B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IAE/D;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAOD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAoC7D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEpE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,cAAc,EAAE,CAEzD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAkB9E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAG5D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,GACf,kBAAkB,GAAG,SAAS,CAGhC"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Provider Registry
3
+ *
4
+ * Extensible system for registering custom AI providers.
5
+ * Allows users to add support for new providers without modifying core code.
6
+ */
7
+ /**
8
+ * Symbol used to mark objects with their provider.
9
+ * Allows explicit provider identification without duck-typing.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { TOKENMETER_PROVIDER } from 'tokenmeter';
14
+ *
15
+ * const client = new CustomAIClient();
16
+ * client[TOKENMETER_PROVIDER] = 'custom-ai';
17
+ *
18
+ * const monitored = monitor(client); // Will use 'custom-ai' as provider
19
+ * ```
20
+ */
21
+ export const TOKENMETER_PROVIDER = Symbol.for("tokenmeter.provider");
22
+ /**
23
+ * Internal registry storage
24
+ */
25
+ const providerRegistry = new Map();
26
+ /**
27
+ * Register a custom provider with tokenmeter.
28
+ *
29
+ * This is the recommended way to add support for new AI providers
30
+ * without modifying the core library code.
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * import { registerProvider } from 'tokenmeter';
35
+ *
36
+ * registerProvider({
37
+ * name: 'my-ai-provider',
38
+ * detect: (client) => 'generateText' in client && 'myProvider' in client,
39
+ * extractUsage: (response) => ({
40
+ * inputUnits: response.usage?.inputTokens,
41
+ * outputUnits: response.usage?.outputTokens,
42
+ * }),
43
+ * extractModel: (args) => args[0]?.model || 'unknown',
44
+ * factoryMethods: ['createModel'],
45
+ * });
46
+ *
47
+ * // Now you can monitor your custom client
48
+ * const client = monitor(new MyAIProvider());
49
+ * ```
50
+ */
51
+ export function registerProvider(config) {
52
+ if (!config.name) {
53
+ throw new Error("Provider name is required");
54
+ }
55
+ // If strategy is not provided, create one from extractUsage/extractModel
56
+ if (!config.strategy && config.extractUsage) {
57
+ config.strategy = {
58
+ provider: config.name,
59
+ canHandle: (_methodPath, result) => {
60
+ // Try to extract usage - if it succeeds, we can handle this result
61
+ const usage = config.extractUsage(result, []);
62
+ return usage !== null;
63
+ },
64
+ extract: (_methodPath, result, args) => {
65
+ const partialUsage = config.extractUsage(result, args);
66
+ if (!partialUsage)
67
+ return null;
68
+ const model = config.extractModel
69
+ ? config.extractModel(args, result)
70
+ : "unknown";
71
+ return {
72
+ provider: config.name,
73
+ model,
74
+ ...partialUsage,
75
+ };
76
+ },
77
+ };
78
+ }
79
+ providerRegistry.set(config.name, config);
80
+ }
81
+ /**
82
+ * Unregister a provider
83
+ */
84
+ export function unregisterProvider(name) {
85
+ return providerRegistry.delete(name);
86
+ }
87
+ /**
88
+ * Get a registered provider by name
89
+ */
90
+ export function getProvider(name) {
91
+ return providerRegistry.get(name);
92
+ }
93
+ /**
94
+ * Get all registered providers
95
+ */
96
+ export function getRegisteredProviders() {
97
+ return Array.from(providerRegistry.values());
98
+ }
99
+ /**
100
+ * Clear all registered providers (useful for testing)
101
+ */
102
+ export function clearProviderRegistry() {
103
+ providerRegistry.clear();
104
+ }
105
+ /**
106
+ * Detect provider from a client using the registry.
107
+ * Returns the first matching provider or undefined.
108
+ *
109
+ * @internal
110
+ */
111
+ export function detectProviderFromRegistry(client) {
112
+ // First, check for explicit Symbol-based provider
113
+ if (client &&
114
+ typeof client === "object" &&
115
+ TOKENMETER_PROVIDER in client) {
116
+ return client[TOKENMETER_PROVIDER];
117
+ }
118
+ // Then check registered providers
119
+ for (const [name, config] of providerRegistry) {
120
+ if (config.detect && config.detect(client)) {
121
+ return name;
122
+ }
123
+ }
124
+ return undefined;
125
+ }
126
+ /**
127
+ * Get factory methods for a provider
128
+ *
129
+ * @internal
130
+ */
131
+ export function getFactoryMethods(provider) {
132
+ const config = providerRegistry.get(provider);
133
+ return config?.factoryMethods || [];
134
+ }
135
+ /**
136
+ * Get extraction strategy for a provider from the registry
137
+ *
138
+ * @internal
139
+ */
140
+ export function getRegisteredStrategy(provider) {
141
+ const config = providerRegistry.get(provider);
142
+ return config?.strategy;
143
+ }
144
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}