dsh-subscriptions 0.2.0 → 0.2.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.
Files changed (105) hide show
  1. package/README.md +220 -180
  2. package/lib/auth/claude-code-creds.js +31 -9
  3. package/lib/auth/device-flow.js +16 -9
  4. package/lib/auth/oauth-flow.js +13 -10
  5. package/lib/auth/rpc.d.ts +8 -4
  6. package/lib/auth/rpc.js +89 -25
  7. package/lib/auth/store.js +80 -31
  8. package/lib/client/CursorCard.d.ts +1 -1
  9. package/lib/client/CursorCard.js +50 -16
  10. package/lib/client/ExternalUsageCards.d.ts +1 -1
  11. package/lib/client/ExternalUsageCards.js +37 -16
  12. package/lib/client/ImageGallery.d.ts +2 -2
  13. package/lib/client/ImageGallery.js +92 -33
  14. package/lib/client/ImageGenerateToolview.js +50 -14
  15. package/lib/client/OllamaCard.d.ts +1 -1
  16. package/lib/client/OllamaCard.js +26 -8
  17. package/lib/client/OllamaSettingsManager.js +113 -30
  18. package/lib/client/ProviderAccountManager.d.ts +1 -1
  19. package/lib/client/ProviderAccountManager.js +164 -49
  20. package/lib/client/ProviderModelEditor.js +137 -34
  21. package/lib/client/SpeedSelect.d.ts +62 -14
  22. package/lib/client/SpeedSelect.js +261 -49
  23. package/lib/client/SubscriptionUsageBadge.d.ts +4 -10
  24. package/lib/client/SubscriptionUsageBadge.js +300 -112
  25. package/lib/client/SubscriptionsSection.d.ts +2 -0
  26. package/lib/client/SubscriptionsSection.js +265 -85
  27. package/lib/client/UsageBadgeDisplaySetting.js +35 -12
  28. package/lib/client/UsageMeter.d.ts +1 -1
  29. package/lib/client/UsageMeter.js +62 -24
  30. package/lib/client/VideoGenerateToolview.js +69 -17
  31. package/lib/client/account-preferences.d.ts +8 -0
  32. package/lib/client/account-preferences.js +20 -5
  33. package/lib/client/host-contract.d.ts +11 -2
  34. package/lib/client/host-contract.js +20 -3
  35. package/lib/client/index.d.ts +5 -5
  36. package/lib/client/index.js +34 -12
  37. package/lib/client/locales.d.ts +22 -0
  38. package/lib/client/locales.js +73 -51
  39. package/lib/client/model-filter.d.ts +37 -0
  40. package/lib/client/model-filter.js +45 -0
  41. package/lib/client/ollama-draft.js +21 -12
  42. package/lib/client/reset-action.js +6 -4
  43. package/lib/client/reset-credits-view.d.ts +1 -1
  44. package/lib/client/reset-credits-view.js +66 -17
  45. package/lib/client/subscription-card-styles.js +94 -24
  46. package/lib/client/usage-color-preferences.js +4 -2
  47. package/lib/client/usage-pace.js +30 -12
  48. package/lib/client/usage-window-filter.d.ts +7 -0
  49. package/lib/client/usage-window-filter.js +12 -0
  50. package/lib/client.js +480 -136
  51. package/lib/client.js.map +1 -1
  52. package/lib/http.js +1 -1
  53. package/lib/index.d.ts +3 -3
  54. package/lib/index.js +167 -76
  55. package/lib/model-defaults.js +4 -2
  56. package/lib/provider-settings.d.ts +17 -0
  57. package/lib/provider-settings.js +79 -16
  58. package/lib/providers/account-preferences.js +51 -22
  59. package/lib/providers/accounts.js +15 -9
  60. package/lib/providers/antigravity-oauth-client.js +2 -2
  61. package/lib/providers/antigravity.js +141 -68
  62. package/lib/providers/catalog-store.js +120 -41
  63. package/lib/providers/claude-cli-version.js +3 -3
  64. package/lib/providers/claude.d.ts +9 -2
  65. package/lib/providers/claude.js +153 -90
  66. package/lib/providers/codex-client-version.js +3 -3
  67. package/lib/providers/codex-search.js +40 -13
  68. package/lib/providers/codex.js +196 -112
  69. package/lib/providers/common.js +71 -39
  70. package/lib/providers/copilot.js +143 -82
  71. package/lib/providers/cursor-adapter.js +42 -18
  72. package/lib/providers/cursor-auth.d.ts +1 -1
  73. package/lib/providers/cursor-auth.js +69 -24
  74. package/lib/providers/cursor-model-settings.js +14 -5
  75. package/lib/providers/cursor-usage.js +27 -13
  76. package/lib/providers/external-usage-controller.js +14 -5
  77. package/lib/providers/external-usage.js +59 -23
  78. package/lib/providers/grok.js +152 -89
  79. package/lib/providers/image-pool.js +29 -11
  80. package/lib/providers/minimax-usage.js +31 -11
  81. package/lib/providers/npm-cli-version.js +10 -3
  82. package/lib/providers/ollama-settings.js +24 -8
  83. package/lib/providers/ollama-web.js +29 -11
  84. package/lib/providers/ollama.js +129 -66
  85. package/lib/providers/pool-family.js +11 -3
  86. package/lib/providers/pool-health.js +28 -8
  87. package/lib/providers/pool-usage.js +16 -9
  88. package/lib/providers/pool.d.ts +8 -0
  89. package/lib/providers/pool.js +81 -42
  90. package/lib/providers/rate-limit.js +8 -2
  91. package/lib/providers/replay.js +40 -17
  92. package/lib/providers/reset-redemption.js +18 -6
  93. package/lib/tools/image-generate.js +123 -65
  94. package/lib/tools/registration.js +5 -2
  95. package/lib/tools/video-generate.js +51 -31
  96. package/lib/tools/x-search.js +50 -22
  97. package/lib/translate/anthropic.js +85 -37
  98. package/lib/translate/antigravity-schema.js +71 -28
  99. package/lib/translate/antigravity-thinking.js +22 -9
  100. package/lib/translate/antigravity.js +151 -52
  101. package/lib/translate/chat-completions.js +67 -23
  102. package/lib/translate/resolved.js +55 -21
  103. package/lib/translate/responses.js +69 -29
  104. package/lib/translate/sse.js +4 -1
  105. package/package.json +27 -4
@@ -18,9 +18,10 @@ import { subscriptionChromeCss } from './provider-settings-styles.js';
18
18
  import { en } from './locales.js';
19
19
  /**
20
20
  * The `loadSpeed` half of the inject face: the plugin's own speed state plus
21
- * the host's current model selection (the visibility gate). A model-RPC
22
- * failure throws rather than answering "hidden" — the caller keeps its last
23
- * known state, so a transient failure never locks the toggle away.
21
+ * the host's current model selection (the visibility gate). A session whose
22
+ * model selection is unavailable (an addressed subagent) answers hidden.
23
+ * Any other model-directory failure throws, so the caller keeps its last
24
+ * known state instead of locking the toggle away.
24
25
  *
25
26
  * `sessionId` is a plain string: slot and command contexts brand it through
26
27
  * different dsh-session copies, and only the service boundary needs one.
@@ -31,20 +32,149 @@ import { en } from './locales.js';
31
32
  */
32
33
  export function createSpeedLoader(connection, models, sessionId) {
33
34
  return async () => {
34
- const state = await callSubscriptionsAuth(connection.rpc, 'speed', { sessionId });
35
35
  const directories = models();
36
- if (directories === undefined)
37
- return { visible: false, tier: state.tier };
38
- const { current } = await directories.directoryFor(sessionId).load();
39
- const visible = current !== null && current.provider === 'codex'
40
- && state.fastModels.includes(current.model);
36
+ let current = null;
37
+ if (directories !== undefined) {
38
+ try {
39
+ current = (await directories.directoryFor(sessionId).load()).current;
40
+ }
41
+ catch (error) {
42
+ if (!modelSelectionUnavailable(error))
43
+ throw error;
44
+ }
45
+ }
46
+ const state = await callSubscriptionsAuth(connection.rpc, 'speed', {
47
+ sessionId,
48
+ ...(current?.provider === 'codex' ? { model: current.model } : {}),
49
+ });
50
+ const visible = current !== null &&
51
+ current.provider === 'codex' &&
52
+ state.fastModels.includes(current.model);
41
53
  return { visible, tier: state.tier };
42
54
  };
43
55
  }
56
+ /** Host copy for a session that has no model seat (an addressed subagent). */
57
+ const MODEL_SELECTION_UNAVAILABLE = 'model selection is unavailable';
58
+ function modelSelectionUnavailable(error) {
59
+ const message = error instanceof Error ? error.message : String(error);
60
+ return message.includes(MODEL_SELECTION_UNAVAILABLE);
61
+ }
62
+ /** Stable identity of a model selection. Empty when nothing is selected. */
63
+ export function modelSelectionKey(current) {
64
+ if (current == null)
65
+ return '';
66
+ return JSON.stringify([current.provider, current.model]);
67
+ }
68
+ /**
69
+ * How often a host without a directory store is re-read, and how often a
70
+ * missing directory service is retried. Neither interval calls
71
+ * `subscriptions-auth.speed`.
72
+ */
73
+ export const MODEL_DIRECTORY_POLL_INTERVAL_MS = 3000;
74
+ /**
75
+ * Mount reads of `speed`, including the first attempt. Further failures stop
76
+ * instead of polling for the life of the composer.
77
+ */
78
+ export const SPEED_MOUNT_READ_ATTEMPTS = 4;
79
+ /** Fired after `/fast` writes a tier, so an open composer re-reads `speed`. */
80
+ export const SPEED_CHANGED_EVENT = 'dsh:subscriptions:speed-changed';
81
+ /** Tell mounted Speed controls that this page changed a session tier. */
82
+ export function notifySpeedChanged() {
83
+ if (typeof window === 'undefined')
84
+ return;
85
+ window.dispatchEvent(new Event(SPEED_CHANGED_EVENT));
86
+ }
87
+ /**
88
+ * Subscribe to the session's selected model. A directory store notifies the
89
+ * listener only when `provider` or `model` changes. A directory with no store
90
+ * is re-read on {@link MODEL_DIRECTORY_POLL_INTERVAL_MS}; a service that is
91
+ * not registered yet, or whose `directoryFor` throws, is retried on that same
92
+ * interval. The first successful attach after a miss notifies once, so a
93
+ * mount that ran before the service existed reads `speed` again.
94
+ */
95
+ export function createModelSelectionWatch(models, sessionId) {
96
+ return (listener) => {
97
+ let stopped = false;
98
+ let unsubscribeStore;
99
+ let timer;
100
+ let mode = 'seek';
101
+ let lastKey;
102
+ const stopTimer = () => {
103
+ if (timer === undefined)
104
+ return;
105
+ clearInterval(timer);
106
+ timer = undefined;
107
+ };
108
+ const changed = (current) => {
109
+ const next = modelSelectionKey(current);
110
+ if (lastKey === undefined) {
111
+ lastKey = next;
112
+ return false;
113
+ }
114
+ if (next === lastKey)
115
+ return false;
116
+ lastKey = next;
117
+ return true;
118
+ };
119
+ const attach = (late) => {
120
+ if (stopped || mode !== 'seek')
121
+ return;
122
+ let directory;
123
+ try {
124
+ directory = models()?.directoryFor(sessionId);
125
+ }
126
+ catch {
127
+ return;
128
+ }
129
+ if (directory === undefined)
130
+ return;
131
+ const store = directory.store;
132
+ if (store !== undefined) {
133
+ mode = 'store';
134
+ stopTimer();
135
+ lastKey = modelSelectionKey(store.getSnapshot().current);
136
+ unsubscribeStore = store.subscribe(() => {
137
+ if (!stopped && changed(store.getSnapshot().current))
138
+ listener();
139
+ });
140
+ if (late)
141
+ listener();
142
+ return;
143
+ }
144
+ mode = 'poll';
145
+ stopTimer();
146
+ let force = late;
147
+ const seed = () => {
148
+ void directory.load().then((state) => {
149
+ if (stopped || mode !== 'poll')
150
+ return;
151
+ const identityChanged = changed(state.current);
152
+ const forced = force;
153
+ force = false;
154
+ if (identityChanged || forced)
155
+ listener();
156
+ }, () => {
157
+ /* keep the last model; the next tick retries */
158
+ });
159
+ };
160
+ seed();
161
+ timer = setInterval(seed, MODEL_DIRECTORY_POLL_INTERVAL_MS);
162
+ };
163
+ attach(false);
164
+ if (mode === 'seek')
165
+ timer = setInterval(() => {
166
+ attach(true);
167
+ }, MODEL_DIRECTORY_POLL_INTERVAL_MS);
168
+ return () => {
169
+ stopped = true;
170
+ unsubscribeStore?.();
171
+ stopTimer();
172
+ };
173
+ };
174
+ }
44
175
  /** The `setSpeed` half of the inject face: boolean outcome for the component's busy state. */
45
176
  export function createSpeedSetter(connection, sessionId) {
46
- return tier => callSubscriptionsAuth(connection.rpc, 'setSpeed', { sessionId, tier })
47
- .then(() => true, () => false);
177
+ return (tier) => callSubscriptionsAuth(connection.rpc, 'setSpeed', { sessionId, tier }).then(() => true, () => false);
48
178
  }
49
179
  /** English-dictionary fallback for a missing inject `t` (standalone renders). */
50
180
  function fallbackTranslate(key) {
@@ -54,48 +184,86 @@ const TIERS = ['standard', 'fast'];
54
184
  /**
55
185
  * The composer Speed control: a trigger reading `速度 · 快速`/`速度 · 标准`
56
186
  * that opens a two-row menu (standard/fast with descriptions, check mark on
57
- * the current tier). Mount and every open reload the host state so a model
58
- * switch made since the last open self-corrects.
59
- */
60
- /** How often the control re-reads the host state (model switches arrive only by asking). */
61
- const POLL_INTERVAL_MS = 3000;
62
- /**
63
- * The composer Speed control: a trigger reading `速度 · 快速`/`速度 · 标准`
64
- * that opens a two-row menu (standard/fast with descriptions, check mark on
65
- * the current tier). The host pushes nothing on a model switch, so the
66
- * control re-reads on a slow poll with a single-flight guard; a failed read
67
- * keeps the last known state, so a transient RPC failure can never lock the
68
- * toggle away (the earlier mount-only load had no recovery path).
187
+ * the current tier). It reads `subscriptions-auth.speed` on mount, when the
188
+ * menu opens, when {@link SpeedSelectInjected.watchModel} reports a new
189
+ * selected model, and when {@link notifySpeedChanged} fires. Until the first
190
+ * read succeeds, a failure is retried on
191
+ * {@link MODEL_DIRECTORY_POLL_INTERVAL_MS}, at most
192
+ * {@link SPEED_MOUNT_READ_ATTEMPTS} times; after that, a failed read keeps
193
+ * the last known state.
69
194
  */
70
- export function SpeedSelect({ loadSpeed, setSpeed, t }) {
195
+ export function SpeedSelect({ loadSpeed, setSpeed, watchModel, t, }) {
71
196
  const translate = t ?? fallbackTranslate;
72
197
  const [state, setState] = useState(null);
73
198
  const [open, setOpen] = useState(false);
74
199
  const [busy, setBusy] = useState(false);
75
200
  const rootRef = useRef(null);
76
201
  // The inject face may be re-evaluated (new callback identities) on re-render;
77
- // the poll effect mounts once and reads through this ref, so identity churn
78
- // neither resets the interval nor multiplies in-flight loads.
202
+ // the mount effect reads through these refs, so identity churn neither
203
+ // resubscribes nor multiplies in-flight loads.
79
204
  const loadRef = useRef(loadSpeed);
80
205
  loadRef.current = loadSpeed;
206
+ const watchRef = useRef(watchModel);
207
+ watchRef.current = watchModel;
81
208
  useEffect(() => {
82
209
  if (loadRef.current === undefined)
83
210
  return;
84
211
  let cancelled = false;
85
212
  let inflight = false;
213
+ let again = false;
214
+ let loadedOnce = false;
215
+ let failures = 0;
216
+ let retry;
217
+ const stopRetry = () => {
218
+ if (retry === undefined)
219
+ return;
220
+ clearInterval(retry);
221
+ retry = undefined;
222
+ };
86
223
  const reload = () => {
87
224
  const load = loadRef.current;
88
- if (load === undefined || inflight)
225
+ if (load === undefined)
226
+ return;
227
+ if (inflight) {
228
+ again = true;
89
229
  return;
230
+ }
90
231
  inflight = true;
91
- void load().then((loaded) => { if (!cancelled)
92
- setState(loaded); }, () => { }).finally(() => { inflight = false; });
232
+ void load()
233
+ .then((loaded) => {
234
+ if (cancelled)
235
+ return;
236
+ loadedOnce = true;
237
+ stopRetry();
238
+ setState(loaded);
239
+ }, () => {
240
+ failures += 1;
241
+ if (failures >= SPEED_MOUNT_READ_ATTEMPTS)
242
+ stopRetry();
243
+ })
244
+ .finally(() => {
245
+ inflight = false;
246
+ if (cancelled || !again)
247
+ return;
248
+ again = false;
249
+ reload();
250
+ });
93
251
  };
94
252
  reload();
95
- const timer = setInterval(reload, POLL_INTERVAL_MS);
253
+ retry = setInterval(() => {
254
+ if (!loadedOnce)
255
+ reload();
256
+ }, MODEL_DIRECTORY_POLL_INTERVAL_MS);
257
+ const unsubscribe = watchRef.current?.(reload);
258
+ const onSpeedChanged = () => {
259
+ reload();
260
+ };
261
+ window.addEventListener(SPEED_CHANGED_EVENT, onSpeedChanged);
96
262
  return () => {
97
263
  cancelled = true;
98
- clearInterval(timer);
264
+ unsubscribe?.();
265
+ stopRetry();
266
+ window.removeEventListener(SPEED_CHANGED_EVENT, onSpeedChanged);
99
267
  };
100
268
  }, []);
101
269
  useEffect(() => {
@@ -106,9 +274,14 @@ export function SpeedSelect({ loadSpeed, setSpeed, t }) {
106
274
  setOpen(false);
107
275
  };
108
276
  document.addEventListener('mousedown', closeOutside);
109
- return () => { document.removeEventListener('mousedown', closeOutside); };
277
+ return () => {
278
+ document.removeEventListener('mousedown', closeOutside);
279
+ };
110
280
  }, [open]);
111
- if (loadSpeed === undefined || setSpeed === undefined || state === null || !state.visible) {
281
+ if (loadSpeed === undefined ||
282
+ setSpeed === undefined ||
283
+ state === null ||
284
+ !state.visible) {
112
285
  return null;
113
286
  }
114
287
  const choose = (tier) => {
@@ -132,7 +305,9 @@ export function SpeedSelect({ loadSpeed, setSpeed, t }) {
132
305
  const load = loadRef.current;
133
306
  if (load === undefined)
134
307
  return;
135
- void load().then(setState, () => { });
308
+ void load().then(setState, () => {
309
+ /* keep showing the last good state */
310
+ });
136
311
  };
137
312
  const tierName = (tier) => translate(tier === 'fast' ? 'speedFast' : 'speedStandard');
138
313
  const tierDescription = (tier) => translate(tier === 'fast' ? 'speedFastDescription' : 'speedStandardDescription');
@@ -142,7 +317,9 @@ export function SpeedSelect({ loadSpeed, setSpeed, t }) {
142
317
  event.preventDefault();
143
318
  setOpen(false);
144
319
  }
145
- }, children: [_jsx("style", { children: subscriptionChromeCss }), open && (_jsx("div", { style: styles.menu, role: "menu", "aria-label": translate('speed'), children: TIERS.map(tier => (_jsxs("button", { type: "button", role: "menuitemradio", "aria-checked": tier === state.tier, style: styles.item, disabled: busy, onClick: () => { choose(tier); }, children: [_jsx("span", { style: styles.itemCheck, children: tier === state.tier ? '✓' : '' }), _jsxs("span", { style: styles.itemText, children: [_jsx("span", { style: styles.itemName, children: tierName(tier) }), _jsx("span", { style: styles.itemDescription, children: tierDescription(tier) })] })] }, tier))) })), _jsx("button", { type: "button", style: styles.trigger, "aria-haspopup": "menu", "aria-expanded": open, title: triggerLabel, disabled: busy, onClick: () => {
320
+ }, children: [_jsx("style", { children: subscriptionChromeCss }), open && (_jsx("div", { style: styles.menu, role: "menu", "aria-label": translate('speed'), children: TIERS.map((tier) => (_jsxs("button", { type: "button", role: "menuitemradio", "aria-checked": tier === state.tier, style: styles.item, disabled: busy, onClick: () => {
321
+ choose(tier);
322
+ }, children: [_jsx("span", { style: styles.itemCheck, children: tier === state.tier ? '✓' : '' }), _jsxs("span", { style: styles.itemText, children: [_jsx("span", { style: styles.itemName, children: tierName(tier) }), _jsx("span", { style: styles.itemDescription, children: tierDescription(tier) })] })] }, tier))) })), _jsx("button", { type: "button", style: styles.trigger, "aria-haspopup": "menu", "aria-expanded": open, title: triggerLabel, disabled: busy, onClick: () => {
146
323
  if (open)
147
324
  setOpen(false);
148
325
  else
@@ -152,27 +329,62 @@ export function SpeedSelect({ loadSpeed, setSpeed, t }) {
152
329
  const styles = {
153
330
  root: { position: 'relative', display: 'inline-flex' },
154
331
  trigger: {
155
- border: '0.5px solid var(--dsw-alias-border-l3)', borderRadius: 'var(--dsw-radius-sm, 8px)',
156
- background: 'var(--dsh-subscription-speed-hover, transparent)', color: 'var(--dsw-alias-label-secondary)',
157
- font: 'inherit', fontSize: 12, lineHeight: '18px',
158
- padding: '2px 8px', cursor: 'pointer', whiteSpace: 'nowrap',
332
+ border: '0.5px solid var(--dsw-alias-border-l3)',
333
+ borderRadius: 'var(--dsw-radius-sm, 8px)',
334
+ background: 'var(--dsh-subscription-speed-hover, transparent)',
335
+ color: 'var(--dsw-alias-label-secondary)',
336
+ font: 'inherit',
337
+ fontSize: 12,
338
+ lineHeight: '18px',
339
+ padding: '2px 8px',
340
+ cursor: 'pointer',
341
+ whiteSpace: 'nowrap',
159
342
  },
160
343
  menu: {
161
- position: 'absolute', bottom: '100%', right: 0, marginBottom: 4,
162
- minWidth: 180, padding: 4, zIndex: 20,
163
- background: 'var(--dsw-specific-menu, var(--dsw-alias-bg-layer-2))', border: 0,
164
- boxShadow: 'var(--dsw-elevation-prominent)', borderRadius: 'var(--dsw-radius-lg, 16px)', display: 'flex', flexDirection: 'column', gap: 2,
344
+ position: 'absolute',
345
+ bottom: '100%',
346
+ right: 0,
347
+ marginBottom: 4,
348
+ minWidth: 180,
349
+ padding: 4,
350
+ zIndex: 20,
351
+ background: 'var(--dsw-specific-menu, var(--dsw-alias-bg-layer-2))',
352
+ border: 0,
353
+ boxShadow: 'var(--dsw-elevation-prominent)',
354
+ borderRadius: 'var(--dsw-radius-lg, 16px)',
355
+ display: 'flex',
356
+ flexDirection: 'column',
357
+ gap: 2,
165
358
  },
166
359
  item: {
167
- display: 'flex', alignItems: 'flex-start', gap: 6, width: '100%',
168
- border: 'none', borderRadius: 'var(--dsw-radius-sm, 8px)', background: 'var(--dsh-subscription-speed-hover, transparent)',
169
- padding: '6px 8px', cursor: 'pointer', font: 'inherit', textAlign: 'left',
360
+ display: 'flex',
361
+ alignItems: 'flex-start',
362
+ gap: 6,
363
+ width: '100%',
364
+ border: 'none',
365
+ borderRadius: 'var(--dsw-radius-sm, 8px)',
366
+ background: 'var(--dsh-subscription-speed-hover, transparent)',
367
+ padding: '6px 8px',
368
+ cursor: 'pointer',
369
+ font: 'inherit',
370
+ textAlign: 'left',
170
371
  },
171
372
  itemCheck: {
172
- width: 14, flexShrink: 0, fontSize: 12, lineHeight: '18px',
373
+ width: 14,
374
+ flexShrink: 0,
375
+ fontSize: 12,
376
+ lineHeight: '18px',
173
377
  color: 'var(--dsw-alias-label-primary)',
174
378
  },
175
379
  itemText: { display: 'flex', flexDirection: 'column' },
176
- itemName: { fontSize: 12, lineHeight: '18px', color: 'var(--dsw-alias-label-primary)' },
177
- itemDescription: { fontSize: 11, lineHeight: '16px', color: 'var(--dsw-alias-label-tertiary)' },
380
+ itemName: {
381
+ fontSize: 12,
382
+ lineHeight: '18px',
383
+ color: 'var(--dsw-alias-label-primary)',
384
+ },
385
+ itemDescription: {
386
+ fontSize: 11,
387
+ lineHeight: '16px',
388
+ color: 'var(--dsw-alias-label-tertiary)',
389
+ },
178
390
  };
@@ -20,9 +20,9 @@ export interface SubscriptionUsageBadgeInjected {
20
20
  } | undefined>;
21
21
  }
22
22
  /** Props delivered by the slot outlet + inject + the locale seat. */
23
- export type SubscriptionUsageBadgeProps = PropsRuntime<'conversation.composer.dock'> & Partial<SubscriptionUsageBadgeInjected> & Partial<PropsLocale<'settings.subscriptions'>>
23
+ export type SubscriptionUsageBadgeProps = PropsRuntime<'conversation.composer.dock'> & Partial<SubscriptionUsageBadgeInjected> & Partial<PropsLocale<'settings.subscriptions'>> &
24
24
  /** Override the rotation cadence (tests only; the slot never passes it). */
25
- & {
25
+ {
26
26
  rotationMs?: number;
27
27
  };
28
28
  /** One logged-in account's usage windows, as listed in the expanded dialog. */
@@ -118,15 +118,9 @@ export declare function rotatingDisplay(displays: readonly ProviderUsageDisplay[
118
118
  /** Order for the expanded dialog: the current provider first, the rest in poll order. */
119
119
  export declare function expandedDisplays(displays: readonly ProviderUsageDisplay[], current: string | undefined): readonly ProviderUsageDisplay[];
120
120
  type Translate = (key: SubscriptionsKey, params?: Record<string, unknown>) => string;
121
- /**
122
- * The composer subscription-usage badge: a pill reading e.g.
123
- * `Codex 6d1h 25%` for the current model's provider, opening a dialog with
124
- * every provider's accounts and their windows. Returns null when no data is
125
- * available.
126
- */
127
- export declare function SubscriptionUsageBadge({ rpc, currentModel, t, rotationMs }: SubscriptionUsageBadgeProps): import("react").JSX.Element;
121
+ export declare function SubscriptionUsageBadge({ rpc, currentModel, t, rotationMs, }: SubscriptionUsageBadgeProps): import("react").JSX.Element;
128
122
  /** Preview each account independently; all remaining quotas stay accessible. */
129
- export declare function AccountWindows({ windows, model, provider, translate, observedAt, stale }: {
123
+ export declare function AccountWindows({ windows, model, provider, translate, observedAt, stale, }: {
130
124
  windows: readonly UsageWindow[];
131
125
  model: string | undefined;
132
126
  provider?: BadgeProvider;