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 +116 -254
- package/dist/react/index.d.mts +16 -22
- package/dist/react/index.d.ts +16 -22
- package/dist/react/index.js +338 -275
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +335 -271
- package/dist/react/index.mjs.map +1 -1
- package/examples/nextjs-app-router-openai/package.json +1 -1
- package/package.json +1 -8
package/README.md
CHANGED
|
@@ -1,133 +1,148 @@
|
|
|
1
1
|
# ✦ VibezCheck
|
|
2
2
|
|
|
3
|
-
> **
|
|
4
|
-
>
|
|
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
|
[](https://npmjs.org/package/vibezcheck)
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
[](https://www.typescriptlang.org/)
|
|
9
|
-
[]()
|
|
10
10
|
[]()
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
### The
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
return vibezcheck.toResponse(result);
|
|
18
|
+
const model = vibezcheck(openai('gpt-4o-mini'), { pricing: { margin: 1.3 } });
|
|
19
|
+
```
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
##
|
|
30
|
+
## What VibezCheck does for you
|
|
29
31
|
|
|
30
|
-
|
|
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
|
-
|
|
42
|
+
---
|
|
38
43
|
|
|
39
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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: '
|
|
79
|
-
pricing: { margin: 1.3 },
|
|
80
|
-
maxCostPerCallUSD: 0.50,
|
|
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
|
-
|
|
73
|
+
instructions: 'You are a helpful AI assistant.',
|
|
74
|
+
messages: await convertToModelMessages(messages),
|
|
83
75
|
});
|
|
84
76
|
|
|
85
|
-
// ✦
|
|
77
|
+
// ✦ Transmits stream with verified spending telemetry attached
|
|
86
78
|
return vibezcheck.toResponse(result);
|
|
87
79
|
}
|
|
88
80
|
```
|
|
89
81
|
|
|
90
|
-
###
|
|
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
|
-
<
|
|
107
|
-
|
|
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
|
|
110
|
-
|
|
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
|
-
{/*
|
|
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,
|
|
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
|
-
{/* ✦
|
|
131
|
+
{/* ✦ 1 Line: Micro-Receipt showing tokens, micro-cost, model, and latency */}
|
|
122
132
|
{message.role === 'assistant' && (
|
|
123
|
-
<div className="mt-
|
|
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-
|
|
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="
|
|
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="
|
|
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
|
-
{/* ✦
|
|
172
|
+
{/* ✦ 1 Line: Floating HUD showing real-time spending and tokens */}
|
|
151
173
|
<VibezCheck messages={messages} />
|
|
152
|
-
</
|
|
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
|
-
```
|
|
180
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
201
|
-
const { messages } = await req.json();
|
|
189
|
+
Import from `vibezcheck/ui` or `vibezcheck/react`:
|
|
202
190
|
|
|
203
|
-
|
|
204
|
-
model: vibezcheck(openai('gpt-4o-mini'), { customer: 'cus_123' }),
|
|
205
|
-
messages,
|
|
206
|
-
});
|
|
191
|
+
### 1. `<VibezCheck messages={messages} />`
|
|
207
192
|
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
###
|
|
309
|
-
|
|
310
|
-
Set a hard $1.00 session budget across multiple LLM steps and external tools:
|
|
207
|
+
### 2. `<VibezReceipt message={message} />`
|
|
311
208
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
343
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
231
|
+
When you want to charge real money, VibezCheck has built-in Stripe helpers:
|
|
368
232
|
|
|
369
|
-
* **
|
|
370
|
-
* **
|
|
371
|
-
* **
|
|
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
|
|
package/dist/react/index.d.mts
CHANGED
|
@@ -214,28 +214,19 @@ interface VibezReceiptProps {
|
|
|
214
214
|
}
|
|
215
215
|
declare const VibezReceipt: React__default.FC<VibezReceiptProps>;
|
|
216
216
|
|
|
217
|
-
interface
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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,
|
|
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 };
|
package/dist/react/index.d.ts
CHANGED
|
@@ -214,28 +214,19 @@ interface VibezReceiptProps {
|
|
|
214
214
|
}
|
|
215
215
|
declare const VibezReceipt: React__default.FC<VibezReceiptProps>;
|
|
216
216
|
|
|
217
|
-
interface
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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,
|
|
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 };
|