openzoo 0.50.92 → 0.50.93

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.
Files changed (2) hide show
  1. package/lib/ozSpendChip.js +67 -17
  2. package/package.json +1 -1
@@ -14,7 +14,7 @@ import { spendChipLabel } from './spendProof.js';
14
14
 
15
15
  export const GROKBOT_CDP_PORT = Number(process.env.OZ_GROKBOT_CDP_PORT || 9444);
16
16
 
17
- /** Session totals for a floating pill when the open canvas has no footer. */
17
+ /** Session totals for the always-on HUD pill. Message chips still fold the footer. */
18
18
  export function sessionSpendLabel(home = os.homedir()) {
19
19
  try {
20
20
  const s = JSON.parse(fs.readFileSync(path.join(home, '.openzoo', 'session.json'), 'utf8'));
@@ -159,7 +159,9 @@ function ozEnsureSpendCss() {
159
159
  }
160
160
  s.textContent = [
161
161
  '.oz-spend{margin:.55rem 0 0;font-size:12px;color:inherit;opacity:.82;max-width:36em}',
162
- '#oz-spend-float>summary{cursor:grab}',
162
+ '#oz-spend-hud{opacity:1}',
163
+ '#oz-spend-hud>summary{cursor:grab;background:rgba(28,28,30,.94);color:#f4f4f5;',
164
+ 'border-color:rgba(255,255,255,.28);box-shadow:0 1px 8px rgba(0,0,0,.35)}',
163
165
  '.oz-spend>summary{cursor:help;list-style:none;display:inline-flex;align-items:center;gap:.35rem;',
164
166
  'padding:3px 9px;border-radius:999px;border:1px solid rgba(255,255,255,.18);white-space:nowrap;',
165
167
  'max-width:100%;overflow:hidden;text-overflow:ellipsis}',
@@ -213,11 +215,19 @@ export function stripSpendFromText(s) {
213
215
  return t;
214
216
  }
215
217
 
218
+ function ozInComposer(el) {
219
+ if (!el) return false;
220
+ if (el.tagName === 'TEXTAREA' || el.tagName === 'INPUT' || el.isContentEditable) return true;
221
+ return !!(el.closest && el.closest('textarea, input, [contenteditable="true"]'));
222
+ }
223
+
216
224
  function ozBlankSpendIn(root) {
225
+ if (ozInComposer(root)) return;
217
226
  const w = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null);
218
227
  while (w.nextNode()) {
219
228
  const tn = w.currentNode;
220
229
  if (tn.parentElement && tn.parentElement.closest && tn.parentElement.closest('.oz-spend')) continue;
230
+ if (ozInComposer(tn.parentElement)) continue;
221
231
  const next = stripSpendFromText(tn.nodeValue || '');
222
232
  if (next !== tn.nodeValue) tn.nodeValue = next;
223
233
  }
@@ -228,6 +238,7 @@ function ozHideSpendLeftovers() {
228
238
  for (let i = 0; i < nodes.length; i += 1) {
229
239
  const el = nodes[i];
230
240
  if (el.closest && el.closest('.oz-spend')) continue;
241
+ if (ozInComposer(el)) continue;
231
242
  if (el.querySelector && el.querySelector('.oz-spend')) continue;
232
243
  const vis = ozVisibleSpendText(el);
233
244
  if (!spendOnlyText(vis)) continue;
@@ -290,10 +301,11 @@ function ozCollapseSpend() {
290
301
  for (let i = 0; i < nodes.length; i += 1) {
291
302
  const el = nodes[i];
292
303
  if (el.closest && el.closest('.oz-spend')) continue;
304
+ if (ozInComposer(el)) continue;
293
305
  const t = ozVisibleSpendText(el);
294
306
  if (!/::oz-spend::|this call \$|spent \$/i.test(t)) continue;
295
307
  const host = ozSpendHost(el);
296
- if (!host || seen.has(host)) continue;
308
+ if (!host || seen.has(host) || ozInComposer(host)) continue;
297
309
  seen.add(host);
298
310
  hosts.push(host);
299
311
  }
@@ -302,10 +314,11 @@ function ozCollapseSpend() {
302
314
  const vis = ozVisibleSpendText(host);
303
315
  const split = splitSpendText(vis);
304
316
  if (!split || !split.body || split.body.length < 12) continue;
317
+ if (split.summary) window.__OZ_SPEND_LAST__ = split.summary;
305
318
  ozEnsureSpendCss();
306
319
  if (spendOnlyText(vis)) {
307
320
  const prev = ozPreviousMessageCard(host);
308
- if (prev && prev !== host) {
321
+ if (prev && prev !== host && !ozInComposer(prev)) {
309
322
  ozAttachSpendChip(prev, split);
310
323
  host.setAttribute('data-oz-spend-hide', '1');
311
324
  continue;
@@ -318,18 +331,46 @@ function ozCollapseSpend() {
318
331
  ozEnsureFloatSpend();
319
332
  }
320
333
 
334
+ /** Live HUD label: latest folded chip, then a read-only canvas scan, then inject snapshot. */
335
+ function ozFloatLabel() {
336
+ const pills = document.querySelectorAll('.oz-spend:not(#oz-spend-hud):not(#oz-spend-float) summary');
337
+ if (pills.length) {
338
+ const lab = String(pills[pills.length - 1].textContent || '').replace(/^ⓘ\s*/, '').trim();
339
+ if (lab) {
340
+ window.__OZ_SPEND_LAST__ = lab;
341
+ return lab;
342
+ }
343
+ }
344
+ try {
345
+ const nodes = document.querySelectorAll('[class*="sand-message"]');
346
+ for (let i = nodes.length - 1; i >= 0; i -= 1) {
347
+ if (ozInComposer(nodes[i])) continue;
348
+ const vis = ozVisibleSpendText(nodes[i]);
349
+ if (!/::oz-spend::|this call \$|spent \$/i.test(vis)) continue;
350
+ const split = splitSpendText(vis);
351
+ if (split && split.summary) {
352
+ window.__OZ_SPEND_LAST__ = split.summary;
353
+ return split.summary;
354
+ }
355
+ }
356
+ } catch (e) {}
357
+ if (window.__OZ_SPEND_LAST__) return String(window.__OZ_SPEND_LAST__);
358
+ return String(window.__OZ_SESSION_SPEND__ || '').trim();
359
+ }
360
+
321
361
  function ozEnsureFloatSpend() {
322
- const label = String(window.__OZ_SESSION_SPEND__ || '').trim();
323
- const msgPills = document.querySelectorAll('.oz-spend:not(#oz-spend-float)').length;
324
- let el = document.getElementById('oz-spend-float');
325
- if (!label || msgPills) {
362
+ const label = ozFloatLabel();
363
+ const leftover = document.getElementById('oz-spend-float');
364
+ if (leftover) leftover.remove();
365
+ let el = document.getElementById('oz-spend-hud');
366
+ if (!label) {
326
367
  if (el) el.remove();
327
368
  return;
328
369
  }
329
370
  ozEnsureSpendCss();
330
371
  if (!el) {
331
372
  el = document.createElement('details');
332
- el.id = 'oz-spend-float';
373
+ el.id = 'oz-spend-hud';
333
374
  el.className = 'oz-spend';
334
375
  const sum = document.createElement('summary');
335
376
  const body = document.createElement('div');
@@ -357,7 +398,7 @@ function ozPlaceFloat(el) {
357
398
  if (!el) return;
358
399
  el.style.position = 'fixed';
359
400
  el.style.zIndex = '2147483646';
360
- el.style.opacity = '0.95';
401
+ el.style.opacity = '1';
361
402
  const saved = ozSavedFloatPos();
362
403
  if (saved) {
363
404
  el.style.left = Math.max(8, saved.left) + 'px';
@@ -416,29 +457,36 @@ function ozDragFloat(el) {
416
457
 
417
458
  function ozWatchSpend() {
418
459
  let t = 0;
460
+ const inComposer = () => ozInComposer(document.activeElement);
419
461
  const run = () => {
420
- const a = document.activeElement;
421
- if (a && (a.tagName === 'TEXTAREA' || a.tagName === 'INPUT' || a.isContentEditable)) return;
422
- try { ozCollapseSpend(); } catch (e) {}
462
+ try {
463
+ if (inComposer()) {
464
+ ozEnsureSpendCss();
465
+ ozEnsureFloatSpend();
466
+ } else {
467
+ ozCollapseSpend();
468
+ }
469
+ } catch (e) {}
423
470
  };
424
- const debounced = () => { clearTimeout(t); t = setTimeout(run, 600); };
471
+ const debounced = () => { clearTimeout(t); t = setTimeout(run, 400); };
425
472
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', run);
426
473
  else run();
427
474
  try {
428
475
  const mo = new MutationObserver(debounced);
429
- const start = () => { if (document.body) mo.observe(document.body, { childList: true, subtree: false }); };
476
+ const start = () => { if (document.body) mo.observe(document.body, { childList: true, subtree: true }); };
430
477
  if (document.body) start();
431
478
  else document.addEventListener('DOMContentLoaded', start);
432
479
  } catch (e) {}
433
480
  try { window.addEventListener('resize', debounced); } catch (e) {}
481
+ try { setInterval(run, 2000); } catch (e) {}
434
482
  }
435
483
 
436
484
  export function spendChipSource() {
437
485
  return [
438
486
  '(function ozSpendChip(){',
439
487
  "'use strict';",
440
- 'if (window.__OZ_SPEND_CHIP__ === 12) return;',
441
- 'window.__OZ_SPEND_CHIP__ = 12;',
488
+ 'if (window.__OZ_SPEND_CHIP__ === 13) return;',
489
+ 'window.__OZ_SPEND_CHIP__ = 13;',
442
490
  chipUsd.toString(),
443
491
  labelFromSpendBody.toString(),
444
492
  spendLinesOnly.toString(),
@@ -448,11 +496,13 @@ export function spendChipSource() {
448
496
  ozSpendHost.toString(),
449
497
  ozVisibleSpendText.toString(),
450
498
  stripSpendFromText.toString(),
499
+ ozInComposer.toString(),
451
500
  ozBlankSpendIn.toString(),
452
501
  ozHideSpendLeftovers.toString(),
453
502
  ozPreviousMessageCard.toString(),
454
503
  ozAttachSpendChip.toString(),
455
504
  ozCollapseSpend.toString(),
505
+ ozFloatLabel.toString(),
456
506
  ozEnsureFloatSpend.toString(),
457
507
  ozSavedFloatPos.toString(),
458
508
  ozPlaceFloat.toString(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.50.92",
3
+ "version": "0.50.93",
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",