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.
- package/README.md +212 -154
- package/lib/auth/claude-code-creds.js +31 -9
- package/lib/auth/device-flow.js +16 -9
- package/lib/auth/oauth-flow.js +13 -10
- package/lib/auth/rpc.d.ts +73 -2
- package/lib/auth/rpc.js +124 -23
- package/lib/auth/store.js +80 -31
- package/lib/client/CursorCard.d.ts +1 -1
- package/lib/client/CursorCard.js +50 -16
- package/lib/client/ExternalUsageCards.d.ts +1 -1
- package/lib/client/ExternalUsageCards.js +37 -16
- package/lib/client/ImageGallery.d.ts +2 -2
- package/lib/client/ImageGallery.js +92 -33
- package/lib/client/ImageGenerateToolview.js +50 -14
- package/lib/client/OllamaCard.d.ts +13 -0
- package/lib/client/OllamaCard.js +94 -0
- package/lib/client/OllamaSettingsManager.d.ts +24 -0
- package/lib/client/OllamaSettingsManager.js +329 -0
- package/lib/client/ProviderAccountManager.d.ts +1 -1
- package/lib/client/ProviderAccountManager.js +164 -49
- package/lib/client/ProviderModelEditor.js +109 -26
- package/lib/client/SpeedSelect.d.ts +62 -14
- package/lib/client/SpeedSelect.js +257 -46
- package/lib/client/SubscriptionUsageBadge.d.ts +5 -11
- package/lib/client/SubscriptionUsageBadge.js +301 -112
- package/lib/client/SubscriptionsSection.d.ts +2 -0
- package/lib/client/SubscriptionsSection.js +259 -85
- package/lib/client/UsageBadgeDisplaySetting.js +35 -12
- package/lib/client/UsageMeter.d.ts +1 -1
- package/lib/client/UsageMeter.js +69 -27
- package/lib/client/VideoGenerateToolview.js +69 -17
- package/lib/client/account-preferences.d.ts +8 -0
- package/lib/client/account-preferences.js +20 -5
- package/lib/client/host-contract.d.ts +11 -2
- package/lib/client/host-contract.js +20 -3
- package/lib/client/index.d.ts +5 -5
- package/lib/client/index.js +34 -12
- package/lib/client/locales.d.ts +78 -0
- package/lib/client/locales.js +121 -34
- package/lib/client/ollama-draft.d.ts +229 -0
- package/lib/client/ollama-draft.js +255 -0
- package/lib/client/reset-action.js +6 -4
- package/lib/client/reset-credits-view.d.ts +1 -1
- package/lib/client/reset-credits-view.js +66 -17
- package/lib/client/subscription-card-styles.js +94 -24
- package/lib/client/usage-color-preferences.js +4 -2
- package/lib/client/usage-pace.d.ts +7 -0
- package/lib/client/usage-pace.js +43 -10
- package/lib/client.js +1647 -266
- package/lib/client.js.map +1 -1
- package/lib/http.js +1 -1
- package/lib/index.d.ts +28 -3
- package/lib/index.js +9329 -8217
- package/lib/model-defaults.js +4 -2
- package/lib/provider-settings.d.ts +14 -1
- package/lib/provider-settings.js +64 -20
- package/lib/providers/account-preferences.js +51 -22
- package/lib/providers/accounts.js +15 -9
- package/lib/providers/antigravity-oauth-client.js +2 -2
- package/lib/providers/antigravity.js +141 -68
- package/lib/providers/catalog-store.js +120 -41
- package/lib/providers/claude-cli-version.js +3 -3
- package/lib/providers/claude.d.ts +23 -3
- package/lib/providers/claude.js +167 -92
- package/lib/providers/codex-client-version.js +3 -3
- package/lib/providers/codex-search.js +40 -13
- package/lib/providers/codex.js +196 -112
- package/lib/providers/common.d.ts +14 -0
- package/lib/providers/common.js +118 -38
- package/lib/providers/copilot.js +143 -82
- package/lib/providers/cursor-adapter.js +42 -18
- package/lib/providers/cursor-auth.d.ts +1 -1
- package/lib/providers/cursor-auth.js +69 -24
- package/lib/providers/cursor-model-settings.js +14 -5
- package/lib/providers/cursor-usage.js +27 -13
- package/lib/providers/external-usage-controller.d.ts +9 -2
- package/lib/providers/external-usage-controller.js +30 -7
- package/lib/providers/external-usage.d.ts +8 -0
- package/lib/providers/external-usage.js +140 -20
- package/lib/providers/grok.js +152 -89
- package/lib/providers/image-pool.js +29 -11
- package/lib/providers/minimax-usage.js +31 -11
- package/lib/providers/npm-cli-version.js +10 -3
- package/lib/providers/ollama-settings.d.ts +90 -0
- package/lib/providers/ollama-settings.js +213 -0
- package/lib/providers/ollama-web.d.ts +46 -0
- package/lib/providers/ollama-web.js +231 -0
- package/lib/providers/ollama.d.ts +107 -0
- package/lib/providers/ollama.js +608 -0
- package/lib/providers/pool-family.js +11 -3
- package/lib/providers/pool-health.js +28 -8
- package/lib/providers/pool-usage.js +16 -9
- package/lib/providers/pool.d.ts +8 -0
- package/lib/providers/pool.js +81 -42
- package/lib/providers/rate-limit.js +8 -2
- package/lib/providers/replay.js +40 -17
- package/lib/providers/reset-redemption.js +18 -6
- package/lib/tools/image-generate.js +123 -65
- package/lib/tools/registration.js +5 -2
- package/lib/tools/video-generate.js +51 -31
- package/lib/tools/x-search.js +50 -22
- package/lib/translate/anthropic.js +85 -37
- package/lib/translate/antigravity-schema.js +71 -28
- package/lib/translate/antigravity-thinking.js +22 -9
- package/lib/translate/antigravity.js +141 -50
- package/lib/translate/chat-completions.js +67 -23
- package/lib/translate/resolved.js +55 -21
- package/lib/translate/responses.js +69 -29
- package/lib/translate/sse.js +4 -1
- 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
|
|
22
|
-
*
|
|
23
|
-
*
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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).
|
|
58
|
-
*
|
|
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
|
-
|
|
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
|
|
78
|
-
//
|
|
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
|
|
224
|
+
if (load === undefined)
|
|
225
|
+
return;
|
|
226
|
+
if (inflight) {
|
|
227
|
+
again = true;
|
|
89
228
|
return;
|
|
229
|
+
}
|
|
90
230
|
inflight = true;
|
|
91
|
-
void load()
|
|
92
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 () => {
|
|
276
|
+
return () => {
|
|
277
|
+
document.removeEventListener('mousedown', closeOutside);
|
|
278
|
+
};
|
|
110
279
|
}, [open]);
|
|
111
|
-
if (loadSpeed === undefined ||
|
|
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: () => {
|
|
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)',
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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',
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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',
|
|
168
|
-
|
|
169
|
-
|
|
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,
|
|
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: {
|
|
177
|
-
|
|
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;
|