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.
Files changed (80) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +249 -273
  3. package/bin/vibezcheck.js +4 -4
  4. package/dist/ai-sdk/index.d.mts +28 -59
  5. package/dist/ai-sdk/index.d.ts +28 -59
  6. package/dist/ai-sdk/index.js +307 -69
  7. package/dist/ai-sdk/index.js.map +1 -1
  8. package/dist/ai-sdk/index.mjs +307 -69
  9. package/dist/ai-sdk/index.mjs.map +1 -1
  10. package/dist/ai-sdk/middleware.d.mts +15 -0
  11. package/dist/ai-sdk/middleware.d.ts +15 -0
  12. package/dist/ai-sdk/middleware.js +1433 -0
  13. package/dist/ai-sdk/middleware.js.map +1 -0
  14. package/dist/ai-sdk/middleware.mjs +1396 -0
  15. package/dist/ai-sdk/middleware.mjs.map +1 -0
  16. package/dist/auth/index.js.map +1 -1
  17. package/dist/auth/index.mjs.map +1 -1
  18. package/dist/billing/index.d.mts +90 -1
  19. package/dist/billing/index.d.ts +90 -1
  20. package/dist/billing/index.js +1542 -2
  21. package/dist/billing/index.js.map +1 -1
  22. package/dist/billing/index.mjs +1537 -1
  23. package/dist/billing/index.mjs.map +1 -1
  24. package/dist/cli/index.js +59 -7
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/cli/index.mjs +59 -7
  27. package/dist/cli/index.mjs.map +1 -1
  28. package/dist/{client-ynfWcHX6.d.ts → client-BORmJy8s.d.ts} +1 -1
  29. package/dist/{client-w_hWhQ6g.d.mts → client-CbuXmoXz.d.mts} +1 -1
  30. package/dist/compat/stripe-meter.d.mts +21 -0
  31. package/dist/compat/stripe-meter.d.ts +21 -0
  32. package/dist/compat/stripe-meter.js +1451 -0
  33. package/dist/compat/stripe-meter.js.map +1 -0
  34. package/dist/compat/stripe-meter.mjs +1414 -0
  35. package/dist/compat/stripe-meter.mjs.map +1 -0
  36. package/dist/compat/stripe-provider.d.mts +34 -0
  37. package/dist/compat/stripe-provider.d.ts +34 -0
  38. package/dist/compat/stripe-provider.js +1620 -0
  39. package/dist/compat/stripe-provider.js.map +1 -0
  40. package/dist/compat/stripe-provider.mjs +1587 -0
  41. package/dist/compat/stripe-provider.mjs.map +1 -0
  42. package/dist/compat/token-meter.d.mts +28 -0
  43. package/dist/compat/token-meter.d.ts +28 -0
  44. package/dist/compat/token-meter.js +1320 -0
  45. package/dist/compat/token-meter.js.map +1 -0
  46. package/dist/compat/token-meter.mjs +1283 -0
  47. package/dist/compat/token-meter.mjs.map +1 -0
  48. package/dist/customers/index.d.mts +1 -1
  49. package/dist/customers/index.d.ts +1 -1
  50. package/dist/customers/index.js.map +1 -1
  51. package/dist/customers/index.mjs.map +1 -1
  52. package/dist/index.d.mts +25 -11
  53. package/dist/index.d.ts +25 -11
  54. package/dist/index.js +810 -72
  55. package/dist/index.js.map +1 -1
  56. package/dist/index.mjs +798 -72
  57. package/dist/index.mjs.map +1 -1
  58. package/dist/meter/index.d.mts +2 -2
  59. package/dist/meter/index.d.ts +2 -2
  60. package/dist/meter/index.js +176 -42
  61. package/dist/meter/index.js.map +1 -1
  62. package/dist/meter/index.mjs +176 -42
  63. package/dist/meter/index.mjs.map +1 -1
  64. package/dist/pricing/index.d.mts +15 -4
  65. package/dist/pricing/index.d.ts +15 -4
  66. package/dist/pricing/index.js +165 -29
  67. package/dist/pricing/index.js.map +1 -1
  68. package/dist/pricing/index.mjs +164 -29
  69. package/dist/pricing/index.mjs.map +1 -1
  70. package/dist/react/index.d.mts +46 -2
  71. package/dist/react/index.d.ts +46 -2
  72. package/dist/react/index.js +471 -29
  73. package/dist/react/index.js.map +1 -1
  74. package/dist/react/index.mjs +469 -29
  75. package/dist/react/index.mjs.map +1 -1
  76. package/dist/{types-Mozk4-Mr.d.mts → types-6P71CXAD.d.mts} +16 -6
  77. package/dist/{types-Mozk4-Mr.d.ts → types-6P71CXAD.d.ts} +16 -6
  78. package/dist/with-billing-Bj6Ya_Iy.d.ts +49 -0
  79. package/dist/with-billing-DndWGxL8.d.mts +49 -0
  80. package/package.json +35 -10
@@ -21,6 +21,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var react_exports = {};
22
22
  __export(react_exports, {
23
23
  VibezBillingModal: () => VibezBillingModal,
24
+ VibezCheck: () => VibezCheck,
25
+ VibezPill: () => VibezPill,
24
26
  VibezReceipt: () => VibezReceipt,
25
27
  VibezSessionBadge: () => VibezSessionBadge,
26
28
  VibezSessionContext: () => VibezSessionContext,
@@ -37,7 +39,7 @@ var import_react = require("react");
37
39
 
38
40
  // src/pricing/table.ts
39
41
  var MODEL_PRICING_TABLE = {
40
- // --- OpenAI ---
42
+ // --- OpenAI (Modern & Reasoning) ---
41
43
  "gpt-5.6-sol": { inputPer1M: 4, outputPer1M: 20, cachedInputPer1M: 0.4 },
42
44
  "gpt-5.6-terra": { inputPer1M: 2, outputPer1M: 12, cachedInputPer1M: 0.2 },
43
45
  "gpt-5.6-luna": { inputPer1M: 0.2, outputPer1M: 1.2, cachedInputPer1M: 0.02 },
@@ -49,11 +51,22 @@ var MODEL_PRICING_TABLE = {
49
51
  "o3-mini": { inputPer1M: 1.1, outputPer1M: 4.4, cachedInputPer1M: 0.55 },
50
52
  "gpt-4o": { inputPer1M: 2.5, outputPer1M: 10, cachedInputPer1M: 1.25 },
51
53
  "gpt-4o-mini": { inputPer1M: 0.15, outputPer1M: 0.6, cachedInputPer1M: 0.075 },
54
+ "gpt-4.5": { inputPer1M: 75, outputPer1M: 150, cachedInputPer1M: 37.5 },
55
+ "gpt-4.5-preview": { inputPer1M: 75, outputPer1M: 150, cachedInputPer1M: 37.5 },
56
+ "chatgpt-4o-latest": { inputPer1M: 5, outputPer1M: 15 },
52
57
  "gpt-4.1": { inputPer1M: 2, outputPer1M: 8, cachedInputPer1M: 1 },
53
58
  "gpt-4.1-nano": { inputPer1M: 0.1, outputPer1M: 0.4, cachedInputPer1M: 0.05 },
59
+ // --- OpenAI (Legacy & Backward Compatibility) ---
60
+ "gpt-4-turbo": { inputPer1M: 10, outputPer1M: 30, cachedInputPer1M: 5 },
61
+ "gpt-4-turbo-preview": { inputPer1M: 10, outputPer1M: 30, cachedInputPer1M: 5 },
62
+ "gpt-4": { inputPer1M: 30, outputPer1M: 60 },
63
+ "gpt-4-32k": { inputPer1M: 60, outputPer1M: 120 },
64
+ "gpt-3.5-turbo": { inputPer1M: 0.5, outputPer1M: 1.5 },
65
+ "gpt-3.5-turbo-16k": { inputPer1M: 3, outputPer1M: 4 },
54
66
  "text-embedding-3-small": { inputPer1M: 0.02, outputPer1M: 0 },
55
67
  "text-embedding-3-large": { inputPer1M: 0.13, outputPer1M: 0 },
56
- // --- Anthropic ---
68
+ "text-embedding-ada-002": { inputPer1M: 0.1, outputPer1M: 0 },
69
+ // --- Anthropic (Modern & Extended Thinking) ---
57
70
  "claude-3-7-sonnet": { inputPer1M: 0.59, outputPer1M: 2.93, cachedInputPer1M: 0.3 },
58
71
  "claude-sonnet-5": { inputPer1M: 2, outputPer1M: 10, cachedInputPer1M: 0.3 },
59
72
  "claude-3-5-sonnet": { inputPer1M: 3, outputPer1M: 15, cachedInputPer1M: 0.3 },
@@ -61,48 +74,145 @@ var MODEL_PRICING_TABLE = {
61
74
  "haiku-4.5": { inputPer1M: 1, outputPer1M: 5, cachedInputPer1M: 0.1 },
62
75
  "claude-opus-5": { inputPer1M: 5, outputPer1M: 25, cachedInputPer1M: 1.5 },
63
76
  "claude-3-opus": { inputPer1M: 15, outputPer1M: 75, cachedInputPer1M: 1.5 },
64
- // --- Google Gemini ---
77
+ // --- Anthropic (Legacy & Backward Compatibility) ---
78
+ "claude-3-sonnet": { inputPer1M: 3, outputPer1M: 15, cachedInputPer1M: 0.3 },
79
+ "claude-3-haiku": { inputPer1M: 0.25, outputPer1M: 1.25, cachedInputPer1M: 0.025 },
80
+ "claude-2.1": { inputPer1M: 8, outputPer1M: 24 },
81
+ "claude-2.0": { inputPer1M: 8, outputPer1M: 24 },
82
+ "claude-instant-1.2": { inputPer1M: 1.63, outputPer1M: 5.51 },
83
+ // --- Google Gemini (Modern & Thoughts) ---
65
84
  "gemini-3.7-flash": { inputPer1M: 0.75, outputPer1M: 3.75, cachedInputPer1M: 0.18 },
66
85
  "gemini-3.1-pro": { inputPer1M: 2, outputPer1M: 12, cachedInputPer1M: 0.5 },
67
86
  "gemini-3.5-flash": { inputPer1M: 1.5, outputPer1M: 9, cachedInputPer1M: 0.38 },
68
87
  "gemini-3.1-flash-lite": { inputPer1M: 0.25, outputPer1M: 1.5, cachedInputPer1M: 0.06 },
88
+ "gemini-2.5-pro": { inputPer1M: 1.25, outputPer1M: 5, cachedInputPer1M: 0.3125 },
89
+ "gemini-2.5-flash": { inputPer1M: 0.15, outputPer1M: 0.6, cachedInputPer1M: 0.0375 },
69
90
  "gemini-2.0-flash": { inputPer1M: 0.1, outputPer1M: 0.4, cachedInputPer1M: 0.025 },
91
+ "gemini-2.0-flash-lite": { inputPer1M: 0.075, outputPer1M: 0.3, cachedInputPer1M: 0.01875 },
92
+ "gemini-2.0-pro": { inputPer1M: 1.25, outputPer1M: 5, cachedInputPer1M: 0.3125 },
93
+ // --- Google Gemini (Legacy & Backward Compatibility) ---
70
94
  "gemini-1.5-pro": { inputPer1M: 1.25, outputPer1M: 5, cachedInputPer1M: 0.3125 },
71
95
  "gemini-1.5-flash": { inputPer1M: 0.075, outputPer1M: 0.3, cachedInputPer1M: 0.01875 },
96
+ "gemini-1.5-flash-8b": { inputPer1M: 0.0375, outputPer1M: 0.15, cachedInputPer1M: 9375e-6 },
97
+ "gemini-1.0-pro": { inputPer1M: 0.5, outputPer1M: 1.5 },
72
98
  // --- xAI Grok ---
73
99
  "grok-4.6": { inputPer1M: 3, outputPer1M: 15 },
100
+ "grok-3": { inputPer1M: 3, outputPer1M: 15 },
101
+ "grok-3-mini": { inputPer1M: 0.3, outputPer1M: 1.5 },
74
102
  "grok-2": { inputPer1M: 2, outputPer1M: 10 },
75
103
  "grok-2-vision": { inputPer1M: 2, outputPer1M: 10 },
76
104
  "grok-beta": { inputPer1M: 5, outputPer1M: 15 },
77
105
  // --- Mistral ---
78
106
  "mistral-large-3": { inputPer1M: 2, outputPer1M: 6 },
79
107
  "mistral-large-latest": { inputPer1M: 2, outputPer1M: 6 },
108
+ "mistral-large-2411": { inputPer1M: 2, outputPer1M: 6 },
80
109
  "codestral-latest": { inputPer1M: 0.3, outputPer1M: 0.9 },
110
+ "mistral-medium-latest": { inputPer1M: 2.7, outputPer1M: 8.1 },
81
111
  "mistral-small-latest": { inputPer1M: 0.2, outputPer1M: 0.6 },
82
112
  "ministral-8b-latest": { inputPer1M: 0.1, outputPer1M: 0.1 },
83
- // --- Groq LPUs ---
113
+ "ministral-3b-latest": { inputPer1M: 0.04, outputPer1M: 0.04 },
114
+ "open-mistral-7b": { inputPer1M: 0.2, outputPer1M: 0.2 },
115
+ "open-mixtral-8x7b": { inputPer1M: 0.7, outputPer1M: 0.7 },
116
+ "open-mixtral-8x22b": { inputPer1M: 2, outputPer1M: 6 },
117
+ // --- Groq & Meta Llama LPUs ---
84
118
  "llama-3.3-70b-versatile": { inputPer1M: 0.59, outputPer1M: 0.79 },
119
+ "llama-3.1-405b": { inputPer1M: 3, outputPer1M: 3 },
120
+ "llama-3.1-70b-versatile": { inputPer1M: 0.59, outputPer1M: 0.79 },
85
121
  "llama-3.1-8b-instant": { inputPer1M: 0.05, outputPer1M: 0.08 },
122
+ "llama-3.2-1b-preview": { inputPer1M: 0.04, outputPer1M: 0.04 },
123
+ "llama-3.2-3b-preview": { inputPer1M: 0.06, outputPer1M: 0.06 },
124
+ "llama-3.2-11b-vision": { inputPer1M: 0.18, outputPer1M: 0.18 },
125
+ "llama-3.2-90b-vision": { inputPer1M: 0.9, outputPer1M: 0.9 },
86
126
  "deepseek-r1-distill-llama-70b": { inputPer1M: 0.75, outputPer1M: 0.99 },
127
+ "deepseek-r1-distill-qwen-32b": { inputPer1M: 0.49, outputPer1M: 0.49 },
87
128
  "qwen-2.5-32b": { inputPer1M: 0.29, outputPer1M: 0.39 },
129
+ "qwen-2.5-72b": { inputPer1M: 0.35, outputPer1M: 0.4 },
130
+ "mixtral-8x7b-32768": { inputPer1M: 0.24, outputPer1M: 0.24 },
131
+ "gemma2-9b-it": { inputPer1M: 0.2, outputPer1M: 0.2 },
88
132
  // --- DeepSeek ---
89
133
  "deepseek-v4-pro": { inputPer1M: 0.66, outputPer1M: 1.98, cachedInputPer1M: 0.15 },
90
134
  "deepseek-v4-flash": { inputPer1M: 0.22, outputPer1M: 0.66, cachedInputPer1M: 0.05 },
91
- "deepseek-chat": { inputPer1M: 0.22, outputPer1M: 0.66, cachedInputPer1M: 0.05 },
92
- "deepseek-reasoner": { inputPer1M: 0.66, outputPer1M: 1.98, cachedInputPer1M: 0.15 },
135
+ "deepseek-v3": { inputPer1M: 0.14, outputPer1M: 0.28, cachedInputPer1M: 0.014 },
136
+ "deepseek-chat": { inputPer1M: 0.14, outputPer1M: 0.28, cachedInputPer1M: 0.014 },
137
+ "deepseek-r1": { inputPer1M: 0.55, outputPer1M: 2.19, cachedInputPer1M: 0.14 },
138
+ "deepseek-reasoner": { inputPer1M: 0.55, outputPer1M: 2.19, cachedInputPer1M: 0.14 },
93
139
  // --- Cohere ---
94
140
  "command-r-plus": { inputPer1M: 2.5, outputPer1M: 10 },
95
- "command-r": { inputPer1M: 0.15, outputPer1M: 0.6 }
141
+ "command-r": { inputPer1M: 0.15, outputPer1M: 0.6 },
142
+ "command": { inputPer1M: 1, outputPer1M: 2 },
143
+ "command-light": { inputPer1M: 0.3, outputPer1M: 0.6 },
144
+ "embed-english-v3.0": { inputPer1M: 0.1, outputPer1M: 0 },
145
+ // --- Perplexity ---
146
+ "sonar": { inputPer1M: 1, outputPer1M: 1 },
147
+ "sonar-pro": { inputPer1M: 3, outputPer1M: 15 },
148
+ "sonar-reasoning": { inputPer1M: 1, outputPer1M: 5 },
149
+ "sonar-reasoning-pro": { inputPer1M: 2, outputPer1M: 8 }
150
+ };
151
+ var MODEL_ALIASES = {
152
+ // OpenAI Shorthands & Aliases
153
+ "gpt4": "gpt-4",
154
+ "gpt4o": "gpt-4o",
155
+ "gpt-4-preview": "gpt-4-turbo",
156
+ "gpt-4-0125-preview": "gpt-4-turbo",
157
+ "gpt-4-1106-preview": "gpt-4-turbo",
158
+ "gpt-3.5": "gpt-3.5-turbo",
159
+ "gpt-3.5-turbo-0125": "gpt-3.5-turbo",
160
+ "gpt-3.5-turbo-1106": "gpt-3.5-turbo",
161
+ "gpt-3.5-turbo-16k-0613": "gpt-3.5-turbo-16k",
162
+ // Anthropic Shorthands
163
+ "sonnet": "claude-3-5-sonnet",
164
+ "sonnet-3.7": "claude-3-7-sonnet",
165
+ "sonnet-3.5": "claude-3-5-sonnet",
166
+ "haiku": "claude-3-5-haiku",
167
+ "haiku-3.5": "claude-3-5-haiku",
168
+ "opus": "claude-3-opus",
169
+ "claude-2": "claude-2.0",
170
+ "claude-instant": "claude-instant-1.2",
171
+ // DeepSeek Shorthands
172
+ "r1": "deepseek-r1",
173
+ "v3": "deepseek-v3",
174
+ // Gemini Shorthands
175
+ "flash": "gemini-2.0-flash",
176
+ "pro": "gemini-1.5-pro",
177
+ // Meta / Groq Shorthands
178
+ "llama-3.3-70b": "llama-3.3-70b-versatile",
179
+ "llama-3.1-70b": "llama-3.1-70b-versatile",
180
+ "llama-3.1-8b": "llama-3.1-8b-instant",
181
+ "llama-3-70b": "llama-3.1-70b-versatile",
182
+ "llama-3-8b": "llama-3.1-8b-instant",
183
+ // Mistral Shorthands
184
+ "codestral": "codestral-latest",
185
+ "mistral-large": "mistral-large-latest",
186
+ "mistral-small": "mistral-small-latest"
96
187
  };
97
188
  var customPricingRegistry = {};
98
189
  function normalizeModelKey(rawModel) {
99
190
  if (!rawModel) return "unknown";
100
191
  let model = rawModel.toLowerCase().trim();
192
+ model = model.replace(/^[a-z0-9_-]+\.(anthropic|meta|amazon|cohere|mistral|ai21)\./i, "");
193
+ model = model.replace(/^(anthropic|meta|amazon|cohere|mistral|ai21)\./i, "");
194
+ model = model.replace(/-v\d+(:\d+)?$/, "");
195
+ model = model.replace(/:\d+$/, "");
101
196
  if (model.includes("/")) {
102
- model = model.split("/")[1] || model;
197
+ model = model.split("/").slice(1).join("/");
103
198
  }
199
+ model = model.replace(/:(latest|free|beta)$/, "");
104
200
  model = model.replace(/-\d{8}$/, "");
105
201
  model = model.replace(/-\d{4}-\d{2}-\d{2}$/, "");
202
+ model = model.replace(/llama(\d+)-(\d+)-/g, "llama-$1.$2-");
203
+ model = model.replace(/llama(\d+)\.(\d+)-/g, "llama-$1.$2-");
204
+ if (MODEL_ALIASES[model]) {
205
+ return MODEL_ALIASES[model];
206
+ }
207
+ if (!MODEL_PRICING_TABLE[model]) {
208
+ const withoutInstruct = model.replace(/-(instruct|chat|preview)$/, "");
209
+ if (MODEL_PRICING_TABLE[withoutInstruct]) {
210
+ return withoutInstruct;
211
+ }
212
+ if (MODEL_ALIASES[withoutInstruct]) {
213
+ return MODEL_ALIASES[withoutInstruct];
214
+ }
215
+ }
106
216
  return model;
107
217
  }
108
218
  function getModelPricing(modelName) {
@@ -119,6 +229,10 @@ function getModelPricing(modelName) {
119
229
  if (MODEL_PRICING_TABLE[modelName]) {
120
230
  return MODEL_PRICING_TABLE[modelName];
121
231
  }
232
+ const alias = MODEL_ALIASES[modelName.toLowerCase().trim()];
233
+ if (alias && MODEL_PRICING_TABLE[alias]) {
234
+ return MODEL_PRICING_TABLE[alias];
235
+ }
122
236
  return {
123
237
  inputPer1M: 1,
124
238
  outputPer1M: 3,
@@ -141,35 +255,57 @@ function calculateCost(params) {
141
255
  } else {
142
256
  rates = getModelPricing(params.model);
143
257
  }
144
- const inputTokens = params.inputTokens ?? 0;
145
- const outputTokens = params.outputTokens ?? 0;
146
- const reasoningTokens = params.reasoningTokens ?? 0;
147
- const cachedTokens = params.cachedTokens ?? 0;
148
- const regularInputTokens = Math.max(0, inputTokens - cachedTokens);
149
- const regularInputCost = regularInputTokens / 1e6 * rates.inputPer1M;
150
- const cachedRate = rates.cachedInputPer1M ?? rates.inputPer1M * 0.15;
151
- const cachedInputCost = cachedTokens / 1e6 * cachedRate;
152
- const inputCostUSD = regularInputCost + cachedInputCost;
153
- const outputCostUSD = outputTokens / 1e6 * rates.outputPer1M;
154
- const reasoningRate = rates.reasoningPer1M ?? rates.outputPer1M;
155
- const reasoningCostUSD = reasoningTokens / 1e6 * reasoningRate;
156
- const standardCacheCost = cachedTokens / 1e6 * rates.inputPer1M;
157
- const cachedDiscountUSD = Math.max(0, standardCacheCost - cachedInputCost);
158
- let totalUSD = inputCostUSD + outputCostUSD;
258
+ const inputTokens = BigInt(Math.max(0, params.inputTokens ?? 0));
259
+ const outputTokens = BigInt(Math.max(0, params.outputTokens ?? 0));
260
+ const reasoningTokens = BigInt(Math.max(0, params.reasoningTokens ?? 0));
261
+ const cachedTokens = BigInt(Math.max(0, params.cachedTokens ?? 0));
262
+ const regularInputTokens = inputTokens > cachedTokens ? inputTokens - cachedTokens : 0n;
263
+ const rateInputNano = BigInt(Math.round(rates.inputPer1M * 1e3));
264
+ const cachedPer1M = rates.cachedInputPer1M ?? rates.inputPer1M * 0.15;
265
+ const rateCachedNano = BigInt(Math.round(cachedPer1M * 1e3));
266
+ const rateOutputNano = BigInt(Math.round(rates.outputPer1M * 1e3));
267
+ const reasoningPer1M = rates.reasoningPer1M ?? rates.outputPer1M;
268
+ const rateReasoningNano = BigInt(Math.round(reasoningPer1M * 1e3));
269
+ const regularInputCostNano = regularInputTokens * rateInputNano;
270
+ const cachedInputCostNano = cachedTokens * rateCachedNano;
271
+ const inputCostNano = regularInputCostNano + cachedInputCostNano;
272
+ const outputCostNano = outputTokens * rateOutputNano;
273
+ const reasoningCostNano = reasoningTokens * rateReasoningNano;
274
+ const standardCacheCostNano = cachedTokens * rateInputNano;
275
+ const cachedDiscountNano = standardCacheCostNano > cachedInputCostNano ? standardCacheCostNano - cachedInputCostNano : 0n;
276
+ const wholesaleNano = inputCostNano + outputCostNano;
159
277
  const markup = params.markupMultiplier ?? 1;
160
- let retailUSD = void 0;
278
+ let billedNano = wholesaleNano;
279
+ let hasRetail = false;
161
280
  if (markup !== 1 || params.minimumChargeUSD !== void 0) {
162
- retailUSD = totalUSD * markup;
163
- if (params.minimumChargeUSD !== void 0 && retailUSD < params.minimumChargeUSD) {
164
- retailUSD = params.minimumChargeUSD;
281
+ hasRetail = true;
282
+ const markupMultiplierNano = BigInt(Math.round(markup * 1e3));
283
+ billedNano = wholesaleNano * markupMultiplierNano / 1000n;
284
+ if (params.minimumChargeUSD !== void 0 && params.minimumChargeUSD > 0) {
285
+ const minChargeNano = BigInt(Math.round(params.minimumChargeUSD * 1e9));
286
+ if (billedNano < minChargeNano) {
287
+ billedNano = minChargeNano;
288
+ }
165
289
  }
166
290
  }
291
+ const inputCostUSD = Number(inputCostNano) / 1e9;
292
+ const outputCostUSD = Number(outputCostNano) / 1e9;
293
+ const reasoningCostUSD = Number(reasoningCostNano) / 1e9;
294
+ const cachedDiscountUSD = Number(cachedDiscountNano) / 1e9;
295
+ const totalUSD = Number(wholesaleNano) / 1e9;
296
+ const wholesaleTotalUSD = totalUSD;
297
+ const billedUSD = Number(billedNano) / 1e9;
298
+ const profitUSD = Math.max(0, billedUSD - wholesaleTotalUSD);
299
+ const retailUSD = hasRetail ? billedUSD : void 0;
167
300
  return {
168
301
  inputCostUSD: Number(inputCostUSD.toFixed(8)),
169
302
  outputCostUSD: Number(outputCostUSD.toFixed(8)),
170
- reasoningCostUSD: reasoningTokens > 0 ? Number(reasoningCostUSD.toFixed(8)) : void 0,
171
- cachedDiscountUSD: cachedTokens > 0 ? Number(cachedDiscountUSD.toFixed(8)) : void 0,
303
+ reasoningCostUSD: reasoningTokens > 0n ? Number(reasoningCostUSD.toFixed(8)) : void 0,
304
+ cachedDiscountUSD: cachedTokens > 0n ? Number(cachedDiscountUSD.toFixed(8)) : void 0,
172
305
  totalUSD: Number(totalUSD.toFixed(8)),
306
+ wholesaleTotalUSD: Number(wholesaleTotalUSD.toFixed(8)),
307
+ billedUSD: Number(billedUSD.toFixed(8)),
308
+ profitUSD: Number(profitUSD.toFixed(8)),
173
309
  retailUSD: retailUSD !== void 0 ? Number(retailUSD.toFixed(8)) : void 0,
174
310
  currency: rates.currency || "USD"
175
311
  };
@@ -1120,9 +1256,315 @@ var VibezBillingModal = ({
1120
1256
  }
1121
1257
  ) });
1122
1258
  };
1259
+
1260
+ // src/react/vibezcheck-ui.tsx
1261
+ var import_react5 = require("react");
1262
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1263
+ var DEV_RATES = {
1264
+ "gpt-4o": { input: 2.5, output: 10 },
1265
+ "gpt-4o-mini": { input: 0.15, output: 0.6 },
1266
+ "claude-3-5-sonnet": { input: 3, output: 15 },
1267
+ "claude-3-7-sonnet": { input: 3, output: 15 },
1268
+ "gemini-1.5-pro": { input: 1.25, output: 5 },
1269
+ "gemini-1.5-flash": { input: 0.075, output: 0.3 },
1270
+ "deepseek-chat": { input: 0.14, output: 0.28 },
1271
+ default: { input: 2, output: 8 }
1272
+ };
1273
+ function VibezCheck({
1274
+ messages,
1275
+ events,
1276
+ model = "gpt-4o",
1277
+ margin = 1.25,
1278
+ totalCostUSD: manualCost,
1279
+ totalTokens: manualTokens,
1280
+ remainingBalanceUSD,
1281
+ position = "bottom-center",
1282
+ theme = "dark",
1283
+ devMode,
1284
+ className = "",
1285
+ onTopUp,
1286
+ onCostUpdate
1287
+ }) {
1288
+ const [isOpen, setIsOpen] = (0, import_react5.useState)(false);
1289
+ const normalizedModel = (0, import_react5.useMemo)(() => {
1290
+ const clean = model.toLowerCase().replace(/^(openai|anthropic|google)\//, "");
1291
+ return Object.keys(DEV_RATES).find((k) => clean.includes(k)) || "default";
1292
+ }, [model]);
1293
+ const stats = (0, import_react5.useMemo)(() => {
1294
+ let hasServerTelemetry = false;
1295
+ let wholesaleUSD = 0;
1296
+ let billedUSD = manualCost ?? 0;
1297
+ let totalTokens = manualTokens ?? 0;
1298
+ let promptTokens = 0;
1299
+ let completionTokens = 0;
1300
+ let cachedTokens = 0;
1301
+ let reasoningTokens = 0;
1302
+ let turns = 0;
1303
+ if (events && events.length > 0) {
1304
+ hasServerTelemetry = true;
1305
+ for (const ev of events) {
1306
+ billedUSD += ev.cost?.retailUSD ?? ev.cost?.billedUSD ?? ev.cost?.totalUSD ?? 0;
1307
+ wholesaleUSD += ev.cost?.wholesaleTotalUSD ?? ev.cost?.totalUSD ?? 0;
1308
+ totalTokens += ev.usage?.totalTokens ?? 0;
1309
+ promptTokens += ev.usage?.inputTokens ?? 0;
1310
+ completionTokens += ev.usage?.outputTokens ?? 0;
1311
+ cachedTokens += ev.usage?.cachedTokens ?? 0;
1312
+ reasoningTokens += ev.usage?.reasoningTokens ?? 0;
1313
+ turns++;
1314
+ }
1315
+ }
1316
+ if (messages && messages.length > 0) {
1317
+ for (const msg of messages) {
1318
+ turns++;
1319
+ let eventFound = null;
1320
+ if (Array.isArray(msg.annotations)) {
1321
+ for (const ann of msg.annotations) {
1322
+ if (ann && (ann.cost || ann.usage || ann.vibez)) {
1323
+ eventFound = ann.vibez || ann;
1324
+ break;
1325
+ }
1326
+ }
1327
+ }
1328
+ if (!eventFound && Array.isArray(msg.parts)) {
1329
+ for (const part of msg.parts) {
1330
+ if (part && (part.type === "data" || part.type === "custom") && part.data?.vibez) {
1331
+ eventFound = part.data.vibez;
1332
+ break;
1333
+ }
1334
+ }
1335
+ }
1336
+ if (eventFound) {
1337
+ hasServerTelemetry = true;
1338
+ billedUSD += eventFound.cost?.retailUSD ?? eventFound.cost?.billedUSD ?? eventFound.cost?.totalUSD ?? 0;
1339
+ wholesaleUSD += eventFound.cost?.wholesaleTotalUSD ?? eventFound.cost?.totalUSD ?? 0;
1340
+ totalTokens += eventFound.usage?.totalTokens ?? 0;
1341
+ promptTokens += eventFound.usage?.inputTokens ?? 0;
1342
+ completionTokens += eventFound.usage?.outputTokens ?? 0;
1343
+ cachedTokens += eventFound.usage?.cachedTokens ?? 0;
1344
+ reasoningTokens += eventFound.usage?.reasoningTokens ?? 0;
1345
+ } else {
1346
+ let text = "";
1347
+ if (typeof msg.content === "string") {
1348
+ text = msg.content;
1349
+ } else if (Array.isArray(msg.parts)) {
1350
+ text = msg.parts.filter((p) => p.type === "text").map((p) => p.text).join(" ");
1351
+ }
1352
+ const estimatedTok = Math.ceil(text.length / 3.8);
1353
+ if (msg.role === "user") {
1354
+ promptTokens += estimatedTok;
1355
+ } else if (msg.role === "assistant") {
1356
+ completionTokens += estimatedTok;
1357
+ } else {
1358
+ promptTokens += estimatedTok;
1359
+ }
1360
+ totalTokens += estimatedTok;
1361
+ }
1362
+ }
1363
+ if (!hasServerTelemetry && totalTokens > 0) {
1364
+ const rates = DEV_RATES[normalizedModel] || DEV_RATES.default;
1365
+ wholesaleUSD = (promptTokens * rates.input + completionTokens * rates.output) / 1e6;
1366
+ billedUSD = wholesaleUSD * margin;
1367
+ }
1368
+ }
1369
+ const profitUSD = Math.max(0, billedUSD - wholesaleUSD);
1370
+ const isDev = devMode !== void 0 ? devMode : !hasServerTelemetry;
1371
+ return {
1372
+ wholesaleUSD,
1373
+ billedUSD,
1374
+ profitUSD,
1375
+ totalTokens,
1376
+ promptTokens,
1377
+ completionTokens,
1378
+ cachedTokens,
1379
+ reasoningTokens,
1380
+ turns,
1381
+ isDevMode: isDev
1382
+ };
1383
+ }, [messages, events, manualCost, manualTokens, normalizedModel, margin, devMode]);
1384
+ (0, import_react5.useEffect)(() => {
1385
+ if (onCostUpdate) {
1386
+ onCostUpdate({
1387
+ totalCostUSD: stats.billedUSD,
1388
+ wholesaleUSD: stats.wholesaleUSD,
1389
+ profitUSD: stats.profitUSD,
1390
+ totalTokens: stats.totalTokens,
1391
+ isDevMode: stats.isDevMode
1392
+ });
1393
+ }
1394
+ }, [stats.billedUSD, stats.totalTokens, stats.isDevMode, onCostUpdate]);
1395
+ const isDark = theme === "dark" || theme === "auto";
1396
+ const positionStyles = (0, import_react5.useMemo)(() => {
1397
+ const base = { position: "fixed", zIndex: 9999 };
1398
+ switch (position) {
1399
+ case "bottom-center":
1400
+ return { ...base, bottom: "24px", left: "50%", transform: "translateX(-50%)" };
1401
+ case "bottom-right":
1402
+ return { ...base, bottom: "24px", right: "24px" };
1403
+ case "bottom-left":
1404
+ return { ...base, bottom: "24px", left: "24px" };
1405
+ case "top-center":
1406
+ return { ...base, top: "24px", left: "50%", transform: "translateX(-50%)" };
1407
+ default:
1408
+ return { ...base, bottom: "24px", left: "50%", transform: "translateX(-50%)" };
1409
+ }
1410
+ }, [position]);
1411
+ const formatTokens = (num) => {
1412
+ if (num >= 1e6) return (num / 1e6).toFixed(2) + "M";
1413
+ if (num >= 1e3) return (num / 1e3).toFixed(1) + "k";
1414
+ return num.toLocaleString();
1415
+ };
1416
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: positionStyles, className: `vibezcheck-ui-root font-sans text-xs select-none ${className}`, children: [
1417
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1418
+ "div",
1419
+ {
1420
+ style: {
1421
+ background: isDark ? "rgba(15, 23, 42, 0.96)" : "rgba(255, 255, 255, 0.98)",
1422
+ backdropFilter: "blur(16px)",
1423
+ borderColor: isDark ? "#334155" : "#e2e8f0",
1424
+ color: isDark ? "#f8fafc" : "#0f172a"
1425
+ },
1426
+ className: "mb-3 p-4 rounded-2xl border shadow-2xl w-84 space-y-3.5 transition-all animate-in fade-in slide-in-from-bottom-2",
1427
+ children: [
1428
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between border-b pb-2 border-slate-700/50", children: [
1429
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
1430
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-lime-400 font-bold text-sm", children: "\u2726" }),
1431
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-semibold tracking-wide uppercase text-[11px] text-lime-400", children: "VibezCheck Financial Meter" })
1432
+ ] }),
1433
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1434
+ "button",
1435
+ {
1436
+ onClick: () => setIsOpen(false),
1437
+ className: "text-slate-400 hover:text-white text-xs px-1.5 py-0.5 rounded cursor-pointer transition",
1438
+ children: "\u2715"
1439
+ }
1440
+ )
1441
+ ] }),
1442
+ stats.isDevMode ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "bg-amber-950/40 border border-amber-500/30 rounded-lg p-2 text-[10px] text-amber-300 flex items-center justify-between", children: [
1443
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-center gap-1.5 font-medium", children: [
1444
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-2 h-2 rounded-full bg-amber-400 animate-ping" }),
1445
+ "Zero-DB Dev Mode (Simulated Bill)"
1446
+ ] }),
1447
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-[9px] bg-amber-500/20 px-1.5 py-0.5 rounded font-mono", children: [
1448
+ "+",
1449
+ Math.round((margin - 1) * 100),
1450
+ "% Margin"
1451
+ ] })
1452
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "bg-emerald-950/40 border border-emerald-500/30 rounded-lg p-2 text-[10px] text-emerald-300 flex items-center gap-1.5", children: [
1453
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-2 h-2 rounded-full bg-emerald-400" }),
1454
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Live Stripe Usage Meter Active" })
1455
+ ] }),
1456
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "bg-slate-800/60 p-2.5 rounded-lg border border-slate-700/40 space-y-2 text-[11px]", children: [
1457
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between items-center text-slate-400", children: [
1458
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Provider Cost (Wholesale):" }),
1459
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-mono text-slate-300", children: [
1460
+ "$",
1461
+ stats.wholesaleUSD.toFixed(4)
1462
+ ] })
1463
+ ] }),
1464
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between items-center text-slate-400", children: [
1465
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1466
+ "Your Profit (+",
1467
+ Math.round((margin - 1) * 100),
1468
+ "%):"
1469
+ ] }),
1470
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-mono text-lime-400 font-medium", children: [
1471
+ "+$",
1472
+ stats.profitUSD.toFixed(4)
1473
+ ] })
1474
+ ] }),
1475
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "border-t border-slate-700/60 pt-1.5 flex justify-between items-center font-bold", children: [
1476
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-white", children: "Customer Billed Total:" }),
1477
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-mono text-lime-400 text-sm", children: [
1478
+ "$",
1479
+ stats.billedUSD.toFixed(4)
1480
+ ] })
1481
+ ] })
1482
+ ] }),
1483
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "bg-slate-800/40 p-2.5 rounded-lg border border-slate-700/30 space-y-1.5 text-[11px]", children: [
1484
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between text-slate-400", children: [
1485
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Prompt Tokens:" }),
1486
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-mono text-slate-200", children: formatTokens(stats.promptTokens) })
1487
+ ] }),
1488
+ stats.cachedTokens > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between text-[10px] text-lime-300", children: [
1489
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u21B3 Cache Savings (85% off):" }),
1490
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-mono", children: [
1491
+ "-",
1492
+ formatTokens(stats.cachedTokens)
1493
+ ] })
1494
+ ] }),
1495
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between text-slate-400", children: [
1496
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Completion Tokens:" }),
1497
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-mono text-slate-200", children: formatTokens(stats.completionTokens) })
1498
+ ] }),
1499
+ stats.reasoningTokens > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between text-[10px] text-purple-300", children: [
1500
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u21B3 Thinking / Reasoning:" }),
1501
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-mono", children: formatTokens(stats.reasoningTokens) })
1502
+ ] }),
1503
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between border-t border-slate-700/50 pt-1 font-semibold text-slate-300", children: [
1504
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Total Tokens:" }),
1505
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-mono text-white", children: formatTokens(stats.totalTokens) })
1506
+ ] })
1507
+ ] }),
1508
+ typeof remainingBalanceUSD === "number" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between items-center text-[11px] px-1", children: [
1509
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-slate-400", children: "Remaining Balance:" }),
1510
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1511
+ "span",
1512
+ {
1513
+ className: `font-mono font-bold ${remainingBalanceUSD < 1 ? "text-amber-400" : "text-slate-200"}`,
1514
+ children: [
1515
+ "$",
1516
+ remainingBalanceUSD.toFixed(2)
1517
+ ]
1518
+ }
1519
+ )
1520
+ ] }),
1521
+ onTopUp && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1522
+ "button",
1523
+ {
1524
+ onClick: onTopUp,
1525
+ className: "w-full py-2 px-3 rounded-lg bg-lime-500 hover:bg-lime-400 text-slate-950 font-semibold text-xs transition cursor-pointer shadow-md active:scale-98",
1526
+ children: "+ Add / Top Up Credits"
1527
+ }
1528
+ ),
1529
+ stats.isDevMode && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-[9px] text-slate-500 text-center leading-tight", children: "Zero-DB Dev Mode: Running in local memory without database or Stripe dependencies." })
1530
+ ]
1531
+ }
1532
+ ),
1533
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1534
+ "div",
1535
+ {
1536
+ onClick: () => setIsOpen(!isOpen),
1537
+ style: {
1538
+ background: isDark ? "rgba(15, 23, 42, 0.90)" : "rgba(255, 255, 255, 0.95)",
1539
+ backdropFilter: "blur(12px)",
1540
+ borderColor: isDark ? "#334155" : "#e2e8f0",
1541
+ color: isDark ? "#f8fafc" : "#0f172a"
1542
+ },
1543
+ className: "flex items-center gap-2.5 px-3.5 py-1.5 rounded-full border shadow-xl cursor-pointer hover:scale-105 active:scale-95 transition-all select-none",
1544
+ children: [
1545
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-lime-400 font-bold text-xs animate-pulse", children: "\u2726" }),
1546
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-mono font-semibold text-lime-400 text-xs", children: [
1547
+ "$",
1548
+ stats.billedUSD.toFixed(4)
1549
+ ] }),
1550
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-slate-500", children: "\u2022" }),
1551
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-mono text-slate-300 text-xs", children: [
1552
+ formatTokens(stats.totalTokens),
1553
+ " tok"
1554
+ ] }),
1555
+ stats.isDevMode && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[9px] font-mono text-amber-400 bg-amber-400/10 px-1 py-0.2 rounded", children: "DEV" }),
1556
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[10px] text-slate-400 ml-0.5", children: isOpen ? "\u25BC" : "\u25B2" })
1557
+ ]
1558
+ }
1559
+ )
1560
+ ] });
1561
+ }
1562
+ var VibezPill = VibezCheck;
1123
1563
  // Annotate the CommonJS export names for ESM import in node:
1124
1564
  0 && (module.exports = {
1125
1565
  VibezBillingModal,
1566
+ VibezCheck,
1567
+ VibezPill,
1126
1568
  VibezReceipt,
1127
1569
  VibezSessionBadge,
1128
1570
  VibezSessionContext,