tokenmeter 0.9.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.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +346 -0
  3. package/dist/__tests__/context.test.d.ts +2 -0
  4. package/dist/__tests__/context.test.d.ts.map +1 -0
  5. package/dist/__tests__/context.test.js +94 -0
  6. package/dist/__tests__/context.test.js.map +1 -0
  7. package/dist/__tests__/elevenlabs.test.d.ts +2 -0
  8. package/dist/__tests__/elevenlabs.test.d.ts.map +1 -0
  9. package/dist/__tests__/elevenlabs.test.js +108 -0
  10. package/dist/__tests__/elevenlabs.test.js.map +1 -0
  11. package/dist/__tests__/fal.test.d.ts +2 -0
  12. package/dist/__tests__/fal.test.d.ts.map +1 -0
  13. package/dist/__tests__/fal.test.js +153 -0
  14. package/dist/__tests__/fal.test.js.map +1 -0
  15. package/dist/__tests__/pricing.test.d.ts +2 -0
  16. package/dist/__tests__/pricing.test.d.ts.map +1 -0
  17. package/dist/__tests__/pricing.test.js +76 -0
  18. package/dist/__tests__/pricing.test.js.map +1 -0
  19. package/dist/__tests__/recorder.test.d.ts +2 -0
  20. package/dist/__tests__/recorder.test.d.ts.map +1 -0
  21. package/dist/__tests__/recorder.test.js +133 -0
  22. package/dist/__tests__/recorder.test.js.map +1 -0
  23. package/dist/__tests__/storage.test.d.ts +2 -0
  24. package/dist/__tests__/storage.test.d.ts.map +1 -0
  25. package/dist/__tests__/storage.test.js +106 -0
  26. package/dist/__tests__/storage.test.js.map +1 -0
  27. package/dist/client/index.d.ts +8 -0
  28. package/dist/client/index.d.ts.map +1 -0
  29. package/dist/client/index.js +7 -0
  30. package/dist/client/index.js.map +1 -0
  31. package/dist/config.d.ts +92 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +166 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/context.d.ts +80 -0
  36. package/dist/context.d.ts.map +1 -0
  37. package/dist/context.js +131 -0
  38. package/dist/context.js.map +1 -0
  39. package/dist/exporter/PostgresExporter.d.ts +82 -0
  40. package/dist/exporter/PostgresExporter.d.ts.map +1 -0
  41. package/dist/exporter/PostgresExporter.js +237 -0
  42. package/dist/exporter/PostgresExporter.js.map +1 -0
  43. package/dist/exporter/index.d.ts +8 -0
  44. package/dist/exporter/index.d.ts.map +1 -0
  45. package/dist/exporter/index.js +7 -0
  46. package/dist/exporter/index.js.map +1 -0
  47. package/dist/index.d.ts +31 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +37 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/instrumentation/proxy.d.ts +26 -0
  52. package/dist/instrumentation/proxy.d.ts.map +1 -0
  53. package/dist/instrumentation/proxy.js +337 -0
  54. package/dist/instrumentation/proxy.js.map +1 -0
  55. package/dist/instrumentation/strategies/index.d.ts +55 -0
  56. package/dist/instrumentation/strategies/index.d.ts.map +1 -0
  57. package/dist/instrumentation/strategies/index.js +429 -0
  58. package/dist/instrumentation/strategies/index.js.map +1 -0
  59. package/dist/integrations/express/index.d.ts +137 -0
  60. package/dist/integrations/express/index.d.ts.map +1 -0
  61. package/dist/integrations/express/index.js +186 -0
  62. package/dist/integrations/express/index.js.map +1 -0
  63. package/dist/integrations/inngest/index.d.ts +222 -0
  64. package/dist/integrations/inngest/index.d.ts.map +1 -0
  65. package/dist/integrations/inngest/index.js +223 -0
  66. package/dist/integrations/inngest/index.js.map +1 -0
  67. package/dist/integrations/langfuse/index.d.ts +170 -0
  68. package/dist/integrations/langfuse/index.d.ts.map +1 -0
  69. package/dist/integrations/langfuse/index.js +225 -0
  70. package/dist/integrations/langfuse/index.js.map +1 -0
  71. package/dist/integrations/next/index.d.ts +138 -0
  72. package/dist/integrations/next/index.d.ts.map +1 -0
  73. package/dist/integrations/next/index.js +170 -0
  74. package/dist/integrations/next/index.js.map +1 -0
  75. package/dist/integrations/nextjs/index.d.ts +198 -0
  76. package/dist/integrations/nextjs/index.d.ts.map +1 -0
  77. package/dist/integrations/nextjs/index.js +181 -0
  78. package/dist/integrations/nextjs/index.js.map +1 -0
  79. package/dist/integrations/vercel-ai/index.d.ts +288 -0
  80. package/dist/integrations/vercel-ai/index.d.ts.map +1 -0
  81. package/dist/integrations/vercel-ai/index.js +260 -0
  82. package/dist/integrations/vercel-ai/index.js.map +1 -0
  83. package/dist/logger.d.ts +58 -0
  84. package/dist/logger.d.ts.map +1 -0
  85. package/dist/logger.js +89 -0
  86. package/dist/logger.js.map +1 -0
  87. package/dist/pricing/catalog.d.ts +10 -0
  88. package/dist/pricing/catalog.d.ts.map +1 -0
  89. package/dist/pricing/catalog.js +297 -0
  90. package/dist/pricing/catalog.js.map +1 -0
  91. package/dist/pricing/index.d.ts +77 -0
  92. package/dist/pricing/index.d.ts.map +1 -0
  93. package/dist/pricing/index.js +251 -0
  94. package/dist/pricing/index.js.map +1 -0
  95. package/dist/pricing/manifest.d.ts +156 -0
  96. package/dist/pricing/manifest.d.ts.map +1 -0
  97. package/dist/pricing/manifest.js +381 -0
  98. package/dist/pricing/manifest.js.map +1 -0
  99. package/dist/pricing/manifest.json +12786 -0
  100. package/dist/pricing/providers/anthropic.json +253 -0
  101. package/dist/pricing/providers/bedrock.json +341 -0
  102. package/dist/pricing/providers/bfl.json +220 -0
  103. package/dist/pricing/providers/elevenlabs.json +142 -0
  104. package/dist/pricing/providers/fal.json +15866 -0
  105. package/dist/pricing/providers/google.json +346 -0
  106. package/dist/pricing/providers/openai.json +1035 -0
  107. package/dist/pricing/schema.d.ts +102 -0
  108. package/dist/pricing/schema.d.ts.map +1 -0
  109. package/dist/pricing/schema.js +56 -0
  110. package/dist/pricing/schema.js.map +1 -0
  111. package/dist/processor/TokenMeterProcessor.d.ts +55 -0
  112. package/dist/processor/TokenMeterProcessor.d.ts.map +1 -0
  113. package/dist/processor/TokenMeterProcessor.js +132 -0
  114. package/dist/processor/TokenMeterProcessor.js.map +1 -0
  115. package/dist/query/client.d.ts +61 -0
  116. package/dist/query/client.d.ts.map +1 -0
  117. package/dist/query/client.js +206 -0
  118. package/dist/query/client.js.map +1 -0
  119. package/dist/query/index.d.ts +8 -0
  120. package/dist/query/index.d.ts.map +1 -0
  121. package/dist/query/index.js +7 -0
  122. package/dist/query/index.js.map +1 -0
  123. package/dist/recorder.d.ts +74 -0
  124. package/dist/recorder.d.ts.map +1 -0
  125. package/dist/recorder.js +227 -0
  126. package/dist/recorder.js.map +1 -0
  127. package/dist/sdks/anthropic.d.ts +21 -0
  128. package/dist/sdks/anthropic.d.ts.map +1 -0
  129. package/dist/sdks/anthropic.js +258 -0
  130. package/dist/sdks/anthropic.js.map +1 -0
  131. package/dist/sdks/elevenlabs.d.ts +59 -0
  132. package/dist/sdks/elevenlabs.d.ts.map +1 -0
  133. package/dist/sdks/elevenlabs.js +192 -0
  134. package/dist/sdks/elevenlabs.js.map +1 -0
  135. package/dist/sdks/fal.d.ts +102 -0
  136. package/dist/sdks/fal.d.ts.map +1 -0
  137. package/dist/sdks/fal.js +306 -0
  138. package/dist/sdks/fal.js.map +1 -0
  139. package/dist/sdks/openai.d.ts +17 -0
  140. package/dist/sdks/openai.d.ts.map +1 -0
  141. package/dist/sdks/openai.js +191 -0
  142. package/dist/sdks/openai.js.map +1 -0
  143. package/dist/storage/interface.d.ts +15 -0
  144. package/dist/storage/interface.d.ts.map +1 -0
  145. package/dist/storage/interface.js +53 -0
  146. package/dist/storage/interface.js.map +1 -0
  147. package/dist/storage/prisma.d.ts +15 -0
  148. package/dist/storage/prisma.d.ts.map +1 -0
  149. package/dist/storage/prisma.js +135 -0
  150. package/dist/storage/prisma.js.map +1 -0
  151. package/dist/types.d.ts +206 -0
  152. package/dist/types.d.ts.map +1 -0
  153. package/dist/types.js +45 -0
  154. package/dist/types.js.map +1 -0
  155. package/dist/vercel-ai/index.d.ts +89 -0
  156. package/dist/vercel-ai/index.d.ts.map +1 -0
  157. package/dist/vercel-ai/index.js +298 -0
  158. package/dist/vercel-ai/index.js.map +1 -0
  159. package/package.json +119 -0
@@ -0,0 +1,237 @@
1
+ /**
2
+ * PostgreSQL Span Exporter
3
+ *
4
+ * Exports tokenmeter cost spans to PostgreSQL for persistence and querying.
5
+ */
6
+ import { ExportResultCode } from "@opentelemetry/core";
7
+ import { TM_ATTRIBUTES } from "../types.js";
8
+ import { logger } from "../logger.js";
9
+ /**
10
+ * PostgreSQL exporter for tokenmeter cost spans
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
15
+ * import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
16
+ * import { PostgresExporter } from 'tokenmeter/exporter';
17
+ *
18
+ * const exporter = new PostgresExporter({
19
+ * connectionString: process.env.DATABASE_URL,
20
+ * });
21
+ *
22
+ * const provider = new NodeTracerProvider();
23
+ * provider.addSpanProcessor(new BatchSpanProcessor(exporter));
24
+ * provider.register();
25
+ * ```
26
+ */
27
+ export class PostgresExporter {
28
+ config;
29
+ pool = null;
30
+ buffer = [];
31
+ flushTimer = null;
32
+ flushPromise = null;
33
+ isShuttingDown = false;
34
+ constructor(config) {
35
+ this.config = {
36
+ connectionString: config.connectionString,
37
+ tableName: config.tableName ?? "tokenmeter_events",
38
+ batchSize: config.batchSize ?? 100,
39
+ flushIntervalMs: config.flushIntervalMs ?? 5000,
40
+ };
41
+ // Start flush interval
42
+ this.flushTimer = setInterval(() => {
43
+ this.flushBuffer().catch((err) => {
44
+ logger.error("Error flushing buffer:", err);
45
+ });
46
+ }, this.config.flushIntervalMs);
47
+ }
48
+ /**
49
+ * Lazily initialize the database pool
50
+ */
51
+ async getPool() {
52
+ if (this.pool) {
53
+ return this.pool;
54
+ }
55
+ // Dynamic import to avoid requiring pg at load time
56
+ const { Pool } = await import("pg");
57
+ this.pool = new Pool({
58
+ connectionString: this.config.connectionString,
59
+ });
60
+ return this.pool;
61
+ }
62
+ /**
63
+ * Export spans to PostgreSQL
64
+ */
65
+ export(spans, resultCallback) {
66
+ if (this.isShuttingDown) {
67
+ resultCallback({ code: ExportResultCode.FAILED });
68
+ return;
69
+ }
70
+ // Filter and convert spans to cost records
71
+ const records = spans
72
+ .map((span) => this.spanToCostRecord(span))
73
+ .filter((record) => record !== null);
74
+ if (records.length === 0) {
75
+ resultCallback({ code: ExportResultCode.SUCCESS });
76
+ return;
77
+ }
78
+ // Add to buffer
79
+ this.buffer.push(...records);
80
+ // Flush if buffer is full
81
+ if (this.buffer.length >= this.config.batchSize) {
82
+ this.flushBuffer()
83
+ .then(() => {
84
+ resultCallback({ code: ExportResultCode.SUCCESS });
85
+ })
86
+ .catch((err) => {
87
+ logger.error("Export error:", err);
88
+ resultCallback({ code: ExportResultCode.FAILED });
89
+ });
90
+ }
91
+ else {
92
+ resultCallback({ code: ExportResultCode.SUCCESS });
93
+ }
94
+ }
95
+ /**
96
+ * Convert a ReadableSpan to a CostRecord
97
+ * Returns null if the span doesn't have cost data
98
+ */
99
+ spanToCostRecord(span) {
100
+ const attrs = span.attributes;
101
+ // Only export spans with tokenmeter cost data
102
+ const costUsd = attrs[TM_ATTRIBUTES.COST_USD];
103
+ const provider = attrs[TM_ATTRIBUTES.PROVIDER];
104
+ const model = attrs[TM_ATTRIBUTES.MODEL];
105
+ // Skip spans without cost data
106
+ if (costUsd === undefined || !provider || !model) {
107
+ return null;
108
+ }
109
+ const spanContext = span.spanContext();
110
+ return {
111
+ id: crypto.randomUUID(),
112
+ traceId: spanContext.traceId,
113
+ spanId: spanContext.spanId,
114
+ provider,
115
+ model,
116
+ organizationId: attrs[TM_ATTRIBUTES.ORG_ID],
117
+ userId: attrs[TM_ATTRIBUTES.USER_ID],
118
+ costUsd,
119
+ inputUnits: attrs[TM_ATTRIBUTES.INPUT_UNITS],
120
+ outputUnits: attrs[TM_ATTRIBUTES.OUTPUT_UNITS],
121
+ attributes: this.extractCustomAttributes(attrs),
122
+ createdAt: this.hrTimeToDate(span.startTime),
123
+ };
124
+ }
125
+ /**
126
+ * Extract custom attributes (exclude standard tokenmeter attributes)
127
+ */
128
+ extractCustomAttributes(attrs) {
129
+ const standardKeys = new Set(Object.values(TM_ATTRIBUTES));
130
+ const custom = {};
131
+ let hasCustom = false;
132
+ for (const [key, value] of Object.entries(attrs)) {
133
+ if (!standardKeys.has(key) && !key.startsWith("gen_ai.")) {
134
+ custom[key] = value;
135
+ hasCustom = true;
136
+ }
137
+ }
138
+ return hasCustom ? custom : undefined;
139
+ }
140
+ /**
141
+ * Convert HrTime to Date
142
+ */
143
+ hrTimeToDate(hrTime) {
144
+ const milliseconds = hrTime[0] * 1000 + hrTime[1] / 1_000_000;
145
+ return new Date(milliseconds);
146
+ }
147
+ /**
148
+ * Flush buffered records to the database
149
+ */
150
+ async flushBuffer() {
151
+ // If already flushing, wait for that to complete
152
+ if (this.flushPromise) {
153
+ return this.flushPromise;
154
+ }
155
+ if (this.buffer.length === 0) {
156
+ return;
157
+ }
158
+ // Take current buffer and clear it
159
+ const records = this.buffer;
160
+ this.buffer = [];
161
+ this.flushPromise = this.insertRecords(records).finally(() => {
162
+ this.flushPromise = null;
163
+ });
164
+ return this.flushPromise;
165
+ }
166
+ /**
167
+ * Insert records into the database
168
+ */
169
+ async insertRecords(records) {
170
+ if (records.length === 0) {
171
+ return;
172
+ }
173
+ const pool = await this.getPool();
174
+ const tableName = this.config.tableName;
175
+ // Build bulk insert query
176
+ const columns = [
177
+ "id",
178
+ "trace_id",
179
+ "span_id",
180
+ "provider",
181
+ "model",
182
+ "organization_id",
183
+ "user_id",
184
+ "cost_usd",
185
+ "input_tokens",
186
+ "output_tokens",
187
+ "metadata",
188
+ "created_at",
189
+ ];
190
+ const values = [];
191
+ const placeholders = [];
192
+ records.forEach((record, i) => {
193
+ const offset = i * columns.length;
194
+ const rowPlaceholders = columns.map((_, j) => `$${offset + j + 1}`);
195
+ placeholders.push(`(${rowPlaceholders.join(", ")})`);
196
+ values.push(record.id, record.traceId, record.spanId, record.provider, record.model, record.organizationId ?? null, record.userId ?? null, record.costUsd, record.inputUnits ?? null, record.outputUnits ?? null, record.attributes ? JSON.stringify(record.attributes) : null, record.createdAt);
197
+ });
198
+ const query = `
199
+ INSERT INTO ${tableName} (${columns.join(", ")})
200
+ VALUES ${placeholders.join(", ")}
201
+ ON CONFLICT (id) DO NOTHING
202
+ `;
203
+ try {
204
+ await pool.query(query, values);
205
+ }
206
+ catch (err) {
207
+ logger.error("Failed to insert records:", err);
208
+ throw err;
209
+ }
210
+ }
211
+ /**
212
+ * Shutdown the exporter
213
+ */
214
+ async shutdown() {
215
+ this.isShuttingDown = true;
216
+ // Stop flush timer
217
+ if (this.flushTimer) {
218
+ clearInterval(this.flushTimer);
219
+ this.flushTimer = null;
220
+ }
221
+ // Flush remaining records
222
+ await this.flushBuffer();
223
+ // Close pool
224
+ if (this.pool) {
225
+ await this.pool.end();
226
+ this.pool = null;
227
+ }
228
+ }
229
+ /**
230
+ * Force flush (for testing or manual control)
231
+ */
232
+ async forceFlush() {
233
+ await this.flushBuffer();
234
+ }
235
+ }
236
+ export default PostgresExporter;
237
+ //# sourceMappingURL=PostgresExporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresExporter.js","sourceRoot":"","sources":["../../src/exporter/PostgresExporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Exporter module
3
+ *
4
+ * Provides the PostgresExporter for persisting cost data.
5
+ */
6
+ export { PostgresExporter } from "./PostgresExporter.js";
7
+ export type { SpanExporter } from "./PostgresExporter.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exporter/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Exporter module
3
+ *
4
+ * Provides the PostgresExporter for persisting cost data.
5
+ */
6
+ export { PostgresExporter } from "./PostgresExporter.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exporter/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * TokenMeter v5
3
+ *
4
+ * OpenTelemetry-native cost tracking for AI workflows.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import OpenAI from 'openai';
9
+ * import { monitor, withAttributes } from 'tokenmeter';
10
+ *
11
+ * // 1. Wrap your client
12
+ * const openai = monitor(new OpenAI({ apiKey: '...' }));
13
+ *
14
+ * // 2. Track with attributes
15
+ * await withAttributes({ 'org.id': 'org_123' }, async () => {
16
+ * await openai.chat.completions.create({
17
+ * model: 'gpt-4o',
18
+ * messages: [{ role: 'user', content: 'Hello!' }]
19
+ * });
20
+ * });
21
+ * ```
22
+ */
23
+ export { monitor } from "./instrumentation/proxy.js";
24
+ export { withAttributes, withAttributesSync, getCurrentAttributes, getAttribute, extractTraceHeaders, contextFromHeaders, withExtractedContext, } from "./context.js";
25
+ export { TokenMeterProcessor } from "./processor/TokenMeterProcessor.js";
26
+ export { loadManifest, getModelPricing, calculateCost, getCachedManifest, clearManifestCache, configurePricing, getPricingConfig, setModelAliases, clearModelAliases, getModelAliases, type PricingConfig, type ModelAlias, } from "./pricing/manifest.js";
27
+ export type { PricingUnit, ModelPricing, ProviderPricing, PricingManifest, MonitorOptions, UsageData, ExtractionStrategy, TokenMeterAttributes, TokenMeterProcessorConfig, PostgresExporterConfig, CostRecord, CostQueryOptions, CostResult, } from "./types.js";
28
+ export { TM_ATTRIBUTES, GEN_AI_ATTRIBUTES } from "./types.js";
29
+ export { configureLogger, getLoggerConfig, resetLogger, type LogLevel, type LoggerConfig, } from "./logger.js";
30
+ export { strategies, findStrategy, extractUsage, openaiStrategy, anthropicStrategy, bedrockStrategy, vertexAIStrategy, falStrategy, bflStrategy, elevenlabsStrategy, vercelAIStrategy, } from "./instrumentation/strategies/index.js";
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAGrD,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAGzE,OAAO,EACL,YAAY,EACZ,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EAEV,WAAW,EACX,YAAY,EACZ,eAAe,EACf,eAAe,EAEf,cAAc,EACd,SAAS,EACT,kBAAkB,EAElB,oBAAoB,EAEpB,yBAAyB,EAEzB,sBAAsB,EACtB,UAAU,EAEV,gBAAgB,EAChB,UAAU,GACX,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAG9D,OAAO,EACL,eAAe,EACf,eAAe,EACf,WAAW,EACX,KAAK,QAAQ,EACb,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,uCAAuC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * TokenMeter v5
3
+ *
4
+ * OpenTelemetry-native cost tracking for AI workflows.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import OpenAI from 'openai';
9
+ * import { monitor, withAttributes } from 'tokenmeter';
10
+ *
11
+ * // 1. Wrap your client
12
+ * const openai = monitor(new OpenAI({ apiKey: '...' }));
13
+ *
14
+ * // 2. Track with attributes
15
+ * await withAttributes({ 'org.id': 'org_123' }, async () => {
16
+ * await openai.chat.completions.create({
17
+ * model: 'gpt-4o',
18
+ * messages: [{ role: 'user', content: 'Hello!' }]
19
+ * });
20
+ * });
21
+ * ```
22
+ */
23
+ // Core instrumentation
24
+ export { monitor } from "./instrumentation/proxy.js";
25
+ // Context management
26
+ export { withAttributes, withAttributesSync, getCurrentAttributes, getAttribute, extractTraceHeaders, contextFromHeaders, withExtractedContext, } from "./context.js";
27
+ // Processor
28
+ export { TokenMeterProcessor } from "./processor/TokenMeterProcessor.js";
29
+ // Pricing utilities
30
+ export { loadManifest, getModelPricing, calculateCost, getCachedManifest, clearManifestCache, configurePricing, getPricingConfig, setModelAliases, clearModelAliases, getModelAliases, } from "./pricing/manifest.js";
31
+ // Semantic conventions
32
+ export { TM_ATTRIBUTES, GEN_AI_ATTRIBUTES } from "./types.js";
33
+ // Logger configuration
34
+ export { configureLogger, getLoggerConfig, resetLogger, } from "./logger.js";
35
+ // Extraction strategies (for custom implementations)
36
+ export { strategies, findStrategy, extractUsage, openaiStrategy, anthropicStrategy, bedrockStrategy, vertexAIStrategy, falStrategy, bflStrategy, elevenlabsStrategy, vercelAIStrategy, } from "./instrumentation/strategies/index.js";
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,uBAAuB;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAErD,qBAAqB;AACrB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,YAAY;AACZ,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAEzE,oBAAoB;AACpB,OAAO,EACL,YAAY,EACZ,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,eAAe,GAGhB,MAAM,uBAAuB,CAAC;AAyB/B,uBAAuB;AACvB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE9D,uBAAuB;AACvB,OAAO,EACL,eAAe,EACf,eAAe,EACf,WAAW,GAGZ,MAAM,aAAa,CAAC;AAErB,qDAAqD;AACrD,OAAO,EACL,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,uCAAuC,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Proxy Engine
3
+ *
4
+ * Creates a recursive Proxy that intercepts method calls and creates OTel spans.
5
+ * Calculates costs and adds them to spans before export.
6
+ */
7
+ import type { MonitorOptions } from "../types.js";
8
+ /**
9
+ * Create a monitored proxy for a client instance
10
+ *
11
+ * @param client - The SDK client instance to wrap
12
+ * @param options - Configuration options
13
+ * @returns A proxied version of the client that creates spans for method calls
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * import OpenAI from 'openai';
18
+ * import { monitor } from 'tokenmeter';
19
+ *
20
+ * const openai = monitor(new OpenAI({ apiKey: '...' }));
21
+ * await openai.chat.completions.create({ model: 'gpt-4o', messages: [...] });
22
+ * ```
23
+ */
24
+ export declare function monitor<T extends object>(client: T, options?: MonitorOptions): T;
25
+ export default monitor;
26
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/instrumentation/proxy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH,OAAO,KAAK,EAAE,cAAc,EAA8B,MAAM,aAAa,CAAC;AAsQ9E;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,EACtC,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,cAAmB,GAC3B,CAAC,CA4IH;AAED,eAAe,OAAO,CAAC"}