@chenlongapps/opencode-token-usage 0.4.1 → 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/source.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { OpenCodeClient, SessionInfo } from "@opencode/client";
2
2
  import type { ContextSources } from "./context-sources.js";
3
3
  import type { PriceCatalog, UsageMessage } from "./usage.js";
4
- export type Session = Pick<SessionInfo, "id" | "parentID" | "fork" | "model" | "location" | "title">;
4
+ export type Session = Pick<SessionInfo, "id" | "parentID" | "fork" | "model" | "location" | "title" | "revert">;
5
5
  export interface Page<T> {
6
6
  data: T[];
7
7
  cursor: {
@@ -31,7 +31,8 @@ export interface Snapshot {
31
31
  messages: Map<string, Map<string, UsageMessage>>;
32
32
  model: ActiveModel;
33
33
  }
34
- export declare function loadSnapshot(source: UsageSource, sessionID: string, signal: AbortSignal): Promise<Snapshot>;
34
+ /** A changed set permits reuse of unchanged histories. Omitting it forces a full read. */
35
+ export declare function loadSnapshot(source: UsageSource, sessionID: string, signal: AbortSignal, previous?: Snapshot, changed?: ReadonlySet<string>): Promise<Snapshot>;
35
36
  /** History of the viewed session only, in API order (`order: "asc"`). */
36
37
  export declare function viewedMessages(snapshot: Snapshot): readonly UsageMessage[];
37
38
  export declare function uniqueMessages(snapshot: Snapshot): Iterable<UsageMessage>;
package/dist/source.js CHANGED
@@ -48,7 +48,8 @@ export async function pages(read, signal) {
48
48
  } while (cursor);
49
49
  return result;
50
50
  }
51
- export async function loadSnapshot(source, sessionID, signal) {
51
+ /** A changed set permits reuse of unchanged histories. Omitting it forces a full read. */
52
+ export async function loadSnapshot(source, sessionID, signal, previous, changed) {
52
53
  const viewed = await source.session(sessionID, signal);
53
54
  let root = viewed;
54
55
  const ancestors = new Set();
@@ -61,26 +62,40 @@ export async function loadSnapshot(source, sessionID, signal) {
61
62
  }
62
63
  const sessions = new Map([[root.id, root]]);
63
64
  const messages = new Map();
64
- // Breadth-first discovery includes unopened descendants, with bounded parallelism.
65
- const queue = [root];
66
- for (let index = 0; index < queue.length; index++) {
67
- const session = queue[index];
68
- const [children, history] = await Promise.all([
69
- pages(cursor => source.children(session.id, cursor, signal), signal),
70
- pages(cursor => source.messages(session.id, cursor, signal), signal),
71
- ]);
72
- messages.set(session.id, new Map(history.map(message => [message.id, message])));
73
- for (const child of children) {
74
- if (child.parentID !== session.id)
75
- throw new Error("Unexpected child session");
76
- if (!sessions.has(child.id)) {
77
- sessions.set(child.id, child);
78
- queue.push(child);
65
+ const cache = previous?.rootID === root.id && previous.viewedID === viewed.id && changed
66
+ ? previous.messages : undefined;
67
+ // Traverse every branch so additions and removals replace the tree atomically. Each
68
+ // wave reads at most four sessions concurrently; pagination within one stays ordered.
69
+ let frontier = [root];
70
+ while (frontier.length) {
71
+ const next = [];
72
+ for (let offset = 0; offset < frontier.length; offset += 4) {
73
+ signal.throwIfAborted();
74
+ const batch = frontier.slice(offset, offset + 4);
75
+ const results = await Promise.all(batch.map(async (session) => {
76
+ const reused = !changed?.has(session.id) ? cache?.get(session.id) : undefined;
77
+ const children = await pages(cursor => source.children(session.id, cursor, signal), signal);
78
+ const history = reused ?? new Map((await pages(cursor => source.messages(session.id, cursor, signal), signal))
79
+ .map(message => [message.id, message]));
80
+ return { session, children, history };
81
+ }));
82
+ for (const { session, children, history } of results) {
83
+ messages.set(session.id, history);
84
+ for (const child of children) {
85
+ if (child.parentID !== session.id)
86
+ throw new Error("Unexpected child session");
87
+ if (!sessions.has(child.id)) {
88
+ sessions.set(child.id, child);
89
+ next.push(child);
90
+ }
91
+ }
79
92
  }
80
93
  }
94
+ frontier = next;
81
95
  }
82
96
  if (!sessions.has(viewed.id))
83
97
  throw new Error("Session tree changed during refresh");
98
+ sessions.set(viewed.id, viewed);
84
99
  const model = await source.model(viewed, signal);
85
100
  signal.throwIfAborted();
86
101
  return { rootID: root.id, viewedID: viewed.id, sessions, messages, model };
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,