vibezcheck 0.5.9 → 0.5.10
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 +269 -146
- package/dist/ai-sdk/index.d.mts +106 -26
- package/dist/ai-sdk/index.d.ts +106 -26
- package/dist/ai-sdk/index.js +500 -189
- package/dist/ai-sdk/index.js.map +1 -1
- package/dist/ai-sdk/index.mjs +497 -179
- package/dist/ai-sdk/index.mjs.map +1 -1
- package/dist/ai-sdk/middleware.d.mts +3 -4
- package/dist/ai-sdk/middleware.d.ts +3 -4
- package/dist/ai-sdk/middleware.js +110 -136
- package/dist/ai-sdk/middleware.js.map +1 -1
- package/dist/ai-sdk/middleware.mjs +110 -126
- package/dist/ai-sdk/middleware.mjs.map +1 -1
- package/dist/billing/index.d.mts +128 -123
- package/dist/billing/index.d.ts +128 -123
- package/dist/billing/index.js +319 -234
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/index.mjs +315 -232
- package/dist/billing/index.mjs.map +1 -1
- package/dist/cli/index.js +24 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +24 -10
- package/dist/cli/index.mjs.map +1 -1
- package/dist/{client-CbO6vLUe.d.ts → client-eXSwD_kI.d.ts} +2 -3
- package/dist/{client-BzwEHQlC.d.mts → client-ttJwYM7x.d.mts} +2 -3
- package/dist/customers/index.d.mts +2 -63
- package/dist/customers/index.d.ts +2 -63
- package/dist/customers/index.js +0 -176
- package/dist/customers/index.js.map +1 -1
- package/dist/customers/index.mjs +0 -163
- package/dist/customers/index.mjs.map +1 -1
- package/dist/database/index.d.mts +79 -0
- package/dist/database/index.d.ts +79 -0
- package/dist/database/index.js +160 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/index.mjs +128 -0
- package/dist/database/index.mjs.map +1 -0
- package/dist/index.d.mts +38 -35
- package/dist/index.d.ts +38 -35
- package/dist/index.js +1110 -987
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1085 -973
- package/dist/index.mjs.map +1 -1
- package/dist/meter/index.d.mts +11 -11
- package/dist/meter/index.d.ts +11 -11
- package/dist/meter/index.js +93 -94
- package/dist/meter/index.js.map +1 -1
- package/dist/meter/index.mjs +92 -84
- package/dist/meter/index.mjs.map +1 -1
- package/dist/pricing/index.d.mts +116 -3
- package/dist/pricing/index.d.ts +116 -3
- package/dist/pricing/index.js +303 -4
- package/dist/pricing/index.js.map +1 -1
- package/dist/pricing/index.mjs +291 -3
- package/dist/pricing/index.mjs.map +1 -1
- package/dist/react/index.d.mts +133 -217
- package/dist/react/index.d.ts +133 -217
- package/dist/react/index.js +797 -1198
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +791 -1191
- package/dist/react/index.mjs.map +1 -1
- package/dist/session-CUnv_muf.d.ts +84 -0
- package/dist/session-D9fdP255.d.mts +84 -0
- package/dist/{types-Btf2OhIr.d.mts → types-DHlsaLvI.d.mts} +8 -42
- package/dist/{types-Btf2OhIr.d.ts → types-DHlsaLvI.d.ts} +8 -42
- package/dist/{with-billing-D7QRoNHM.d.ts → with-billing-CVGxl3ot.d.ts} +6 -8
- package/dist/{with-billing-BEqiJtCR.d.mts → with-billing-DhHGWCAp.d.mts} +6 -8
- package/examples/nextjs-app-router-openai/package.json +1 -1
- package/examples/nextjs-saas-starter/app/page.tsx +3 -3
- package/examples/nextjs-saas-starter/package.json +1 -1
- package/manifest/pricing-v1.json +10014 -0
- package/package.json +10 -31
- package/dist/auth/index.d.mts +0 -59
- package/dist/auth/index.d.ts +0 -59
- package/dist/auth/index.js +0 -129
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/index.mjs +0 -90
- package/dist/auth/index.mjs.map +0 -1
- package/dist/compat/stripe-meter.d.mts +0 -21
- package/dist/compat/stripe-meter.d.ts +0 -21
- package/dist/compat/stripe-meter.js +0 -1588
- package/dist/compat/stripe-meter.js.map +0 -1
- package/dist/compat/stripe-meter.mjs +0 -1551
- package/dist/compat/stripe-meter.mjs.map +0 -1
- package/dist/compat/stripe-provider.d.mts +0 -34
- package/dist/compat/stripe-provider.d.ts +0 -34
- package/dist/compat/stripe-provider.js +0 -1898
- package/dist/compat/stripe-provider.js.map +0 -1
- package/dist/compat/stripe-provider.mjs +0 -1865
- package/dist/compat/stripe-provider.mjs.map +0 -1
- package/dist/compat/token-meter.d.mts +0 -28
- package/dist/compat/token-meter.d.ts +0 -28
- package/dist/compat/token-meter.js +0 -1405
- package/dist/compat/token-meter.js.map +0 -1
- package/dist/compat/token-meter.mjs +0 -1368
- package/dist/compat/token-meter.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,58 +1,289 @@
|
|
|
1
1
|
# ✦ VibezCheck
|
|
2
2
|
|
|
3
|
-
> **Track AI token spend and bill users in real time. Setup in 1 line.**
|
|
4
|
-
>
|
|
3
|
+
> **Track AI token spend, protect agent loops, and bill users in real time. Setup in 1 line.**
|
|
4
|
+
> Zero external dependencies (`dependencies: {}`). 0ms added latency. Works completely offline.
|
|
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
|
|
|
14
|
-
|
|
15
|
+
## ⚡ The 1-Line Setup
|
|
15
16
|
|
|
16
|
-
**1. On your server:** wrap
|
|
17
|
+
**1. On your server:** wrap any model to track spending, add profit margin, and set safety fuses:
|
|
17
18
|
```typescript
|
|
18
|
-
|
|
19
|
+
import { openai } from '@ai-sdk/openai';
|
|
20
|
+
import { vibezcheck } from 'vibezcheck';
|
|
21
|
+
|
|
22
|
+
const model = vibezcheck(openai('gpt-4o-mini'), {
|
|
23
|
+
customer: 'usr_123',
|
|
24
|
+
pricing: { margin: 1.3 }, // +30% profit margin
|
|
25
|
+
maxCostPerCallUSD: 0.50, // Auto-stops runaway calls at $0.50
|
|
26
|
+
});
|
|
19
27
|
```
|
|
20
28
|
|
|
21
|
-
**2. On your frontend:** drop in the component to
|
|
29
|
+
**2. On your frontend:** drop in the HUD component to display real-time usage:
|
|
22
30
|
```tsx
|
|
31
|
+
import { VibezCheck } from 'vibezcheck/ui';
|
|
32
|
+
|
|
23
33
|
<VibezCheck messages={messages} />
|
|
24
34
|
```
|
|
25
35
|
|
|
26
|
-
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 📦 Features & Simplest Usage Examples
|
|
39
|
+
|
|
40
|
+
### 1. 1-Line Model Metering (Vercel AI SDK)
|
|
41
|
+
Wrap existing provider models or use declarative string model identifiers with 0ms added latency:
|
|
42
|
+
```typescript
|
|
43
|
+
import { generateText, streamText } from 'ai';
|
|
44
|
+
import { openai } from '@ai-sdk/openai';
|
|
45
|
+
import { vibezcheck } from 'vibezcheck';
|
|
46
|
+
|
|
47
|
+
// Option A: Wrap an existing provider instance
|
|
48
|
+
const result = streamText({
|
|
49
|
+
model: vibezcheck(openai('gpt-4o-mini')),
|
|
50
|
+
prompt: 'Summarize quantum computing in 3 sentences.',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Option B: Declarative string model identifier
|
|
54
|
+
const { text } = await generateText({
|
|
55
|
+
model: vibezcheck('openai/gpt-4o-mini'),
|
|
56
|
+
prompt: 'Explain general relativity.',
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
### 2. Customer Identification & Session Metadata
|
|
63
|
+
Attach user IDs, agent threads, and custom billing tags without extra database lookups:
|
|
64
|
+
```typescript
|
|
65
|
+
const model = vibezcheck(openai('gpt-4o-mini'), {
|
|
66
|
+
customer: 'user_alex@example.com', // User ID, email, or Stripe Customer ID
|
|
67
|
+
threadId: 'agent_thread_4920', // Conversation or workflow thread ID
|
|
68
|
+
metadata: { plan: 'pro', team: 'ai-ops' },
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### 3. Monetization & Profit Margins (Markups)
|
|
75
|
+
Turn wholesale LLM expenses into profitable revenue with automatic markups:
|
|
76
|
+
```typescript
|
|
77
|
+
const model = vibezcheck(openai('gpt-4o-mini'), {
|
|
78
|
+
pricing: {
|
|
79
|
+
margin: 1.25, // 25% profit margin applied to billed cost
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### 4. Circuit Breakers (Runaway Loop & Cost Protection)
|
|
87
|
+
Prevent infinite agent loops and accidental multi-hundred-dollar API bills with pre-flight and in-flight circuit breakers:
|
|
88
|
+
```typescript
|
|
89
|
+
const model = vibezcheck(openai('gpt-4o-mini'), {
|
|
90
|
+
maxCostPerCallUSD: 0.25, // Auto-terminates if call exceeds $0.25
|
|
91
|
+
maxTokensPerCall: 4000, // Auto-terminates if prompt + completion exceeds 4,000 tokens
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### 5. Floating React Spending HUD (`<VibezCheck />`)
|
|
98
|
+
A zero-prop floating financial HUD and expandable card that displays real-time tokens and costs directly from your `useChat()` messages array:
|
|
99
|
+
```tsx
|
|
100
|
+
'use client';
|
|
101
|
+
|
|
102
|
+
import { useChat } from '@ai-sdk/react';
|
|
103
|
+
import { VibezCheck } from 'vibezcheck/ui'; // or 'vibezcheck/react'
|
|
104
|
+
|
|
105
|
+
export default function ChatView() {
|
|
106
|
+
const { messages } = useChat();
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<div>
|
|
110
|
+
{/* Your chat UI */}
|
|
111
|
+
<VibezCheck messages={messages} />
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
* **⇅ Unit Swap**: Click to toggle between **Dollar Cost** (`$0.0028`) and **Tokens** (`1,420 tok`).
|
|
117
|
+
* **Multi-Model Breakdown**: Automatically displays per-model spend splits when conversations route across multiple models.
|
|
118
|
+
* **Customer Privacy by Default**: Wholesale developer costs and margin formulas remain private unless explicitly enabled.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
### 6. Per-Message Turn Micro-Receipt (`<VibezReceipt />`)
|
|
123
|
+
Display an elegant micro-badge showing token count, cost, model, and latency below each assistant message:
|
|
124
|
+
```tsx
|
|
125
|
+
import { VibezReceipt } from 'vibezcheck/ui';
|
|
126
|
+
|
|
127
|
+
// Inside your assistant message bubble
|
|
128
|
+
{message.role === 'assistant' && (
|
|
129
|
+
<div className="flex justify-end mt-2">
|
|
130
|
+
<VibezReceipt message={message} />
|
|
131
|
+
</div>
|
|
132
|
+
)}
|
|
133
|
+
// Renders: ✦ $0.0001 · 31 tok · gpt-4o-mini
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### 7. Supabase Database Sink
|
|
139
|
+
Persist usage records directly into your Supabase database in the background without slowing down the inference stream:
|
|
140
|
+
```typescript
|
|
141
|
+
import { createClient } from '@supabase/supabase-js';
|
|
142
|
+
import { openai } from '@ai-sdk/openai';
|
|
143
|
+
import { vibezcheck } from 'vibezcheck';
|
|
144
|
+
|
|
145
|
+
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_KEY!);
|
|
146
|
+
|
|
147
|
+
const model = vibezcheck(openai('gpt-4o-mini'), {
|
|
148
|
+
customer: 'usr_alex',
|
|
149
|
+
database: vibezcheck.supabase(supabase), // Inserts to default 'vibez_usage' table
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### 8. Extensible DIY Database Adapter (Drizzle, Kysely, MongoDB, ClickHouse)
|
|
156
|
+
Plug in any custom database, ORM, or logging service with a simple 1-line callback:
|
|
157
|
+
```typescript
|
|
158
|
+
import { openai } from '@ai-sdk/openai';
|
|
159
|
+
import { vibezcheck } from 'vibezcheck';
|
|
160
|
+
|
|
161
|
+
const model = vibezcheck(openai('gpt-4o-mini'), {
|
|
162
|
+
customer: 'usr_alex',
|
|
163
|
+
database: vibezcheck.database(async (event) => {
|
|
164
|
+
// Custom sink: Drizzle, Kysely, Mongo, Prisma, or custom webhook
|
|
165
|
+
await db.insert(usageEvents).values({
|
|
166
|
+
customerId: event.customerId,
|
|
167
|
+
model: event.model,
|
|
168
|
+
tokens: event.usage.totalTokens,
|
|
169
|
+
costUSD: event.cost.totalUSD,
|
|
170
|
+
});
|
|
171
|
+
}),
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### 9. Metronome Usage-Based Billing Ingestion
|
|
178
|
+
Directly stream usage records to Metronome's `/v1/ingest` API using native zero-dependency HTTP requests:
|
|
179
|
+
```typescript
|
|
180
|
+
import { openai } from '@ai-sdk/openai';
|
|
181
|
+
import { vibezcheck } from 'vibezcheck';
|
|
182
|
+
|
|
183
|
+
const model = vibezcheck(openai('gpt-4o-mini'), {
|
|
184
|
+
customer: 'cust_metronome_456',
|
|
185
|
+
database: vibezcheck.metronome({
|
|
186
|
+
apiKey: process.env.METRONOME_API_KEY!,
|
|
187
|
+
}),
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
### 10. Offline Pricing Engine & Dynamic Rate Sync
|
|
194
|
+
Compute token costs synchronously in 0ms using bundled offline catalogs (700+ models) or optionally sync dynamic upstream rates:
|
|
195
|
+
```typescript
|
|
196
|
+
import { vibezcheck } from 'vibezcheck';
|
|
197
|
+
|
|
198
|
+
// Synchronous 0ms offline calculation (works without internet)
|
|
199
|
+
const rates = vibezcheck.getModelPricing('gpt-4o-mini');
|
|
200
|
+
// { inputPer1M: 0.15, outputPer1M: 0.60 }
|
|
201
|
+
|
|
202
|
+
const cost = vibezcheck.calculateCost('gpt-4o-mini', {
|
|
203
|
+
promptTokens: 1000,
|
|
204
|
+
completionTokens: 500,
|
|
205
|
+
});
|
|
206
|
+
console.log(cost.totalUSD); // $0.00045
|
|
207
|
+
|
|
208
|
+
// Optional: refresh rates dynamically in the background
|
|
209
|
+
await vibezcheck.syncPricing(); // Sync Stripe Metronome rates
|
|
210
|
+
await vibezcheck.syncVercelGateway(); // Sync Vercel AI Gateway 260+ models
|
|
211
|
+
```
|
|
27
212
|
|
|
28
213
|
---
|
|
29
214
|
|
|
30
|
-
|
|
215
|
+
### 11. Autonomous Agent Governance & Tool Ceilings
|
|
216
|
+
Enforce a hard budget ceiling over multi-step agent loops and bill for tool invocations:
|
|
217
|
+
```typescript
|
|
218
|
+
import { vibezcheck } from 'vibezcheck';
|
|
31
219
|
|
|
32
|
-
|
|
220
|
+
const session = vibezcheck.session({
|
|
221
|
+
customer: 'usr_agent_runner',
|
|
222
|
+
sessionBudgetUSD: 1.00, // Hard ceiling for entire multi-turn workflow
|
|
223
|
+
});
|
|
33
224
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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.
|
|
225
|
+
// Bill for tool executions
|
|
226
|
+
const tools = session.tools(myTools, {
|
|
227
|
+
web_search: { costUSD: 0.01 },
|
|
228
|
+
code_interpreter: { costUSD: 0.05 },
|
|
229
|
+
});
|
|
230
|
+
```
|
|
41
231
|
|
|
42
232
|
---
|
|
43
233
|
|
|
44
|
-
|
|
234
|
+
### 12. Serverless Lifecycle Spooling & Manual Flush
|
|
235
|
+
VibezCheck automatically hooks into `globalThis.after()` on Next.js / Vercel and `globalThis.waitUntil()` on Cloudflare Workers so logging never delays stream delivery. You can also explicitly flush before process termination:
|
|
236
|
+
```typescript
|
|
237
|
+
import { vibezcheck } from 'vibezcheck';
|
|
238
|
+
|
|
239
|
+
// Guarantees all queued usage telemetry is written before worker teardown
|
|
240
|
+
await vibezcheck.flush();
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
45
244
|
|
|
46
|
-
|
|
245
|
+
### 13. Native Non-AI-SDK Streams (OpenAI, Anthropic, Gemini)
|
|
246
|
+
Meter raw SDK streams outside the Vercel AI SDK with 0ms added latency:
|
|
247
|
+
```typescript
|
|
248
|
+
import OpenAI from 'openai';
|
|
249
|
+
import { vibezcheck } from 'vibezcheck';
|
|
47
250
|
|
|
48
|
-
|
|
251
|
+
const openai = new OpenAI();
|
|
252
|
+
const client = vibezcheck.create();
|
|
253
|
+
|
|
254
|
+
const stream = await openai.chat.completions.create({
|
|
255
|
+
model: 'gpt-4o-mini',
|
|
256
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
257
|
+
stream: true,
|
|
258
|
+
stream_options: { include_usage: true },
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Meter stream in real time
|
|
262
|
+
const meteredStream = client.wrapStream(stream, {
|
|
263
|
+
model: 'gpt-4o-mini',
|
|
264
|
+
onUsage: (event) => {
|
|
265
|
+
console.log(`Billed: $${event.cost.totalUSD} for ${event.usage.totalTokens} tokens`);
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
```
|
|
49
269
|
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### 14. CLI Diagnostics & Starter Scaffolding
|
|
273
|
+
Inspect your codebase for unmetered LLM endpoints or scaffold complete starter templates:
|
|
50
274
|
```bash
|
|
51
|
-
|
|
275
|
+
# Scan project routes for unmetered AI SDK calls
|
|
276
|
+
npx vibezcheck audit
|
|
277
|
+
|
|
278
|
+
# Scaffold starter projects (Next.js App Router, minimal scripts, etc.)
|
|
279
|
+
npx vibezcheck examples
|
|
52
280
|
```
|
|
53
281
|
|
|
54
|
-
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## 🚀 Complete Next.js App Router Example
|
|
55
285
|
|
|
286
|
+
### Server Route (`app/api/chat/route.ts`)
|
|
56
287
|
```typescript
|
|
57
288
|
import { convertToModelMessages, streamText, UIMessage } from 'ai';
|
|
58
289
|
import { openai } from '@ai-sdk/openai';
|
|
@@ -64,23 +295,20 @@ export async function POST(req: Request) {
|
|
|
64
295
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
65
296
|
|
|
66
297
|
const result = streamText({
|
|
67
|
-
// ✦ 1 Line: track costs, add 30% profit margin, and set $0.50 runaway safety fuse
|
|
68
298
|
model: vibezcheck(openai('gpt-4o-mini'), {
|
|
69
|
-
customer: 'user_alex@example.com',
|
|
70
|
-
pricing: { margin: 1.3 },
|
|
71
|
-
maxCostPerCallUSD: 0.50,
|
|
299
|
+
customer: 'user_alex@example.com',
|
|
300
|
+
pricing: { margin: 1.3 }, // +30% margin
|
|
301
|
+
maxCostPerCallUSD: 0.50, // Circuit breaker
|
|
72
302
|
}),
|
|
73
|
-
instructions: 'You are a helpful
|
|
303
|
+
instructions: 'You are a helpful assistant.',
|
|
74
304
|
messages: await convertToModelMessages(messages),
|
|
75
305
|
});
|
|
76
306
|
|
|
77
|
-
// ✦ Transmits stream with verified spending telemetry attached
|
|
78
307
|
return vibezcheck.toResponse(result);
|
|
79
308
|
}
|
|
80
309
|
```
|
|
81
310
|
|
|
82
|
-
###
|
|
83
|
-
|
|
311
|
+
### Frontend Client (`app/page.tsx`)
|
|
84
312
|
```tsx
|
|
85
313
|
'use client';
|
|
86
314
|
|
|
@@ -92,147 +320,42 @@ import { VibezReceipt, VibezCheck } from 'vibezcheck/ui';
|
|
|
92
320
|
export default function ChatPage() {
|
|
93
321
|
const [input, setInput] = useState('');
|
|
94
322
|
const { messages, sendMessage, status } = useChat({
|
|
95
|
-
transport: new DefaultChatTransport({
|
|
96
|
-
api: '/api/chat',
|
|
97
|
-
}),
|
|
323
|
+
transport: new DefaultChatTransport({ api: '/api/chat' }),
|
|
98
324
|
});
|
|
99
325
|
|
|
100
326
|
return (
|
|
101
327
|
<div className="flex flex-col w-full max-w-lg py-20 mx-auto px-4 min-h-screen">
|
|
102
|
-
{/* Messages Stream */}
|
|
103
328
|
<div className="flex-1 space-y-4 mb-28">
|
|
104
329
|
{messages.map((message) => (
|
|
105
|
-
<div
|
|
106
|
-
|
|
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">
|
|
114
|
-
{message.role === 'user' ? 'You' : 'Assistant'}
|
|
115
|
-
</div>
|
|
116
|
-
|
|
117
|
-
{/* Message Text */}
|
|
118
|
-
<div className="text-sm whitespace-pre-wrap leading-relaxed">
|
|
119
|
-
{message.parts
|
|
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
|
-
})
|
|
128
|
-
: message.content}
|
|
129
|
-
</div>
|
|
130
|
-
|
|
131
|
-
{/* ✦ 1 Line: Micro-Receipt showing tokens, micro-cost, model, and latency */}
|
|
330
|
+
<div key={message.id} className="p-4 rounded-xl border">
|
|
331
|
+
<div>{message.content}</div>
|
|
132
332
|
{message.role === 'assistant' && (
|
|
133
|
-
<div className="mt-
|
|
333
|
+
<div className="mt-2 flex justify-end">
|
|
134
334
|
<VibezReceipt message={message} />
|
|
135
335
|
</div>
|
|
136
336
|
)}
|
|
137
337
|
</div>
|
|
138
338
|
))}
|
|
139
|
-
|
|
140
|
-
{status === 'streaming' && (
|
|
141
|
-
<div className="text-xs text-zinc-400 italic">Assistant is typing...</div>
|
|
142
|
-
)}
|
|
143
339
|
</div>
|
|
144
340
|
|
|
145
|
-
{
|
|
146
|
-
|
|
147
|
-
onSubmit={(e) => {
|
|
148
|
-
e.preventDefault();
|
|
149
|
-
if (!input.trim()) return;
|
|
150
|
-
sendMessage({ text: input });
|
|
151
|
-
setInput('');
|
|
152
|
-
}}
|
|
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"
|
|
154
|
-
>
|
|
155
|
-
<div className="max-w-lg mx-auto flex gap-2">
|
|
156
|
-
<input
|
|
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"
|
|
158
|
-
value={input}
|
|
159
|
-
placeholder="Type your prompt..."
|
|
160
|
-
onChange={(e) => setInput(e.target.value)}
|
|
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>
|
|
169
|
-
</div>
|
|
341
|
+
<form onSubmit={(e) => { e.preventDefault(); sendMessage({ text: input }); setInput(''); }}>
|
|
342
|
+
<input value={input} onChange={(e) => setInput(e.target.value)} placeholder="Type prompt..." />
|
|
170
343
|
</form>
|
|
171
344
|
|
|
172
|
-
{/* ✦ 1 Line: Floating HUD showing real-time spending and tokens */}
|
|
173
345
|
<VibezCheck messages={messages} />
|
|
174
346
|
</div>
|
|
175
347
|
);
|
|
176
348
|
}
|
|
177
349
|
```
|
|
178
350
|
|
|
179
|
-
### 4. Environment Variables (`.env.local`)
|
|
180
|
-
|
|
181
|
-
```env
|
|
182
|
-
OPENAI_API_KEY=sk-...
|
|
183
|
-
```
|
|
184
|
-
|
|
185
351
|
---
|
|
186
352
|
|
|
187
|
-
##
|
|
188
|
-
|
|
189
|
-
Import from `vibezcheck/ui` or `vibezcheck/react`:
|
|
190
|
-
|
|
191
|
-
### 1. `<VibezCheck messages={messages} />`
|
|
192
|
-
|
|
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.
|
|
198
|
-
|
|
199
|
-
```tsx
|
|
200
|
-
<VibezCheck
|
|
201
|
-
messages={messages}
|
|
202
|
-
remainingBalanceUSD={10.00}
|
|
203
|
-
onTopUp={(amount) => console.log('User wants to top up credits:', amount)}
|
|
204
|
-
/>
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### 2. `<VibezReceipt message={message} />`
|
|
208
|
-
|
|
209
|
-
A small, elegant badge under each assistant message:
|
|
210
|
-
```tsx
|
|
211
|
-
<VibezReceipt message={message} />
|
|
212
|
-
// Renders: ✦ $0.0001 · 31 tok · gpt-4o-mini
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
## Multi-Model Sessions (Automatic Breakdown)
|
|
218
|
-
|
|
219
|
-
If your app routes between different models (e.g. `gpt-4o-mini` for quick chat and `claude-3-5-sonnet` for coding):
|
|
220
|
-
|
|
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
|
|
224
|
-
|
|
225
|
-
Click any model to see its specific spending.
|
|
226
|
-
|
|
227
|
-
---
|
|
228
|
-
|
|
229
|
-
## Need Stripe Billing? (Optional)
|
|
230
|
-
|
|
231
|
-
When you want to charge real money, VibezCheck has built-in Stripe helpers:
|
|
353
|
+
## 🛡️ Core Guarantees & Philosophy
|
|
232
354
|
|
|
233
|
-
* **
|
|
234
|
-
* **
|
|
235
|
-
* **
|
|
355
|
+
* **Zero Added Latency (0ms)**: Calculations happen in-memory synchronously. Telemetry and database writes occur asynchronously via non-blocking lifecycles.
|
|
356
|
+
* **Pure Zero Runtime Dependencies (`dependencies: {}`)**: Completely self-contained engine. Peer dependencies (`ai`, `@ai-sdk/provider`, `openai`, `react`) are purely optional.
|
|
357
|
+
* **Airbag Failure Isolation**: Database or remote sync outages will never crash user-facing AI chat streams.
|
|
358
|
+
* **Offline-First Resilience**: All rate calculations work immediately with bundled catalogs even with zero network access.
|
|
236
359
|
|
|
237
360
|
---
|
|
238
361
|
|
package/dist/ai-sdk/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { W as WithBillingOptions } from '../with-billing-
|
|
2
|
-
export { m as meteredModel, w as withBilling } from '../with-billing-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import '
|
|
1
|
+
import { W as WithBillingOptions } from '../with-billing-DhHGWCAp.mjs';
|
|
2
|
+
export { m as meteredModel, w as withBilling } from '../with-billing-DhHGWCAp.mjs';
|
|
3
|
+
import { A as AgentSession, a as AgentSessionOptions, c as createAgentSession } from '../session-D9fdP255.mjs';
|
|
4
|
+
import { C as CustomerParam } from '../types-DHlsaLvI.mjs';
|
|
5
|
+
import '../client-ttJwYM7x.mjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* ✦ VibezCheck Universal Telemetry Response Stream Injector
|
|
@@ -49,24 +49,8 @@ interface VibezCheckModelOptions extends WithBillingOptions {
|
|
|
49
49
|
/** AI Gateway / Provider Base URL override */
|
|
50
50
|
baseURL?: string;
|
|
51
51
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
stripeApiKey?: string;
|
|
55
|
-
pricing?: WithBillingOptions['pricing'];
|
|
56
|
-
billing?: WithBillingOptions['billing'];
|
|
57
|
-
metadata?: Record<string, string | number | boolean>;
|
|
58
|
-
}
|
|
59
|
-
interface VibezSession {
|
|
60
|
-
/** Creates a metered model bound to this session customer */
|
|
61
|
-
model: (modelOrId: any, options?: VibezCheckModelOptions) => any;
|
|
62
|
-
/** Tracks a non-LLM tool execution cost (e.g. search, scraper, image gen) */
|
|
63
|
-
trackTool: (name: string, options: {
|
|
64
|
-
costUSD: number;
|
|
65
|
-
metadata?: Record<string, any>;
|
|
66
|
-
}) => Promise<void>;
|
|
67
|
-
/** Underlying meter instance */
|
|
68
|
-
meter: VibezMeter;
|
|
69
|
-
}
|
|
52
|
+
type VibezSessionOptions = AgentSessionOptions;
|
|
53
|
+
type VibezSession = AgentSession;
|
|
70
54
|
/**
|
|
71
55
|
* Creates or resolves an AI SDK compatible LanguageModel with built-in VibezCheck billing & metering.
|
|
72
56
|
*
|
|
@@ -103,12 +87,108 @@ interface VibezSession {
|
|
|
103
87
|
*/
|
|
104
88
|
declare function createVibezModel(modelOrId: any, options?: VibezCheckModelOptions): any;
|
|
105
89
|
/**
|
|
106
|
-
* Creates a scoped session for unified multi-call and tool tracking.
|
|
90
|
+
* Creates a scoped agent session for unified multi-call and tool tracking.
|
|
91
|
+
* Alias for createAgentSession from vibezcheck/billing.
|
|
107
92
|
*/
|
|
108
|
-
declare
|
|
93
|
+
declare const createVibezSession: typeof createAgentSession;
|
|
109
94
|
declare const vibezcheck: typeof createVibezModel & {
|
|
110
95
|
session: typeof createVibezSession;
|
|
111
96
|
toResponse: typeof toResponse;
|
|
112
97
|
};
|
|
113
98
|
|
|
114
|
-
|
|
99
|
+
/**
|
|
100
|
+
* ✦ VibezCheck Native AI SDK v7 DataUIPart Stream Helper
|
|
101
|
+
*
|
|
102
|
+
* Automatically injects native `{ type: 'data-vibezcheck', data }` parts into
|
|
103
|
+
* AI SDK SSE streams, UI message streams, and Data Stream protocol pipes.
|
|
104
|
+
*
|
|
105
|
+
* Seamlessly hydrates client-side `useVibez(messages)` with real-time verified:
|
|
106
|
+
* - Cost breakdown (costUSD, wholesaleUSD, profitUSD)
|
|
107
|
+
* - Token metrics (prompt, completion, reasoning, cached)
|
|
108
|
+
* - Model & Provider metadata
|
|
109
|
+
* - Tool usage & itemized costs
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Normalized telemetry payload transmitted inside `{ type: 'data-vibezcheck', data: ... }`
|
|
114
|
+
*/
|
|
115
|
+
interface VibezDataStreamPayload {
|
|
116
|
+
model: string;
|
|
117
|
+
provider?: string;
|
|
118
|
+
costUSD: number;
|
|
119
|
+
wholesaleUSD: number;
|
|
120
|
+
profitUSD: number;
|
|
121
|
+
tokens: number;
|
|
122
|
+
promptTokens: number;
|
|
123
|
+
completionTokens: number;
|
|
124
|
+
reasoningTokens?: number;
|
|
125
|
+
cachedTokens?: number;
|
|
126
|
+
toolCalls?: Array<{
|
|
127
|
+
name: string;
|
|
128
|
+
calls: number;
|
|
129
|
+
costUSD: number;
|
|
130
|
+
latencyMs?: number;
|
|
131
|
+
}>;
|
|
132
|
+
customerId?: string;
|
|
133
|
+
timestamp?: string;
|
|
134
|
+
metadata?: Record<string, any>;
|
|
135
|
+
[key: string]: any;
|
|
136
|
+
}
|
|
137
|
+
interface ToVibezDataStreamOptions {
|
|
138
|
+
/** Explicit telemetry payload or overrides */
|
|
139
|
+
telemetry?: Partial<VibezDataStreamPayload>;
|
|
140
|
+
/** Customer param for billing attribution */
|
|
141
|
+
customer?: CustomerParam;
|
|
142
|
+
/** Model override if not auto-detected */
|
|
143
|
+
model?: string;
|
|
144
|
+
/** Profit margin multiplier if recalculating (e.g. 1.30 for 30%) */
|
|
145
|
+
margin?: number;
|
|
146
|
+
/** Callback fired when telemetry is written to stream */
|
|
147
|
+
onTelemetry?: (telemetry: VibezDataStreamPayload) => void | Promise<void>;
|
|
148
|
+
/** Custom extra stream parts to emit alongside data-vibezcheck */
|
|
149
|
+
extraParts?: any[];
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Augmented ReadableStream with convenient 1-line `.toResponse()` helper
|
|
153
|
+
*/
|
|
154
|
+
interface VibezDataStream extends ReadableStream<any> {
|
|
155
|
+
toResponse(init?: ResponseInit & {
|
|
156
|
+
headers?: HeadersInit;
|
|
157
|
+
}): Response;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Normalizes any raw telemetry or usage event into a canonical VibezDataStreamPayload
|
|
161
|
+
*/
|
|
162
|
+
declare function normalizeTelemetryPayload(raw?: any, options?: ToVibezDataStreamOptions): VibezDataStreamPayload;
|
|
163
|
+
/**
|
|
164
|
+
* Transforms an AI SDK stream (or StreamTextResult) into a VibezDataStream
|
|
165
|
+
* that writes native `{ type: 'data-vibezcheck', data }` parts directly into the SSE stream.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* import { streamText } from 'ai';
|
|
170
|
+
* import { openai } from '@ai-sdk/openai';
|
|
171
|
+
* import { vibezcheck, toVibezDataStream } from 'vibezcheck';
|
|
172
|
+
*
|
|
173
|
+
* export async function POST(req: Request) {
|
|
174
|
+
* const { messages } = await req.json();
|
|
175
|
+
* const result = streamText({
|
|
176
|
+
* model: vibezcheck(openai('gpt-4o')),
|
|
177
|
+
* messages,
|
|
178
|
+
* });
|
|
179
|
+
*
|
|
180
|
+
* // ✦ 1-Line Data Stream with Native Telemetry Part
|
|
181
|
+
* return toVibezDataStream(result).toResponse();
|
|
182
|
+
* }
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
declare function toVibezDataStream(source: any, options?: ToVibezDataStreamOptions): VibezDataStream;
|
|
186
|
+
/**
|
|
187
|
+
* Transforms an AI SDK stream into an HTTP Response with native `data-vibezcheck` telemetry parts.
|
|
188
|
+
*/
|
|
189
|
+
declare function toVibezDataStreamResponse(source: any, options?: ToVibezDataStreamOptions & {
|
|
190
|
+
init?: ResponseInit;
|
|
191
|
+
headers?: HeadersInit;
|
|
192
|
+
}): Response;
|
|
193
|
+
|
|
194
|
+
export { type ToResponseOptions, type ToVibezDataStreamOptions, type VibezCheckModelOptions, type VibezDataStream, type VibezDataStreamPayload, type VibezSession, type VibezSessionOptions, WithBillingOptions, createVibezModel, createVibezSession, normalizeTelemetryPayload, toResponse, toVibezDataStream, toVibezDataStreamResponse, vibezcheck };
|