openzoo 0.50.95 → 0.50.97
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/bin/claude-zoo.js +28 -3
- package/lib/aoe.js +8 -2
- package/lib/cursorbackend.js +47 -22
- package/lib/cursorbackend.js.bak-hiddenbots +4072 -0
- package/lib/grokbotAccount.js +4 -2
- package/lib/grokbotAccount.js.bak-hiddenbots +386 -0
- package/lib/grokbotweb.js +10 -1
- package/lib/grokcli.js +89 -7
- package/lib/launch.js +18 -24
- package/lib/modelroute/README.md +1 -0
- package/lib/modelroute/catalog.json +1 -0
- package/lib/modelroute/outcomes.json +1566 -0
- package/lib/modelroute/router.json +1 -0
- package/lib/modelroute.js +737 -0
- package/lib/ozSpendChip.js +187 -29
- package/lib/podagent.mjs +1425 -0
- package/lib/proxy.js +127 -48
- package/lib/runguard.js +31 -0
- package/lib/setup.js +12 -13
- package/lib/spill.js +2031 -0
- package/lib/stripeOnramp.js +50 -0
- package/lib/subscription.js +207 -0
- package/lib/worktree.mjs +424 -0
- package/package.json +1 -1
package/lib/ozSpendChip.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Cafe spend
|
|
2
|
+
* Cafe/Grok Bot spend HUD. Live totals come from /oz-spend and /api/ozSpend;
|
|
3
|
+
* leftover ::oz-spend:: footers in old transcripts still fold into a chip.
|
|
3
4
|
*
|
|
4
5
|
* Cafe injects this via grokbotweb-shim concatenation. Grok Bot.app cannot
|
|
5
6
|
* be patched (asar integrity), so `openzoo bot` launches Chromium with a
|
|
@@ -14,18 +15,82 @@ import { spendChipLabel } from './spendProof.js';
|
|
|
14
15
|
|
|
15
16
|
export const GROKBOT_CDP_PORT = Number(process.env.OZ_GROKBOT_CDP_PORT || 9444);
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
export function spendHudPath(home = os.homedir()) {
|
|
19
|
+
return path.join(home, '.openzoo', 'spend-hud.json');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function writeSpendHud(state, home = os.homedir()) {
|
|
23
|
+
try {
|
|
24
|
+
const spent = Number(state?.spent) || 0;
|
|
25
|
+
const would = Number(state?.would) || 0;
|
|
26
|
+
const saved = Number(state?.saved) || 0;
|
|
27
|
+
const pct = Number(state?.pct) || 0;
|
|
28
|
+
const payload = {
|
|
29
|
+
spent,
|
|
30
|
+
would,
|
|
31
|
+
saved,
|
|
32
|
+
pct,
|
|
33
|
+
label: String(state?.label || ''),
|
|
34
|
+
body: String(state?.body || ''),
|
|
35
|
+
billedUsd: state?.billedUsd ?? null,
|
|
36
|
+
updatedAt: Date.now(),
|
|
37
|
+
};
|
|
38
|
+
fs.mkdirSync(path.dirname(spendHudPath(home)), { recursive: true, mode: 0o700 });
|
|
39
|
+
fs.writeFileSync(spendHudPath(home), JSON.stringify(payload), { mode: 0o600 });
|
|
40
|
+
return true;
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function readSpendHud(home = os.homedir()) {
|
|
47
|
+
try {
|
|
48
|
+
const j = JSON.parse(fs.readFileSync(spendHudPath(home), 'utf8'));
|
|
49
|
+
return j && typeof j === 'object' ? j : null;
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function sessionTotals(home) {
|
|
19
56
|
try {
|
|
20
57
|
const s = JSON.parse(fs.readFileSync(path.join(home, '.openzoo', 'session.json'), 'utf8'));
|
|
21
58
|
const spent = Number(s.spentUsd || s.spendUsd || 0);
|
|
22
59
|
const would = Number(s.directUsd || 0);
|
|
23
60
|
const saved = Number(s.savedUsd != null ? s.savedUsd : Math.max(0, would - spent));
|
|
24
|
-
|
|
25
|
-
|
|
61
|
+
const pct = would > 0 ? (100 * saved) / would : 0;
|
|
62
|
+
const label = spent > 0.00005 ? spendChipLabel({ spent, would, saved, pct }) : '';
|
|
63
|
+
return { spent, would, saved, pct, label };
|
|
26
64
|
} catch {
|
|
27
|
-
return '';
|
|
65
|
+
return { spent: 0, would: 0, saved: 0, pct: 0, label: '' };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function sessionBody(sess) {
|
|
70
|
+
if (!(sess.spent > 0.00005)) return '';
|
|
71
|
+
return `spent $${sess.spent.toFixed(4)} · OpenRouter would $${sess.would.toFixed(4)} · saved $${sess.saved.toFixed(4)} (${Math.round(sess.pct)}%)`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Session totals + last-call dump for the HUD pill. */
|
|
75
|
+
export function sessionSpendState(home = os.homedir()) {
|
|
76
|
+
const sess = sessionTotals(home);
|
|
77
|
+
const hud = readSpendHud(home);
|
|
78
|
+
if (hud && (hud.label || hud.body)) {
|
|
79
|
+
return {
|
|
80
|
+
spent: Number(hud.spent) || sess.spent,
|
|
81
|
+
would: Number(hud.would) || sess.would,
|
|
82
|
+
saved: Number(hud.saved) || sess.saved,
|
|
83
|
+
pct: Number(hud.pct) || sess.pct,
|
|
84
|
+
label: String(hud.label || sess.label || ''),
|
|
85
|
+
body: String(hud.body || sessionBody(sess)),
|
|
86
|
+
billedUsd: hud.billedUsd ?? null,
|
|
87
|
+
};
|
|
28
88
|
}
|
|
89
|
+
return { ...sess, body: sessionBody(sess), billedUsd: null };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function sessionSpendLabel(home = os.homedir()) {
|
|
93
|
+
return sessionSpendState(home).label;
|
|
29
94
|
}
|
|
30
95
|
|
|
31
96
|
export function grokBotChromiumArgs(port = GROKBOT_CDP_PORT) {
|
|
@@ -159,9 +224,13 @@ function ozEnsureSpendCss() {
|
|
|
159
224
|
}
|
|
160
225
|
s.textContent = [
|
|
161
226
|
'.oz-spend{margin:.55rem 0 0;font-size:12px;color:inherit;opacity:.82;max-width:36em}',
|
|
162
|
-
'#oz-spend-
|
|
227
|
+
'#oz-spend-hud{opacity:1;max-width:min(28em,calc(100vw - 24px));pointer-events:auto}',
|
|
228
|
+
'#oz-spend-hud>summary{cursor:grab;background:#e85d1c;color:#fff;font-weight:600;font-size:13px;',
|
|
229
|
+
'border:0;box-shadow:0 4px 18px rgba(0,0,0,.5)}',
|
|
230
|
+
'#oz-spend-hud>.oz-spend-body{background:rgba(20,20,22,.94);color:#f4f4f5;padding:8px 10px;',
|
|
231
|
+
'border-radius:10px;margin-top:6px}',
|
|
163
232
|
'.oz-spend>summary{cursor:help;list-style:none;display:inline-flex;align-items:center;gap:.35rem;',
|
|
164
|
-
'padding:
|
|
233
|
+
'padding:6px 12px;border-radius:999px;border:1px solid rgba(255,255,255,.18);white-space:nowrap;',
|
|
165
234
|
'max-width:100%;overflow:hidden;text-overflow:ellipsis}',
|
|
166
235
|
'.oz-spend>summary::-webkit-details-marker{display:none}',
|
|
167
236
|
'.oz-spend-body{white-space:pre-wrap;margin:.55rem 0 0;font-size:11px;line-height:1.45;opacity:.88;overflow-wrap:anywhere}',
|
|
@@ -213,11 +282,19 @@ export function stripSpendFromText(s) {
|
|
|
213
282
|
return t;
|
|
214
283
|
}
|
|
215
284
|
|
|
285
|
+
function ozInComposer(el) {
|
|
286
|
+
if (!el) return false;
|
|
287
|
+
if (el.tagName === 'TEXTAREA' || el.tagName === 'INPUT' || el.isContentEditable) return true;
|
|
288
|
+
return !!(el.closest && el.closest('textarea, input, [contenteditable="true"]'));
|
|
289
|
+
}
|
|
290
|
+
|
|
216
291
|
function ozBlankSpendIn(root) {
|
|
292
|
+
if (ozInComposer(root)) return;
|
|
217
293
|
const w = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null);
|
|
218
294
|
while (w.nextNode()) {
|
|
219
295
|
const tn = w.currentNode;
|
|
220
296
|
if (tn.parentElement && tn.parentElement.closest && tn.parentElement.closest('.oz-spend')) continue;
|
|
297
|
+
if (ozInComposer(tn.parentElement)) continue;
|
|
221
298
|
const next = stripSpendFromText(tn.nodeValue || '');
|
|
222
299
|
if (next !== tn.nodeValue) tn.nodeValue = next;
|
|
223
300
|
}
|
|
@@ -228,6 +305,7 @@ function ozHideSpendLeftovers() {
|
|
|
228
305
|
for (let i = 0; i < nodes.length; i += 1) {
|
|
229
306
|
const el = nodes[i];
|
|
230
307
|
if (el.closest && el.closest('.oz-spend')) continue;
|
|
308
|
+
if (ozInComposer(el)) continue;
|
|
231
309
|
if (el.querySelector && el.querySelector('.oz-spend')) continue;
|
|
232
310
|
const vis = ozVisibleSpendText(el);
|
|
233
311
|
if (!spendOnlyText(vis)) continue;
|
|
@@ -290,10 +368,11 @@ function ozCollapseSpend() {
|
|
|
290
368
|
for (let i = 0; i < nodes.length; i += 1) {
|
|
291
369
|
const el = nodes[i];
|
|
292
370
|
if (el.closest && el.closest('.oz-spend')) continue;
|
|
371
|
+
if (ozInComposer(el)) continue;
|
|
293
372
|
const t = ozVisibleSpendText(el);
|
|
294
373
|
if (!/::oz-spend::|this call \$|spent \$/i.test(t)) continue;
|
|
295
374
|
const host = ozSpendHost(el);
|
|
296
|
-
if (!host || seen.has(host)) continue;
|
|
375
|
+
if (!host || seen.has(host) || ozInComposer(host)) continue;
|
|
297
376
|
seen.add(host);
|
|
298
377
|
hosts.push(host);
|
|
299
378
|
}
|
|
@@ -302,10 +381,11 @@ function ozCollapseSpend() {
|
|
|
302
381
|
const vis = ozVisibleSpendText(host);
|
|
303
382
|
const split = splitSpendText(vis);
|
|
304
383
|
if (!split || !split.body || split.body.length < 12) continue;
|
|
384
|
+
if (split.summary) window.__OZ_SPEND_LAST__ = split.summary;
|
|
305
385
|
ozEnsureSpendCss();
|
|
306
386
|
if (spendOnlyText(vis)) {
|
|
307
387
|
const prev = ozPreviousMessageCard(host);
|
|
308
|
-
if (prev && prev !== host) {
|
|
388
|
+
if (prev && prev !== host && !ozInComposer(prev)) {
|
|
309
389
|
ozAttachSpendChip(prev, split);
|
|
310
390
|
host.setAttribute('data-oz-spend-hide', '1');
|
|
311
391
|
continue;
|
|
@@ -318,19 +398,44 @@ function ozCollapseSpend() {
|
|
|
318
398
|
ozEnsureFloatSpend();
|
|
319
399
|
}
|
|
320
400
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (
|
|
327
|
-
|
|
401
|
+
/** Live HUD label: latest folded chip, then a read-only canvas scan, then inject snapshot. */
|
|
402
|
+
function ozFloatLabel() {
|
|
403
|
+
const pills = document.querySelectorAll('.oz-spend:not(#oz-spend-hud):not(#oz-spend-float) summary');
|
|
404
|
+
if (pills.length) {
|
|
405
|
+
const lab = String(pills[pills.length - 1].textContent || '').replace(/^ⓘ\s*/, '').trim();
|
|
406
|
+
if (lab) {
|
|
407
|
+
window.__OZ_SPEND_LAST__ = lab;
|
|
408
|
+
return lab;
|
|
409
|
+
}
|
|
328
410
|
}
|
|
411
|
+
try {
|
|
412
|
+
const nodes = document.querySelectorAll('[class*="sand-message"]');
|
|
413
|
+
for (let i = nodes.length - 1; i >= 0; i -= 1) {
|
|
414
|
+
if (ozInComposer(nodes[i])) continue;
|
|
415
|
+
const vis = ozVisibleSpendText(nodes[i]);
|
|
416
|
+
if (!/::oz-spend::|this call \$|spent \$/i.test(vis)) continue;
|
|
417
|
+
const split = splitSpendText(vis);
|
|
418
|
+
if (split && split.summary) {
|
|
419
|
+
window.__OZ_SPEND_LAST__ = split.summary;
|
|
420
|
+
return split.summary;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
} catch (e) {}
|
|
424
|
+
if (window.__OZ_SPEND_LAST__) return String(window.__OZ_SPEND_LAST__);
|
|
425
|
+
return String(window.__OZ_SESSION_SPEND__ || '').trim();
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function ozEnsureFloatSpend() {
|
|
429
|
+
const leftover = document.getElementById('oz-spend-float');
|
|
430
|
+
if (leftover) leftover.remove();
|
|
431
|
+
const label = ozFloatLabel() || String(window.__OZ_SESSION_SPEND__ || '').trim() || 'openzoo';
|
|
432
|
+
let el = document.getElementById('oz-spend-hud');
|
|
329
433
|
ozEnsureSpendCss();
|
|
330
434
|
if (!el) {
|
|
331
435
|
el = document.createElement('details');
|
|
332
|
-
el.id = 'oz-spend-
|
|
436
|
+
el.id = 'oz-spend-hud';
|
|
333
437
|
el.className = 'oz-spend';
|
|
438
|
+
el.open = true;
|
|
334
439
|
const sum = document.createElement('summary');
|
|
335
440
|
const body = document.createElement('div');
|
|
336
441
|
body.className = 'oz-spend-body';
|
|
@@ -343,6 +448,9 @@ function ozEnsureFloatSpend() {
|
|
|
343
448
|
ozDragFloat(el);
|
|
344
449
|
const sum = el.querySelector('summary');
|
|
345
450
|
if (sum) sum.textContent = 'ⓘ ' + label;
|
|
451
|
+
const bodyEl = el.querySelector('.oz-spend-body');
|
|
452
|
+
const dump = String(window.__OZ_SPEND_BODY__ || '').trim();
|
|
453
|
+
if (bodyEl && dump) bodyEl.textContent = dump;
|
|
346
454
|
}
|
|
347
455
|
|
|
348
456
|
function ozSavedFloatPos() {
|
|
@@ -357,9 +465,15 @@ function ozPlaceFloat(el) {
|
|
|
357
465
|
if (!el) return;
|
|
358
466
|
el.style.position = 'fixed';
|
|
359
467
|
el.style.zIndex = '2147483646';
|
|
360
|
-
el.style.opacity = '
|
|
468
|
+
el.style.opacity = '1';
|
|
469
|
+
el.style.pointerEvents = 'auto';
|
|
470
|
+
const vw = Math.max(320, Number(window.innerWidth) || 800);
|
|
471
|
+
const vh = Math.max(240, Number(window.innerHeight) || 600);
|
|
361
472
|
const saved = ozSavedFloatPos();
|
|
362
|
-
|
|
473
|
+
const onScreen = saved
|
|
474
|
+
&& saved.left >= 0 && saved.top >= 0
|
|
475
|
+
&& saved.left < vw - 24 && saved.top < vh - 24;
|
|
476
|
+
if (onScreen) {
|
|
363
477
|
el.style.left = Math.max(8, saved.left) + 'px';
|
|
364
478
|
el.style.top = Math.max(8, saved.top) + 'px';
|
|
365
479
|
el.style.right = 'auto';
|
|
@@ -368,8 +482,8 @@ function ozPlaceFloat(el) {
|
|
|
368
482
|
}
|
|
369
483
|
el.style.left = 'auto';
|
|
370
484
|
el.style.right = '16px';
|
|
371
|
-
el.style.top = '
|
|
372
|
-
el.style.bottom = '
|
|
485
|
+
el.style.top = 'auto';
|
|
486
|
+
el.style.bottom = '88px';
|
|
373
487
|
}
|
|
374
488
|
|
|
375
489
|
function ozDragFloat(el) {
|
|
@@ -414,31 +528,71 @@ function ozDragFloat(el) {
|
|
|
414
528
|
}, true);
|
|
415
529
|
}
|
|
416
530
|
|
|
531
|
+
function ozLabelFromInfo(j) {
|
|
532
|
+
if (!j || typeof j !== 'object') return '';
|
|
533
|
+
if (typeof j.label === 'string' && j.label.trim()) return j.label.trim();
|
|
534
|
+
const spent = Number(j.spentUsd ?? j.spendUsd ?? j.spent ?? 0);
|
|
535
|
+
const would = Number(j.directUsd ?? j.would ?? 0);
|
|
536
|
+
const saved = Number(j.savedUsd != null ? j.savedUsd : (j.saved != null ? j.saved : Math.max(0, would - spent)));
|
|
537
|
+
if (!(spent > 0.00005)) return '';
|
|
538
|
+
return labelFromSpendBody(
|
|
539
|
+
'spent $' + spent.toFixed(4) + ' OpenRouter would $' + would.toFixed(4) + ' saved $' + saved.toFixed(4),
|
|
540
|
+
'',
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function ozPollSpend() {
|
|
545
|
+
const urls = ['/oz-spend', '/api/ozSpend', 'https://127.0.0.1:8443/api/ozSpend', 'http://127.0.0.1:8402/v1/info'];
|
|
546
|
+
(async () => {
|
|
547
|
+
for (let i = 0; i < urls.length; i += 1) {
|
|
548
|
+
try {
|
|
549
|
+
const r = await fetch(urls[i], { signal: AbortSignal.timeout(1500) });
|
|
550
|
+
if (!r || !r.ok) continue;
|
|
551
|
+
const j = await r.json();
|
|
552
|
+
const lab = ozLabelFromInfo(j);
|
|
553
|
+
if (!lab) continue;
|
|
554
|
+
window.__OZ_SESSION_SPEND__ = lab;
|
|
555
|
+
if (typeof j.body === 'string' && j.body.trim()) window.__OZ_SPEND_BODY__ = j.body.trim();
|
|
556
|
+
ozEnsureFloatSpend();
|
|
557
|
+
return;
|
|
558
|
+
} catch (e) {}
|
|
559
|
+
}
|
|
560
|
+
})();
|
|
561
|
+
}
|
|
562
|
+
|
|
417
563
|
function ozWatchSpend() {
|
|
418
564
|
let t = 0;
|
|
565
|
+
const inComposer = () => ozInComposer(document.activeElement);
|
|
419
566
|
const run = () => {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
567
|
+
try {
|
|
568
|
+
if (inComposer()) {
|
|
569
|
+
ozEnsureSpendCss();
|
|
570
|
+
ozEnsureFloatSpend();
|
|
571
|
+
} else {
|
|
572
|
+
ozCollapseSpend();
|
|
573
|
+
}
|
|
574
|
+
} catch (e) {}
|
|
423
575
|
};
|
|
424
|
-
const debounced = () => { clearTimeout(t); t = setTimeout(run,
|
|
576
|
+
const debounced = () => { clearTimeout(t); t = setTimeout(run, 400); };
|
|
425
577
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', run);
|
|
426
578
|
else run();
|
|
427
579
|
try {
|
|
428
580
|
const mo = new MutationObserver(debounced);
|
|
429
|
-
const start = () => { if (document.body) mo.observe(document.body, { childList: true, subtree:
|
|
581
|
+
const start = () => { if (document.body) mo.observe(document.body, { childList: true, subtree: true }); };
|
|
430
582
|
if (document.body) start();
|
|
431
583
|
else document.addEventListener('DOMContentLoaded', start);
|
|
432
584
|
} catch (e) {}
|
|
433
585
|
try { window.addEventListener('resize', debounced); } catch (e) {}
|
|
586
|
+
try { setInterval(() => { run(); ozPollSpend(); }, 2000); } catch (e) {}
|
|
587
|
+
try { ozPollSpend(); } catch (e) {}
|
|
434
588
|
}
|
|
435
589
|
|
|
436
590
|
export function spendChipSource() {
|
|
437
591
|
return [
|
|
438
592
|
'(function ozSpendChip(){',
|
|
439
593
|
"'use strict';",
|
|
440
|
-
'if (window.__OZ_SPEND_CHIP__ ===
|
|
441
|
-
'window.__OZ_SPEND_CHIP__ =
|
|
594
|
+
'if (window.__OZ_SPEND_CHIP__ === 16) return;',
|
|
595
|
+
'window.__OZ_SPEND_CHIP__ = 16;',
|
|
442
596
|
chipUsd.toString(),
|
|
443
597
|
labelFromSpendBody.toString(),
|
|
444
598
|
spendLinesOnly.toString(),
|
|
@@ -448,15 +602,19 @@ export function spendChipSource() {
|
|
|
448
602
|
ozSpendHost.toString(),
|
|
449
603
|
ozVisibleSpendText.toString(),
|
|
450
604
|
stripSpendFromText.toString(),
|
|
605
|
+
ozInComposer.toString(),
|
|
451
606
|
ozBlankSpendIn.toString(),
|
|
452
607
|
ozHideSpendLeftovers.toString(),
|
|
453
608
|
ozPreviousMessageCard.toString(),
|
|
454
609
|
ozAttachSpendChip.toString(),
|
|
455
610
|
ozCollapseSpend.toString(),
|
|
611
|
+
ozFloatLabel.toString(),
|
|
456
612
|
ozEnsureFloatSpend.toString(),
|
|
457
613
|
ozSavedFloatPos.toString(),
|
|
458
614
|
ozPlaceFloat.toString(),
|
|
459
615
|
ozDragFloat.toString(),
|
|
616
|
+
ozLabelFromInfo.toString(),
|
|
617
|
+
ozPollSpend.toString(),
|
|
460
618
|
ozWatchSpend.toString(),
|
|
461
619
|
'ozWatchSpend();',
|
|
462
620
|
'})();',
|