dsh-subscriptions 0.2.3 → 0.3.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 (35) hide show
  1. package/README.md +7 -19
  2. package/lib/auth/rpc.d.ts +2 -20
  3. package/lib/auth/rpc.js +3 -49
  4. package/lib/client/ProviderAccountManager.d.ts +1 -1
  5. package/lib/client/ProviderAccountManager.js +86 -110
  6. package/lib/client/ProviderModelEditor.d.ts +1 -1
  7. package/lib/client/ProviderModelEditor.js +2 -6
  8. package/lib/client/SubscriptionUsageBadge.d.ts +1 -1
  9. package/lib/client/SubscriptionUsageBadge.js +1 -13
  10. package/lib/client/SubscriptionsSection.js +1 -2
  11. package/lib/client/locales.d.ts +0 -32
  12. package/lib/client/locales.js +0 -32
  13. package/lib/client/model-filter.js +1 -1
  14. package/lib/client/subscription-card-styles.d.ts +1 -1
  15. package/lib/client/subscription-card-styles.js +1 -1
  16. package/lib/client.js +175 -489
  17. package/lib/client.js.map +1 -1
  18. package/lib/index.js +165 -3275
  19. package/lib/providers/ollama-settings.d.ts +1 -1
  20. package/lib/providers/ollama-settings.js +1 -1
  21. package/package.json +1 -7
  22. package/lib/client/CursorCard.d.ts +0 -9
  23. package/lib/client/CursorCard.js +0 -151
  24. package/lib/providers/cursor-adapter.d.ts +0 -50
  25. package/lib/providers/cursor-adapter.js +0 -304
  26. package/lib/providers/cursor-auth.d.ts +0 -43
  27. package/lib/providers/cursor-auth.js +0 -221
  28. package/lib/providers/cursor-model-settings.d.ts +0 -15
  29. package/lib/providers/cursor-model-settings.js +0 -60
  30. package/lib/providers/cursor-usage.d.ts +0 -9
  31. package/lib/providers/cursor-usage.js +0 -131
  32. package/vendor/cursor/LICENSE +0 -21
  33. package/vendor/cursor/index.d.ts +0 -18
  34. package/vendor/cursor/index.js +0 -3574
  35. package/vendor/cursor/proto.js +0 -254
package/README.md CHANGED
@@ -10,9 +10,9 @@ reported quota in **Settings → Subscriptions**.
10
10
 
11
11
  ## What it adds
12
12
 
13
- - **Six subscription model sources:** Connect ChatGPT/Codex, Claude, Grok,
14
- GitHub Copilot, Google Antigravity, or Cursor and choose their models in DSH's
15
- picker. These routes use account sign-in, without provider API keys.
13
+ - **Five subscription model sources:** Connect ChatGPT/Codex, Claude, Grok,
14
+ GitHub Copilot, or Google Antigravity and choose their models in DSH's picker.
15
+ These routes use account sign-in, without provider API keys.
16
16
  - **Ollama Cloud key route:** Add the `ollama-cloud` route with an
17
17
  `OLLAMA_API_KEY` credential. The route ships no model catalog: configure it on
18
18
  the Settings → Subscriptions card, which fetches the cloud list, ticks the
@@ -46,10 +46,10 @@ reported quota in **Settings → Subscriptions**.
46
46
 
47
47
  ## Screenshots
48
48
 
49
- Captured against DSH 0.2.0-rc.2 in the web UI with a local stub serving frozen
50
- provider responses, so each image shows a product state rather than a real
51
- account. Identities in the images are fabricated, and the quota percentages,
52
- catalogs, and reset countdowns are sample data.
49
+ Captured against DSH 0.2.0-rc.2 and 0.2.1-rc.5 in the web UI with a local stub
50
+ serving frozen provider responses, so each image shows a product state rather
51
+ than a real account. Identities in the images are fabricated, and the quota
52
+ percentages, catalogs, and reset countdowns are sample data.
53
53
 
54
54
  ### Subscriptions
55
55
 
@@ -224,12 +224,6 @@ the checks and their limits.
224
224
  A manual check in an isolated `0.1.7-rc.2` web profile found the client bundle
225
225
  served and the auth and usage-status RPCs answering. Live sign-in and model
226
226
  requests on the supported DSH lines remain to be checked.
227
- - **Cursor:** Browser sign-in and live model discovery were verified in an
228
- isolated `0.1.7-rc.2` profile. A successful live model request remains to be
229
- verified. Its transport comes from
230
- [orrinzeng/dsh-cursor-subscription](https://github.com/orrinzeng/dsh-cursor-subscription)
231
- and uses an undocumented Cursor protocol; see the
232
- [source note](docs/cursor-origin.md).
233
227
  - **OpenCode Go and Kimi Code:** Live usage responses were verified. Their API
234
228
  keys stay on the DSH host; the browser receives configured status and quota
235
229
  windows, not the keys.
@@ -239,12 +233,6 @@ the checks and their limits.
239
233
  browser test. Live chat, listing, usage, and web calls against `ollama.com`
240
234
  remain to be verified with a real key.
241
235
 
242
- Cursor uses one connected account and a live model catalog. Its model visibility
243
- selection persists under the DSH home directory, and automatic display follows
244
- newly discovered models. It ships no fallback model list and does not import the
245
- local `cursor-agent` credential cache. Individual usage comes from Cursor
246
- dashboard endpoints; the documented Admin API covers team usage.
247
-
248
236
  The plugin follows DSH network settings. Its former proxy configuration and UI
249
237
  have been retired; an old plugin proxy config file is ignored.
250
238
 
package/lib/auth/rpc.d.ts CHANGED
@@ -12,7 +12,6 @@ import { type ProviderId } from './store.js';
12
12
  import type { ProviderUsage } from '../providers/common.js';
13
13
  import type { CliVersion } from '../providers/npm-cli-version.js';
14
14
  import type { ExternalUsageSource, ExternalUsageStatus } from '../providers/external-usage-controller.js';
15
- import type { CursorAuthStatus } from '../providers/cursor-auth.js';
16
15
  /**
17
16
  * Endpoint-name prefix under the shared `/api` channel: endpoint `status`
18
17
  * is served at `/api/subscriptions-auth.status`. The browser half calls
@@ -23,7 +22,7 @@ export declare const SUBSCRIPTIONS_AUTH_PREFIX = "subscriptions-auth.";
23
22
  * Every endpoint {@link dispatch} answers; each gets one exact Fetch route.
24
23
  * Kept in one place so the route table and the switch cannot drift apart.
25
24
  */
26
- export declare const SUBSCRIPTIONS_AUTH_ENDPOINTS: readonly ["providerSettings", "setProviderSettings", "status", "login", "manual", "cancel", "logout", "setDefault", "usage", "externalStatus", "externalUsage", "cursorStatus", "cursorLogin", "cursorCancel", "cursorLogout", "cursorUsage", "cursorModels", "cursorSettings", "cursorSetSettings", "ollamaSettings", "ollamaSetSettings", "ollamaModels", "image", "video", "prepareReset", "consumeReset", "speed", "setSpeed", "modelDefaults", "setModelDefault"];
25
+ export declare const SUBSCRIPTIONS_AUTH_ENDPOINTS: readonly ["providerSettings", "setProviderSettings", "status", "login", "manual", "cancel", "logout", "setDefault", "usage", "externalStatus", "externalUsage", "ollamaSettings", "ollamaSetSettings", "ollamaModels", "image", "video", "prepareReset", "consumeReset", "speed", "setSpeed", "modelDefaults", "setModelDefault"];
27
26
  /** Decoded image bytes returned by the `image` endpoint. */
28
27
  export interface ImageBytesResult {
29
28
  mediaType: string;
@@ -189,22 +188,6 @@ export interface ExternalUsageRpcController {
189
188
  status(): Promise<Record<ExternalUsageSource, ExternalUsageStatus>>;
190
189
  usage(source: ExternalUsageSource, signal: AbortSignal): Promise<ProviderUsage>;
191
190
  }
192
- /** Cursor account actions; OAuth tokens remain in the host credential service. */
193
- export interface CursorRpcController {
194
- status(): Promise<CursorAuthStatus>;
195
- login(): Promise<{
196
- authorizeUrl: string;
197
- }>;
198
- cancel(): Promise<void>;
199
- logout(): Promise<void>;
200
- usage(signal: AbortSignal): Promise<ProviderUsage>;
201
- models(force: boolean, signal: AbortSignal): Promise<{
202
- id: string;
203
- name: string;
204
- }[]>;
205
- settings(force: boolean, signal: AbortSignal): Promise<unknown>;
206
- setSettings(input: unknown): Promise<void>;
207
- }
208
191
  /** One model in the Ollama Cloud picker catalog, with its capability flags. */
209
192
  export interface OllamaModelView {
210
193
  id: string;
@@ -280,7 +263,6 @@ export interface OllamaRpcController {
280
263
  * @param modelDefaults - optional per-model default-effort state backing `modelDefaults`/`setModelDefault`.
281
264
  * @param providerSettings - optional OAuth provider/account preferences.
282
265
  * @param externalUsage - optional credential-backed quota readers.
283
- * @param cursor - optional Cursor account and model-visibility actions.
284
266
  * @param ollama - optional Ollama Cloud catalog and connection settings.
285
267
  */
286
- export declare function registerAuthRpc(ctx: Context, controller: AuthController, speed: SpeedController, modelDefaults?: ModelDefaultsController | undefined, providerSettings?: ProviderSettingsController | undefined, externalUsage?: ExternalUsageRpcController | undefined, cursor?: CursorRpcController | undefined, ollama?: OllamaRpcController | undefined): void;
268
+ export declare function registerAuthRpc(ctx: Context, controller: AuthController, speed: SpeedController, modelDefaults?: ModelDefaultsController | undefined, providerSettings?: ProviderSettingsController | undefined, externalUsage?: ExternalUsageRpcController | undefined, ollama?: OllamaRpcController | undefined): void;
package/lib/auth/rpc.js CHANGED
@@ -32,14 +32,6 @@ export const SUBSCRIPTIONS_AUTH_ENDPOINTS = [
32
32
  'usage',
33
33
  'externalStatus',
34
34
  'externalUsage',
35
- 'cursorStatus',
36
- 'cursorLogin',
37
- 'cursorCancel',
38
- 'cursorLogout',
39
- 'cursorUsage',
40
- 'cursorModels',
41
- 'cursorSettings',
42
- 'cursorSetSettings',
43
35
  'ollamaSettings',
44
36
  'ollamaSetSettings',
45
37
  'ollamaModels',
@@ -284,7 +276,7 @@ function readSessionId(payload) {
284
276
  throw new BadRequest('payload must be an object');
285
277
  return readString(payload, 'sessionId');
286
278
  }
287
- async function dispatch(controller, speed, modelDefaults, endpoint, payload, signal, providerSettings, externalUsage, cursor, ollama) {
279
+ async function dispatch(controller, speed, modelDefaults, endpoint, payload, signal, providerSettings, externalUsage, ollama) {
288
280
  switch (endpoint) {
289
281
  case 'providerSettings':
290
282
  if (!providerSettings)
@@ -361,43 +353,6 @@ async function dispatch(controller, speed, modelDefaults, endpoint, payload, sig
361
353
  }
362
354
  return ok(await externalUsage.usage(source, signal));
363
355
  }
364
- case 'cursorStatus':
365
- if (!cursor)
366
- throw new BadRequest('Cursor account is unavailable');
367
- return ok(await cursor.status());
368
- case 'cursorLogin':
369
- if (!cursor)
370
- throw new BadRequest('Cursor account is unavailable');
371
- return ok(await cursor.login());
372
- case 'cursorCancel':
373
- if (!cursor)
374
- throw new BadRequest('Cursor account is unavailable');
375
- await cursor.cancel();
376
- return ok({ ok: true });
377
- case 'cursorLogout':
378
- if (!cursor)
379
- throw new BadRequest('Cursor account is unavailable');
380
- await cursor.logout();
381
- return ok({ ok: true });
382
- case 'cursorUsage':
383
- if (!cursor)
384
- throw new BadRequest('Cursor account is unavailable');
385
- return ok(await cursor.usage(signal));
386
- case 'cursorModels':
387
- if (!cursor)
388
- throw new BadRequest('Cursor account is unavailable');
389
- return ok(await cursor.models(readForce(payload), signal));
390
- case 'cursorSettings':
391
- if (!cursor)
392
- throw new BadRequest('Cursor account is unavailable');
393
- return ok(await cursor.settings(readForce(payload), signal));
394
- case 'cursorSetSettings':
395
- if (!cursor)
396
- throw new BadRequest('Cursor account is unavailable');
397
- if (payload === null || typeof payload !== 'object')
398
- throw new BadRequest('payload must be an object');
399
- await cursor.setSettings(payload.settings);
400
- return ok({ ok: true });
401
356
  case 'ollamaSettings':
402
357
  if (!ollama)
403
358
  throw new BadRequest('Ollama settings are unavailable');
@@ -475,10 +430,9 @@ async function dispatch(controller, speed, modelDefaults, endpoint, payload, sig
475
430
  * @param modelDefaults - optional per-model default-effort state backing `modelDefaults`/`setModelDefault`.
476
431
  * @param providerSettings - optional OAuth provider/account preferences.
477
432
  * @param externalUsage - optional credential-backed quota readers.
478
- * @param cursor - optional Cursor account and model-visibility actions.
479
433
  * @param ollama - optional Ollama Cloud catalog and connection settings.
480
434
  */
481
- export function registerAuthRpc(ctx, controller, speed, modelDefaults = undefined, providerSettings = undefined, externalUsage = undefined, cursor = undefined, ollama = undefined) {
435
+ export function registerAuthRpc(ctx, controller, speed, modelDefaults = undefined, providerSettings = undefined, externalUsage = undefined, ollama = undefined) {
482
436
  // `connection` is not in this plugin's inject list (headless compositions
483
437
  // lack it), so its startup order is unconstrained: defer registration until
484
438
  // the service exists instead of probing once at apply time.
@@ -495,7 +449,7 @@ export function registerAuthRpc(ctx, controller, speed, modelDefaults = undefine
495
449
  const connection = ctx.get('connection');
496
450
  const handler = async (endpoint, payload, signal) => {
497
451
  try {
498
- return await dispatch(controller, speed, modelDefaults, endpoint, payload, signal, providerSettings, externalUsage, cursor, ollama);
452
+ return await dispatch(controller, speed, modelDefaults, endpoint, payload, signal, providerSettings, externalUsage, ollama);
499
453
  }
500
454
  catch (error) {
501
455
  return failure(error);
@@ -2,7 +2,7 @@ import type { ConnectionHandle } from '@deepseek-ai/dsh-api-remotes/client';
2
2
  import type { SubscriptionProvider } from './SubscriptionsSection.js';
3
3
  import type { SubscriptionsKey } from './locales.js';
4
4
  interface Props {
5
- provider: SubscriptionProvider | 'cursor-subscription';
5
+ provider: SubscriptionProvider;
6
6
  name: string;
7
7
  rpc: ConnectionHandle['rpc'];
8
8
  t: (key: SubscriptionsKey, params?: Record<string, unknown>) => string;
@@ -47,9 +47,7 @@ export function ProviderAccountManager({ provider, name, rpc, t, onClose, }) {
47
47
  let current = true;
48
48
  setLoading(true);
49
49
  setError('');
50
- void callSubscriptionsAuth(rpc, provider === 'cursor-subscription'
51
- ? 'cursorSettings'
52
- : 'providerSettings', { provider })
50
+ void callSubscriptionsAuth(rpc, 'providerSettings', { provider })
53
51
  .then((data) => {
54
52
  if (current) {
55
53
  setCatalog(data);
@@ -94,43 +92,32 @@ export function ProviderAccountManager({ provider, name, rpc, t, onClose, }) {
94
92
  setSaveError('');
95
93
  let savedEfforts = 0;
96
94
  try {
97
- if (provider !== 'cursor-subscription') {
98
- for (const { model, effort } of models.efforts) {
99
- await callSubscriptionsAuth(rpc, 'setModelDefault', {
100
- provider,
101
- model,
102
- ...(effort ? { effort } : {}),
103
- });
104
- savedEfforts++;
105
- if (!alive.current)
106
- return;
107
- }
95
+ for (const { model, effort } of models.efforts) {
96
+ await callSubscriptionsAuth(rpc, 'setModelDefault', {
97
+ provider,
98
+ model,
99
+ ...(effort ? { effort } : {}),
100
+ });
101
+ savedEfforts++;
102
+ if (!alive.current)
103
+ return;
108
104
  }
109
105
  // Re-read before writing: another client may have saved since this
110
106
  // dialog loaded, and a stale snapshot must never be written back.
111
- const latest = await callSubscriptionsAuth(rpc, provider === 'cursor-subscription'
112
- ? 'cursorSettings'
113
- : 'providerSettings', { provider });
107
+ const latest = await callSubscriptionsAuth(rpc, 'providerSettings', { provider });
114
108
  if (!alive.current)
115
109
  return;
116
- if (provider === 'cursor-subscription') {
117
- await callSubscriptionsAuth(rpc, 'cursorSetSettings', {
118
- settings: models.settings ?? latest.settings,
119
- });
120
- }
121
- else {
122
- const base = models.settings === undefined
123
- ? latest.settings
124
- : mergeLatestAccounts(models.settings, latest.settings);
125
- // The editor's draft carries the TTL it loaded, so the dialog always
126
- // replaces it: the picker's choice when touched, otherwise the value
127
- // from the freshly re-read settings.
128
- const withTtl = mergePromptCacheTtl(base, ttlDirty ? ttlDraft : latest.settings.promptCacheTtl);
129
- await callSubscriptionsAuth(rpc, 'setProviderSettings', {
130
- provider,
131
- settings: mergeAccountChanges(withTtl, changes),
132
- });
133
- }
110
+ const base = models.settings === undefined
111
+ ? latest.settings
112
+ : mergeLatestAccounts(models.settings, latest.settings);
113
+ // The editor's draft carries the TTL it loaded, so the dialog always
114
+ // replaces it: the picker's choice when touched, otherwise the value
115
+ // from the freshly re-read settings.
116
+ const withTtl = mergePromptCacheTtl(base, ttlDirty ? ttlDraft : latest.settings.promptCacheTtl);
117
+ await callSubscriptionsAuth(rpc, 'setProviderSettings', {
118
+ provider,
119
+ settings: mergeAccountChanges(withTtl, changes),
120
+ });
134
121
  if (alive.current)
135
122
  onClose();
136
123
  }
@@ -155,81 +142,70 @@ export function ProviderAccountManager({ provider, name, rpc, t, onClose, }) {
155
142
  maxWidth: 'calc(100vw - 32px)',
156
143
  maxHeight: 'calc(100dvh - 32px)',
157
144
  overflow: 'auto',
158
- }, children: [_jsx("style", { children: providerSettingsCss }), _jsxs("div", { style: { ...stack, padding: 20 }, children: [_jsxs("header", { style: { ...actions, justifyContent: 'space-between' }, children: [_jsx("h2", { id: title, style: { margin: 0 }, children: t('accountsTitle', { provider: name }) }), _jsx("button", { type: "button", autoFocus: true, disabled: saving, onClick: onClose, children: t('imageClose') })] }), _jsx("p", { id: description, className: "dsh-subscription-hint", children: t(provider === 'cursor-subscription'
159
- ? 'cursorAccountsHint'
160
- : 'accountsHint') }), error && _jsx("p", { role: "alert", children: error }), loading && (_jsx("p", { role: "status", className: "dsh-subscription-hint", children: t('accountsLoading') })), !loading && !catalog && (_jsx("button", { type: "button", onClick: () => setAttempt((value) => value + 1), children: t('modelDefaultsRetry') })), catalog && (_jsxs("fieldset", { disabled: saving || loading, style: { ...stack, border: 0, margin: 0, padding: 0 }, children: [catalog.accounts.length === 0 && (_jsx("p", { className: "dsh-subscription-hint", children: t(provider === 'cursor-subscription'
161
- ? 'cursorManageSignIn'
162
- : 'accountsEmpty') })), provider === 'cursor-subscription' &&
163
- catalog.accounts.length > 0 && (_jsxs("fieldset", { style: {
164
- border,
165
- borderRadius: 'var(--dsw-radius-lg, 12px)',
166
- padding: 14,
167
- }, children: [_jsx("legend", { style: { padding: '0 6px' }, children: name }), _jsx("p", { className: "dsh-subscription-hint", children: t('cursorConnected') })] })), provider !== 'cursor-subscription' &&
168
- catalog.accounts.map((account) => {
169
- const preferences = changes[account.key] ??
170
- catalog.settings.accounts?.[account.key] ??
171
- {};
172
- const selected = accountPoolSelection(preferences, account.models);
173
- const models = accountModelRows(account, preferences);
174
- return (_jsxs("fieldset", { style: {
175
- ...stack,
176
- border,
177
- borderRadius: 'var(--dsw-radius-lg, 12px)',
178
- padding: 14,
179
- margin: 0,
180
- }, children: [_jsx("legend", { style: {
181
- padding: '0 6px',
182
- overflowWrap: 'anywhere',
183
- maxWidth: '100%',
184
- }, children: account.label }), account.unavailable && (_jsx("p", { className: "dsh-subscription-hint", children: t('accountsCatalogUnavailable') })), _jsxs("label", { style: { ...stack, gap: 6 }, children: [_jsx("span", { className: "dsh-subscription-label", children: t('accountsAlias') }), _jsx("input", { value: preferences.alias ?? '', placeholder: account.label, onChange: (event) => {
185
- const next = { ...preferences };
186
- if (event.target.value.trim())
187
- next.alias = event.target.value;
188
- else
189
- delete next.alias;
190
- edit(account.key, next);
191
- } })] }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: preferences.poolEnabled !== false, onChange: (event) => edit(account.key, {
192
- ...preferences,
193
- poolEnabled: event.target.checked,
194
- }) }), ' ', t('accountsPoolEnabled')] }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: preferences.independentEntry === true, onChange: (event) => edit(account.key, {
195
- ...preferences,
196
- independentEntry: event.target.checked,
197
- }) }), ' ', t('accountsIndependent')] }), _jsx("p", { className: "dsh-subscription-hint", children: t('accountsIndependentHint') }), _jsxs("details", { children: [_jsxs("summary", { style: { cursor: 'pointer', fontSize: 13 }, children: [t('accountsModels'), " \u00B7", ' ', preferences.poolModels === undefined
198
- ? t('accountsModelsAll')
199
- : t('accountsModelsCount', {
200
- count: preferences.poolModels.length,
201
- })] }), _jsxs("div", { style: { ...stack, marginTop: 12 }, children: [_jsx("p", { className: "dsh-subscription-hint", children: t('accountsModelsHint') }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: preferences.poolModels === undefined, onChange: (event) => {
202
- const next = { ...preferences };
203
- if (event.target.checked)
204
- delete next.poolModels;
205
- else
206
- next.poolModels = account.models.map((model) => model.id);
207
- edit(account.key, next);
208
- } }), ' ', t('accountsModelsAutomatic')] }), _jsxs("div", { style: actions, children: [_jsx("button", { type: "button", onClick: () => edit(account.key, {
209
- ...preferences,
210
- poolModels: models.map((model) => model.id),
211
- }), children: t('modelsSelectAll') }), _jsx("button", { type: "button", onClick: () => edit(account.key, {
212
- ...preferences,
213
- poolModels: [],
214
- }), children: t('modelsSelectNone') })] }), _jsxs("div", { style: {
215
- ...stack,
216
- gap: 8,
217
- maxHeight: 240,
218
- overflowY: 'auto',
219
- }, children: [models.map((model) => (_jsxs("label", { style: { overflowWrap: 'anywhere' }, children: [_jsx("input", { type: "checkbox", checked: selected.has(model.id), onChange: (event) => {
220
- const next = new Set(selected);
221
- if (event.target.checked)
222
- next.add(model.id);
223
- else
224
- next.delete(model.id);
225
- edit(account.key, {
226
- ...preferences,
227
- poolModels: [...next],
228
- });
229
- } }), ' ', model.name, model.unavailable &&
230
- ` (${t('modelsUnavailable')})`] }, model.id))), models.length === 0 && (_jsx("p", { className: "dsh-subscription-hint", children: t('accountsNoModels') }))] })] })] })] }, account.key));
231
- })] })), (provider !== 'cursor-subscription' ||
232
- (catalog?.accounts.length ?? 0) > 0) && (_jsx(ProviderModelEditor, { ref: editor, provider: provider, rpc: rpc, t: t, disabled: saving, onDirtyChange: setModelsDirty })), provider === 'claude' && catalog && (_jsxs("div", { style: {
145
+ }, children: [_jsx("style", { children: providerSettingsCss }), _jsxs("div", { style: { ...stack, padding: 20 }, children: [_jsxs("header", { style: { ...actions, justifyContent: 'space-between' }, children: [_jsx("h2", { id: title, style: { margin: 0 }, children: t('accountsTitle', { provider: name }) }), _jsx("button", { type: "button", autoFocus: true, disabled: saving, onClick: onClose, children: t('imageClose') })] }), _jsx("p", { id: description, className: "dsh-subscription-hint", children: t('accountsHint') }), error && _jsx("p", { role: "alert", children: error }), loading && (_jsx("p", { role: "status", className: "dsh-subscription-hint", children: t('accountsLoading') })), !loading && !catalog && (_jsx("button", { type: "button", onClick: () => setAttempt((value) => value + 1), children: t('modelDefaultsRetry') })), catalog && (_jsxs("fieldset", { disabled: saving || loading, style: { ...stack, border: 0, margin: 0, padding: 0 }, children: [catalog.accounts.length === 0 && (_jsx("p", { className: "dsh-subscription-hint", children: t('accountsEmpty') })), catalog.accounts.map((account) => {
146
+ const preferences = changes[account.key] ??
147
+ catalog.settings.accounts?.[account.key] ??
148
+ {};
149
+ const selected = accountPoolSelection(preferences, account.models);
150
+ const models = accountModelRows(account, preferences);
151
+ return (_jsxs("fieldset", { style: {
152
+ ...stack,
153
+ border,
154
+ borderRadius: 'var(--dsw-radius-lg, 12px)',
155
+ padding: 14,
156
+ margin: 0,
157
+ }, children: [_jsx("legend", { style: {
158
+ padding: '0 6px',
159
+ overflowWrap: 'anywhere',
160
+ maxWidth: '100%',
161
+ }, children: account.label }), account.unavailable && (_jsx("p", { className: "dsh-subscription-hint", children: t('accountsCatalogUnavailable') })), _jsxs("label", { style: { ...stack, gap: 6 }, children: [_jsx("span", { className: "dsh-subscription-label", children: t('accountsAlias') }), _jsx("input", { value: preferences.alias ?? '', placeholder: account.label, onChange: (event) => {
162
+ const next = { ...preferences };
163
+ if (event.target.value.trim())
164
+ next.alias = event.target.value;
165
+ else
166
+ delete next.alias;
167
+ edit(account.key, next);
168
+ } })] }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: preferences.poolEnabled !== false, onChange: (event) => edit(account.key, {
169
+ ...preferences,
170
+ poolEnabled: event.target.checked,
171
+ }) }), ' ', t('accountsPoolEnabled')] }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: preferences.independentEntry === true, onChange: (event) => edit(account.key, {
172
+ ...preferences,
173
+ independentEntry: event.target.checked,
174
+ }) }), ' ', t('accountsIndependent')] }), _jsx("p", { className: "dsh-subscription-hint", children: t('accountsIndependentHint') }), _jsxs("details", { children: [_jsxs("summary", { style: { cursor: 'pointer', fontSize: 13 }, children: [t('accountsModels'), " \u00B7", ' ', preferences.poolModels === undefined
175
+ ? t('accountsModelsAll')
176
+ : t('accountsModelsCount', {
177
+ count: preferences.poolModels.length,
178
+ })] }), _jsxs("div", { style: { ...stack, marginTop: 12 }, children: [_jsx("p", { className: "dsh-subscription-hint", children: t('accountsModelsHint') }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: preferences.poolModels === undefined, onChange: (event) => {
179
+ const next = { ...preferences };
180
+ if (event.target.checked)
181
+ delete next.poolModels;
182
+ else
183
+ next.poolModels = account.models.map((model) => model.id);
184
+ edit(account.key, next);
185
+ } }), ' ', t('accountsModelsAutomatic')] }), _jsxs("div", { style: actions, children: [_jsx("button", { type: "button", onClick: () => edit(account.key, {
186
+ ...preferences,
187
+ poolModels: models.map((model) => model.id),
188
+ }), children: t('modelsSelectAll') }), _jsx("button", { type: "button", onClick: () => edit(account.key, {
189
+ ...preferences,
190
+ poolModels: [],
191
+ }), children: t('modelsSelectNone') })] }), _jsxs("div", { style: {
192
+ ...stack,
193
+ gap: 8,
194
+ maxHeight: 240,
195
+ overflowY: 'auto',
196
+ }, children: [models.map((model) => (_jsxs("label", { style: { overflowWrap: 'anywhere' }, children: [_jsx("input", { type: "checkbox", checked: selected.has(model.id), onChange: (event) => {
197
+ const next = new Set(selected);
198
+ if (event.target.checked)
199
+ next.add(model.id);
200
+ else
201
+ next.delete(model.id);
202
+ edit(account.key, {
203
+ ...preferences,
204
+ poolModels: [...next],
205
+ });
206
+ } }), ' ', model.name, model.unavailable &&
207
+ ` (${t('modelsUnavailable')})`] }, model.id))), models.length === 0 && (_jsx("p", { className: "dsh-subscription-hint", children: t('accountsNoModels') }))] })] })] })] }, account.key));
208
+ })] })), _jsx(ProviderModelEditor, { ref: editor, provider: provider, rpc: rpc, t: t, disabled: saving, onDirtyChange: setModelsDirty }), provider === 'claude' && catalog && (_jsxs("div", { style: {
233
209
  ...stack,
234
210
  gap: 6,
235
211
  borderTop: border,
@@ -3,7 +3,7 @@ import type { ProviderPreferences } from '../provider-settings.js';
3
3
  import type { SubscriptionProvider } from './SubscriptionsSection.js';
4
4
  import type { SubscriptionsKey } from './locales.js';
5
5
  interface Props {
6
- provider: SubscriptionProvider | 'cursor-subscription';
6
+ provider: SubscriptionProvider;
7
7
  rpc: ConnectionHandle['rpc'];
8
8
  t: (key: SubscriptionsKey, params?: Record<string, unknown>) => string;
9
9
  /** Freeze the editor while the owning dialog submits. */
@@ -48,9 +48,7 @@ export const ProviderModelEditor = forwardRef(function ProviderModelEditor({ pro
48
48
  setBusy(true);
49
49
  setError('');
50
50
  try {
51
- const data = await callSubscriptionsAuth(rpc, provider === 'cursor-subscription'
52
- ? 'cursorSettings'
53
- : 'providerSettings', { provider, force });
51
+ const data = await callSubscriptionsAuth(rpc, 'providerSettings', { provider, force });
54
52
  if (generation.current === request)
55
53
  reset(data);
56
54
  }
@@ -124,9 +122,7 @@ export const ProviderModelEditor = forwardRef(function ProviderModelEditor({ pro
124
122
  });
125
123
  const selected = new Set(draft.visibleModels ??
126
124
  [...allModels, ...missing].map((model) => model.id));
127
- return (_jsxs("div", { style: { borderTop: border, marginTop: 12, paddingTop: 12 }, children: [_jsx("h3", { style: { margin: 0 }, children: t('modelsEdit') }), _jsxs("div", { style: { display: 'grid', gap: 12, marginTop: 12 }, children: [_jsx("p", { className: "dsh-subscription-hint", children: t(provider === 'cursor-subscription'
128
- ? 'cursorManageHint'
129
- : 'modelsHint') }), error && _jsx("p", { role: "alert", children: error }), _jsxs("div", { style: actions, children: [_jsx("button", { type: "button", className: "dsh-subscription-quiet", disabled: busy || disabled || dirty, onClick: () => {
125
+ return (_jsxs("div", { style: { borderTop: border, marginTop: 12, paddingTop: 12 }, children: [_jsx("h3", { style: { margin: 0 }, children: t('modelsEdit') }), _jsxs("div", { style: { display: 'grid', gap: 12, marginTop: 12 }, children: [_jsx("p", { className: "dsh-subscription-hint", children: t('modelsHint') }), error && _jsx("p", { role: "alert", children: error }), _jsxs("div", { style: actions, children: [_jsx("button", { type: "button", className: "dsh-subscription-quiet", disabled: busy || disabled || dirty, onClick: () => {
130
126
  void load(true);
131
127
  }, children: t('usageRefresh') }), busy && _jsx("span", { role: "status", children: t('modelDefaultsLoading') })] }), !busy && catalog && (_jsxs("fieldset", { disabled: busy || disabled, style: {
132
128
  border: 0,
@@ -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' | 'ollama-cloud';
51
+ export type BadgeProvider = SubscriptionProvider | 'opencode-go' | 'kimi-coding' | 'minimax' | 'minimax-cn' | 'ollama-cloud';
52
52
  export interface UsageRosterEntry {
53
53
  provider: BadgeProvider;
54
54
  account: AccountStatus;
@@ -60,7 +60,6 @@ const PROVIDER_NAMES = {
60
60
  grok: 'Grok',
61
61
  copilot: 'Copilot',
62
62
  antigravity: 'Antigravity',
63
- 'cursor-subscription': 'Cursor',
64
63
  'opencode-go': 'OpenCode Go',
65
64
  'kimi-coding': 'Kimi Code',
66
65
  minimax: 'MiniMax',
@@ -110,9 +109,8 @@ export function groupUsageDisplays(roster, windowsOf, plans) {
110
109
  }
111
110
  /** Read each account source independently so a failing endpoint cannot hide the others. */
112
111
  export async function loadBadgeRoster(rpc) {
113
- const [subscriptions, cursor, external] = await Promise.allSettled([
112
+ const [subscriptions, external] = await Promise.allSettled([
114
113
  callSubscriptionsAuth(rpc, 'status', {}),
115
- callSubscriptionsAuth(rpc, 'cursorStatus', {}),
116
114
  callSubscriptionsAuth(rpc, 'externalStatus', {}),
117
115
  ]);
118
116
  const roster = [];
@@ -130,14 +128,6 @@ export async function loadBadgeRoster(rpc) {
130
128
  roster.push({ provider, account });
131
129
  }
132
130
  }
133
- if (cursor.status === 'fulfilled') {
134
- refreshed.add('cursor-subscription');
135
- if (cursor.value.authenticated)
136
- roster.push({
137
- provider: 'cursor-subscription',
138
- account: { key: 'cursor', isDefault: true },
139
- });
140
- }
141
131
  if (external.status === 'fulfilled') {
142
132
  for (const [source, provider] of [
143
133
  ['opencode-go', 'opencode-go'],
@@ -157,8 +147,6 @@ export async function loadBadgeRoster(rpc) {
157
147
  return { roster, refreshed };
158
148
  }
159
149
  export async function usageOf(rpc, { provider, account }) {
160
- if (provider === 'cursor-subscription')
161
- return callSubscriptionsAuth(rpc, 'cursorUsage', {});
162
150
  if (provider === 'opencode-go' ||
163
151
  provider === 'kimi-coding' ||
164
152
  provider === 'minimax' ||
@@ -19,7 +19,6 @@ import { visibleUsageWindows } from './usage-window-filter.js';
19
19
  import { ProviderAccountManager } from './ProviderAccountManager.js';
20
20
  import { providerSettingsCss } from './provider-settings-styles.js';
21
21
  import { ExternalUsageCards } from './ExternalUsageCards.js';
22
- import { CursorCard } from './CursorCard.js';
23
22
  import { OllamaCard } from './OllamaCard.js';
24
23
  import { UsageMeter } from './UsageMeter.js';
25
24
  import { ResetCreditsDisclosure, ResetCreditsErrorLine, showsResetCredits, } from './reset-credits-view.js';
@@ -720,7 +719,7 @@ export function SubscriptionsSection(props) {
720
719
  })) }), _jsx("button", { type: "button", onClick: () => {
721
720
  void submitManual(id);
722
721
  }, children: t('submit') })] })] }))] }, id));
723
- }), _jsx(CursorCard, { rpc: rpc, t: t }), _jsx(OllamaCard, { rpc: rpc, t: t }), _jsx(ExternalUsageCards, { rpc: rpc, t: t }), managedProvider && (_jsx(ProviderAccountManager, { provider: managedProvider.id, name: managedProvider.name, rpc: rpc, t: t, onClose: () => {
722
+ }), _jsx(OllamaCard, { rpc: rpc, t: t }), _jsx(ExternalUsageCards, { rpc: rpc, t: t }), managedProvider && (_jsx(ProviderAccountManager, { provider: managedProvider.id, name: managedProvider.name, rpc: rpc, t: t, onClose: () => {
724
723
  setManagedProvider(undefined);
725
724
  void refresh();
726
725
  } })), _jsx("style", { children: '.subscriptions-reset-dialog::backdrop { background: var(--dsw-alias-bg-mask-1, #0006); backdrop-filter: var(--dsw-mask-blur, none); }' }), _jsx("dialog", { ref: resetDialogRef, className: "subscriptions-reset-dialog", "aria-labelledby": "subscriptions-reset-title", onCancel: () => setResetConfirmation(undefined), onClose: () => setResetConfirmation(undefined), style: {
@@ -148,22 +148,6 @@ export declare const en: {
148
148
  externalUsageApiKey: string;
149
149
  externalUsageConfigure: string;
150
150
  externalUsageUnavailable: string;
151
- cursorTitle: string;
152
- cursorOpenLogin: string;
153
- cursorWaiting: string;
154
- cursorConnected: string;
155
- cursorManageTitle: string;
156
- cursorManageSignIn: string;
157
- cursorAccountsHint: string;
158
- cursorManageHint: string;
159
- cursorFilterModels: string;
160
- cursorModelsLoading: string;
161
- cursorModelsError: string;
162
- cursorModelsCount: string;
163
- cursorIncluded: string;
164
- cursorModels: string;
165
- cursorOtherModels: string;
166
- cursorIncludedRequests: string;
167
151
  modelDefaultsTitle: string;
168
152
  modelDefaultsHint: string;
169
153
  modelDefaultsFollowProvider: string;
@@ -394,22 +378,6 @@ export declare const zh: {
394
378
  externalUsageApiKey: string;
395
379
  externalUsageConfigure: string;
396
380
  externalUsageUnavailable: string;
397
- cursorTitle: string;
398
- cursorOpenLogin: string;
399
- cursorWaiting: string;
400
- cursorConnected: string;
401
- cursorManageTitle: string;
402
- cursorManageSignIn: string;
403
- cursorAccountsHint: string;
404
- cursorManageHint: string;
405
- cursorFilterModels: string;
406
- cursorModelsLoading: string;
407
- cursorModelsError: string;
408
- cursorModelsCount: string;
409
- cursorIncluded: string;
410
- cursorModels: string;
411
- cursorOtherModels: string;
412
- cursorIncludedRequests: string;
413
381
  modelDefaultsTitle: string;
414
382
  modelDefaultsHint: string;
415
383
  modelDefaultsFollowProvider: string;