openzoo 0.51.10 → 0.51.11
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/launcher/savings-renderer.js +1 -1
- package/lib/billing.js +7 -4
- package/lib/proxy.js +5 -5
- package/lib/session.js +4 -0
- package/package.json +1 -1
|
@@ -4,6 +4,6 @@ window.savings.listen(d => {
|
|
|
4
4
|
const saved=d.comparison?.calls > 0 ? d.comparison.directUsd-d.comparison.spentUsd : null;
|
|
5
5
|
document.getElementById('saved').textContent=usd(saved);
|
|
6
6
|
document.getElementById('saving-label').textContent=saved!==null && saved<0 ? 'Extra cost' : 'Saved';
|
|
7
|
-
document.getElementById('state').textContent=d.online ? (d.billing?.calls > 0 ? 'Final charges ·
|
|
7
|
+
document.getElementById('state').textContent=d.online ? (d.billing?.calls > 0 ? 'Final charges · saved receipts' : 'Waiting for final billing · balance is live') : 'Reconnecting · showing last known amounts';
|
|
8
8
|
});
|
|
9
9
|
document.getElementById('close').addEventListener('click',()=>window.savings.close());
|
package/lib/billing.js
CHANGED
|
@@ -2,10 +2,13 @@ const money = n => typeof n === 'number' && Number.isFinite(n) && n >= 0 ? n : n
|
|
|
2
2
|
|
|
3
3
|
// Only final, explicitly reported charges. Never substitute upstream cost or a quote.
|
|
4
4
|
export function finalBilling(x = {}, usage = {}) {
|
|
5
|
+
const receipt = x._completedResponse === true || x.settle?.success === true;
|
|
5
6
|
const charged = [usage.billedUsd, x.billedActualUsd, x.settledBilledUsd, x.chargedUsd,
|
|
6
|
-
x.settledUsd,
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
x.settledUsd, receipt ? x.billedUsd : null,
|
|
8
|
+
usage.cost_details?.upstream_inference_cost != null ? usage.cost : null].map(money).find(n => n !== null) ?? null;
|
|
9
|
+
const direct = receipt ? money(x.directUsd) : null;
|
|
10
|
+
const upstream = money(usage.cost_details?.upstream_inference_cost) ?? (receipt ? money(x.actualUsd) : null);
|
|
11
|
+
return { charged, direct, upstream };
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
// Observe billing without retaining prompts, output text, or changing the stream.
|
|
@@ -21,7 +24,7 @@ export function billingObserver(onReceipt) {
|
|
|
21
24
|
else if (line.startsWith('data:')) {
|
|
22
25
|
const event = JSON.parse(line.slice(5).trim());
|
|
23
26
|
const value = event.response || event;
|
|
24
|
-
if (value.usage || value.x402) onReceipt({ ...value.x402, usage: value.usage });
|
|
27
|
+
if (value.usage || value.x402) onReceipt({ ...value.x402, usage: value.usage, _completedResponse: event.type === 'response.completed' || value.status === 'completed' });
|
|
25
28
|
}
|
|
26
29
|
} catch { /* Not a billing event. */ }
|
|
27
30
|
}
|
package/lib/proxy.js
CHANGED
|
@@ -424,10 +424,10 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
424
424
|
let lastQuoteUsd = null;
|
|
425
425
|
let sessionCogs = restored.cogsUsd;
|
|
426
426
|
let sessionDirect = restored.directUsd;
|
|
427
|
-
let comparedSpent = 0, comparedDirect = 0, comparedCalls = 0;
|
|
428
|
-
let verifiedCharged = 0, verifiedCalls = 0;
|
|
427
|
+
let comparedSpent = restored.comparison?.spentUsd ?? 0, comparedDirect = restored.comparison?.directUsd ?? 0, comparedCalls = restored.comparison?.calls ?? 0;
|
|
428
|
+
let verifiedCharged = restored.billing?.chargedUsd ?? 0, verifiedCalls = restored.billing?.calls ?? 0;
|
|
429
429
|
const rememberSpend = () => {
|
|
430
|
-
saveSessionSpend({ spentUsd: sessionSpent, cogsUsd: sessionCogs, directUsd: sessionDirect, paidCalls });
|
|
430
|
+
saveSessionSpend({ spentUsd: sessionSpent, cogsUsd: sessionCogs, directUsd: sessionDirect, paidCalls, billing: { chargedUsd: verifiedCharged, calls: verifiedCalls }, comparison: { spentUsd: comparedSpent, directUsd: comparedDirect, calls: comparedCalls } });
|
|
431
431
|
};
|
|
432
432
|
if (restored.ok && (sessionSpent > 0 || paidCalls > 0)) {
|
|
433
433
|
say(`session restored: $${sessionSpent.toFixed(6)} · ${paidCalls} paid call${paidCalls === 1 ? '' : 's'}`);
|
|
@@ -656,7 +656,7 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
656
656
|
creditUsd,
|
|
657
657
|
// WHAT THE SAME CALLS WOULD HAVE COST DIRECT. Spend on its own is a
|
|
658
658
|
// bill; spend beside the counterfactual is the product.
|
|
659
|
-
billing: { chargedUsd: verifiedCharged, calls: verifiedCalls, scope: "verified
|
|
659
|
+
billing: { chargedUsd: verifiedCharged, calls: verifiedCalls, scope: "saved verified receipts" },
|
|
660
660
|
comparison: { spentUsd: comparedSpent, directUsd: comparedDirect, calls: comparedCalls },
|
|
661
661
|
directUsd: sessionDirect,
|
|
662
662
|
savedUsd: Math.max(0, sessionDirect - sessionSpent),
|
|
@@ -996,7 +996,7 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
996
996
|
if (isPaidPost && response.ok && upCt.includes('application/json')) {
|
|
997
997
|
let data = null;
|
|
998
998
|
try { data = await response.clone().json(); } catch { /* not JSON after all */ }
|
|
999
|
-
meterFinal({ ...data?.x402, usage: data?.usage });
|
|
999
|
+
meterFinal({ ...data?.x402, usage: data?.usage, _completedResponse: response.ok });
|
|
1000
1000
|
if (data?.object === 'chat.completion') {
|
|
1001
1001
|
if (statsOff) {
|
|
1002
1002
|
// The gateway already dropped its half; drop ours, and any block an
|
package/lib/session.js
CHANGED
|
@@ -30,6 +30,8 @@ export function loadSessionSpend(file = sessionSpendFile()) {
|
|
|
30
30
|
try { data = JSON.parse(raw); }
|
|
31
31
|
catch { return { ...EMPTY, ok: false, reason: 'corrupt' }; }
|
|
32
32
|
return {
|
|
33
|
+
...(data.billing ? { billing: { chargedUsd: num(data.billing.chargedUsd), calls: Math.floor(num(data.billing.calls)) } } : {}),
|
|
34
|
+
...(data.comparison ? { comparison: { spentUsd: num(data.comparison.spentUsd), directUsd: num(data.comparison.directUsd), calls: Math.floor(num(data.comparison.calls)) } } : {}),
|
|
33
35
|
spentUsd: num(data.spentUsd),
|
|
34
36
|
cogsUsd: num(data.cogsUsd),
|
|
35
37
|
directUsd: num(data.directUsd),
|
|
@@ -40,6 +42,8 @@ export function loadSessionSpend(file = sessionSpendFile()) {
|
|
|
40
42
|
|
|
41
43
|
export function saveSessionSpend(stats, file = sessionSpendFile()) {
|
|
42
44
|
const payload = {
|
|
45
|
+
...(stats?.billing ? { billing: { chargedUsd: num(stats.billing.chargedUsd), calls: Math.floor(num(stats.billing.calls)) } } : {}),
|
|
46
|
+
...(stats?.comparison ? { comparison: { spentUsd: num(stats.comparison.spentUsd), directUsd: num(stats.comparison.directUsd), calls: Math.floor(num(stats.comparison.calls)) } } : {}),
|
|
43
47
|
spentUsd: num(stats?.spentUsd),
|
|
44
48
|
cogsUsd: num(stats?.cogsUsd),
|
|
45
49
|
directUsd: num(stats?.directUsd),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.51.
|
|
3
|
+
"version": "0.51.11",
|
|
4
4
|
"description": "Local x402-paying proxy + MCP server for openzoo.fun — point any OpenAI-compatible harness (Cursor, Claude Code, aider, SDKs) at localhost and it pays per call from a local burner wallet. Solana and Base rails live; Robinhood experimental.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|