@cortexkit/opencode-anthropic-auth 1.15.1 → 1.17.0

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.
@@ -11,6 +11,7 @@ import { createElement as _$createElement } from "opentui:runtime-module:%40open
11
11
  import { readFileSync } from "node:fs";
12
12
  import { dirname, join } from "node:path";
13
13
  import { fileURLToPath } from "node:url";
14
+ import { formatQuotaMoney } from "@cortexkit/anthropic-auth-core";
14
15
  import { createEffect, createSignal, For, onCleanup, Show } from "opentui:runtime-module:solid-js";
15
16
  import { createRpcClient } from "./rpc/rpc-client.js";
16
17
  import { getRpcDir } from "./rpc/rpc-dir.js";
@@ -265,7 +266,7 @@ function QuotaRow(props) {
265
266
  return _el$21;
266
267
  })()
267
268
  }), _el$11);
268
- _$insert(_el$11, () => ` ${String(Math.round(used())).padStart(3)}%`);
269
+ _$insert(_el$11, () => ` ${String(Math.round(used())).padStart(3)}%${props.binding ? ' •' : ''}`);
269
270
  _$insert(_el$0, _$createComponent(Show, {
270
271
  get when() {
271
272
  return reset();
@@ -342,7 +343,7 @@ function AccountBlock(props) {
342
343
  _$setProp(_el$23, "flexDirection", 'row');
343
344
  _$setProp(_el$23, "justifyContent", 'space-between');
344
345
  _$insertNode(_el$24, _el$25);
345
- _$insert(_el$25, () => props.name);
346
+ _$insert(_el$25, () => `${props.name}${props.tierLabel ? ` · ${props.tierLabel}` : ''}`);
346
347
  _$insertNode(_el$26, _el$27);
347
348
  _$insert(_el$27, statusWord);
348
349
  _$insert(_el$22, _$createComponent(Show, {
@@ -351,10 +352,10 @@ function AccountBlock(props) {
351
352
  },
352
353
  get fallback() {
353
354
  return (() => {
354
- var _el$28 = _$createElement("text");
355
- _$insertNode(_el$28, _$createTextNode(`checking…`));
356
- _$effect(_$p => _$setProp(_el$28, "fg", props.theme.textMuted, _$p));
357
- return _el$28;
355
+ var _el$30 = _$createElement("text");
356
+ _$insertNode(_el$30, _$createTextNode(`checking…`));
357
+ _$effect(_$p => _$setProp(_el$30, "fg", props.theme.textMuted, _$p));
358
+ return _el$30;
358
359
  })();
359
360
  },
360
361
  get children() {
@@ -371,6 +372,9 @@ function AccountBlock(props) {
371
372
  },
372
373
  get pacing() {
373
374
  return pacingFor(props.quota?.five_hour, FIVE_HOUR_MS);
375
+ },
376
+ get binding() {
377
+ return props.quota?.bindingWindow === 'five_hour';
374
378
  }
375
379
  }), _$createComponent(QuotaRow, {
376
380
  get theme() {
@@ -385,6 +389,9 @@ function AccountBlock(props) {
385
389
  },
386
390
  get pacing() {
387
391
  return pacingFor(props.quota?.seven_day, SEVEN_DAY_MS);
392
+ },
393
+ get binding() {
394
+ return props.quota?.bindingWindow === 'seven_day';
388
395
  }
389
396
  }), _$createComponent(For, {
390
397
  get each() {
@@ -403,8 +410,31 @@ function AccountBlock(props) {
403
410
  window: window,
404
411
  get pacing() {
405
412
  return pacingFor(window, SEVEN_DAY_MS);
413
+ },
414
+ get binding() {
415
+ return props.quota?.bindingWindow === window.id;
406
416
  }
407
417
  })
418
+ }), _$createComponent(Show, {
419
+ get when() {
420
+ return props.quota?.extraUsage;
421
+ },
422
+ children: extraUsage => (() => {
423
+ var _el$32 = _$createElement("text");
424
+ _$insert(_el$32, () => `credits ${formatQuotaMoney(extraUsage().used)}/${formatQuotaMoney(extraUsage().limit)}${extraUsage().exhausted ? ' · exhausted' : ''}`);
425
+ _$effect(_$p => _$setProp(_el$32, "fg", toneColor(props.theme, extraUsage().severity === 'critical' ? 'err' : extraUsage().severity === 'warning' || extraUsage().exhausted ? 'warn' : 'muted'), _$p));
426
+ return _el$32;
427
+ })()
428
+ }), _$createComponent(Show, {
429
+ get when() {
430
+ return props.quota?.fallbackAdvised === true;
431
+ },
432
+ get children() {
433
+ var _el$28 = _$createElement("text");
434
+ _$insertNode(_el$28, _$createTextNode(`→ fallback advised`));
435
+ _$effect(_$p => _$setProp(_el$28, "fg", props.theme.textMuted, _$p));
436
+ return _el$28;
437
+ }
408
438
  })];
409
439
  }
410
440
  }), null);
@@ -424,6 +454,7 @@ function AccountBlock(props) {
424
454
  return _el$22;
425
455
  })();
426
456
  }
457
+ export { formatQuotaMoney };
427
458
 
428
459
  // --- Quota dialog content ---------------------------------------------------
429
460
 
@@ -448,26 +479,26 @@ function QuotaDialogContent(props) {
448
479
  const theme = () => props.api.theme.current;
449
480
  const enabledFallbacks = () => (state().fallbacks ?? []).filter(f => f.enabled);
450
481
  return (() => {
451
- var _el$30 = _$createElement("box"),
452
- _el$31 = _$createElement("box"),
453
- _el$32 = _$createElement("box"),
454
- _el$33 = _$createElement("text"),
455
- _el$34 = _$createElement("b");
456
- _$insertNode(_el$30, _el$31);
457
- _$setProp(_el$30, "flexDirection", 'column');
458
- _$setProp(_el$30, "padding", 2);
459
- _$setProp(_el$30, "width", '100%');
460
- _$setProp(_el$30, "alignItems", 'center');
461
- _$insertNode(_el$31, _el$32);
462
- _$setProp(_el$31, "flexDirection", 'column');
463
- _$setProp(_el$31, "width", 58);
464
- _$insertNode(_el$32, _el$33);
465
- _$setProp(_el$32, "width", '100%');
466
- _$setProp(_el$32, "justifyContent", 'center');
467
- _$setProp(_el$32, "marginBottom", 1);
482
+ var _el$33 = _$createElement("box"),
483
+ _el$34 = _$createElement("box"),
484
+ _el$35 = _$createElement("box"),
485
+ _el$36 = _$createElement("text"),
486
+ _el$37 = _$createElement("b");
468
487
  _$insertNode(_el$33, _el$34);
469
- _$insertNode(_el$34, _$createTextNode(`Quota`));
470
- _$insert(_el$31, _$createComponent(AccountBlock, {
488
+ _$setProp(_el$33, "flexDirection", 'column');
489
+ _$setProp(_el$33, "padding", 2);
490
+ _$setProp(_el$33, "width", '100%');
491
+ _$setProp(_el$33, "alignItems", 'center');
492
+ _$insertNode(_el$34, _el$35);
493
+ _$setProp(_el$34, "flexDirection", 'column');
494
+ _$setProp(_el$34, "width", 58);
495
+ _$insertNode(_el$35, _el$36);
496
+ _$setProp(_el$35, "width", '100%');
497
+ _$setProp(_el$35, "justifyContent", 'center');
498
+ _$setProp(_el$35, "marginBottom", 1);
499
+ _$insertNode(_el$36, _el$37);
500
+ _$insertNode(_el$37, _$createTextNode(`Quota`));
501
+ _$insert(_el$34, _$createComponent(AccountBlock, {
471
502
  get theme() {
472
503
  return theme();
473
504
  },
@@ -483,9 +514,12 @@ function QuotaDialogContent(props) {
483
514
  },
484
515
  get pacingEnabled() {
485
516
  return prefs().sections.pacing;
517
+ },
518
+ get tierLabel() {
519
+ return state().main?.tierLabel;
486
520
  }
487
521
  }), null);
488
- _$insert(_el$31, _$createComponent(Show, {
522
+ _$insert(_el$34, _$createComponent(Show, {
489
523
  get when() {
490
524
  return prefs().sections.fallbackAccounts;
491
525
  },
@@ -513,6 +547,9 @@ function QuotaDialogContent(props) {
513
547
  get pacingEnabled() {
514
548
  return prefs().sections.pacing;
515
549
  },
550
+ get tierLabel() {
551
+ return fb.tierLabel;
552
+ },
516
553
  get needsReauth() {
517
554
  return fb.needsReauth;
518
555
  },
@@ -521,8 +558,8 @@ function QuotaDialogContent(props) {
521
558
  });
522
559
  }
523
560
  }), null);
524
- _$effect(_$p => _$setProp(_el$33, "fg", theme().text, _$p));
525
- return _el$30;
561
+ _$effect(_$p => _$setProp(_el$36, "fg", theme().text, _$p));
562
+ return _el$33;
526
563
  })();
527
564
  }
528
565
 
@@ -654,33 +691,33 @@ function QuotaSidebar(props) {
654
691
  return `${r.transport} \u00b7 ${r.enabled ? 'on' : 'off'}`;
655
692
  };
656
693
  return (() => {
657
- var _el$36 = _$createElement("box"),
658
- _el$37 = _$createElement("box"),
659
- _el$38 = _$createElement("box"),
660
- _el$39 = _$createElement("text"),
661
- _el$40 = _$createElement("b");
662
- _$insertNode(_el$36, _el$37);
663
- _$setProp(_el$36, "width", '100%');
664
- _$setProp(_el$36, "flexDirection", 'column');
665
- _$setProp(_el$36, "border", SINGLE_BORDER);
666
- _$setProp(_el$36, "paddingTop", 1);
667
- _$setProp(_el$36, "paddingBottom", 1);
668
- _$setProp(_el$36, "paddingLeft", 1);
669
- _$setProp(_el$36, "paddingRight", 1);
670
- _$insertNode(_el$37, _el$38);
671
- _$setProp(_el$37, "width", '100%');
672
- _$setProp(_el$37, "flexDirection", 'row');
673
- _$setProp(_el$37, "justifyContent", 'space-between');
674
- _$setProp(_el$37, "alignItems", 'center');
675
- _$setProp(_el$37, "onMouseDown", () => {
694
+ var _el$39 = _$createElement("box"),
695
+ _el$40 = _$createElement("box"),
696
+ _el$41 = _$createElement("box"),
697
+ _el$42 = _$createElement("text"),
698
+ _el$43 = _$createElement("b");
699
+ _$insertNode(_el$39, _el$40);
700
+ _$setProp(_el$39, "width", '100%');
701
+ _$setProp(_el$39, "flexDirection", 'column');
702
+ _$setProp(_el$39, "border", SINGLE_BORDER);
703
+ _$setProp(_el$39, "paddingTop", 1);
704
+ _$setProp(_el$39, "paddingBottom", 1);
705
+ _$setProp(_el$39, "paddingLeft", 1);
706
+ _$setProp(_el$39, "paddingRight", 1);
707
+ _$insertNode(_el$40, _el$41);
708
+ _$setProp(_el$40, "width", '100%');
709
+ _$setProp(_el$40, "flexDirection", 'row');
710
+ _$setProp(_el$40, "justifyContent", 'space-between');
711
+ _$setProp(_el$40, "alignItems", 'center');
712
+ _$setProp(_el$40, "onMouseDown", () => {
676
713
  if (hasData()) props.controller.toggleCollapsed();
677
714
  });
678
- _$insertNode(_el$38, _el$39);
679
- _$setProp(_el$38, "paddingLeft", 1);
680
- _$setProp(_el$38, "paddingRight", 1);
681
- _$insertNode(_el$39, _el$40);
682
- _$insert(_el$40, headerLabel);
683
- _$insert(_el$37, _$createComponent(Show, {
715
+ _$insertNode(_el$41, _el$42);
716
+ _$setProp(_el$41, "paddingLeft", 1);
717
+ _$setProp(_el$41, "paddingRight", 1);
718
+ _$insertNode(_el$42, _el$43);
719
+ _$insert(_el$43, headerLabel);
720
+ _$insert(_el$40, _$createComponent(Show, {
684
721
  get when() {
685
722
  return degraded();
686
723
  },
@@ -690,36 +727,36 @@ function QuotaSidebar(props) {
690
727
  return prefs().header.showVersion && PLUGIN_VERSION !== '';
691
728
  },
692
729
  get children() {
693
- var _el$50 = _$createElement("text");
694
- _$insert(_el$50, `v${PLUGIN_VERSION}`);
695
- _$effect(_$p => _$setProp(_el$50, "fg", theme().textMuted, _$p));
696
- return _el$50;
730
+ var _el$53 = _$createElement("text");
731
+ _$insert(_el$53, `v${PLUGIN_VERSION}`);
732
+ _$effect(_$p => _$setProp(_el$53, "fg", theme().textMuted, _$p));
733
+ return _el$53;
697
734
  }
698
735
  });
699
736
  },
700
737
  get children() {
701
- var _el$41 = _$createElement("box"),
702
- _el$42 = _$createElement("text"),
703
- _el$43 = _$createElement("b");
704
- _$insertNode(_el$41, _el$42);
705
- _$setProp(_el$41, "paddingLeft", 1);
706
- _$setProp(_el$41, "paddingRight", 1);
707
- _$insertNode(_el$42, _el$43);
708
- _$insertNode(_el$43, _$createTextNode(`LIMITED`));
738
+ var _el$44 = _$createElement("box"),
739
+ _el$45 = _$createElement("text"),
740
+ _el$46 = _$createElement("b");
741
+ _$insertNode(_el$44, _el$45);
742
+ _$setProp(_el$44, "paddingLeft", 1);
743
+ _$setProp(_el$44, "paddingRight", 1);
744
+ _$insertNode(_el$45, _el$46);
745
+ _$insertNode(_el$46, _$createTextNode(`LIMITED`));
709
746
  _$effect(_p$ => {
710
747
  var _v$12 = theme().warning,
711
748
  _v$13 = theme().background;
712
- _v$12 !== _p$.e && (_p$.e = _$setProp(_el$41, "backgroundColor", _v$12, _p$.e));
713
- _v$13 !== _p$.t && (_p$.t = _$setProp(_el$42, "fg", _v$13, _p$.t));
749
+ _v$12 !== _p$.e && (_p$.e = _$setProp(_el$44, "backgroundColor", _v$12, _p$.e));
750
+ _v$13 !== _p$.t && (_p$.t = _$setProp(_el$45, "fg", _v$13, _p$.t));
714
751
  return _p$;
715
752
  }, {
716
753
  e: undefined,
717
754
  t: undefined
718
755
  });
719
- return _el$41;
756
+ return _el$44;
720
757
  }
721
758
  }), null);
722
- _$insert(_el$36, _$createComponent(Show, {
759
+ _$insert(_el$39, _$createComponent(Show, {
723
760
  get when() {
724
761
  return _$memo(() => !!collapsed())() && hasData();
725
762
  },
@@ -738,19 +775,19 @@ function QuotaSidebar(props) {
738
775
  },
739
776
  get fallback() {
740
777
  return (() => {
741
- var _el$51 = _$createElement("text");
742
- _$insertNode(_el$51, _$createTextNode(`—`));
743
- _$effect(_$p => _$setProp(_el$51, "fg", theme().textMuted, _$p));
744
- return _el$51;
778
+ var _el$54 = _$createElement("text");
779
+ _$insertNode(_el$54, _$createTextNode(`—`));
780
+ _$effect(_$p => _$setProp(_el$54, "fg", theme().textMuted, _$p));
781
+ return _el$54;
745
782
  })();
746
783
  },
747
784
  get children() {
748
- var _el$45 = _$createElement("text"),
749
- _el$46 = _$createElement("b");
750
- _$insertNode(_el$45, _el$46);
751
- _$insert(_el$46, () => activeQuotaSummary().text);
752
- _$effect(_$p => _$setProp(_el$45, "fg", toneColor(theme(), activeQuotaTone()), _$p));
753
- return _el$45;
785
+ var _el$48 = _$createElement("text"),
786
+ _el$49 = _$createElement("b");
787
+ _$insertNode(_el$48, _el$49);
788
+ _$insert(_el$49, () => activeQuotaSummary().text);
789
+ _$effect(_$p => _$setProp(_el$48, "fg", toneColor(theme(), activeQuotaTone()), _$p));
790
+ return _el$48;
754
791
  }
755
792
  });
756
793
  }
@@ -765,12 +802,12 @@ function QuotaSidebar(props) {
765
802
  },
766
803
  label: "Mode",
767
804
  get children() {
768
- var _el$47 = _$createElement("text"),
769
- _el$48 = _$createElement("b");
770
- _$insertNode(_el$47, _el$48);
771
- _$insertNode(_el$48, _$createTextNode(`fast`));
772
- _$effect(_$p => _$setProp(_el$47, "fg", toneColor(theme(), 'accent'), _$p));
773
- return _el$47;
805
+ var _el$50 = _$createElement("text"),
806
+ _el$51 = _$createElement("b");
807
+ _$insertNode(_el$50, _el$51);
808
+ _$insertNode(_el$51, _$createTextNode(`fast`));
809
+ _$effect(_$p => _$setProp(_el$50, "fg", toneColor(theme(), 'accent'), _$p));
810
+ return _el$50;
774
811
  }
775
812
  });
776
813
  }
@@ -784,18 +821,18 @@ function QuotaSidebar(props) {
784
821
  },
785
822
  label: "Recovery",
786
823
  get children() {
787
- var _el$53 = _$createElement("text"),
788
- _el$54 = _$createElement("b");
789
- _$insertNode(_el$53, _el$54);
790
- _$insert(_el$54, summary);
791
- _$effect(_$p => _$setProp(_el$53, "fg", toneColor(theme(), fableRecoveryTone()), _$p));
792
- return _el$53;
824
+ var _el$56 = _$createElement("text"),
825
+ _el$57 = _$createElement("b");
826
+ _$insertNode(_el$56, _el$57);
827
+ _$insert(_el$57, summary);
828
+ _$effect(_$p => _$setProp(_el$56, "fg", toneColor(theme(), fableRecoveryTone()), _$p));
829
+ return _el$56;
793
830
  }
794
831
  })
795
832
  })];
796
833
  }
797
834
  }), null);
798
- _$insert(_el$36, _$createComponent(Show, {
835
+ _$insert(_el$39, _$createComponent(Show, {
799
836
  get when() {
800
837
  return !collapsed() || !hasData();
801
838
  },
@@ -806,14 +843,14 @@ function QuotaSidebar(props) {
806
843
  },
807
844
  get fallback() {
808
845
  return (() => {
809
- var _el$55 = _$createElement("box"),
810
- _el$56 = _$createElement("text");
811
- _$insertNode(_el$55, _el$56);
812
- _$setProp(_el$55, "marginTop", 1);
813
- _$setProp(_el$55, "width", '100%');
814
- _$insertNode(_el$56, _$createTextNode(`Waiting for quota…`));
815
- _$effect(_$p => _$setProp(_el$56, "fg", theme().textMuted, _$p));
816
- return _el$55;
846
+ var _el$58 = _$createElement("box"),
847
+ _el$59 = _$createElement("text");
848
+ _$insertNode(_el$58, _el$59);
849
+ _$setProp(_el$58, "marginTop", 1);
850
+ _$setProp(_el$58, "width", '100%');
851
+ _$insertNode(_el$59, _$createTextNode(`Waiting for quota…`));
852
+ _$effect(_$p => _$setProp(_el$59, "fg", theme().textMuted, _$p));
853
+ return _el$58;
817
854
  })();
818
855
  },
819
856
  get children() {
@@ -843,6 +880,9 @@ function QuotaSidebar(props) {
843
880
  },
844
881
  get pacingEnabled() {
845
882
  return prefs().sections.pacing;
883
+ },
884
+ get tierLabel() {
885
+ return state().main?.tierLabel;
846
886
  }
847
887
  }), _$createComponent(Show, {
848
888
  get when() {
@@ -872,6 +912,9 @@ function QuotaSidebar(props) {
872
912
  get pacingEnabled() {
873
913
  return prefs().sections.pacing;
874
914
  },
915
+ get tierLabel() {
916
+ return fb.tierLabel;
917
+ },
875
918
  get needsReauth() {
876
919
  return fb.needsReauth;
877
920
  },
@@ -1032,16 +1075,16 @@ function QuotaSidebar(props) {
1032
1075
  var _v$14 = theme().borderActive,
1033
1076
  _v$15 = theme().accent,
1034
1077
  _v$16 = theme().background;
1035
- _v$14 !== _p$.e && (_p$.e = _$setProp(_el$36, "borderColor", _v$14, _p$.e));
1036
- _v$15 !== _p$.t && (_p$.t = _$setProp(_el$38, "backgroundColor", _v$15, _p$.t));
1037
- _v$16 !== _p$.a && (_p$.a = _$setProp(_el$39, "fg", _v$16, _p$.a));
1078
+ _v$14 !== _p$.e && (_p$.e = _$setProp(_el$39, "borderColor", _v$14, _p$.e));
1079
+ _v$15 !== _p$.t && (_p$.t = _$setProp(_el$41, "backgroundColor", _v$15, _p$.t));
1080
+ _v$16 !== _p$.a && (_p$.a = _$setProp(_el$42, "fg", _v$16, _p$.a));
1038
1081
  return _p$;
1039
1082
  }, {
1040
1083
  e: undefined,
1041
1084
  t: undefined,
1042
1085
  a: undefined
1043
1086
  });
1044
- return _el$36;
1087
+ return _el$39;
1045
1088
  })();
1046
1089
  }
1047
1090
  const tui = async api => {
package/src/tui.tsx CHANGED
@@ -3,6 +3,7 @@
3
3
  import { readFileSync } from 'node:fs'
4
4
  import { dirname, join } from 'node:path'
5
5
  import { fileURLToPath } from 'node:url'
6
+ import { formatQuotaMoney } from '@cortexkit/anthropic-auth-core'
6
7
  import type {
7
8
  TuiPlugin,
8
9
  TuiPluginApi,
@@ -237,6 +238,7 @@ function QuotaRow(props: {
237
238
  label: string
238
239
  window: { usedPercent: number; resetsAt?: string } | undefined
239
240
  pacing: QuotaPacing | null
241
+ binding?: boolean
240
242
  }) {
241
243
  const used = () => props.window?.usedPercent ?? 0
242
244
  const reset = () => formatResetIn(props.window?.resetsAt)
@@ -275,7 +277,7 @@ function QuotaRow(props: {
275
277
  <text
276
278
  fg={toneColor(props.theme, usageTone(used(), props.appearance))}
277
279
  >
278
- {` ${String(Math.round(used())).padStart(3)}%`}
280
+ {` ${String(Math.round(used())).padStart(3)}%${props.binding ? ' •' : ''}`}
279
281
  </text>
280
282
  </box>
281
283
  <Show when={reset()}>
@@ -310,6 +312,7 @@ function AccountBlock(props: {
310
312
  active: boolean
311
313
  pacingEnabled: boolean
312
314
  needsReauth?: boolean
315
+ tierLabel?: string
313
316
  marginTop?: number
314
317
  }) {
315
318
  const statusWord = () =>
@@ -329,7 +332,7 @@ function AccountBlock(props: {
329
332
  <box width='100%' flexDirection='column' marginTop={props.marginTop ?? 0}>
330
333
  <box width='100%' flexDirection='row' justifyContent='space-between'>
331
334
  <text fg={props.theme.text}>
332
- <b>{props.name}</b>
335
+ <b>{`${props.name}${props.tierLabel ? ` · ${props.tierLabel}` : ''}`}</b>
333
336
  </text>
334
337
  <text fg={toneColor(props.theme, statusTone())}>
335
338
  <b>{statusWord()}</b>
@@ -345,6 +348,7 @@ function AccountBlock(props: {
345
348
  label='5h'
346
349
  window={props.quota?.five_hour}
347
350
  pacing={pacingFor(props.quota?.five_hour, FIVE_HOUR_MS)}
351
+ binding={props.quota?.bindingWindow === 'five_hour'}
348
352
  />
349
353
  <QuotaRow
350
354
  theme={props.theme}
@@ -352,6 +356,7 @@ function AccountBlock(props: {
352
356
  label='7d'
353
357
  window={props.quota?.seven_day}
354
358
  pacing={pacingFor(props.quota?.seven_day, SEVEN_DAY_MS)}
359
+ binding={props.quota?.bindingWindow === 'seven_day'}
355
360
  />
356
361
  <For each={props.quota?.scoped ?? []}>
357
362
  {(window) => (
@@ -361,14 +366,37 @@ function AccountBlock(props: {
361
366
  label={formatScopedQuotaLabel(window.title)}
362
367
  window={window}
363
368
  pacing={pacingFor(window, SEVEN_DAY_MS)}
369
+ binding={props.quota?.bindingWindow === window.id}
364
370
  />
365
371
  )}
366
372
  </For>
373
+ <Show when={props.quota?.extraUsage}>
374
+ {(extraUsage: () => NonNullable<AccountQuota['extraUsage']>) => (
375
+ <text
376
+ fg={toneColor(
377
+ props.theme,
378
+ extraUsage().severity === 'critical'
379
+ ? 'err'
380
+ : extraUsage().severity === 'warning' ||
381
+ extraUsage().exhausted
382
+ ? 'warn'
383
+ : 'muted',
384
+ )}
385
+ >
386
+ {`credits ${formatQuotaMoney(extraUsage().used)}/${formatQuotaMoney(extraUsage().limit)}${extraUsage().exhausted ? ' · exhausted' : ''}`}
387
+ </text>
388
+ )}
389
+ </Show>
390
+ <Show when={props.quota?.fallbackAdvised === true}>
391
+ <text fg={props.theme.textMuted}>{'→ fallback advised'}</text>
392
+ </Show>
367
393
  </Show>
368
394
  </box>
369
395
  )
370
396
  }
371
397
 
398
+ export { formatQuotaMoney }
399
+
372
400
  // --- Quota dialog content ---------------------------------------------------
373
401
 
374
402
  // Renders the same rich visualization as the sidebar (account blocks with
@@ -410,6 +438,7 @@ function QuotaDialogContent(props: {
410
438
  quota={state().main?.quota}
411
439
  active={state().activeId === 'main'}
412
440
  pacingEnabled={prefs().sections.pacing}
441
+ tierLabel={state().main?.tierLabel}
413
442
  />
414
443
  <Show when={prefs().sections.fallbackAccounts}>
415
444
  <For each={enabledFallbacks()}>
@@ -421,6 +450,7 @@ function QuotaDialogContent(props: {
421
450
  quota={fb.quota}
422
451
  active={state().activeId === fb.id}
423
452
  pacingEnabled={prefs().sections.pacing}
453
+ tierLabel={fb.tierLabel}
424
454
  needsReauth={fb.needsReauth}
425
455
  marginTop={1}
426
456
  />
@@ -724,6 +754,7 @@ function QuotaSidebar(props: {
724
754
  quota={state().main?.quota}
725
755
  active={state().activeId === 'main'}
726
756
  pacingEnabled={prefs().sections.pacing}
757
+ tierLabel={state().main?.tierLabel}
727
758
  />
728
759
  <Show when={prefs().sections.fallbackAccounts}>
729
760
  <For each={enabledFallbacks()}>
@@ -735,6 +766,7 @@ function QuotaSidebar(props: {
735
766
  quota={fb.quota}
736
767
  active={state().activeId === fb.id}
737
768
  pacingEnabled={prefs().sections.pacing}
769
+ tierLabel={fb.tierLabel}
738
770
  needsReauth={fb.needsReauth}
739
771
  marginTop={1}
740
772
  />
@@ -1,2 +0,0 @@
1
- import{mkdir as q,readFile as M,writeFile as L}from"node:fs/promises";import{tmpdir as k}from"node:os";import{dirname as b,join as g}from"node:path";var R="OPENCODE_ANTHROPIC_AUTH_SIDEBAR_STATE_FILE",F=g(k(),"opencode-anthropic-auth"),f=g(F,"sidebar-state.json");function h(){return process.env[R]||f}var K={main:{quota:null},fallbacks:[],activeId:void 0,route:"main",relay:null,fastMode:!1,lastUpdated:0};function G(x){return x!==null&&typeof x==="object"&&!Array.isArray(x)}function z(x){if(!G(x))return;let X=Number(x.usedPercent),Z=Number(x.remainingPercent);if(!Number.isFinite(X)||!Number.isFinite(Z))return;return{usedPercent:X,remainingPercent:Z,resetsAt:typeof x.resetsAt==="string"?x.resetsAt:void 0}}function N(x){if(!G(x))return null;let X={},Z=z(x.five_hour),$=z(x.seven_day);if(Z)X.five_hour=Z;if($)X.seven_day=$;if(Array.isArray(x.scoped)){let V=x.scoped.map((Y)=>{if(!G(Y))return;let J=z(Y);if(!J)return;if(typeof Y.id!=="string"||!Y.id.trim())return;if(typeof Y.title!=="string"||!Y.title.trim())return;if(typeof Y.modelName!=="string"||!Y.modelName.trim())return;let j=typeof Y.modelId==="string"&&Y.modelId.trim()?Y.modelId.trim():void 0;return{...J,id:Y.id.trim(),title:Y.title.trim(),...j&&{modelId:j},modelName:Y.modelName.trim()}}).filter((Y)=>Y!=null);X.scoped=V}return Object.keys(X).length?X:null}function I(x){if(!G(x))return{...K};let X={quota:null};if(G(x.main)){let J=x.main;if(X.quota=N(J.quota),typeof J.quotaBackedOff==="boolean")X.quotaBackedOff=J.quotaBackedOff;if(typeof J.quotaBackoffUntil==="number")X.quotaBackoffUntil=J.quotaBackoffUntil;if(typeof J.refreshBackedOff==="boolean")X.refreshBackedOff=J.refreshBackedOff;if(typeof J.refreshBackoffUntil==="number")X.refreshBackoffUntil=J.refreshBackoffUntil}let Z=Array.isArray(x.fallbacks)?x.fallbacks.filter(G).filter((J)=>typeof J.id==="string").map((J)=>({id:J.id,label:typeof J.label==="string"?J.label:void 0,quota:N(J.quota),enabled:typeof J.enabled==="boolean"?J.enabled:!1,needsReauth:typeof J.needsReauth==="boolean"?J.needsReauth:!1})):[],$=null;if(G(x.relay)){let J=x.relay;if(typeof J.enabled==="boolean"&&typeof J.transport==="string")$={enabled:J.enabled,transport:J.transport}}let V;if(G(x.cacheKeep)){let J=x.cacheKeep;if(typeof J.enabled==="boolean")V={enabled:J.enabled,window:typeof J.window==="string"?J.window:void 0,trackedSessions:typeof J.trackedSessions==="number"?J.trackedSessions:void 0}}let Y=Array.isArray(x.fableRecoveries)?x.fableRecoveries.filter(G).flatMap((J)=>{if(typeof J.sessionId!=="string"||J.mode!=="opus"&&J.mode!=="fable"||typeof J.remaining!=="number"||!Number.isFinite(J.remaining)||typeof J.changedAt!=="number"||!Number.isFinite(J.changedAt))return[];return[{sessionId:J.sessionId,mode:J.mode,remaining:Math.max(0,Math.floor(J.remaining)),changedAt:J.changedAt}]}):[];return{main:X,fallbacks:Z,activeId:typeof x.activeId==="string"?x.activeId:void 0,route:typeof x.route==="string"?x.route:K.route,relay:$,fastMode:typeof x.fastMode==="boolean"?x.fastMode:K.fastMode,cacheKeep:V,fableRecoveries:Y.length>0?Y:void 0,lastUpdated:typeof x.lastUpdated==="number"?x.lastUpdated:0}}var W=Promise.resolve();async function P(){try{let x=await M(h(),"utf8");return I(JSON.parse(x))}catch{return K}}async function A(x,X=h()){return W=W.then(async()=>{await q(b(X),{recursive:!0}),await L(X,JSON.stringify(x),"utf8")}).catch(()=>{}),W}async function m(){return W}function u(x){let X=x.activeId;if(X&&X!=="main"){let Z=x.fallbacks?.find(($)=>$.enabled&&$.id===X);if(Z)return{id:Z.id,name:Z.label??Z.id,quota:Z.quota}}return{id:"main",name:"main",quota:x.main?.quota??null}}function U(x){let X=x.replace(/\s+only$/i,"").trim();return/^fable$/i.test(X)?"Fa":X}function l(x,X){let Z=x.fableRecoveries?.find(($)=>$.sessionId===X);if(!Z)return;if(Z.mode==="fable")return"Fable 5 · restored";return`Opus 4.8 · ${Z.remaining} left`}function v(x){let X=x?.five_hour?.usedPercent??null,Z=x?.seven_day?.usedPercent??null,$=x?.scoped??[],V=$.map((j)=>j.usedPercent);if(X==null&&Z==null&&$.length===0)return{fiveHourUsedPercent:X,sevenDayUsedPercent:Z,scopedUsedPercents:V,text:null};let Y=$.map((j)=>`${U(j.title)}: ${Math.round(j.usedPercent)}%`),J=X==null&&Z==null?[]:[`5h: ${X==null?"—":`${Math.round(X)}%`}`,`7d: ${Z==null?"—":`${Math.round(Z)}%`}`];return{fiveHourUsedPercent:X,sevenDayUsedPercent:Z,scopedUsedPercents:V,text:[...J,...Y].join(" ")}}var y=18000000,d=604800000,D=300000,_=0.01,p=1;function w(x,X,Z){if(!x.resetsAt)return null;let $=new Date(x.resetsAt).getTime();if(!Number.isFinite($))return null;let V=$-X,Y=Z-V;if(Y<D)return null;if(Y<X*_)return null;if(Y>=X)return null;let J=x.usedPercent,j=Math.min(Math.max(Y/X*100,0),100),B=J-j,C=Math.abs(B)<p?"on-pace":B>0?"deficit":"reserve",O=null;if(J>0){let H=Y*100/J,Q=V+H;if(Q<$)O=new Date(Q).toISOString()}return{pacePercent:j,deltaPercent:B,state:C,runsOutAt:O}}
2
- export{h as Eb,K as Fb,I as Gb,P as Hb,A as Ib,m as Jb,u as Kb,U as Lb,l as Mb,v as Nb,y as Ob,d as Pb,w as Qb};