dsh-subscriptions 0.1.5 → 0.2.2

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 (110) hide show
  1. package/README.md +212 -154
  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 +73 -2
  6. package/lib/auth/rpc.js +124 -23
  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 +13 -0
  16. package/lib/client/OllamaCard.js +94 -0
  17. package/lib/client/OllamaSettingsManager.d.ts +24 -0
  18. package/lib/client/OllamaSettingsManager.js +329 -0
  19. package/lib/client/ProviderAccountManager.d.ts +1 -1
  20. package/lib/client/ProviderAccountManager.js +164 -49
  21. package/lib/client/ProviderModelEditor.js +109 -26
  22. package/lib/client/SpeedSelect.d.ts +62 -14
  23. package/lib/client/SpeedSelect.js +257 -46
  24. package/lib/client/SubscriptionUsageBadge.d.ts +5 -11
  25. package/lib/client/SubscriptionUsageBadge.js +301 -112
  26. package/lib/client/SubscriptionsSection.d.ts +2 -0
  27. package/lib/client/SubscriptionsSection.js +259 -85
  28. package/lib/client/UsageBadgeDisplaySetting.js +35 -12
  29. package/lib/client/UsageMeter.d.ts +1 -1
  30. package/lib/client/UsageMeter.js +69 -27
  31. package/lib/client/VideoGenerateToolview.js +69 -17
  32. package/lib/client/account-preferences.d.ts +8 -0
  33. package/lib/client/account-preferences.js +20 -5
  34. package/lib/client/host-contract.d.ts +11 -2
  35. package/lib/client/host-contract.js +20 -3
  36. package/lib/client/index.d.ts +5 -5
  37. package/lib/client/index.js +34 -12
  38. package/lib/client/locales.d.ts +78 -0
  39. package/lib/client/locales.js +121 -34
  40. package/lib/client/ollama-draft.d.ts +229 -0
  41. package/lib/client/ollama-draft.js +255 -0
  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.d.ts +7 -0
  48. package/lib/client/usage-pace.js +43 -10
  49. package/lib/client.js +1647 -266
  50. package/lib/client.js.map +1 -1
  51. package/lib/http.js +1 -1
  52. package/lib/index.d.ts +28 -3
  53. package/lib/index.js +9329 -8217
  54. package/lib/model-defaults.js +4 -2
  55. package/lib/provider-settings.d.ts +14 -1
  56. package/lib/provider-settings.js +64 -20
  57. package/lib/providers/account-preferences.js +51 -22
  58. package/lib/providers/accounts.js +15 -9
  59. package/lib/providers/antigravity-oauth-client.js +2 -2
  60. package/lib/providers/antigravity.js +141 -68
  61. package/lib/providers/catalog-store.js +120 -41
  62. package/lib/providers/claude-cli-version.js +3 -3
  63. package/lib/providers/claude.d.ts +23 -3
  64. package/lib/providers/claude.js +167 -92
  65. package/lib/providers/codex-client-version.js +3 -3
  66. package/lib/providers/codex-search.js +40 -13
  67. package/lib/providers/codex.js +196 -112
  68. package/lib/providers/common.d.ts +14 -0
  69. package/lib/providers/common.js +118 -38
  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.d.ts +9 -2
  77. package/lib/providers/external-usage-controller.js +30 -7
  78. package/lib/providers/external-usage.d.ts +8 -0
  79. package/lib/providers/external-usage.js +140 -20
  80. package/lib/providers/grok.js +152 -89
  81. package/lib/providers/image-pool.js +29 -11
  82. package/lib/providers/minimax-usage.js +31 -11
  83. package/lib/providers/npm-cli-version.js +10 -3
  84. package/lib/providers/ollama-settings.d.ts +90 -0
  85. package/lib/providers/ollama-settings.js +213 -0
  86. package/lib/providers/ollama-web.d.ts +46 -0
  87. package/lib/providers/ollama-web.js +231 -0
  88. package/lib/providers/ollama.d.ts +107 -0
  89. package/lib/providers/ollama.js +608 -0
  90. package/lib/providers/pool-family.js +11 -3
  91. package/lib/providers/pool-health.js +28 -8
  92. package/lib/providers/pool-usage.js +16 -9
  93. package/lib/providers/pool.d.ts +8 -0
  94. package/lib/providers/pool.js +81 -42
  95. package/lib/providers/rate-limit.js +8 -2
  96. package/lib/providers/replay.js +40 -17
  97. package/lib/providers/reset-redemption.js +18 -6
  98. package/lib/tools/image-generate.js +123 -65
  99. package/lib/tools/registration.js +5 -2
  100. package/lib/tools/video-generate.js +51 -31
  101. package/lib/tools/x-search.js +50 -22
  102. package/lib/translate/anthropic.js +85 -37
  103. package/lib/translate/antigravity-schema.js +71 -28
  104. package/lib/translate/antigravity-thinking.js +22 -9
  105. package/lib/translate/antigravity.js +141 -50
  106. package/lib/translate/chat-completions.js +67 -23
  107. package/lib/translate/resolved.js +55 -21
  108. package/lib/translate/responses.js +69 -29
  109. package/lib/translate/sse.js +4 -1
  110. package/package.json +26 -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.
@@ -35,16 +36,144 @@ export function createSpeedLoader(connection, models, sessionId) {
35
36
  const directories = models();
36
37
  if (directories === undefined)
37
38
  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);
39
+ let current;
40
+ try {
41
+ const loaded = await directories.directoryFor(sessionId).load();
42
+ current = loaded.current;
43
+ }
44
+ catch (error) {
45
+ if (!modelSelectionUnavailable(error))
46
+ throw error;
47
+ return { visible: false, tier: state.tier };
48
+ }
49
+ const visible = current !== null &&
50
+ current.provider === 'codex' &&
51
+ state.fastModels.includes(current.model);
41
52
  return { visible, tier: state.tier };
42
53
  };
43
54
  }
55
+ /** Host copy for a session that has no model seat (an addressed subagent). */
56
+ const MODEL_SELECTION_UNAVAILABLE = 'model selection is unavailable';
57
+ function modelSelectionUnavailable(error) {
58
+ const message = error instanceof Error ? error.message : String(error);
59
+ return message.includes(MODEL_SELECTION_UNAVAILABLE);
60
+ }
61
+ /** Stable identity of a model selection. Empty when nothing is selected. */
62
+ export function modelSelectionKey(current) {
63
+ if (current == null)
64
+ return '';
65
+ return JSON.stringify([current.provider, current.model]);
66
+ }
67
+ /**
68
+ * How often a host without a directory store is re-read, and how often a
69
+ * missing directory service is retried. Neither interval calls
70
+ * `subscriptions-auth.speed`.
71
+ */
72
+ export const MODEL_DIRECTORY_POLL_INTERVAL_MS = 3000;
73
+ /**
74
+ * Mount reads of `speed`, including the first attempt. Further failures stop
75
+ * instead of polling for the life of the composer.
76
+ */
77
+ export const SPEED_MOUNT_READ_ATTEMPTS = 4;
78
+ /** Fired after `/fast` writes a tier, so an open composer re-reads `speed`. */
79
+ export const SPEED_CHANGED_EVENT = 'dsh:subscriptions:speed-changed';
80
+ /** Tell mounted Speed controls that this page changed a session tier. */
81
+ export function notifySpeedChanged() {
82
+ if (typeof window === 'undefined')
83
+ return;
84
+ window.dispatchEvent(new Event(SPEED_CHANGED_EVENT));
85
+ }
86
+ /**
87
+ * Subscribe to the session's selected model. A directory store notifies the
88
+ * listener only when `provider` or `model` changes. A directory with no store
89
+ * is re-read on {@link MODEL_DIRECTORY_POLL_INTERVAL_MS}; a service that is
90
+ * not registered yet, or whose `directoryFor` throws, is retried on that same
91
+ * interval. The first successful attach after a miss notifies once, so a
92
+ * mount that ran before the service existed reads `speed` again.
93
+ */
94
+ export function createModelSelectionWatch(models, sessionId) {
95
+ return (listener) => {
96
+ let stopped = false;
97
+ let unsubscribeStore;
98
+ let timer;
99
+ let mode = 'seek';
100
+ let lastKey;
101
+ const stopTimer = () => {
102
+ if (timer === undefined)
103
+ return;
104
+ clearInterval(timer);
105
+ timer = undefined;
106
+ };
107
+ const changed = (current) => {
108
+ const next = modelSelectionKey(current);
109
+ if (lastKey === undefined) {
110
+ lastKey = next;
111
+ return false;
112
+ }
113
+ if (next === lastKey)
114
+ return false;
115
+ lastKey = next;
116
+ return true;
117
+ };
118
+ const attach = (late) => {
119
+ if (stopped || mode !== 'seek')
120
+ return;
121
+ let directory;
122
+ try {
123
+ directory = models()?.directoryFor(sessionId);
124
+ }
125
+ catch {
126
+ return;
127
+ }
128
+ if (directory === undefined)
129
+ return;
130
+ const store = directory.store;
131
+ if (store !== undefined) {
132
+ mode = 'store';
133
+ stopTimer();
134
+ lastKey = modelSelectionKey(store.getSnapshot().current);
135
+ unsubscribeStore = store.subscribe(() => {
136
+ if (!stopped && changed(store.getSnapshot().current))
137
+ listener();
138
+ });
139
+ if (late)
140
+ listener();
141
+ return;
142
+ }
143
+ mode = 'poll';
144
+ stopTimer();
145
+ let force = late;
146
+ const seed = () => {
147
+ void directory.load().then((state) => {
148
+ if (stopped || mode !== 'poll')
149
+ return;
150
+ const identityChanged = changed(state.current);
151
+ const forced = force;
152
+ force = false;
153
+ if (identityChanged || forced)
154
+ listener();
155
+ }, () => {
156
+ /* keep the last model; the next tick retries */
157
+ });
158
+ };
159
+ seed();
160
+ timer = setInterval(seed, MODEL_DIRECTORY_POLL_INTERVAL_MS);
161
+ };
162
+ attach(false);
163
+ if (mode === 'seek')
164
+ timer = setInterval(() => {
165
+ attach(true);
166
+ }, MODEL_DIRECTORY_POLL_INTERVAL_MS);
167
+ return () => {
168
+ stopped = true;
169
+ unsubscribeStore?.();
170
+ stopTimer();
171
+ };
172
+ };
173
+ }
44
174
  /** The `setSpeed` half of the inject face: boolean outcome for the component's busy state. */
45
175
  export function createSpeedSetter(connection, sessionId) {
46
- return tier => callSubscriptionsAuth(connection.rpc, 'setSpeed', { sessionId, tier })
47
- .then(() => true, () => false);
176
+ return (tier) => callSubscriptionsAuth(connection.rpc, 'setSpeed', { sessionId, tier }).then(() => true, () => false);
48
177
  }
49
178
  /** English-dictionary fallback for a missing inject `t` (standalone renders). */
50
179
  function fallbackTranslate(key) {
@@ -54,48 +183,86 @@ const TIERS = ['standard', 'fast'];
54
183
  /**
55
184
  * The composer Speed control: a trigger reading `速度 · 快速`/`速度 · 标准`
56
185
  * 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.
186
+ * the current tier). It reads `subscriptions-auth.speed` on mount, when the
187
+ * menu opens, when {@link SpeedSelectInjected.watchModel} reports a new
188
+ * selected model, and when {@link notifySpeedChanged} fires. Until the first
189
+ * read succeeds, a failure is retried on
190
+ * {@link MODEL_DIRECTORY_POLL_INTERVAL_MS}, at most
191
+ * {@link SPEED_MOUNT_READ_ATTEMPTS} times; after that, a failed read keeps
192
+ * the last known state.
59
193
  */
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).
69
- */
70
- export function SpeedSelect({ loadSpeed, setSpeed, t }) {
194
+ export function SpeedSelect({ loadSpeed, setSpeed, watchModel, t, }) {
71
195
  const translate = t ?? fallbackTranslate;
72
196
  const [state, setState] = useState(null);
73
197
  const [open, setOpen] = useState(false);
74
198
  const [busy, setBusy] = useState(false);
75
199
  const rootRef = useRef(null);
76
200
  // 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.
201
+ // the mount effect reads through these refs, so identity churn neither
202
+ // resubscribes nor multiplies in-flight loads.
79
203
  const loadRef = useRef(loadSpeed);
80
204
  loadRef.current = loadSpeed;
205
+ const watchRef = useRef(watchModel);
206
+ watchRef.current = watchModel;
81
207
  useEffect(() => {
82
208
  if (loadRef.current === undefined)
83
209
  return;
84
210
  let cancelled = false;
85
211
  let inflight = false;
212
+ let again = false;
213
+ let loadedOnce = false;
214
+ let failures = 0;
215
+ let retry;
216
+ const stopRetry = () => {
217
+ if (retry === undefined)
218
+ return;
219
+ clearInterval(retry);
220
+ retry = undefined;
221
+ };
86
222
  const reload = () => {
87
223
  const load = loadRef.current;
88
- if (load === undefined || inflight)
224
+ if (load === undefined)
225
+ return;
226
+ if (inflight) {
227
+ again = true;
89
228
  return;
229
+ }
90
230
  inflight = true;
91
- void load().then((loaded) => { if (!cancelled)
92
- setState(loaded); }, () => { }).finally(() => { inflight = false; });
231
+ void load()
232
+ .then((loaded) => {
233
+ if (cancelled)
234
+ return;
235
+ loadedOnce = true;
236
+ stopRetry();
237
+ setState(loaded);
238
+ }, () => {
239
+ failures += 1;
240
+ if (failures >= SPEED_MOUNT_READ_ATTEMPTS)
241
+ stopRetry();
242
+ })
243
+ .finally(() => {
244
+ inflight = false;
245
+ if (cancelled || !again)
246
+ return;
247
+ again = false;
248
+ reload();
249
+ });
93
250
  };
94
251
  reload();
95
- const timer = setInterval(reload, POLL_INTERVAL_MS);
252
+ retry = setInterval(() => {
253
+ if (!loadedOnce)
254
+ reload();
255
+ }, MODEL_DIRECTORY_POLL_INTERVAL_MS);
256
+ const unsubscribe = watchRef.current?.(reload);
257
+ const onSpeedChanged = () => {
258
+ reload();
259
+ };
260
+ window.addEventListener(SPEED_CHANGED_EVENT, onSpeedChanged);
96
261
  return () => {
97
262
  cancelled = true;
98
- clearInterval(timer);
263
+ unsubscribe?.();
264
+ stopRetry();
265
+ window.removeEventListener(SPEED_CHANGED_EVENT, onSpeedChanged);
99
266
  };
100
267
  }, []);
101
268
  useEffect(() => {
@@ -106,9 +273,14 @@ export function SpeedSelect({ loadSpeed, setSpeed, t }) {
106
273
  setOpen(false);
107
274
  };
108
275
  document.addEventListener('mousedown', closeOutside);
109
- return () => { document.removeEventListener('mousedown', closeOutside); };
276
+ return () => {
277
+ document.removeEventListener('mousedown', closeOutside);
278
+ };
110
279
  }, [open]);
111
- if (loadSpeed === undefined || setSpeed === undefined || state === null || !state.visible) {
280
+ if (loadSpeed === undefined ||
281
+ setSpeed === undefined ||
282
+ state === null ||
283
+ !state.visible) {
112
284
  return null;
113
285
  }
114
286
  const choose = (tier) => {
@@ -132,7 +304,9 @@ export function SpeedSelect({ loadSpeed, setSpeed, t }) {
132
304
  const load = loadRef.current;
133
305
  if (load === undefined)
134
306
  return;
135
- void load().then(setState, () => { });
307
+ void load().then(setState, () => {
308
+ /* keep showing the last good state */
309
+ });
136
310
  };
137
311
  const tierName = (tier) => translate(tier === 'fast' ? 'speedFast' : 'speedStandard');
138
312
  const tierDescription = (tier) => translate(tier === 'fast' ? 'speedFastDescription' : 'speedStandardDescription');
@@ -142,7 +316,9 @@ export function SpeedSelect({ loadSpeed, setSpeed, t }) {
142
316
  event.preventDefault();
143
317
  setOpen(false);
144
318
  }
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: () => {
319
+ }, 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: () => {
320
+ choose(tier);
321
+ }, 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
322
  if (open)
147
323
  setOpen(false);
148
324
  else
@@ -152,27 +328,62 @@ export function SpeedSelect({ loadSpeed, setSpeed, t }) {
152
328
  const styles = {
153
329
  root: { position: 'relative', display: 'inline-flex' },
154
330
  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',
331
+ border: '0.5px solid var(--dsw-alias-border-l3)',
332
+ borderRadius: 'var(--dsw-radius-sm, 8px)',
333
+ background: 'var(--dsh-subscription-speed-hover, transparent)',
334
+ color: 'var(--dsw-alias-label-secondary)',
335
+ font: 'inherit',
336
+ fontSize: 12,
337
+ lineHeight: '18px',
338
+ padding: '2px 8px',
339
+ cursor: 'pointer',
340
+ whiteSpace: 'nowrap',
159
341
  },
160
342
  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,
343
+ position: 'absolute',
344
+ bottom: '100%',
345
+ right: 0,
346
+ marginBottom: 4,
347
+ minWidth: 180,
348
+ padding: 4,
349
+ zIndex: 20,
350
+ background: 'var(--dsw-specific-menu, var(--dsw-alias-bg-layer-2))',
351
+ border: 0,
352
+ boxShadow: 'var(--dsw-elevation-prominent)',
353
+ borderRadius: 'var(--dsw-radius-lg, 16px)',
354
+ display: 'flex',
355
+ flexDirection: 'column',
356
+ gap: 2,
165
357
  },
166
358
  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',
359
+ display: 'flex',
360
+ alignItems: 'flex-start',
361
+ gap: 6,
362
+ width: '100%',
363
+ border: 'none',
364
+ borderRadius: 'var(--dsw-radius-sm, 8px)',
365
+ background: 'var(--dsh-subscription-speed-hover, transparent)',
366
+ padding: '6px 8px',
367
+ cursor: 'pointer',
368
+ font: 'inherit',
369
+ textAlign: 'left',
170
370
  },
171
371
  itemCheck: {
172
- width: 14, flexShrink: 0, fontSize: 12, lineHeight: '18px',
372
+ width: 14,
373
+ flexShrink: 0,
374
+ fontSize: 12,
375
+ lineHeight: '18px',
173
376
  color: 'var(--dsw-alias-label-primary)',
174
377
  },
175
378
  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)' },
379
+ itemName: {
380
+ fontSize: 12,
381
+ lineHeight: '18px',
382
+ color: 'var(--dsw-alias-label-primary)',
383
+ },
384
+ itemDescription: {
385
+ fontSize: 11,
386
+ lineHeight: '16px',
387
+ color: 'var(--dsw-alias-label-tertiary)',
388
+ },
178
389
  };
@@ -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. */
@@ -48,7 +48,7 @@ export interface ProviderUsageDisplay {
48
48
  /** The account the collapsed pill reads: the default one, else the first listed. */
49
49
  export declare function pillAccountOf(d: ProviderUsageDisplay): AccountUsageDisplay;
50
50
  /** Brand display names (short form for the compact badge). */
51
- export type BadgeProvider = SubscriptionProvider | 'cursor-subscription' | 'opencode-go' | 'kimi-coding' | 'minimax' | 'minimax-cn';
51
+ export type BadgeProvider = SubscriptionProvider | 'cursor-subscription' | 'opencode-go' | 'kimi-coding' | 'minimax' | 'minimax-cn' | 'ollama-cloud';
52
52
  export interface UsageRosterEntry {
53
53
  provider: BadgeProvider;
54
54
  account: AccountStatus;
@@ -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;