@slkiser/opencode-quota 4.5.1 → 4.6.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.
Files changed (43) hide show
  1. package/README.md +1 -0
  2. package/dist/data/modelsdev-pricing.min.json +5 -0
  3. package/dist/lib/config.d.ts +1 -1
  4. package/dist/lib/config.d.ts.map +1 -1
  5. package/dist/lib/config.js +51 -0
  6. package/dist/lib/config.js.map +1 -1
  7. package/dist/lib/maintainer-announcements.d.ts +3 -0
  8. package/dist/lib/maintainer-announcements.d.ts.map +1 -1
  9. package/dist/lib/maintainer-announcements.js +13 -0
  10. package/dist/lib/maintainer-announcements.js.map +1 -1
  11. package/dist/lib/quota-export.d.ts +1 -0
  12. package/dist/lib/quota-export.d.ts.map +1 -1
  13. package/dist/lib/quota-export.js +4 -0
  14. package/dist/lib/quota-export.js.map +1 -1
  15. package/dist/lib/quota-render-data.d.ts +2 -0
  16. package/dist/lib/quota-render-data.d.ts.map +1 -1
  17. package/dist/lib/quota-render-data.js +7 -0
  18. package/dist/lib/quota-render-data.js.map +1 -1
  19. package/dist/lib/quota-reset-notifications.d.ts +20 -0
  20. package/dist/lib/quota-reset-notifications.d.ts.map +1 -0
  21. package/dist/lib/quota-reset-notifications.js +328 -0
  22. package/dist/lib/quota-reset-notifications.js.map +1 -0
  23. package/dist/lib/quota-stats.d.ts.map +1 -1
  24. package/dist/lib/quota-stats.js +4 -0
  25. package/dist/lib/quota-stats.js.map +1 -1
  26. package/dist/lib/tui-refresh-lifecycle.d.ts.map +1 -1
  27. package/dist/lib/tui-refresh-lifecycle.js +0 -1
  28. package/dist/lib/tui-refresh-lifecycle.js.map +1 -1
  29. package/dist/lib/tui-runtime.d.ts +8 -1
  30. package/dist/lib/tui-runtime.d.ts.map +1 -1
  31. package/dist/lib/tui-runtime.js +36 -5
  32. package/dist/lib/tui-runtime.js.map +1 -1
  33. package/dist/lib/types.d.ts +9 -0
  34. package/dist/lib/types.d.ts.map +1 -1
  35. package/dist/lib/types.js +4 -0
  36. package/dist/lib/types.js.map +1 -1
  37. package/dist/plugin.d.ts.map +1 -1
  38. package/dist/plugin.js +38 -1
  39. package/dist/plugin.js.map +1 -1
  40. package/dist/tui.d.ts.map +1 -1
  41. package/dist/tui.js +166 -72
  42. package/dist/tui.tsx +213 -73
  43. package/package.json +1 -1
package/dist/tui.js CHANGED
@@ -23,6 +23,61 @@ const COMPACT_ORDER = 90;
23
23
  const REFRESH_INTERVAL_MS = 60_000;
24
24
  const EVENT_REFRESH_DELAYS_MS = [150, 600];
25
25
  const MOUNT_RECOVERY_DELAYS_MS = [500, 1_500, 4_000];
26
+ const FALLBACK_SURFACE_REGISTRATION = {
27
+ commandDisplay: "inline",
28
+ sidebar: {
29
+ enabled: true
30
+ },
31
+ compact: {
32
+ enabled: false,
33
+ homeBottom: false,
34
+ sessionPrompt: false,
35
+ hasNativeProviderQuota: false,
36
+ suppressedByNativeProviderQuota: false
37
+ },
38
+ announcements: {
39
+ homeBottom: false
40
+ },
41
+ homeBottom: false
42
+ };
43
+ function createTuiInitialLoadCoordinator(seed) {
44
+ let sessionAvailable = true;
45
+ let homeAvailable = true;
46
+ return {
47
+ takeInitialSession() {
48
+ if (!sessionAvailable) return undefined;
49
+ sessionAvailable = false;
50
+ return seed;
51
+ },
52
+ takeInitialHome() {
53
+ if (!homeAvailable) return undefined;
54
+ homeAvailable = false;
55
+ return seed;
56
+ }
57
+ };
58
+ }
59
+ function createTuiRegistrationGate() {
60
+ const [current, setCurrent] = createSignal({
61
+ status: "pending"
62
+ });
63
+ return {
64
+ current,
65
+ activate(registration, initialLoads) {
66
+ if (current().status !== "pending") return;
67
+ setCurrent({
68
+ status: "active",
69
+ registration,
70
+ initialLoads
71
+ });
72
+ },
73
+ dispose() {
74
+ if (current().status === "disposed") return;
75
+ setCurrent({
76
+ status: "disposed"
77
+ });
78
+ }
79
+ };
80
+ }
26
81
  const sessionResources = new WeakMap();
27
82
  const homeResources = new WeakMap();
28
83
  function getSessionResourceMap(api) {
@@ -32,7 +87,7 @@ function getSessionResourceMap(api) {
32
87
  sessionResources.set(api, next);
33
88
  return next;
34
89
  }
35
- function createSessionQuotaResource(api, sessionID) {
90
+ function createSessionQuotaResource(api, sessionID, initialLoads) {
36
91
  const [sidebar, setSidebar] = createSignal({
37
92
  status: "loading",
38
93
  lines: []
@@ -40,11 +95,19 @@ function createSessionQuotaResource(api, sessionID) {
40
95
  const [compact, setCompact] = createSignal({
41
96
  status: "loading"
42
97
  });
98
+ let loadOrdinal = 0;
43
99
  const lifecycle = createTuiRefreshLifecycle({
44
- load: () => loadTuiSessionQuotaSurfaces({
45
- api,
46
- sessionID
47
- }),
100
+ load: () => {
101
+ const initialRuntimeSeed = loadOrdinal === 0 ? initialLoads?.takeInitialSession() : undefined;
102
+ loadOrdinal += 1;
103
+ return loadTuiSessionQuotaSurfaces({
104
+ api,
105
+ sessionID,
106
+ ...(initialRuntimeSeed ? {
107
+ initialRuntimeSeed
108
+ } : {})
109
+ });
110
+ },
48
111
  apply: next => {
49
112
  setSidebar(next.sidebar);
50
113
  setCompact(next.compact);
@@ -87,15 +150,15 @@ function createSessionQuotaResource(api, sessionID) {
87
150
  };
88
151
  return resource;
89
152
  }
90
- function acquireSessionQuotaResource(api, sessionID) {
153
+ function acquireSessionQuotaResource(api, sessionID, initialLoads) {
91
154
  const resources = getSessionResourceMap(api);
92
155
  const existing = resources.get(sessionID);
93
156
  if (existing) return existing.retain();
94
- const next = createSessionQuotaResource(api, sessionID).retain();
157
+ const next = createSessionQuotaResource(api, sessionID, initialLoads).retain();
95
158
  resources.set(sessionID, next);
96
159
  return next;
97
160
  }
98
- function createHomeBottomResource(api, compactHomeBottomEnabled) {
161
+ function createHomeBottomResource(api, compactHomeBottomEnabled, initialLoads) {
99
162
  const [bottom, setBottom] = createSignal({
100
163
  status: "loading",
101
164
  compact: compactHomeBottomEnabled ? {
@@ -104,10 +167,18 @@ function createHomeBottomResource(api, compactHomeBottomEnabled) {
104
167
  status: "disabled"
105
168
  }
106
169
  });
170
+ let loadOrdinal = 0;
107
171
  const lifecycle = createTuiRefreshLifecycle({
108
- load: () => loadTuiHomeBottomStatus({
109
- api
110
- }),
172
+ load: () => {
173
+ const initialRuntimeSeed = loadOrdinal === 0 ? initialLoads?.takeInitialHome() : undefined;
174
+ loadOrdinal += 1;
175
+ return loadTuiHomeBottomStatus({
176
+ api,
177
+ ...(initialRuntimeSeed ? {
178
+ initialRuntimeSeed
179
+ } : {})
180
+ });
181
+ },
111
182
  apply: setBottom,
112
183
  afterApply: () => {
113
184
  // Fire-and-forget: write export file if enabled. A failed write must
@@ -135,21 +206,21 @@ function createHomeBottomResource(api, compactHomeBottomEnabled) {
135
206
  };
136
207
  return resource;
137
208
  }
138
- function acquireHomeBottomResource(api, compactHomeBottomEnabled) {
209
+ function acquireHomeBottomResource(api, compactHomeBottomEnabled, initialLoads) {
139
210
  const existing = homeResources.get(api);
140
211
  if (existing) return existing.retain();
141
- const next = createHomeBottomResource(api, compactHomeBottomEnabled).retain();
212
+ const next = createHomeBottomResource(api, compactHomeBottomEnabled, initialLoads).retain();
142
213
  homeResources.set(api, next);
143
214
  return next;
144
215
  }
145
- function useSessionQuotaResource(api, sessionID) {
146
- let current = acquireSessionQuotaResource(api, sessionID());
216
+ function useSessionQuotaResource(api, sessionID, initialLoads) {
217
+ let current = acquireSessionQuotaResource(api, sessionID(), initialLoads);
147
218
  const [resource, setResource] = createSignal(current);
148
219
  createEffect(() => {
149
220
  const nextSessionID = sessionID();
150
221
  if (current.sessionID === nextSessionID) return;
151
222
  const previous = current;
152
- current = acquireSessionQuotaResource(api, nextSessionID);
223
+ current = acquireSessionQuotaResource(api, nextSessionID, initialLoads);
153
224
  setResource(current);
154
225
  previous.release();
155
226
  });
@@ -159,7 +230,7 @@ function useSessionQuotaResource(api, sessionID) {
159
230
  return resource;
160
231
  }
161
232
  function SidebarContentView(props) {
162
- const resource = useSessionQuotaResource(props.api, () => props.sessionID);
233
+ const resource = useSessionQuotaResource(props.api, () => props.sessionID, props.initialLoads);
163
234
  const panel = () => resource().sidebar();
164
235
  const lines = () => getSidebarPanelLines(panel());
165
236
  const hasDetailLines = () => Boolean(panel().linesExpanded?.length);
@@ -276,7 +347,7 @@ function CompactStatusLine(props) {
276
347
  });
277
348
  }
278
349
  function SessionPromptWithCompactStatus(props) {
279
- const resource = useSessionQuotaResource(props.api, () => props.sessionID);
350
+ const resource = useSessionQuotaResource(props.api, () => props.sessionID, props.initialLoads);
280
351
  const panel = () => resource().compact();
281
352
  return (() => {
282
353
  var _el$13 = _$createElement("box");
@@ -310,7 +381,7 @@ function SessionPromptWithCompactStatus(props) {
310
381
  })();
311
382
  }
312
383
  function HomeBottomView(props) {
313
- const resource = acquireHomeBottomResource(props.api, props.compactHomeBottomEnabled);
384
+ const resource = acquireHomeBottomResource(props.api, props.compactHomeBottomEnabled, props.initialLoads);
314
385
  onCleanup(() => resource.release());
315
386
  const announcement = () => getHomeBottomAnnouncementText(resource.bottom());
316
387
  const compact = () => resource.bottom().compact;
@@ -629,7 +700,7 @@ async function runQuotaDialogCommandAsync(api, command, commandDisplay, rawInput
629
700
  });
630
701
  }
631
702
  }
632
- function registerQuotaDialogCommands(api, commandDisplay) {
703
+ function registerQuotaDialogCommands(api, gate) {
633
704
  const commandState = {};
634
705
  const dispose = api.keymap.registerLayer({
635
706
  commands: QUOTA_DIALOG_COMMANDS.map(spec => ({
@@ -640,88 +711,111 @@ function registerQuotaDialogCommands(api, commandDisplay) {
640
711
  category: "OpenCode Quota",
641
712
  slashName: spec.slashName,
642
713
  run(input) {
643
- void runQuotaDialogCommandAsync(api, spec.id, commandDisplay, input, commandState);
714
+ const state = gate.current();
715
+ if (state.status !== "active") return;
716
+ void runQuotaDialogCommandAsync(api, spec.id, state.registration.commandDisplay, input, commandState);
644
717
  }
645
718
  })),
646
719
  bindings: []
647
720
  });
648
721
  api.lifecycle.onDispose(dispose);
649
722
  }
650
- function registerSidebarSlots(api) {
723
+ function registerStableTuiSlots(api, current) {
651
724
  api.slots.register({
652
725
  order: SIDEBAR_ORDER,
653
726
  slots: {
654
727
  sidebar_content(_ctx, props) {
728
+ const state = current();
729
+ if (state.status !== "active" || !state.registration.sidebar.enabled) return null;
655
730
  return _$createComponent(SidebarContentView, {
656
731
  api: api,
657
732
  get sessionID() {
658
733
  return props.session_id;
734
+ },
735
+ get initialLoads() {
736
+ return state.initialLoads;
737
+ }
738
+ });
739
+ }
740
+ }
741
+ });
742
+ api.slots.register({
743
+ order: COMPACT_ORDER,
744
+ slots: {
745
+ session_prompt(_ctx, props) {
746
+ const state = current();
747
+ if (state.status !== "active" || !state.registration.compact.sessionPrompt) return null;
748
+ return _$createComponent(SessionPromptWithCompactStatus, {
749
+ api: api,
750
+ get sessionID() {
751
+ return props.session_id;
752
+ },
753
+ get initialLoads() {
754
+ return state.initialLoads;
755
+ },
756
+ get visible() {
757
+ return props.visible;
758
+ },
759
+ get disabled() {
760
+ return props.disabled;
761
+ },
762
+ get onSubmit() {
763
+ return props.on_submit;
764
+ },
765
+ get promptRef() {
766
+ return props.ref;
767
+ }
768
+ });
769
+ },
770
+ home_bottom() {
771
+ const state = current();
772
+ if (state.status !== "active" || !state.registration.homeBottom) return null;
773
+ return _$createComponent(HomeBottomView, {
774
+ api: api,
775
+ get compactHomeBottomEnabled() {
776
+ return state.registration.compact.homeBottom;
777
+ },
778
+ get initialLoads() {
779
+ return state.initialLoads;
659
780
  }
660
781
  });
661
782
  }
662
783
  }
663
784
  });
664
785
  }
665
- async function initializeTuiRegistration(api, isDisposed) {
786
+ async function initializeTuiRegistration(api, gate) {
787
+ let initialRuntimeSeed;
666
788
  let surfaceRegistration;
667
789
  try {
668
- surfaceRegistration = await resolveTuiSurfaceRegistration(api);
669
- } catch {
670
- if (isDisposed()) return;
671
- registerQuotaDialogCommands(api, "inline");
672
- registerSidebarSlots(api);
673
- return;
674
- }
675
- if (isDisposed()) return;
676
- registerQuotaDialogCommands(api, surfaceRegistration.commandDisplay);
677
- if (surfaceRegistration.sidebar.enabled) {
678
- registerSidebarSlots(api);
679
- }
680
- const compactRegistration = surfaceRegistration.compact;
681
- if (!compactRegistration.enabled && !surfaceRegistration.homeBottom) return;
682
- const compactSlots = {};
683
- if (compactRegistration.sessionPrompt) {
684
- compactSlots.session_prompt = (_ctx, props) => _$createComponent(SessionPromptWithCompactStatus, {
685
- api: api,
686
- get sessionID() {
687
- return props.session_id;
688
- },
689
- get visible() {
690
- return props.visible;
691
- },
692
- get disabled() {
693
- return props.disabled;
694
- },
695
- get onSubmit() {
696
- return props.on_submit;
697
- },
698
- get promptRef() {
699
- return props.ref;
790
+ surfaceRegistration = resolveTuiSurfaceRegistration(api, {
791
+ captureInitialRuntime(seed) {
792
+ initialRuntimeSeed = seed;
700
793
  }
794
+ }).then(registration => ({
795
+ registration,
796
+ initialRuntimeSeed
797
+ })).catch(() => ({
798
+ registration: FALLBACK_SURFACE_REGISTRATION
799
+ }));
800
+ } catch {
801
+ surfaceRegistration = Promise.resolve({
802
+ registration: FALLBACK_SURFACE_REGISTRATION
701
803
  });
702
804
  }
703
- if (surfaceRegistration.homeBottom) {
704
- compactSlots.home_bottom = () => _$createComponent(HomeBottomView, {
705
- api: api,
706
- get compactHomeBottomEnabled() {
707
- return surfaceRegistration.compact.homeBottom;
708
- }
709
- });
710
- }
711
- if (Object.keys(compactSlots).length > 0) {
712
- api.slots.register({
713
- order: COMPACT_ORDER,
714
- slots: compactSlots
715
- });
716
- }
805
+ registerQuotaDialogCommands(api, gate);
806
+ void surfaceRegistration.then(({
807
+ registration,
808
+ initialRuntimeSeed
809
+ }) => gate.activate(registration, initialRuntimeSeed ? createTuiInitialLoadCoordinator(initialRuntimeSeed) : undefined));
810
+ registerStableTuiSlots(api, gate.current);
717
811
  }
718
812
  const tui = async api => {
719
- let disposed = false;
813
+ const registrationGate = createTuiRegistrationGate();
720
814
  api.lifecycle.onDispose(() => {
721
- disposed = true;
815
+ registrationGate.dispose();
722
816
  disposeQuotaTelemetryOwner(createTuiQuotaClient(api));
723
817
  });
724
- void initializeTuiRegistration(api, () => disposed).catch(() => {});
818
+ void initializeTuiRegistration(api, registrationGate).catch(() => {});
725
819
  };
726
820
  const pluginModule = {
727
821
  id,