vibezcheck 0.4.2 → 0.5.3
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 -21
- package/README.md +249 -273
- package/bin/vibezcheck.js +4 -4
- package/dist/ai-sdk/index.d.mts +28 -59
- package/dist/ai-sdk/index.d.ts +28 -59
- package/dist/ai-sdk/index.js +307 -69
- package/dist/ai-sdk/index.js.map +1 -1
- package/dist/ai-sdk/index.mjs +307 -69
- package/dist/ai-sdk/index.mjs.map +1 -1
- package/dist/ai-sdk/middleware.d.mts +15 -0
- package/dist/ai-sdk/middleware.d.ts +15 -0
- package/dist/ai-sdk/middleware.js +1433 -0
- package/dist/ai-sdk/middleware.js.map +1 -0
- package/dist/ai-sdk/middleware.mjs +1396 -0
- package/dist/ai-sdk/middleware.mjs.map +1 -0
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/index.mjs.map +1 -1
- package/dist/billing/index.d.mts +90 -1
- package/dist/billing/index.d.ts +90 -1
- package/dist/billing/index.js +1542 -2
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/index.mjs +1537 -1
- package/dist/billing/index.mjs.map +1 -1
- package/dist/cli/index.js +59 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +59 -7
- package/dist/cli/index.mjs.map +1 -1
- package/dist/{client-ynfWcHX6.d.ts → client-BORmJy8s.d.ts} +1 -1
- package/dist/{client-w_hWhQ6g.d.mts → client-CbuXmoXz.d.mts} +1 -1
- package/dist/compat/stripe-meter.d.mts +21 -0
- package/dist/compat/stripe-meter.d.ts +21 -0
- package/dist/compat/stripe-meter.js +1451 -0
- package/dist/compat/stripe-meter.js.map +1 -0
- package/dist/compat/stripe-meter.mjs +1414 -0
- package/dist/compat/stripe-meter.mjs.map +1 -0
- package/dist/compat/stripe-provider.d.mts +34 -0
- package/dist/compat/stripe-provider.d.ts +34 -0
- package/dist/compat/stripe-provider.js +1620 -0
- package/dist/compat/stripe-provider.js.map +1 -0
- package/dist/compat/stripe-provider.mjs +1587 -0
- package/dist/compat/stripe-provider.mjs.map +1 -0
- package/dist/compat/token-meter.d.mts +28 -0
- package/dist/compat/token-meter.d.ts +28 -0
- package/dist/compat/token-meter.js +1320 -0
- package/dist/compat/token-meter.js.map +1 -0
- package/dist/compat/token-meter.mjs +1283 -0
- package/dist/compat/token-meter.mjs.map +1 -0
- package/dist/customers/index.d.mts +1 -1
- package/dist/customers/index.d.ts +1 -1
- package/dist/customers/index.js.map +1 -1
- package/dist/customers/index.mjs.map +1 -1
- package/dist/index.d.mts +25 -11
- package/dist/index.d.ts +25 -11
- package/dist/index.js +810 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +798 -72
- package/dist/index.mjs.map +1 -1
- package/dist/meter/index.d.mts +2 -2
- package/dist/meter/index.d.ts +2 -2
- package/dist/meter/index.js +176 -42
- package/dist/meter/index.js.map +1 -1
- package/dist/meter/index.mjs +176 -42
- package/dist/meter/index.mjs.map +1 -1
- package/dist/pricing/index.d.mts +15 -4
- package/dist/pricing/index.d.ts +15 -4
- package/dist/pricing/index.js +165 -29
- package/dist/pricing/index.js.map +1 -1
- package/dist/pricing/index.mjs +164 -29
- package/dist/pricing/index.mjs.map +1 -1
- package/dist/react/index.d.mts +46 -2
- package/dist/react/index.d.ts +46 -2
- package/dist/react/index.js +471 -29
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +469 -29
- package/dist/react/index.mjs.map +1 -1
- package/dist/{types-Mozk4-Mr.d.mts → types-6P71CXAD.d.mts} +16 -6
- package/dist/{types-Mozk4-Mr.d.ts → types-6P71CXAD.d.ts} +16 -6
- package/dist/with-billing-Bj6Ya_Iy.d.ts +49 -0
- package/dist/with-billing-DndWGxL8.d.mts +49 -0
- package/package.json +35 -10
|
@@ -0,0 +1,1620 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/compat/stripe-provider.ts
|
|
31
|
+
var stripe_provider_exports = {};
|
|
32
|
+
__export(stripe_provider_exports, {
|
|
33
|
+
createStripe: () => createStripe,
|
|
34
|
+
createStripeV3: () => createStripeV3,
|
|
35
|
+
stripe: () => stripe,
|
|
36
|
+
stripeV3: () => stripeV3
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(stripe_provider_exports);
|
|
39
|
+
|
|
40
|
+
// src/types.ts
|
|
41
|
+
var VibezCircuitBreakerError = class extends Error {
|
|
42
|
+
event;
|
|
43
|
+
constructor(event) {
|
|
44
|
+
super(event.message);
|
|
45
|
+
this.name = "VibezCircuitBreakerError";
|
|
46
|
+
this.event = event;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/meter/client.ts
|
|
51
|
+
var import_stripe = __toESM(require("stripe"));
|
|
52
|
+
|
|
53
|
+
// src/meter/batcher.ts
|
|
54
|
+
var MeterBatcher = class {
|
|
55
|
+
queue = [];
|
|
56
|
+
timer = null;
|
|
57
|
+
isFlushing = false;
|
|
58
|
+
maxBatchSize;
|
|
59
|
+
flushIntervalMs;
|
|
60
|
+
stripeClient;
|
|
61
|
+
eventName;
|
|
62
|
+
onUsageCallback;
|
|
63
|
+
onErrorCallback;
|
|
64
|
+
debug;
|
|
65
|
+
// In-memory ledger for local stats
|
|
66
|
+
totalRequests = 0;
|
|
67
|
+
totalTokens = 0;
|
|
68
|
+
totalInputTokens = 0;
|
|
69
|
+
totalOutputTokens = 0;
|
|
70
|
+
totalReasoningTokens = 0;
|
|
71
|
+
totalCostUSD = 0;
|
|
72
|
+
byModel = {};
|
|
73
|
+
constructor(options = {}) {
|
|
74
|
+
this.stripeClient = options.stripe;
|
|
75
|
+
this.eventName = options.eventName || "token-billing-tokens";
|
|
76
|
+
this.maxBatchSize = options.batching?.maxBatchSize ?? 50;
|
|
77
|
+
this.flushIntervalMs = options.batching?.flushIntervalMs ?? 50;
|
|
78
|
+
this.onUsageCallback = options.onUsage;
|
|
79
|
+
this.onErrorCallback = options.onError;
|
|
80
|
+
this.debug = options.debug ?? false;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Enqueue a usage event for batch dispatching
|
|
84
|
+
*/
|
|
85
|
+
enqueue(event) {
|
|
86
|
+
this.recordInLedger(event);
|
|
87
|
+
if (this.onUsageCallback) {
|
|
88
|
+
try {
|
|
89
|
+
const res = this.onUsageCallback(event);
|
|
90
|
+
if (res instanceof Promise) {
|
|
91
|
+
res.catch((err) => {
|
|
92
|
+
if (this.debug) console.error("[vibezcheck] Error in onUsage callback:", err);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
} catch (err) {
|
|
96
|
+
if (this.debug) console.error("[vibezcheck] Error in onUsage callback:", err);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (!this.stripeClient) {
|
|
100
|
+
if (this.debug) {
|
|
101
|
+
console.log(
|
|
102
|
+
`[vibezcheck:local] \u{1F4CA} ${event.model} | Tokens: ${event.usage.totalTokens} | Cost: $${event.cost.totalUSD.toFixed(6)}`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
this.queue.push(event);
|
|
108
|
+
if (this.queue.length >= this.maxBatchSize) {
|
|
109
|
+
this.flush().catch((err) => {
|
|
110
|
+
if (this.debug) console.error("[vibezcheck] Batch flush error:", err);
|
|
111
|
+
});
|
|
112
|
+
} else if (!this.timer) {
|
|
113
|
+
this.timer = setTimeout(() => {
|
|
114
|
+
this.timer = null;
|
|
115
|
+
this.flush().catch((err) => {
|
|
116
|
+
if (this.debug) console.error("[vibezcheck] Debounce flush error:", err);
|
|
117
|
+
});
|
|
118
|
+
}, this.flushIntervalMs);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Immediately flush all queued events to Stripe
|
|
123
|
+
*/
|
|
124
|
+
async flush() {
|
|
125
|
+
if (this.timer) {
|
|
126
|
+
clearTimeout(this.timer);
|
|
127
|
+
this.timer = null;
|
|
128
|
+
}
|
|
129
|
+
if (this.queue.length === 0 || !this.stripeClient || this.isFlushing) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
this.isFlushing = true;
|
|
133
|
+
const eventsToSend = [...this.queue];
|
|
134
|
+
this.queue = [];
|
|
135
|
+
try {
|
|
136
|
+
await this.sendEventsToStripe(eventsToSend);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
139
|
+
if (this.debug) {
|
|
140
|
+
console.error("[vibezcheck] Failed to send meter events to Stripe:", err);
|
|
141
|
+
}
|
|
142
|
+
if (this.onErrorCallback) {
|
|
143
|
+
this.onErrorCallback(err, eventsToSend);
|
|
144
|
+
}
|
|
145
|
+
} finally {
|
|
146
|
+
this.isFlushing = false;
|
|
147
|
+
if (this.queue.length > 0) {
|
|
148
|
+
this.flush().catch(() => {
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Sends events to Stripe Billing Meter Events API
|
|
155
|
+
*/
|
|
156
|
+
async sendEventsToStripe(events) {
|
|
157
|
+
if (!this.stripeClient) return;
|
|
158
|
+
for (const event of events) {
|
|
159
|
+
const customerId = event.customerId;
|
|
160
|
+
if (!customerId) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const timestamp = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
164
|
+
const model = `${event.provider}/${event.model}`;
|
|
165
|
+
if (event.usage.inputTokens > 0) {
|
|
166
|
+
try {
|
|
167
|
+
await this.stripeClient.v2.billing.meterEvents.create({
|
|
168
|
+
event_name: this.eventName,
|
|
169
|
+
timestamp,
|
|
170
|
+
payload: {
|
|
171
|
+
stripe_customer_id: customerId,
|
|
172
|
+
value: event.usage.inputTokens.toString(),
|
|
173
|
+
model,
|
|
174
|
+
token_type: "input",
|
|
175
|
+
cached_tokens: (event.usage.cachedTokens ?? 0).toString(),
|
|
176
|
+
...event.metadata ? event.metadata : {}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
} catch (e) {
|
|
180
|
+
if (this.debug) console.warn("[vibezcheck] Input meter event error:", e);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (event.usage.outputTokens > 0) {
|
|
184
|
+
try {
|
|
185
|
+
await this.stripeClient.v2.billing.meterEvents.create({
|
|
186
|
+
event_name: this.eventName,
|
|
187
|
+
timestamp,
|
|
188
|
+
payload: {
|
|
189
|
+
stripe_customer_id: customerId,
|
|
190
|
+
value: event.usage.outputTokens.toString(),
|
|
191
|
+
model,
|
|
192
|
+
token_type: "output",
|
|
193
|
+
reasoning_tokens: (event.usage.reasoningTokens ?? 0).toString(),
|
|
194
|
+
visible_tokens: (event.usage.visibleOutputTokens ?? event.usage.outputTokens).toString(),
|
|
195
|
+
...event.metadata ? event.metadata : {}
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
} catch (e) {
|
|
199
|
+
if (this.debug) console.warn("[vibezcheck] Output meter event error:", e);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Updates internal in-memory ledger
|
|
206
|
+
*/
|
|
207
|
+
recordInLedger(event) {
|
|
208
|
+
this.totalRequests += 1;
|
|
209
|
+
this.totalTokens += event.usage.totalTokens;
|
|
210
|
+
this.totalInputTokens += event.usage.inputTokens;
|
|
211
|
+
this.totalOutputTokens += event.usage.outputTokens;
|
|
212
|
+
this.totalReasoningTokens += event.usage.reasoningTokens ?? 0;
|
|
213
|
+
this.totalCostUSD += event.cost.totalUSD;
|
|
214
|
+
const modelKey = event.model;
|
|
215
|
+
if (!this.byModel[modelKey]) {
|
|
216
|
+
this.byModel[modelKey] = { requests: 0, tokens: 0, costUSD: 0 };
|
|
217
|
+
}
|
|
218
|
+
this.byModel[modelKey].requests += 1;
|
|
219
|
+
this.byModel[modelKey].tokens += event.usage.totalTokens;
|
|
220
|
+
this.byModel[modelKey].costUSD += event.cost.totalUSD;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Get in-memory usage summary
|
|
224
|
+
*/
|
|
225
|
+
getSummary() {
|
|
226
|
+
return {
|
|
227
|
+
totalRequests: this.totalRequests,
|
|
228
|
+
totalTokens: this.totalTokens,
|
|
229
|
+
totalInputTokens: this.totalInputTokens,
|
|
230
|
+
totalOutputTokens: this.totalOutputTokens,
|
|
231
|
+
totalReasoningTokens: this.totalReasoningTokens,
|
|
232
|
+
totalCostUSD: Number(this.totalCostUSD.toFixed(6)),
|
|
233
|
+
byModel: { ...this.byModel }
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Reset in-memory ledger
|
|
238
|
+
*/
|
|
239
|
+
resetLedger() {
|
|
240
|
+
this.totalRequests = 0;
|
|
241
|
+
this.totalTokens = 0;
|
|
242
|
+
this.totalInputTokens = 0;
|
|
243
|
+
this.totalOutputTokens = 0;
|
|
244
|
+
this.totalReasoningTokens = 0;
|
|
245
|
+
this.totalCostUSD = 0;
|
|
246
|
+
this.byModel = {};
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
// src/meter/extractors/openai.ts
|
|
251
|
+
function extractOpenAIResponseUsage(response) {
|
|
252
|
+
if (!response || typeof response !== "object") return null;
|
|
253
|
+
if ("choices" in response && "usage" in response && response.usage) {
|
|
254
|
+
const rawUsage = response.usage;
|
|
255
|
+
const model = response.model || "gpt-4o";
|
|
256
|
+
const inputTokens = rawUsage.prompt_tokens ?? 0;
|
|
257
|
+
const outputTokens = rawUsage.completion_tokens ?? 0;
|
|
258
|
+
const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens ?? 0;
|
|
259
|
+
const cachedTokens = rawUsage.prompt_tokens_details?.cached_tokens ?? 0;
|
|
260
|
+
return {
|
|
261
|
+
model,
|
|
262
|
+
provider: "openai",
|
|
263
|
+
usage: {
|
|
264
|
+
inputTokens,
|
|
265
|
+
outputTokens,
|
|
266
|
+
totalTokens: inputTokens + outputTokens,
|
|
267
|
+
reasoningTokens: reasoningTokens > 0 ? reasoningTokens : void 0,
|
|
268
|
+
visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),
|
|
269
|
+
cachedTokens: cachedTokens > 0 ? cachedTokens : void 0
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
if ("data" in response && "usage" in response && response.usage && "model" in response) {
|
|
274
|
+
const rawUsage = response.usage;
|
|
275
|
+
const inputTokens = rawUsage.prompt_tokens ?? 0;
|
|
276
|
+
return {
|
|
277
|
+
model: response.model || "text-embedding-3-small",
|
|
278
|
+
provider: "openai",
|
|
279
|
+
usage: {
|
|
280
|
+
inputTokens,
|
|
281
|
+
outputTokens: 0,
|
|
282
|
+
totalTokens: inputTokens
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
if ("status" in response && "usage" in response && response.usage) {
|
|
287
|
+
const rawUsage = response.usage;
|
|
288
|
+
const model = response.model || "gpt-5.6-sol";
|
|
289
|
+
const inputTokens = rawUsage.input_tokens ?? rawUsage.prompt_tokens ?? 0;
|
|
290
|
+
const outputTokens = rawUsage.output_tokens ?? rawUsage.completion_tokens ?? 0;
|
|
291
|
+
const reasoningTokens = rawUsage.output_token_details?.reasoning_tokens ?? rawUsage.completion_tokens_details?.reasoning_tokens ?? 0;
|
|
292
|
+
const cachedTokens = rawUsage.input_token_details?.cached_tokens ?? rawUsage.prompt_tokens_details?.cached_tokens ?? 0;
|
|
293
|
+
return {
|
|
294
|
+
model,
|
|
295
|
+
provider: "openai",
|
|
296
|
+
usage: {
|
|
297
|
+
inputTokens,
|
|
298
|
+
outputTokens,
|
|
299
|
+
totalTokens: inputTokens + outputTokens,
|
|
300
|
+
reasoningTokens: reasoningTokens > 0 ? reasoningTokens : void 0,
|
|
301
|
+
visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),
|
|
302
|
+
cachedTokens: cachedTokens > 0 ? cachedTokens : void 0
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
function inspectOpenAIStreamChunk(chunk) {
|
|
309
|
+
if (!chunk || typeof chunk !== "object") return {};
|
|
310
|
+
const model = chunk.model;
|
|
311
|
+
const rawUsage = chunk.usage || chunk.token_usage || chunk.x_groq?.usage || chunk.usageMetadata;
|
|
312
|
+
if (rawUsage) {
|
|
313
|
+
const inputTokens = rawUsage.prompt_tokens ?? rawUsage.input_tokens ?? rawUsage.promptTokens ?? rawUsage.inputTokens ?? rawUsage.promptTokenCount ?? 0;
|
|
314
|
+
const outputTokens = rawUsage.completion_tokens ?? rawUsage.output_tokens ?? rawUsage.completionTokens ?? rawUsage.outputTokens ?? rawUsage.candidatesTokenCount ?? 0;
|
|
315
|
+
const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens ?? rawUsage.output_token_details?.reasoning_tokens ?? rawUsage.reasoning_tokens ?? rawUsage.reasoningTokens ?? rawUsage.thoughtsTokenCount ?? 0;
|
|
316
|
+
const cachedTokens = rawUsage.prompt_tokens_details?.cached_tokens ?? rawUsage.input_token_details?.cached_tokens ?? rawUsage.prompt_cache_hit_tokens ?? rawUsage.cached_tokens ?? rawUsage.cachedTokens ?? rawUsage.cachedContentTokenCount ?? 0;
|
|
317
|
+
return {
|
|
318
|
+
model,
|
|
319
|
+
usage: {
|
|
320
|
+
inputTokens,
|
|
321
|
+
outputTokens,
|
|
322
|
+
totalTokens: inputTokens + outputTokens,
|
|
323
|
+
reasoningTokens: reasoningTokens > 0 ? reasoningTokens : void 0,
|
|
324
|
+
visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),
|
|
325
|
+
cachedTokens: cachedTokens > 0 ? cachedTokens : void 0
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
if (chunk.type === "response.completed" || chunk.type === "response.done") {
|
|
330
|
+
if (chunk.response?.usage) {
|
|
331
|
+
const rawUsage2 = chunk.response.usage;
|
|
332
|
+
const inputTokens = rawUsage2.input_tokens ?? 0;
|
|
333
|
+
const outputTokens = rawUsage2.output_tokens ?? 0;
|
|
334
|
+
const reasoningTokens = rawUsage2.output_token_details?.reasoning_tokens ?? 0;
|
|
335
|
+
const cachedTokens = rawUsage2.input_token_details?.cached_tokens ?? 0;
|
|
336
|
+
return {
|
|
337
|
+
model: chunk.response.model || model,
|
|
338
|
+
usage: {
|
|
339
|
+
inputTokens,
|
|
340
|
+
outputTokens,
|
|
341
|
+
totalTokens: inputTokens + outputTokens,
|
|
342
|
+
reasoningTokens: reasoningTokens > 0 ? reasoningTokens : void 0,
|
|
343
|
+
visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),
|
|
344
|
+
cachedTokens: cachedTokens > 0 ? cachedTokens : void 0
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return { model };
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// src/meter/extractors/anthropic.ts
|
|
353
|
+
function extractAnthropicResponseUsage(response) {
|
|
354
|
+
if (!response || typeof response !== "object") return null;
|
|
355
|
+
if (response.type === "message" || "content" in response && "usage" in response) {
|
|
356
|
+
const rawUsage = response.usage || {};
|
|
357
|
+
const model = response.model || "claude-3-7-sonnet";
|
|
358
|
+
const inputTokens = rawUsage.input_tokens ?? 0;
|
|
359
|
+
const outputTokens = rawUsage.output_tokens ?? 0;
|
|
360
|
+
const cachedTokens = rawUsage.cache_read_input_tokens ?? 0;
|
|
361
|
+
const cacheWriteTokens = rawUsage.cache_creation_input_tokens ?? 0;
|
|
362
|
+
let reasoningTokens = void 0;
|
|
363
|
+
if (Array.isArray(response.content)) {
|
|
364
|
+
const thinkingBlocks = response.content.filter((b) => b.type === "thinking");
|
|
365
|
+
if (thinkingBlocks.length > 0) {
|
|
366
|
+
reasoningTokens = rawUsage.thinking_tokens ?? void 0;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return {
|
|
370
|
+
model,
|
|
371
|
+
provider: "anthropic",
|
|
372
|
+
usage: {
|
|
373
|
+
inputTokens,
|
|
374
|
+
outputTokens,
|
|
375
|
+
totalTokens: inputTokens + outputTokens,
|
|
376
|
+
reasoningTokens,
|
|
377
|
+
visibleOutputTokens: reasoningTokens !== void 0 ? Math.max(0, outputTokens - reasoningTokens) : outputTokens,
|
|
378
|
+
cachedTokens: cachedTokens > 0 ? cachedTokens : void 0,
|
|
379
|
+
cacheWriteTokens: cacheWriteTokens > 0 ? cacheWriteTokens : void 0
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
var AnthropicStreamAccumulator = class {
|
|
386
|
+
model = "claude-3-7-sonnet";
|
|
387
|
+
inputTokens = 0;
|
|
388
|
+
outputTokens = 0;
|
|
389
|
+
cachedTokens = 0;
|
|
390
|
+
cacheWriteTokens = 0;
|
|
391
|
+
reasoningTokens = 0;
|
|
392
|
+
processEvent(event) {
|
|
393
|
+
if (!event || typeof event !== "object") return;
|
|
394
|
+
if (event.type === "message_start" && event.message) {
|
|
395
|
+
if (event.message.model) {
|
|
396
|
+
this.model = event.message.model;
|
|
397
|
+
}
|
|
398
|
+
if (event.message.usage) {
|
|
399
|
+
this.inputTokens = event.message.usage.input_tokens ?? 0;
|
|
400
|
+
this.cachedTokens = event.message.usage.cache_read_input_tokens ?? 0;
|
|
401
|
+
this.cacheWriteTokens = event.message.usage.cache_creation_input_tokens ?? 0;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (event.type === "message_delta" && event.usage) {
|
|
405
|
+
this.outputTokens = event.usage.output_tokens ?? 0;
|
|
406
|
+
if (event.usage.thinking_tokens) {
|
|
407
|
+
this.reasoningTokens = event.usage.thinking_tokens;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (event.type === "content_block_start" && event.content_block?.type === "thinking") {
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
getUsage() {
|
|
414
|
+
return {
|
|
415
|
+
model: this.model,
|
|
416
|
+
provider: "anthropic",
|
|
417
|
+
usage: {
|
|
418
|
+
inputTokens: this.inputTokens,
|
|
419
|
+
outputTokens: this.outputTokens,
|
|
420
|
+
totalTokens: this.inputTokens + this.outputTokens,
|
|
421
|
+
reasoningTokens: this.reasoningTokens > 0 ? this.reasoningTokens : void 0,
|
|
422
|
+
visibleOutputTokens: this.reasoningTokens > 0 ? Math.max(0, this.outputTokens - this.reasoningTokens) : this.outputTokens,
|
|
423
|
+
cachedTokens: this.cachedTokens > 0 ? this.cachedTokens : void 0,
|
|
424
|
+
cacheWriteTokens: this.cacheWriteTokens > 0 ? this.cacheWriteTokens : void 0
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
// src/meter/extractors/gemini.ts
|
|
431
|
+
function extractGeminiResponseUsage(response, fallbackModel = "gemini-3.7-flash") {
|
|
432
|
+
if (!response || typeof response !== "object") return null;
|
|
433
|
+
const usageMetadata = response.usageMetadata || response.response?.usageMetadata;
|
|
434
|
+
if (usageMetadata) {
|
|
435
|
+
const inputTokens = usageMetadata.promptTokenCount ?? 0;
|
|
436
|
+
const baseOutputTokens = usageMetadata.candidatesTokenCount ?? 0;
|
|
437
|
+
const thoughtsTokenCount = usageMetadata.thoughtsTokenCount ?? usageMetadata.reasoningTokenCount ?? 0;
|
|
438
|
+
const cachedTokens = usageMetadata.cachedContentTokenCount ?? 0;
|
|
439
|
+
const totalOutput = baseOutputTokens + thoughtsTokenCount;
|
|
440
|
+
const model = response.model || response.response?.model || fallbackModel;
|
|
441
|
+
return {
|
|
442
|
+
model,
|
|
443
|
+
provider: "google",
|
|
444
|
+
usage: {
|
|
445
|
+
inputTokens,
|
|
446
|
+
outputTokens: totalOutput,
|
|
447
|
+
totalTokens: inputTokens + totalOutput,
|
|
448
|
+
reasoningTokens: thoughtsTokenCount > 0 ? thoughtsTokenCount : void 0,
|
|
449
|
+
visibleOutputTokens: baseOutputTokens,
|
|
450
|
+
cachedTokens: cachedTokens > 0 ? cachedTokens : void 0
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// src/meter/extractors/generic.ts
|
|
458
|
+
function extractGenericResponseUsage(response, fallbackModel = "generic-llm", fallbackProvider = "generic") {
|
|
459
|
+
if (!response || typeof response !== "object") return null;
|
|
460
|
+
const usage = response.usage || response.token_usage || response.usageMetadata;
|
|
461
|
+
if (usage) {
|
|
462
|
+
const inputTokens = usage.prompt_tokens ?? usage.input_tokens ?? usage.promptTokenCount ?? usage.prompt_eval_count ?? 0;
|
|
463
|
+
const outputTokens = usage.completion_tokens ?? usage.output_tokens ?? usage.candidatesTokenCount ?? usage.eval_count ?? 0;
|
|
464
|
+
const reasoningTokens = usage.reasoning_tokens ?? usage.thoughtsTokenCount ?? usage.completion_tokens_details?.reasoning_tokens ?? 0;
|
|
465
|
+
const cachedTokens = usage.prompt_tokens_details?.cached_tokens ?? usage.cached_tokens ?? usage.cachedContentTokenCount ?? 0;
|
|
466
|
+
const model = response.model || fallbackModel;
|
|
467
|
+
const provider = response.provider || fallbackProvider;
|
|
468
|
+
return {
|
|
469
|
+
model,
|
|
470
|
+
provider,
|
|
471
|
+
usage: {
|
|
472
|
+
inputTokens,
|
|
473
|
+
outputTokens,
|
|
474
|
+
totalTokens: inputTokens + outputTokens,
|
|
475
|
+
reasoningTokens: reasoningTokens > 0 ? reasoningTokens : void 0,
|
|
476
|
+
visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),
|
|
477
|
+
cachedTokens: cachedTokens > 0 ? cachedTokens : void 0
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// src/meter/extractors/index.ts
|
|
485
|
+
function detectAndExtractUsage(response, fallbackModel, fallbackProvider) {
|
|
486
|
+
if (!response || typeof response !== "object") return null;
|
|
487
|
+
const openaiResult = extractOpenAIResponseUsage(response);
|
|
488
|
+
if (openaiResult) return openaiResult;
|
|
489
|
+
const anthropicResult = extractAnthropicResponseUsage(response);
|
|
490
|
+
if (anthropicResult) return anthropicResult;
|
|
491
|
+
const geminiResult = extractGeminiResponseUsage(response, fallbackModel);
|
|
492
|
+
if (geminiResult) return geminiResult;
|
|
493
|
+
const genericResult = extractGenericResponseUsage(response, fallbackModel, fallbackProvider);
|
|
494
|
+
if (genericResult) return genericResult;
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// src/pricing/table.ts
|
|
499
|
+
var MODEL_PRICING_TABLE = {
|
|
500
|
+
// --- OpenAI (Modern & Reasoning) ---
|
|
501
|
+
"gpt-5.6-sol": { inputPer1M: 4, outputPer1M: 20, cachedInputPer1M: 0.4 },
|
|
502
|
+
"gpt-5.6-terra": { inputPer1M: 2, outputPer1M: 12, cachedInputPer1M: 0.2 },
|
|
503
|
+
"gpt-5.6-luna": { inputPer1M: 0.2, outputPer1M: 1.2, cachedInputPer1M: 0.02 },
|
|
504
|
+
"gpt-5": { inputPer1M: 4, outputPer1M: 20, cachedInputPer1M: 0.4 },
|
|
505
|
+
"gpt-5-mini": { inputPer1M: 0.2, outputPer1M: 1.2, cachedInputPer1M: 0.02 },
|
|
506
|
+
"o1": { inputPer1M: 15, outputPer1M: 60, cachedInputPer1M: 7.5 },
|
|
507
|
+
"o1-mini": { inputPer1M: 1.1, outputPer1M: 4.4, cachedInputPer1M: 0.55 },
|
|
508
|
+
"o3": { inputPer1M: 15, outputPer1M: 60, cachedInputPer1M: 7.5 },
|
|
509
|
+
"o3-mini": { inputPer1M: 1.1, outputPer1M: 4.4, cachedInputPer1M: 0.55 },
|
|
510
|
+
"gpt-4o": { inputPer1M: 2.5, outputPer1M: 10, cachedInputPer1M: 1.25 },
|
|
511
|
+
"gpt-4o-mini": { inputPer1M: 0.15, outputPer1M: 0.6, cachedInputPer1M: 0.075 },
|
|
512
|
+
"gpt-4.5": { inputPer1M: 75, outputPer1M: 150, cachedInputPer1M: 37.5 },
|
|
513
|
+
"gpt-4.5-preview": { inputPer1M: 75, outputPer1M: 150, cachedInputPer1M: 37.5 },
|
|
514
|
+
"chatgpt-4o-latest": { inputPer1M: 5, outputPer1M: 15 },
|
|
515
|
+
"gpt-4.1": { inputPer1M: 2, outputPer1M: 8, cachedInputPer1M: 1 },
|
|
516
|
+
"gpt-4.1-nano": { inputPer1M: 0.1, outputPer1M: 0.4, cachedInputPer1M: 0.05 },
|
|
517
|
+
// --- OpenAI (Legacy & Backward Compatibility) ---
|
|
518
|
+
"gpt-4-turbo": { inputPer1M: 10, outputPer1M: 30, cachedInputPer1M: 5 },
|
|
519
|
+
"gpt-4-turbo-preview": { inputPer1M: 10, outputPer1M: 30, cachedInputPer1M: 5 },
|
|
520
|
+
"gpt-4": { inputPer1M: 30, outputPer1M: 60 },
|
|
521
|
+
"gpt-4-32k": { inputPer1M: 60, outputPer1M: 120 },
|
|
522
|
+
"gpt-3.5-turbo": { inputPer1M: 0.5, outputPer1M: 1.5 },
|
|
523
|
+
"gpt-3.5-turbo-16k": { inputPer1M: 3, outputPer1M: 4 },
|
|
524
|
+
"text-embedding-3-small": { inputPer1M: 0.02, outputPer1M: 0 },
|
|
525
|
+
"text-embedding-3-large": { inputPer1M: 0.13, outputPer1M: 0 },
|
|
526
|
+
"text-embedding-ada-002": { inputPer1M: 0.1, outputPer1M: 0 },
|
|
527
|
+
// --- Anthropic (Modern & Extended Thinking) ---
|
|
528
|
+
"claude-3-7-sonnet": { inputPer1M: 0.59, outputPer1M: 2.93, cachedInputPer1M: 0.3 },
|
|
529
|
+
"claude-sonnet-5": { inputPer1M: 2, outputPer1M: 10, cachedInputPer1M: 0.3 },
|
|
530
|
+
"claude-3-5-sonnet": { inputPer1M: 3, outputPer1M: 15, cachedInputPer1M: 0.3 },
|
|
531
|
+
"claude-3-5-haiku": { inputPer1M: 0.8, outputPer1M: 4, cachedInputPer1M: 0.08 },
|
|
532
|
+
"haiku-4.5": { inputPer1M: 1, outputPer1M: 5, cachedInputPer1M: 0.1 },
|
|
533
|
+
"claude-opus-5": { inputPer1M: 5, outputPer1M: 25, cachedInputPer1M: 1.5 },
|
|
534
|
+
"claude-3-opus": { inputPer1M: 15, outputPer1M: 75, cachedInputPer1M: 1.5 },
|
|
535
|
+
// --- Anthropic (Legacy & Backward Compatibility) ---
|
|
536
|
+
"claude-3-sonnet": { inputPer1M: 3, outputPer1M: 15, cachedInputPer1M: 0.3 },
|
|
537
|
+
"claude-3-haiku": { inputPer1M: 0.25, outputPer1M: 1.25, cachedInputPer1M: 0.025 },
|
|
538
|
+
"claude-2.1": { inputPer1M: 8, outputPer1M: 24 },
|
|
539
|
+
"claude-2.0": { inputPer1M: 8, outputPer1M: 24 },
|
|
540
|
+
"claude-instant-1.2": { inputPer1M: 1.63, outputPer1M: 5.51 },
|
|
541
|
+
// --- Google Gemini (Modern & Thoughts) ---
|
|
542
|
+
"gemini-3.7-flash": { inputPer1M: 0.75, outputPer1M: 3.75, cachedInputPer1M: 0.18 },
|
|
543
|
+
"gemini-3.1-pro": { inputPer1M: 2, outputPer1M: 12, cachedInputPer1M: 0.5 },
|
|
544
|
+
"gemini-3.5-flash": { inputPer1M: 1.5, outputPer1M: 9, cachedInputPer1M: 0.38 },
|
|
545
|
+
"gemini-3.1-flash-lite": { inputPer1M: 0.25, outputPer1M: 1.5, cachedInputPer1M: 0.06 },
|
|
546
|
+
"gemini-2.5-pro": { inputPer1M: 1.25, outputPer1M: 5, cachedInputPer1M: 0.3125 },
|
|
547
|
+
"gemini-2.5-flash": { inputPer1M: 0.15, outputPer1M: 0.6, cachedInputPer1M: 0.0375 },
|
|
548
|
+
"gemini-2.0-flash": { inputPer1M: 0.1, outputPer1M: 0.4, cachedInputPer1M: 0.025 },
|
|
549
|
+
"gemini-2.0-flash-lite": { inputPer1M: 0.075, outputPer1M: 0.3, cachedInputPer1M: 0.01875 },
|
|
550
|
+
"gemini-2.0-pro": { inputPer1M: 1.25, outputPer1M: 5, cachedInputPer1M: 0.3125 },
|
|
551
|
+
// --- Google Gemini (Legacy & Backward Compatibility) ---
|
|
552
|
+
"gemini-1.5-pro": { inputPer1M: 1.25, outputPer1M: 5, cachedInputPer1M: 0.3125 },
|
|
553
|
+
"gemini-1.5-flash": { inputPer1M: 0.075, outputPer1M: 0.3, cachedInputPer1M: 0.01875 },
|
|
554
|
+
"gemini-1.5-flash-8b": { inputPer1M: 0.0375, outputPer1M: 0.15, cachedInputPer1M: 9375e-6 },
|
|
555
|
+
"gemini-1.0-pro": { inputPer1M: 0.5, outputPer1M: 1.5 },
|
|
556
|
+
// --- xAI Grok ---
|
|
557
|
+
"grok-4.6": { inputPer1M: 3, outputPer1M: 15 },
|
|
558
|
+
"grok-3": { inputPer1M: 3, outputPer1M: 15 },
|
|
559
|
+
"grok-3-mini": { inputPer1M: 0.3, outputPer1M: 1.5 },
|
|
560
|
+
"grok-2": { inputPer1M: 2, outputPer1M: 10 },
|
|
561
|
+
"grok-2-vision": { inputPer1M: 2, outputPer1M: 10 },
|
|
562
|
+
"grok-beta": { inputPer1M: 5, outputPer1M: 15 },
|
|
563
|
+
// --- Mistral ---
|
|
564
|
+
"mistral-large-3": { inputPer1M: 2, outputPer1M: 6 },
|
|
565
|
+
"mistral-large-latest": { inputPer1M: 2, outputPer1M: 6 },
|
|
566
|
+
"mistral-large-2411": { inputPer1M: 2, outputPer1M: 6 },
|
|
567
|
+
"codestral-latest": { inputPer1M: 0.3, outputPer1M: 0.9 },
|
|
568
|
+
"mistral-medium-latest": { inputPer1M: 2.7, outputPer1M: 8.1 },
|
|
569
|
+
"mistral-small-latest": { inputPer1M: 0.2, outputPer1M: 0.6 },
|
|
570
|
+
"ministral-8b-latest": { inputPer1M: 0.1, outputPer1M: 0.1 },
|
|
571
|
+
"ministral-3b-latest": { inputPer1M: 0.04, outputPer1M: 0.04 },
|
|
572
|
+
"open-mistral-7b": { inputPer1M: 0.2, outputPer1M: 0.2 },
|
|
573
|
+
"open-mixtral-8x7b": { inputPer1M: 0.7, outputPer1M: 0.7 },
|
|
574
|
+
"open-mixtral-8x22b": { inputPer1M: 2, outputPer1M: 6 },
|
|
575
|
+
// --- Groq & Meta Llama LPUs ---
|
|
576
|
+
"llama-3.3-70b-versatile": { inputPer1M: 0.59, outputPer1M: 0.79 },
|
|
577
|
+
"llama-3.1-405b": { inputPer1M: 3, outputPer1M: 3 },
|
|
578
|
+
"llama-3.1-70b-versatile": { inputPer1M: 0.59, outputPer1M: 0.79 },
|
|
579
|
+
"llama-3.1-8b-instant": { inputPer1M: 0.05, outputPer1M: 0.08 },
|
|
580
|
+
"llama-3.2-1b-preview": { inputPer1M: 0.04, outputPer1M: 0.04 },
|
|
581
|
+
"llama-3.2-3b-preview": { inputPer1M: 0.06, outputPer1M: 0.06 },
|
|
582
|
+
"llama-3.2-11b-vision": { inputPer1M: 0.18, outputPer1M: 0.18 },
|
|
583
|
+
"llama-3.2-90b-vision": { inputPer1M: 0.9, outputPer1M: 0.9 },
|
|
584
|
+
"deepseek-r1-distill-llama-70b": { inputPer1M: 0.75, outputPer1M: 0.99 },
|
|
585
|
+
"deepseek-r1-distill-qwen-32b": { inputPer1M: 0.49, outputPer1M: 0.49 },
|
|
586
|
+
"qwen-2.5-32b": { inputPer1M: 0.29, outputPer1M: 0.39 },
|
|
587
|
+
"qwen-2.5-72b": { inputPer1M: 0.35, outputPer1M: 0.4 },
|
|
588
|
+
"mixtral-8x7b-32768": { inputPer1M: 0.24, outputPer1M: 0.24 },
|
|
589
|
+
"gemma2-9b-it": { inputPer1M: 0.2, outputPer1M: 0.2 },
|
|
590
|
+
// --- DeepSeek ---
|
|
591
|
+
"deepseek-v4-pro": { inputPer1M: 0.66, outputPer1M: 1.98, cachedInputPer1M: 0.15 },
|
|
592
|
+
"deepseek-v4-flash": { inputPer1M: 0.22, outputPer1M: 0.66, cachedInputPer1M: 0.05 },
|
|
593
|
+
"deepseek-v3": { inputPer1M: 0.14, outputPer1M: 0.28, cachedInputPer1M: 0.014 },
|
|
594
|
+
"deepseek-chat": { inputPer1M: 0.14, outputPer1M: 0.28, cachedInputPer1M: 0.014 },
|
|
595
|
+
"deepseek-r1": { inputPer1M: 0.55, outputPer1M: 2.19, cachedInputPer1M: 0.14 },
|
|
596
|
+
"deepseek-reasoner": { inputPer1M: 0.55, outputPer1M: 2.19, cachedInputPer1M: 0.14 },
|
|
597
|
+
// --- Cohere ---
|
|
598
|
+
"command-r-plus": { inputPer1M: 2.5, outputPer1M: 10 },
|
|
599
|
+
"command-r": { inputPer1M: 0.15, outputPer1M: 0.6 },
|
|
600
|
+
"command": { inputPer1M: 1, outputPer1M: 2 },
|
|
601
|
+
"command-light": { inputPer1M: 0.3, outputPer1M: 0.6 },
|
|
602
|
+
"embed-english-v3.0": { inputPer1M: 0.1, outputPer1M: 0 },
|
|
603
|
+
// --- Perplexity ---
|
|
604
|
+
"sonar": { inputPer1M: 1, outputPer1M: 1 },
|
|
605
|
+
"sonar-pro": { inputPer1M: 3, outputPer1M: 15 },
|
|
606
|
+
"sonar-reasoning": { inputPer1M: 1, outputPer1M: 5 },
|
|
607
|
+
"sonar-reasoning-pro": { inputPer1M: 2, outputPer1M: 8 }
|
|
608
|
+
};
|
|
609
|
+
var MODEL_ALIASES = {
|
|
610
|
+
// OpenAI Shorthands & Aliases
|
|
611
|
+
"gpt4": "gpt-4",
|
|
612
|
+
"gpt4o": "gpt-4o",
|
|
613
|
+
"gpt-4-preview": "gpt-4-turbo",
|
|
614
|
+
"gpt-4-0125-preview": "gpt-4-turbo",
|
|
615
|
+
"gpt-4-1106-preview": "gpt-4-turbo",
|
|
616
|
+
"gpt-3.5": "gpt-3.5-turbo",
|
|
617
|
+
"gpt-3.5-turbo-0125": "gpt-3.5-turbo",
|
|
618
|
+
"gpt-3.5-turbo-1106": "gpt-3.5-turbo",
|
|
619
|
+
"gpt-3.5-turbo-16k-0613": "gpt-3.5-turbo-16k",
|
|
620
|
+
// Anthropic Shorthands
|
|
621
|
+
"sonnet": "claude-3-5-sonnet",
|
|
622
|
+
"sonnet-3.7": "claude-3-7-sonnet",
|
|
623
|
+
"sonnet-3.5": "claude-3-5-sonnet",
|
|
624
|
+
"haiku": "claude-3-5-haiku",
|
|
625
|
+
"haiku-3.5": "claude-3-5-haiku",
|
|
626
|
+
"opus": "claude-3-opus",
|
|
627
|
+
"claude-2": "claude-2.0",
|
|
628
|
+
"claude-instant": "claude-instant-1.2",
|
|
629
|
+
// DeepSeek Shorthands
|
|
630
|
+
"r1": "deepseek-r1",
|
|
631
|
+
"v3": "deepseek-v3",
|
|
632
|
+
// Gemini Shorthands
|
|
633
|
+
"flash": "gemini-2.0-flash",
|
|
634
|
+
"pro": "gemini-1.5-pro",
|
|
635
|
+
// Meta / Groq Shorthands
|
|
636
|
+
"llama-3.3-70b": "llama-3.3-70b-versatile",
|
|
637
|
+
"llama-3.1-70b": "llama-3.1-70b-versatile",
|
|
638
|
+
"llama-3.1-8b": "llama-3.1-8b-instant",
|
|
639
|
+
"llama-3-70b": "llama-3.1-70b-versatile",
|
|
640
|
+
"llama-3-8b": "llama-3.1-8b-instant",
|
|
641
|
+
// Mistral Shorthands
|
|
642
|
+
"codestral": "codestral-latest",
|
|
643
|
+
"mistral-large": "mistral-large-latest",
|
|
644
|
+
"mistral-small": "mistral-small-latest"
|
|
645
|
+
};
|
|
646
|
+
var customPricingRegistry = {};
|
|
647
|
+
function normalizeModelKey(rawModel) {
|
|
648
|
+
if (!rawModel) return "unknown";
|
|
649
|
+
let model = rawModel.toLowerCase().trim();
|
|
650
|
+
model = model.replace(/^[a-z0-9_-]+\.(anthropic|meta|amazon|cohere|mistral|ai21)\./i, "");
|
|
651
|
+
model = model.replace(/^(anthropic|meta|amazon|cohere|mistral|ai21)\./i, "");
|
|
652
|
+
model = model.replace(/-v\d+(:\d+)?$/, "");
|
|
653
|
+
model = model.replace(/:\d+$/, "");
|
|
654
|
+
if (model.includes("/")) {
|
|
655
|
+
model = model.split("/").slice(1).join("/");
|
|
656
|
+
}
|
|
657
|
+
model = model.replace(/:(latest|free|beta)$/, "");
|
|
658
|
+
model = model.replace(/-\d{8}$/, "");
|
|
659
|
+
model = model.replace(/-\d{4}-\d{2}-\d{2}$/, "");
|
|
660
|
+
model = model.replace(/llama(\d+)-(\d+)-/g, "llama-$1.$2-");
|
|
661
|
+
model = model.replace(/llama(\d+)\.(\d+)-/g, "llama-$1.$2-");
|
|
662
|
+
if (MODEL_ALIASES[model]) {
|
|
663
|
+
return MODEL_ALIASES[model];
|
|
664
|
+
}
|
|
665
|
+
if (!MODEL_PRICING_TABLE[model]) {
|
|
666
|
+
const withoutInstruct = model.replace(/-(instruct|chat|preview)$/, "");
|
|
667
|
+
if (MODEL_PRICING_TABLE[withoutInstruct]) {
|
|
668
|
+
return withoutInstruct;
|
|
669
|
+
}
|
|
670
|
+
if (MODEL_ALIASES[withoutInstruct]) {
|
|
671
|
+
return MODEL_ALIASES[withoutInstruct];
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return model;
|
|
675
|
+
}
|
|
676
|
+
function getModelPricing(modelName) {
|
|
677
|
+
const normalized = normalizeModelKey(modelName);
|
|
678
|
+
if (customPricingRegistry[normalized]) {
|
|
679
|
+
return customPricingRegistry[normalized];
|
|
680
|
+
}
|
|
681
|
+
if (customPricingRegistry[modelName]) {
|
|
682
|
+
return customPricingRegistry[modelName];
|
|
683
|
+
}
|
|
684
|
+
if (MODEL_PRICING_TABLE[normalized]) {
|
|
685
|
+
return MODEL_PRICING_TABLE[normalized];
|
|
686
|
+
}
|
|
687
|
+
if (MODEL_PRICING_TABLE[modelName]) {
|
|
688
|
+
return MODEL_PRICING_TABLE[modelName];
|
|
689
|
+
}
|
|
690
|
+
const alias = MODEL_ALIASES[modelName.toLowerCase().trim()];
|
|
691
|
+
if (alias && MODEL_PRICING_TABLE[alias]) {
|
|
692
|
+
return MODEL_PRICING_TABLE[alias];
|
|
693
|
+
}
|
|
694
|
+
return {
|
|
695
|
+
inputPer1M: 1,
|
|
696
|
+
outputPer1M: 3,
|
|
697
|
+
cachedInputPer1M: 0.5
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// src/pricing/calculator.ts
|
|
702
|
+
function calculateCost(params) {
|
|
703
|
+
let rates;
|
|
704
|
+
if (params.customRate) {
|
|
705
|
+
const outRate = params.customRate.out ?? params.customRate.output ?? 0;
|
|
706
|
+
rates = {
|
|
707
|
+
inputPer1M: params.customRate.in,
|
|
708
|
+
outputPer1M: outRate,
|
|
709
|
+
reasoningPer1M: params.customRate.reasoning ?? outRate,
|
|
710
|
+
cachedInputPer1M: params.customRate.cached ?? params.customRate.in * 0.15,
|
|
711
|
+
currency: "USD"
|
|
712
|
+
};
|
|
713
|
+
} else {
|
|
714
|
+
rates = getModelPricing(params.model);
|
|
715
|
+
}
|
|
716
|
+
const inputTokens = BigInt(Math.max(0, params.inputTokens ?? 0));
|
|
717
|
+
const outputTokens = BigInt(Math.max(0, params.outputTokens ?? 0));
|
|
718
|
+
const reasoningTokens = BigInt(Math.max(0, params.reasoningTokens ?? 0));
|
|
719
|
+
const cachedTokens = BigInt(Math.max(0, params.cachedTokens ?? 0));
|
|
720
|
+
const regularInputTokens = inputTokens > cachedTokens ? inputTokens - cachedTokens : 0n;
|
|
721
|
+
const rateInputNano = BigInt(Math.round(rates.inputPer1M * 1e3));
|
|
722
|
+
const cachedPer1M = rates.cachedInputPer1M ?? rates.inputPer1M * 0.15;
|
|
723
|
+
const rateCachedNano = BigInt(Math.round(cachedPer1M * 1e3));
|
|
724
|
+
const rateOutputNano = BigInt(Math.round(rates.outputPer1M * 1e3));
|
|
725
|
+
const reasoningPer1M = rates.reasoningPer1M ?? rates.outputPer1M;
|
|
726
|
+
const rateReasoningNano = BigInt(Math.round(reasoningPer1M * 1e3));
|
|
727
|
+
const regularInputCostNano = regularInputTokens * rateInputNano;
|
|
728
|
+
const cachedInputCostNano = cachedTokens * rateCachedNano;
|
|
729
|
+
const inputCostNano = regularInputCostNano + cachedInputCostNano;
|
|
730
|
+
const outputCostNano = outputTokens * rateOutputNano;
|
|
731
|
+
const reasoningCostNano = reasoningTokens * rateReasoningNano;
|
|
732
|
+
const standardCacheCostNano = cachedTokens * rateInputNano;
|
|
733
|
+
const cachedDiscountNano = standardCacheCostNano > cachedInputCostNano ? standardCacheCostNano - cachedInputCostNano : 0n;
|
|
734
|
+
const wholesaleNano = inputCostNano + outputCostNano;
|
|
735
|
+
const markup = params.markupMultiplier ?? 1;
|
|
736
|
+
let billedNano = wholesaleNano;
|
|
737
|
+
let hasRetail = false;
|
|
738
|
+
if (markup !== 1 || params.minimumChargeUSD !== void 0) {
|
|
739
|
+
hasRetail = true;
|
|
740
|
+
const markupMultiplierNano = BigInt(Math.round(markup * 1e3));
|
|
741
|
+
billedNano = wholesaleNano * markupMultiplierNano / 1000n;
|
|
742
|
+
if (params.minimumChargeUSD !== void 0 && params.minimumChargeUSD > 0) {
|
|
743
|
+
const minChargeNano = BigInt(Math.round(params.minimumChargeUSD * 1e9));
|
|
744
|
+
if (billedNano < minChargeNano) {
|
|
745
|
+
billedNano = minChargeNano;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
const inputCostUSD = Number(inputCostNano) / 1e9;
|
|
750
|
+
const outputCostUSD = Number(outputCostNano) / 1e9;
|
|
751
|
+
const reasoningCostUSD = Number(reasoningCostNano) / 1e9;
|
|
752
|
+
const cachedDiscountUSD = Number(cachedDiscountNano) / 1e9;
|
|
753
|
+
const totalUSD = Number(wholesaleNano) / 1e9;
|
|
754
|
+
const wholesaleTotalUSD = totalUSD;
|
|
755
|
+
const billedUSD = Number(billedNano) / 1e9;
|
|
756
|
+
const profitUSD = Math.max(0, billedUSD - wholesaleTotalUSD);
|
|
757
|
+
const retailUSD = hasRetail ? billedUSD : void 0;
|
|
758
|
+
return {
|
|
759
|
+
inputCostUSD: Number(inputCostUSD.toFixed(8)),
|
|
760
|
+
outputCostUSD: Number(outputCostUSD.toFixed(8)),
|
|
761
|
+
reasoningCostUSD: reasoningTokens > 0n ? Number(reasoningCostUSD.toFixed(8)) : void 0,
|
|
762
|
+
cachedDiscountUSD: cachedTokens > 0n ? Number(cachedDiscountUSD.toFixed(8)) : void 0,
|
|
763
|
+
totalUSD: Number(totalUSD.toFixed(8)),
|
|
764
|
+
wholesaleTotalUSD: Number(wholesaleTotalUSD.toFixed(8)),
|
|
765
|
+
billedUSD: Number(billedUSD.toFixed(8)),
|
|
766
|
+
profitUSD: Number(profitUSD.toFixed(8)),
|
|
767
|
+
retailUSD: retailUSD !== void 0 ? Number(retailUSD.toFixed(8)) : void 0,
|
|
768
|
+
currency: rates.currency || "USD"
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
function calculateUsageCost(model, usage, optionsOrMarkup) {
|
|
772
|
+
const options = typeof optionsOrMarkup === "number" ? { markupMultiplier: optionsOrMarkup } : optionsOrMarkup || {};
|
|
773
|
+
return calculateCost({
|
|
774
|
+
model,
|
|
775
|
+
inputTokens: usage.inputTokens,
|
|
776
|
+
outputTokens: usage.outputTokens,
|
|
777
|
+
reasoningTokens: usage.reasoningTokens,
|
|
778
|
+
cachedTokens: usage.cachedTokens,
|
|
779
|
+
cacheWriteTokens: usage.cacheWriteTokens,
|
|
780
|
+
markupMultiplier: options.markupMultiplier,
|
|
781
|
+
minimumChargeUSD: options.minimumChargeUSD,
|
|
782
|
+
customRate: options.customRate
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// src/customers/helpers.ts
|
|
787
|
+
function normalizeCustomer(customer, extraCustomerId) {
|
|
788
|
+
if (!customer && !extraCustomerId) {
|
|
789
|
+
return {
|
|
790
|
+
customerId: void 0,
|
|
791
|
+
customerEmail: void 0,
|
|
792
|
+
customerObj: void 0,
|
|
793
|
+
customerMetadata: {}
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
if (typeof customer === "string") {
|
|
797
|
+
const isEmail = customer.includes("@");
|
|
798
|
+
const customerObj2 = {
|
|
799
|
+
id: customer,
|
|
800
|
+
email: isEmail ? customer : void 0
|
|
801
|
+
};
|
|
802
|
+
return {
|
|
803
|
+
customerId: customer,
|
|
804
|
+
customerEmail: isEmail ? customer : void 0,
|
|
805
|
+
customerObj: customerObj2,
|
|
806
|
+
customerMetadata: {}
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
const customerObj = customer || (extraCustomerId ? { id: extraCustomerId } : void 0);
|
|
810
|
+
const customerId = customerObj?.id || customerObj?.userId || extraCustomerId;
|
|
811
|
+
const customerEmail = customerObj?.email;
|
|
812
|
+
const customerMetadata = {};
|
|
813
|
+
if (customerObj) {
|
|
814
|
+
const orgId = customerObj.orgId || customerObj.organizationId;
|
|
815
|
+
if (orgId) customerMetadata.org_id = String(orgId);
|
|
816
|
+
const teamId = customerObj.teamId || customerObj.workspaceId;
|
|
817
|
+
if (teamId) customerMetadata.team_id = String(teamId);
|
|
818
|
+
if (customerObj.plan) customerMetadata.plan = String(customerObj.plan);
|
|
819
|
+
if (customerObj.tier) customerMetadata.tier = String(customerObj.tier);
|
|
820
|
+
if (customerObj.role) customerMetadata.role = String(customerObj.role);
|
|
821
|
+
if (customerObj.orgName) customerMetadata.org_name = String(customerObj.orgName);
|
|
822
|
+
if (customerObj.metadata) {
|
|
823
|
+
for (const [key, val] of Object.entries(customerObj.metadata)) {
|
|
824
|
+
if (val !== null && val !== void 0) {
|
|
825
|
+
customerMetadata[key] = val;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
return {
|
|
831
|
+
customerId,
|
|
832
|
+
customerEmail,
|
|
833
|
+
customerObj,
|
|
834
|
+
customerMetadata
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// src/meter/stream.ts
|
|
839
|
+
function wrapOpenAIStream(stream, options, onComplete) {
|
|
840
|
+
let detectedModel = options.model || "gpt-4o";
|
|
841
|
+
let finalUsage = null;
|
|
842
|
+
const wrappedAsyncIterable = {
|
|
843
|
+
async *[Symbol.asyncIterator]() {
|
|
844
|
+
try {
|
|
845
|
+
for await (const chunk of stream) {
|
|
846
|
+
const inspected = inspectOpenAIStreamChunk(chunk);
|
|
847
|
+
if (inspected.model) {
|
|
848
|
+
detectedModel = inspected.model;
|
|
849
|
+
}
|
|
850
|
+
if (inspected.usage) {
|
|
851
|
+
finalUsage = inspected.usage;
|
|
852
|
+
}
|
|
853
|
+
yield chunk;
|
|
854
|
+
}
|
|
855
|
+
} finally {
|
|
856
|
+
if (finalUsage) {
|
|
857
|
+
const cost = calculateUsageCost(detectedModel, finalUsage);
|
|
858
|
+
const normalized = normalizeCustomer(options.customer, options.customerId);
|
|
859
|
+
const event = {
|
|
860
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
861
|
+
model: detectedModel,
|
|
862
|
+
provider: "openai",
|
|
863
|
+
usage: finalUsage,
|
|
864
|
+
cost,
|
|
865
|
+
customerId: normalized.customerId,
|
|
866
|
+
customerEmail: normalized.customerEmail,
|
|
867
|
+
customer: normalized.customerObj,
|
|
868
|
+
metadata: {
|
|
869
|
+
...normalized.customerMetadata,
|
|
870
|
+
...options.metadata
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
onComplete(event);
|
|
874
|
+
if (options.onUsage) {
|
|
875
|
+
options.onUsage(event);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
return wrappedAsyncIterable;
|
|
882
|
+
}
|
|
883
|
+
function wrapAnthropicStream(stream, options, onComplete) {
|
|
884
|
+
const accumulator = new AnthropicStreamAccumulator();
|
|
885
|
+
const wrappedAsyncIterable = {
|
|
886
|
+
async *[Symbol.asyncIterator]() {
|
|
887
|
+
try {
|
|
888
|
+
for await (const event of stream) {
|
|
889
|
+
accumulator.processEvent(event);
|
|
890
|
+
yield event;
|
|
891
|
+
}
|
|
892
|
+
} finally {
|
|
893
|
+
const extracted = accumulator.getUsage();
|
|
894
|
+
const model = options.model || extracted.model;
|
|
895
|
+
const cost = calculateUsageCost(model, extracted.usage);
|
|
896
|
+
const normalized = normalizeCustomer(options.customer, options.customerId);
|
|
897
|
+
const usageEvent = {
|
|
898
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
899
|
+
model,
|
|
900
|
+
provider: "anthropic",
|
|
901
|
+
usage: extracted.usage,
|
|
902
|
+
cost,
|
|
903
|
+
customerId: normalized.customerId,
|
|
904
|
+
customerEmail: normalized.customerEmail,
|
|
905
|
+
customer: normalized.customerObj,
|
|
906
|
+
metadata: {
|
|
907
|
+
...normalized.customerMetadata,
|
|
908
|
+
...options.metadata
|
|
909
|
+
}
|
|
910
|
+
};
|
|
911
|
+
onComplete(usageEvent);
|
|
912
|
+
if (options.onUsage) {
|
|
913
|
+
options.onUsage(usageEvent);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
return wrappedAsyncIterable;
|
|
919
|
+
}
|
|
920
|
+
function wrapGeminiStream(result, options, onComplete) {
|
|
921
|
+
if (!result || !result.stream) return result;
|
|
922
|
+
const originalStream = result.stream;
|
|
923
|
+
const model = options.model || "gemini-3.7-flash";
|
|
924
|
+
let lastChunkWithUsage = null;
|
|
925
|
+
const wrappedStream = (async function* () {
|
|
926
|
+
try {
|
|
927
|
+
for await (const chunk of originalStream) {
|
|
928
|
+
if (chunk.usageMetadata) {
|
|
929
|
+
lastChunkWithUsage = chunk;
|
|
930
|
+
}
|
|
931
|
+
yield chunk;
|
|
932
|
+
}
|
|
933
|
+
} finally {
|
|
934
|
+
if (lastChunkWithUsage) {
|
|
935
|
+
const extracted = extractGeminiResponseUsage(lastChunkWithUsage, model);
|
|
936
|
+
if (extracted) {
|
|
937
|
+
const cost = calculateUsageCost(extracted.model, extracted.usage);
|
|
938
|
+
const normalized = normalizeCustomer(options.customer, options.customerId);
|
|
939
|
+
const event = {
|
|
940
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
941
|
+
model: extracted.model,
|
|
942
|
+
provider: "google",
|
|
943
|
+
usage: extracted.usage,
|
|
944
|
+
cost,
|
|
945
|
+
customerId: normalized.customerId,
|
|
946
|
+
customerEmail: normalized.customerEmail,
|
|
947
|
+
customer: normalized.customerObj,
|
|
948
|
+
metadata: {
|
|
949
|
+
...normalized.customerMetadata,
|
|
950
|
+
...options.metadata
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
onComplete(event);
|
|
954
|
+
if (options.onUsage) {
|
|
955
|
+
options.onUsage(event);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
})();
|
|
961
|
+
return {
|
|
962
|
+
...result,
|
|
963
|
+
stream: wrappedStream
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
function wrapUniversalStream(stream, options = {}, onComplete) {
|
|
967
|
+
if (!stream || typeof stream !== "object") return stream;
|
|
968
|
+
if ("stream" in stream && "response" in stream) {
|
|
969
|
+
return wrapGeminiStream(stream, options, onComplete);
|
|
970
|
+
}
|
|
971
|
+
if (Symbol.asyncIterator in stream) {
|
|
972
|
+
if (options.provider === "anthropic" || options.model?.toLowerCase().includes("claude")) {
|
|
973
|
+
return wrapAnthropicStream(stream, options, onComplete);
|
|
974
|
+
}
|
|
975
|
+
return wrapOpenAIStream(stream, options, onComplete);
|
|
976
|
+
}
|
|
977
|
+
return stream;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// src/meter/client.ts
|
|
981
|
+
var VibezMeter = class {
|
|
982
|
+
batcher;
|
|
983
|
+
stripeClient;
|
|
984
|
+
markupMultiplier;
|
|
985
|
+
constructor(options = {}) {
|
|
986
|
+
this.markupMultiplier = options.markupMultiplier;
|
|
987
|
+
if (options.stripe) {
|
|
988
|
+
this.stripeClient = options.stripe;
|
|
989
|
+
} else if (options.apiKey || process.env.STRIPE_SECRET_KEY) {
|
|
990
|
+
const key = options.apiKey || process.env.STRIPE_SECRET_KEY;
|
|
991
|
+
this.stripeClient = new import_stripe.default(key, {
|
|
992
|
+
appInfo: {
|
|
993
|
+
name: "vibezcheck",
|
|
994
|
+
version: "0.5.3",
|
|
995
|
+
url: "https://vibezcheck.xyz"
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
this.batcher = new MeterBatcher({
|
|
1000
|
+
...options,
|
|
1001
|
+
stripe: this.stripeClient
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Track token usage from a non-streaming response object (OpenAI, Anthropic, Gemini, etc.)
|
|
1006
|
+
*/
|
|
1007
|
+
trackUsage(response, options = {}) {
|
|
1008
|
+
const extracted = detectAndExtractUsage(response, options.model, options.provider);
|
|
1009
|
+
if (!extracted) {
|
|
1010
|
+
return null;
|
|
1011
|
+
}
|
|
1012
|
+
const model = options.model || extracted.model;
|
|
1013
|
+
const cost = calculateUsageCost(model, extracted.usage, this.markupMultiplier);
|
|
1014
|
+
const normalized = normalizeCustomer(options.customer, options.customerId);
|
|
1015
|
+
const mergedMeta = {
|
|
1016
|
+
...normalized.customerMetadata,
|
|
1017
|
+
...options.metadata
|
|
1018
|
+
};
|
|
1019
|
+
const event = {
|
|
1020
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1021
|
+
model,
|
|
1022
|
+
provider: extracted.provider,
|
|
1023
|
+
usage: extracted.usage,
|
|
1024
|
+
cost,
|
|
1025
|
+
customerId: normalized.customerId,
|
|
1026
|
+
customerEmail: normalized.customerEmail,
|
|
1027
|
+
customer: normalized.customerObj,
|
|
1028
|
+
metadata: mergedMeta
|
|
1029
|
+
};
|
|
1030
|
+
this.batcher.enqueue(event);
|
|
1031
|
+
return event;
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Wrap any LLM stream (OpenAI, Anthropic, Gemini) with zero added latency
|
|
1035
|
+
*/
|
|
1036
|
+
wrapStream(stream, options = {}) {
|
|
1037
|
+
return wrapUniversalStream(stream, options, (event) => {
|
|
1038
|
+
this.batcher.enqueue(event);
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Directly record token usage manually
|
|
1043
|
+
*/
|
|
1044
|
+
recordUsage(options) {
|
|
1045
|
+
const inputTokens = options.inputTokens ?? 0;
|
|
1046
|
+
const outputTokens = options.outputTokens ?? 0;
|
|
1047
|
+
const reasoningTokens = options.reasoningTokens;
|
|
1048
|
+
const cachedTokens = options.cachedTokens;
|
|
1049
|
+
const usage = {
|
|
1050
|
+
inputTokens,
|
|
1051
|
+
outputTokens,
|
|
1052
|
+
totalTokens: inputTokens + outputTokens,
|
|
1053
|
+
reasoningTokens,
|
|
1054
|
+
visibleOutputTokens: reasoningTokens !== void 0 ? Math.max(0, outputTokens - reasoningTokens) : outputTokens,
|
|
1055
|
+
cachedTokens
|
|
1056
|
+
};
|
|
1057
|
+
const cost = calculateUsageCost(options.model, usage, this.markupMultiplier);
|
|
1058
|
+
const normalized = normalizeCustomer(options.customer, options.customerId);
|
|
1059
|
+
const mergedMeta = {
|
|
1060
|
+
...normalized.customerMetadata,
|
|
1061
|
+
...options.metadata
|
|
1062
|
+
};
|
|
1063
|
+
const event = {
|
|
1064
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1065
|
+
model: options.model,
|
|
1066
|
+
provider: options.provider || "custom",
|
|
1067
|
+
usage,
|
|
1068
|
+
cost,
|
|
1069
|
+
customerId: normalized.customerId,
|
|
1070
|
+
customerEmail: normalized.customerEmail,
|
|
1071
|
+
customer: normalized.customerObj,
|
|
1072
|
+
metadata: mergedMeta
|
|
1073
|
+
};
|
|
1074
|
+
this.batcher.enqueue(event);
|
|
1075
|
+
return event;
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Flush pending events to Stripe (vital for Serverless & Edge environments)
|
|
1079
|
+
*/
|
|
1080
|
+
async flush() {
|
|
1081
|
+
await this.batcher.flush();
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Get in-memory aggregated usage statistics
|
|
1085
|
+
*/
|
|
1086
|
+
getUsageSummary() {
|
|
1087
|
+
return this.batcher.getSummary();
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Reset in-memory ledger
|
|
1091
|
+
*/
|
|
1092
|
+
resetSummary() {
|
|
1093
|
+
this.batcher.resetLedger();
|
|
1094
|
+
}
|
|
1095
|
+
};
|
|
1096
|
+
function createMeter(options = {}) {
|
|
1097
|
+
return new VibezMeter(options);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// src/ai-sdk/with-billing.ts
|
|
1101
|
+
function withBilling(model, optionsOrCustomer, extraOptions = {}) {
|
|
1102
|
+
if (!model || typeof model !== "object") {
|
|
1103
|
+
return model;
|
|
1104
|
+
}
|
|
1105
|
+
let options = {};
|
|
1106
|
+
if (typeof optionsOrCustomer === "string") {
|
|
1107
|
+
options = { ...extraOptions, customer: optionsOrCustomer };
|
|
1108
|
+
} else if (typeof optionsOrCustomer === "object" && optionsOrCustomer !== null) {
|
|
1109
|
+
if ("userId" in optionsOrCustomer || "email" in optionsOrCustomer || "id" in optionsOrCustomer) {
|
|
1110
|
+
options = { ...extraOptions, customer: optionsOrCustomer };
|
|
1111
|
+
} else {
|
|
1112
|
+
options = { ...optionsOrCustomer, ...extraOptions };
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
const meter = options.meter || createMeter({
|
|
1116
|
+
apiKey: options.stripeApiKey,
|
|
1117
|
+
eventName: options.eventName
|
|
1118
|
+
});
|
|
1119
|
+
const normalized = normalizeCustomer(options.customer, options.customerId);
|
|
1120
|
+
const customerId = normalized.customerId;
|
|
1121
|
+
const customerEmail = normalized.customerEmail;
|
|
1122
|
+
const customerObj = normalized.customerObj;
|
|
1123
|
+
const customerMetadata = normalized.customerMetadata;
|
|
1124
|
+
const modelId = model.modelId || "unknown-model";
|
|
1125
|
+
const provider = model.provider?.replace(/^@ai-sdk\//, "") || "ai-sdk";
|
|
1126
|
+
const maxCostPerCall = options.maxCostPerCallUSD !== void 0 ? options.maxCostPerCallUSD : 0.5;
|
|
1127
|
+
const captureOnAbort = options.captureOnAbort !== false;
|
|
1128
|
+
const scheduleFlush = () => {
|
|
1129
|
+
try {
|
|
1130
|
+
const flushPromise = meter.flush();
|
|
1131
|
+
if (typeof globalThis !== "undefined") {
|
|
1132
|
+
const g = globalThis;
|
|
1133
|
+
if (typeof g.after === "function") {
|
|
1134
|
+
g.after(() => flushPromise);
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
} catch {
|
|
1139
|
+
}
|
|
1140
|
+
};
|
|
1141
|
+
const handleUsage = (rawUsage, extraMeta) => {
|
|
1142
|
+
if (!rawUsage) return;
|
|
1143
|
+
const inputTokens = rawUsage.promptTokens ?? rawUsage.inputTokens ?? rawUsage.prompt_tokens ?? rawUsage.input_tokens ?? rawUsage.promptTokenCount ?? 0;
|
|
1144
|
+
const outputTokens = rawUsage.completionTokens ?? rawUsage.outputTokens ?? rawUsage.completion_tokens ?? rawUsage.output_tokens ?? rawUsage.candidatesTokenCount ?? 0;
|
|
1145
|
+
const reasoningTokens = rawUsage.reasoningTokens ?? rawUsage.completionTokensDetails?.reasoningTokens ?? rawUsage.outputTokenDetails?.reasoningTokens ?? rawUsage.reasoning_tokens ?? rawUsage.completion_tokens_details?.reasoning_tokens ?? rawUsage.output_token_details?.reasoning_tokens ?? rawUsage.thoughtsTokenCount ?? 0;
|
|
1146
|
+
const cachedTokens = rawUsage.promptTokensDetails?.cachedTokens ?? rawUsage.inputTokenDetails?.cachedTokens ?? rawUsage.cachedTokens ?? rawUsage.cached_tokens ?? rawUsage.prompt_tokens_details?.cached_tokens ?? rawUsage.input_token_details?.cached_tokens ?? rawUsage.cachedContentTokenCount ?? rawUsage.cache_read_input_tokens ?? 0;
|
|
1147
|
+
const cacheWriteTokens = rawUsage.cacheWriteTokens ?? rawUsage.cache_creation_input_tokens ?? rawUsage.cacheCreationTokens ?? 0;
|
|
1148
|
+
const usage = {
|
|
1149
|
+
inputTokens,
|
|
1150
|
+
outputTokens,
|
|
1151
|
+
totalTokens: inputTokens + outputTokens,
|
|
1152
|
+
reasoningTokens: reasoningTokens > 0 ? reasoningTokens : void 0,
|
|
1153
|
+
visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),
|
|
1154
|
+
cachedTokens: cachedTokens > 0 ? cachedTokens : void 0,
|
|
1155
|
+
cacheWriteTokens: cacheWriteTokens > 0 ? cacheWriteTokens : void 0
|
|
1156
|
+
};
|
|
1157
|
+
const cost = calculateUsageCost(modelId, usage, {
|
|
1158
|
+
markupMultiplier: options.pricing?.margin,
|
|
1159
|
+
minimumChargeUSD: options.pricing?.minimumChargeUSD,
|
|
1160
|
+
customRate: options.rate
|
|
1161
|
+
});
|
|
1162
|
+
if (maxCostPerCall > 0 && maxCostPerCall !== Infinity && cost.totalUSD > maxCostPerCall) {
|
|
1163
|
+
const budgetEvent = {
|
|
1164
|
+
reason: "cost_per_call_exceeded",
|
|
1165
|
+
limit: maxCostPerCall,
|
|
1166
|
+
current: cost.totalUSD,
|
|
1167
|
+
model: modelId,
|
|
1168
|
+
customerId,
|
|
1169
|
+
message: `[vibezcheck] Circuit Breaker tripped: Call cost ($${cost.totalUSD.toFixed(4)}) exceeded budget ceiling ($${maxCostPerCall.toFixed(4)}).`
|
|
1170
|
+
};
|
|
1171
|
+
if (options.onBudgetExceeded) {
|
|
1172
|
+
options.onBudgetExceeded(budgetEvent);
|
|
1173
|
+
}
|
|
1174
|
+
if (options.throwOnBudgetExceeded) {
|
|
1175
|
+
throw new VibezCircuitBreakerError(budgetEvent);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
if (options.maxTokensPerCall && usage.totalTokens > options.maxTokensPerCall) {
|
|
1179
|
+
const budgetEvent = {
|
|
1180
|
+
reason: "max_tokens_exceeded",
|
|
1181
|
+
limit: options.maxTokensPerCall,
|
|
1182
|
+
current: usage.totalTokens,
|
|
1183
|
+
model: modelId,
|
|
1184
|
+
customerId,
|
|
1185
|
+
message: `[vibezcheck] Circuit Breaker tripped: Token count (${usage.totalTokens}) exceeded maxTokensPerCall limit (${options.maxTokensPerCall}).`
|
|
1186
|
+
};
|
|
1187
|
+
if (options.onBudgetExceeded) {
|
|
1188
|
+
options.onBudgetExceeded(budgetEvent);
|
|
1189
|
+
}
|
|
1190
|
+
if (options.throwOnBudgetExceeded) {
|
|
1191
|
+
throw new VibezCircuitBreakerError(budgetEvent);
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
const mergedMetadata = {
|
|
1195
|
+
...customerMetadata,
|
|
1196
|
+
...options.metadata,
|
|
1197
|
+
...extraMeta,
|
|
1198
|
+
billingMode: options.billing?.mode || "postpaid"
|
|
1199
|
+
};
|
|
1200
|
+
const event = {
|
|
1201
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1202
|
+
model: modelId,
|
|
1203
|
+
provider,
|
|
1204
|
+
usage,
|
|
1205
|
+
cost,
|
|
1206
|
+
customerId,
|
|
1207
|
+
customerEmail,
|
|
1208
|
+
customer: customerObj,
|
|
1209
|
+
metadata: mergedMetadata
|
|
1210
|
+
};
|
|
1211
|
+
meter.recordUsage({
|
|
1212
|
+
model: modelId,
|
|
1213
|
+
provider,
|
|
1214
|
+
inputTokens,
|
|
1215
|
+
outputTokens,
|
|
1216
|
+
reasoningTokens: usage.reasoningTokens,
|
|
1217
|
+
cachedTokens: usage.cachedTokens,
|
|
1218
|
+
customerId,
|
|
1219
|
+
customer: customerObj,
|
|
1220
|
+
metadata: event.metadata
|
|
1221
|
+
});
|
|
1222
|
+
if (options.onUsage) {
|
|
1223
|
+
options.onUsage(event);
|
|
1224
|
+
}
|
|
1225
|
+
if (options.database) {
|
|
1226
|
+
const dbTarget = options.database;
|
|
1227
|
+
const executeDbWrite = async () => {
|
|
1228
|
+
try {
|
|
1229
|
+
const supabaseClient = typeof dbTarget === "object" && dbTarget !== null && typeof dbTarget.from === "function" ? dbTarget : typeof dbTarget === "object" && dbTarget !== null && typeof dbTarget.client?.from === "function" ? dbTarget.client : null;
|
|
1230
|
+
if (supabaseClient) {
|
|
1231
|
+
const tableName = dbTarget?.table || "vibez_usage";
|
|
1232
|
+
await supabaseClient.from(tableName).insert({
|
|
1233
|
+
customer_id: customerId,
|
|
1234
|
+
user_id: customerObj?.userId || customerId,
|
|
1235
|
+
model: modelId,
|
|
1236
|
+
input_tokens: usage.inputTokens,
|
|
1237
|
+
output_tokens: usage.outputTokens,
|
|
1238
|
+
total_tokens: usage.totalTokens,
|
|
1239
|
+
cached_tokens: usage.cachedTokens,
|
|
1240
|
+
reasoning_tokens: usage.reasoningTokens,
|
|
1241
|
+
cost_usd: cost.totalUSD,
|
|
1242
|
+
created_at: event.timestamp,
|
|
1243
|
+
metadata: event.metadata
|
|
1244
|
+
});
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
if (typeof dbTarget === "object" && dbTarget !== null && typeof dbTarget.save === "function") {
|
|
1248
|
+
await dbTarget.save(event);
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
if (typeof dbTarget === "function") {
|
|
1252
|
+
await dbTarget(event);
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
} catch (err) {
|
|
1256
|
+
if (process.env.NODE_ENV !== "test" && !options.silent) {
|
|
1257
|
+
console.warn(`[vibezcheck] Database record failed safely:`, err?.message || err);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
};
|
|
1261
|
+
if (typeof globalThis !== "undefined" && typeof globalThis.after === "function") {
|
|
1262
|
+
globalThis.after(() => executeDbWrite());
|
|
1263
|
+
} else {
|
|
1264
|
+
executeDbWrite().catch(() => {
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
if (options.billing?.charge && typeof options.billing.charge === "function") {
|
|
1269
|
+
const chargeFn = options.billing.charge;
|
|
1270
|
+
const executeCharge = async () => {
|
|
1271
|
+
try {
|
|
1272
|
+
await chargeFn(cost.totalUSD, event);
|
|
1273
|
+
} catch (err) {
|
|
1274
|
+
if (process.env.NODE_ENV !== "test" && !options.silent) {
|
|
1275
|
+
console.warn(`[vibezcheck] Custom charge handler failed safely:`, err?.message || err);
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
};
|
|
1279
|
+
if (typeof globalThis !== "undefined" && typeof globalThis.after === "function") {
|
|
1280
|
+
globalThis.after(() => executeCharge());
|
|
1281
|
+
} else {
|
|
1282
|
+
executeCharge().catch(() => {
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1285
|
+
} else if (options.billing?.provider && typeof options.billing.provider === "object" && typeof options.billing.provider.charge === "function") {
|
|
1286
|
+
const providerCharge = options.billing.provider.charge;
|
|
1287
|
+
const executeCharge = async () => {
|
|
1288
|
+
try {
|
|
1289
|
+
await providerCharge(cost.totalUSD, event);
|
|
1290
|
+
} catch (err) {
|
|
1291
|
+
if (process.env.NODE_ENV !== "test" && !options.silent) {
|
|
1292
|
+
console.warn(`[vibezcheck] Payment provider charge failed safely:`, err?.message || err);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
};
|
|
1296
|
+
if (typeof globalThis !== "undefined" && typeof globalThis.after === "function") {
|
|
1297
|
+
globalThis.after(() => executeCharge());
|
|
1298
|
+
} else {
|
|
1299
|
+
executeCharge().catch(() => {
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
scheduleFlush();
|
|
1304
|
+
};
|
|
1305
|
+
const handler = {
|
|
1306
|
+
get(target, prop, receiver) {
|
|
1307
|
+
const originalValue = Reflect.get(target, prop, receiver);
|
|
1308
|
+
if (prop === "doStream" && typeof originalValue === "function") {
|
|
1309
|
+
return async function(...args) {
|
|
1310
|
+
const result = await originalValue.apply(target, args);
|
|
1311
|
+
if (!result || !result.stream) {
|
|
1312
|
+
return result;
|
|
1313
|
+
}
|
|
1314
|
+
const originalStream = result.stream;
|
|
1315
|
+
let streamCompleted = false;
|
|
1316
|
+
let accumulatedChars = 0;
|
|
1317
|
+
let estimatedInputTokens = 0;
|
|
1318
|
+
try {
|
|
1319
|
+
if (args[0]?.prompt) {
|
|
1320
|
+
const str = typeof args[0].prompt === "string" ? args[0].prompt : JSON.stringify(args[0].prompt);
|
|
1321
|
+
estimatedInputTokens = Math.ceil(str.length / 4);
|
|
1322
|
+
}
|
|
1323
|
+
} catch {
|
|
1324
|
+
}
|
|
1325
|
+
const abortSignal = args[0]?.abortSignal;
|
|
1326
|
+
if (abortSignal && captureOnAbort) {
|
|
1327
|
+
abortSignal.addEventListener(
|
|
1328
|
+
"abort",
|
|
1329
|
+
() => {
|
|
1330
|
+
if (!streamCompleted && accumulatedChars > 0) {
|
|
1331
|
+
streamCompleted = true;
|
|
1332
|
+
const estimatedOutputTokens = Math.ceil(accumulatedChars / 3.8);
|
|
1333
|
+
handleUsage(
|
|
1334
|
+
{
|
|
1335
|
+
inputTokens: estimatedInputTokens,
|
|
1336
|
+
outputTokens: estimatedOutputTokens
|
|
1337
|
+
},
|
|
1338
|
+
{ aborted: true, partial: true }
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
},
|
|
1342
|
+
{ once: true }
|
|
1343
|
+
);
|
|
1344
|
+
}
|
|
1345
|
+
const transformStream = new TransformStream({
|
|
1346
|
+
transform(chunk, controller) {
|
|
1347
|
+
controller.enqueue(chunk);
|
|
1348
|
+
const delta = chunk.textDelta || chunk.text || chunk.delta;
|
|
1349
|
+
if (delta && typeof delta === "string") {
|
|
1350
|
+
accumulatedChars += delta.length;
|
|
1351
|
+
} else if (chunk.type === "reasoning" || chunk.type === "reasoning-delta") {
|
|
1352
|
+
const reasoning = chunk.reasoning || chunk.textDelta || chunk.text || chunk.delta || "";
|
|
1353
|
+
if (typeof reasoning === "string") {
|
|
1354
|
+
accumulatedChars += reasoning.length;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
const chunkUsage = chunk.usage || chunk.token_usage || chunk.usageMetadata;
|
|
1358
|
+
if (chunkUsage) {
|
|
1359
|
+
streamCompleted = true;
|
|
1360
|
+
handleUsage(chunkUsage);
|
|
1361
|
+
}
|
|
1362
|
+
},
|
|
1363
|
+
flush() {
|
|
1364
|
+
if (!streamCompleted && captureOnAbort && accumulatedChars > 0) {
|
|
1365
|
+
streamCompleted = true;
|
|
1366
|
+
const estimatedOutputTokens = Math.ceil(accumulatedChars / 3.8);
|
|
1367
|
+
handleUsage(
|
|
1368
|
+
{
|
|
1369
|
+
inputTokens: estimatedInputTokens,
|
|
1370
|
+
outputTokens: estimatedOutputTokens
|
|
1371
|
+
},
|
|
1372
|
+
{ aborted: true, partial: true }
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
});
|
|
1377
|
+
return {
|
|
1378
|
+
...result,
|
|
1379
|
+
stream: originalStream.pipeThrough(transformStream)
|
|
1380
|
+
};
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
if (prop === "doGenerate" && typeof originalValue === "function") {
|
|
1384
|
+
return async function(...args) {
|
|
1385
|
+
const result = await originalValue.apply(target, args);
|
|
1386
|
+
const usage = result?.usage || result?.tokenUsage || result?.usageMetadata;
|
|
1387
|
+
if (usage) {
|
|
1388
|
+
handleUsage(usage);
|
|
1389
|
+
}
|
|
1390
|
+
return result;
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
return originalValue;
|
|
1394
|
+
},
|
|
1395
|
+
apply(target, thisArg, argArray) {
|
|
1396
|
+
if (typeof target === "function") {
|
|
1397
|
+
return Reflect.apply(target, thisArg, argArray);
|
|
1398
|
+
}
|
|
1399
|
+
return target;
|
|
1400
|
+
},
|
|
1401
|
+
has(target, prop) {
|
|
1402
|
+
return Reflect.has(target, prop);
|
|
1403
|
+
},
|
|
1404
|
+
ownKeys(target) {
|
|
1405
|
+
return Reflect.ownKeys(target);
|
|
1406
|
+
},
|
|
1407
|
+
getPrototypeOf(target) {
|
|
1408
|
+
return Reflect.getPrototypeOf(target);
|
|
1409
|
+
}
|
|
1410
|
+
};
|
|
1411
|
+
return new Proxy(model, handler);
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
// src/ai-sdk/declarative.ts
|
|
1415
|
+
function createVibezModel(modelOrId, options = {}) {
|
|
1416
|
+
if (typeof modelOrId === "object" && modelOrId !== null) {
|
|
1417
|
+
return withBilling(modelOrId, options);
|
|
1418
|
+
}
|
|
1419
|
+
if (typeof modelOrId === "string") {
|
|
1420
|
+
const rawId = modelOrId;
|
|
1421
|
+
let providerName = "openai";
|
|
1422
|
+
let cleanModelId = rawId;
|
|
1423
|
+
if (rawId.includes("/")) {
|
|
1424
|
+
const parts = rawId.split("/");
|
|
1425
|
+
providerName = parts[0].toLowerCase();
|
|
1426
|
+
cleanModelId = parts.slice(1).join("/");
|
|
1427
|
+
} else if (rawId.startsWith("claude-")) {
|
|
1428
|
+
providerName = "anthropic";
|
|
1429
|
+
} else if (rawId.startsWith("gemini-")) {
|
|
1430
|
+
providerName = "google";
|
|
1431
|
+
} else if (rawId.startsWith("deepseek-")) {
|
|
1432
|
+
providerName = "deepseek";
|
|
1433
|
+
} else if (rawId.startsWith("grok-")) {
|
|
1434
|
+
providerName = "xai";
|
|
1435
|
+
} else if (rawId.startsWith("mistral-") || rawId.startsWith("codestral-") || rawId.startsWith("ministral-") || rawId.startsWith("open-mistral") || rawId.startsWith("open-mixtral")) {
|
|
1436
|
+
providerName = "mistral";
|
|
1437
|
+
} else if (rawId.startsWith("llama-") || rawId.startsWith("mixtral-") || rawId.startsWith("gemma") || rawId.startsWith("qwen-")) {
|
|
1438
|
+
providerName = "groq";
|
|
1439
|
+
} else if (rawId.startsWith("command-")) {
|
|
1440
|
+
providerName = "cohere";
|
|
1441
|
+
}
|
|
1442
|
+
const apiKey = options.apiKey || process.env.AI_GATEWAY_API_KEY || (providerName === "anthropic" ? process.env.ANTHROPIC_API_KEY : void 0) || (providerName === "google" ? process.env.GOOGLE_GENERATIVE_AI_API_KEY : void 0) || (providerName === "mistral" ? process.env.MISTRAL_API_KEY : void 0) || (providerName === "groq" ? process.env.GROQ_API_KEY : void 0) || (providerName === "deepseek" ? process.env.DEEPSEEK_API_KEY : void 0) || (providerName === "xai" ? process.env.XAI_API_KEY : void 0) || (providerName === "cohere" ? process.env.COHERE_API_KEY : void 0) || process.env.OPENAI_API_KEY;
|
|
1443
|
+
const baseURL = options.baseURL || process.env.AI_GATEWAY_BASE_URL || (providerName === "openai" ? "https://api.openai.com/v1" : void 0);
|
|
1444
|
+
let baseModelInstance = null;
|
|
1445
|
+
try {
|
|
1446
|
+
if (providerName === "openai" || providerName === "gateway" || !providerName) {
|
|
1447
|
+
const mod = require("@ai-sdk/openai");
|
|
1448
|
+
const factory = mod.createOpenAI || mod.openai || mod.default?.createOpenAI || mod.default?.openai;
|
|
1449
|
+
if (typeof factory === "function") {
|
|
1450
|
+
if (mod.createOpenAI) {
|
|
1451
|
+
const provider = factory({ apiKey, baseURL });
|
|
1452
|
+
baseModelInstance = provider(cleanModelId);
|
|
1453
|
+
} else {
|
|
1454
|
+
baseModelInstance = factory(cleanModelId);
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
} else if (providerName === "anthropic") {
|
|
1458
|
+
const mod = require("@ai-sdk/anthropic");
|
|
1459
|
+
const factory = mod.createAnthropic || mod.anthropic || mod.default?.createAnthropic || mod.default?.anthropic;
|
|
1460
|
+
if (typeof factory === "function") {
|
|
1461
|
+
if (mod.createAnthropic) {
|
|
1462
|
+
const provider = factory({ apiKey, baseURL });
|
|
1463
|
+
baseModelInstance = provider(cleanModelId);
|
|
1464
|
+
} else {
|
|
1465
|
+
baseModelInstance = factory(cleanModelId);
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
} else if (providerName === "google") {
|
|
1469
|
+
const mod = require("@ai-sdk/google");
|
|
1470
|
+
const factory = mod.createGoogleGenerativeAI || mod.google || mod.default?.createGoogleGenerativeAI || mod.default?.google;
|
|
1471
|
+
if (typeof factory === "function") {
|
|
1472
|
+
if (mod.createGoogleGenerativeAI) {
|
|
1473
|
+
const provider = factory({ apiKey, baseURL });
|
|
1474
|
+
baseModelInstance = provider(cleanModelId);
|
|
1475
|
+
} else {
|
|
1476
|
+
baseModelInstance = factory(cleanModelId);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
} else if (providerName === "mistral") {
|
|
1480
|
+
const mod = require("@ai-sdk/mistral");
|
|
1481
|
+
const factory = mod.createMistral || mod.mistral || mod.default?.createMistral || mod.default?.mistral;
|
|
1482
|
+
if (typeof factory === "function") {
|
|
1483
|
+
baseModelInstance = mod.createMistral ? factory({ apiKey, baseURL })(cleanModelId) : factory(cleanModelId);
|
|
1484
|
+
}
|
|
1485
|
+
} else if (providerName === "groq") {
|
|
1486
|
+
const mod = require("@ai-sdk/groq");
|
|
1487
|
+
const factory = mod.createGroq || mod.groq || mod.default?.createGroq || mod.default?.groq;
|
|
1488
|
+
if (typeof factory === "function") {
|
|
1489
|
+
baseModelInstance = mod.createGroq ? factory({ apiKey, baseURL })(cleanModelId) : factory(cleanModelId);
|
|
1490
|
+
}
|
|
1491
|
+
} else if (providerName === "deepseek") {
|
|
1492
|
+
const mod = require("@ai-sdk/deepseek");
|
|
1493
|
+
const factory = mod.createDeepSeek || mod.deepseek || mod.default?.createDeepSeek || mod.default?.deepseek;
|
|
1494
|
+
if (typeof factory === "function") {
|
|
1495
|
+
baseModelInstance = mod.createDeepSeek ? factory({ apiKey, baseURL })(cleanModelId) : factory(cleanModelId);
|
|
1496
|
+
}
|
|
1497
|
+
} else if (providerName === "xai") {
|
|
1498
|
+
const mod = require("@ai-sdk/xai");
|
|
1499
|
+
const factory = mod.createXai || mod.xai || mod.default?.createXai || mod.default?.xai;
|
|
1500
|
+
if (typeof factory === "function") {
|
|
1501
|
+
baseModelInstance = mod.createXai ? factory({ apiKey, baseURL })(cleanModelId) : factory(cleanModelId);
|
|
1502
|
+
}
|
|
1503
|
+
} else if (providerName === "cohere") {
|
|
1504
|
+
const mod = require("@ai-sdk/cohere");
|
|
1505
|
+
const factory = mod.createCohere || mod.cohere || mod.default?.createCohere || mod.default?.cohere;
|
|
1506
|
+
if (typeof factory === "function") {
|
|
1507
|
+
baseModelInstance = mod.createCohere ? factory({ apiKey, baseURL })(cleanModelId) : factory(cleanModelId);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
} catch {
|
|
1511
|
+
baseModelInstance = {
|
|
1512
|
+
specificationVersion: "v2",
|
|
1513
|
+
provider: providerName,
|
|
1514
|
+
modelId: cleanModelId
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
if (!baseModelInstance) {
|
|
1518
|
+
baseModelInstance = {
|
|
1519
|
+
specificationVersion: "v2",
|
|
1520
|
+
provider: providerName,
|
|
1521
|
+
modelId: cleanModelId
|
|
1522
|
+
};
|
|
1523
|
+
}
|
|
1524
|
+
return withBilling(baseModelInstance, options);
|
|
1525
|
+
}
|
|
1526
|
+
return modelOrId;
|
|
1527
|
+
}
|
|
1528
|
+
function createVibezSession(sessionOptions = {}) {
|
|
1529
|
+
const meter = createMeter({
|
|
1530
|
+
apiKey: sessionOptions.stripeApiKey
|
|
1531
|
+
});
|
|
1532
|
+
const customerId = typeof sessionOptions.customer === "string" ? sessionOptions.customer : sessionOptions.customer?.id;
|
|
1533
|
+
return {
|
|
1534
|
+
meter,
|
|
1535
|
+
model: (modelOrId, callOptions = {}) => {
|
|
1536
|
+
return createVibezModel(modelOrId, {
|
|
1537
|
+
customer: sessionOptions.customer,
|
|
1538
|
+
pricing: sessionOptions.pricing,
|
|
1539
|
+
billing: sessionOptions.billing,
|
|
1540
|
+
meter,
|
|
1541
|
+
metadata: {
|
|
1542
|
+
...sessionOptions.metadata,
|
|
1543
|
+
...callOptions.metadata
|
|
1544
|
+
},
|
|
1545
|
+
...callOptions
|
|
1546
|
+
});
|
|
1547
|
+
},
|
|
1548
|
+
trackTool: async (name, { costUSD, metadata }) => {
|
|
1549
|
+
const event = {
|
|
1550
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1551
|
+
model: `tool:${name}`,
|
|
1552
|
+
provider: "tool",
|
|
1553
|
+
usage: {
|
|
1554
|
+
inputTokens: 0,
|
|
1555
|
+
outputTokens: 0,
|
|
1556
|
+
totalTokens: 0
|
|
1557
|
+
},
|
|
1558
|
+
cost: {
|
|
1559
|
+
inputCostUSD: 0,
|
|
1560
|
+
outputCostUSD: costUSD,
|
|
1561
|
+
totalUSD: costUSD,
|
|
1562
|
+
currency: "USD"
|
|
1563
|
+
},
|
|
1564
|
+
customerId,
|
|
1565
|
+
metadata: {
|
|
1566
|
+
...sessionOptions.metadata,
|
|
1567
|
+
...metadata,
|
|
1568
|
+
tool: name
|
|
1569
|
+
}
|
|
1570
|
+
};
|
|
1571
|
+
meter.recordUsage({
|
|
1572
|
+
model: `tool:${name}`,
|
|
1573
|
+
provider: "tool",
|
|
1574
|
+
inputTokens: 0,
|
|
1575
|
+
outputTokens: 0,
|
|
1576
|
+
customerId,
|
|
1577
|
+
metadata: event.metadata
|
|
1578
|
+
});
|
|
1579
|
+
await meter.flush();
|
|
1580
|
+
}
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1583
|
+
var vibezcheck = Object.assign(createVibezModel, {
|
|
1584
|
+
session: createVibezSession
|
|
1585
|
+
});
|
|
1586
|
+
|
|
1587
|
+
// src/compat/stripe-provider.ts
|
|
1588
|
+
function createStripe(config = {}) {
|
|
1589
|
+
const apiKey = config.apiKey || (typeof process !== "undefined" ? process.env?.STRIPE_API_KEY || process.env?.STRIPE_SECRET_KEY : void 0);
|
|
1590
|
+
const provider = function(modelId, settings = {}) {
|
|
1591
|
+
const customerId = settings.customerId || config.customerId || "anonymous";
|
|
1592
|
+
const options = {
|
|
1593
|
+
customer: customerId,
|
|
1594
|
+
stripeApiKey: apiKey
|
|
1595
|
+
};
|
|
1596
|
+
if (settings.model && typeof settings.model === "object") {
|
|
1597
|
+
return withBilling(settings.model, options);
|
|
1598
|
+
}
|
|
1599
|
+
return createVibezModel(modelId, {
|
|
1600
|
+
...settings,
|
|
1601
|
+
customer: customerId,
|
|
1602
|
+
stripeApiKey: apiKey,
|
|
1603
|
+
baseURL: config.baseURL
|
|
1604
|
+
});
|
|
1605
|
+
};
|
|
1606
|
+
provider.languageModel = provider;
|
|
1607
|
+
provider.specificationVersion = "v3";
|
|
1608
|
+
return provider;
|
|
1609
|
+
}
|
|
1610
|
+
var stripe = createStripe();
|
|
1611
|
+
var createStripeV3 = createStripe;
|
|
1612
|
+
var stripeV3 = stripe;
|
|
1613
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1614
|
+
0 && (module.exports = {
|
|
1615
|
+
createStripe,
|
|
1616
|
+
createStripeV3,
|
|
1617
|
+
stripe,
|
|
1618
|
+
stripeV3
|
|
1619
|
+
});
|
|
1620
|
+
//# sourceMappingURL=stripe-provider.js.map
|