vibezcheck 0.5.7 → 0.5.9

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/README.md CHANGED
@@ -1,133 +1,148 @@
1
1
  # ✦ VibezCheck
2
2
 
3
- > **The 1-Line Token Meter & Real-Time Billing Engine for AI.**
4
- > Track tokens, compute real-time micro-costs, set profit margins, and bill customers with **0ms added latency** across Vercel AI SDK (v4, v5, v6, v7) and native LLM SDKs.
3
+ > **Track AI token spend and bill users in real time. Setup in 1 line.**
4
+ > No database needed. No added latency.
5
5
 
6
6
  [![npm version](https://img.shields.io/npm/v/vibezcheck.svg?color=cb3837)](https://npmjs.org/package/vibezcheck)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
8
8
  [![TypeScript](https://img.shields.io/badge/TypeScript-Strict-blue.svg)](https://www.typescriptlang.org/)
9
- [![Tests](https://img.shields.io/badge/Tests-94%20Passed-brightgreen.svg)]()
9
+ [![Tests](https://img.shields.io/badge/Tests-95%20Passed-brightgreen.svg)]()
10
10
  [![Latency](https://img.shields.io/badge/Latency-0ms%20Added-orange.svg)]()
11
11
 
12
12
  ---
13
13
 
14
- ### The 2-Line Promise
14
+ ### The 1-Line Setup
15
15
 
16
+ **1. On your server:** wrap your model to track spending and set a profit margin
16
17
  ```typescript
17
- // 1. Server: Wrap your model with billing & inject telemetry into stream
18
- const model = vibezcheck('openai/gpt-4o-mini', { customer: 'cus_alex', pricing: { margin: 1.3 } });
19
- return vibezcheck.toResponse(result);
18
+ const model = vibezcheck(openai('gpt-4o-mini'), { pricing: { margin: 1.3 } });
19
+ ```
20
20
 
21
- // 2. Client: Drop in zero-prop financial HUD & micro-receipts
22
- <VibezReceipt message={message} />
21
+ **2. On your frontend:** drop in the component to see spendings in real time
22
+ ```tsx
23
23
  <VibezCheck messages={messages} />
24
24
  ```
25
25
 
26
+ That’s it. You get real-time token tracking, live dollar costs, runaway loop protection, and a sleek spending HUD.
27
+
26
28
  ---
27
29
 
28
- ## ⚡ What's New in v0.5.6
30
+ ## What VibezCheck does for you
29
31
 
30
- * **🪄 Zero-Prop Client UIs**: `<VibezReceipt message={message} />` and `<VibezCheck messages={messages} />` auto-derive model slugs, exact tokens, dollar micro-costs, profit margins (`+30% Margin`), and latency straight from the telemetry stream. No manual `model`, `margin`, or `cost` props required.
31
- * **📡 Universal Stream Injector (`vibezcheck.toResponse`)**: Intercepts AI SDK stream completion chunks to attach verified telemetry (`data-vibezcheck` & `message-metadata` SSE for v5/v6/v7, or `2:[{...}]` annotations for v4) with **0ms TTFB overhead**.
32
- * **🛡️ Zero Context Window Pollution**: Telemetry travels out-of-band. When AI SDK's `convertToModelMessages(messages)` prepares future conversation turns, metadata parts are automatically omitted—keeping your LLM context pure and preventing runaway token loops.
33
- * **🎨 Scoped Zero-Config Styling**: Built-in inline fallback styles guarantee that receipts and HUD components look polished out-of-the-box, even if your Tailwind configuration ignores `node_modules`.
32
+ When you build an AI app, chatbot, or agent:
34
33
 
35
- ---
34
+ * **👀 See spending in real time**: You and your users can see the exact cost (e.g. `$0.0014`) and token count for every turn as it streams in.
35
+ * **🛡️ Never get a surprise $500 bill**: A built-in `$0.50` circuit breaker stops runaway prompts or infinite agent loops automatically before they drain your credit card.
36
+ * **💰 Turn costs into profit**: Add `pricing: { margin: 1.3 }` to mark up wholesale API prices by 30%. You make money on every message without writing custom billing code.
37
+ * **🤖 Works with multiple models**: If a conversation uses GPT-4o-mini, Claude 3.5, or Gemini, VibezCheck automatically breaks down the spending per model.
38
+ * **🆓 Zero database required**: Test locally on `localhost:3000` with zero database tables and zero Stripe keys. It runs straight in memory.
39
+ * **⚡ 0ms added latency**: Streaming is direct and transparent. Spending telemetry attaches cleanly at the very end of the stream without delaying first-token response time.
40
+ * **🧹 Clean context window**: Telemetry stays out of your prompts. When messages get sent back to the model on the next turn, telemetry is automatically stripped so you never waste tokens.
36
41
 
37
- ## 🚀 Key Features
42
+ ---
38
43
 
39
- * **⚡ 0ms Added Latency**: Direct transparent proxy stream; no external server redirects, no pre-buffering, and zero impact on first-token response time.
40
- * **🛡️ Built-in $0.50 Circuit Breaker**: Auto-trips if an agent or query exceeds the safety fuse box, preventing infinite loops and surprise $1,000 bills.
41
- * **🛟 In-Flight Abort Trapper**: Accurately meters and debits tokens even if the client closes their laptop lid or navigates away mid-stream.
42
- * **🪙 BigInt Nano-USD Precision**: Sub-cent financial math ($1 = $10^9$ Nano-USD) eliminating IEEE 754 floating-point drift.
43
- * **💰 1-Line Profit Margins**: Turn wholesale API costs into retail revenue with `pricing: { margin: 1.3 }` (+30% markup).
44
- * **🆓 Zero-DB Dev Mode**: Run locally on `localhost:3000` with NO database and NO Stripe keys required.
45
- * **💳 Pluggable SaaS Billing**: Credit wallets, top-ups, checkout sessions, customer portal, and user API keys (`vz_live_...`).
46
- * **🤖 Multi-Tool Agent Sessions**: Cumulative session budgets across multiple LLM steps, Python sandboxes, and web scrapers.
47
- * **🔄 100% Drop-In Polyfills**: Direct replacement for `@stripe/ai-sdk/meter`, `@stripe/ai-sdk/provider`, and `@stripe/token-meter`.
44
+ ## 🚀 End-to-End Chatbot Example (Next.js App Router)
48
45
 
49
- ---
46
+ Here is a complete, copy-paste ready AI chatbot with live per-message spending receipts and the floating financial HUD:
50
47
 
51
- ## 📦 Installation
48
+ ### 1. Install Dependencies
52
49
 
53
50
  ```bash
54
51
  npm install vibezcheck ai @ai-sdk/openai @ai-sdk/react stripe
55
52
  ```
56
53
 
57
- ---
58
-
59
- ## ⚡ 1-Minute Quickstart: Next.js App Router
60
-
61
- ### 1. Server Route (`app/api/chat/route.ts`)
62
-
63
- Wrap any model with `vibezcheck()`, and return the response using `vibezcheck.toResponse()`:
54
+ ### 2. Server Route (`app/api/chat/route.ts`)
64
55
 
65
56
  ```typescript
66
- import { streamText } from 'ai';
57
+ import { convertToModelMessages, streamText, UIMessage } from 'ai';
67
58
  import { openai } from '@ai-sdk/openai';
68
59
  import { vibezcheck } from 'vibezcheck';
69
60
 
70
61
  export const maxDuration = 30;
71
62
 
72
63
  export async function POST(req: Request) {
73
- const { messages } = await req.json();
64
+ const { messages }: { messages: UIMessage[] } = await req.json();
74
65
 
75
66
  const result = streamText({
76
- // Wrap any provider (OpenAI, Anthropic, Google, DeepSeek, etc.)
67
+ // ✦ 1 Line: track costs, add 30% profit margin, and set $0.50 runaway safety fuse
77
68
  model: vibezcheck(openai('gpt-4o-mini'), {
78
- customer: 'cus_alex', // Stripe customer ID or user email
79
- pricing: { margin: 1.3 }, // +30% profit margin
80
- maxCostPerCallUSD: 0.50, // Safety fuse box ($0.50 cap)
69
+ customer: 'user_alex@example.com', // User email or Stripe customer ID
70
+ pricing: { margin: 1.3 }, // +30% profit margin
71
+ maxCostPerCallUSD: 0.50, // Auto-stops if call exceeds $0.50
81
72
  }),
82
- messages,
73
+ instructions: 'You are a helpful AI assistant.',
74
+ messages: await convertToModelMessages(messages),
83
75
  });
84
76
 
85
- // ✦ Universal telemetry stream injector (works with v4, v5, v6, and v7)
77
+ // ✦ Transmits stream with verified spending telemetry attached
86
78
  return vibezcheck.toResponse(result);
87
79
  }
88
80
  ```
89
81
 
90
- ### 2. Frontend Client (`app/page.tsx`)
91
-
92
- Render message bubbles with `<VibezReceipt />` and float the aggregated `<VibezCheck />` HUD:
82
+ ### 3. Frontend Client (`app/page.tsx`)
93
83
 
94
84
  ```tsx
95
85
  'use client';
96
86
 
97
87
  import { useChat } from '@ai-sdk/react';
88
+ import { DefaultChatTransport } from 'ai';
98
89
  import { useState } from 'react';
99
90
  import { VibezReceipt, VibezCheck } from 'vibezcheck/ui';
100
91
 
101
92
  export default function ChatPage() {
102
93
  const [input, setInput] = useState('');
103
- const { messages, sendMessage } = useChat();
94
+ const { messages, sendMessage, status } = useChat({
95
+ transport: new DefaultChatTransport({
96
+ api: '/api/chat',
97
+ }),
98
+ });
104
99
 
105
100
  return (
106
- <main className="flex flex-col w-full max-w-lg py-20 mx-auto px-4 min-h-screen">
107
- <div className="flex-1 space-y-4 mb-24">
101
+ <div className="flex flex-col w-full max-w-lg py-20 mx-auto px-4 min-h-screen">
102
+ {/* Messages Stream */}
103
+ <div className="flex-1 space-y-4 mb-28">
108
104
  {messages.map((message) => (
109
- <div key={message.id} className="p-3 rounded-xl border border-zinc-200 dark:border-zinc-800">
110
- <div className="text-xs font-semibold uppercase tracking-wider text-zinc-400 mb-1">
105
+ <div
106
+ key={message.id}
107
+ className={`p-4 rounded-2xl border ${
108
+ message.role === 'user'
109
+ ? 'bg-zinc-100 dark:bg-zinc-800 border-zinc-200 dark:border-zinc-700 ml-10'
110
+ : 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 mr-10 shadow-sm'
111
+ }`}
112
+ >
113
+ <div className="text-xs font-semibold uppercase tracking-wider text-zinc-400 mb-1.5">
111
114
  {message.role === 'user' ? 'You' : 'Assistant'}
112
115
  </div>
113
116
 
114
- {/* Display message content */}
115
- <div className="text-sm whitespace-pre-wrap">
117
+ {/* Message Text */}
118
+ <div className="text-sm whitespace-pre-wrap leading-relaxed">
116
119
  {message.parts
117
- ? message.parts.map((part, i) => (part.type === 'text' ? part.text : null))
120
+ ? message.parts.map((part, index) => {
121
+ switch (part.type) {
122
+ case 'text':
123
+ return <span key={index}>{part.text}</span>;
124
+ default:
125
+ return null;
126
+ }
127
+ })
118
128
  : message.content}
119
129
  </div>
120
130
 
121
- {/* ✦ Zero-Prop Micro-Receipt: auto-derives tokens, micro-cost, model, & latency */}
131
+ {/* ✦ 1 Line: Micro-Receipt showing tokens, micro-cost, model, and latency */}
122
132
  {message.role === 'assistant' && (
123
- <div className="mt-2 flex justify-end">
133
+ <div className="mt-3 flex justify-end">
124
134
  <VibezReceipt message={message} />
125
135
  </div>
126
136
  )}
127
137
  </div>
128
138
  ))}
139
+
140
+ {status === 'streaming' && (
141
+ <div className="text-xs text-zinc-400 italic">Assistant is typing...</div>
142
+ )}
129
143
  </div>
130
144
 
145
+ {/* Input Form */}
131
146
  <form
132
147
  onSubmit={(e) => {
133
148
  e.preventDefault();
@@ -135,242 +150,89 @@ export default function ChatPage() {
135
150
  sendMessage({ text: input });
136
151
  setInput('');
137
152
  }}
138
- className="fixed bottom-0 left-0 right-0 p-4 bg-background/80 backdrop-blur-md"
153
+ className="fixed bottom-0 left-0 right-0 p-4 bg-white/80 dark:bg-zinc-950/80 backdrop-blur-md border-t border-zinc-200 dark:border-zinc-800"
139
154
  >
140
- <div className="max-w-lg mx-auto">
155
+ <div className="max-w-lg mx-auto flex gap-2">
141
156
  <input
142
- className="w-full p-3 rounded-lg border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 shadow-sm"
157
+ className="flex-1 p-3 text-sm rounded-xl border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 shadow-sm focus:outline-none focus:ring-2 focus:ring-zinc-900 dark:focus:ring-zinc-100"
143
158
  value={input}
144
- placeholder="Ask something..."
159
+ placeholder="Type your prompt..."
145
160
  onChange={(e) => setInput(e.target.value)}
146
161
  />
162
+ <button
163
+ type="submit"
164
+ disabled={status === 'streaming' || !input.trim()}
165
+ className="px-5 py-3 bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900 text-sm font-semibold rounded-xl hover:opacity-90 disabled:opacity-50 transition"
166
+ >
167
+ Send
168
+ </button>
147
169
  </div>
148
170
  </form>
149
171
 
150
- {/* ✦ Zero-Prop Financial HUD: aggregated conversation tokens, cost, & active model */}
172
+ {/* ✦ 1 Line: Floating HUD showing real-time spending and tokens */}
151
173
  <VibezCheck messages={messages} />
152
- </main>
174
+ </div>
153
175
  );
154
176
  }
155
177
  ```
156
178
 
157
- ---
158
-
159
- ## 🧩 Zero-Prop Client Components
160
-
161
- Import from either `vibezcheck/ui` or `vibezcheck/react`:
162
-
163
- ### 1. `<VibezReceipt />` (Per-Message Micro-Badge)
164
-
165
- Displays verified tokens, cost in USD, model slug, and latency under individual assistant messages.
166
-
167
- ```tsx
168
- <VibezReceipt message={message} />
169
- ```
170
-
171
- * **Zero Required Props**: Reads telemetry from `message.parts` (`data-vibezcheck`), `message.annotations`, and `message.metadata`.
172
- * **Variants**: `variant="pill"` (default), `variant="minimal"`, or `variant="card"`.
173
- * **Scoped Styling**: Ships with inline fallback styling so it never breaks even without Tailwind CSS.
174
-
175
- ### 2. `<VibezCheck />` (Global Conversation HUD)
176
-
177
- Floating pill and expandable popover showing real-time conversation metrics.
179
+ ### 4. Environment Variables (`.env.local`)
178
180
 
179
- ```tsx
180
- <VibezCheck messages={messages} />
181
+ ```env
182
+ OPENAI_API_KEY=sk-...
181
183
  ```
182
184
 
183
- * **Aggregated Metrics**: Automatically sums input, output, and reasoning tokens across all messages.
184
- * **Auto-Derived Model & Margin**: Displays the active model badge (e.g. `gpt-4o-mini`) and configured markup (e.g. `+30% Margin`).
185
- * **Optional Top-Up**: Pass `onTopUp={() => openBillingModal()}` to display an integrated credit top-up button.
186
-
187
185
  ---
188
186
 
189
- ## 🔄 Multi-Version Vercel AI SDK Compatibility
190
-
191
- `vibezcheck` provides seamless compatibility across every major generation of the Vercel AI SDK:
192
-
193
- ### AI SDK v5, v6 & v7 (UI Message Stream)
194
-
195
- ```typescript
196
- import { createUIMessageStreamResponse, toUIMessageStream, streamText } from 'ai';
197
- import { openai } from '@ai-sdk/openai';
198
- import { vibezcheck } from 'vibezcheck';
187
+ ## The UI Components (Zero Props Needed)
199
188
 
200
- export async function POST(req: Request) {
201
- const { messages } = await req.json();
189
+ Import from `vibezcheck/ui` or `vibezcheck/react`:
202
190
 
203
- const result = streamText({
204
- model: vibezcheck(openai('gpt-4o-mini'), { customer: 'cus_123' }),
205
- messages,
206
- });
191
+ ### 1. `<VibezCheck messages={messages} />`
207
192
 
208
- // Recommended: pass result directly
209
- return vibezcheck.toResponse(result);
193
+ A floating financial HUD and expandable card:
194
+ * **⇅ Unit Swap**: Click the `⇅` icon to switch between **Dollar Cost** (`$0.0028`) and **Tokens** (`1,420 tok`).
195
+ * **Session vs Turn**: Switch between `[Session]` (total conversation spend) and `[Latest Turn]` (last reply).
196
+ * **Multi-Model Breakdown**: If you use multiple models in one chat, it shows the exact split for each model.
197
+ * **Customer Privacy by Default**: End-users only see their billed cost. Your wholesale costs and profit margins are hidden by default.
210
198
 
211
- // Or wrap custom UI message stream responses:
212
- // return vibezcheck.toResponse(
213
- // createUIMessageStreamResponse({
214
- // stream: toUIMessageStream({ stream: result.stream }),
215
- // })
216
- // );
217
- }
218
- ```
219
-
220
- ### AI SDK v4 (Data Stream Protocol)
221
-
222
- ```typescript
223
- import { streamText } from 'ai';
224
- import { openai } from '@ai-sdk/openai';
225
- import { vibezcheck } from 'vibezcheck';
226
-
227
- export async function POST(req: Request) {
228
- const { messages } = await req.json();
229
-
230
- const result = streamText({
231
- model: vibezcheck(openai('gpt-4o'), { customer: 'cus_123' }),
232
- messages,
233
- });
234
-
235
- // Automatically emits 2:[{"type":"vibezcheck", ...}] data stream annotations
236
- return vibezcheck.toResponse(result);
237
- }
238
- ```
239
-
240
- ---
241
-
242
- ## 🛡️ Context Window Hygiene: How It Works
243
-
244
- A frequent hazard in LLM streaming is "telemetry leakage"—where usage data sent to the client gets accidentally included in subsequent conversation turns, causing runaway context growth and unnecessary token costs.
245
-
246
- VibezCheck prevents this by design:
247
- 1. **Server Injection**: `vibezcheck.toResponse` injects telemetry out-of-band right before stream completion (`data-vibezcheck` and `message-metadata` SSE events).
248
- 2. **Client Ingestion**: `<VibezReceipt />` and `<VibezCheck />` extract telemetry from message parts without mutating textual content.
249
- 3. **Next Request**: When `convertToModelMessages(messages)` runs on subsequent requests, the AI SDK automatically discards transient metadata and data parts. **Zero telemetry tokens are sent to the LLM.**
250
-
251
- ---
252
-
253
- ## 💳 Commercial SaaS Billing
254
-
255
- ### 1. Stripe Top-Up Sessions (`BillingHelper`)
256
-
257
- Allow users to purchase pre-paid AI credits with Stripe Checkout:
258
-
259
- ```typescript
260
- import { BillingHelper } from 'vibezcheck';
261
-
262
- const billing = new BillingHelper({ apiKey: process.env.STRIPE_SECRET_KEY });
263
-
264
- export async function POST(req: Request) {
265
- const { customerId } = await req.json();
266
-
267
- const checkoutUrl = await billing.createTopUpSession({
268
- customerId,
269
- amountCents: 2000, // $20.00
270
- returnUrl: 'https://myapp.com/dashboard',
271
- });
272
-
273
- return Response.json({ url: checkoutUrl });
274
- }
275
- ```
276
-
277
- ### 2. Customer API Keys (`ApiKeyAuth`)
278
-
279
- Issue customer API keys (`vz_live_...`) backed by Stripe customer metadata—zero database required:
280
-
281
- ```typescript
282
- import { ApiKeyAuth } from 'vibezcheck';
283
- import Stripe from 'stripe';
284
-
285
- const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
286
- const auth = new ApiKeyAuth(stripe);
287
-
288
- // 1. Generate key for customer
289
- const { apiKey } = await auth.createKey({
290
- customerId: 'cus_123',
291
- name: 'Production Key',
292
- });
293
- // => "vz_live_9f83b2..."
294
-
295
- // 2. Authenticate API requests in middleware
296
- export async function middleware(req: Request) {
297
- const token = req.headers.get('Authorization')?.replace('Bearer ', '');
298
- const verification = await auth.verifyKey(token);
299
-
300
- if (!verification.valid) {
301
- return new Response('Unauthorized', { status: 401 });
302
- }
303
-
304
- // verification.customerId is verified against Stripe!
305
- }
199
+ ```tsx
200
+ <VibezCheck
201
+ messages={messages}
202
+ remainingBalanceUSD={10.00}
203
+ onTopUp={(amount) => console.log('User wants to top up credits:', amount)}
204
+ />
306
205
  ```
307
206
 
308
- ### 3. Multi-Tool Agent Sessions (`AgentSession`)
309
-
310
- Set a hard $1.00 session budget across multiple LLM steps and external tools:
207
+ ### 2. `<VibezReceipt message={message} />`
311
208
 
312
- ```typescript
313
- import { AgentSession, wrapTool } from 'vibezcheck';
314
- import { openai } from '@ai-sdk/openai';
315
-
316
- const session = new AgentSession({
317
- customer: 'cus_agent_user',
318
- sessionBudgetUSD: 1.00, // Hard ceiling for entire session
319
- });
320
-
321
- // Wrap external tools with financial tracking
322
- const webSearchTool = wrapTool({
323
- name: 'web_search',
324
- costUSD: 0.01,
325
- execute: async ({ query }) => fetchSearch(query),
326
- });
327
-
328
- // Run LLM model bound to this session
329
- const sessionModel = session.model(openai('gpt-4o'));
209
+ A small, elegant badge under each assistant message:
210
+ ```tsx
211
+ <VibezReceipt message={message} />
212
+ // Renders: ✦ $0.0001 · 31 tok · gpt-4o-mini
330
213
  ```
331
214
 
332
215
  ---
333
216
 
334
- ## 🔄 100% Drop-In Compatibility with `@stripe/ai-sdk`
335
-
336
- If you are migrating from `@stripe/ai-sdk` or `@stripe/token-meter`, swap your imports:
217
+ ## Multi-Model Sessions (Automatic Breakdown)
337
218
 
338
- ```typescript
339
- // Replace: import { meteredModel } from '@stripe/ai-sdk/meter';
340
- import { meteredModel } from 'vibezcheck/stripe/meter';
219
+ If your app routes between different models (e.g. `gpt-4o-mini` for quick chat and `claude-3-5-sonnet` for coding):
341
220
 
342
- // Replace: import { stripe } from '@stripe/ai-sdk/provider';
343
- import { stripe } from 'vibezcheck/stripe/provider';
221
+ VibezCheck automatically detects every model used and lists them in the HUD:
222
+ * `gpt-4o-mini (1 turn)`: 31 tok · $0.0001
223
+ * `claude-3-5-sonnet (1 turn)`: 420 tok · $0.0068
344
224
 
345
- // Replace: import { createTokenMeter } from '@stripe/token-meter';
346
- import { createTokenMeter } from 'vibezcheck/stripe/token-meter';
347
- ```
225
+ Click any model to see its specific spending.
348
226
 
349
227
  ---
350
228
 
351
- ## 🛡️ Route Auditor CLI
352
-
353
- Audit your codebase to detect unmetered AI endpoints before shipping to production:
354
-
355
- ```bash
356
- npx vibezcheck audit
357
- ```
358
-
359
- ### CI/CD Mode
360
- Fail the build if unmetered AI routes are detected:
361
- ```bash
362
- npx vibezcheck audit --ci
363
- ```
364
-
365
- ---
229
+ ## Need Stripe Billing? (Optional)
366
230
 
367
- ## 📂 Examples
231
+ When you want to charge real money, VibezCheck has built-in Stripe helpers:
368
232
 
369
- * **[Next.js App Router + OpenAI](examples/nextjs-app-router-openai)**: Modern AI SDK App Router implementation with 1-line token metering and `<VibezCheck />`.
370
- * **[Next.js 15 AI SaaS Starter](examples/nextjs-saas-starter)**: Complete SaaS template with Stripe Checkout, Top-Up Modal, and `<VibezReceipt />`.
371
- * **[Local Cost Meter](examples/01-local-cost-meter.ts)**: Offline micro-transaction calculations with BigInt Nano-USD precision.
372
- * **[Native OpenAI Streaming](examples/03-native-openai-stream.ts)**: Zero-latency stream wrapper for the official `openai` Node SDK.
373
- * **[Claude 3.7 Reasoning Tokens](examples/04-claude-thinking.ts)**: Tracking hidden thought tokens with Anthropic SDK.
233
+ * **Prepaid Credits**: Let users buy credit balance with Stripe Checkout (`BillingHelper.createTopUpSession`).
234
+ * **Customer API Keys**: Issue `vz_live_...` keys saved in Stripe customer metadata (`ApiKeyAuth`).
235
+ * **Agent Session Ceilings**: Limit a multi-step agent to a hard $1.00 budget with `AgentSession`.
374
236
 
375
237
  ---
376
238
 
@@ -214,28 +214,19 @@ interface VibezReceiptProps {
214
214
  }
215
215
  declare const VibezReceipt: React__default.FC<VibezReceiptProps>;
216
216
 
217
- interface VibezBillingNotice {
218
- status?: 'requires_payment' | 'limit_reached' | 'upgrade_required';
219
- customerId?: string;
220
- customerEmail?: string;
221
- checkoutUrl?: string;
222
- tokensUsed?: number;
223
- costUSD?: number;
224
- message?: string;
225
- }
226
- interface VibezBillingModalProps {
227
- notice?: VibezBillingNotice | null;
228
- isOpen?: boolean;
229
- onClose?: () => void;
230
- onSuccess?: () => void;
231
- theme?: 'light' | 'dark';
232
- testMode?: boolean;
217
+ interface ModelUsageDetail {
218
+ model: string;
219
+ displayName: string;
220
+ tokens: number;
221
+ promptTokens: number;
222
+ completionTokens: number;
223
+ reasoningTokens: number;
224
+ cachedTokens: number;
225
+ billedUSD: number;
226
+ wholesaleUSD: number;
227
+ profitUSD: number;
228
+ turns: number;
233
229
  }
234
- /**
235
- * Intuitive React Modal for Stripe Top-Up, Card Registration & Paywall
236
- */
237
- declare const VibezBillingModal: React__default.FC<VibezBillingModalProps>;
238
-
239
230
  interface VibezCheckProps {
240
231
  /** Messages array from AI SDK useChat() — automatically aggregates tokens & costs */
241
232
  messages?: any[];
@@ -280,6 +271,7 @@ interface VibezCheckProps {
280
271
  profitUSD: number;
281
272
  totalTokens: number;
282
273
  isDevMode: boolean;
274
+ byModel?: Record<string, ModelUsageDetail>;
283
275
  }) => void;
284
276
  /** Whether popover is initially open (default: false) */
285
277
  defaultOpen?: boolean;
@@ -289,6 +281,8 @@ interface VibezCheckProps {
289
281
  *
290
282
  * An ultra-modern, interactive fintech AI financial HUD inspired by Aztec Web3 design.
291
283
  * Features:
284
+ * - Precise token accounting with zero double counting (server telemetry is authoritative)
285
+ * - Multi-model session breakdown (details and distributions across models)
292
286
  * - Huge hero typography with interactive USD ⇄ Token unit toggle (⇅)
293
287
  * - Segmented Session ⇄ Latest Turn pill switcher
294
288
  * - Interactive preset pills ([$5] [$10] [$25] [Max])
@@ -298,4 +292,4 @@ interface VibezCheckProps {
298
292
  declare function VibezCheck({ messages, events, model, margin, showWholesale, showMargin, totalCostUSD: manualCost, totalTokens: manualTokens, remainingBalanceUSD, position, theme, devMode, className, title, onTopUp, onCostUpdate, defaultOpen, }: VibezCheckProps): React__default.JSX.Element;
299
293
  declare const VibezPill: typeof VibezCheck;
300
294
 
301
- export { type CustomStorageAdapter, type SessionPersistenceMode, type SessionState, type SessionTurnRecord, type UseVibezChatOptions, VibezBillingModal, type VibezBillingModalProps, type VibezBillingNotice, type VibezChatMessage, VibezCheck, type VibezCheckProps, VibezPill, VibezReceipt, type VibezReceiptProps, VibezSessionBadge, type VibezSessionBadgeProps, VibezSessionContext, type VibezSessionContextValue, VibezSessionProvider, type VibezSessionProviderProps, VibezSessionWidget, type VibezSessionWidgetProps, useVibez, useVibezChat, useVibezSession };
295
+ export { type CustomStorageAdapter, type ModelUsageDetail, type SessionPersistenceMode, type SessionState, type SessionTurnRecord, type UseVibezChatOptions, type VibezChatMessage, VibezCheck, type VibezCheckProps, VibezPill, VibezReceipt, type VibezReceiptProps, VibezSessionBadge, type VibezSessionBadgeProps, VibezSessionContext, type VibezSessionContextValue, VibezSessionProvider, type VibezSessionProviderProps, VibezSessionWidget, type VibezSessionWidgetProps, useVibez, useVibezChat, useVibezSession };
@@ -214,28 +214,19 @@ interface VibezReceiptProps {
214
214
  }
215
215
  declare const VibezReceipt: React__default.FC<VibezReceiptProps>;
216
216
 
217
- interface VibezBillingNotice {
218
- status?: 'requires_payment' | 'limit_reached' | 'upgrade_required';
219
- customerId?: string;
220
- customerEmail?: string;
221
- checkoutUrl?: string;
222
- tokensUsed?: number;
223
- costUSD?: number;
224
- message?: string;
225
- }
226
- interface VibezBillingModalProps {
227
- notice?: VibezBillingNotice | null;
228
- isOpen?: boolean;
229
- onClose?: () => void;
230
- onSuccess?: () => void;
231
- theme?: 'light' | 'dark';
232
- testMode?: boolean;
217
+ interface ModelUsageDetail {
218
+ model: string;
219
+ displayName: string;
220
+ tokens: number;
221
+ promptTokens: number;
222
+ completionTokens: number;
223
+ reasoningTokens: number;
224
+ cachedTokens: number;
225
+ billedUSD: number;
226
+ wholesaleUSD: number;
227
+ profitUSD: number;
228
+ turns: number;
233
229
  }
234
- /**
235
- * Intuitive React Modal for Stripe Top-Up, Card Registration & Paywall
236
- */
237
- declare const VibezBillingModal: React__default.FC<VibezBillingModalProps>;
238
-
239
230
  interface VibezCheckProps {
240
231
  /** Messages array from AI SDK useChat() — automatically aggregates tokens & costs */
241
232
  messages?: any[];
@@ -280,6 +271,7 @@ interface VibezCheckProps {
280
271
  profitUSD: number;
281
272
  totalTokens: number;
282
273
  isDevMode: boolean;
274
+ byModel?: Record<string, ModelUsageDetail>;
283
275
  }) => void;
284
276
  /** Whether popover is initially open (default: false) */
285
277
  defaultOpen?: boolean;
@@ -289,6 +281,8 @@ interface VibezCheckProps {
289
281
  *
290
282
  * An ultra-modern, interactive fintech AI financial HUD inspired by Aztec Web3 design.
291
283
  * Features:
284
+ * - Precise token accounting with zero double counting (server telemetry is authoritative)
285
+ * - Multi-model session breakdown (details and distributions across models)
292
286
  * - Huge hero typography with interactive USD ⇄ Token unit toggle (⇅)
293
287
  * - Segmented Session ⇄ Latest Turn pill switcher
294
288
  * - Interactive preset pills ([$5] [$10] [$25] [Max])
@@ -298,4 +292,4 @@ interface VibezCheckProps {
298
292
  declare function VibezCheck({ messages, events, model, margin, showWholesale, showMargin, totalCostUSD: manualCost, totalTokens: manualTokens, remainingBalanceUSD, position, theme, devMode, className, title, onTopUp, onCostUpdate, defaultOpen, }: VibezCheckProps): React__default.JSX.Element;
299
293
  declare const VibezPill: typeof VibezCheck;
300
294
 
301
- export { type CustomStorageAdapter, type SessionPersistenceMode, type SessionState, type SessionTurnRecord, type UseVibezChatOptions, VibezBillingModal, type VibezBillingModalProps, type VibezBillingNotice, type VibezChatMessage, VibezCheck, type VibezCheckProps, VibezPill, VibezReceipt, type VibezReceiptProps, VibezSessionBadge, type VibezSessionBadgeProps, VibezSessionContext, type VibezSessionContextValue, VibezSessionProvider, type VibezSessionProviderProps, VibezSessionWidget, type VibezSessionWidgetProps, useVibez, useVibezChat, useVibezSession };
295
+ export { type CustomStorageAdapter, type ModelUsageDetail, type SessionPersistenceMode, type SessionState, type SessionTurnRecord, type UseVibezChatOptions, type VibezChatMessage, VibezCheck, type VibezCheckProps, VibezPill, VibezReceipt, type VibezReceiptProps, VibezSessionBadge, type VibezSessionBadgeProps, VibezSessionContext, type VibezSessionContextValue, VibezSessionProvider, type VibezSessionProviderProps, VibezSessionWidget, type VibezSessionWidgetProps, useVibez, useVibezChat, useVibezSession };