dsh-codex-subscription 1.2.2 → 1.4.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.
- package/AGENTS.md +5 -5
- package/README.md +99 -90
- package/README.zh-CN.md +220 -0
- package/docs/assets/composer-quota-en.png +0 -0
- package/docs/assets/settings-en.png +0 -0
- package/docs/assets/settings-focus-en.png +0 -0
- package/docs/assets/settings-focus.png +0 -0
- package/docs/assets/settings.png +0 -0
- package/lib/client.js +269 -31
- package/lib/index.js +262 -29
- package/package.json +5 -3
- package/README.en.md +0 -210
package/lib/client.js
CHANGED
|
@@ -50,7 +50,9 @@ window.__ModuleLoader__.load({
|
|
|
50
50
|
//#endregion
|
|
51
51
|
//#region src/settings-contract.js
|
|
52
52
|
const SETTINGS_NAMESPACE = "codex-subscription";
|
|
53
|
-
const
|
|
53
|
+
const QUICK_QUOTA_MODE_FIELD = "quickQuotaMode";
|
|
54
|
+
const LEGACY_QUICK_QUOTA_FIELD = "quickQuotaVisible";
|
|
55
|
+
const QUICK_QUOTA_MODE_PERCENT = "percent";
|
|
54
56
|
const SEARCH_PROVIDER_FIELD = "searchProvider";
|
|
55
57
|
const SEARCH_PROVIDER_CODEX = "codex";
|
|
56
58
|
const SPEED_MODE_FIELD = "speedMode";
|
|
@@ -59,6 +61,11 @@ window.__ModuleLoader__.load({
|
|
|
59
61
|
const DEFAULT_SPEED_MODE = SPEED_MODE_STANDARD;
|
|
60
62
|
const normalizeSearchProvider = (value) => ["dsh", "codex"].includes(value) ? value : "dsh";
|
|
61
63
|
const normalizeSpeedMode = (value) => ["standard", "fast"].includes(value) ? value : DEFAULT_SPEED_MODE;
|
|
64
|
+
const normalizeQuickQuotaMode = (value, legacyVisible = false) => [
|
|
65
|
+
"off",
|
|
66
|
+
"percent",
|
|
67
|
+
"bar"
|
|
68
|
+
].includes(value) ? value : legacyVisible === true ? QUICK_QUOTA_MODE_PERCENT : "off";
|
|
62
69
|
const supportsCodexFastMode = (modelId) => typeof modelId === "string" && (/^gpt-5\.(?:5|6)(?:$|-)/u.test(modelId) || modelId === "gpt-5.4");
|
|
63
70
|
//#endregion
|
|
64
71
|
//#region src/sidebar-quota.js
|
|
@@ -176,12 +183,36 @@ window.__ModuleLoader__.load({
|
|
|
176
183
|
monthlyCreditLimit: "Credits 月度消费上限",
|
|
177
184
|
resetCredits: "可用额度重置次数",
|
|
178
185
|
resetCreditsValue: "{count} 次",
|
|
186
|
+
resetUse: "使用一次重置",
|
|
187
|
+
resetUnavailable: "仅当至少一个 Codex 模型额度已用尽时可使用。",
|
|
188
|
+
resetPreparing: "正在读取重置详情…",
|
|
189
|
+
resetConfirmTitle: "确认使用额度重置",
|
|
190
|
+
resetWarning: "此操作会立即消耗 1 次额度重置,且无法撤销。请确认你确实需要恢复已用尽的模型额度。",
|
|
191
|
+
resetAcknowledge: "我知道这会消耗 1 次额度重置",
|
|
192
|
+
resetTypeHint: "输入 {phrase} 以继续",
|
|
193
|
+
resetWait: "请再等待 {count} 秒",
|
|
194
|
+
resetFinal: "消耗 1 次并重置额度",
|
|
195
|
+
resetUsing: "正在重置…",
|
|
196
|
+
resetSuccess: "额度重置已完成。",
|
|
197
|
+
resetNothing: "当前没有可重置的额度,未消耗新的重置次数。",
|
|
198
|
+
resetNoCredit: "没有可用的额度重置。",
|
|
199
|
+
resetAlready: "这次重置请求已处理。",
|
|
200
|
+
resetFailed: "无法使用额度重置。",
|
|
201
|
+
resetRenewLogin: "登录状态已失效,请重新登录。",
|
|
202
|
+
resetExpired: "本次确认已失效,请重新开始。",
|
|
203
|
+
resetInProgress: "额度重置正在处理中。",
|
|
204
|
+
resetTooEarly: "请等待冷静期结束后再确认。",
|
|
205
|
+
resetPhraseMismatch: "确认短语不一致。",
|
|
206
|
+
resetNotExhausted: "当前 Codex 模型额度尚未用尽。",
|
|
207
|
+
resetAccountChanged: "登录账号已变更,请重新开始。",
|
|
179
208
|
creditsNote: "仅显示 Codex 为此账户或工作区实际返回的额外 Credits、消费上限或额度重置次数;三者不是同一项。",
|
|
180
209
|
creditsUsed: "已用 {used} / {limit} credits",
|
|
181
210
|
spendReached: "Credits 月度消费上限已用尽。",
|
|
182
211
|
unavailable: "暂无数据",
|
|
183
212
|
quickQuotaSetting: "输入框额度",
|
|
184
|
-
|
|
213
|
+
quickQuotaOff: "关闭",
|
|
214
|
+
quickQuotaPercent: "百分比",
|
|
215
|
+
quickQuotaBar: "进度条",
|
|
185
216
|
quickQuotaStatus: "Codex 剩余额度 {value}%",
|
|
186
217
|
speedTitle: "速度",
|
|
187
218
|
speedStandard: "标准",
|
|
@@ -265,12 +296,36 @@ window.__ModuleLoader__.load({
|
|
|
265
296
|
monthlyCreditLimit: "Monthly Credits spending cap",
|
|
266
297
|
resetCredits: "Available quota resets",
|
|
267
298
|
resetCreditsValue: "{count} available",
|
|
299
|
+
resetUse: "Use one reset",
|
|
300
|
+
resetUnavailable: "Available only when at least one Codex model quota is exhausted.",
|
|
301
|
+
resetPreparing: "Reading reset details…",
|
|
302
|
+
resetConfirmTitle: "Confirm quota reset",
|
|
303
|
+
resetWarning: "This immediately consumes one quota reset and cannot be undone. Continue only if you intend to restore an exhausted model quota.",
|
|
304
|
+
resetAcknowledge: "I understand this consumes one quota reset",
|
|
305
|
+
resetTypeHint: "Type {phrase} to continue",
|
|
306
|
+
resetWait: "Wait {count} more seconds",
|
|
307
|
+
resetFinal: "Consume one reset",
|
|
308
|
+
resetUsing: "Resetting…",
|
|
309
|
+
resetSuccess: "Quota reset completed.",
|
|
310
|
+
resetNothing: "There is currently nothing to reset; no new reset was consumed.",
|
|
311
|
+
resetNoCredit: "No quota reset is available.",
|
|
312
|
+
resetAlready: "This reset request was already processed.",
|
|
313
|
+
resetFailed: "Could not use the quota reset.",
|
|
314
|
+
resetRenewLogin: "Your sign-in expired. Sign in again.",
|
|
315
|
+
resetExpired: "This confirmation expired. Start again.",
|
|
316
|
+
resetInProgress: "A quota reset is already in progress.",
|
|
317
|
+
resetTooEarly: "Wait for the cooldown before confirming.",
|
|
318
|
+
resetPhraseMismatch: "The confirmation phrase does not match.",
|
|
319
|
+
resetNotExhausted: "The current Codex model quota is not exhausted.",
|
|
320
|
+
resetAccountChanged: "The signed-in account changed. Start again.",
|
|
268
321
|
creditsNote: "Shows only extra Credits, spending caps, or quota resets returned for this account or workspace; these are separate items.",
|
|
269
322
|
creditsUsed: "{used} / {limit} credits used",
|
|
270
323
|
spendReached: "The monthly Credits spending cap has been reached.",
|
|
271
324
|
unavailable: "No data yet",
|
|
272
325
|
quickQuotaSetting: "Composer quota",
|
|
273
|
-
|
|
326
|
+
quickQuotaOff: "Off",
|
|
327
|
+
quickQuotaPercent: "Percent",
|
|
328
|
+
quickQuotaBar: "Progress bar",
|
|
274
329
|
quickQuotaStatus: "Codex quota: {value}% remaining",
|
|
275
330
|
speedTitle: "Speed",
|
|
276
331
|
speedStandard: "Standard",
|
|
@@ -308,6 +363,7 @@ window.__ModuleLoader__.load({
|
|
|
308
363
|
.codexSubscriptionNote{font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary)}
|
|
309
364
|
.codexSubscriptionCard{border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-1);padding:14px 16px;display:flex;flex-direction:column;gap:12px}
|
|
310
365
|
.codexSubscriptionUsageCard{padding:12px 14px;gap:9px}.codexSubscriptionPreferencesCard{padding:12px 14px;gap:10px}.codexSubscriptionPreference{min-height:32px;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:12px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px}.codexSubscriptionPreferenceCopy{display:flex;min-width:0;flex-direction:column;gap:2px}.codexSubscriptionPreferenceLabel{display:flex;align-items:center;gap:6px}
|
|
366
|
+
.codexSubscriptionQuotaModes{display:flex;align-items:center;gap:3px;padding:2px;border-radius:9px;background:var(--dsw-alias-bg-module-platform)}.codexSubscriptionQuotaMode{position:relative;display:flex;align-items:center;justify-content:center;min-height:26px;padding:0 9px;border-radius:7px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;cursor:pointer}.codexSubscriptionQuotaMode:has(input:checked){background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);box-shadow:0 0 0 1px var(--dsw-alias-border-l3)}.codexSubscriptionQuotaMode:has(input:focus-visible){outline:2px solid var(--dsw-alias-border-l3);outline-offset:1px}.codexSubscriptionQuotaMode:has(input:disabled){cursor:not-allowed;opacity:.5}.codexSubscriptionQuotaMode input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
|
|
311
367
|
.codexSubscriptionSwitch{position:relative;flex:0 0 auto;width:32px;height:18px;padding:0;border:1px solid var(--dsw-alias-border-l3);border-radius:999px;background:var(--dsw-alias-bg-module-platform);cursor:pointer}.codexSubscriptionSwitch:disabled{cursor:not-allowed;opacity:.5}.codexSubscriptionSwitch[aria-checked=true]{background:var(--dsw-alias-label-secondary);border-color:var(--dsw-alias-label-secondary)}.codexSubscriptionSwitchKnob{position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:var(--dsw-alias-bg-layer-1);transition:transform 120ms var(--ds-ease-in-out)}.codexSubscriptionSwitch[aria-checked=true] .codexSubscriptionSwitchKnob{transform:translateX(14px)}
|
|
312
368
|
.codexSubscriptionSearch{display:flex;flex-direction:column;gap:7px}.codexSubscriptionSearchChoices{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}.codexSubscriptionSearchChoice{display:grid;grid-template-columns:14px minmax(0,1fr);align-items:center;column-gap:8px;min-width:0;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);padding:9px 10px;text-align:left;cursor:pointer}.codexSubscriptionSearchChoice:has(input:disabled){cursor:not-allowed;opacity:.5}.codexSubscriptionSearchChoice:has(input:checked){border-color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}.codexSubscriptionSearchChoice:has(input:focus-visible){outline:2px solid var(--dsw-alias-border-l3);outline-offset:2px}.codexSubscriptionSearchInput{width:14px;height:14px;margin:0;accent-color:var(--dsw-alias-label-primary);cursor:inherit}.codexSubscriptionSearchCopy{display:block;min-width:0;pointer-events:none}.codexSubscriptionSearchCopy strong,.codexSubscriptionSearchCopy span{display:block}.codexSubscriptionSearchCopy strong{font-size:12px;line-height:18px;font-weight:500;color:var(--dsw-alias-label-secondary)}.codexSubscriptionSearchChoice:has(input:checked) strong{color:var(--dsw-alias-label-primary)}.codexSubscriptionSearchCopy span{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary)}.codexSubscriptionDivider{height:1px;background:var(--dsw-alias-border-l2)}
|
|
313
369
|
.codexSubscriptionAccountRow,.codexSubscriptionSectionHead{display:flex;align-items:center;justify-content:space-between;gap:12px}.codexSubscriptionStatus{display:flex;align-items:center;gap:8px;font-size:14px;line-height:22px;font-weight:500}
|
|
@@ -326,8 +382,9 @@ window.__ModuleLoader__.load({
|
|
|
326
382
|
.codexSubscriptionLimit progress::-webkit-progress-bar{background:var(--dsw-alias-border-l3);border-radius:999px}.codexSubscriptionLimit progress::-webkit-progress-value{background:var(--dsw-alias-brand-primary,#3964fe);border-radius:999px}.codexSubscriptionLimit progress::-moz-progress-bar{background:var(--dsw-alias-brand-primary,#3964fe);border-radius:999px}.codexSubscriptionLimitMeta{display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}
|
|
327
383
|
.codexSubscriptionCreditSection{display:flex;flex-direction:column;gap:7px}.codexSubscriptionCreditNote{font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}.codexSubscriptionCreditRows{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px}.codexSubscriptionCreditBalance,.codexSubscriptionSpendLimit{min-width:0;border-radius:10px;padding:12px 14px;background:var(--dsw-alias-bg-module-platform)}
|
|
328
384
|
.codexSubscriptionCreditBalance{display:flex;flex-direction:column;gap:6px}.codexSubscriptionCreditBalance span,.codexSubscriptionCreditLabel{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}.codexSubscriptionCreditBalance strong{font:600 18px/24px ui-monospace,SFMono-Regular,Consolas,monospace;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
|
|
385
|
+
.codexSubscriptionResetSummary{display:flex;align-items:center;justify-content:space-between;gap:10px}.codexSubscriptionResetBalance{display:flex;flex-direction:column;gap:8px}.codexSubscriptionResetBalance .codexSubscriptionActions{justify-content:flex-start}.codexSubscriptionResetFlow{display:flex;flex-direction:column;gap:9px;border:1px solid var(--dsw-alias-state-warning-border,var(--dsw-alias-border-l2));border-radius:10px;padding:11px 12px;background:var(--dsw-alias-bg-module-platform)}.codexSubscriptionResetFlow h4{margin:0;font-size:13px;line-height:20px;font-weight:600}.codexSubscriptionResetWarning{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}.codexSubscriptionResetCheck{display:flex;align-items:flex-start;gap:8px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary);cursor:pointer}.codexSubscriptionResetCheck input{margin:3px 0 0;accent-color:var(--dsw-alias-label-primary)}.codexSubscriptionResetPhrase{font:600 12px/18px ui-monospace,SFMono-Regular,Consolas,monospace}.codexSubscriptionResetFinal{border-color:var(--dsw-alias-state-error-primary)!important;color:var(--dsw-alias-state-error-primary)!important}.codexSubscriptionResetResult{font-size:12px;line-height:18px;color:var(--dsw-alias-state-success-primary)}
|
|
329
386
|
.codexSubscriptionSpendLimit{display:flex;flex-direction:column;gap:8px}.codexSubscriptionSpendTop{display:flex;align-items:baseline;justify-content:space-between;gap:12px}.codexSubscriptionSpendTop strong{font:600 16px/22px ui-monospace,SFMono-Regular,Consolas,monospace;font-variant-numeric:tabular-nums}.codexSubscriptionSpendLimit progress{width:100%;height:6px;border:0;border-radius:999px;overflow:hidden;background:var(--dsw-alias-border-l3);accent-color:var(--dsw-alias-brand-primary,#3964fe);-webkit-appearance:none;appearance:none}.codexSubscriptionSpendLimit progress::-webkit-progress-bar{background:var(--dsw-alias-border-l3);border-radius:999px}.codexSubscriptionSpendLimit progress::-webkit-progress-value{background:var(--dsw-alias-brand-primary,#3964fe);border-radius:999px}.codexSubscriptionSpendLimit progress::-moz-progress-bar{background:var(--dsw-alias-brand-primary,#3964fe);border-radius:999px}
|
|
330
|
-
.codexComposerQuota{display:inline-flex;align-items:center;flex:0 0 auto;height:28px;box-sizing:border-box;padding:0;color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;line-height:20px;font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap;user-select:none}
|
|
387
|
+
.codexComposerQuota{display:inline-flex;align-items:center;flex:0 0 auto;height:28px;box-sizing:border-box;padding:0;color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;line-height:20px;font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap;user-select:none}.codexComposerQuotaBar{display:block;width:40px;height:4px;border:0;border-radius:999px;overflow:hidden;background:var(--dsw-alias-border-l3);accent-color:var(--dsw-alias-label-secondary);-webkit-appearance:none;appearance:none}.codexComposerQuotaBar::-webkit-progress-bar{background:var(--dsw-alias-border-l3);border-radius:999px}.codexComposerQuotaBar::-webkit-progress-value{background:var(--dsw-alias-label-secondary);border-radius:999px}.codexComposerQuotaBar::-moz-progress-bar{background:var(--dsw-alias-label-secondary);border-radius:999px}
|
|
331
388
|
.codexModelSelect{position:relative;min-width:0}.codexModelSelectTrigger{display:flex;align-items:center;gap:4px;min-width:0;max-width:min(360px,45cqw);height:28px;padding:0 4px 0 8px;border:0;border-radius:24px;outline:0;background:transparent;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:500;line-height:20px;cursor:pointer}.codexModelSelectTrigger:hover:not(:disabled),.codexModelSelectTrigger[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover)}.codexModelSelectTrigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}.codexModelSelectTrigger:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.codexModelSelectBolt{display:block;flex:none;width:14px;height:14px;color:var(--dsw-alias-label-primary)}.codexModelSelectLabel{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectEffort{flex:none;color:var(--dsw-alias-label-caption)}.codexModelSelectChevron{flex:none;color:var(--dsw-alias-label-caption);transition:transform 120ms}.codexModelSelectTrigger[aria-expanded=true] .codexModelSelectChevron{transform:rotate(180deg)}
|
|
332
389
|
.codexModelSelectMenu,.codexModelSelectSubmenu{position:absolute;z-index:30;box-sizing:border-box;width:max-content;min-width:min(240px,calc(100vw - 32px));max-width:min(420px,calc(100vw - 32px));max-height:min(360px,calc(100vh - 96px));padding:4px;border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary);overflow:hidden}.codexModelSelectMenu{right:0;bottom:calc(100% + 8px)}.codexModelSelectSubmenu{right:calc(100% + 8px);bottom:0;min-width:min(230px,calc(100vw - 32px))}.codexModelSelectCell{display:flex;align-items:center;gap:8px;width:100%;min-width:100%;height:40px;box-sizing:border-box;padding:0 10px;border:0;border-radius:10px;background:transparent;color:inherit;font-size:14px;line-height:22px;text-align:left;cursor:pointer}.codexModelSelectCell:hover,.codexModelSelectCell:focus-visible,.codexModelSelectCell[data-open=true]{background:var(--dsw-alias-interactive-bg-hover);outline:0}.codexModelSelectCell:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.codexModelSelectCellLabel{flex:none;white-space:nowrap}.codexModelSelectCellValue{flex:auto;min-width:0;overflow:hidden;color:var(--dsw-alias-label-tertiary);text-align:right;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectCellChevron{flex:none;color:var(--dsw-alias-label-tertiary)}.codexModelSelectGroups{min-height:0;max-height:352px;overflow-y:auto}.codexModelSelectGroup+.codexModelSelectGroup{margin-top:4px}.codexModelSelectGroupTitle{position:sticky;top:0;z-index:1;padding:5px 8px 3px;background:var(--dsw-specific-menu);color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:500;line-height:18px}.codexModelSelectOption{display:flex;align-items:center;gap:8px;width:100%;min-width:100%;min-height:38px;box-sizing:border-box;padding:6px 8px;border:0;border-radius:10px;outline:0;background:transparent;color:inherit;text-align:left;cursor:pointer}.codexModelSelectOption:hover:not(:disabled),.codexModelSelectOption:focus-visible{background:var(--dsw-alias-interactive-bg-hover)}.codexModelSelectOption:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.codexModelSelectOptionCopy{display:flex;flex:1;min-width:0;flex-direction:column}.codexModelSelectOptionName{overflow:hidden;color:inherit;font-size:14px;font-weight:500;line-height:20px;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectOptionDescription{overflow:hidden;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectCheck{display:grid;place-items:center;flex:0 0 18px;color:var(--dsw-alias-label-primary)}.codexModelSelectStatus,.codexModelSelectEmpty{padding:10px;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.codexModelSelectError,.codexModelSelectWarning{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:4px;padding:7px 8px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}.codexModelSelectWarning{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-state-warn-label)}.codexModelSelectRetry{flex:none;padding:0;border:0;background:transparent;color:inherit;font:inherit;font-weight:600;cursor:pointer}
|
|
333
390
|
.codexModelSelectMenu{overflow:visible}
|
|
@@ -494,7 +551,7 @@ window.__ModuleLoader__.load({
|
|
|
494
551
|
const current = native.status === "ready" ? native : fallbackStatus === "ready" ? fallback : native;
|
|
495
552
|
return Object.freeze({
|
|
496
553
|
status: updating ? "updating" : current.status,
|
|
497
|
-
|
|
554
|
+
quickQuotaMode: normalizeQuickQuotaMode(current.value?.[QUICK_QUOTA_MODE_FIELD], current.value?.[LEGACY_QUICK_QUOTA_FIELD]),
|
|
498
555
|
searchProvider: normalizeSearchProvider(current.value?.[SEARCH_PROVIDER_FIELD]),
|
|
499
556
|
speedMode: normalizeSpeedMode(current.value?.[SPEED_MODE_FIELD]),
|
|
500
557
|
writable: !updating && current.status === "ready" && current.writable === true,
|
|
@@ -517,7 +574,7 @@ window.__ModuleLoader__.load({
|
|
|
517
574
|
fallback = {
|
|
518
575
|
status: "ready",
|
|
519
576
|
value: {
|
|
520
|
-
[
|
|
577
|
+
[QUICK_QUOTA_MODE_FIELD]: normalizeQuickQuotaMode(value?.[QUICK_QUOTA_MODE_FIELD], value?.[LEGACY_QUICK_QUOTA_FIELD]),
|
|
521
578
|
[SEARCH_PROVIDER_FIELD]: normalizeSearchProvider(value?.[SEARCH_PROVIDER_FIELD]),
|
|
522
579
|
[SPEED_MODE_FIELD]: normalizeSpeedMode(value?.[SPEED_MODE_FIELD])
|
|
523
580
|
},
|
|
@@ -638,33 +695,36 @@ window.__ModuleLoader__.load({
|
|
|
638
695
|
}
|
|
639
696
|
function QuickQuotaPreference({ preference, t }) {
|
|
640
697
|
const snapshot = usePreferenceSnapshot(preference);
|
|
641
|
-
const visible = snapshot.visible;
|
|
642
698
|
const writable = snapshot.status === "ready" && snapshot.writable === true;
|
|
699
|
+
const choice = (value, label) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
700
|
+
className: "codexSubscriptionQuotaMode",
|
|
701
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
702
|
+
type: "radio",
|
|
703
|
+
name: "codex-subscription-quota-mode",
|
|
704
|
+
checked: snapshot.quickQuotaMode === value,
|
|
705
|
+
disabled: !writable,
|
|
706
|
+
onChange: () => {
|
|
707
|
+
preference.set({ [QUICK_QUOTA_MODE_FIELD]: value });
|
|
708
|
+
}
|
|
709
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })]
|
|
710
|
+
});
|
|
643
711
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
644
712
|
className: "codexSubscriptionPreference",
|
|
645
713
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
646
714
|
className: "codexSubscriptionPreferenceCopy",
|
|
647
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
715
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
648
716
|
className: "codexSubscriptionPreferenceLabel",
|
|
649
|
-
children:
|
|
650
|
-
className: "codexSubscriptionTag",
|
|
651
|
-
children: t("quickQuotaBeta")
|
|
652
|
-
})]
|
|
717
|
+
children: t("quickQuotaSetting")
|
|
653
718
|
})
|
|
654
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
655
|
-
className: "
|
|
656
|
-
|
|
657
|
-
role: "switch",
|
|
658
|
-
"aria-checked": visible,
|
|
719
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
720
|
+
className: "codexSubscriptionQuotaModes",
|
|
721
|
+
role: "radiogroup",
|
|
659
722
|
"aria-label": t("quickQuotaSetting"),
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
className: "codexSubscriptionSwitchKnob",
|
|
666
|
-
"aria-hidden": "true"
|
|
667
|
-
})
|
|
723
|
+
children: [
|
|
724
|
+
choice("off", t("quickQuotaOff")),
|
|
725
|
+
choice(QUICK_QUOTA_MODE_PERCENT, t("quickQuotaPercent")),
|
|
726
|
+
choice("bar", t("quickQuotaBar"))
|
|
727
|
+
]
|
|
668
728
|
})]
|
|
669
729
|
});
|
|
670
730
|
}
|
|
@@ -733,17 +793,23 @@ window.__ModuleLoader__.load({
|
|
|
733
793
|
const preferenceSnapshot = usePreferenceSnapshot(preference);
|
|
734
794
|
const current = (0, react.useSyncExternalStore)((listener) => directory.subscribe(listener), () => directory.getSnapshot()).current;
|
|
735
795
|
const codex = current?.provider === "openai-codex";
|
|
736
|
-
const quotaEnabled = preferenceSnapshot.status === "ready" && preferenceSnapshot.
|
|
796
|
+
const quotaEnabled = preferenceSnapshot.status === "ready" && preferenceSnapshot.quickQuotaMode !== "off" && codex;
|
|
737
797
|
const quota = useQuickQuota(rpc, quotaEnabled, current?.model);
|
|
738
798
|
if (!quotaEnabled || quota === void 0) return null;
|
|
739
|
-
const value =
|
|
740
|
-
const
|
|
741
|
-
|
|
799
|
+
const value = Math.round(Number(quota.remainingPercent) * 10) / 10;
|
|
800
|
+
const display = percent(value);
|
|
801
|
+
const label = fill(t("quickQuotaStatus"), { value: display });
|
|
802
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
742
803
|
className: "codexComposerQuota",
|
|
743
804
|
role: "status",
|
|
744
805
|
"aria-label": label,
|
|
745
806
|
title: label,
|
|
746
|
-
children:
|
|
807
|
+
children: preferenceSnapshot.quickQuotaMode === "bar" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("progress", {
|
|
808
|
+
className: "codexComposerQuotaBar",
|
|
809
|
+
max: 100,
|
|
810
|
+
value,
|
|
811
|
+
"aria-hidden": "true"
|
|
812
|
+
}) : `${display}%`
|
|
747
813
|
});
|
|
748
814
|
}
|
|
749
815
|
function CodexModelSelect({ locked, available, directory, load, select, preference, t }) {
|
|
@@ -1283,6 +1349,171 @@ window.__ModuleLoader__.load({
|
|
|
1283
1349
|
children: fill(t("resets"), { value })
|
|
1284
1350
|
});
|
|
1285
1351
|
}
|
|
1352
|
+
function ResetCreditControl({ rpc, t, count, exhausted, onConsumed }) {
|
|
1353
|
+
const [challenge, setChallenge] = (0, react.useState)();
|
|
1354
|
+
const [resetBusy, setResetBusy] = (0, react.useState)(false);
|
|
1355
|
+
const [resetAcknowledged, setResetAcknowledged] = (0, react.useState)(false);
|
|
1356
|
+
const [resetPhrase, setResetPhrase] = (0, react.useState)("");
|
|
1357
|
+
const [resetCountdown, setResetCountdown] = (0, react.useState)(0);
|
|
1358
|
+
const [resetError, setResetError] = (0, react.useState)();
|
|
1359
|
+
const [resetResult, setResetResult] = (0, react.useState)();
|
|
1360
|
+
(0, react.useEffect)(() => {
|
|
1361
|
+
if (challenge === void 0) {
|
|
1362
|
+
setResetCountdown(0);
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
const update = () => setResetCountdown(Math.max(0, Math.ceil((challenge.readyAt - Date.now()) / 1e3)));
|
|
1366
|
+
update();
|
|
1367
|
+
const timer = window.setInterval(update, 250);
|
|
1368
|
+
return () => window.clearInterval(timer);
|
|
1369
|
+
}, [challenge]);
|
|
1370
|
+
const prepareReset = () => {
|
|
1371
|
+
if (resetBusy || !exhausted) return;
|
|
1372
|
+
setResetBusy(true);
|
|
1373
|
+
setResetError(void 0);
|
|
1374
|
+
setResetResult(void 0);
|
|
1375
|
+
rpc.call(CHANNEL, "reset-credit/prepare", {}).then(unwrap).then((next) => {
|
|
1376
|
+
setChallenge(next);
|
|
1377
|
+
setResetAcknowledged(false);
|
|
1378
|
+
setResetPhrase("");
|
|
1379
|
+
}).catch((error) => setResetError(resetCreditErrorText(error, t))).finally(() => setResetBusy(false));
|
|
1380
|
+
};
|
|
1381
|
+
const cancelReset = () => {
|
|
1382
|
+
if (resetBusy) return;
|
|
1383
|
+
setChallenge(void 0);
|
|
1384
|
+
setResetAcknowledged(false);
|
|
1385
|
+
setResetPhrase("");
|
|
1386
|
+
setResetError(void 0);
|
|
1387
|
+
};
|
|
1388
|
+
const resetReady = challenge !== void 0 && resetAcknowledged && resetPhrase === challenge.confirmPhrase && resetCountdown === 0;
|
|
1389
|
+
const consumeReset = () => {
|
|
1390
|
+
if (resetBusy) return;
|
|
1391
|
+
if (!resetReady) return;
|
|
1392
|
+
setResetBusy(true);
|
|
1393
|
+
setResetError(void 0);
|
|
1394
|
+
setResetResult(void 0);
|
|
1395
|
+
rpc.call(CHANNEL, "reset-credit/consume", {
|
|
1396
|
+
challengeId: challenge.challengeId,
|
|
1397
|
+
phrase: resetPhrase
|
|
1398
|
+
}).then(unwrap).then((result) => {
|
|
1399
|
+
setChallenge(void 0);
|
|
1400
|
+
setResetAcknowledged(false);
|
|
1401
|
+
setResetPhrase("");
|
|
1402
|
+
const message = result.code === "reset" ? t("resetSuccess") : result.code === "nothing_to_reset" ? t("resetNothing") : result.code === "no_credit" ? t("resetNoCredit") : t("resetAlready");
|
|
1403
|
+
setResetResult(message);
|
|
1404
|
+
onConsumed();
|
|
1405
|
+
}).catch((error) => setResetError(resetCreditErrorText(error, t))).finally(() => setResetBusy(false));
|
|
1406
|
+
};
|
|
1407
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1408
|
+
className: "codexSubscriptionResetBalance",
|
|
1409
|
+
children: [
|
|
1410
|
+
challenge === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1411
|
+
className: "codexSubscriptionResetSummary",
|
|
1412
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: fill(t("resetCreditsValue"), { count }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1413
|
+
className: "codexSubscriptionActions",
|
|
1414
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1415
|
+
type: "button",
|
|
1416
|
+
variant: "outline",
|
|
1417
|
+
disabled: !exhausted || resetBusy,
|
|
1418
|
+
"aria-busy": resetBusy,
|
|
1419
|
+
title: !exhausted ? t("resetUnavailable") : void 0,
|
|
1420
|
+
onClick: prepareReset,
|
|
1421
|
+
children: resetBusy ? t("resetPreparing") : t("resetUse")
|
|
1422
|
+
})
|
|
1423
|
+
})]
|
|
1424
|
+
}) }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1425
|
+
className: "codexSubscriptionResetFlow",
|
|
1426
|
+
role: "group",
|
|
1427
|
+
"aria-labelledby": "codex-reset-confirm-title",
|
|
1428
|
+
children: [
|
|
1429
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
1430
|
+
id: "codex-reset-confirm-title",
|
|
1431
|
+
children: challenge.title ?? t("resetConfirmTitle")
|
|
1432
|
+
}),
|
|
1433
|
+
challenge.description ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1434
|
+
className: "codexSubscriptionResetWarning",
|
|
1435
|
+
children: challenge.description
|
|
1436
|
+
}) : null,
|
|
1437
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1438
|
+
className: "codexSubscriptionResetWarning",
|
|
1439
|
+
children: t("resetWarning")
|
|
1440
|
+
}),
|
|
1441
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1442
|
+
className: "codexSubscriptionResetCheck",
|
|
1443
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1444
|
+
type: "checkbox",
|
|
1445
|
+
checked: resetAcknowledged,
|
|
1446
|
+
disabled: resetBusy,
|
|
1447
|
+
onChange: (event) => setResetAcknowledged(event.target.checked)
|
|
1448
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("resetAcknowledge") })]
|
|
1449
|
+
}),
|
|
1450
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1451
|
+
className: "codexSubscriptionPreferenceCopy",
|
|
1452
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1453
|
+
className: "codexSubscriptionCreditLabel",
|
|
1454
|
+
children: fill(t("resetTypeHint"), { phrase: challenge.confirmPhrase })
|
|
1455
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
1456
|
+
className: "codexSubscriptionInput codexSubscriptionResetPhrase",
|
|
1457
|
+
value: resetPhrase,
|
|
1458
|
+
disabled: resetBusy,
|
|
1459
|
+
autoComplete: "off",
|
|
1460
|
+
spellCheck: false,
|
|
1461
|
+
onChange: (event) => setResetPhrase(event.target.value)
|
|
1462
|
+
})]
|
|
1463
|
+
}),
|
|
1464
|
+
resetCountdown > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1465
|
+
className: "codexSubscriptionCreditNote",
|
|
1466
|
+
role: "status",
|
|
1467
|
+
children: fill(t("resetWait"), { count: resetCountdown })
|
|
1468
|
+
}) : null,
|
|
1469
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1470
|
+
className: "codexSubscriptionActions",
|
|
1471
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1472
|
+
type: "button",
|
|
1473
|
+
variant: "outline",
|
|
1474
|
+
disabled: resetBusy,
|
|
1475
|
+
onClick: cancelReset,
|
|
1476
|
+
children: t("cancel")
|
|
1477
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1478
|
+
className: "codexSubscriptionResetFinal",
|
|
1479
|
+
type: "button",
|
|
1480
|
+
variant: "outline",
|
|
1481
|
+
disabled: !resetReady || resetBusy,
|
|
1482
|
+
"aria-busy": resetBusy,
|
|
1483
|
+
onClick: consumeReset,
|
|
1484
|
+
children: resetBusy ? t("resetUsing") : t("resetFinal")
|
|
1485
|
+
})]
|
|
1486
|
+
})
|
|
1487
|
+
]
|
|
1488
|
+
}),
|
|
1489
|
+
resetResult ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1490
|
+
className: "codexSubscriptionResetResult",
|
|
1491
|
+
role: "status",
|
|
1492
|
+
children: resetResult
|
|
1493
|
+
}) : null,
|
|
1494
|
+
resetError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1495
|
+
className: "codexSubscriptionError",
|
|
1496
|
+
role: "alert",
|
|
1497
|
+
children: resetError || t("resetFailed")
|
|
1498
|
+
}) : null
|
|
1499
|
+
]
|
|
1500
|
+
});
|
|
1501
|
+
}
|
|
1502
|
+
function resetCreditErrorText(error, t) {
|
|
1503
|
+
return t((/* @__PURE__ */ new Map([
|
|
1504
|
+
["ChatGPT subscription is not signed in", "resetRenewLogin"],
|
|
1505
|
+
["ChatGPT sign-in needs to be renewed", "resetRenewLogin"],
|
|
1506
|
+
["No quota reset is available", "resetNoCredit"],
|
|
1507
|
+
["No usable quota reset is available", "resetNoCredit"],
|
|
1508
|
+
["The available quota reset expires too soon", "resetExpired"],
|
|
1509
|
+
["This quota reset confirmation is no longer valid", "resetExpired"],
|
|
1510
|
+
["This quota reset is already in progress", "resetInProgress"],
|
|
1511
|
+
["Wait before confirming this quota reset", "resetTooEarly"],
|
|
1512
|
+
["The quota reset confirmation phrase does not match", "resetPhraseMismatch"],
|
|
1513
|
+
["The current Codex quota is not exhausted", "resetNotExhausted"],
|
|
1514
|
+
["The signed-in ChatGPT account changed", "resetAccountChanged"]
|
|
1515
|
+
])).get(error instanceof Error ? error.message : "") ?? "resetFailed");
|
|
1516
|
+
}
|
|
1286
1517
|
function UsageCard({ rpc, t, signedIn, resetKey }) {
|
|
1287
1518
|
const [usage, setUsage] = (0, react.useState)();
|
|
1288
1519
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
@@ -1318,6 +1549,7 @@ window.__ModuleLoader__.load({
|
|
|
1318
1549
|
}, [signedIn, resetKey]);
|
|
1319
1550
|
const visibleUsage = signedIn ? usage : void 0;
|
|
1320
1551
|
const limits = visibleUsage?.rateLimits ?? [];
|
|
1552
|
+
const exhausted = limits.some((limit) => limit.id !== "code_review" && limit.windows.some((window) => window.usedPercent >= 100));
|
|
1321
1553
|
const hasUsageDetails = limits.length > 0 || visibleUsage?.credits !== void 0 || visibleUsage?.individualLimit !== void 0 || visibleUsage?.resetCredits?.availableCount > 0;
|
|
1322
1554
|
const fetchedAt = typeof visibleUsage?.fetchedAt === "number" ? validDate(visibleUsage.fetchedAt) : void 0;
|
|
1323
1555
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -1412,7 +1644,13 @@ window.__ModuleLoader__.load({
|
|
|
1412
1644
|
}) : null,
|
|
1413
1645
|
visibleUsage?.resetCredits?.availableCount > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1414
1646
|
className: "codexSubscriptionCreditBalance",
|
|
1415
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("resetCredits") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
1647
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("resetCredits") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResetCreditControl, {
|
|
1648
|
+
rpc,
|
|
1649
|
+
t,
|
|
1650
|
+
count: visibleUsage.resetCredits.availableCount,
|
|
1651
|
+
exhausted,
|
|
1652
|
+
onConsumed: () => load(true)
|
|
1653
|
+
})]
|
|
1416
1654
|
}) : null,
|
|
1417
1655
|
visibleUsage?.individualLimit ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1418
1656
|
className: "codexSubscriptionSpendLimit",
|