vibezcheck 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,642 @@
1
+ // src/react/context.tsx
2
+ import { createContext, useState, useEffect, useCallback, useMemo } from "react";
3
+
4
+ // src/pricing/table.ts
5
+ var MODEL_PRICING_TABLE = {
6
+ // --- OpenAI ---
7
+ "gpt-5.6-sol": { inputPer1M: 4, outputPer1M: 20, cachedInputPer1M: 0.4 },
8
+ "gpt-5.6-terra": { inputPer1M: 2, outputPer1M: 12, cachedInputPer1M: 0.2 },
9
+ "gpt-5.6-luna": { inputPer1M: 0.2, outputPer1M: 1.2, cachedInputPer1M: 0.02 },
10
+ "gpt-5": { inputPer1M: 4, outputPer1M: 20, cachedInputPer1M: 0.4 },
11
+ "gpt-5-mini": { inputPer1M: 0.2, outputPer1M: 1.2, cachedInputPer1M: 0.02 },
12
+ "o1": { inputPer1M: 15, outputPer1M: 60, cachedInputPer1M: 7.5 },
13
+ "o1-mini": { inputPer1M: 1.1, outputPer1M: 4.4, cachedInputPer1M: 0.55 },
14
+ "o3": { inputPer1M: 15, outputPer1M: 60, cachedInputPer1M: 7.5 },
15
+ "o3-mini": { inputPer1M: 1.1, outputPer1M: 4.4, cachedInputPer1M: 0.55 },
16
+ "gpt-4o": { inputPer1M: 2.5, outputPer1M: 10, cachedInputPer1M: 1.25 },
17
+ "gpt-4o-mini": { inputPer1M: 0.15, outputPer1M: 0.6, cachedInputPer1M: 0.075 },
18
+ "gpt-4.1": { inputPer1M: 2, outputPer1M: 8, cachedInputPer1M: 1 },
19
+ "gpt-4.1-nano": { inputPer1M: 0.1, outputPer1M: 0.4, cachedInputPer1M: 0.05 },
20
+ "text-embedding-3-small": { inputPer1M: 0.02, outputPer1M: 0 },
21
+ "text-embedding-3-large": { inputPer1M: 0.13, outputPer1M: 0 },
22
+ // --- Anthropic ---
23
+ "claude-3-7-sonnet": { inputPer1M: 0.59, outputPer1M: 2.93, cachedInputPer1M: 0.3 },
24
+ "claude-sonnet-5": { inputPer1M: 2, outputPer1M: 10, cachedInputPer1M: 0.3 },
25
+ "claude-3-5-sonnet": { inputPer1M: 3, outputPer1M: 15, cachedInputPer1M: 0.3 },
26
+ "claude-3-5-haiku": { inputPer1M: 0.8, outputPer1M: 4, cachedInputPer1M: 0.08 },
27
+ "haiku-4.5": { inputPer1M: 1, outputPer1M: 5, cachedInputPer1M: 0.1 },
28
+ "claude-opus-5": { inputPer1M: 5, outputPer1M: 25, cachedInputPer1M: 1.5 },
29
+ "claude-3-opus": { inputPer1M: 15, outputPer1M: 75, cachedInputPer1M: 1.5 },
30
+ // --- Google Gemini ---
31
+ "gemini-3.7-flash": { inputPer1M: 0.75, outputPer1M: 3.75, cachedInputPer1M: 0.18 },
32
+ "gemini-3.1-pro": { inputPer1M: 2, outputPer1M: 12, cachedInputPer1M: 0.5 },
33
+ "gemini-3.5-flash": { inputPer1M: 1.5, outputPer1M: 9, cachedInputPer1M: 0.38 },
34
+ "gemini-3.1-flash-lite": { inputPer1M: 0.25, outputPer1M: 1.5, cachedInputPer1M: 0.06 },
35
+ "gemini-2.0-flash": { inputPer1M: 0.1, outputPer1M: 0.4, cachedInputPer1M: 0.025 },
36
+ "gemini-1.5-pro": { inputPer1M: 1.25, outputPer1M: 5, cachedInputPer1M: 0.3125 },
37
+ "gemini-1.5-flash": { inputPer1M: 0.075, outputPer1M: 0.3, cachedInputPer1M: 0.01875 },
38
+ // --- xAI Grok ---
39
+ "grok-4.6": { inputPer1M: 3, outputPer1M: 15 },
40
+ "grok-2": { inputPer1M: 2, outputPer1M: 10 },
41
+ "grok-2-vision": { inputPer1M: 2, outputPer1M: 10 },
42
+ "grok-beta": { inputPer1M: 5, outputPer1M: 15 },
43
+ // --- Mistral ---
44
+ "mistral-large-3": { inputPer1M: 2, outputPer1M: 6 },
45
+ "mistral-large-latest": { inputPer1M: 2, outputPer1M: 6 },
46
+ "codestral-latest": { inputPer1M: 0.3, outputPer1M: 0.9 },
47
+ "mistral-small-latest": { inputPer1M: 0.2, outputPer1M: 0.6 },
48
+ "ministral-8b-latest": { inputPer1M: 0.1, outputPer1M: 0.1 },
49
+ // --- Groq LPUs ---
50
+ "llama-3.3-70b-versatile": { inputPer1M: 0.59, outputPer1M: 0.79 },
51
+ "llama-3.1-8b-instant": { inputPer1M: 0.05, outputPer1M: 0.08 },
52
+ "deepseek-r1-distill-llama-70b": { inputPer1M: 0.75, outputPer1M: 0.99 },
53
+ "qwen-2.5-32b": { inputPer1M: 0.29, outputPer1M: 0.39 },
54
+ // --- DeepSeek ---
55
+ "deepseek-v4-pro": { inputPer1M: 0.66, outputPer1M: 1.98, cachedInputPer1M: 0.15 },
56
+ "deepseek-v4-flash": { inputPer1M: 0.22, outputPer1M: 0.66, cachedInputPer1M: 0.05 },
57
+ "deepseek-chat": { inputPer1M: 0.22, outputPer1M: 0.66, cachedInputPer1M: 0.05 },
58
+ "deepseek-reasoner": { inputPer1M: 0.66, outputPer1M: 1.98, cachedInputPer1M: 0.15 },
59
+ // --- Cohere ---
60
+ "command-r-plus": { inputPer1M: 2.5, outputPer1M: 10 },
61
+ "command-r": { inputPer1M: 0.15, outputPer1M: 0.6 }
62
+ };
63
+ var customPricingRegistry = {};
64
+ function normalizeModelKey(rawModel) {
65
+ if (!rawModel) return "unknown";
66
+ let model = rawModel.toLowerCase().trim();
67
+ if (model.includes("/")) {
68
+ model = model.split("/")[1] || model;
69
+ }
70
+ model = model.replace(/-\d{8}$/, "");
71
+ model = model.replace(/-\d{4}-\d{2}-\d{2}$/, "");
72
+ return model;
73
+ }
74
+ function getModelPricing(modelName) {
75
+ const normalized = normalizeModelKey(modelName);
76
+ if (customPricingRegistry[normalized]) {
77
+ return customPricingRegistry[normalized];
78
+ }
79
+ if (customPricingRegistry[modelName]) {
80
+ return customPricingRegistry[modelName];
81
+ }
82
+ if (MODEL_PRICING_TABLE[normalized]) {
83
+ return MODEL_PRICING_TABLE[normalized];
84
+ }
85
+ if (MODEL_PRICING_TABLE[modelName]) {
86
+ return MODEL_PRICING_TABLE[modelName];
87
+ }
88
+ return {
89
+ inputPer1M: 1,
90
+ outputPer1M: 3,
91
+ cachedInputPer1M: 0.5
92
+ };
93
+ }
94
+
95
+ // src/pricing/calculator.ts
96
+ function calculateCost(params) {
97
+ const rates = getModelPricing(params.model);
98
+ const inputTokens = params.inputTokens ?? 0;
99
+ const outputTokens = params.outputTokens ?? 0;
100
+ const reasoningTokens = params.reasoningTokens ?? 0;
101
+ const cachedTokens = params.cachedTokens ?? 0;
102
+ const regularInputTokens = Math.max(0, inputTokens - cachedTokens);
103
+ const regularInputCost = regularInputTokens / 1e6 * rates.inputPer1M;
104
+ const cachedRate = rates.cachedInputPer1M ?? rates.inputPer1M * 0.5;
105
+ const cachedInputCost = cachedTokens / 1e6 * cachedRate;
106
+ const inputCostUSD = regularInputCost + cachedInputCost;
107
+ const outputCostUSD = outputTokens / 1e6 * rates.outputPer1M;
108
+ const reasoningRate = rates.reasoningPer1M ?? rates.outputPer1M;
109
+ const reasoningCostUSD = reasoningTokens / 1e6 * reasoningRate;
110
+ const standardCacheCost = cachedTokens / 1e6 * rates.inputPer1M;
111
+ const cachedDiscountUSD = Math.max(0, standardCacheCost - cachedInputCost);
112
+ const totalUSD = inputCostUSD + outputCostUSD;
113
+ const markup = params.markupMultiplier ?? 1;
114
+ const retailUSD = markup !== 1 ? totalUSD * markup : void 0;
115
+ return {
116
+ inputCostUSD: Number(inputCostUSD.toFixed(8)),
117
+ outputCostUSD: Number(outputCostUSD.toFixed(8)),
118
+ reasoningCostUSD: reasoningTokens > 0 ? Number(reasoningCostUSD.toFixed(8)) : void 0,
119
+ cachedDiscountUSD: cachedTokens > 0 ? Number(cachedDiscountUSD.toFixed(8)) : void 0,
120
+ totalUSD: Number(totalUSD.toFixed(8)),
121
+ retailUSD: retailUSD ? Number(retailUSD.toFixed(8)) : void 0,
122
+ currency: rates.currency || "USD"
123
+ };
124
+ }
125
+ function calculateUsageCost(model, usage, markupMultiplier) {
126
+ return calculateCost({
127
+ model,
128
+ inputTokens: usage.inputTokens,
129
+ outputTokens: usage.outputTokens,
130
+ reasoningTokens: usage.reasoningTokens,
131
+ cachedTokens: usage.cachedTokens,
132
+ cacheWriteTokens: usage.cacheWriteTokens,
133
+ markupMultiplier
134
+ });
135
+ }
136
+
137
+ // src/react/context.tsx
138
+ import { jsx } from "react/jsx-runtime";
139
+ var INITIAL_USAGE = {
140
+ inputTokens: 0,
141
+ outputTokens: 0,
142
+ totalTokens: 0,
143
+ reasoningTokens: 0,
144
+ visibleOutputTokens: 0,
145
+ cachedTokens: 0
146
+ };
147
+ var INITIAL_COST = {
148
+ inputCostUSD: 0,
149
+ outputCostUSD: 0,
150
+ reasoningCostUSD: 0,
151
+ cachedDiscountUSD: 0,
152
+ totalUSD: 0,
153
+ currency: "USD"
154
+ };
155
+ var VibezSessionContext = createContext(null);
156
+ function generateId() {
157
+ return "sess_" + Math.random().toString(36).substring(2, 11) + "_" + Date.now().toString(36);
158
+ }
159
+ var VibezSessionProvider = ({
160
+ children,
161
+ sessionId: customSessionId,
162
+ persist = "memory",
163
+ storage,
164
+ storageKey = "vibez_session_",
165
+ markupMultiplier,
166
+ onTurnRecorded
167
+ }) => {
168
+ const [sessionId, setSessionId] = useState(() => customSessionId || generateId());
169
+ const [turnCount, setTurnCount] = useState(0);
170
+ const [sessionUsage, setSessionUsage] = useState(INITIAL_USAGE);
171
+ const [sessionCost, setSessionCost] = useState(INITIAL_COST);
172
+ const [byModel, setByModel] = useState({});
173
+ const [history, setHistory] = useState([]);
174
+ const fullStorageKey = useMemo(() => `${storageKey}${sessionId}`, [storageKey, sessionId]);
175
+ useEffect(() => {
176
+ if (persist === "memory") return;
177
+ try {
178
+ if (persist === "sessionStorage" && typeof window !== "undefined" && window.sessionStorage) {
179
+ const data = window.sessionStorage.getItem(fullStorageKey);
180
+ if (data) {
181
+ const parsed = JSON.parse(data);
182
+ setTurnCount(parsed.turnCount);
183
+ setSessionUsage(parsed.sessionUsage);
184
+ setSessionCost(parsed.sessionCost);
185
+ setByModel(parsed.byModel);
186
+ setHistory(parsed.history);
187
+ }
188
+ } else if (persist === "localStorage" && typeof window !== "undefined" && window.localStorage) {
189
+ const data = window.localStorage.getItem(fullStorageKey);
190
+ if (data) {
191
+ const parsed = JSON.parse(data);
192
+ setTurnCount(parsed.turnCount);
193
+ setSessionUsage(parsed.sessionUsage);
194
+ setSessionCost(parsed.sessionCost);
195
+ setByModel(parsed.byModel);
196
+ setHistory(parsed.history);
197
+ }
198
+ } else if (persist === "custom" && storage) {
199
+ const res = storage.getItem(fullStorageKey);
200
+ if (res instanceof Promise) {
201
+ res.then((data) => {
202
+ if (data) {
203
+ const parsed = JSON.parse(data);
204
+ setTurnCount(parsed.turnCount);
205
+ setSessionUsage(parsed.sessionUsage);
206
+ setSessionCost(parsed.sessionCost);
207
+ setByModel(parsed.byModel);
208
+ setHistory(parsed.history);
209
+ }
210
+ });
211
+ } else if (res) {
212
+ const parsed = JSON.parse(res);
213
+ setTurnCount(parsed.turnCount);
214
+ setSessionUsage(parsed.sessionUsage);
215
+ setSessionCost(parsed.sessionCost);
216
+ setByModel(parsed.byModel);
217
+ setHistory(parsed.history);
218
+ }
219
+ }
220
+ } catch {
221
+ }
222
+ }, [persist, fullStorageKey, storage]);
223
+ const saveState = useCallback(
224
+ (newState) => {
225
+ if (persist === "memory") return;
226
+ try {
227
+ const json = JSON.stringify(newState);
228
+ if (persist === "sessionStorage" && typeof window !== "undefined" && window.sessionStorage) {
229
+ window.sessionStorage.setItem(fullStorageKey, json);
230
+ } else if (persist === "localStorage" && typeof window !== "undefined" && window.localStorage) {
231
+ window.localStorage.setItem(fullStorageKey, json);
232
+ } else if (persist === "custom" && storage) {
233
+ storage.setItem(fullStorageKey, json);
234
+ }
235
+ } catch {
236
+ }
237
+ },
238
+ [persist, fullStorageKey, storage]
239
+ );
240
+ const recordTurn = useCallback(
241
+ ({ model, usage: rawUsage, metadata }) => {
242
+ const inputTokens = rawUsage.promptTokens ?? rawUsage.inputTokens ?? 0;
243
+ const outputTokens = rawUsage.completionTokens ?? rawUsage.outputTokens ?? 0;
244
+ const reasoningTokens = rawUsage.reasoningTokens ?? rawUsage.completionTokensDetails?.reasoning_tokens ?? 0;
245
+ const cachedTokens = rawUsage.cachedTokens ?? rawUsage.promptTokensDetails?.cached_tokens ?? 0;
246
+ const cacheWriteTokens = rawUsage.cacheWriteTokens ?? 0;
247
+ const turnUsage = {
248
+ inputTokens,
249
+ outputTokens,
250
+ totalTokens: rawUsage.totalTokens ?? inputTokens + outputTokens,
251
+ reasoningTokens: reasoningTokens > 0 ? reasoningTokens : void 0,
252
+ visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),
253
+ cachedTokens: cachedTokens > 0 ? cachedTokens : void 0,
254
+ cacheWriteTokens: cacheWriteTokens > 0 ? cacheWriteTokens : void 0
255
+ };
256
+ const turnCost = calculateUsageCost(model, turnUsage, markupMultiplier);
257
+ const record = {
258
+ id: "turn_" + Math.random().toString(36).substring(2, 9) + "_" + Date.now().toString(36),
259
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
260
+ model,
261
+ usage: turnUsage,
262
+ cost: turnCost,
263
+ metadata
264
+ };
265
+ const newTurnCount = turnCount + 1;
266
+ setTurnCount(newTurnCount);
267
+ const newUsage = {
268
+ inputTokens: sessionUsage.inputTokens + inputTokens,
269
+ outputTokens: sessionUsage.outputTokens + outputTokens,
270
+ totalTokens: sessionUsage.totalTokens + turnUsage.totalTokens,
271
+ reasoningTokens: (sessionUsage.reasoningTokens ?? 0) + (turnUsage.reasoningTokens ?? 0),
272
+ visibleOutputTokens: (sessionUsage.visibleOutputTokens ?? 0) + (turnUsage.visibleOutputTokens ?? outputTokens),
273
+ cachedTokens: (sessionUsage.cachedTokens ?? 0) + (turnUsage.cachedTokens ?? 0),
274
+ cacheWriteTokens: (sessionUsage.cacheWriteTokens ?? 0) + (turnUsage.cacheWriteTokens ?? 0)
275
+ };
276
+ setSessionUsage(newUsage);
277
+ const newCost = {
278
+ inputCostUSD: Number((sessionCost.inputCostUSD + turnCost.inputCostUSD).toFixed(6)),
279
+ outputCostUSD: Number((sessionCost.outputCostUSD + turnCost.outputCostUSD).toFixed(6)),
280
+ reasoningCostUSD: turnCost.reasoningCostUSD !== void 0 || sessionCost.reasoningCostUSD !== void 0 ? Number(
281
+ ((sessionCost.reasoningCostUSD ?? 0) + (turnCost.reasoningCostUSD ?? 0)).toFixed(6)
282
+ ) : void 0,
283
+ cachedDiscountUSD: turnCost.cachedDiscountUSD !== void 0 || sessionCost.cachedDiscountUSD !== void 0 ? Number(
284
+ ((sessionCost.cachedDiscountUSD ?? 0) + (turnCost.cachedDiscountUSD ?? 0)).toFixed(6)
285
+ ) : void 0,
286
+ totalUSD: Number((sessionCost.totalUSD + turnCost.totalUSD).toFixed(6)),
287
+ retailUSD: turnCost.retailUSD !== void 0 || sessionCost.retailUSD !== void 0 ? Number(((sessionCost.retailUSD ?? 0) + (turnCost.retailUSD ?? 0)).toFixed(6)) : void 0,
288
+ currency: turnCost.currency || "USD"
289
+ };
290
+ setSessionCost(newCost);
291
+ const prevModelStats = byModel[model] || {
292
+ turns: 0,
293
+ usage: { ...INITIAL_USAGE },
294
+ cost: { ...INITIAL_COST }
295
+ };
296
+ const newModelStats = {
297
+ turns: prevModelStats.turns + 1,
298
+ usage: {
299
+ inputTokens: prevModelStats.usage.inputTokens + inputTokens,
300
+ outputTokens: prevModelStats.usage.outputTokens + outputTokens,
301
+ totalTokens: prevModelStats.usage.totalTokens + turnUsage.totalTokens,
302
+ reasoningTokens: (prevModelStats.usage.reasoningTokens ?? 0) + (turnUsage.reasoningTokens ?? 0),
303
+ visibleOutputTokens: (prevModelStats.usage.visibleOutputTokens ?? 0) + (turnUsage.visibleOutputTokens ?? outputTokens),
304
+ cachedTokens: (prevModelStats.usage.cachedTokens ?? 0) + (turnUsage.cachedTokens ?? 0)
305
+ },
306
+ cost: {
307
+ inputCostUSD: Number(
308
+ (prevModelStats.cost.inputCostUSD + turnCost.inputCostUSD).toFixed(6)
309
+ ),
310
+ outputCostUSD: Number(
311
+ (prevModelStats.cost.outputCostUSD + turnCost.outputCostUSD).toFixed(6)
312
+ ),
313
+ totalUSD: Number((prevModelStats.cost.totalUSD + turnCost.totalUSD).toFixed(6)),
314
+ currency: turnCost.currency || "USD"
315
+ }
316
+ };
317
+ const newByModel = {
318
+ ...byModel,
319
+ [model]: newModelStats
320
+ };
321
+ setByModel(newByModel);
322
+ const newHistory = [...history, record];
323
+ setHistory(newHistory);
324
+ const updatedState = {
325
+ sessionId,
326
+ turnCount: newTurnCount,
327
+ sessionUsage: newUsage,
328
+ sessionCost: newCost,
329
+ byModel: newByModel,
330
+ history: newHistory
331
+ };
332
+ saveState(updatedState);
333
+ if (onTurnRecorded) {
334
+ onTurnRecorded(record, updatedState);
335
+ }
336
+ return record;
337
+ },
338
+ [
339
+ turnCount,
340
+ sessionUsage,
341
+ sessionCost,
342
+ byModel,
343
+ history,
344
+ sessionId,
345
+ markupMultiplier,
346
+ onTurnRecorded,
347
+ saveState
348
+ ]
349
+ );
350
+ const resetSession = useCallback(
351
+ (newSessionId) => {
352
+ const nextId = newSessionId || generateId();
353
+ setSessionId(nextId);
354
+ setTurnCount(0);
355
+ setSessionUsage(INITIAL_USAGE);
356
+ setSessionCost(INITIAL_COST);
357
+ setByModel({});
358
+ setHistory([]);
359
+ if (persist === "sessionStorage" && typeof window !== "undefined" && window.sessionStorage) {
360
+ window.sessionStorage.removeItem(fullStorageKey);
361
+ } else if (persist === "localStorage" && typeof window !== "undefined" && window.localStorage) {
362
+ window.localStorage.removeItem(fullStorageKey);
363
+ } else if (persist === "custom" && storage) {
364
+ storage.removeItem(fullStorageKey);
365
+ }
366
+ },
367
+ [persist, fullStorageKey, storage]
368
+ );
369
+ const value = useMemo(
370
+ () => ({
371
+ sessionId,
372
+ turnCount,
373
+ sessionUsage,
374
+ sessionCost,
375
+ byModel,
376
+ history,
377
+ recordTurn,
378
+ resetSession
379
+ }),
380
+ [sessionId, turnCount, sessionUsage, sessionCost, byModel, history, recordTurn, resetSession]
381
+ );
382
+ return /* @__PURE__ */ jsx(VibezSessionContext.Provider, { value, children });
383
+ };
384
+
385
+ // src/react/hooks.ts
386
+ import { useContext } from "react";
387
+ function useVibezSession() {
388
+ const context = useContext(VibezSessionContext);
389
+ if (!context) {
390
+ throw new Error(
391
+ "[vibezcheck/react] useVibezSession must be used within a <VibezSessionProvider>."
392
+ );
393
+ }
394
+ return context;
395
+ }
396
+ var useVibez = useVibezSession;
397
+
398
+ // src/react/widget.tsx
399
+ import { useState as useState2 } from "react";
400
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
401
+ var VibezSessionWidget = ({
402
+ position = "bottom-right",
403
+ showCost = true,
404
+ showTokens = true,
405
+ showReasoning = true,
406
+ theme = "auto",
407
+ className,
408
+ style
409
+ }) => {
410
+ const { sessionUsage, sessionCost, turnCount, byModel } = useVibezSession();
411
+ const [expanded, setExpanded] = useState2(false);
412
+ const hasUsage = sessionUsage.totalTokens > 0;
413
+ const isDark = theme === "dark" || theme === "auto" && typeof window !== "undefined" && window.matchMedia?.("(prefers-color-scheme: dark)").matches;
414
+ const colors = {
415
+ bg: isDark ? "#171717" : "#ffffff",
416
+ text: isDark ? "#f5f5f5" : "#171717",
417
+ subtext: isDark ? "#a3a3a3" : "#737373",
418
+ border: isDark ? "#262626" : "#e5e5e5",
419
+ accent: "#8b5cf6",
420
+ reasoningBg: isDark ? "#2e1065" : "#f3e8ff",
421
+ reasoningText: isDark ? "#c084fc" : "#7c3aed"
422
+ };
423
+ const getPositionStyles = () => {
424
+ if (position === "inline") return {};
425
+ const base = { position: "fixed", zIndex: 9999 };
426
+ switch (position) {
427
+ case "bottom-right":
428
+ return { ...base, bottom: "20px", right: "20px" };
429
+ case "bottom-left":
430
+ return { ...base, bottom: "20px", left: "20px" };
431
+ case "top-right":
432
+ return { ...base, top: "20px", right: "20px" };
433
+ case "top-left":
434
+ return { ...base, top: "20px", left: "20px" };
435
+ default:
436
+ return base;
437
+ }
438
+ };
439
+ const formatTokens = (num) => {
440
+ if (num >= 1e6) return (num / 1e6).toFixed(1) + "M";
441
+ if (num >= 1e3) return (num / 1e3).toFixed(1) + "k";
442
+ return num.toString();
443
+ };
444
+ return /* @__PURE__ */ jsxs(
445
+ "div",
446
+ {
447
+ className,
448
+ style: {
449
+ ...getPositionStyles(),
450
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
451
+ fontSize: "13px",
452
+ ...style
453
+ },
454
+ children: [
455
+ /* @__PURE__ */ jsxs(
456
+ "div",
457
+ {
458
+ onClick: () => setExpanded(!expanded),
459
+ style: {
460
+ display: "flex",
461
+ alignItems: "center",
462
+ gap: "8px",
463
+ padding: "8px 14px",
464
+ backgroundColor: colors.bg,
465
+ color: colors.text,
466
+ border: `1px solid ${colors.border}`,
467
+ borderRadius: "9999px",
468
+ boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
469
+ cursor: "pointer",
470
+ userSelect: "none",
471
+ transition: "all 0.15s ease"
472
+ },
473
+ children: [
474
+ /* @__PURE__ */ jsx2("span", { style: { color: colors.accent, fontWeight: "bold" }, children: "\u26A1" }),
475
+ showTokens && /* @__PURE__ */ jsxs("span", { style: { fontWeight: 600 }, children: [
476
+ formatTokens(sessionUsage.totalTokens),
477
+ " tokens"
478
+ ] }),
479
+ showCost && /* @__PURE__ */ jsxs("span", { style: { color: colors.subtext }, children: [
480
+ "($",
481
+ sessionCost.totalUSD.toFixed(4),
482
+ ")"
483
+ ] }),
484
+ showReasoning && sessionUsage.reasoningTokens > 0 && /* @__PURE__ */ jsxs(
485
+ "span",
486
+ {
487
+ style: {
488
+ fontSize: "11px",
489
+ padding: "2px 6px",
490
+ borderRadius: "6px",
491
+ backgroundColor: colors.reasoningBg,
492
+ color: colors.reasoningText,
493
+ fontWeight: 500
494
+ },
495
+ children: [
496
+ "\u{1F9E0} ",
497
+ formatTokens(sessionUsage.reasoningTokens)
498
+ ]
499
+ }
500
+ ),
501
+ /* @__PURE__ */ jsx2("span", { style: { color: colors.subtext, fontSize: "10px" }, children: expanded ? "\u25B2" : "\u25BC" })
502
+ ]
503
+ }
504
+ ),
505
+ expanded && /* @__PURE__ */ jsxs(
506
+ "div",
507
+ {
508
+ style: {
509
+ marginTop: "8px",
510
+ padding: "14px",
511
+ backgroundColor: colors.bg,
512
+ color: colors.text,
513
+ border: `1px solid ${colors.border}`,
514
+ borderRadius: "12px",
515
+ boxShadow: "0 10px 25px rgba(0,0,0,0.15)",
516
+ width: "260px"
517
+ },
518
+ children: [
519
+ /* @__PURE__ */ jsxs(
520
+ "div",
521
+ {
522
+ style: {
523
+ display: "flex",
524
+ justifyContent: "space-between",
525
+ fontWeight: 600,
526
+ marginBottom: "8px",
527
+ paddingBottom: "6px",
528
+ borderBottom: `1px solid ${colors.border}`
529
+ },
530
+ children: [
531
+ /* @__PURE__ */ jsx2("span", { children: "Live Session Usage" }),
532
+ /* @__PURE__ */ jsxs("span", { style: { color: colors.subtext }, children: [
533
+ turnCount,
534
+ " turns"
535
+ ] })
536
+ ]
537
+ }
538
+ ),
539
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "6px", fontSize: "12px" }, children: [
540
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
541
+ /* @__PURE__ */ jsx2("span", { style: { color: colors.subtext }, children: "Prompt Input:" }),
542
+ /* @__PURE__ */ jsx2("span", { children: sessionUsage.inputTokens.toLocaleString() })
543
+ ] }),
544
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
545
+ /* @__PURE__ */ jsx2("span", { style: { color: colors.subtext }, children: "Output Tokens:" }),
546
+ /* @__PURE__ */ jsx2("span", { children: sessionUsage.outputTokens.toLocaleString() })
547
+ ] }),
548
+ sessionUsage.reasoningTokens > 0 && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", color: colors.reasoningText }, children: [
549
+ /* @__PURE__ */ jsx2("span", { children: "\u{1F9E0} Thinking Tokens:" }),
550
+ /* @__PURE__ */ jsx2("span", { children: sessionUsage.reasoningTokens.toLocaleString() })
551
+ ] }),
552
+ sessionUsage.cachedTokens > 0 && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", color: "#10b981" }, children: [
553
+ /* @__PURE__ */ jsx2("span", { children: "\u26A1 Cached Tokens:" }),
554
+ /* @__PURE__ */ jsx2("span", { children: sessionUsage.cachedTokens.toLocaleString() })
555
+ ] }),
556
+ /* @__PURE__ */ jsxs(
557
+ "div",
558
+ {
559
+ style: {
560
+ display: "flex",
561
+ justifyContent: "space-between",
562
+ fontWeight: 600,
563
+ marginTop: "6px",
564
+ paddingTop: "6px",
565
+ borderTop: `1px solid ${colors.border}`
566
+ },
567
+ children: [
568
+ /* @__PURE__ */ jsx2("span", { children: "Session Cost:" }),
569
+ /* @__PURE__ */ jsxs("span", { children: [
570
+ "$",
571
+ sessionCost.totalUSD.toFixed(5),
572
+ " ",
573
+ sessionCost.currency
574
+ ] })
575
+ ]
576
+ }
577
+ )
578
+ ] })
579
+ ]
580
+ }
581
+ )
582
+ ]
583
+ }
584
+ );
585
+ };
586
+
587
+ // src/react/badge.tsx
588
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
589
+ var VibezSessionBadge = ({
590
+ showCost = true,
591
+ showTokens = true,
592
+ className,
593
+ style
594
+ }) => {
595
+ const { sessionUsage, sessionCost } = useVibezSession();
596
+ const formatTokens = (num) => {
597
+ if (num >= 1e6) return (num / 1e6).toFixed(1) + "M";
598
+ if (num >= 1e3) return (num / 1e3).toFixed(1) + "k";
599
+ return num.toString();
600
+ };
601
+ return /* @__PURE__ */ jsxs2(
602
+ "span",
603
+ {
604
+ className,
605
+ style: {
606
+ display: "inline-flex",
607
+ alignItems: "center",
608
+ gap: "5px",
609
+ padding: "3px 8px",
610
+ fontSize: "11px",
611
+ fontWeight: 500,
612
+ borderRadius: "9999px",
613
+ backgroundColor: "rgba(139, 92, 246, 0.1)",
614
+ color: "#8b5cf6",
615
+ border: "1px solid rgba(139, 92, 246, 0.2)",
616
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
617
+ ...style
618
+ },
619
+ children: [
620
+ /* @__PURE__ */ jsx3("span", { children: "\u26A1" }),
621
+ showTokens && /* @__PURE__ */ jsxs2("span", { children: [
622
+ formatTokens(sessionUsage.totalTokens),
623
+ " tok"
624
+ ] }),
625
+ showCost && /* @__PURE__ */ jsxs2("span", { children: [
626
+ "($",
627
+ sessionCost.totalUSD.toFixed(4),
628
+ ")"
629
+ ] })
630
+ ]
631
+ }
632
+ );
633
+ };
634
+ export {
635
+ VibezSessionBadge,
636
+ VibezSessionContext,
637
+ VibezSessionProvider,
638
+ VibezSessionWidget,
639
+ useVibez,
640
+ useVibezSession
641
+ };
642
+ //# sourceMappingURL=index.mjs.map