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.
- package/LICENSE +21 -0
- package/README.md +346 -0
- package/dist/__tests__/context.test.d.ts +2 -0
- package/dist/__tests__/context.test.d.ts.map +1 -0
- package/dist/__tests__/context.test.js +94 -0
- package/dist/__tests__/context.test.js.map +1 -0
- package/dist/__tests__/elevenlabs.test.d.ts +2 -0
- package/dist/__tests__/elevenlabs.test.d.ts.map +1 -0
- package/dist/__tests__/elevenlabs.test.js +108 -0
- package/dist/__tests__/elevenlabs.test.js.map +1 -0
- package/dist/__tests__/fal.test.d.ts +2 -0
- package/dist/__tests__/fal.test.d.ts.map +1 -0
- package/dist/__tests__/fal.test.js +153 -0
- package/dist/__tests__/fal.test.js.map +1 -0
- package/dist/__tests__/pricing.test.d.ts +2 -0
- package/dist/__tests__/pricing.test.d.ts.map +1 -0
- package/dist/__tests__/pricing.test.js +76 -0
- package/dist/__tests__/pricing.test.js.map +1 -0
- package/dist/__tests__/recorder.test.d.ts +2 -0
- package/dist/__tests__/recorder.test.d.ts.map +1 -0
- package/dist/__tests__/recorder.test.js +133 -0
- package/dist/__tests__/recorder.test.js.map +1 -0
- package/dist/__tests__/storage.test.d.ts +2 -0
- package/dist/__tests__/storage.test.d.ts.map +1 -0
- package/dist/__tests__/storage.test.js +106 -0
- package/dist/__tests__/storage.test.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/config.d.ts +92 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +166 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +80 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +131 -0
- package/dist/context.js.map +1 -0
- package/dist/exporter/PostgresExporter.d.ts +82 -0
- package/dist/exporter/PostgresExporter.d.ts.map +1 -0
- package/dist/exporter/PostgresExporter.js +237 -0
- package/dist/exporter/PostgresExporter.js.map +1 -0
- package/dist/exporter/index.d.ts +8 -0
- package/dist/exporter/index.d.ts.map +1 -0
- package/dist/exporter/index.js +7 -0
- package/dist/exporter/index.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumentation/proxy.d.ts +26 -0
- package/dist/instrumentation/proxy.d.ts.map +1 -0
- package/dist/instrumentation/proxy.js +337 -0
- package/dist/instrumentation/proxy.js.map +1 -0
- package/dist/instrumentation/strategies/index.d.ts +55 -0
- package/dist/instrumentation/strategies/index.d.ts.map +1 -0
- package/dist/instrumentation/strategies/index.js +429 -0
- package/dist/instrumentation/strategies/index.js.map +1 -0
- package/dist/integrations/express/index.d.ts +137 -0
- package/dist/integrations/express/index.d.ts.map +1 -0
- package/dist/integrations/express/index.js +186 -0
- package/dist/integrations/express/index.js.map +1 -0
- package/dist/integrations/inngest/index.d.ts +222 -0
- package/dist/integrations/inngest/index.d.ts.map +1 -0
- package/dist/integrations/inngest/index.js +223 -0
- package/dist/integrations/inngest/index.js.map +1 -0
- package/dist/integrations/langfuse/index.d.ts +170 -0
- package/dist/integrations/langfuse/index.d.ts.map +1 -0
- package/dist/integrations/langfuse/index.js +225 -0
- package/dist/integrations/langfuse/index.js.map +1 -0
- package/dist/integrations/next/index.d.ts +138 -0
- package/dist/integrations/next/index.d.ts.map +1 -0
- package/dist/integrations/next/index.js +170 -0
- package/dist/integrations/next/index.js.map +1 -0
- package/dist/integrations/nextjs/index.d.ts +198 -0
- package/dist/integrations/nextjs/index.d.ts.map +1 -0
- package/dist/integrations/nextjs/index.js +181 -0
- package/dist/integrations/nextjs/index.js.map +1 -0
- package/dist/integrations/vercel-ai/index.d.ts +288 -0
- package/dist/integrations/vercel-ai/index.d.ts.map +1 -0
- package/dist/integrations/vercel-ai/index.js +260 -0
- package/dist/integrations/vercel-ai/index.js.map +1 -0
- package/dist/logger.d.ts +58 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +89 -0
- package/dist/logger.js.map +1 -0
- package/dist/pricing/catalog.d.ts +10 -0
- package/dist/pricing/catalog.d.ts.map +1 -0
- package/dist/pricing/catalog.js +297 -0
- package/dist/pricing/catalog.js.map +1 -0
- package/dist/pricing/index.d.ts +77 -0
- package/dist/pricing/index.d.ts.map +1 -0
- package/dist/pricing/index.js +251 -0
- package/dist/pricing/index.js.map +1 -0
- package/dist/pricing/manifest.d.ts +156 -0
- package/dist/pricing/manifest.d.ts.map +1 -0
- package/dist/pricing/manifest.js +381 -0
- package/dist/pricing/manifest.js.map +1 -0
- package/dist/pricing/manifest.json +12786 -0
- package/dist/pricing/providers/anthropic.json +253 -0
- package/dist/pricing/providers/bedrock.json +341 -0
- package/dist/pricing/providers/bfl.json +220 -0
- package/dist/pricing/providers/elevenlabs.json +142 -0
- package/dist/pricing/providers/fal.json +15866 -0
- package/dist/pricing/providers/google.json +346 -0
- package/dist/pricing/providers/openai.json +1035 -0
- package/dist/pricing/schema.d.ts +102 -0
- package/dist/pricing/schema.d.ts.map +1 -0
- package/dist/pricing/schema.js +56 -0
- package/dist/pricing/schema.js.map +1 -0
- package/dist/processor/TokenMeterProcessor.d.ts +55 -0
- package/dist/processor/TokenMeterProcessor.d.ts.map +1 -0
- package/dist/processor/TokenMeterProcessor.js +132 -0
- package/dist/processor/TokenMeterProcessor.js.map +1 -0
- package/dist/query/client.d.ts +61 -0
- package/dist/query/client.d.ts.map +1 -0
- package/dist/query/client.js +206 -0
- package/dist/query/client.js.map +1 -0
- package/dist/query/index.d.ts +8 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +7 -0
- package/dist/query/index.js.map +1 -0
- package/dist/recorder.d.ts +74 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +227 -0
- package/dist/recorder.js.map +1 -0
- package/dist/sdks/anthropic.d.ts +21 -0
- package/dist/sdks/anthropic.d.ts.map +1 -0
- package/dist/sdks/anthropic.js +258 -0
- package/dist/sdks/anthropic.js.map +1 -0
- package/dist/sdks/elevenlabs.d.ts +59 -0
- package/dist/sdks/elevenlabs.d.ts.map +1 -0
- package/dist/sdks/elevenlabs.js +192 -0
- package/dist/sdks/elevenlabs.js.map +1 -0
- package/dist/sdks/fal.d.ts +102 -0
- package/dist/sdks/fal.d.ts.map +1 -0
- package/dist/sdks/fal.js +306 -0
- package/dist/sdks/fal.js.map +1 -0
- package/dist/sdks/openai.d.ts +17 -0
- package/dist/sdks/openai.d.ts.map +1 -0
- package/dist/sdks/openai.js +191 -0
- package/dist/sdks/openai.js.map +1 -0
- package/dist/storage/interface.d.ts +15 -0
- package/dist/storage/interface.d.ts.map +1 -0
- package/dist/storage/interface.js +53 -0
- package/dist/storage/interface.js.map +1 -0
- package/dist/storage/prisma.d.ts +15 -0
- package/dist/storage/prisma.d.ts.map +1 -0
- package/dist/storage/prisma.js +135 -0
- package/dist/storage/prisma.js.map +1 -0
- package/dist/types.d.ts +206 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +45 -0
- package/dist/types.js.map +1 -0
- package/dist/vercel-ai/index.d.ts +89 -0
- package/dist/vercel-ai/index.d.ts.map +1 -0
- package/dist/vercel-ai/index.js +298 -0
- package/dist/vercel-ai/index.js.map +1 -0
- package/package.json +119 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import { trackFal } from "../sdks/fal.js";
|
|
3
|
+
import { init, shutdown, withCostTrace, flush } from "../index.js";
|
|
4
|
+
import { InMemoryStorageAdapter } from "../storage/interface.js";
|
|
5
|
+
describe("fal.ai SDK Wrapper", () => {
|
|
6
|
+
let storage;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
storage = new InMemoryStorageAdapter();
|
|
9
|
+
init({ storage });
|
|
10
|
+
});
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
await flush();
|
|
13
|
+
await shutdown();
|
|
14
|
+
});
|
|
15
|
+
const createMockClient = () => ({
|
|
16
|
+
subscribe: vi.fn().mockImplementation(async (endpointId, options) => {
|
|
17
|
+
if (endpointId.includes("flux") || endpointId.includes("sdxl")) {
|
|
18
|
+
const numImages = options.input.num_images || 1;
|
|
19
|
+
return {
|
|
20
|
+
data: { images: Array(numImages).fill({ url: "https://example.com/image.png" }) },
|
|
21
|
+
requestId: "req_123",
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
else if (endpointId.includes("video")) {
|
|
25
|
+
return {
|
|
26
|
+
data: { video: { url: "https://example.com/video.mp4" }, duration: options.input.duration || 5 },
|
|
27
|
+
requestId: "req_456",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return { data: {}, requestId: "req_789" };
|
|
31
|
+
}),
|
|
32
|
+
run: vi.fn().mockResolvedValue({
|
|
33
|
+
data: { images: [{ url: "https://example.com/image.png" }] },
|
|
34
|
+
requestId: "req_run_123",
|
|
35
|
+
}),
|
|
36
|
+
});
|
|
37
|
+
describe("trackFal", () => {
|
|
38
|
+
it("should wrap subscribe and track image generation costs", async () => {
|
|
39
|
+
const mockClient = createMockClient();
|
|
40
|
+
const trackedClient = trackFal(mockClient);
|
|
41
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
42
|
+
await trackedClient.subscribe("fal-ai/flux-pro", {
|
|
43
|
+
input: { prompt: "A sunset", num_images: 1 },
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
await flush();
|
|
47
|
+
const events = storage.getEvents();
|
|
48
|
+
expect(events).toHaveLength(1);
|
|
49
|
+
expect(events[0]?.provider).toBe("fal");
|
|
50
|
+
expect(events[0]?.model).toBe("fal/flux-pro");
|
|
51
|
+
expect(events[0]?.operation).toBe("image");
|
|
52
|
+
expect(events[0]?.costUsd).toBeCloseTo(0.05, 4); // $0.05 per image
|
|
53
|
+
});
|
|
54
|
+
it("should calculate cost for multiple images", async () => {
|
|
55
|
+
const mockClient = createMockClient();
|
|
56
|
+
const trackedClient = trackFal(mockClient);
|
|
57
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
58
|
+
await trackedClient.subscribe("fal-ai/flux-pro", {
|
|
59
|
+
input: { prompt: "A sunset", num_images: 4 },
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
await flush();
|
|
63
|
+
const events = storage.getEvents();
|
|
64
|
+
expect(events[0]?.costUsd).toBeCloseTo(0.20, 4); // 4 * $0.05
|
|
65
|
+
expect((events[0]?.metadata).imageCount).toBe(4);
|
|
66
|
+
});
|
|
67
|
+
it("should use cheaper pricing for flux-schnell", async () => {
|
|
68
|
+
const mockClient = createMockClient();
|
|
69
|
+
const trackedClient = trackFal(mockClient);
|
|
70
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
71
|
+
await trackedClient.subscribe("fal-ai/flux-schnell", {
|
|
72
|
+
input: { prompt: "A sunset", num_images: 1 },
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
await flush();
|
|
76
|
+
const events = storage.getEvents();
|
|
77
|
+
expect(events[0]?.costUsd).toBeCloseTo(0.003, 4); // $0.003 per image
|
|
78
|
+
});
|
|
79
|
+
it("should track video generation costs per second", async () => {
|
|
80
|
+
const mockClient = createMockClient();
|
|
81
|
+
const trackedClient = trackFal(mockClient);
|
|
82
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
83
|
+
await trackedClient.subscribe("fal-ai/minimax/video-01", {
|
|
84
|
+
input: { prompt: "A product showcase", duration: 10 },
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
await flush();
|
|
88
|
+
const events = storage.getEvents();
|
|
89
|
+
expect(events[0]?.operation).toBe("video");
|
|
90
|
+
expect(events[0]?.costUsd).toBeCloseTo(3.0, 4); // 10 seconds * $0.30
|
|
91
|
+
expect((events[0]?.metadata).videoDuration).toBe(10);
|
|
92
|
+
});
|
|
93
|
+
it("should wrap run method", async () => {
|
|
94
|
+
const mockClient = createMockClient();
|
|
95
|
+
const trackedClient = trackFal(mockClient);
|
|
96
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
97
|
+
await trackedClient.run("fal-ai/flux-pro", {
|
|
98
|
+
input: { prompt: "A sunset" },
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
await flush();
|
|
102
|
+
const events = storage.getEvents();
|
|
103
|
+
expect(events).toHaveLength(1);
|
|
104
|
+
expect(events[0]?.provider).toBe("fal");
|
|
105
|
+
});
|
|
106
|
+
it("should track failed calls", async () => {
|
|
107
|
+
const mockClient = createMockClient();
|
|
108
|
+
mockClient.subscribe.mockRejectedValue(new Error("Rate limit exceeded"));
|
|
109
|
+
const trackedClient = trackFal(mockClient);
|
|
110
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
111
|
+
try {
|
|
112
|
+
await trackedClient.subscribe("fal-ai/flux-pro", {
|
|
113
|
+
input: { prompt: "Test" },
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
// Expected error
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
await flush();
|
|
121
|
+
const events = storage.getEvents();
|
|
122
|
+
expect(events).toHaveLength(1);
|
|
123
|
+
expect(events[0]?.status).toBe("failed");
|
|
124
|
+
expect(events[0]?.billable).toBe(false);
|
|
125
|
+
expect(events[0]?.errorMessage).toBe("Rate limit exceeded");
|
|
126
|
+
});
|
|
127
|
+
it("should normalize fal-ai/ prefix to fal/", async () => {
|
|
128
|
+
const mockClient = createMockClient();
|
|
129
|
+
const trackedClient = trackFal(mockClient);
|
|
130
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
131
|
+
await trackedClient.subscribe("fal-ai/flux-pro/v1.1", {
|
|
132
|
+
input: { prompt: "A sunset" },
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
await flush();
|
|
136
|
+
const events = storage.getEvents();
|
|
137
|
+
expect(events[0]?.model).toBe("fal/flux-pro");
|
|
138
|
+
});
|
|
139
|
+
it("should include requestId in metadata", async () => {
|
|
140
|
+
const mockClient = createMockClient();
|
|
141
|
+
const trackedClient = trackFal(mockClient);
|
|
142
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
143
|
+
await trackedClient.subscribe("fal-ai/flux-pro", {
|
|
144
|
+
input: { prompt: "A sunset" },
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
await flush();
|
|
148
|
+
const events = storage.getEvents();
|
|
149
|
+
expect((events[0]?.metadata).requestId).toBe("req_123");
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
//# sourceMappingURL=fal.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fal.test.js","sourceRoot":"","sources":["../../src/__tests__/fal.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pricing.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { calculateCost, defaultPricing, mergePricing } from "../pricing/index.js";
|
|
3
|
+
describe("Pricing Module", () => {
|
|
4
|
+
describe("calculateCost", () => {
|
|
5
|
+
it("should calculate cost for OpenAI GPT-4o", () => {
|
|
6
|
+
const cost = calculateCost("gpt-4o", 1000, 500, defaultPricing);
|
|
7
|
+
// Input: 1000 tokens * $0.0025/1K = $0.0025
|
|
8
|
+
// Output: 500 tokens * $0.01/1K = $0.005
|
|
9
|
+
// Total: $0.0075
|
|
10
|
+
expect(cost).toBeCloseTo(0.0075, 6);
|
|
11
|
+
});
|
|
12
|
+
it("should calculate cost for OpenAI GPT-4o-mini", () => {
|
|
13
|
+
const cost = calculateCost("gpt-4o-mini", 10000, 5000, defaultPricing);
|
|
14
|
+
// Input: 10000 tokens * $0.00015/1K = $0.0015
|
|
15
|
+
// Output: 5000 tokens * $0.0006/1K = $0.003
|
|
16
|
+
// Total: $0.0045
|
|
17
|
+
expect(cost).toBeCloseTo(0.0045, 6);
|
|
18
|
+
});
|
|
19
|
+
it("should calculate cost with provider prefix", () => {
|
|
20
|
+
const cost = calculateCost("openai/gpt-4o", 1000, 500, defaultPricing);
|
|
21
|
+
expect(cost).toBeCloseTo(0.0075, 6);
|
|
22
|
+
});
|
|
23
|
+
it("should return 0 for unknown model and warn", () => {
|
|
24
|
+
const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
|
|
25
|
+
const cost = calculateCost("unknown-model", 1000, 500, defaultPricing);
|
|
26
|
+
expect(cost).toBe(0);
|
|
27
|
+
expect(consoleSpy).toHaveBeenCalledWith("[tokenmeter] No pricing found for model: unknown-model");
|
|
28
|
+
consoleSpy.mockRestore();
|
|
29
|
+
});
|
|
30
|
+
it("should handle zero tokens", () => {
|
|
31
|
+
const cost = calculateCost("gpt-4o", 0, 0, defaultPricing);
|
|
32
|
+
expect(cost).toBe(0);
|
|
33
|
+
});
|
|
34
|
+
it("should handle cached input tokens", () => {
|
|
35
|
+
const cost = calculateCost("gpt-4o", 1000, 500, defaultPricing, 500);
|
|
36
|
+
// Regular input: 1000 * $0.0025/1K = $0.0025
|
|
37
|
+
// Cached input: 500 * $0.00125/1K = $0.000625
|
|
38
|
+
// Output: 500 * $0.01/1K = $0.005
|
|
39
|
+
// Total: $0.008125
|
|
40
|
+
expect(cost).toBeCloseTo(0.008125, 6);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe("mergePricing", () => {
|
|
44
|
+
it("should merge custom pricing with defaults", () => {
|
|
45
|
+
const custom = {
|
|
46
|
+
"custom-model": { input: 0.01, output: 0.02 },
|
|
47
|
+
};
|
|
48
|
+
const merged = mergePricing(defaultPricing, custom);
|
|
49
|
+
expect(merged["custom-model"]).toEqual({ input: 0.01, output: 0.02 });
|
|
50
|
+
expect(merged["gpt-4o"]).toEqual(defaultPricing["gpt-4o"]);
|
|
51
|
+
});
|
|
52
|
+
it("should override default pricing with custom", () => {
|
|
53
|
+
const custom = {
|
|
54
|
+
"gpt-4o": { input: 0.005, output: 0.02 },
|
|
55
|
+
};
|
|
56
|
+
const merged = mergePricing(defaultPricing, custom);
|
|
57
|
+
expect(merged["gpt-4o"]).toEqual({ input: 0.005, output: 0.02 });
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe("defaultPricing", () => {
|
|
61
|
+
it("should have ElevenLabs models", () => {
|
|
62
|
+
expect(defaultPricing["elevenlabs/eleven_multilingual_v2"]).toBeDefined();
|
|
63
|
+
expect(defaultPricing["eleven_turbo_v2_5"]).toBeDefined();
|
|
64
|
+
});
|
|
65
|
+
it("should have fal.ai models", () => {
|
|
66
|
+
expect(defaultPricing["fal/flux-pro"]).toBeDefined();
|
|
67
|
+
expect(defaultPricing["fal/flux-schnell"]).toBeDefined();
|
|
68
|
+
expect(defaultPricing["fal/minimax/video-01"]).toBeDefined();
|
|
69
|
+
});
|
|
70
|
+
it("should have Anthropic models", () => {
|
|
71
|
+
expect(defaultPricing["anthropic/claude-3-5-sonnet-20241022"]).toBeDefined();
|
|
72
|
+
expect(defaultPricing["claude-3-5-sonnet-20241022"]).toBeDefined();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=pricing.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.test.js","sourceRoot":"","sources":["../../src/__tests__/pricing.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recorder.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/recorder.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import { init, shutdown, withCostTrace, trackCost, flush } from "../index.js";
|
|
3
|
+
import { InMemoryStorageAdapter } from "../storage/interface.js";
|
|
4
|
+
describe("Recorder Module", () => {
|
|
5
|
+
let storage;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
storage = new InMemoryStorageAdapter();
|
|
8
|
+
init({
|
|
9
|
+
storage,
|
|
10
|
+
batching: {
|
|
11
|
+
enabled: true,
|
|
12
|
+
flushInterval: 10000, // Long interval to prevent auto-flush
|
|
13
|
+
maxBatchSize: 100,
|
|
14
|
+
flushOnExit: false,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
afterEach(async () => {
|
|
19
|
+
await flush();
|
|
20
|
+
await shutdown();
|
|
21
|
+
});
|
|
22
|
+
describe("trackCost", () => {
|
|
23
|
+
it("should record manual cost events", async () => {
|
|
24
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
25
|
+
trackCost({
|
|
26
|
+
provider: "custom-provider",
|
|
27
|
+
model: "custom-model",
|
|
28
|
+
operation: "inference",
|
|
29
|
+
costUsd: 0.05,
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
await flush();
|
|
33
|
+
const events = storage.getEvents();
|
|
34
|
+
expect(events).toHaveLength(1);
|
|
35
|
+
expect(events[0]?.provider).toBe("custom-provider");
|
|
36
|
+
expect(events[0]?.model).toBe("custom-model");
|
|
37
|
+
expect(events[0]?.costUsd).toBe(0.05);
|
|
38
|
+
});
|
|
39
|
+
it("should inherit context from withCostTrace", async () => {
|
|
40
|
+
await withCostTrace({
|
|
41
|
+
identifier: "org_456",
|
|
42
|
+
workflowId: "wf_custom",
|
|
43
|
+
workflowType: "custom-workflow",
|
|
44
|
+
metadata: { source: "api" },
|
|
45
|
+
}, async () => {
|
|
46
|
+
trackCost({
|
|
47
|
+
provider: "runway",
|
|
48
|
+
model: "gen3",
|
|
49
|
+
costUsd: 0.50,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
await flush();
|
|
53
|
+
const events = storage.getEvents();
|
|
54
|
+
expect(events[0]?.identifier).toBe("org_456");
|
|
55
|
+
expect(events[0]?.workflowId).toBe("wf_custom");
|
|
56
|
+
expect(events[0]?.workflowType).toBe("custom-workflow");
|
|
57
|
+
expect((events[0]?.metadata).source).toBe("api");
|
|
58
|
+
});
|
|
59
|
+
it("should track failed costs with error message", async () => {
|
|
60
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
61
|
+
trackCost({
|
|
62
|
+
provider: "veo",
|
|
63
|
+
model: "veo-2",
|
|
64
|
+
operation: "video",
|
|
65
|
+
costUsd: 0,
|
|
66
|
+
status: "failed",
|
|
67
|
+
billable: false,
|
|
68
|
+
errorMessage: "Insufficient credits",
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
await flush();
|
|
72
|
+
const events = storage.getEvents();
|
|
73
|
+
expect(events[0]?.status).toBe("failed");
|
|
74
|
+
expect(events[0]?.billable).toBe(false);
|
|
75
|
+
expect(events[0]?.errorMessage).toBe("Insufficient credits");
|
|
76
|
+
});
|
|
77
|
+
it("should warn when called outside of context", async () => {
|
|
78
|
+
const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
|
|
79
|
+
trackCost({
|
|
80
|
+
provider: "test",
|
|
81
|
+
model: "test",
|
|
82
|
+
costUsd: 0.01,
|
|
83
|
+
});
|
|
84
|
+
expect(consoleSpy).toHaveBeenCalledWith("[tokenmeter] No trace context. Wrap your code in withCostTrace().");
|
|
85
|
+
consoleSpy.mockRestore();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe("flush", () => {
|
|
89
|
+
it("should write batched events to storage", async () => {
|
|
90
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
91
|
+
trackCost({ provider: "a", model: "a", costUsd: 0.01 });
|
|
92
|
+
trackCost({ provider: "b", model: "b", costUsd: 0.02 });
|
|
93
|
+
trackCost({ provider: "c", model: "c", costUsd: 0.03 });
|
|
94
|
+
});
|
|
95
|
+
// Events should be batched, not yet in storage
|
|
96
|
+
expect(storage.getEvents()).toHaveLength(0);
|
|
97
|
+
await flush();
|
|
98
|
+
expect(storage.getEvents()).toHaveLength(3);
|
|
99
|
+
});
|
|
100
|
+
it("should handle empty queue gracefully", async () => {
|
|
101
|
+
await flush();
|
|
102
|
+
expect(storage.getEvents()).toHaveLength(0);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe("batching", () => {
|
|
106
|
+
it("should flush when batch size is reached", async () => {
|
|
107
|
+
// Reinit with small batch size
|
|
108
|
+
await shutdown();
|
|
109
|
+
storage = new InMemoryStorageAdapter();
|
|
110
|
+
init({
|
|
111
|
+
storage,
|
|
112
|
+
batching: {
|
|
113
|
+
enabled: true,
|
|
114
|
+
flushInterval: 10000,
|
|
115
|
+
maxBatchSize: 3,
|
|
116
|
+
flushOnExit: false,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
await withCostTrace({ identifier: "user_123" }, async () => {
|
|
120
|
+
trackCost({ provider: "a", model: "a", costUsd: 0.01 });
|
|
121
|
+
trackCost({ provider: "b", model: "b", costUsd: 0.02 });
|
|
122
|
+
// Not yet flushed
|
|
123
|
+
expect(storage.getEvents()).toHaveLength(0);
|
|
124
|
+
trackCost({ provider: "c", model: "c", costUsd: 0.03 });
|
|
125
|
+
// Give time for async flush
|
|
126
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
127
|
+
});
|
|
128
|
+
// Should have auto-flushed at batch size 3
|
|
129
|
+
expect(storage.getEvents()).toHaveLength(3);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
//# sourceMappingURL=recorder.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recorder.test.js","sourceRoot":"","sources":["../../src/__tests__/recorder.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/storage.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
+
import { InMemoryStorageAdapter } from "../storage/interface.js";
|
|
3
|
+
describe("InMemoryStorageAdapter", () => {
|
|
4
|
+
let storage;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
storage = new InMemoryStorageAdapter();
|
|
7
|
+
});
|
|
8
|
+
const createEvent = (overrides = {}) => ({
|
|
9
|
+
identifier: "user_123",
|
|
10
|
+
provider: "openai",
|
|
11
|
+
model: "gpt-4o",
|
|
12
|
+
costUsd: 0.01,
|
|
13
|
+
createdAt: new Date(),
|
|
14
|
+
...overrides,
|
|
15
|
+
});
|
|
16
|
+
describe("writeEvent", () => {
|
|
17
|
+
it("should store a single event", async () => {
|
|
18
|
+
const event = createEvent();
|
|
19
|
+
await storage.writeEvent(event);
|
|
20
|
+
const events = storage.getEvents();
|
|
21
|
+
expect(events).toHaveLength(1);
|
|
22
|
+
expect(events[0]).toEqual(event);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe("writeBatch", () => {
|
|
26
|
+
it("should store multiple events", async () => {
|
|
27
|
+
const events = [
|
|
28
|
+
createEvent({ costUsd: 0.01 }),
|
|
29
|
+
createEvent({ costUsd: 0.02 }),
|
|
30
|
+
createEvent({ costUsd: 0.03 }),
|
|
31
|
+
];
|
|
32
|
+
await storage.writeBatch(events);
|
|
33
|
+
expect(storage.getEvents()).toHaveLength(3);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe("query", () => {
|
|
37
|
+
beforeEach(async () => {
|
|
38
|
+
await storage.writeBatch([
|
|
39
|
+
createEvent({
|
|
40
|
+
identifier: "user_1",
|
|
41
|
+
provider: "openai",
|
|
42
|
+
workflowId: "wf_1",
|
|
43
|
+
costUsd: 0.01,
|
|
44
|
+
createdAt: new Date("2024-01-15"),
|
|
45
|
+
}),
|
|
46
|
+
createEvent({
|
|
47
|
+
identifier: "user_1",
|
|
48
|
+
provider: "anthropic",
|
|
49
|
+
workflowId: "wf_1",
|
|
50
|
+
costUsd: 0.02,
|
|
51
|
+
createdAt: new Date("2024-01-16"),
|
|
52
|
+
}),
|
|
53
|
+
createEvent({
|
|
54
|
+
identifier: "user_2",
|
|
55
|
+
provider: "openai",
|
|
56
|
+
workflowId: "wf_2",
|
|
57
|
+
costUsd: 0.03,
|
|
58
|
+
createdAt: new Date("2024-01-17"),
|
|
59
|
+
}),
|
|
60
|
+
]);
|
|
61
|
+
});
|
|
62
|
+
it("should query by identifier", async () => {
|
|
63
|
+
const result = await storage.query({ identifier: "user_1" });
|
|
64
|
+
expect(result.events).toHaveLength(2);
|
|
65
|
+
expect(result.totalCost).toBeCloseTo(0.03, 6);
|
|
66
|
+
});
|
|
67
|
+
it("should query by workflowId", async () => {
|
|
68
|
+
const result = await storage.query({ workflowId: "wf_1" });
|
|
69
|
+
expect(result.events).toHaveLength(2);
|
|
70
|
+
expect(result.totalCost).toBeCloseTo(0.03, 6);
|
|
71
|
+
});
|
|
72
|
+
it("should query by provider", async () => {
|
|
73
|
+
const result = await storage.query({ provider: "openai" });
|
|
74
|
+
expect(result.events).toHaveLength(2);
|
|
75
|
+
expect(result.totalCost).toBeCloseTo(0.04, 6);
|
|
76
|
+
});
|
|
77
|
+
it("should query by date range", async () => {
|
|
78
|
+
const result = await storage.query({
|
|
79
|
+
from: new Date("2024-01-15"),
|
|
80
|
+
to: new Date("2024-01-16"),
|
|
81
|
+
});
|
|
82
|
+
expect(result.events).toHaveLength(2);
|
|
83
|
+
});
|
|
84
|
+
it("should group costs by provider", async () => {
|
|
85
|
+
const result = await storage.query({ identifier: "user_1" });
|
|
86
|
+
expect(result.byProvider).toEqual({
|
|
87
|
+
openai: 0.01,
|
|
88
|
+
anthropic: 0.02,
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
it("should return all events when no filters", async () => {
|
|
92
|
+
const result = await storage.query({});
|
|
93
|
+
expect(result.events).toHaveLength(3);
|
|
94
|
+
expect(result.totalCost).toBeCloseTo(0.06, 6);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe("clear", () => {
|
|
98
|
+
it("should clear all events", async () => {
|
|
99
|
+
await storage.writeEvent(createEvent());
|
|
100
|
+
expect(storage.getEvents()).toHaveLength(1);
|
|
101
|
+
storage.clear();
|
|
102
|
+
expect(storage.getEvents()).toHaveLength(0);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=storage.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.test.js","sourceRoot":"","sources":["../../src/__tests__/storage.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { TokenmeterConfig, StorageAdapter, PricingConfig, BatchingConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Initialize tokenmeter with configuration.
|
|
4
|
+
*
|
|
5
|
+
* Must be called before using any tokenmeter functions. Typically called
|
|
6
|
+
* once at application startup.
|
|
7
|
+
*
|
|
8
|
+
* @param config - Configuration options
|
|
9
|
+
* @param config.databaseUrl - PostgreSQL connection URL (required if no storage adapter)
|
|
10
|
+
* @param config.storage - Custom storage adapter (overrides databaseUrl)
|
|
11
|
+
* @param config.pricing - Custom pricing overrides for models
|
|
12
|
+
* @param config.modelAliases - Map of model aliases to canonical names
|
|
13
|
+
* @param config.batching - Batching configuration (enabled, flushInterval, maxBatchSize, flushOnExit)
|
|
14
|
+
* @param config.identifierType - Label for the identifier field (documentation only)
|
|
15
|
+
*
|
|
16
|
+
* @throws Error if neither databaseUrl nor storage is provided
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // With PostgreSQL
|
|
21
|
+
* init({
|
|
22
|
+
* databaseUrl: process.env.DATABASE_URL,
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // With custom storage adapter
|
|
26
|
+
* init({
|
|
27
|
+
* storage: new InMemoryStorageAdapter(),
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // With pricing overrides
|
|
31
|
+
* init({
|
|
32
|
+
* databaseUrl: process.env.DATABASE_URL,
|
|
33
|
+
* pricing: {
|
|
34
|
+
* "custom-model": { input: 0.001, output: 0.002 },
|
|
35
|
+
* },
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function init(config: TokenmeterConfig): void;
|
|
40
|
+
/**
|
|
41
|
+
* Get the current storage adapter
|
|
42
|
+
*/
|
|
43
|
+
export declare function getStorage(): StorageAdapter;
|
|
44
|
+
/**
|
|
45
|
+
* Get pricing configuration
|
|
46
|
+
*/
|
|
47
|
+
export declare function getPricing(): PricingConfig;
|
|
48
|
+
/**
|
|
49
|
+
* Get model aliases
|
|
50
|
+
*/
|
|
51
|
+
export declare function getModelAliases(): Record<string, string>;
|
|
52
|
+
/**
|
|
53
|
+
* Get batching configuration
|
|
54
|
+
*/
|
|
55
|
+
export declare function getBatching(): BatchingConfig;
|
|
56
|
+
/**
|
|
57
|
+
* Check if tokenmeter has been initialized.
|
|
58
|
+
*
|
|
59
|
+
* @returns true if init() has been called and shutdown() has not been called
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* if (!isInitialized()) {
|
|
64
|
+
* init({ databaseUrl: process.env.DATABASE_URL });
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function isInitialized(): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Resolve a model name through aliases
|
|
71
|
+
*/
|
|
72
|
+
export declare function resolveModel(model: string): string;
|
|
73
|
+
/**
|
|
74
|
+
* Shutdown tokenmeter and clean up resources.
|
|
75
|
+
*
|
|
76
|
+
* Disconnects from the database and resets the initialized state.
|
|
77
|
+
* Call this before reinitializing or when shutting down your application.
|
|
78
|
+
*
|
|
79
|
+
* @returns A promise that resolves when shutdown is complete
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // Graceful shutdown
|
|
84
|
+
* process.on("SIGTERM", async () => {
|
|
85
|
+
* await flush();
|
|
86
|
+
* await shutdown();
|
|
87
|
+
* process.exit(0);
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare function shutdown(): Promise<void>;
|
|
92
|
+
//# sourceMappingURL=config.d.ts.map
|