dsh-subscriptions 0.2.3 → 0.3.1
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 +9 -21
- package/lib/auth/rpc.d.ts +2 -20
- package/lib/auth/rpc.js +3 -49
- package/lib/client/ProviderAccountManager.d.ts +1 -1
- package/lib/client/ProviderAccountManager.js +86 -110
- package/lib/client/ProviderModelEditor.d.ts +1 -1
- package/lib/client/ProviderModelEditor.js +2 -6
- package/lib/client/SubscriptionUsageBadge.d.ts +8 -2
- package/lib/client/SubscriptionUsageBadge.js +24 -17
- package/lib/client/SubscriptionsSection.js +1 -2
- package/lib/client/locales.d.ts +2 -32
- package/lib/client/locales.js +2 -32
- package/lib/client/model-filter.js +1 -1
- package/lib/client/subscription-card-styles.d.ts +1 -1
- package/lib/client/subscription-card-styles.js +1 -1
- package/lib/client.js +234 -518
- package/lib/client.js.map +1 -1
- package/lib/index.js +208 -3305
- package/lib/providers/claude.d.ts +3 -1
- package/lib/providers/claude.js +2 -2
- package/lib/providers/ollama-settings.d.ts +1 -1
- package/lib/providers/ollama-settings.js +1 -1
- package/lib/providers/pool-usage.d.ts +10 -9
- package/lib/providers/pool-usage.js +30 -19
- package/lib/providers/pool.d.ts +6 -6
- package/lib/providers/pool.js +24 -12
- package/package.json +1 -7
- package/lib/client/CursorCard.d.ts +0 -9
- package/lib/client/CursorCard.js +0 -151
- package/lib/providers/cursor-adapter.d.ts +0 -50
- package/lib/providers/cursor-adapter.js +0 -304
- package/lib/providers/cursor-auth.d.ts +0 -43
- package/lib/providers/cursor-auth.js +0 -221
- package/lib/providers/cursor-model-settings.d.ts +0 -15
- package/lib/providers/cursor-model-settings.js +0 -60
- package/lib/providers/cursor-usage.d.ts +0 -9
- package/lib/providers/cursor-usage.js +0 -131
- package/vendor/cursor/LICENSE +0 -21
- package/vendor/cursor/index.d.ts +0 -18
- package/vendor/cursor/index.js +0 -3574
- package/vendor/cursor/proto.js +0 -254
|
@@ -35,6 +35,7 @@ import { en } from './locales.js';
|
|
|
35
35
|
import { hostIcon } from './host-icons.js';
|
|
36
36
|
import { HOST_CONTRACT, markerSelector } from './host-contract.js';
|
|
37
37
|
import { USAGE_BADGE_REFRESH_EVENT, useUsageBadgeMode, } from './usage-badge-preferences.js';
|
|
38
|
+
import { visibleUsageWindows } from './usage-window-filter.js';
|
|
38
39
|
/** DSH renamed the data icon in 0.1.7; retain older supported hosts too. */
|
|
39
40
|
export function usageBadgeIcon(icons) {
|
|
40
41
|
return hostIcon(icons, 'DataOutline');
|
|
@@ -60,7 +61,6 @@ const PROVIDER_NAMES = {
|
|
|
60
61
|
grok: 'Grok',
|
|
61
62
|
copilot: 'Copilot',
|
|
62
63
|
antigravity: 'Antigravity',
|
|
63
|
-
'cursor-subscription': 'Cursor',
|
|
64
64
|
'opencode-go': 'OpenCode Go',
|
|
65
65
|
'kimi-coding': 'Kimi Code',
|
|
66
66
|
minimax: 'MiniMax',
|
|
@@ -110,13 +110,13 @@ export function groupUsageDisplays(roster, windowsOf, plans) {
|
|
|
110
110
|
}
|
|
111
111
|
/** Read each account source independently so a failing endpoint cannot hide the others. */
|
|
112
112
|
export async function loadBadgeRoster(rpc) {
|
|
113
|
-
const [subscriptions,
|
|
113
|
+
const [subscriptions, external] = await Promise.allSettled([
|
|
114
114
|
callSubscriptionsAuth(rpc, 'status', {}),
|
|
115
|
-
callSubscriptionsAuth(rpc, 'cursorStatus', {}),
|
|
116
115
|
callSubscriptionsAuth(rpc, 'externalStatus', {}),
|
|
117
116
|
]);
|
|
118
117
|
const roster = [];
|
|
119
118
|
const refreshed = new Set();
|
|
119
|
+
const visibleModels = new Map();
|
|
120
120
|
if (subscriptions.status === 'fulfilled') {
|
|
121
121
|
for (const provider of [
|
|
122
122
|
'codex',
|
|
@@ -126,18 +126,13 @@ export async function loadBadgeRoster(rpc) {
|
|
|
126
126
|
'antigravity',
|
|
127
127
|
]) {
|
|
128
128
|
refreshed.add(provider);
|
|
129
|
+
const visible = subscriptions.value.providers[provider]?.visibleModels;
|
|
130
|
+
if (visible !== undefined)
|
|
131
|
+
visibleModels.set(provider, visible);
|
|
129
132
|
for (const account of accountsOf(subscriptions.value.providers[provider]))
|
|
130
133
|
roster.push({ provider, account });
|
|
131
134
|
}
|
|
132
135
|
}
|
|
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
136
|
if (external.status === 'fulfilled') {
|
|
142
137
|
for (const [source, provider] of [
|
|
143
138
|
['opencode-go', 'opencode-go'],
|
|
@@ -154,11 +149,9 @@ export async function loadBadgeRoster(rpc) {
|
|
|
154
149
|
});
|
|
155
150
|
}
|
|
156
151
|
}
|
|
157
|
-
return { roster, refreshed };
|
|
152
|
+
return { roster, refreshed, visibleModels };
|
|
158
153
|
}
|
|
159
154
|
export async function usageOf(rpc, { provider, account }) {
|
|
160
|
-
if (provider === 'cursor-subscription')
|
|
161
|
-
return callSubscriptionsAuth(rpc, 'cursorUsage', {});
|
|
162
155
|
if (provider === 'opencode-go' ||
|
|
163
156
|
provider === 'kimi-coding' ||
|
|
164
157
|
provider === 'minimax' ||
|
|
@@ -382,7 +375,7 @@ export function SubscriptionUsageBadge({ rpc, currentModel, t, rotationMs, }) {
|
|
|
382
375
|
return;
|
|
383
376
|
inflightRef.current = true;
|
|
384
377
|
try {
|
|
385
|
-
const { roster, refreshed } = await loadBadgeRoster(rpc);
|
|
378
|
+
const { roster, refreshed, visibleModels } = await loadBadgeRoster(rpc);
|
|
386
379
|
if (!mountedRef.current)
|
|
387
380
|
return;
|
|
388
381
|
const lastKnown = lastKnownRef.current;
|
|
@@ -433,6 +426,9 @@ export function SubscriptionUsageBadge({ rpc, currentModel, t, rotationMs, }) {
|
|
|
433
426
|
...display,
|
|
434
427
|
accounts: display.accounts.map((account) => ({
|
|
435
428
|
...account,
|
|
429
|
+
// Filter only the display row, not lastKnown: restoring visibility
|
|
430
|
+
// must work even when the next usage request fails and uses cache.
|
|
431
|
+
windows: visibleUsageWindows(display.provider, account.windows, visibleModels.get(display.provider)),
|
|
436
432
|
...observationsRef.current.get(`${display.provider}:${account.key}`),
|
|
437
433
|
})),
|
|
438
434
|
})),
|
|
@@ -624,7 +620,7 @@ export function SubscriptionUsageBadge({ rpc, currentModel, t, rotationMs, }) {
|
|
|
624
620
|
}, onMouseLeave: () => {
|
|
625
621
|
setHover(false);
|
|
626
622
|
}, onClick: toggle, children: [_jsx(UsageBadgeIcon, {}), _jsx("span", { style: styles.label, children: label })] }), open &&
|
|
627
|
-
createPortal(_jsxs("div", { ref: panelRef, role: "dialog", "aria-label": title, className: "dsh-subscription-usage-panel", style: { ...styles.panel, ...(pos ?? MEASURE_STYLE) }, children: [_jsx("div", { style: styles.title, children: _jsxs("span", { style: styles.titleLabel, children: [_jsx(UsageBadgeIcon, {}), title] }) }), _jsx("div", { style: styles.titleRule, "aria-hidden": true }), expanded.map((d, index) => (_jsxs("section", { style: index === 0 ? undefined : styles.section, children: [_jsxs("div", { style: styles.providerRow, children: [_jsxs("span", { style: styles.providerName, children: [d.name, d.provider === current && (_jsx("span", { style: styles.currentTag, children: translate('usageBadgeCurrent') }))] }), d.accounts.length === 1 && (_jsx(AccountMeta, { account: d.accounts[0], translate: translate }))] }), d.accounts.map((account, accountIndex) => (_jsxs("div", { style: accountIndex === 0 ? undefined : styles.accountBlock, children: [d.accounts.length > 1 && (_jsx("div", { style: styles.accountRow, children: _jsx(AccountMeta, { account: account, translate: translate }) })), _jsx(AccountWindows, { windows: account.windows, observedAt: account.observedAt, stale: account.stale, model: d.provider === dialogProvider ? dialogModel : undefined, provider: d.provider, translate: translate }, `${d.provider}:${dialogModel ?? ''}`)] }, account.key)))] }, d.provider)))] }), document.body)] }));
|
|
623
|
+
createPortal(_jsxs("div", { ref: panelRef, role: "dialog", "aria-label": title, className: "dsh-subscription-usage-panel", style: { ...styles.panel, ...(pos ?? MEASURE_STYLE) }, children: [_jsx("div", { style: styles.title, children: _jsxs("span", { style: styles.titleLabel, children: [_jsx(UsageBadgeIcon, {}), title] }) }), _jsx("div", { style: styles.titleRule, "aria-hidden": true }), expanded.map((d, index) => (_jsxs("section", { style: index === 0 ? undefined : styles.section, children: [_jsxs("div", { style: styles.providerRow, children: [_jsxs("span", { style: styles.providerName, children: [d.name, d.provider === current && (_jsx("span", { style: styles.currentTag, children: translate('usageBadgeCurrent') }))] }), d.accounts.length === 1 && (_jsx(AccountMeta, { account: d.accounts[0], translate: translate }))] }), _jsx(CodexExhaustionNotice, { display: d, translate: translate }), d.accounts.map((account, accountIndex) => (_jsxs("div", { style: accountIndex === 0 ? undefined : styles.accountBlock, children: [d.accounts.length > 1 && (_jsx("div", { style: styles.accountRow, children: _jsx(AccountMeta, { account: account, translate: translate }) })), _jsx(AccountWindows, { windows: account.windows, observedAt: account.observedAt, stale: account.stale, model: d.provider === dialogProvider ? dialogModel : undefined, provider: d.provider, translate: translate }, `${d.provider}:${dialogModel ?? ''}`)] }, account.key)))] }, d.provider)))] }), document.body)] }));
|
|
628
624
|
return (_jsxs(_Fragment, { children: [seat, statsRow !== null && statsRow.isConnected
|
|
629
625
|
? createPortal(pill, statsRow)
|
|
630
626
|
: pill] }));
|
|
@@ -647,6 +643,15 @@ function statsScopeOf(seat) {
|
|
|
647
643
|
}
|
|
648
644
|
return seat.parentElement;
|
|
649
645
|
}
|
|
646
|
+
/** Warn only when every displayed Codex account has a known exhausted window. */
|
|
647
|
+
export function CodexExhaustionNotice({ display, translate, }) {
|
|
648
|
+
if (display.provider !== 'codex' ||
|
|
649
|
+
display.accounts.length === 0 ||
|
|
650
|
+
display.accounts.some((account) => account.windows.length === 0 ||
|
|
651
|
+
!account.windows.some((window) => window.usedPercent >= 100)))
|
|
652
|
+
return null;
|
|
653
|
+
return (_jsx("p", { role: "status", style: { ...styles.providerMeta, margin: '8px 0 0' }, children: translate('usageBadgeAllCodexExhausted') }));
|
|
654
|
+
}
|
|
650
655
|
/**
|
|
651
656
|
* One account's handle and plan: `★ ys@example.com · 计划:pro`. The star
|
|
652
657
|
* marks the default account (the one direct routes serve and the collapsed
|
|
@@ -661,8 +666,10 @@ function AccountMeta({ account, translate, }) {
|
|
|
661
666
|
].filter((part) => part !== undefined && part !== '');
|
|
662
667
|
return (_jsxs("span", { style: styles.providerMeta, title: account.account, children: [account.isDefault && (_jsxs("span", { style: styles.defaultStar, "aria-label": "default", children: ["\u2605", ' '] })), parts.join(' · ')] }));
|
|
663
668
|
}
|
|
664
|
-
/** Preview each account independently;
|
|
669
|
+
/** Preview each account independently; remaining visible quotas stay accessible. */
|
|
665
670
|
export function AccountWindows({ windows, model, provider, translate, observedAt, stale, }) {
|
|
671
|
+
if (windows.length === 0)
|
|
672
|
+
return (_jsx("p", { style: styles.providerMeta, children: translate('usageNoVisibleModels') }));
|
|
666
673
|
const { shown, hidden } = previewWindows(windows, model, provider);
|
|
667
674
|
const rows = (items) => (_jsx("dl", { style: styles.details, children: items.map((w, i) => (_jsx(WindowRow, { label: `${usageWindowLabel(translate, w)}${model !== undefined && w.scope === model ? ` · ${translate('usageBadgeCurrent')}` : ''}`, window: w, t: translate, observedAt: observedAt, stale: stale }, i))) }));
|
|
668
675
|
return (_jsxs(_Fragment, { children: [rows(shown), hidden.length > 0 && (_jsxs("details", { style: styles.moreWindows, children: [_jsx("summary", { style: styles.moreSummary, children: translate('usageBadgeMoreWindows', { count: hidden.length }) }), rows(hidden)] }))] }));
|
|
@@ -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(
|
|
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: {
|
package/lib/client/locales.d.ts
CHANGED
|
@@ -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;
|
|
@@ -204,6 +188,7 @@ export declare const en: {
|
|
|
204
188
|
usageBadgeModelCount: string;
|
|
205
189
|
usageBadgeModelUnavailable: string;
|
|
206
190
|
usageBadgeMoreWindows: string;
|
|
191
|
+
usageBadgeAllCodexExhausted: string;
|
|
207
192
|
speed: string;
|
|
208
193
|
speedStandard: string;
|
|
209
194
|
speedStandardDescription: string;
|
|
@@ -394,22 +379,6 @@ export declare const zh: {
|
|
|
394
379
|
externalUsageApiKey: string;
|
|
395
380
|
externalUsageConfigure: string;
|
|
396
381
|
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
382
|
modelDefaultsTitle: string;
|
|
414
383
|
modelDefaultsHint: string;
|
|
415
384
|
modelDefaultsFollowProvider: string;
|
|
@@ -450,6 +419,7 @@ export declare const zh: {
|
|
|
450
419
|
usageBadgeModelCount: string;
|
|
451
420
|
usageBadgeModelUnavailable: string;
|
|
452
421
|
usageBadgeMoreWindows: string;
|
|
422
|
+
usageBadgeAllCodexExhausted: string;
|
|
453
423
|
speed: string;
|
|
454
424
|
speedStandard: string;
|
|
455
425
|
speedStandardDescription: string;
|
package/lib/client/locales.js
CHANGED
|
@@ -148,22 +148,6 @@ export const en = {
|
|
|
148
148
|
externalUsageApiKey: 'API key',
|
|
149
149
|
externalUsageConfigure: 'No API key found at {ref}. Add one in Settings → Models.',
|
|
150
150
|
externalUsageUnavailable: 'Usage status unavailable: {message}',
|
|
151
|
-
cursorTitle: 'Cursor',
|
|
152
|
-
cursorOpenLogin: 'Open Cursor sign-in',
|
|
153
|
-
cursorWaiting: 'Waiting for Cursor sign-in…',
|
|
154
|
-
cursorConnected: 'Connected',
|
|
155
|
-
cursorManageTitle: 'Manage Cursor',
|
|
156
|
-
cursorManageSignIn: 'Sign in to see the models available to this Cursor account.',
|
|
157
|
-
cursorAccountsHint: 'Cursor uses one connected account. Choose which of its models appear in the model picker.',
|
|
158
|
-
cursorManageHint: 'Choose model visibility here. Refresh fetches the current models from Cursor; Save changes updates the model picker.',
|
|
159
|
-
cursorFilterModels: 'Filter models',
|
|
160
|
-
cursorModelsLoading: 'Loading Cursor models…',
|
|
161
|
-
cursorModelsError: 'Could not load Cursor models: {message}',
|
|
162
|
-
cursorModelsCount: '{count} models available',
|
|
163
|
-
cursorIncluded: 'Included usage',
|
|
164
|
-
cursorModels: 'Cursor Models',
|
|
165
|
-
cursorOtherModels: 'Other Models',
|
|
166
|
-
cursorIncludedRequests: 'Included requests',
|
|
167
151
|
modelDefaultsTitle: 'Default reasoning effort',
|
|
168
152
|
modelDefaultsHint: 'The model picker preselects this level when you switch to the model; models without levels always follow the provider.',
|
|
169
153
|
modelDefaultsFollowProvider: 'Follow provider',
|
|
@@ -204,6 +188,7 @@ export const en = {
|
|
|
204
188
|
usageBadgeModelCount: '{count} model quotas',
|
|
205
189
|
usageBadgeModelUnavailable: 'Current model quota unavailable',
|
|
206
190
|
usageBadgeMoreWindows: 'More quota windows ({count})',
|
|
191
|
+
usageBadgeAllCodexExhausted: 'All displayed Codex accounts report exhausted subscription quota. New requests stop before spending paid credits. After an external reset, use Settings > Subscriptions > Refresh to re-check usage.',
|
|
207
192
|
speed: 'Speed',
|
|
208
193
|
speedStandard: 'Standard',
|
|
209
194
|
speedStandardDescription: 'Default speed',
|
|
@@ -402,22 +387,6 @@ export const zh = {
|
|
|
402
387
|
externalUsageApiKey: 'API 密钥',
|
|
403
388
|
externalUsageConfigure: '未在 {ref} 找到 API 密钥。请在「设置 → 模型」中添加。',
|
|
404
389
|
externalUsageUnavailable: '无法获取用量状态:{message}',
|
|
405
|
-
cursorTitle: 'Cursor',
|
|
406
|
-
cursorOpenLogin: '打开 Cursor 登录页面',
|
|
407
|
-
cursorWaiting: '等待 Cursor 登录…',
|
|
408
|
-
cursorConnected: '已连接',
|
|
409
|
-
cursorManageTitle: '管理 Cursor',
|
|
410
|
-
cursorManageSignIn: '登录后可查看此 Cursor 账号可用的模型。',
|
|
411
|
-
cursorAccountsHint: 'Cursor 使用一个已连接账号。可在此选择模型选择器中显示的模型。',
|
|
412
|
-
cursorManageHint: '在此选择模型是否显示。刷新可从 Cursor 获取当前模型;保存更改后更新模型选择器。',
|
|
413
|
-
cursorFilterModels: '筛选模型',
|
|
414
|
-
cursorModelsLoading: '正在加载 Cursor 模型…',
|
|
415
|
-
cursorModelsError: '无法加载 Cursor 模型:{message}',
|
|
416
|
-
cursorModelsCount: '可用模型:{count} 个',
|
|
417
|
-
cursorIncluded: '套餐内用量',
|
|
418
|
-
cursorModels: 'Cursor 模型',
|
|
419
|
-
cursorOtherModels: '其他模型',
|
|
420
|
-
cursorIncludedRequests: '套餐内请求',
|
|
421
390
|
modelDefaultsTitle: '默认推理档',
|
|
422
391
|
modelDefaultsHint: '切换到该模型时,模型选择器会预选此档位;没有推理档的模型始终跟随服务商默认。',
|
|
423
392
|
modelDefaultsFollowProvider: '跟随服务商',
|
|
@@ -458,6 +427,7 @@ export const zh = {
|
|
|
458
427
|
usageBadgeModelCount: '{count} 个模型配额',
|
|
459
428
|
usageBadgeModelUnavailable: '当前模型暂无配额数据',
|
|
460
429
|
usageBadgeMoreWindows: '更多配额窗口({count})',
|
|
430
|
+
usageBadgeAllCodexExhausted: '当前显示的所有 Codex 账号都报告订阅额度已耗尽。新请求会在消耗付费额度前停止;外部额度重置后,请使用“设置 > 订阅 > 刷新”重新检查用量。',
|
|
461
431
|
speed: '速度',
|
|
462
432
|
speedStandard: '标准',
|
|
463
433
|
speedStandardDescription: '默认速度',
|
|
@@ -21,7 +21,7 @@ export function savedModelIds(visibleModels, subagentSpeeds) {
|
|
|
21
21
|
* accounts with failed discovery need a retry, not another login prompt.
|
|
22
22
|
*/
|
|
23
23
|
export function modelEditorNotice(accounts) {
|
|
24
|
-
//
|
|
24
|
+
// Missing account evidence uses the neutral empty-catalog copy.
|
|
25
25
|
if (accounts === undefined)
|
|
26
26
|
return 'noModels';
|
|
27
27
|
if (accounts.length === 0)
|