@chenlongapps/opencode-token-usage 0.4.2 → 0.4.3

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/dist/tui.js CHANGED
@@ -14,7 +14,7 @@ import { UsageController } from "./controller.js";
14
14
  import { PerformanceMonitor } from "./performance.js";
15
15
  import { breakdownRows } from "./context-sources.js";
16
16
  import { createSource } from "./source.js";
17
- import { bar, countLabel, formatCompact, formatEstimatedCost, formatTokens, requestRows, summaryRows, usageRows } from "./usage.js";
17
+ import { bar, countLabel, formatCompact, formatEstimatedCost, formatRateTier, formatTokens, rateRows, requestRows, summaryRows, usageRows } from "./usage.js";
18
18
  function UsageView(props) {
19
19
  const rows = createMemo(() => usageRows(props.state().summary, props.state().context, props.state().performance));
20
20
  const performanceStart = createMemo(() => rows().findIndex(([label]) => label === "TPS" || label === "TTFT"));
@@ -333,6 +333,8 @@ function UsageDialog(props) {
333
333
  _$setProp(_el$19, "gap", 2);
334
334
  _$setProp(_el$20, "flexShrink", 0);
335
335
  _$insert(_el$20, label);
336
+ _$setProp(_el$21, "wrapMode", "word");
337
+ _$setProp(_el$21, "minWidth", 0);
336
338
  _$insert(_el$21, value);
337
339
  _$effect(_p$ => {
338
340
  var _v$8 = theme().muted,
@@ -398,12 +400,12 @@ function UsageDialog(props) {
398
400
  _el$30 = _$createElement("text"),
399
401
  _el$31 = _$createElement("b"),
400
402
  _el$33 = _$createElement("text"),
401
- _el$60 = _$createElement("box"),
402
- _el$61 = _$createElement("text"),
403
+ _el$62 = _$createElement("box"),
403
404
  _el$63 = _$createElement("text"),
404
- _el$65 = _$createElement("text");
405
+ _el$65 = _$createElement("text"),
406
+ _el$67 = _$createElement("text");
405
407
  _$insertNode(_el$28, _el$29);
406
- _$insertNode(_el$28, _el$60);
408
+ _$insertNode(_el$28, _el$62);
407
409
  _$setProp(_el$28, "paddingLeft", 2);
408
410
  _$setProp(_el$28, "paddingRight", 2);
409
411
  _$setProp(_el$28, "paddingBottom", 1);
@@ -428,7 +430,7 @@ function UsageDialog(props) {
428
430
  _$effect(_$p => _$setProp(_el$35, "fg", theme().muted, _$p));
429
431
  return _el$35;
430
432
  }
431
- }), _el$60);
433
+ }), _el$62);
432
434
  _$insert(_el$28, _$createComponent(Show, {
433
435
  get when() {
434
436
  return state().status !== "ready";
@@ -439,7 +441,7 @@ function UsageDialog(props) {
439
441
  _$effect(_$p => _$setProp(_el$36, "fg", theme().muted, _$p));
440
442
  return _el$36;
441
443
  }
442
- }), _el$60);
444
+ }), _el$62);
443
445
  _$insert(_el$28, _$createComponent(Show, {
444
446
  get when() {
445
447
  return state().summary;
@@ -488,48 +490,48 @@ function UsageDialog(props) {
488
490
  },
489
491
  get fallback() {
490
492
  return (() => {
491
- var _el$67 = _$createElement("text");
492
- _$insertNode(_el$67, _$createTextNode(`Context usage unavailable`));
493
- _$effect(_$p => _$setProp(_el$67, "fg", theme().muted, _$p));
494
- return _el$67;
493
+ var _el$69 = _$createElement("text");
494
+ _$insertNode(_el$69, _$createTextNode(`Context usage unavailable`));
495
+ _$effect(_$p => _$setProp(_el$69, "fg", theme().muted, _$p));
496
+ return _el$69;
495
497
  })();
496
498
  },
497
499
  children: details => (() => {
498
- var _el$69 = _$createElement("box"),
499
- _el$70 = _$createElement("box"),
500
- _el$71 = _$createElement("text"),
500
+ var _el$71 = _$createElement("box"),
501
+ _el$72 = _$createElement("box"),
501
502
  _el$73 = _$createElement("text"),
502
- _el$74 = _$createTextNode(` / `),
503
- _el$75 = _$createTextNode(` (`),
504
- _el$76 = _$createTextNode(`%)`);
505
- _$insertNode(_el$69, _el$70);
506
- _$insertNode(_el$70, _el$71);
507
- _$insertNode(_el$70, _el$73);
508
- _$setProp(_el$70, "flexDirection", "row");
509
- _$setProp(_el$70, "justifyContent", "space-between");
510
- _$setProp(_el$70, "gap", 2);
511
- _$insertNode(_el$71, _$createTextNode(`Used / Limit`));
512
- _$setProp(_el$71, "flexShrink", 0);
513
- _$insertNode(_el$73, _el$74);
514
- _$insertNode(_el$73, _el$75);
515
- _$insertNode(_el$73, _el$76);
516
- _$setProp(_el$73, "wrapMode", "word");
517
- _$setProp(_el$73, "minWidth", 0);
518
- _$insert(_el$73, () => number(details().usage.used), _el$74);
519
- _$insert(_el$73, () => number(details().usage.limit), _el$75);
520
- _$insert(_el$73, () => details().usage.percent.toFixed(1), _el$76);
521
- _$insert(_el$69, () => barRow(details().usage.percent, windowBar()), null);
503
+ _el$75 = _$createElement("text"),
504
+ _el$76 = _$createTextNode(` / `),
505
+ _el$77 = _$createTextNode(` (`),
506
+ _el$78 = _$createTextNode(`%)`);
507
+ _$insertNode(_el$71, _el$72);
508
+ _$insertNode(_el$72, _el$73);
509
+ _$insertNode(_el$72, _el$75);
510
+ _$setProp(_el$72, "flexDirection", "row");
511
+ _$setProp(_el$72, "justifyContent", "space-between");
512
+ _$setProp(_el$72, "gap", 2);
513
+ _$insertNode(_el$73, _$createTextNode(`Used / Limit`));
514
+ _$setProp(_el$73, "flexShrink", 0);
515
+ _$insertNode(_el$75, _el$76);
516
+ _$insertNode(_el$75, _el$77);
517
+ _$insertNode(_el$75, _el$78);
518
+ _$setProp(_el$75, "wrapMode", "word");
519
+ _$setProp(_el$75, "minWidth", 0);
520
+ _$insert(_el$75, () => number(details().usage.used), _el$76);
521
+ _$insert(_el$75, () => number(details().usage.limit), _el$77);
522
+ _$insert(_el$75, () => details().usage.percent.toFixed(1), _el$78);
523
+ _$insert(_el$71, () => barRow(details().usage.percent, windowBar()), null);
522
524
  _$effect(_p$ => {
523
525
  var _v$21 = theme().muted,
524
526
  _v$22 = theme().base;
525
- _v$21 !== _p$.e && (_p$.e = _$setProp(_el$71, "fg", _v$21, _p$.e));
526
- _v$22 !== _p$.t && (_p$.t = _$setProp(_el$73, "fg", _v$22, _p$.t));
527
+ _v$21 !== _p$.e && (_p$.e = _$setProp(_el$73, "fg", _v$21, _p$.e));
528
+ _v$22 !== _p$.t && (_p$.t = _$setProp(_el$75, "fg", _v$22, _p$.t));
527
529
  return _p$;
528
530
  }, {
529
531
  e: undefined,
530
532
  t: undefined
531
533
  });
532
- return _el$69;
534
+ return _el$71;
533
535
  })()
534
536
  }), null);
535
537
  _$insertNode(_el$43, _el$44);
@@ -544,10 +546,10 @@ function UsageDialog(props) {
544
546
  return sources();
545
547
  },
546
548
  children: captured => (() => {
547
- var _el$77 = _$createElement("text");
548
- _$insert(_el$77, () => new Date(captured().capturedAt).toLocaleTimeString());
549
- _$effect(_$p => _$setProp(_el$77, "fg", theme().muted, _$p));
550
- return _el$77;
549
+ var _el$79 = _$createElement("text");
550
+ _$insert(_el$79, () => new Date(captured().capturedAt).toLocaleTimeString());
551
+ _$effect(_$p => _$setProp(_el$79, "fg", theme().muted, _$p));
552
+ return _el$79;
551
553
  })()
552
554
  }), null);
553
555
  _$insert(_el$43, _$createComponent(Show, {
@@ -556,16 +558,16 @@ function UsageDialog(props) {
556
558
  },
557
559
  get fallback() {
558
560
  return (() => {
559
- var _el$78 = _$createElement("text");
560
- _$insertNode(_el$78, _$createTextNode(`Request composition unavailable`));
561
- _$effect(_$p => _$setProp(_el$78, "fg", theme().muted, _$p));
562
- return _el$78;
561
+ var _el$80 = _$createElement("text");
562
+ _$insertNode(_el$80, _$createTextNode(`Request composition unavailable`));
563
+ _$effect(_$p => _$setProp(_el$80, "fg", theme().muted, _$p));
564
+ return _el$80;
563
565
  })();
564
566
  },
565
567
  children: details => (() => {
566
- var _el$80 = _$createElement("box");
567
- _$insert(_el$80, () => requestRowsList(requestRows(details(), compact())));
568
- return _el$80;
568
+ var _el$82 = _$createElement("box");
569
+ _$insert(_el$82, () => requestRowsList(requestRows(details(), compact())));
570
+ return _el$82;
569
571
  })()
570
572
  }), null);
571
573
  _$insertNode(_el$48, _el$49);
@@ -577,10 +579,10 @@ function UsageDialog(props) {
577
579
  },
578
580
  get fallback() {
579
581
  return (() => {
580
- var _el$81 = _$createElement("text");
581
- _$insertNode(_el$81, _$createTextNode(`Source estimates unavailable (no request snapshot or RPC)`));
582
- _$effect(_$p => _$setProp(_el$81, "fg", theme().muted, _$p));
583
- return _el$81;
582
+ var _el$83 = _$createElement("text");
583
+ _$insertNode(_el$83, _$createTextNode(`Source estimates unavailable (no request snapshot or RPC)`));
584
+ _$effect(_$p => _$setProp(_el$83, "fg", theme().muted, _$p));
585
+ return _el$83;
584
586
  })();
585
587
  },
586
588
  children: captured => _$createComponent(For, {
@@ -588,39 +590,39 @@ function UsageDialog(props) {
588
590
  return breakdownRows(captured(), detailed());
589
591
  },
590
592
  children: row => (() => {
591
- var _el$83 = _$createElement("box"),
592
- _el$84 = _$createElement("box"),
593
- _el$85 = _$createElement("text"),
593
+ var _el$85 = _$createElement("box"),
594
594
  _el$86 = _$createElement("box"),
595
595
  _el$87 = _$createElement("text"),
596
- _el$88 = _$createElement("text"),
597
- _el$89 = _$createTextNode(`%`);
598
- _$insertNode(_el$83, _el$84);
599
- _$insertNode(_el$83, _el$86);
600
- _$insertNode(_el$83, _el$87);
601
- _$insertNode(_el$83, _el$88);
602
- _$setProp(_el$83, "flexDirection", "row");
603
- _$setProp(_el$83, "gap", 1);
604
- _$insertNode(_el$84, _el$85);
605
- _$setProp(_el$84, "width", 14);
606
- _$setProp(_el$84, "flexShrink", 0);
607
- _$insert(_el$85, () => row.label);
596
+ _el$88 = _$createElement("box"),
597
+ _el$89 = _$createElement("text"),
598
+ _el$90 = _$createElement("text"),
599
+ _el$91 = _$createTextNode(`%`);
600
+ _$insertNode(_el$85, _el$86);
601
+ _$insertNode(_el$85, _el$88);
602
+ _$insertNode(_el$85, _el$89);
603
+ _$insertNode(_el$85, _el$90);
604
+ _$setProp(_el$85, "flexDirection", "row");
605
+ _$setProp(_el$85, "gap", 1);
606
+ _$insertNode(_el$86, _el$87);
607
+ _$setProp(_el$86, "width", 14);
608
608
  _$setProp(_el$86, "flexShrink", 0);
609
- _$insert(_el$86, () => barRow(row.percent, breakdownBar()));
610
- _$setProp(_el$87, "flexShrink", 0);
611
- _$insert(_el$87, () => number(row.tokens));
612
- _$insertNode(_el$88, _el$89);
609
+ _$insert(_el$87, () => row.label);
613
610
  _$setProp(_el$88, "flexShrink", 0);
614
- _$insert(_el$88, () => row.percent.toFixed(1), _el$89);
611
+ _$insert(_el$88, () => barRow(row.percent, breakdownBar()));
612
+ _$setProp(_el$89, "flexShrink", 0);
613
+ _$insert(_el$89, () => number(row.tokens));
614
+ _$insertNode(_el$90, _el$91);
615
+ _$setProp(_el$90, "flexShrink", 0);
616
+ _$insert(_el$90, () => row.percent.toFixed(1), _el$91);
615
617
  _$effect(_p$ => {
616
618
  var _v$23 = theme().muted,
617
619
  _v$24 = breakdownBar(),
618
620
  _v$25 = theme().base,
619
621
  _v$26 = theme().muted;
620
- _v$23 !== _p$.e && (_p$.e = _$setProp(_el$85, "fg", _v$23, _p$.e));
621
- _v$24 !== _p$.t && (_p$.t = _$setProp(_el$86, "width", _v$24, _p$.t));
622
- _v$25 !== _p$.a && (_p$.a = _$setProp(_el$87, "fg", _v$25, _p$.a));
623
- _v$26 !== _p$.o && (_p$.o = _$setProp(_el$88, "fg", _v$26, _p$.o));
622
+ _v$23 !== _p$.e && (_p$.e = _$setProp(_el$87, "fg", _v$23, _p$.e));
623
+ _v$24 !== _p$.t && (_p$.t = _$setProp(_el$88, "width", _v$24, _p$.t));
624
+ _v$25 !== _p$.a && (_p$.a = _$setProp(_el$89, "fg", _v$25, _p$.a));
625
+ _v$26 !== _p$.o && (_p$.o = _$setProp(_el$90, "fg", _v$26, _p$.o));
624
626
  return _p$;
625
627
  }, {
626
628
  e: undefined,
@@ -628,7 +630,7 @@ function UsageDialog(props) {
628
630
  a: undefined,
629
631
  o: undefined
630
632
  });
631
- return _el$83;
633
+ return _el$85;
632
634
  })()
633
635
  })
634
636
  }), null);
@@ -641,10 +643,10 @@ function UsageDialog(props) {
641
643
  },
642
644
  get fallback() {
643
645
  return (() => {
644
- var _el$90 = _$createElement("text");
645
- _$insertNode(_el$90, _$createTextNode(`Session usage unavailable`));
646
- _$effect(_$p => _$setProp(_el$90, "fg", theme().muted, _$p));
647
- return _el$90;
646
+ var _el$92 = _$createElement("text");
647
+ _$insertNode(_el$92, _$createTextNode(`Session usage unavailable`));
648
+ _$effect(_$p => _$setProp(_el$92, "fg", theme().muted, _$p));
649
+ return _el$92;
648
650
  })();
649
651
  },
650
652
  children: summary => _$createComponent(Show, {
@@ -653,26 +655,26 @@ function UsageDialog(props) {
653
655
  },
654
656
  get fallback() {
655
657
  return (() => {
656
- var _el$92 = _$createElement("text"),
657
- _el$93 = _$createTextNode(` · `),
658
- _el$94 = _$createTextNode(` · `),
659
- _el$95 = _$createTextNode(` tokens · `),
660
- _el$96 = _$createTextNode(`% cached`);
661
- _$insertNode(_el$92, _el$93);
662
- _$insertNode(_el$92, _el$94);
663
- _$insertNode(_el$92, _el$95);
664
- _$insertNode(_el$92, _el$96);
665
- _$setProp(_el$92, "wrapMode", "word");
666
- _$insert(_el$92, () => countLabel(summary().steps, "step"), _el$93);
667
- _$insert(_el$92, () => countLabel(summary().calls, "call"), _el$94);
668
- _$insert(_el$92, () => formatCompact(summary().total), _el$95);
669
- _$insert(_el$92, () => (summary().cacheRate * 100).toFixed(1), _el$96);
670
- _$insert(_el$92, (() => {
658
+ var _el$94 = _$createElement("text"),
659
+ _el$95 = _$createTextNode(` · `),
660
+ _el$96 = _$createTextNode(` · `),
661
+ _el$97 = _$createTextNode(` tokens · `),
662
+ _el$98 = _$createTextNode(`% cached`);
663
+ _$insertNode(_el$94, _el$95);
664
+ _$insertNode(_el$94, _el$96);
665
+ _$insertNode(_el$94, _el$97);
666
+ _$insertNode(_el$94, _el$98);
667
+ _$setProp(_el$94, "wrapMode", "word");
668
+ _$insert(_el$94, () => countLabel(summary().steps, "step"), _el$95);
669
+ _$insert(_el$94, () => countLabel(summary().calls, "call"), _el$96);
670
+ _$insert(_el$94, () => formatCompact(summary().total), _el$97);
671
+ _$insert(_el$94, () => (summary().cacheRate * 100).toFixed(1), _el$98);
672
+ _$insert(_el$94, (() => {
671
673
  var _c$ = _$memo(() => !!formatEstimatedCost(summary().cost, summary().costStatus));
672
674
  return () => _c$() ? ` · ${formatEstimatedCost(summary().cost, summary().costStatus)}` : "";
673
675
  })(), null);
674
- _$effect(_$p => _$setProp(_el$92, "fg", theme().base, _$p));
675
- return _el$92;
676
+ _$effect(_$p => _$setProp(_el$94, "fg", theme().base, _$p));
677
+ return _el$94;
676
678
  })();
677
679
  },
678
680
  get children() {
@@ -681,28 +683,28 @@ function UsageDialog(props) {
681
683
  return summaryRows(summary());
682
684
  },
683
685
  children: ([label, value]) => (() => {
684
- var _el$97 = _$createElement("box"),
685
- _el$98 = _$createElement("text"),
686
- _el$99 = _$createElement("text");
687
- _$insertNode(_el$97, _el$98);
688
- _$insertNode(_el$97, _el$99);
689
- _$setProp(_el$97, "flexDirection", "row");
690
- _$setProp(_el$97, "justifyContent", "space-between");
691
- _$setProp(_el$97, "gap", 2);
692
- _$setProp(_el$98, "flexShrink", 0);
693
- _$insert(_el$98, label);
694
- _$insert(_el$99, value);
686
+ var _el$99 = _$createElement("box"),
687
+ _el$100 = _$createElement("text"),
688
+ _el$101 = _$createElement("text");
689
+ _$insertNode(_el$99, _el$100);
690
+ _$insertNode(_el$99, _el$101);
691
+ _$setProp(_el$99, "flexDirection", "row");
692
+ _$setProp(_el$99, "justifyContent", "space-between");
693
+ _$setProp(_el$99, "gap", 2);
694
+ _$setProp(_el$100, "flexShrink", 0);
695
+ _$insert(_el$100, label);
696
+ _$insert(_el$101, value);
695
697
  _$effect(_p$ => {
696
698
  var _v$27 = theme().muted,
697
699
  _v$28 = theme().base;
698
- _v$27 !== _p$.e && (_p$.e = _$setProp(_el$98, "fg", _v$27, _p$.e));
699
- _v$28 !== _p$.t && (_p$.t = _$setProp(_el$99, "fg", _v$28, _p$.t));
700
+ _v$27 !== _p$.e && (_p$.e = _$setProp(_el$100, "fg", _v$27, _p$.e));
701
+ _v$28 !== _p$.t && (_p$.t = _$setProp(_el$101, "fg", _v$28, _p$.t));
700
702
  return _p$;
701
703
  }, {
702
704
  e: undefined,
703
705
  t: undefined
704
706
  });
705
- return _el$97;
707
+ return _el$99;
706
708
  })()
707
709
  });
708
710
  }
@@ -711,16 +713,28 @@ function UsageDialog(props) {
711
713
  _$insertNode(_el$56, _el$57);
712
714
  _$insertNode(_el$57, _el$58);
713
715
  _$insertNode(_el$58, _$createTextNode(`By Model`));
716
+ _$insert(_el$56, _$createComponent(Show, {
717
+ get when() {
718
+ return _$memo(() => !!detailed())() && models().length;
719
+ },
720
+ get children() {
721
+ var _el$60 = _$createElement("text");
722
+ _$insertNode(_el$60, _$createTextNode(`Rates used for Est. Cost · USD / 1M text tokens · incoming = Input + Cache Read + Cache Write`));
723
+ _$setProp(_el$60, "wrapMode", "word");
724
+ _$effect(_$p => _$setProp(_el$60, "fg", theme().muted, _$p));
725
+ return _el$60;
726
+ }
727
+ }), null);
714
728
  _$insert(_el$56, _$createComponent(Show, {
715
729
  get when() {
716
730
  return models().length;
717
731
  },
718
732
  get fallback() {
719
733
  return (() => {
720
- var _el$100 = _$createElement("text");
721
- _$insertNode(_el$100, _$createTextNode(`No model usage yet`));
722
- _$effect(_$p => _$setProp(_el$100, "fg", theme().muted, _$p));
723
- return _el$100;
734
+ var _el$102 = _$createElement("text");
735
+ _$insertNode(_el$102, _$createTextNode(`No model usage yet`));
736
+ _$effect(_$p => _$setProp(_el$102, "fg", theme().muted, _$p));
737
+ return _el$102;
724
738
  })();
725
739
  },
726
740
  get children() {
@@ -729,42 +743,84 @@ function UsageDialog(props) {
729
743
  return models();
730
744
  },
731
745
  children: model => (() => {
732
- var _el$102 = _$createElement("box"),
733
- _el$103 = _$createElement("box"),
734
- _el$104 = _$createElement("text"),
735
- _el$105 = _$createElement("text"),
746
+ var _el$104 = _$createElement("box"),
747
+ _el$105 = _$createElement("box"),
736
748
  _el$106 = _$createElement("text"),
737
- _el$107 = _$createTextNode(` tokens · `);
738
- _$insertNode(_el$102, _el$103);
739
- _$insertNode(_el$102, _el$106);
740
- _$insertNode(_el$103, _el$104);
741
- _$insertNode(_el$103, _el$105);
742
- _$setProp(_el$103, "flexDirection", "row");
743
- _$setProp(_el$103, "justifyContent", "space-between");
744
- _$setProp(_el$103, "gap", 2);
745
- _$setProp(_el$104, "wrapMode", "word");
746
- _$setProp(_el$104, "minWidth", 0);
747
- _$setProp(_el$104, "flexGrow", 1);
748
- _$insert(_el$104, () => model.model);
749
- _$setProp(_el$105, "flexShrink", 0);
750
- _$insert(_el$105, () => formatEstimatedCost(model.cost, model.costStatus) ?? "");
751
- _$insertNode(_el$106, _el$107);
752
- _$insert(_el$106, () => number(model.tokens), _el$107);
753
- _$insert(_el$106, () => countLabel(model.calls, "call"), null);
749
+ _el$107 = _$createElement("text"),
750
+ _el$108 = _$createElement("text"),
751
+ _el$109 = _$createTextNode(` tokens · `);
752
+ _$insertNode(_el$104, _el$105);
753
+ _$insertNode(_el$104, _el$108);
754
+ _$insertNode(_el$105, _el$106);
755
+ _$insertNode(_el$105, _el$107);
756
+ _$setProp(_el$105, "flexDirection", "row");
757
+ _$setProp(_el$105, "justifyContent", "space-between");
758
+ _$setProp(_el$105, "gap", 2);
759
+ _$setProp(_el$106, "wrapMode", "word");
760
+ _$setProp(_el$106, "minWidth", 0);
761
+ _$setProp(_el$106, "flexGrow", 1);
762
+ _$insert(_el$106, () => model.model);
763
+ _$setProp(_el$107, "flexShrink", 0);
764
+ _$insert(_el$107, () => formatEstimatedCost(model.cost, model.costStatus) ?? "");
765
+ _$insertNode(_el$108, _el$109);
766
+ _$insert(_el$108, () => number(model.tokens), _el$109);
767
+ _$insert(_el$108, () => countLabel(model.calls, "call"), null);
768
+ _$insert(_el$104, _$createComponent(Show, {
769
+ get when() {
770
+ return detailed();
771
+ },
772
+ get children() {
773
+ return [_$createComponent(For, {
774
+ get each() {
775
+ return model.appliedRates;
776
+ },
777
+ children: rates => (() => {
778
+ var _el$112 = _$createElement("box"),
779
+ _el$113 = _$createElement("text"),
780
+ _el$114 = _$createTextNode(` · `),
781
+ _el$115 = _$createTextNode(` · `);
782
+ _$insertNode(_el$112, _el$113);
783
+ _$setProp(_el$112, "marginTop", 1);
784
+ _$insertNode(_el$113, _el$114);
785
+ _$insertNode(_el$113, _el$115);
786
+ _$setProp(_el$113, "wrapMode", "word");
787
+ _$insert(_el$113, () => rates.source, _el$114);
788
+ _$insert(_el$113, () => formatRateTier(rates), _el$115);
789
+ _$insert(_el$113, () => countLabel(rates.calls, "call"), null);
790
+ _$insert(_el$112, () => requestRowsList(rateRows(rates)), null);
791
+ _$effect(_$p => _$setProp(_el$113, "fg", theme().muted, _$p));
792
+ return _el$112;
793
+ })()
794
+ }), _$createComponent(Show, {
795
+ get when() {
796
+ return model.unpricedCalls > 0;
797
+ },
798
+ get children() {
799
+ var _el$110 = _$createElement("text"),
800
+ _el$111 = _$createTextNode(`Pricing unavailable for `);
801
+ _$insertNode(_el$110, _el$111);
802
+ _$setProp(_el$110, "wrapMode", "word");
803
+ _$insert(_el$110, () => countLabel(model.unpricedCalls, "call"), null);
804
+ _$effect(_$p => _$setProp(_el$110, "fg", theme().muted, _$p));
805
+ return _el$110;
806
+ }
807
+ })];
808
+ }
809
+ }), null);
754
810
  _$effect(_p$ => {
755
811
  var _v$29 = theme().base,
756
812
  _v$30 = theme().base,
757
813
  _v$31 = theme().muted;
758
- _v$29 !== _p$.e && (_p$.e = _$setProp(_el$104, "fg", _v$29, _p$.e));
759
- _v$30 !== _p$.t && (_p$.t = _$setProp(_el$105, "fg", _v$30, _p$.t));
760
- _v$31 !== _p$.a && (_p$.a = _$setProp(_el$106, "fg", _v$31, _p$.a));
814
+ _v$29 !== _p$.e && (_p$.e = _$setProp(_el$106, "fg", _v$29, _p$.e));
815
+ _v$30 !== _p$.t && (_p$.t = _$setProp(_el$107, "fg", _v$30, _p$.t));
816
+ _v$31 !== _p$.a && (_p$.a = _$setProp(_el$108, "fg", _v$31, _p$.a));
761
817
  return _p$;
762
818
  }, {
763
819
  e: undefined,
764
820
  t: undefined,
765
821
  a: undefined
766
822
  });
767
- return _el$102;
823
+ return _el$104;
768
824
  })()
769
825
  });
770
826
  }
@@ -793,17 +849,17 @@ function UsageDialog(props) {
793
849
  });
794
850
  return _el$37;
795
851
  }
796
- }), _el$60);
797
- _$insertNode(_el$60, _el$61);
798
- _$insertNode(_el$60, _el$63);
799
- _$insertNode(_el$60, _el$65);
800
- _$setProp(_el$60, "flexDirection", "row");
801
- _$insertNode(_el$61, _$createTextNode(`↑/↓ scroll · `));
802
- _$insertNode(_el$63, _$createTextNode(`d details`));
803
- _$setProp(_el$63, "onMouseUp", event => {
852
+ }), _el$62);
853
+ _$insertNode(_el$62, _el$63);
854
+ _$insertNode(_el$62, _el$65);
855
+ _$insertNode(_el$62, _el$67);
856
+ _$setProp(_el$62, "flexDirection", "row");
857
+ _$insertNode(_el$63, _$createTextNode(`↑/↓ scroll · `));
858
+ _$insertNode(_el$65, _$createTextNode(`d details`));
859
+ _$setProp(_el$65, "onMouseUp", event => {
804
860
  if (event.button === 0) toggleDetails();
805
861
  });
806
- _$insertNode(_el$65, _$createTextNode(` · esc close`));
862
+ _$insertNode(_el$67, _$createTextNode(` · esc close`));
807
863
  _$effect(_p$ => {
808
864
  var _v$16 = theme().base,
809
865
  _v$17 = theme().muted,
@@ -812,9 +868,9 @@ function UsageDialog(props) {
812
868
  _v$20 = theme().muted;
813
869
  _v$16 !== _p$.e && (_p$.e = _$setProp(_el$30, "fg", _v$16, _p$.e));
814
870
  _v$17 !== _p$.t && (_p$.t = _$setProp(_el$33, "fg", _v$17, _p$.t));
815
- _v$18 !== _p$.a && (_p$.a = _$setProp(_el$61, "fg", _v$18, _p$.a));
816
- _v$19 !== _p$.o && (_p$.o = _$setProp(_el$63, "fg", _v$19, _p$.o));
817
- _v$20 !== _p$.i && (_p$.i = _$setProp(_el$65, "fg", _v$20, _p$.i));
871
+ _v$18 !== _p$.a && (_p$.a = _$setProp(_el$63, "fg", _v$18, _p$.a));
872
+ _v$19 !== _p$.o && (_p$.o = _$setProp(_el$65, "fg", _v$19, _p$.o));
873
+ _v$20 !== _p$.i && (_p$.i = _$setProp(_el$67, "fg", _v$20, _p$.i));
818
874
  return _p$;
819
875
  }, {
820
876
  e: undefined,
package/dist/usage.d.ts CHANGED
@@ -85,6 +85,20 @@ export declare function estimate(tokens: Tokens, prices?: readonly Price[]): {
85
85
  defaultPrice: boolean;
86
86
  };
87
87
  export type CostStatus = "empty" | "complete" | "partial" | "unavailable";
88
+ export type PriceSource = "OpenCode" | "Built-in snapshot";
89
+ export interface AppliedRates {
90
+ source: PriceSource;
91
+ lowerExclusive: number | undefined;
92
+ upperInclusive: number | undefined;
93
+ calls: number;
94
+ rates: {
95
+ input: number | undefined;
96
+ output: number | undefined;
97
+ reasoning: number | undefined;
98
+ cacheRead: number | undefined;
99
+ cacheWrite: number | undefined;
100
+ };
101
+ }
88
102
  /** Prices every call with its recorded model. A complete non-zero OpenCode
89
103
  * price wins; a complete snapshot price can replace a complete OpenCode zero.
90
104
  * Incomplete OpenCode prices fall back to the snapshot as a whole. */
@@ -104,6 +118,8 @@ export interface ModelCost {
104
118
  tokens: number;
105
119
  cost: number;
106
120
  costStatus: CostStatus;
121
+ appliedRates: readonly AppliedRates[];
122
+ unpricedCalls: number;
107
123
  }
108
124
  /** Groups the same per-message estimates used by the tree total; unlabelled calls stay visible. */
109
125
  export declare function summarizeModels(messages: Iterable<UsageMessage>, catalog?: PriceCatalog): ModelCost[];
@@ -116,11 +132,15 @@ export interface ContextDetails {
116
132
  usage: ContextUsage;
117
133
  tokens: Tokens;
118
134
  }
119
- export declare function contextDetails(messages: readonly UsageMessage[], limit?: number): ContextDetails | undefined;
120
- export declare function contextUsage(messages: readonly UsageMessage[], limit?: number): ContextUsage | undefined;
135
+ export declare function contextDetails(messages: readonly UsageMessage[], limit?: number, revertMessageID?: string): ContextDetails | undefined;
136
+ export declare function contextUsage(messages: readonly UsageMessage[], limit?: number, revertMessageID?: string): ContextUsage | undefined;
121
137
  export declare function formatTokens(value: number): string;
122
138
  export declare const formatCost: (value: number) => string;
123
139
  export declare function formatEstimatedCost(cost: number, status: CostStatus): string | undefined;
140
+ /** Per-million rates need more precision than a rounded total cost. */
141
+ export declare function formatRate(value: number | undefined): string;
142
+ export declare function formatRateTier(value: Pick<AppliedRates, "lowerExclusive" | "upperInclusive">): string;
143
+ export declare function rateRows(value: AppliedRates): readonly (readonly [string, string])[];
124
144
  /** Compact display for scan-first views: 812, 139.4K, 3.70M. Detailed views keep formatTokens. */
125
145
  export declare function formatCompact(value: number): string;
126
146
  /** Splits a percentage into filled and empty cell counts for a plain-text bar. */